pop3c-sync.c revision 2676c973a61edf2a9dd5d0196e0993ecb04bb2a2
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2011-2016 Dovecot authors, see the included COPYING file */
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo SirainenARRAY_DEFINE_TYPE(pop3c_sync_msg, struct pop3c_sync_msg);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenint pop3c_sync_get_uidls(struct pop3c_mailbox *mbox)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if ((pop3c_client_get_capabilities(mbox->client) &
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen "UIDLs not supported by server");
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (pop3c_client_cmd_stream(mbox->client, "UIDL\r\n",
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mbox->uidl_pool = pool_alloconly_create("POP3 UIDLs", 1024*32);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen p_array_init(&uidls, mbox->uidl_pool, 64); seq = 0;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen while ((line = i_stream_read_next_line(input)) != NULL) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (str_to_uint(line, &line_seq) < 0 || line_seq != seq) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* make msg_uidls non-NULL */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenint pop3c_sync_get_sizes(struct pop3c_mailbox *mbox)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (pop3c_client_cmd_stream(mbox->client, "LIST\r\n",
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mbox->msg_sizes = i_new(uoff_t, mbox->msg_count); seq = 0;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen while ((line = i_stream_read_next_line(input)) != NULL) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (str_to_uint(line, &line_seq) < 0 || line_seq != seq) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (str_to_uoff(p, &mbox->msg_sizes[seq-1]) < 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen "Invalid LIST size: %s", p);
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainenpop3c_get_local_msgs(pool_t pool, ARRAY_TYPE(pop3c_sync_msg) *local_msgs,
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen if (mail_cache_lookup_field(cache_view, str, seq,
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainenpop3c_get_remote_msgs(ARRAY_TYPE(pop3c_sync_msg) *remote_msgs,
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen for (seq = 1; seq <= mbox->msg_count; seq++) {
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainenstatic int pop3c_sync_msg_uidl_cmp(const struct pop3c_sync_msg *msg1,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenpop3c_sync_messages(struct pop3c_mailbox *mbox,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct mail_cache_transaction_ctx *cache_trans;
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen ARRAY_TYPE(pop3c_sync_msg) local_msgs, remote_msgs;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen unsigned int cache_idx = ibox->cache_fields[MAIL_CACHE_POP3_UIDL].idx;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* set our uidvalidity */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen offsetof(struct mail_index_header, uid_validity),
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen pool = pool_alloconly_create(MEMPOOL_GROWING"pop3c sync", 10240);
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen p_array_init(&local_msgs, pool, hdr->messages_count);
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen pop3c_get_local_msgs(pool, &local_msgs, hdr->messages_count,
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen p_array_init(&remote_msgs, pool, mbox->msg_count);
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen /* sort the messages by UIDLs, because some servers reorder messages */
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen array_sort(&local_msgs, pop3c_sync_msg_uidl_cmp);
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen array_sort(&remote_msgs, pop3c_sync_msg_uidl_cmp);
c06f45d06438bd063bd3d915682d9db3b6adf725Timo Sirainen /* skip over existing messages with matching UIDLs and expunge the ones
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen that no longer exist in remote. (+1 to avoid malloc(0) assert) */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mbox->msg_uids = i_new(uint32_t, mbox->msg_count + 1);
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen cache_trans = mail_cache_get_transaction(cache_view, sync_trans);
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen uint32_t lseq = lidx < lcount ? lmsg[lidx].seq : 0;
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen uint32_t rseq = ridx < rcount ? rmsg[ridx].seq : 0;
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen ret = strcmp(lmsg[lidx].uidl, rmsg[ridx].uidl);
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen /* message expunged in remote */
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen } else if (ret > 0) {
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen /* new message in remote */
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen mail_index_append(sync_trans, next_uid++, &lseq);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* UIDL matched */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* mark the newly seen messages as recent */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (mail_index_lookup_seq_range(sync_view, hdr->first_recent_uid,
817d027593510c3ba70ad542ce0011f5f6916d1eTimo Sirainen mailbox_recent_flags_set_seqs(&mbox->box, sync_view, seq1, seq2);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct mail_index_view *sync_view, *trans_view;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen unsigned int idx;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen sync_flags = index_storage_get_sync_flags(&mbox->box) |
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ret = mail_index_sync_begin(mbox->box.index, &index_sync_ctx,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen trans_view = mail_index_transaction_open_updated_view(sync_trans);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen cache_view = mail_cache_view_open(mbox->box.cache, trans_view);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen pop3c_sync_messages(mbox, sync_view, sync_trans, cache_view);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* mark expunges messages as deleted in this pop3 session,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if those exist */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen while (mail_index_sync_next(index_sync_ctx, &sync_rec)) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (sync_rec.type != MAIL_INDEX_SYNC_TYPE_EXPUNGE)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (!bsearch_insert_pos(&sync_rec.uid1, mbox->msg_uids,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* no such messages in this session */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_assert(mbox->msg_uids[idx] >= sync_rec.uid1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen pop3c_client_cmd_line_async(mbox->client, str_c(str));
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (mail_index_sync_commit(&index_sync_ctx) < 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (pop3c_client_cmd_line(mbox->client, "QUIT\r\n",
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenpop3c_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct pop3c_mailbox *mbox = (struct pop3c_mailbox *)box;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FULL_READ) != 0 &&
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* FIXME: reconnect */