dovecot-2.1: pop3: Added pop3_uidl_duplicates setting.
dovecot at dovecot.org
dovecot at dovecot.org
Mon May 14 21:07:52 EEST 2012
details: http://hg.dovecot.org/dovecot-2.1/rev/3a095892242b
changeset: 14527:3a095892242b
user: Timo Sirainen <tss at iki.fi>
date: Mon May 14 21:07:43 2012 +0300
description:
pop3: Added pop3_uidl_duplicates setting.
diffstat:
doc/example-config/conf.d/20-pop3.conf | 5 +
src/pop3/pop3-client.c | 37 ++-
src/pop3/pop3-client.h | 5 +-
src/pop3/pop3-commands.c | 272 ++++++++++++++++++++++----------
src/pop3/pop3-settings.c | 4 +-
src/pop3/pop3-settings.h | 1 +
6 files changed, 220 insertions(+), 104 deletions(-)
diffs (truncated from 509 to 300 lines):
diff -r 4bbc12a87a29 -r 3a095892242b doc/example-config/conf.d/20-pop3.conf
--- a/doc/example-config/conf.d/20-pop3.conf Mon May 14 19:30:03 2012 +0300
+++ b/doc/example-config/conf.d/20-pop3.conf Mon May 14 21:07:43 2012 +0300
@@ -54,6 +54,11 @@
# won't change those UIDLs. Currently this works only with Maildir.
#pop3_save_uidl = no
+ # What to do about duplicate UIDLs if they exist?
+ # allow: Show duplicates to clients.
+ # rename: Append a temporary -2, -3, etc. counter after the UIDL.
+ #pop3_uidl_duplicates = allow
+
# POP3 logout format string:
# %i - total number of bytes read from client
# %o - total number of bytes sent to client
diff -r 4bbc12a87a29 -r 3a095892242b src/pop3/pop3-client.c
--- a/src/pop3/pop3-client.c Mon May 14 19:30:03 2012 +0300
+++ b/src/pop3/pop3-client.c Mon May 14 21:07:43 2012 +0300
@@ -6,6 +6,7 @@
#include "network.h"
#include "istream.h"
#include "ostream.h"
+#include "crc32.h"
#include "str.h"
#include "llist.h"
#include "hostpid.h"
@@ -344,15 +345,20 @@
return NULL;
}
- if (var_has_key(set->pop3_logout_format, 'u', "uidl_change") &&
- client->messages_count > 0)
- client->message_uidl_hashes_save = TRUE;
-
client->uidl_keymask =
parse_uidl_keymask(client->mail_set->pop3_uidl_format);
if (client->uidl_keymask == 0)
i_fatal("Invalid pop3_uidl_format");
+ if (var_has_key(set->pop3_logout_format, 'u', "uidl_change")) {
+ /* logging uidl_change. we need hashes of the UIDLs */
+ client->message_uidls_save = TRUE;
+ } else if (strcmp(set->pop3_uidl_duplicates, "allow") != 0) {
+ /* UIDL duplicates aren't allowed, so we'll need to
+ keep track of them */
+ client->message_uidls_save = TRUE;
+ }
+
if (!set->pop3_no_flag_updates && client->messages_count > 0)
client->seen_bitmask = i_malloc(MSGS_BITMASK_SIZE(client));
@@ -375,12 +381,8 @@
uint32_t i, old_hash, new_hash;
unsigned int old_msg_count, new_msg_count;
- if (client->message_uidl_hashes == NULL) {
- /* UIDL command not given or %u not actually used in format */
- return "";
- }
- if (client->message_uidl_hashes_save) {
- /* UIDL command not finished */
+ if (client->message_uidls == NULL) {
+ /* UIDL command not given */
return "";
}
@@ -388,18 +390,18 @@
old_msg_count = client->lowest_retr_pop3_msn > 0 ?
client->lowest_retr_pop3_msn - 1 : client->messages_count;
for (i = 0, old_hash = 0; i < old_msg_count; i++)
- old_hash ^= client->message_uidl_hashes[i];
+ old_hash ^= crc32_str(client->message_uidls[i]);
/* assume all except deleted messages were sent to POP3 client */
if (!client->deleted) {
for (i = 0, new_hash = 0; i < client->messages_count; i++)
- new_hash ^= client->message_uidl_hashes[i];
+ new_hash ^= crc32_str(client->message_uidls[i]);
} else {
for (i = 0, new_hash = 0; i < client->messages_count; i++) {
if (client->deleted_bitmask[i / CHAR_BIT] &
(1 << (i % CHAR_BIT)))
continue;
- new_hash ^= client->message_uidl_hashes[i];
+ new_hash ^= crc32_str(client->message_uidls[i]);
}
}
@@ -444,7 +446,11 @@
tab[6].value = dec2str(client->total_size);
tab[7].value = dec2str(client->input->v_offset);
tab[8].value = dec2str(client->output->offset);
- tab[9].value = client_build_uidl_change_string(client);
+ if (var_has_key(client->set->pop3_logout_format,
+ tab[9].key, tab[9].long_key))
+ tab[9].value = client_build_uidl_change_string(client);
+ else
+ tab[9].value = "";
tab[10].value = client->session_id;
str = t_str_new(128);
@@ -498,8 +504,9 @@
}
mail_user_unref(&client->user);
+ if (client->uidl_pool != NULL)
+ pool_unref(&client->uidl_pool);
i_free(client->message_sizes);
- i_free(client->message_uidl_hashes);
i_free(client->deleted_bitmask);
i_free(client->seen_bitmask);
i_free(client->msgnum_to_seq_map);
diff -r 4bbc12a87a29 -r 3a095892242b src/pop3/pop3-client.h
--- a/src/pop3/pop3-client.h Mon May 14 19:30:03 2012 +0300
+++ b/src/pop3/pop3-client.h Mon May 14 21:07:43 2012 +0300
@@ -55,7 +55,7 @@
unsigned int retr_count;
/* [msgnum] */
- uint32_t *message_uidl_hashes;
+ const char **message_uidls;
uoff_t *message_sizes;
/* [msgnum/8] & msgnum%8 */
unsigned char *deleted_bitmask;
@@ -64,13 +64,14 @@
/* settings: */
const struct pop3_settings *set;
const struct mail_storage_settings *mail_set;
+ pool_t uidl_pool;
enum uidl_keys uidl_keymask;
unsigned int disconnected:1;
unsigned int deleted:1;
unsigned int waiting_input:1;
unsigned int anvil_sent:1;
- unsigned int message_uidl_hashes_save:1;
+ unsigned int message_uidls_save:1;
};
extern struct client *pop3_clients;
diff -r 4bbc12a87a29 -r 3a095892242b src/pop3/pop3-commands.c
--- a/src/pop3/pop3-commands.c Mon May 14 19:30:03 2012 +0300
+++ b/src/pop3/pop3-commands.c Mon May 14 21:07:43 2012 +0300
@@ -4,8 +4,8 @@
#include "array.h"
#include "istream.h"
#include "ostream.h"
+#include "hash.h"
#include "str.h"
-#include "crc32.h"
#include "var-expand.h"
#include "message-size.h"
#include "mail-storage.h"
@@ -550,62 +550,9 @@
bool list_all;
};
-static bool pop3_get_uid(struct client *client, struct cmd_uidl_context *ctx,
- struct var_expand_table *tab, string_t *str)
-{
- char uid_str[MAX_INT_STRLEN];
- const char *uidl;
-
- if (mail_get_special(ctx->mail, MAIL_FETCH_UIDL_BACKEND, &uidl) == 0 &&
- *uidl != '\0') {
- str_append(str, uidl);
- return TRUE;
- }
-
- if (client->set->pop3_reuse_xuidl &&
- mail_get_first_header(ctx->mail, "X-UIDL", &uidl) > 0) {
- str_append(str, uidl);
- return FALSE;
- }
-
- if ((client->uidl_keymask & UIDL_UID) != 0) {
- i_snprintf(uid_str, sizeof(uid_str), "%u",
- ctx->mail->uid);
- tab[1].value = uid_str;
- }
- if ((client->uidl_keymask & UIDL_MD5) != 0) {
- if (mail_get_special(ctx->mail, MAIL_FETCH_HEADER_MD5,
- &tab[2].value) < 0 ||
- *tab[2].value == '\0') {
- /* broken */
- i_fatal("UIDL: Header MD5 not found "
- "(pop3_uidl_format=%%m not supported by storage?)");
- }
- }
- if ((client->uidl_keymask & UIDL_FILE_NAME) != 0) {
- if (mail_get_special(ctx->mail,
- MAIL_FETCH_UIDL_FILE_NAME,
- &tab[3].value) < 0 ||
- *tab[3].value == '\0') {
- /* broken */
- i_fatal("UIDL: File name not found "
- "(pop3_uidl_format=%%f not supported by storage?)");
- }
- }
- if ((client->uidl_keymask & UIDL_GUID) != 0) {
- if (mail_get_special(ctx->mail, MAIL_FETCH_GUID,
- &tab[4].value) < 0 ||
- *tab[4].value == '\0') {
- /* broken */
- i_fatal("UIDL: Message GUID not found "
- "(pop3_uidl_format=%%g not supported by storage?)");
- }
- }
- var_expand(str, client->mail_set->pop3_uidl_format, tab);
- return FALSE;
-}
-
-static bool list_uids_iter(struct client *client, struct cmd_uidl_context *ctx)
+static void
+pop3_get_uid(struct client *client, struct mail *mail, string_t *str,
+ bool *permanent_uidl_r)
{
static struct var_expand_table static_tab[] = {
{ 'v', NULL, "uidvalidity" },
@@ -616,20 +563,108 @@
{ '\0', NULL, NULL }
};
struct var_expand_table *tab;
- string_t *str;
- int ret;
- unsigned int uidl_pos;
- bool save_hashes, found = FALSE;
+ char uid_str[MAX_INT_STRLEN];
+ const char *uidl;
+
+ if (mail_get_special(mail, MAIL_FETCH_UIDL_BACKEND, &uidl) == 0 &&
+ *uidl != '\0') {
+ str_append(str, uidl);
+ /* UIDL is already permanent */
+ *permanent_uidl_r = TRUE;
+ return;
+ }
+
+ *permanent_uidl_r = FALSE;
+
+ if (client->set->pop3_reuse_xuidl &&
+ mail_get_first_header(mail, "X-UIDL", &uidl) > 0) {
+ str_append(str, uidl);
+ return;
+ }
tab = t_malloc(sizeof(static_tab));
memcpy(tab, static_tab, sizeof(static_tab));
tab[0].value = t_strdup_printf("%u", client->uid_validity);
- save_hashes = client->message_uidl_hashes_save && ctx->list_all;
- if (save_hashes && client->message_uidl_hashes == NULL) {
- client->message_uidl_hashes =
- i_new(uint32_t, client->messages_count);
+ if ((client->uidl_keymask & UIDL_UID) != 0) {
+ i_snprintf(uid_str, sizeof(uid_str), "%u",
+ mail->uid);
+ tab[1].value = uid_str;
}
+ if ((client->uidl_keymask & UIDL_MD5) != 0) {
+ if (mail_get_special(mail, MAIL_FETCH_HEADER_MD5,
+ &tab[2].value) < 0 ||
+ *tab[2].value == '\0') {
+ /* broken */
+ i_fatal("UIDL: Header MD5 not found "
+ "(pop3_uidl_format=%%m not supported by storage?)");
+ }
+ }
+ if ((client->uidl_keymask & UIDL_FILE_NAME) != 0) {
+ if (mail_get_special(mail, MAIL_FETCH_UIDL_FILE_NAME,
+ &tab[3].value) < 0 ||
+ *tab[3].value == '\0') {
+ /* broken */
+ i_fatal("UIDL: File name not found "
+ "(pop3_uidl_format=%%f not supported by storage?)");
+ }
+ }
+ if ((client->uidl_keymask & UIDL_GUID) != 0) {
+ if (mail_get_special(mail, MAIL_FETCH_GUID,
+ &tab[4].value) < 0 ||
+ *tab[4].value == '\0') {
+ /* broken */
+ i_fatal("UIDL: Message GUID not found "
+ "(pop3_uidl_format=%%g not supported by storage?)");
+ }
+ }
+ var_expand(str, client->mail_set->pop3_uidl_format, tab);
+}
+
+static bool
+list_uidls_saved_iter(struct client *client, struct cmd_uidl_context *ctx)
+{
+ bool found = FALSE;
+ int ret;
+
+ while (ctx->msgnum < client->messages_count) {
+ uint32_t msgnum = ctx->msgnum++;
+
+ if (client->deleted) {
+ if (client->deleted_bitmask[msgnum / CHAR_BIT] &
More information about the dovecot-cvs
mailing list