mail-messageset.c revision 4f08c1d64625ab2c0dda7f5793b539852238d19c
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen#include "lib.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen#include "mail-index.h"
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen#include "mail-index-util.h"
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen#include "mail-hash.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen#include "mail-modifylog.h"
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen#include "mail-messageset.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen
45155bb1250cf5a120278f349465aded513a100fTimo Sirainenstatic unsigned int get_next_number(const char **str)
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen{
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen unsigned int num;
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen num = 0;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen while (**str != '\0') {
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen if (**str < '0' || **str > '9')
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen break;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen num = num*10 + (**str - '0');
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen (*str)++;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen }
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen return num;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen}
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainenstatic int mail_index_foreach(MailIndex *index,
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen unsigned int seq, unsigned int seq2,
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen MsgsetForeachFunc func, void *context,
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen const char **error)
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen{
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen MailIndexRecord *rec;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen const unsigned int *expunges;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen unsigned int expunges_before;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen int expunges_found;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen if (seq > seq2) {
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen /* Second sequence can't be smaller than first - we could swap
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen them but I think it's a bug in client if it does this,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen and better complain about it immediately than later let
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen them wonder why it doesn't work with other imapds.. */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen *error = t_strdup_printf("Invalid messageset range: %u > %u",
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen seq, seq2);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen return -2;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* get list of expunged messages in our range. the expunges_before
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen can be used to calculate the current real sequence position */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen expunges = mail_modifylog_seq_get_expunges(index->modifylog, seq, seq2,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen &expunges_before);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen i_assert(expunges_before < seq);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen expunges_found = *expunges != '\0';
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen /* Reset index errors, since we later rely on it to check if failed */
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen index_reset_error(index);
b8cd2f2f99351605725b7260f5da89cff76d0a3aTimo Sirainen
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen /* get the first non-expunged message. note that if all messages
d7cd49f01fad7c87c5a0865ebf54a548275e9feeTimo Sirainen were expunged in the range, this points outside wanted range. */
d7cd49f01fad7c87c5a0865ebf54a548275e9feeTimo Sirainen rec = index->lookup(index, seq - expunges_before);
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen for (; rec != NULL; seq++) {
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen /* skip expunged sequences */
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen i_assert(rec->uid != 0);
b8cd2f2f99351605725b7260f5da89cff76d0a3aTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen while (*expunges != 0 && *expunges < rec->uid) {
45155bb1250cf5a120278f349465aded513a100fTimo Sirainen expunges++;
45155bb1250cf5a120278f349465aded513a100fTimo Sirainen seq++;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen }
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen i_assert(*expunges != rec->uid);
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen if (seq > seq2)
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen break;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen t_push();
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (!func(index, rec, seq, context)) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen t_pop();
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen return 0;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen t_pop();
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen rec = index->next(index, rec);
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen }
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen if (rec == NULL && index->get_last_error(index) != NULL) {
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen /* error occured */
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen return -1;
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen return !expunges_found && seq > seq2 ? 1 : 2;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen}
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainenint mail_index_messageset_foreach(MailIndex *index, const char *messageset,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen unsigned int messages_count,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen MsgsetForeachFunc func, void *context,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen const char **error)
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen{
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen const char *input;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen unsigned int seq, seq2;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen int ret, all_found;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen *error = NULL;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen if (messages_count == 0) {
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen /* no messages in mailbox */
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen return 1;
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen }
b8422738d3c891c7c93294b027a5cfe7d520e378Timo Sirainen
b8422738d3c891c7c93294b027a5cfe7d520e378Timo Sirainen all_found = TRUE;
b8422738d3c891c7c93294b027a5cfe7d520e378Timo Sirainen input = messageset;
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen while (*input != '\0') {
8e50329e2c5e3a199674ae9f6d3dfcddab02487bTimo Sirainen if (*input == '*') {
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen /* last message */
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen seq = messages_count;
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen input++;
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen } else {
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen seq = get_next_number(&input);
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen if (seq == 0) {
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen *error = t_strconcat("Invalid messageset: ",
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen messageset, NULL);
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen return -2;
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen }
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen }
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen if (*input != ':')
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen seq2 = seq;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen else {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* first:last range */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen input++;
1eff76c5dbd2ff14bbb7e40a164c290931bdf692Timo Sirainen
cd94aeaa294f7cc507206b4b2075852f00e14d61Timo Sirainen if (*input != '*') {
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen seq2 = get_next_number(&input);
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen if (seq2 == 0) {
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen *error = t_strconcat("Invalid "
cd94aeaa294f7cc507206b4b2075852f00e14d61Timo Sirainen "messageset: ",
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen messageset, NULL);
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen return -2;
d67848ba944a3172c4834c591ddc921fa4ff16b1Timo Sirainen }
f8a78c816b4dbfda42f13d8ee152e0cdb28c6a4aTimo Sirainen
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen if (seq2 > messages_count) {
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen /* too large .. ignore silently */
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen seq2 = messages_count;
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen }
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen } else {
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen seq2 = messages_count;
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen input++;
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen }
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen }
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen if (*input == ',')
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen input++;
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen else if (*input != '\0') {
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen *error = t_strdup_printf("Unexpected char '%c' "
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen "with messageset: %s",
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen *input, messageset);
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen return -2;
4b6ddd3770c8484da7308032b75fc93b91aa1b49Timo Sirainen }
4b6ddd3770c8484da7308032b75fc93b91aa1b49Timo Sirainen
4b6ddd3770c8484da7308032b75fc93b91aa1b49Timo Sirainen if (seq > messages_count) {
4b6ddd3770c8484da7308032b75fc93b91aa1b49Timo Sirainen /* too large .. ignore silently */
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen } else {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ret = mail_index_foreach(index, seq, seq2,
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen func, context, error);
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen if (ret <= 0)
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen return ret;
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen if (ret == 2)
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen all_found = FALSE;
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen }
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen }
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen return all_found ? 1 : 2;
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen}
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainenstatic int mail_index_uid_foreach(MailIndex *index,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen unsigned int uid, unsigned int uid2,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen unsigned int max_sequence,
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen MsgsetForeachFunc func, void *context,
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen const char **error)
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen{
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen MailIndexRecord *rec;
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen uoff_t pos;
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen const unsigned int *expunges;
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen unsigned int seq;
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen int expunges_found;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen if (uid > uid2) {
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen /* not allowed - see mail_index_foreach() */
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen *error = t_strdup_printf("Invalid uidset range: %u > %u",
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen uid, uid2);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen return -2;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen }
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen /* get list of expunged messages in our range. */
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen expunges = mail_modifylog_uid_get_expunges(index->modifylog, uid, uid2);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen expunges_found = *expunges != '\0';
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen /* skip expunged messages at the beginning */
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen while (*expunges == uid) {
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen expunges++;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen if (++uid == uid2) {
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen /* all were expunged */
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen return 2;
6e8ad595d0603295f57bef576da8a3a00b55c5e2Timo Sirainen }
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen }
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen /* since we skipped the known expunged messages at the beginning
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen and our UIDs are contiguously allocated, the first hash lookup
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen _should_ work.. */
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen pos = mail_hash_lookup_uid(index->hash, uid);
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen if (pos != 0) {
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen if (pos + sizeof(MailIndexRecord) > index->mmap_length) {
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen /* hash is corrupted */
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen index_set_error(index, "Corrupted hash for index %s: "
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen "lookup returned offset outside range",
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen index->filepath);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen index->set_flags |= MAIL_INDEX_FLAG_REBUILD_HASH;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen return -1;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen }
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen rec = (MailIndexRecord *) ((char *) index->mmap_base + pos);
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen if (rec->uid != uid) {
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen /* hash is corrupted */
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen index_set_error(index, "Corrupted hash for index %s: "
f8a78c816b4dbfda42f13d8ee152e0cdb28c6a4aTimo Sirainen "lookup returned offset to "
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen "different UID", index->filepath);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen index->set_flags |= MAIL_INDEX_FLAG_REBUILD_HASH;
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen return -1;
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen } else {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* ..however if for any reason it doesn't,
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen still handle it properly */
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen if (uid == uid2)
feb665db52583259a1f42037c6e8a22852aa8889Timo Sirainen return 2;
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen rec = index->lookup_uid_range(index, uid+1, uid2);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen if (rec == NULL)
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen return 2;
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen }
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen seq = index->get_sequence(index, rec);
71f1783adc89b4fe3588c72b23e059b320da8fadTimo Sirainen while (rec != NULL && rec->uid <= uid2 && seq <= max_sequence) {
71f1783adc89b4fe3588c72b23e059b320da8fadTimo Sirainen uid = rec->uid;
71f1783adc89b4fe3588c72b23e059b320da8fadTimo Sirainen while (*expunges != 0 && *expunges < rec->uid) {
feb665db52583259a1f42037c6e8a22852aa8889Timo Sirainen expunges++;
feb665db52583259a1f42037c6e8a22852aa8889Timo Sirainen seq++;
feb665db52583259a1f42037c6e8a22852aa8889Timo Sirainen }
feb665db52583259a1f42037c6e8a22852aa8889Timo Sirainen i_assert(*expunges != rec->uid);
feb665db52583259a1f42037c6e8a22852aa8889Timo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen t_push();
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen if (!func(index, rec, seq, context)) {
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen t_pop();
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen return 0;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen }
feb665db52583259a1f42037c6e8a22852aa8889Timo Sirainen t_pop();
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen seq++;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen rec = index->next(index, rec);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen }
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen if (rec == NULL && index->get_last_error(index) != NULL) {
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen /* error occured */
ab1236617440e654d5c5a043b677512714b788ddTimo Sirainen return -1;
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen return !expunges_found && uid == uid2 ? 1 : 2;
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen}
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenint mail_index_uidset_foreach(MailIndex *index, const char *uidset,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen unsigned int messages_count,
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen MsgsetForeachFunc func, void *context,
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen const char **error)
{
MailIndexRecord *rec;
const char *input;
unsigned int uid, uid2;
int ret, all_found;
i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
*error = NULL;
if (messages_count == 0) {
/* no messages in mailbox */
return 1;
}
all_found = TRUE;
input = uidset;
while (*input != '\0') {
if (*input == '*') {
/* last message */
rec = index->lookup(index, messages_count);
uid = rec == NULL ? 0 : rec->uid;
input++;
} else {
uid = get_next_number(&input);
if (uid == 0) {
*error = t_strconcat("Invalid uidset: ",
uidset, NULL);
return -2;
}
}
if (*input != ':')
uid2 = uid;
else {
/* first:last range */
input++;
if (*input != '*') {
uid2 = get_next_number(&input);
if (uid2 == 0) {
*error = t_strconcat("Invalid uidset: ",
uidset, NULL);
return -2;
}
} else {
uid2 = index->header->next_uid-1;
input++;
}
}
if (*input == ',')
input++;
else if (*input != '\0') {
*error = t_strdup_printf("Unexpected char '%c' with "
"uidset: %s", *input, uidset);
return -2;
}
if (uid >= index->header->next_uid) {
/* too large .. ignore silently */
} else {
ret = mail_index_uid_foreach(index, uid, uid2,
messages_count,
func, context, error);
if (ret <= 0)
return ret;
if (ret == 2)
all_found = FALSE;
}
}
return all_found ? 1 : 2;
}