bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "lib.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "array.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "hex-binary.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "md5.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "istream.h"
ccaaf1874bb0c569ca2589444717fde155e1becaTimo Sirainen#include "istream-crlf.h"
1dc963aff48292e0d2557527b64fce985b715551Timo Sirainen#include "message-header-hash.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "message-size.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "mail-storage.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "dsync-mail.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
f97c983e7a742e1d54ec60e502093abbb3ad2907Timo Sirainenstruct mailbox_header_lookup_ctx *
69a71891361b2b27ff68ed84b29278486628464aAki Tuomidsync_mail_get_hash_headers(struct mailbox *box, const char *const *hashed_headers)
f97c983e7a742e1d54ec60e502093abbb3ad2907Timo Sirainen{
f97c983e7a742e1d54ec60e502093abbb3ad2907Timo Sirainen return mailbox_header_lookup_init(box, hashed_headers);
f97c983e7a742e1d54ec60e502093abbb3ad2907Timo Sirainen}
f97c983e7a742e1d54ec60e502093abbb3ad2907Timo Sirainen
45af47783693b3ba2768c5ad34eeff68132382d0Timo Sirainenint dsync_mail_get_hdr_hash(struct mail *mail, unsigned int version,
69a71891361b2b27ff68ed84b29278486628464aAki Tuomi const char *const *hashed_headers, const char **hdr_hash_r)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
ccaaf1874bb0c569ca2589444717fde155e1becaTimo Sirainen struct istream *hdr_input, *input;
271ba0b2a103e8040021597a3922f27b40d5b5dcTimo Sirainen struct mailbox_header_lookup_ctx *hdr_ctx;
b75eba4f65c7630d3691f07d22ff4bdfcac5054dTimo Sirainen struct message_header_hash_context hash_ctx;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct md5_context md5_ctx;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen unsigned char md5_result[MD5_RESULTLEN];
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const unsigned char *data;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen size_t size;
7f74811b78f8915e73dffc88bb49009e98b6846dTimo Sirainen ssize_t sret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int ret = 0;
271ba0b2a103e8040021597a3922f27b40d5b5dcTimo Sirainen
271ba0b2a103e8040021597a3922f27b40d5b5dcTimo Sirainen hdr_ctx = mailbox_header_lookup_init(mail->box, hashed_headers);
ccaaf1874bb0c569ca2589444717fde155e1becaTimo Sirainen ret = mail_get_header_stream(mail, hdr_ctx, &hdr_input);
271ba0b2a103e8040021597a3922f27b40d5b5dcTimo Sirainen mailbox_header_lookup_unref(&hdr_ctx);
271ba0b2a103e8040021597a3922f27b40d5b5dcTimo Sirainen if (ret < 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
ccaaf1874bb0c569ca2589444717fde155e1becaTimo Sirainen input = i_stream_create_lf(hdr_input);
ccaaf1874bb0c569ca2589444717fde155e1becaTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen md5_init(&md5_ctx);
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&hash_ctx);
7f74811b78f8915e73dffc88bb49009e98b6846dTimo Sirainen while ((sret = i_stream_read_more(input, &data, &size)) > 0) {
b75eba4f65c7630d3691f07d22ff4bdfcac5054dTimo Sirainen message_header_hash_more(&hash_ctx, &hash_method_md5, &md5_ctx,
b75eba4f65c7630d3691f07d22ff4bdfcac5054dTimo Sirainen version, data, size);
271ba0b2a103e8040021597a3922f27b40d5b5dcTimo Sirainen i_stream_skip(input, size);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7f74811b78f8915e73dffc88bb49009e98b6846dTimo Sirainen i_assert(sret == -1);
271ba0b2a103e8040021597a3922f27b40d5b5dcTimo Sirainen if (input->stream_errno != 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = -1;
ccaaf1874bb0c569ca2589444717fde155e1becaTimo Sirainen i_stream_unref(&input);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen md5_final(&md5_ctx, md5_result);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *hdr_hash_r = binary_to_hex(md5_result, sizeof(md5_result));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainenint dsync_mail_fill(struct mail *mail, bool minimal_fill,
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainen struct dsync_mail *dmail_r, const char **error_field_r)
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen{
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainen const char *guid;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(dmail_r);
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen if (mail_get_special(mail, MAIL_FETCH_GUID, &guid) < 0) {
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen *error_field_r = "GUID";
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen return -1;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen }
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen dmail_r->guid = guid;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen dmail_r->uid = mail->uid;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen dmail_r->input_mail = mail;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen dmail_r->input_mail_uid = mail->uid;
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainen
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainen if (mail_get_save_date(mail, &dmail_r->saved_date) < 0) {
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainen *error_field_r = "saved-date";
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainen return -1;
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainen }
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainen if (!minimal_fill)
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainen return dsync_mail_fill_nonminimal(mail, dmail_r, error_field_r);
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainen dmail_r->minimal_fields = TRUE;
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainen return 0;
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainen}
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainen
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainenint dsync_mail_fill_nonminimal(struct mail *mail, struct dsync_mail *dmail_r,
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainen const char **error_field_r)
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainen{
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainen const char *str;
d519a0449d0e536a32db93305516fdbd7db6773dTimo Sirainen
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen if (mail_get_stream(mail, NULL, NULL, &dmail_r->input) < 0) {
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen *error_field_r = "body";
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen return -1;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen }
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen if (mail_get_special(mail, MAIL_FETCH_UIDL_BACKEND, &dmail_r->pop3_uidl) < 0) {
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen *error_field_r = "pop3-uidl";
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen return -1;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen }
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen if (mail_get_special(mail, MAIL_FETCH_POP3_ORDER, &str) < 0) {
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen *error_field_r = "pop3-order";
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen return -1;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen }
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen if (*str != '\0') {
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen if (str_to_uint(str, &dmail_r->pop3_order) < 0)
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen i_unreached();
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen }
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen if (mail_get_received_date(mail, &dmail_r->received_date) < 0) {
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen *error_field_r = "received-date";
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen return -1;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen }
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen return 0;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen}
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic void
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenconst_string_array_dup(pool_t pool, const ARRAY_TYPE(const_string) *src,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ARRAY_TYPE(const_string) *dest)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *const *strings, *str;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen unsigned int i, count;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!array_is_created(src))
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen strings = array_get(src, &count);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (count == 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen p_array_init(dest, pool, count);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen for (i = 0; i < count; i++) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen str = p_strdup(pool, strings[i]);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen array_append(dest, &str, 1);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid dsync_mail_change_dup(pool_t pool, const struct dsync_mail_change *src,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct dsync_mail_change *dest_r)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dest_r->type = src->type;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dest_r->uid = src->uid;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (src->guid != NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dest_r->guid = *src->guid == '\0' ? "" :
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen p_strdup(pool, src->guid);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dest_r->hdr_hash = p_strdup(pool, src->hdr_hash);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dest_r->modseq = src->modseq;
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen dest_r->pvt_modseq = src->pvt_modseq;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dest_r->add_flags = src->add_flags;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dest_r->remove_flags = src->remove_flags;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dest_r->final_flags = src->final_flags;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dest_r->keywords_reset = src->keywords_reset;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const_string_array_dup(pool, &src->keyword_changes,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen &dest_r->keyword_changes);
3561c7bb472a78af74d755219cc0fc71c85ff5c2Timo Sirainen dest_r->received_timestamp = src->received_timestamp;
ae949831f1f668b5501b4b125e7f7b1767fb109bTimo Sirainen dest_r->virtual_size = src->virtual_size;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}