index-fetch.c revision 100e980900f652c9114997d7153e010e0639effe
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/* Copyright (C) 2002 Timo Sirainen */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "lib.h"
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen#include "obuffer.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "temp-string.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "mail-custom-flags.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "index-storage.h"
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen#include "index-fetch.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "index-messageset.h"
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen#include "message-send.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "imap-date.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "imap-util.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "imap-message-cache.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include <unistd.h>
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainenstatic int index_fetch_internaldate(MailIndexRecord *rec, FetchContext *ctx)
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen{
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen time_t date;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen date = imap_msgcache_get_internal_date(ctx->cache);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (date != (time_t)-1) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen t_string_printfa(ctx->str, "INTERNALDATE \"%s\" ",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen imap_to_datetime(date));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return TRUE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } else {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mail_storage_set_critical(ctx->storage,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "Couldn't generate INTERNALDATE for UID %u (index %s)",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen rec->uid, ctx->index->filepath);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return FALSE;
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen }
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen}
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainenstatic int index_fetch_body(MailIndexRecord *rec, FetchContext *ctx)
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen{
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen const char *body;
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen body = imap_msgcache_get(ctx->cache, IMAP_CACHE_BODY);
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen if (body != NULL) {
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen t_string_printfa(ctx->str, "BODY (%s) ", body);
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen return TRUE;
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen } else {
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen mail_storage_set_critical(ctx->storage,
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen "Couldn't generate BODY for UID %u (index %s)",
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen rec->uid, ctx->index->filepath);
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen return FALSE;
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen }
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen}
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainen
31e7be5e1d41a77f08d26cef46aba1df24b3f1baTimo Sirainenstatic int index_fetch_bodystructure(MailIndexRecord *rec, FetchContext *ctx)
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen{
31e7be5e1d41a77f08d26cef46aba1df24b3f1baTimo Sirainen const char *bodystructure;
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen bodystructure = imap_msgcache_get(ctx->cache, IMAP_CACHE_BODYSTRUCTURE);
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen if (bodystructure != NULL) {
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen t_string_printfa(ctx->str, "BODYSTRUCTURE (%s) ",
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen bodystructure);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return TRUE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } else {
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen mail_storage_set_critical(ctx->storage,
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen "Couldn't generate BODYSTRUCTURE for UID %u (index %s)",
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen rec->uid, ctx->index->filepath);
a9c8c1f74e5d2911d3c15657727a30b649d3bbc4Timo Sirainen return FALSE;
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainenstatic int index_fetch_envelope(MailIndexRecord *rec, FetchContext *ctx)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen const char *envelope;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen envelope = imap_msgcache_get(ctx->cache, IMAP_CACHE_ENVELOPE);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen if (envelope != NULL) {
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen t_string_printfa(ctx->str, "ENVELOPE (%s) ", envelope);
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen return TRUE;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen } else {
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen mail_storage_set_critical(ctx->storage,
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen "Couldn't generate ENVELOPE for UID %u (index %s)",
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen rec->uid, ctx->index->filepath);
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen return FALSE;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen }
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen}
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainenstatic int index_fetch_rfc822_size(MailIndexRecord *rec, FetchContext *ctx)
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen{
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen uoff_t size;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen size = imap_msgcache_get_virtual_size(ctx->cache);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen if (size == (uoff_t)-1) {
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen mail_storage_set_critical(ctx->storage,
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen "Couldn't get RFC822.SIZE for UID %u (index %s)",
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen rec->uid, ctx->index->filepath);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen return FALSE;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen }
dc8ba4890b74bde400e0feef96114940129ab181Timo Sirainen
dc8ba4890b74bde400e0feef96114940129ab181Timo Sirainen t_string_printfa(ctx->str, "RFC822.SIZE %"PRIuUOFF_T" ", size);
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen return TRUE;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen}
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainenstatic void index_fetch_flags(MailIndexRecord *rec, FetchContext *ctx)
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen{
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen MailFlags flags;
1e7252421b9c85b898fef7e75bd6422ef1f046e4Timo Sirainen
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen flags = rec->msg_flags;
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen if (rec->uid >= ctx->index->first_recent_uid)
5af8ea0a24c5930a8e310ebc4f33fba1d084217cTimo Sirainen flags |= MAIL_RECENT;
1e7252421b9c85b898fef7e75bd6422ef1f046e4Timo Sirainen if (ctx->update_seen)
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen flags |= MAIL_SEEN;
17e09bf093bf968f383a90c559399656dffafe73Timo Sirainen
17e09bf093bf968f383a90c559399656dffafe73Timo Sirainen t_string_printfa(ctx->str, "FLAGS (%s) ",
17e09bf093bf968f383a90c559399656dffafe73Timo Sirainen imap_write_flags(flags, ctx->custom_flags,
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen ctx->custom_flags_count));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void index_fetch_uid(MailIndexRecord *rec, FetchContext *ctx)
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen{
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen t_string_printfa(ctx->str, "UID %u ", rec->uid);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen}
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainenstatic int index_fetch_send_rfc822(MailIndexRecord *rec, FetchContext *ctx)
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen{
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen MessageSize hdr_size, body_size;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen IBuffer *inbuf;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen const char *str;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!imap_msgcache_get_rfc822(ctx->cache, &inbuf,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen &hdr_size, &body_size)) {
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen mail_storage_set_critical(ctx->storage,
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen "Couldn't get RFC822 for UID %u (index %s)",
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen rec->uid, ctx->index->filepath);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen return FALSE;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen }
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen str = t_strdup_printf(" RFC822 {%"PRIuUOFF_T"}\r\n",
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen hdr_size.virtual_size + body_size.virtual_size);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen if (ctx->first) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen str++; ctx->first = FALSE;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen }
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0)
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen return FALSE;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen body_size.physical_size += hdr_size.physical_size;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen body_size.virtual_size += hdr_size.virtual_size;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return message_send(ctx->outbuf, inbuf, &body_size, 0, (uoff_t)-1);
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen}
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainenstatic int index_fetch_send_rfc822_header(MailIndexRecord *rec,
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen FetchContext *ctx)
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen{
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen MessageSize hdr_size;
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen IBuffer *inbuf;
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen const char *str;
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!imap_msgcache_get_rfc822(ctx->cache, &inbuf, &hdr_size, NULL)) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_storage_set_critical(ctx->storage,
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen "Couldn't get RFC822.HEADER for UID %u (index %s)",
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen rec->uid, ctx->index->filepath);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen return FALSE;
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen str = t_strdup_printf(" RFC822.HEADER {%"PRIuUOFF_T"}\r\n",
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen hdr_size.virtual_size);
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen if (ctx->first) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen str++; ctx->first = FALSE;
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen }
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0)
a7bee3930831a9261fa6180d02af29c484d862e9Timo Sirainen return FALSE;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen return message_send(ctx->outbuf, inbuf, &hdr_size, 0, (uoff_t)-1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int index_fetch_send_rfc822_text(MailIndexRecord *rec, FetchContext *ctx)
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen{
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen MessageSize body_size;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen IBuffer *inbuf;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *str;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!imap_msgcache_get_rfc822(ctx->cache, &inbuf, NULL, &body_size)) {
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen mail_storage_set_critical(ctx->storage,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "Couldn't get RFC822.TEXT for UID %u (index %s)",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen rec->uid, ctx->index->filepath);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return FALSE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen str = t_strdup_printf(" RFC822.TEXT {%"PRIuUOFF_T"}\r\n",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen body_size.virtual_size);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ctx->first) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen str++; ctx->first = FALSE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0)
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen return FALSE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return message_send(ctx->outbuf, inbuf, &body_size, 0, (uoff_t)-1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic ImapCacheField index_get_cache(MailFetchData *fetch_data)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen MailFetchBodyData *sect;
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen ImapCacheField field;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen field = 0;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen if (fetch_data->body)
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen field |= IMAP_CACHE_BODY;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen if (fetch_data->bodystructure)
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen field |= IMAP_CACHE_BODYSTRUCTURE;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen if (fetch_data->envelope)
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen field |= IMAP_CACHE_ENVELOPE;
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen if (fetch_data->internaldate)
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen field |= IMAP_CACHE_INTERNALDATE;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen if (fetch_data->rfc822_size)
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen field |= IMAP_CACHE_VIRTUAL_SIZE;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen if (fetch_data->rfc822) {
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen field |= IMAP_CACHE_MESSAGE_OPEN | IMAP_CACHE_MESSAGE_HDR_SIZE |
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen IMAP_CACHE_MESSAGE_BODY_SIZE;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (fetch_data->rfc822_header)
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen field |= IMAP_CACHE_MESSAGE_OPEN | IMAP_CACHE_MESSAGE_HDR_SIZE;
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen if (fetch_data->rfc822_text)
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen field |= IMAP_CACHE_MESSAGE_OPEN | IMAP_CACHE_MESSAGE_BODY_SIZE;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* check what body[] sections want */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen sect = fetch_data->body_sections;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen for (; sect != NULL; sect = sect->next)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen field |= index_fetch_body_get_cache(sect->section);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen return field;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen}
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainenstatic int fetch_msgcache_open(FetchContext *ctx, MailIndexRecord *rec)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen{
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen ImapCacheField fields;
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen fields = index_get_cache(ctx->fetch_data);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (fields == 0)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen return TRUE;
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen return index_msgcache_open(ctx->cache, ctx->index, rec, fields);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen}
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainenstatic int index_fetch_mail(MailIndex *index __attr_unused__,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen MailIndexRecord *rec,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen unsigned int client_seq,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen unsigned int idx_seq,
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen void *context)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen{
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen FetchContext *ctx = context;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen MailFetchBodyData *sect;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen unsigned int orig_len;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen int failed, data_written, fetch_flags;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainen /* first see what we need to do. this way we don't first do some
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen light parsing and later notice that we need to do heavier parsing
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen anyway */
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen if (!fetch_msgcache_open(ctx, rec)) {
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen /* most likely message not found, just ignore it. */
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainen imap_msgcache_close(ctx->cache);
e665999b757e60bfb98e5a84a78b05f061453140Timo Sirainen ctx->failed = TRUE;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen return TRUE;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen }
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen if (ctx->update_seen && (rec->msg_flags & MAIL_SEEN) == 0) {
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen (void)index->update_flags(index, rec, idx_seq,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen rec->msg_flags | MAIL_SEEN, FALSE);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen fetch_flags = TRUE;
f3d506e525a720f214020ca0f989a1966b30edaeTimo Sirainen } else {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen fetch_flags = FALSE;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen }
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen ctx->str = t_string_new(2048);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen t_string_printfa(ctx->str, "* %u FETCH (", client_seq);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen orig_len = ctx->str->len;
f8a86fdfb0048f9c87bf223373b35416ceb5856bTimo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen failed = TRUE;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen data_written = FALSE;
e665999b757e60bfb98e5a84a78b05f061453140Timo Sirainen do {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* these can't fail */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ctx->fetch_data->uid)
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen index_fetch_uid(rec, ctx);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ctx->fetch_data->flags || fetch_flags)
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen index_fetch_flags(rec, ctx);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen /* rest can */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (ctx->fetch_data->internaldate)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!index_fetch_internaldate(rec, ctx))
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen break;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen if (ctx->fetch_data->body)
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen if (!index_fetch_body(rec, ctx))
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen break;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ctx->fetch_data->bodystructure)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!index_fetch_bodystructure(rec, ctx))
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen break;
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen if (ctx->fetch_data->envelope)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!index_fetch_envelope(rec, ctx))
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen break;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (ctx->fetch_data->rfc822_size)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!index_fetch_rfc822_size(rec, ctx))
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen break;
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* send the data written into temp string,
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen not including the trailing zero */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx->first = ctx->str->len == orig_len;
if (ctx->str->len > 0) {
if (!ctx->first)
ctx->str->len--;
if (o_buffer_send(ctx->outbuf, ctx->str->str,
ctx->str->len) < 0)
break;
}
data_written = TRUE;
/* large data */
if (ctx->fetch_data->rfc822)
if (!index_fetch_send_rfc822(rec, ctx))
break;
if (ctx->fetch_data->rfc822_text)
if (!index_fetch_send_rfc822_text(rec, ctx))
break;
if (ctx->fetch_data->rfc822_header)
if (!index_fetch_send_rfc822_header(rec, ctx))
break;
sect = ctx->fetch_data->body_sections;
for (; sect != NULL; sect = sect->next) {
if (!index_fetch_body_section(rec, sect, ctx))
break;
}
failed = FALSE;
} while (0);
if (data_written) {
if (o_buffer_send(ctx->outbuf, ")\r\n", 3) < 0)
failed = TRUE;
}
imap_msgcache_close(ctx->cache);
return !failed;
}
int index_storage_fetch(Mailbox *box, MailFetchData *fetch_data,
OBuffer *outbuf, int *all_found)
{
IndexMailbox *ibox = (IndexMailbox *) box;
FetchContext ctx;
MailFetchBodyData *sect;
int ret;
memset(&ctx, 0, sizeof(ctx));
if (!box->readonly) {
/* If we have any BODY[..] sections, \Seen flag is added for
all messages */
sect = fetch_data->body_sections;
for (; sect != NULL; sect = sect->next) {
if (!sect->peek) {
ctx.update_seen = TRUE;
break;
}
}
}
/* need exclusive lock to update the \Seen flags */
if (ctx.update_seen) {
if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_EXCLUSIVE))
return mail_storage_set_index_error(ibox);
}
if (!index_storage_sync_and_lock(ibox, TRUE, MAIL_LOCK_SHARED))
return FALSE;
if (ctx.update_seen &&
ibox->index->header->messages_count ==
ibox->index->header->seen_messages_count) {
/* if all messages are already seen, there's no point in
keeping exclusive lock */
ctx.update_seen = FALSE;
(void)ibox->index->set_lock(ibox->index, MAIL_LOCK_SHARED);
}
ctx.box = box;
ctx.storage = box->storage;
ctx.cache = ibox->cache;
ctx.index = ibox->index;
ctx.custom_flags =
mail_custom_flags_list_get(ibox->index->custom_flags);
ctx.custom_flags_count = MAIL_CUSTOM_FLAGS_COUNT;
ctx.fetch_data = fetch_data;
ctx.outbuf = outbuf;
ret = index_messageset_foreach(ibox, fetch_data->messageset,
fetch_data->uidset,
index_fetch_mail, &ctx);
if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_UNLOCK))
return mail_storage_set_index_error(ibox);
if (all_found != NULL)
*all_found = ret == 1 && !ctx.failed;
return ret > 0;
}