Cross Reference: /dovecot/src/lib-storage/index/maildir/maildir-mail.c
maildir-mail.c revision 2526d52441ef368215ab6bf04fd0356d3b09d235
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen/* Copyright (C) 2003 Timo Sirainen */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "istream.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "index-mail.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "maildir-storage.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "maildir-filename.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "maildir-uidlist.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include <stdlib.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include <fcntl.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include <unistd.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include <sys/stat.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic int
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainendo_open(struct maildir_mailbox *mbox, const char *path, int *fd)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen *fd = open(path, O_RDONLY);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (*fd != -1)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return 1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (errno == ENOENT)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return 0;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_storage_set_critical(&mbox->storage->storage,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen "open(%s) failed: %m", path);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return -1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic int
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainendo_stat(struct maildir_mailbox *mbox, const char *path, struct stat *st)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (stat(path, st) == 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return 1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (errno == ENOENT)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return 0;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_storage_set_critical(&mbox->storage->storage,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen "stat(%s) failed: %m", path);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return -1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic struct istream *
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenmaildir_open_mail(struct maildir_mailbox *mbox, struct mail *mail,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen bool *deleted_r)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const char *path;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen int fd = -1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen *deleted_r = FALSE;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (mail->uid != 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (maildir_file_do(mbox, mail->uid, do_open, &fd) < 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return NULL;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen } else {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen path = maildir_save_file_get_path(mail->transaction, mail->seq);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (do_open(mbox, path, &fd) <= 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return NULL;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (fd == -1) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen *deleted_r = TRUE;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return NULL;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return i_stream_create_fd(fd, MAIL_READ_BLOCK_SIZE, TRUE);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic int maildir_mail_stat(struct mail *mail, struct stat *st)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->box;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct index_mail_data *data = &((struct index_mail *)mail)->data;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const char *path;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen int fd;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (data->access_part != 0 && data->stream == NULL) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* we're going to open the mail anyway */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen (void)mail_get_stream(mail, NULL, NULL);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (data->stream != NULL) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fd = i_stream_get_fd(data->stream);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_assert(fd != -1);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (fstat(fd, st) < 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_storage_set_critical(&mbox->storage->storage,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen "fstat(maildir) failed: %m");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return -1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen } else if (mail->uid != 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (maildir_file_do(mbox, mail->uid, do_stat, st) <= 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return -1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen } else {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen path = maildir_save_file_get_path(mail->transaction, mail->seq);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (do_stat(mbox, path, st) <= 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return -1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return 0;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic time_t maildir_mail_get_received_date(struct mail *_mail)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct index_mail_data *data = &mail->data;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct stat st;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen uint32_t t;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen (void)index_mail_get_received_date(_mail);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (data->received_date != (time_t)-1)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return data->received_date;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (maildir_mail_stat(_mail, &st) < 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return (time_t)-1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen data->received_date = t = st.st_mtime;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen index_mail_cache_add(mail, MAIL_CACHE_RECEIVED_DATE, &t, sizeof(t));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return data->received_date;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic time_t maildir_mail_get_save_date(struct mail *_mail)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct index_mail_data *data = &mail->data;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct stat st;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen uint32_t t;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen (void)index_mail_get_save_date(_mail);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (data->save_date != (time_t)-1)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return data->save_date;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (maildir_mail_stat(_mail, &st) < 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return (time_t)-1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen data->save_date = t = st.st_ctime;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen index_mail_cache_add(mail, MAIL_CACHE_SAVE_DATE, &t, sizeof(t));
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return data->save_date;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic bool
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenmaildir_mail_get_fname(struct maildir_mailbox *mbox, struct mail *mail,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const char **fname_r)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen enum maildir_uidlist_rec_flag flags;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen *fname_r = maildir_uidlist_lookup(mbox->uidlist, mail->uid, &flags);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (*fname_r == NULL) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_set_expunged(mail);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return FALSE;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return TRUE;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic int maildir_get_pop3_state(struct index_mail *mail)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const struct mail_cache_field *fields;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen unsigned int i, count, vsize_idx;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen enum mail_cache_decision_type dec, vsize_dec;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen enum mail_fetch_field allowed_pop3_fields;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen bool not_pop3_only = FALSE;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (mail->pop3_state_set)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return mail->pop3_state;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* if this mail itself has non-pop3 fields we know we're not
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen pop3-only */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen allowed_pop3_fields = MAIL_FETCH_FLAGS | MAIL_FETCH_STREAM_HEADER |
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen MAIL_FETCH_STREAM_BODY | MAIL_FETCH_UIDL_FILE_NAME |
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen MAIL_FETCH_VIRTUAL_SIZE;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (mail->wanted_headers != NULL ||
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen (mail->wanted_fields & allowed_pop3_fields) == 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen not_pop3_only = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* get vsize decision */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen vsize_idx = mail->ibox->cache_fields[MAIL_CACHE_VIRTUAL_FULL_SIZE].idx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (not_pop3_only) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen vsize_dec = mail_cache_field_get_decision(mail->ibox->cache,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen vsize_idx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen vsize_dec &= ~MAIL_CACHE_DECISION_FORCED;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* also check if there are any non-vsize cached fields */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen vsize_dec = MAIL_CACHE_DECISION_NO;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen fields = mail_cache_register_get_list(mail->ibox->cache,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool_datastack_create(),
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < count; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen dec = fields[i].decision & ~MAIL_CACHE_DECISION_FORCED;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (fields[i].idx == vsize_idx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen vsize_dec = dec;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else if (dec != MAIL_CACHE_DECISION_NO)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen not_pop3_only = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen if (!not_pop3_only) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* either nothing is cached, or only vsize is cached. */
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen mail->pop3_state = 1;
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen } else if (vsize_dec != MAIL_CACHE_DECISION_YES) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* if virtual size isn't cached permanently,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen POP3 isn't being used */
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen mail->pop3_state = -1;
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen } else {
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen /* possibly a mixed pop3/imap */
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen mail->pop3_state = 0;
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen }
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen mail->pop3_state_set = TRUE;
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen return mail->pop3_state;
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen}
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainenstatic uoff_t maildir_mail_get_virtual_size(struct mail *_mail)
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct index_mail_data *data = &mail->data;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct message_size hdr_size, body_size;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const char *path, *fname, *value;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uoff_t old_offset;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen int pop3_state;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (index_mail_get_cached_virtual_size(mail) != (uoff_t)-1)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return data->virtual_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (_mail->uid != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!maildir_mail_get_fname(mbox, _mail, &fname))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return (uoff_t)-1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen path = maildir_save_file_get_path(_mail->transaction,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen _mail->seq);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fname = strrchr(path, '/');
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen fname = fname != NULL ? fname + 1 : path;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* size can be included in filename */
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen if (maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &data->virtual_size))
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen return data->virtual_size;
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen /* size can be included in uidlist entry */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (_mail->uid != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen value = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen MAILDIR_UIDLIST_REC_EXT_VSIZE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (value != NULL) {
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen char *p;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen data->virtual_size = strtoull(value, &p, 10);
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen if (*p == '\0')
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return data->virtual_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* fallback to reading the file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen if (mail_get_stream(_mail, &hdr_size, &body_size) == NULL)
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen return (uoff_t)-1;
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen i_stream_seek(data->stream, old_offset);
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen i_assert(data->virtual_size != (uoff_t)-1);
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen /* 1 = pop3-only, 0 = mixed, -1 = no pop3 */
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen pop3_state = maildir_get_pop3_state(mail);
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen if (pop3_state <= 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_cache_add(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &data->virtual_size,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sizeof(data->virtual_size));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (pop3_state >= 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* if virtual size is wanted permanently, store it to uidlist
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen so that in case cache file gets lost we can get it quickly */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen maildir_uidlist_set_ext(mbox->uidlist, _mail->uid,
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen MAILDIR_UIDLIST_REC_EXT_VSIZE,
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen dec2str(data->virtual_size));
659fe5d24825b160cae512538088020d97a60239Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return data->virtual_size;
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic const char *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmaildir_mail_get_special(struct mail *_mail, enum mail_fetch_field field)
659fe5d24825b160cae512538088020d97a60239Timo Sirainen{
659fe5d24825b160cae512538088020d97a60239Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen const char *path, *fname, *end;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainen if (field == MAIL_FETCH_UIDL_FILE_NAME) {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen if (_mail->uid != 0) {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen if (!maildir_mail_get_fname(mbox, _mail, &fname))
659fe5d24825b160cae512538088020d97a60239Timo Sirainen return NULL;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen } else {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen path = maildir_save_file_get_path(_mail->transaction,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen _mail->seq);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fname = strrchr(path, '/');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fname = fname != NULL ? fname + 1 : path;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen end = strchr(fname, MAILDIR_INFO_SEP);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return end == NULL ? fname : t_strdup_until(fname, end);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainen return index_mail_get_special(_mail, field);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen}
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainenstatic uoff_t maildir_mail_get_physical_size(struct mail *_mail)
659fe5d24825b160cae512538088020d97a60239Timo Sirainen{
659fe5d24825b160cae512538088020d97a60239Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen struct index_mail_data *data = &mail->data;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen struct stat st;
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen const char *path, *fname;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uoff_t size;
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen size = index_mail_get_physical_size(_mail);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (size != (uoff_t)-1)
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen return size;
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen if (_mail->uid != 0) {
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen if (!maildir_mail_get_fname(mbox, _mail, &fname))
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen return (uoff_t)-1;
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen path = NULL;
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen } else {
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen path = maildir_save_file_get_path(_mail->transaction,
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen _mail->seq);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fname = strrchr(path, '/');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fname = fname != NULL ? fname + 1 : path;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* size can be included in filename */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!maildir_filename_get_size(fname, MAILDIR_EXTRA_FILE_SIZE, &size)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (_mail->uid != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (maildir_file_do(mbox, _mail->uid,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen do_stat, &st) <= 0)
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen return (uoff_t)-1;
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen } else {
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen /* saved mail which hasn't been committed yet */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (do_stat(mbox, path, &st) <= 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return (uoff_t)-1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen size = st.st_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen index_mail_cache_add(mail, MAIL_CACHE_PHYSICAL_FULL_SIZE,
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen &size, sizeof(size));
65d6ca3fb5450b81df0190d9e9aa62c00fed5116Timo Sirainen data->physical_size = size;
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen return size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
757726d9acbd04cf0d0d4be8ce14e11525476a0bTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic struct istream *maildir_mail_get_stream(struct mail *_mail,
7c95b03620a03a43dd72d39608cea5fc77393ad6Timo Sirainen struct message_size *hdr_size,
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen struct message_size *body_size)
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen{
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct index_mail_data *data = &mail->data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen bool deleted;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (data->stream == NULL) {
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen data->stream = maildir_open_mail(mbox, _mail, &deleted);
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen if (data->stream == NULL) {
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen if (deleted)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_set_expunged(_mail);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
65d6ca3fb5450b81df0190d9e9aa62c00fed5116Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return index_mail_init_stream(mail, hdr_size, body_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_vfuncs maildir_mail_vfuncs = {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_free,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_set_seq,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_set_uid,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_get_flags,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_get_keywords,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_get_parts,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_get_date,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen maildir_mail_get_received_date,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen maildir_mail_get_save_date,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen maildir_mail_get_virtual_size,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen maildir_mail_get_physical_size,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_get_first_header,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_get_headers,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_get_header_stream,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen maildir_mail_get_stream,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen maildir_mail_get_special,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_update_flags,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_update_keywords,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mail_expunge
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen};
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen