pop3-migration-plugin.c revision 1c3dc4c08ced3948f52c3c6c171ed77310b2cbfd
/* Copyright (c) 2007-2013 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "istream.h"
#include "istream-header-filter.h"
#include "sha1.h"
#include "message-size.h"
#include "mail-namespace.h"
#include "mail-search-build.h"
#include "mail-storage-private.h"
#include "pop3-migration-plugin.h"
#define POP3_MIGRATION_CONTEXT(obj) \
#define POP3_MIGRATION_MAIL_CONTEXT(obj) \
struct pop3_uidl_map {
/* UIDL */
const char *pop3_uidl;
/* LIST size */
/* sha1(TOP 0) - set only when needed */
unsigned char hdr_sha1[SHA1_RESULTLEN];
unsigned int hdr_sha1_set:1;
};
struct imap_msg_map {
const char *pop3_uidl;
/* sha1(header) - set only when needed */
unsigned char hdr_sha1[SHA1_RESULTLEN];
unsigned int hdr_sha1_set:1;
};
struct pop3_migration_mail_storage {
const char *pop3_box_vname;
unsigned int all_mailboxes:1;
unsigned int pop3_all_hdr_sha1_set:1;
};
struct pop3_migration_mailbox {
union mailbox_module_context module_ctx;
unsigned int first_unfound_idx;
unsigned int uidl_synced:1;
unsigned int uidl_sync_failed:1;
unsigned int uidl_ordered:1;
};
static const char *hdr_hash_skip_headers[] = {
"Content-Length",
"Status",
"X-IMAP",
"X-IMAPbase",
"X-Keywords",
"X-Message-Flag",
"X-Status",
"X-UID",
"X-UIDL"
};
const char *pop3_migration_plugin_version = DOVECOT_ABI_VERSION;
const struct imap_msg_map *map2)
{
return -1;
return 1;
return 0;
}
const struct pop3_uidl_map *map2)
{
return -1;
return 1;
return 0;
}
const struct pop3_uidl_map *map2)
{
}
const struct imap_msg_map *map2)
{
}
{
struct message_size hdr_size;
const unsigned char *data;
i_error("pop3_migration: Failed to get header for msg %u: %s",
return -1;
}
/* hide headers that might change or be different in IMAP vs. POP3 */
*null_header_filter_callback, (void *)NULL);
}
if (input->stream_errno != 0) {
i_error("pop3_migration: Failed to read header for msg %u: %m",
return -1;
}
return 0;
}
{
struct pop3_migration_mail_storage *mstorage =
struct mail_namespace *ns;
}
{
struct pop3_migration_mail_storage *mstorage =
struct mailbox_transaction_context *t;
struct mail_search_args *search_args;
struct mail_search_context *ctx;
struct pop3_uidl_map *map;
const char *uidl;
int ret = 0;
/* already read these, just reset the imap_uids */
return 0;
}
if (mailbox_sync(pop3_box, 0) < 0) {
i_error("pop3_migration: Couldn't sync mailbox %s: %s",
return -1;
}
t = mailbox_transaction_begin(pop3_box, 0);
i_error("pop3_migration: Failed to get size for msg %u: %s",
ret = -1;
break;
}
i_error("pop3_migration: Failed to get UIDL for msg %u: %s",
ret = -1;
break;
}
if (*uidl == '\0') {
i_warning("pop3_migration: UIDL for msg %u is empty",
continue;
}
}
if (mailbox_search_deinit(&ctx) < 0)
ret = -1;
(void)mailbox_transaction_commit(&t);
return ret;
}
static int
unsigned first_seq)
{
struct pop3_migration_mail_storage *mstorage =
struct mailbox_transaction_context *t;
struct mail_search_args *search_args;
struct mail_search_context *ctx;
struct pop3_uidl_map *map;
int ret = 0;
return 0;
if (mstorage->all_mailboxes) {
/* we may be matching against multiple mailboxes.
read all the hashes only once. */
first_seq = 1;
}
t = mailbox_transaction_begin(pop3_box, 0);
ret = -1;
else
}
if (mailbox_search_deinit(&ctx) < 0)
ret = -1;
(void)mailbox_transaction_commit(&t);
return ret;
}
{
struct mailbox_status status;
struct mailbox_transaction_context *t;
struct mail_search_args *search_args;
struct mail_search_context *ctx;
struct imap_msg_map *map;
int ret = 0;
t = mailbox_transaction_begin(box, 0);
i_error("pop3_migration: Failed to get psize for imap uid %u: %s",
ret = -1;
break;
}
}
if (mailbox_search_deinit(&ctx) < 0)
ret = -1;
(void)mailbox_transaction_commit(&t);
return ret;
}
{
struct mailbox_transaction_context *t;
struct mail_search_args *search_args;
struct mail_search_context *ctx;
struct imap_msg_map *map;
int ret = 0;
t = mailbox_transaction_begin(box, 0);
ret = -1;
else
}
if (mailbox_search_deinit(&ctx) < 0)
ret = -1;
(void)mailbox_transaction_commit(&t);
return ret;
}
{
struct pop3_migration_mail_storage *mstorage =
struct pop3_uidl_map *pop3_map;
struct imap_msg_map *imap_map;
/* see if we can match the messages using sizes */
for (i = 0; i < count; i++) {
break;
/* two messages with same size, don't trust them */
break;
}
}
mbox->first_unfound_idx = i;
return i == count;
}
static int
{
struct pop3_migration_mail_storage *mstorage =
struct pop3_uidl_map *pop3_map;
struct imap_msg_map *imap_map;
unsigned int first_seq, missing_uids_count;
int ret;
imap_map_read_hdr_hashes(box) < 0)
return -1;
pop3_idx++;
continue;
}
imap_idx++;
continue;
}
if (ret < 0)
pop3_idx++;
else if (ret > 0)
imap_idx++;
else {
}
}
missing_uids_count = 0;
}
i_warning("pop3_migration: %u POP3 messages have no "
"matching IMAP messages", missing_uids_count);
}
return 0;
}
{
struct pop3_migration_mail_storage *mstorage =
const struct pop3_uidl_map *pop3_map;
unsigned int i, count;
if (mbox->uidl_synced)
return 0;
/* the POP3 server isn't connected to yet. handle all IMAP traffic
first before connecting, so POP3 server won't disconnect us due to
idling. */
if (imap_map_read(box) < 0 ||
return -1;
}
if (!pop3_uidl_assign_by_size(box)) {
/* everything wasn't assigned, figure out the rest with
header hashes */
return -1;
}
}
/* see if the POP3 UIDL order is the same as IMAP UID order */
prev_uid = 0;
for (i = 0; i < count; i++) {
continue;
break;
}
}
return 0;
}
static int
const char **value_r)
{
if (field == MAIL_FETCH_UIDL_BACKEND ||
field == MAIL_FETCH_POP3_ORDER) {
if (mbox->uidl_sync_failed ||
"POP3 UIDLs couldn't be synced");
return -1;
}
if (field == MAIL_FETCH_UIDL_BACKEND)
else
return 0;
}
/* not found from POP3 server, fallback to default */
}
}
{
struct pop3_migration_mail_storage *mstorage =
union mail_module_context *mmail;
struct mail_namespace *ns;
/* assigns UIDLs only for INBOX */
return;
}
/* we're accessing the pop3-migration namespace itself */
return;
}
}
{
struct pop3_migration_mailbox *mbox;
}
{
struct pop3_migration_mail_storage *mstorage =
}
{
struct pop3_migration_mail_storage *mstorage;
const char *pop3_box_vname;
"pop3_migration_mailbox");
if (pop3_box_vname == NULL)
return;
"pop3_migration_all_mailboxes") != NULL;
}
static struct mail_storage_hooks pop3_migration_mail_storage_hooks = {
};
{
}
void pop3_migration_plugin_deinit(void)
{
}