Lines 25-30
Link Here
|
25 |
#include "mutt.h" |
25 |
#include "mutt.h" |
26 |
#include "mutt_curses.h" |
26 |
#include "mutt_curses.h" |
27 |
#include "imap_private.h" |
27 |
#include "imap_private.h" |
|
|
28 |
#include "imap_headercache.h" |
28 |
#include "message.h" |
29 |
#include "message.h" |
29 |
#include "mx.h" |
30 |
#include "mx.h" |
30 |
|
31 |
|
Lines 54-62
Link Here
|
54 |
int msgno; |
55 |
int msgno; |
55 |
IMAP_HEADER h; |
56 |
IMAP_HEADER h; |
56 |
int rc, mfhrc, oldmsgcount; |
57 |
int rc, mfhrc, oldmsgcount; |
|
|
58 |
IMAP_HEADERCACHE *hc = NULL; |
59 |
int msgbegin_hc; |
57 |
int fetchlast = 0; |
60 |
int fetchlast = 0; |
|
|
61 |
|
58 |
const char *want_headers = "DATE FROM SUBJECT TO CC MESSAGE-ID REFERENCES CONTENT-TYPE IN-REPLY-TO REPLY-TO LINES X-LABEL"; |
62 |
const char *want_headers = "DATE FROM SUBJECT TO CC MESSAGE-ID REFERENCES CONTENT-TYPE IN-REPLY-TO REPLY-TO LINES X-LABEL"; |
59 |
|
63 |
|
|
|
64 |
msgno = msgbegin; |
65 |
|
60 |
ctx = idata->ctx; |
66 |
ctx = idata->ctx; |
61 |
|
67 |
|
62 |
if (mutt_bit_isset (idata->capabilities,IMAP4REV1)) |
68 |
if (mutt_bit_isset (idata->capabilities,IMAP4REV1)) |
Lines 87-122
Link Here
|
87 |
} |
93 |
} |
88 |
unlink (tempfile); |
94 |
unlink (tempfile); |
89 |
|
95 |
|
|
|
96 |
oldmsgcount = ctx->msgcount; |
97 |
|
98 |
msgbegin_hc = msgbegin; |
99 |
|
100 |
hc = idata->hcache; |
101 |
|
102 |
restart: |
90 |
/* make sure context has room to hold the mailbox */ |
103 |
/* make sure context has room to hold the mailbox */ |
91 |
while ((msgend) >= idata->ctx->hdrmax) |
104 |
while ((msgend) >= idata->ctx->hdrmax) |
92 |
mx_alloc_memory (idata->ctx); |
105 |
mx_alloc_memory (idata->ctx); |
93 |
|
106 |
|
94 |
oldmsgcount = ctx->msgcount; |
|
|
95 |
idata->reopen &= ~IMAP_NEWMAIL_PENDING; |
107 |
idata->reopen &= ~IMAP_NEWMAIL_PENDING; |
96 |
idata->newMailCount = 0; |
108 |
idata->newMailCount = 0; |
97 |
|
109 |
|
|
|
110 |
if (hc) |
111 |
{ |
112 |
snprintf(buf, sizeof(buf), "FETCH %d:%d (UID)", msgbegin_hc + 1, |
113 |
msgend + 1); |
114 |
imap_cmd_start(idata, buf); |
115 |
|
116 |
for (msgno = msgbegin_hc; msgno <= msgend; msgno++) |
117 |
{ |
118 |
if (ReadInc && (!msgno || ((msgno+1) % ReadInc == 0))) |
119 |
mutt_message (_("Fetching message UIDs... [%d/%d]"), msgno + 1, |
120 |
msgend + 1); |
121 |
|
122 |
/* XXX */ |
123 |
ctx->hdrs[msgno] = NULL; |
124 |
|
125 |
/* XXX leaking h.data on successful exit */ |
126 |
memset (&h, 0, sizeof (h)); |
127 |
h.data = safe_calloc (1, sizeof (IMAP_HEADER_DATA)); |
128 |
|
129 |
do |
130 |
{ |
131 |
FILE *cache_fp; |
132 |
|
133 |
mfhrc = 0; |
134 |
|
135 |
rc = imap_cmd_step (idata); |
136 |
if (rc != IMAP_CMD_CONTINUE) |
137 |
break; |
138 |
|
139 |
if ((mfhrc = msg_fetch_header (idata->ctx, &h, idata->cmd.buf, NULL)) == -1) |
140 |
continue; |
141 |
else if (mfhrc < 0) |
142 |
break; |
143 |
|
144 |
cache_fp = imap_headercache_find(hc, &h); |
145 |
if (cache_fp) |
146 |
{ |
147 |
/* update context with message header */ |
148 |
ctx->hdrs[msgno] = mutt_new_header (); |
149 |
|
150 |
ctx->hdrs[msgno]->index = h.sid - 1; |
151 |
|
152 |
/* messages which have not been expunged are ACTIVE (borrowed from mh |
153 |
* folders) */ |
154 |
ctx->hdrs[msgno]->active = 1; |
155 |
ctx->hdrs[msgno]->read = h.read; |
156 |
ctx->hdrs[msgno]->old = h.old; |
157 |
ctx->hdrs[msgno]->deleted = h.deleted; |
158 |
ctx->hdrs[msgno]->flagged = h.flagged; |
159 |
ctx->hdrs[msgno]->replied = h.replied; |
160 |
ctx->hdrs[msgno]->changed = h.changed; |
161 |
ctx->hdrs[msgno]->received = h.received; |
162 |
ctx->hdrs[msgno]->data = (void *) (h.data); |
163 |
|
164 |
/* NOTE: if Date: header is missing, mutt_read_rfc822_header depends |
165 |
* on h.received being set */ |
166 |
ctx->hdrs[msgno]->env = mutt_read_rfc822_header (cache_fp, ctx->hdrs[msgno], |
167 |
0, 0); |
168 |
/* content built as a side-effect of mutt_read_rfc822_header */ |
169 |
ctx->hdrs[msgno]->content->length = h.content_length; |
170 |
|
171 |
imap_headercache_done(hc, cache_fp); |
172 |
} |
173 |
} |
174 |
while (mfhrc == -1); |
175 |
|
176 |
/* in case we get new mail while fetching the headers */ |
177 |
if (idata->reopen & IMAP_NEWMAIL_PENDING) |
178 |
{ |
179 |
msgbegin_hc = msgno + 1; |
180 |
msgend = idata->newMailCount - 1; |
181 |
goto restart; |
182 |
} |
183 |
/* XXX freshen... etc */ |
184 |
} |
185 |
} |
186 |
|
187 |
/* Remember where we left if we get new mail while fetching actual headers */ |
188 |
msgbegin_hc = msgno; |
189 |
|
190 |
/* Now, either one of the following is true: |
191 |
* 1. We don't have a headercache (hc == 0) |
192 |
* 2. All messages found in the cache have ctx->hdrs[msgno] != NULL, and |
193 |
* filled up. |
194 |
*/ |
195 |
|
196 |
/* |
197 |
* Make one request for everything. This makes fetching headers an |
198 |
* order of magnitude faster if you have a large mailbox. |
199 |
* |
200 |
* If we get more messages while doing this, we make another |
201 |
* request for all the new messages. |
202 |
*/ |
203 |
if (!hc) |
204 |
{ |
205 |
snprintf (buf, sizeof (buf), |
206 |
"FETCH %d:%d (UID FLAGS INTERNALDATE RFC822.SIZE %s)", msgbegin + 1, |
207 |
msgend + 1, hdrreq); |
208 |
|
209 |
imap_cmd_start (idata, buf); |
210 |
} |
211 |
|
98 |
for (msgno = msgbegin; msgno <= msgend ; msgno++) |
212 |
for (msgno = msgbegin; msgno <= msgend ; msgno++) |
99 |
{ |
213 |
{ |
100 |
if (ReadInc && (!msgno || ((msgno+1) % ReadInc == 0))) |
214 |
if (ReadInc && (!msgno || ((msgno+1) % ReadInc == 0))) |
101 |
mutt_message (_("Fetching message headers... [%d/%d]"), msgno + 1, |
215 |
mutt_message (_("Fetching message headers... [%d/%d]"), msgno + 1, |
102 |
msgend + 1); |
216 |
msgend + 1); |
103 |
|
217 |
|
104 |
if (msgno + 1 > fetchlast) |
218 |
/* If the message is in the cache, skip it */ |
|
|
219 |
if (hc) |
105 |
{ |
220 |
{ |
106 |
/* |
221 |
if (ctx->hdrs[msgno]) |
107 |
* Make one request for everything. This makes fetching headers an |
222 |
{ |
108 |
* order of magnitude faster if you have a large mailbox. |
223 |
ctx->msgcount++; |
109 |
* |
224 |
continue; |
110 |
* If we get more messages while doing this, we make another |
225 |
} |
111 |
* request for all the new messages. |
226 |
else if (msgno >= fetchlast) |
112 |
*/ |
227 |
{ |
113 |
snprintf (buf, sizeof (buf), |
228 |
/* Find the longest "run" of messages not in the cache and fetch it in |
114 |
"FETCH %d:%d (UID FLAGS INTERNALDATE RFC822.SIZE %s)", msgno + 1, |
229 |
* one go |
115 |
msgend + 1, hdrreq); |
230 |
*/ |
116 |
|
231 |
for (fetchlast = msgno + 1; |
117 |
imap_cmd_start (idata, buf); |
232 |
fetchlast <= msgend && !ctx->hdrs[fetchlast]; fetchlast++); |
|
|
233 |
|
234 |
snprintf (buf, sizeof (buf), |
235 |
"FETCH %d:%d (UID FLAGS INTERNALDATE RFC822.SIZE %s)", msgno + 1, |
236 |
fetchlast, hdrreq); |
118 |
|
237 |
|
119 |
fetchlast = msgend + 1; |
238 |
imap_cmd_start (idata, buf); |
|
|
239 |
} |
120 |
} |
240 |
} |
121 |
|
241 |
|
122 |
/* freshen fp, h */ |
242 |
/* freshen fp, h */ |
Lines 130-135
Link Here
|
130 |
*/ |
250 |
*/ |
131 |
do |
251 |
do |
132 |
{ |
252 |
{ |
|
|
253 |
size_t hdrsz; |
254 |
|
133 |
mfhrc = 0; |
255 |
mfhrc = 0; |
134 |
|
256 |
|
135 |
rc = imap_cmd_step (idata); |
257 |
rc = imap_cmd_step (idata); |
Lines 144-155
Link Here
|
144 |
/* make sure we don't get remnants from older larger message headers */ |
266 |
/* make sure we don't get remnants from older larger message headers */ |
145 |
fputs ("\n\n", fp); |
267 |
fputs ("\n\n", fp); |
146 |
|
268 |
|
|
|
269 |
hdrsz = (size_t)ftell(fp); |
270 |
|
147 |
/* update context with message header */ |
271 |
/* update context with message header */ |
148 |
ctx->hdrs[msgno] = mutt_new_header (); |
272 |
ctx->hdrs[msgno] = mutt_new_header (); |
149 |
|
273 |
|
150 |
ctx->hdrs[msgno]->index = h.sid - 1; |
274 |
ctx->hdrs[msgno]->index = h.sid - 1; |
|
|
275 |
#if 0 |
151 |
if (h.sid != ctx->msgcount + 1) |
276 |
if (h.sid != ctx->msgcount + 1) |
152 |
dprint (1, (debugfile, "imap_read_headers: msgcount and sequence ID are inconsistent!")); |
277 |
dprint (1, (debugfile, "imap_read_headers: msgcount and sequence ID are inconsistent!")); |
|
|
278 |
#endif |
153 |
/* messages which have not been expunged are ACTIVE (borrowed from mh |
279 |
/* messages which have not been expunged are ACTIVE (borrowed from mh |
154 |
* folders) */ |
280 |
* folders) */ |
155 |
ctx->hdrs[msgno]->active = 1; |
281 |
ctx->hdrs[msgno]->active = 1; |
Lines 163-168
Link Here
|
163 |
ctx->hdrs[msgno]->data = (void *) (h.data); |
289 |
ctx->hdrs[msgno]->data = (void *) (h.data); |
164 |
|
290 |
|
165 |
rewind (fp); |
291 |
rewind (fp); |
|
|
292 |
|
293 |
if (hc) |
294 |
{ |
295 |
imap_headercache_add(hc, &h, fp, hdrsz); |
296 |
rewind(fp); |
297 |
} |
298 |
|
166 |
/* NOTE: if Date: header is missing, mutt_read_rfc822_header depends |
299 |
/* NOTE: if Date: header is missing, mutt_read_rfc822_header depends |
167 |
* on h.received being set */ |
300 |
* on h.received being set */ |
168 |
ctx->hdrs[msgno]->env = mutt_read_rfc822_header (fp, ctx->hdrs[msgno], |
301 |
ctx->hdrs[msgno]->env = mutt_read_rfc822_header (fp, ctx->hdrs[msgno], |
Lines 172-179
Link Here
|
172 |
|
305 |
|
173 |
ctx->msgcount++; |
306 |
ctx->msgcount++; |
174 |
} |
307 |
} |
175 |
while ((rc != IMAP_CMD_OK) && ((mfhrc == -1) || |
308 |
while (mfhrc == -1); |
176 |
((msgno + 1) >= fetchlast))); |
|
|
177 |
|
309 |
|
178 |
if ((mfhrc < -1) || ((rc != IMAP_CMD_CONTINUE) && (rc != IMAP_CMD_OK))) |
310 |
if ((mfhrc < -1) || ((rc != IMAP_CMD_CONTINUE) && (rc != IMAP_CMD_OK))) |
179 |
{ |
311 |
{ |
Lines 186-196
Link Here
|
186 |
/* in case we get new mail while fetching the headers */ |
318 |
/* in case we get new mail while fetching the headers */ |
187 |
if (idata->reopen & IMAP_NEWMAIL_PENDING) |
319 |
if (idata->reopen & IMAP_NEWMAIL_PENDING) |
188 |
{ |
320 |
{ |
|
|
321 |
msgbegin = msgno + 1; |
189 |
msgend = idata->newMailCount - 1; |
322 |
msgend = idata->newMailCount - 1; |
190 |
while ((msgend) >= ctx->hdrmax) |
323 |
goto restart; |
191 |
mx_alloc_memory (ctx); |
|
|
192 |
idata->reopen &= ~IMAP_NEWMAIL_PENDING; |
193 |
idata->newMailCount = 0; |
194 |
} |
324 |
} |
195 |
} |
325 |
} |
196 |
|
326 |
|
Lines 731-736
Link Here
|
731 |
IMAP_DATA* idata; |
861 |
IMAP_DATA* idata; |
732 |
long bytes; |
862 |
long bytes; |
733 |
int rc = -1; /* default now is that string isn't FETCH response*/ |
863 |
int rc = -1; /* default now is that string isn't FETCH response*/ |
|
|
864 |
int fetch_rc; |
734 |
|
865 |
|
735 |
idata = (IMAP_DATA*) ctx->data; |
866 |
idata = (IMAP_DATA*) ctx->data; |
736 |
|
867 |
|
Lines 753-761
Link Here
|
753 |
|
884 |
|
754 |
/* FIXME: current implementation - call msg_parse_fetch - if it returns -2, |
885 |
/* FIXME: current implementation - call msg_parse_fetch - if it returns -2, |
755 |
* read header lines and call it again. Silly. */ |
886 |
* read header lines and call it again. Silly. */ |
756 |
if (msg_parse_fetch (h, buf) != -2) |
887 |
fetch_rc = msg_parse_fetch(h, buf); |
|
|
888 |
if (fetch_rc == 0) |
889 |
return 0; |
890 |
else if (fetch_rc != -2) |
757 |
return rc; |
891 |
return rc; |
758 |
|
892 |
|
|
|
893 |
if (!fp) |
894 |
return -2; |
895 |
|
759 |
if (imap_get_literal_count (buf, &bytes) < 0) |
896 |
if (imap_get_literal_count (buf, &bytes) < 0) |
760 |
return rc; |
897 |
return rc; |
761 |
imap_read_literal (fp, idata, bytes); |
898 |
imap_read_literal (fp, idata, bytes); |