bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2011-2018 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",
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&mbox->box, "UIDL failed: %s", error);
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",
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(&mbox->box, "LIST failed: %s", error);
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
e7d0bea63a08b08c47c4b5c187d2cb7127859657Timo Sirainen that no longer exist in remote. */
e7d0bea63a08b08c47c4b5c187d2cb7127859657Timo Sirainen i_new(uint32_t, 1) : /* avoid malloc(0) assert */
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;
d546cddd14aa72823a1104e371527ae0a8a99e00Timo Sirainen else if (ridx >= rcount || lmsg[lidx].uidl == NULL)
2676c973a61edf2a9dd5d0196e0993ecb04bb2a2Timo Sirainen ret = strcmp(lmsg[lidx].uidl, rmsg[ridx].uidl);
d546cddd14aa72823a1104e371527ae0a8a99e00Timo Sirainen /* message expunged in remote, or we didn't have a
d546cddd14aa72823a1104e371527ae0a8a99e00Timo Sirainen local message's UIDL in cache. */
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 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);
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen pop3c_client_cmd_line_async_nocb(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)
95d62f8d6d281cc488dc4f488d4388701e559012Josef 'Jeff' Sipek struct pop3c_mailbox *mbox = POP3C_MAILBOX(box);
e098ac1cd4ff0afb33b22cc7fd288014f4fdb0bcTimo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FULL_READ) != 0 &&
e098ac1cd4ff0afb33b22cc7fd288014f4fdb0bcTimo Sirainen /* FIXME: reconnect */