1 /* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
2
3 #include "lib.h"
4 #include "array.h"
5 #include "hex-binary.h"
6 #include "md5.h"
7 #include "istream.h"
8 #include "istream-crlf.h"
9 #include "message-header-hash.h"
10 #include "message-size.h"
11 #include "mail-storage.h"
12 #include "dsync-mail.h"
13
14 struct mailbox_header_lookup_ctx *
dsync_mail_get_hash_headers(struct mailbox * box,const char * const * hashed_headers)15 dsync_mail_get_hash_headers(struct mailbox *box, const char *const *hashed_headers)
16 {
17 return mailbox_header_lookup_init(box, hashed_headers);
18 }
19
dsync_mail_get_hdr_hash(struct mail * mail,unsigned int version,const char * const * hashed_headers,const char ** hdr_hash_r)20 int dsync_mail_get_hdr_hash(struct mail *mail, unsigned int version,
21 const char *const *hashed_headers, const char **hdr_hash_r)
22 {
23 struct istream *hdr_input, *input;
24 struct mailbox_header_lookup_ctx *hdr_ctx;
25 struct message_header_hash_context hash_ctx;
26 struct md5_context md5_ctx;
27 unsigned char md5_result[MD5_RESULTLEN];
28 const unsigned char *data;
29 size_t size;
30 ssize_t sret;
31 int ret = 0;
32
33 hdr_ctx = mailbox_header_lookup_init(mail->box, hashed_headers);
34 ret = mail_get_header_stream(mail, hdr_ctx, &hdr_input);
35 mailbox_header_lookup_unref(&hdr_ctx);
36 if (ret < 0)
37 return -1;
38
39 input = i_stream_create_lf(hdr_input);
40
41 md5_init(&md5_ctx);
42 i_zero(&hash_ctx);
43 while ((sret = i_stream_read_more(input, &data, &size)) > 0) {
44 message_header_hash_more(&hash_ctx, &hash_method_md5, &md5_ctx,
45 version, data, size);
46 i_stream_skip(input, size);
47 }
48 i_assert(sret == -1);
49 if (input->stream_errno != 0)
50 ret = -1;
51 i_stream_unref(&input);
52
53 md5_final(&md5_ctx, md5_result);
54 *hdr_hash_r = binary_to_hex(md5_result, sizeof(md5_result));
55 return ret;
56 }
57
dsync_mail_fill(struct mail * mail,bool minimal_fill,struct dsync_mail * dmail_r,const char ** error_field_r)58 int dsync_mail_fill(struct mail *mail, bool minimal_fill,
59 struct dsync_mail *dmail_r, const char **error_field_r)
60 {
61 const char *guid;
62
63 i_zero(dmail_r);
64
65 if (mail_get_special(mail, MAIL_FETCH_GUID, &guid) < 0) {
66 *error_field_r = "GUID";
67 return -1;
68 }
69 dmail_r->guid = guid;
70 dmail_r->uid = mail->uid;
71
72 dmail_r->input_mail = mail;
73 dmail_r->input_mail_uid = mail->uid;
74
75 if (mail_get_save_date(mail, &dmail_r->saved_date) < 0) {
76 *error_field_r = "saved-date";
77 return -1;
78 }
79 if (!minimal_fill)
80 return dsync_mail_fill_nonminimal(mail, dmail_r, error_field_r);
81 dmail_r->minimal_fields = TRUE;
82 return 0;
83 }
84
dsync_mail_fill_nonminimal(struct mail * mail,struct dsync_mail * dmail_r,const char ** error_field_r)85 int dsync_mail_fill_nonminimal(struct mail *mail, struct dsync_mail *dmail_r,
86 const char **error_field_r)
87 {
88 const char *str;
89
90 if (mail_get_stream(mail, NULL, NULL, &dmail_r->input) < 0) {
91 *error_field_r = "body";
92 return -1;
93 }
94
95 if (mail_get_special(mail, MAIL_FETCH_UIDL_BACKEND, &dmail_r->pop3_uidl) < 0) {
96 *error_field_r = "pop3-uidl";
97 return -1;
98 }
99 if (mail_get_special(mail, MAIL_FETCH_POP3_ORDER, &str) < 0) {
100 *error_field_r = "pop3-order";
101 return -1;
102 }
103 if (*str != '\0') {
104 if (str_to_uint32(str, &dmail_r->pop3_order) < 0)
105 i_unreached();
106 }
107 if (mail_get_received_date(mail, &dmail_r->received_date) < 0) {
108 *error_field_r = "received-date";
109 return -1;
110 }
111 return 0;
112 }
113
114 static void
const_string_array_dup(pool_t pool,const ARRAY_TYPE (const_string)* src,ARRAY_TYPE (const_string)* dest)115 const_string_array_dup(pool_t pool, const ARRAY_TYPE(const_string) *src,
116 ARRAY_TYPE(const_string) *dest)
117 {
118 const char *const *strings, *str;
119 unsigned int i, count;
120
121 if (!array_is_created(src))
122 return;
123
124 strings = array_get(src, &count);
125 if (count == 0)
126 return;
127
128 p_array_init(dest, pool, count);
129 for (i = 0; i < count; i++) {
130 str = p_strdup(pool, strings[i]);
131 array_push_back(dest, &str);
132 }
133 }
134
dsync_mail_change_dup(pool_t pool,const struct dsync_mail_change * src,struct dsync_mail_change * dest_r)135 void dsync_mail_change_dup(pool_t pool, const struct dsync_mail_change *src,
136 struct dsync_mail_change *dest_r)
137 {
138 dest_r->type = src->type;
139 dest_r->uid = src->uid;
140 if (src->guid != NULL) {
141 dest_r->guid = *src->guid == '\0' ? "" :
142 p_strdup(pool, src->guid);
143 }
144 dest_r->hdr_hash = p_strdup(pool, src->hdr_hash);
145 dest_r->modseq = src->modseq;
146 dest_r->pvt_modseq = src->pvt_modseq;
147
148 dest_r->add_flags = src->add_flags;
149 dest_r->remove_flags = src->remove_flags;
150 dest_r->final_flags = src->final_flags;
151 dest_r->keywords_reset = src->keywords_reset;
152 const_string_array_dup(pool, &src->keyword_changes,
153 &dest_r->keyword_changes);
154 dest_r->received_timestamp = src->received_timestamp;
155 dest_r->virtual_size = src->virtual_size;
156 }
157