imap-fetch.c revision 79fcd3f95a6266cc62ceaa753e56dd4456ab7c4b
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (C) 2002-2004 Timo Sirainen */
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include "array.h"
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen#include "buffer.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream.h"
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen#include "ostream.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "str.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include "message-send.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "message-size.h"
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen#include "imap-date.h"
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen#include "commands.h"
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen#include "imap-fetch.h"
3ed2d0f6b5e67e2663d44489d9da3176823789a8Timo Sirainen#include "imap-util.h"
65f8fb656051f1059f7b5a2da9c5555adcc30439Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include <stdlib.h>
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenconst struct imap_fetch_handler default_handlers[7];
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic buffer_t *fetch_handlers = NULL;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic int imap_fetch_handler_cmp(const void *p1, const void *p2)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen const struct imap_fetch_handler *h1 = p1, *h2 = p2;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return strcmp(h1->name, h2->name);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenvoid imap_fetch_handlers_register(const struct imap_fetch_handler *handlers,
2dd39e478269d6fb0bb26d12b394aa30ee965e38Timo Sirainen size_t count)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen void *data;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen size_t size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (fetch_handlers == NULL)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen fetch_handlers = buffer_create_dynamic(default_pool, 128);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen buffer_append(fetch_handlers, handlers, sizeof(*handlers) * count);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen data = buffer_get_modifyable_data(fetch_handlers, &size);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen qsort(data, size / sizeof(*handlers), sizeof(*handlers),
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen imap_fetch_handler_cmp);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainenstatic int imap_fetch_handler_bsearch(const void *name_p, const void *handler_p)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen{
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen const char *name = name_p;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen const struct imap_fetch_handler *h = handler_p;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen int i;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen for (i = 0; h->name[i] != '\0'; i++) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (h->name[i] != name[i]) {
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen if (name[i] < 'A' || name[i] >= 'Z')
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen return -1;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen return name[i] - h->name[i];
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen }
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen }
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen
4ba9a1d3facc515b3feb5238a16bcf91f76fac61Timo Sirainen return name[i] < 'A' || name[i] >= 'Z' ? 0 : -1;
4ba9a1d3facc515b3feb5238a16bcf91f76fac61Timo Sirainen}
dfaefeabae939803ceb8c503101e86b5496541d1Timo Sirainen
dfaefeabae939803ceb8c503101e86b5496541d1Timo Sirainenbool imap_fetch_init_handler(struct imap_fetch_context *ctx, const char *name,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct imap_arg **args)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen{
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const struct imap_fetch_handler *handler;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen handler = bsearch(name, fetch_handlers->data,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen fetch_handlers->used /
57a8c6a95e4bce3eeaba36985adb81c07dd683ffTimo Sirainen sizeof(struct imap_fetch_handler),
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen sizeof(struct imap_fetch_handler),
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen imap_fetch_handler_bsearch);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen if (handler == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_send_command_error(ctx->cmd,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t_strconcat("Unknown command ", name, NULL));
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return FALSE;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen }
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen return handler->init(ctx, name, args);
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen}
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainenstruct imap_fetch_context *imap_fetch_init(struct client_command_context *cmd)
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen{
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen struct client *client = cmd->client;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen struct imap_fetch_context *ctx;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen if (fetch_handlers == NULL) {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen imap_fetch_handlers_register(default_handlers,
f1743785713e7632459d623d5df2108f4b93accbTimo Sirainen sizeof(default_handlers) /
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen sizeof(default_handlers[0]));
70ead6466f9baa8294e71fc2fba0a4f54f488b5eTimo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen ctx = p_new(cmd->pool, struct imap_fetch_context, 1);
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen ctx->client = client;
8d630c15a8ed6f85553467c3a231a273defca5f6Timo Sirainen ctx->cmd = cmd;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->box = client->mailbox;
ee116df08d0fdab703483e18fe8076b2ef9fd9d7Timo Sirainen
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen ctx->cur_str = str_new(default_pool, 8192);
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen ctx->all_headers_buf = buffer_create_dynamic(cmd->pool, 128);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen ARRAY_CREATE(&ctx->handlers, cmd->pool,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen struct imap_fetch_context_handler, 16);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->line_finished = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ctx;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenvoid imap_fetch_add_handler(struct imap_fetch_context *ctx,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen bool buffered, bool want_deinit,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen imap_fetch_handler_t *handler, void *context)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen{
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* partially because of broken clients, but also partially because
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen it potentially can make client implementations faster, we have a
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen buffered parameter which basically means that the handler promises
cff1f182205e674285cf3ff446a0dcf7afea277dTimo Sirainen to write the output in ctx->cur_str. The cur_str is then sent to
cff1f182205e674285cf3ff446a0dcf7afea277dTimo Sirainen client before calling any non-buffered handlers.
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen We try to keep the handler registration order the same as the
e03d986a74128f5ba30fcfda9f6e36578f5d8decTimo Sirainen client requested them. This is especially useful to get UID
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen returned first, which some clients rely on..
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen */
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen const struct imap_fetch_context_handler *handlers;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen struct imap_fetch_context_handler h;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen unsigned int i, size;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (context == NULL) {
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen /* don't allow duplicate handlers */
d3280fe317a4598c0868cc440e7a1191c06d0db3Timo Sirainen handlers = array_get(&ctx->handlers, &size);
d3280fe317a4598c0868cc440e7a1191c06d0db3Timo Sirainen
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen for (i = 0; i < size; i++) {
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen if (handlers[i].handler == handler &&
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen handlers[i].context == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen }
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen }
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen memset(&h, 0, sizeof(h));
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen h.handler = handler;
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen h.context = context;
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen h.buffered = buffered;
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen h.want_deinit = want_deinit;
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen if (!buffered)
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen array_append(&ctx->handlers, &h, 1);
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen else {
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen array_insert(&ctx->handlers, ctx->buffered_handlers_count,
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen &h, 1);
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen ctx->buffered_handlers_count++;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen }
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen}
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
4b41116563110d00330896a568eff1078c382827Timo Sirainenvoid imap_fetch_begin(struct imap_fetch_context *ctx,
4b41116563110d00330896a568eff1078c382827Timo Sirainen struct mail_search_arg *search_arg)
4b41116563110d00330896a568eff1078c382827Timo Sirainen{
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen const void *null = NULL;
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen const void *data;
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen if (ctx->flags_update_seen) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mailbox_is_readonly(ctx->box))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->flags_update_seen = FALSE;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen else if (!ctx->flags_have_handler) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen ctx->flags_show_only_seen_changes = TRUE;
b2c1349cf07410aefab0f5b17153af9e5cfcf48fTimo Sirainen (void)imap_fetch_init_handler(ctx, "FLAGS", NULL);
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
dbe64f3893616a4005c8946be75d2dc8f6823d72Timo Sirainen
8a13b020f90e080570658b18c042e7e352c8b14fTimo Sirainen if (buffer_get_used_size(ctx->all_headers_buf) != 0 &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ((ctx->fetch_data & (MAIL_FETCH_STREAM_HEADER |
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen MAIL_FETCH_STREAM_BODY)) == 0)) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen buffer_append(ctx->all_headers_buf, &null, sizeof(null));
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen data = buffer_get_data(ctx->all_headers_buf, NULL);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen ctx->all_headers_ctx =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mailbox_header_lookup_init(ctx->box, data);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen ctx->trans = mailbox_transaction_begin(ctx->box,
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen MAILBOX_TRANSACTION_FLAG_HIDE);
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen ctx->select_counter = ctx->client->select_counter;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->mail = mail_alloc(ctx->trans, ctx->fetch_data,
f3bb2fbe87425dc89a839908985af496f7f65702Timo Sirainen ctx->all_headers_ctx);
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen ctx->search_ctx =
a3ee5ce6ecc8e228ee69300fdd562d7ac8be89a7Timo Sirainen mailbox_search_init(ctx->trans, NULL, search_arg, NULL);
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainenstatic int imap_fetch_flush_buffer(struct imap_fetch_context *ctx)
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen{
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen const unsigned char *data;
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen size_t len;
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen i_assert(ctx->first);
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen data = str_data(ctx->cur_str);
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen len = str_len(ctx->cur_str);
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen /* there's an extra space at the end if we added any fetch items
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen to buffer */
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen if (data[len-1] == ' ') {
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen len--;
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen ctx->first = FALSE;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (o_stream_send(ctx->client->output, data, len) < 0)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return -1;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen str_truncate(ctx->cur_str, 0);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return 0;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen}
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainenint imap_fetch(struct imap_fetch_context *ctx)
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen{
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen const struct imap_fetch_context_handler *handlers;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen unsigned int size;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen int ret;
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen if (ctx->cont_handler != NULL) {
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen ret = ctx->cont_handler(ctx);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen if (ret == 0)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return 0;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen if (ret < 0) {
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen if (ctx->cur_mail->expunged) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* not an error, just lost it. */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ctx->partial_fetch = TRUE;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen ctx->partial_fetch = TRUE;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen } else {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return -1;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen ctx->cont_handler = NULL;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen ctx->cur_offset = 0;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen ctx->cur_handler++;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen }
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen handlers = array_get(&ctx->handlers, &size);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen for (;;) {
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if (o_stream_get_buffer_used_size(ctx->client->output) >=
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen CLIENT_OUTPUT_OPTIMAL_SIZE) {
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen ret = o_stream_flush(ctx->client->output);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if (ret <= 0)
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen return ret;
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen }
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen if (ctx->cur_mail == NULL) {
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen if (ctx->cur_input != NULL)
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen i_stream_unref(&ctx->cur_input);
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen if (mailbox_search_next(ctx->search_ctx,
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen ctx->mail) <= 0)
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen break;
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen ctx->cur_mail = ctx->mail;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen str_printfa(ctx->cur_str, "* %u FETCH (",
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen ctx->cur_mail->seq);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen ctx->first = TRUE;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen ctx->line_finished = FALSE;
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen }
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen for (; ctx->cur_handler < size; ctx->cur_handler++) {
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen if (str_len(ctx->cur_str) > 0 &&
4bbd396aa6198c84f3f7763b6e8a63a26e97e141Timo Sirainen !handlers[ctx->cur_handler].buffered) {
4bbd396aa6198c84f3f7763b6e8a63a26e97e141Timo Sirainen /* first non-buffered handler.
7baab0b0b60df7ce9093d0881cd322dff1e79491Timo Sirainen flush the buffer. */
7baab0b0b60df7ce9093d0881cd322dff1e79491Timo Sirainen if (imap_fetch_flush_buffer(ctx) < 0)
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen return -1;
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen }
6b0d8106ae51ffc6ce45636b34d2e21cbefca7fdTimo Sirainen
6b0d8106ae51ffc6ce45636b34d2e21cbefca7fdTimo Sirainen t_push();
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen ret = handlers[ctx->cur_handler].
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen handler(ctx, ctx->cur_mail,
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen handlers[ctx->cur_handler].context);
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen t_pop();
7f735cb86b2d8abd8f230089065eacfc24e9e5d6Timo Sirainen
7f735cb86b2d8abd8f230089065eacfc24e9e5d6Timo Sirainen if (ret == 0)
7f735cb86b2d8abd8f230089065eacfc24e9e5d6Timo Sirainen return 0;
7f735cb86b2d8abd8f230089065eacfc24e9e5d6Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (ret < 0) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (ctx->cur_mail->expunged) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* not an error, just lost it. */
0d86aa0d47f7393c669c084b34c0537b193688adTimo Sirainen ctx->partial_fetch = TRUE;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen } else {
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen i_assert(ret < 0 ||
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen ctx->cont_handler != NULL);
aa247243412a49f9bdebf7255e131dc6ece4ed46Timo Sirainen return -1;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen ctx->cont_handler = NULL;
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen ctx->cur_offset = 0;
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen }
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (str_len(ctx->cur_str) > 0) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen /* no non-buffered handlers */
c0225f7f6b43d34dc58c17d3304f0fd60ab89894Timo Sirainen if (imap_fetch_flush_buffer(ctx) < 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return -1;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen }
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen ctx->line_finished = TRUE;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (o_stream_send(ctx->client->output, ")\r\n", 3) < 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return -1;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen ctx->cur_mail = NULL;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen ctx->cur_handler = 0;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen }
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return 1;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen}
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenint imap_fetch_deinit(struct imap_fetch_context *ctx)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen{
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen const struct imap_fetch_context_handler *handlers;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen unsigned int i, count;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
9af6cc9ebc9986c1275ebdfa29c39e152af1557eTimo Sirainen handlers = array_get(&ctx->handlers, &count);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen for (i = 0; i < count; i++) {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (handlers[i].want_deinit)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen handlers[i].handler(ctx, NULL, handlers[i].context);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen }
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen str_free(&ctx->cur_str);
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (!ctx->line_finished) {
c7e14824e4e1ca9dc5d48d1eddc4a38d3041218fTimo Sirainen if (o_stream_send(ctx->client->output, ")\r\n", 3) < 0)
838e367716bbd5e44b4a1691db9cbf72af53e9f0Timo Sirainen ctx->failed = TRUE;
838e367716bbd5e44b4a1691db9cbf72af53e9f0Timo Sirainen }
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (ctx->cur_input != NULL)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen i_stream_unref(&ctx->cur_input);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (ctx->mail != NULL)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen mail_free(&ctx->mail);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (ctx->search_ctx != NULL) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (mailbox_search_deinit(&ctx->search_ctx) < 0)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen ctx->failed = TRUE;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (ctx->all_headers_ctx != NULL)
310767ca33e7636d40ec45dee68a2c319a5fa3c0Timo Sirainen mailbox_header_lookup_deinit(&ctx->all_headers_ctx);
310767ca33e7636d40ec45dee68a2c319a5fa3c0Timo Sirainen
310767ca33e7636d40ec45dee68a2c319a5fa3c0Timo Sirainen if (ctx->trans != NULL) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (ctx->failed)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen mailbox_transaction_rollback(&ctx->trans);
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen else {
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen if (mailbox_transaction_commit(&ctx->trans, 0) < 0)
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen ctx->failed = TRUE;
1eb17e61d3d38372674aa0c55caedb0185a985f5Timo Sirainen }
1eb17e61d3d38372674aa0c55caedb0185a985f5Timo Sirainen }
1eb17e61d3d38372674aa0c55caedb0185a985f5Timo Sirainen return ctx->failed ? -1 : 0;
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen}
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainenstatic int fetch_body(struct imap_fetch_context *ctx, struct mail *mail,
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen void *context __attr_unused__)
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen{
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen const char *body;
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen body = mail_get_special(mail, MAIL_FETCH_IMAP_BODY);
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen if (body == NULL)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return -1;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ctx->first)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->first = FALSE;
e4c90f0b88e40a8f92b8f5e1f1a3ea701e5c965cTimo Sirainen else {
defb12ecd360df672ffb2f4dbf4d1218a0a9549cTimo Sirainen if (o_stream_send(ctx->client->output, " ", 1) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (o_stream_send(ctx->client->output, "BODY (", 6) < 0 ||
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen o_stream_send_str(ctx->client->output, body) < 0 ||
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen o_stream_send(ctx->client->output, ")", 1) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
194603b35061fea1ee8d171a7104b6985c610966Timo Sirainen}
194603b35061fea1ee8d171a7104b6985c610966Timo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainenstatic bool fetch_body_init(struct imap_fetch_context *ctx, const char *name,
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen struct imap_arg **args)
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen{
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen if (name[4] == '\0') {
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen ctx->fetch_data |= MAIL_FETCH_IMAP_BODY;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen imap_fetch_add_handler(ctx, FALSE, FALSE, fetch_body, NULL);
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen return TRUE;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen }
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen return fetch_body_section_init(ctx, name, args);
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen}
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainenstatic int fetch_bodystructure(struct imap_fetch_context *ctx,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen struct mail *mail, void *context __attr_unused__)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen{
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen const char *bodystructure;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen bodystructure = mail_get_special(mail, MAIL_FETCH_IMAP_BODYSTRUCTURE);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (bodystructure == NULL)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return -1;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ctx->first)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->first = FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (o_stream_send(ctx->client->output, " ", 1) < 0)
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen return -1;
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen }
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (o_stream_send(ctx->client->output, "BODYSTRUCTURE (", 15) < 0 ||
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen o_stream_send_str(ctx->client->output, bodystructure) < 0 ||
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen o_stream_send(ctx->client->output, ")", 1) < 0)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return -1;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return 1;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen}
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenstatic bool fetch_bodystructure_init(struct imap_fetch_context *ctx,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen const char *name __attr_unused__,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen struct imap_arg **args __attr_unused__)
a3ee5ce6ecc8e228ee69300fdd562d7ac8be89a7Timo Sirainen{
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen ctx->fetch_data |= MAIL_FETCH_IMAP_BODYSTRUCTURE;
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen imap_fetch_add_handler(ctx, FALSE, FALSE, fetch_bodystructure, NULL);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return TRUE;
4321f6c969e7b8f6b243ff5bb6b8d297921676f6Timo Sirainen}
4321f6c969e7b8f6b243ff5bb6b8d297921676f6Timo Sirainen
d54ab8987e482a8df250615b44f41fa040c38741Timo Sirainenstatic int fetch_envelope(struct imap_fetch_context *ctx, struct mail *mail,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen void *context __attr_unused__)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen const char *envelope;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen envelope = mail_get_special(mail, MAIL_FETCH_IMAP_ENVELOPE);
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen if (envelope == NULL)
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen return -1;
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen if (ctx->first)
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen ctx->first = FALSE;
0cce885512b836ce021260a58e7b4f099b36d0f1Timo Sirainen else {
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen if (o_stream_send(ctx->client->output, " ", 1) < 0)
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen return -1;
0cce885512b836ce021260a58e7b4f099b36d0f1Timo Sirainen }
0cce885512b836ce021260a58e7b4f099b36d0f1Timo Sirainen
e050e5c9b1688765f1fdfce9b7141f7b614383fdTimo Sirainen if (o_stream_send(ctx->client->output, "ENVELOPE (", 10) < 0 ||
4d527c363482be2b65dd0573d878ecda86cbb0bbTimo Sirainen o_stream_send_str(ctx->client->output, envelope) < 0 ||
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen o_stream_send(ctx->client->output, ")", 1) < 0)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return -1;
b62140c5849297a800fee942026d9c3cb8c60206Timo Sirainen return 1;
b62140c5849297a800fee942026d9c3cb8c60206Timo Sirainen}
b62140c5849297a800fee942026d9c3cb8c60206Timo Sirainen
b62140c5849297a800fee942026d9c3cb8c60206Timo Sirainenstatic bool fetch_envelope_init(struct imap_fetch_context *ctx,
4d527c363482be2b65dd0573d878ecda86cbb0bbTimo Sirainen const char *name __attr_unused__,
4d527c363482be2b65dd0573d878ecda86cbb0bbTimo Sirainen struct imap_arg **args __attr_unused__)
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen{
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen ctx->fetch_data |= MAIL_FETCH_IMAP_ENVELOPE;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen imap_fetch_add_handler(ctx, FALSE, FALSE, fetch_envelope, NULL);
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen return TRUE;
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen}
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainenstatic int fetch_flags(struct imap_fetch_context *ctx, struct mail *mail,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen void *context __attr_unused__)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen enum mail_flags flags;
de58be41126e5d68008d2ea706d62ccdc1f29337Timo Sirainen const char *const *keywords;
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen flags = mail_get_flags(mail);
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen keywords = mail_get_keywords(mail);
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (ctx->flags_update_seen && (flags & MAIL_SEEN) == 0) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* Add \Seen flag */
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen flags |= MAIL_SEEN;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen if (mail_update_flags(mail, MODIFY_ADD, MAIL_SEEN) < 0)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return -1;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen } else if (ctx->flags_show_only_seen_changes) {
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen return 1;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen }
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen str_append(ctx->cur_str, "FLAGS (");
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen imap_write_flags(ctx->cur_str, flags, keywords);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen str_append(ctx->cur_str, ") ");
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return 1;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen}
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainenstatic bool fetch_flags_init(struct imap_fetch_context *ctx,
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen const char *name __attr_unused__,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct imap_arg **args __attr_unused__)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->flags_have_handler = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->fetch_data |= MAIL_FETCH_FLAGS;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen imap_fetch_add_handler(ctx, TRUE, FALSE, fetch_flags, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainenstatic int fetch_internaldate(struct imap_fetch_context *ctx, struct mail *mail,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen void *context __attr_unused__)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen{
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen time_t time;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen time = mail_get_received_date(mail);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (time == (time_t)-1)
ebe6df72f1309135f02b6a4d2aef1e81a073f91cTimo Sirainen return -1;
910fa4e4204a73d3d24c03f3059dd24e727ca057Timo Sirainen
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen str_printfa(ctx->cur_str, "INTERNALDATE \"%s\" ",
4bbd396aa6198c84f3f7763b6e8a63a26e97e141Timo Sirainen imap_to_datetime(time));
b83deefd2cf1e293373673eefb4d5cf60907978cTimo Sirainen return 1;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen}
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainenstatic bool fetch_internaldate_init(struct imap_fetch_context *ctx,
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen const char *name __attr_unused__,
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen struct imap_arg **args __attr_unused__)
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen{
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen ctx->fetch_data |= MAIL_FETCH_RECEIVED_DATE;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen imap_fetch_add_handler(ctx, TRUE, FALSE, fetch_internaldate, NULL);
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen return TRUE;
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen}
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen
b3b4f3875850099c9292ad74d08bb385c3988f8fTimo Sirainenstatic int fetch_uid(struct imap_fetch_context *ctx, struct mail *mail,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen void *context __attr_unused__)
{
str_printfa(ctx->cur_str, "UID %u ", mail->uid);
return 1;
}
static bool fetch_uid_init(struct imap_fetch_context *ctx __attr_unused__,
const char *name __attr_unused__,
struct imap_arg **args __attr_unused__)
{
imap_fetch_add_handler(ctx, TRUE, FALSE, fetch_uid, NULL);
return TRUE;
}
const struct imap_fetch_handler default_handlers[7] = {
{ "BODY", fetch_body_init },
{ "BODYSTRUCTURE", fetch_bodystructure_init },
{ "ENVELOPE", fetch_envelope_init },
{ "FLAGS", fetch_flags_init },
{ "INTERNALDATE", fetch_internaldate_init },
{ "RFC822", fetch_rfc822_init },
{ "UID", fetch_uid_init }
};