attachment.c: Typo should be "Content-Disposition"
header.c mbx_mboxscan.c mbx_mbox.c : an other attempt for speed when parsing, the most common use headers (From, To, Date, CC,..) are save in the structure, so when retrieve them it will be faster. Downside the tight parsing loop is not so thight and is frankly ugly. More memory is being use per messages. It is hard to guess at this stage the memory patterns and where to optimise, probably my last attempt at this before the code become truly unmaintable. mbx_imap.c mailbox.c : I did not understand the difference between "recent" and "unseen" english words. I think that "unseen" means new mail, an "recent" mail that was not read yet. So I had to rename some functions mailbox_recent_count() to mailbox_unseen_count(), but I maybe wrong ... sigh somebody with better english skill should explain this to me. mbx_pop.c include/header0.h include/mailbox0.h : Introduce header_set_fill() to let the mailboxes fill up a buffer that will contains the entire headers.
Showing
9 changed files
with
454 additions
and
123 deletions
1 | /* GNU mailutils - a suite of utilities for electronic mail | 1 | /* GNU mailutils - a suite of utilities for electronic mail |
2 | Copyright (C) 1999, 2000 Free Software Foundation, Inc. | 2 | Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. |
3 | 3 | ||
4 | This program is free software; you can redistribute it and/or modify | 4 | This program is free software; you can redistribute it and/or modify |
5 | it under the terms of the GNU General Library Public License as published by | 5 | it under the terms of the GNU General Library Public License as published by |
... | @@ -183,11 +183,11 @@ int message_attachment_filename(message_t msg, char **filename) | ... | @@ -183,11 +183,11 @@ int message_attachment_filename(message_t msg, char **filename) |
183 | 183 | ||
184 | if ( filename != NULL && ( ret = message_get_header(msg, &hdr) ) == 0 ) { | 184 | if ( filename != NULL && ( ret = message_get_header(msg, &hdr) ) == 0 ) { |
185 | *filename = NULL; | 185 | *filename = NULL; |
186 | header_get_value(hdr, "Content-Dispostion", NULL, 0, &size); | 186 | header_get_value(hdr, "Content-Disposition", NULL, 0, &size); |
187 | if ( size ) { | 187 | if ( size ) { |
188 | if ( ( pTmp = alloca(size+1) ) == NULL ) | 188 | if ( ( pTmp = alloca(size+1) ) == NULL ) |
189 | ret = ENOMEM; | 189 | ret = ENOMEM; |
190 | header_get_value(hdr, "Content-Dispostion", pTmp, size+1, 0); | 190 | header_get_value(hdr, "Content-Disposition", pTmp, size+1, 0); |
191 | if ( strstr( pTmp, "attachment" ) != NULL ) | 191 | if ( strstr( pTmp, "attachment" ) != NULL ) |
192 | fname = _header_get_param(pTmp, "filename", &size); | 192 | fname = _header_get_param(pTmp, "filename", &size); |
193 | } | 193 | } | ... | ... |
... | @@ -64,11 +64,21 @@ header_destroy (header_t *ph, void *owner) | ... | @@ -64,11 +64,21 @@ header_destroy (header_t *ph, void *owner) |
64 | /* Can we destroy ?. */ | 64 | /* Can we destroy ?. */ |
65 | if (h->owner == owner) | 65 | if (h->owner == owner) |
66 | { | 66 | { |
67 | size_t i; | ||
67 | stream_destroy (&(h->stream), h); | 68 | stream_destroy (&(h->stream), h); |
68 | if (h->hdr) | 69 | if (h->hdr) |
69 | free (h->hdr); | 70 | free (h->hdr); |
70 | if (h->blurb) | 71 | if (h->blurb) |
71 | free (h->blurb); | 72 | free (h->blurb); |
73 | for (i = 0; i < h->fhdr_count; i++) | ||
74 | { | ||
75 | if (h->fhdr[i].fn) | ||
76 | free (h->fhdr[i].fn); | ||
77 | if (h->fhdr[i].fv) | ||
78 | free (h->fhdr[i].fv); | ||
79 | } | ||
80 | if (h->fhdr) | ||
81 | free (h->fhdr); | ||
72 | free (h); | 82 | free (h); |
73 | } | 83 | } |
74 | *ph = NULL; | 84 | *ph = NULL; |
... | @@ -87,13 +97,10 @@ header_is_modified (header_t header) | ... | @@ -87,13 +97,10 @@ header_is_modified (header_t header) |
87 | return (header) ? (header->flags & HEADER_MODIFIED) : 0; | 97 | return (header) ? (header->flags & HEADER_MODIFIED) : 0; |
88 | } | 98 | } |
89 | 99 | ||
90 | /* Parsing is done in a rather simple fashion. | 100 | /* Parsing is done in a rather simple fashion, meaning we just consider an |
91 | meaning we just consider an entry to be | 101 | entry to be a field-name an a field-value. So they maybe duplicate of |
92 | a field-name an a field-value. So they | 102 | field-name like "Received" they are just put in the array, see _get_value() |
93 | maybe duplicate of field-name like "Received" | 103 | on how to handle the case. in the case of error .i.e a bad header construct |
94 | they are just put in the array, see _get_value() | ||
95 | on how to handle the case. | ||
96 | in the case of error .i.e a bad header construct | ||
97 | we do a full stop and return what we have so far. */ | 104 | we do a full stop and return what we have so far. */ |
98 | static int | 105 | static int |
99 | header_parse (header_t header, const char *blurb, int len) | 106 | header_parse (header_t header, const char *blurb, int len) |
... | @@ -191,11 +198,11 @@ header_parse (header_t header, const char *blurb, int len) | ... | @@ -191,11 +198,11 @@ header_parse (header_t header, const char *blurb, int len) |
191 | free (header->hdr); | 198 | free (header->hdr); |
192 | return ENOMEM; | 199 | return ENOMEM; |
193 | } | 200 | } |
201 | hdr[header->hdr_count].fn = fn; | ||
202 | hdr[header->hdr_count].fn_end = fn_end; | ||
203 | hdr[header->hdr_count].fv = fv; | ||
204 | hdr[header->hdr_count].fv_end = fv_end; | ||
194 | header->hdr = hdr; | 205 | header->hdr = hdr; |
195 | header->hdr[header->hdr_count].fn = fn; | ||
196 | header->hdr[header->hdr_count].fn_end = fn_end; | ||
197 | header->hdr[header->hdr_count].fv = fv; | ||
198 | header->hdr[header->hdr_count].fv_end = fv_end; | ||
199 | header->hdr_count++; | 206 | header->hdr_count++; |
200 | } /* for (header_start ...) */ | 207 | } /* for (header_start ...) */ |
201 | 208 | ||
... | @@ -218,7 +225,7 @@ header_set_value (header_t header, const char *fn, const char *fv, int replace) | ... | @@ -218,7 +225,7 @@ header_set_value (header_t header, const char *fn, const char *fv, int replace) |
218 | return header->_set_value (header, fn, fv, replace); | 225 | return header->_set_value (header, fn, fv, replace); |
219 | 226 | ||
220 | /* Try to fill out the buffer, if we know how. */ | 227 | /* Try to fill out the buffer, if we know how. */ |
221 | if (header->blurb == NULL && header->_get_value == NULL) | 228 | if (header->blurb == NULL) |
222 | { | 229 | { |
223 | int err = fill_blurb (header); | 230 | int err = fill_blurb (header); |
224 | if (err != 0) | 231 | if (err != 0) |
... | @@ -310,6 +317,72 @@ header_set_value (header_t header, const char *fn, const char *fv, int replace) | ... | @@ -310,6 +317,72 @@ header_set_value (header_t header, const char *fn, const char *fv, int replace) |
310 | return 0; | 317 | return 0; |
311 | } | 318 | } |
312 | 319 | ||
320 | static int | ||
321 | header_set_fvalue (header_t header, const char *name, char *buffer) | ||
322 | { | ||
323 | struct _hdr *thdr; | ||
324 | thdr = realloc (header->fhdr, (header->fhdr_count + 1) * sizeof(*thdr)); | ||
325 | if (thdr) | ||
326 | { | ||
327 | size_t len = strlen (name); | ||
328 | char *field = malloc (len + 1); | ||
329 | if (field == NULL) | ||
330 | return ENOMEM; | ||
331 | memcpy (field, name, len); | ||
332 | field[len] = '\0'; | ||
333 | thdr[header->fhdr_count].fn = field; | ||
334 | thdr[header->fhdr_count].fn_end = field + len; | ||
335 | |||
336 | len = strlen (buffer); | ||
337 | field = malloc (len + 1); | ||
338 | if (field == NULL) | ||
339 | return ENOMEM; | ||
340 | memcpy (field, buffer, len); | ||
341 | field[len] = '\0'; | ||
342 | thdr[header->fhdr_count].fv = field; | ||
343 | thdr[header->fhdr_count].fv_end = field + len; | ||
344 | header->fhdr_count++; | ||
345 | header->fhdr = thdr; | ||
346 | return 0; | ||
347 | } | ||
348 | return ENOMEM; | ||
349 | } | ||
350 | |||
351 | static int | ||
352 | header_get_fvalue (header_t header, const char *name, char *buffer, | ||
353 | size_t buflen, size_t *pn) | ||
354 | { | ||
355 | size_t i, fn_len, fv_len = 0; | ||
356 | size_t name_len; | ||
357 | int err = ENOENT; | ||
358 | |||
359 | if (header->_get_fvalue) | ||
360 | return header->_get_fvalue (header, name, buffer, buflen, pn); | ||
361 | |||
362 | for (i = 0, name_len = strlen (name); i < header->fhdr_count; i++) | ||
363 | { | ||
364 | fn_len = header->fhdr[i].fn_end - header->fhdr[i].fn; | ||
365 | if (fn_len == name_len | ||
366 | && strcasecmp (header->fhdr[i].fn, name) == 0) | ||
367 | { | ||
368 | fv_len = header->fhdr[i].fv_end - header->fhdr[i].fv; | ||
369 | if (buffer && buflen > 0) | ||
370 | { | ||
371 | buflen--; | ||
372 | fv_len = (fv_len < buflen) ? fv_len : buflen; | ||
373 | memcpy (buffer, header->fhdr[i].fv, fv_len); | ||
374 | buffer[fv_len] = '\0'; | ||
375 | } | ||
376 | err = 0; | ||
377 | break; | ||
378 | } | ||
379 | } | ||
380 | if (pn) | ||
381 | *pn = fv_len; | ||
382 | return err; | ||
383 | |||
384 | } | ||
385 | |||
313 | int | 386 | int |
314 | header_get_value (header_t header, const char *name, char *buffer, | 387 | header_get_value (header_t header, const char *name, char *buffer, |
315 | size_t buflen, size_t *pn) | 388 | size_t buflen, size_t *pn) |
... | @@ -323,11 +396,35 @@ header_get_value (header_t header, const char *name, char *buffer, | ... | @@ -323,11 +396,35 @@ header_get_value (header_t header, const char *name, char *buffer, |
323 | if (header == NULL || name == NULL) | 396 | if (header == NULL || name == NULL) |
324 | return EINVAL; | 397 | return EINVAL; |
325 | 398 | ||
399 | /* First Try the Fast header for hits. */ | ||
400 | err = header_get_fvalue (header, name, buffer, buflen, pn); | ||
401 | if (err == 0) | ||
402 | return 0; | ||
403 | |||
326 | if (header->_get_value) | 404 | if (header->_get_value) |
327 | return header->_get_value (header, name, buffer, buflen, pn); | 405 | { |
406 | char buf[1024]; /* should suffice for field-value. */ | ||
407 | size_t len = 0; | ||
408 | err = header->_get_value (header, name, buf, sizeof (buf), &len); | ||
409 | if (err == 0) | ||
410 | { | ||
411 | /* Save in the fast header buffer. */ | ||
412 | header_set_fvalue (header, name, buf); | ||
413 | if (buffer && buflen > 0) | ||
414 | { | ||
415 | buflen--; | ||
416 | buflen = (len < buflen) ? len : buflen; | ||
417 | memcpy (buffer, buf, buflen); | ||
418 | buffer[buflen] = '\0'; | ||
419 | if (pn) | ||
420 | *pn = buflen; | ||
421 | } | ||
422 | } | ||
423 | return err; | ||
424 | } | ||
328 | 425 | ||
329 | /* Try to fill out the buffer, if we know how. */ | 426 | /* Try to fill out the buffer, if we know how. */ |
330 | if (header->blurb == NULL && header->_get_value == NULL) | 427 | if (header->blurb == NULL) |
331 | { | 428 | { |
332 | err = fill_blurb (header); | 429 | err = fill_blurb (header); |
333 | if (err != 0) | 430 | if (err != 0) |
... | @@ -378,16 +475,6 @@ header_get_value (header_t header, const char *name, char *buffer, | ... | @@ -378,16 +475,6 @@ header_get_value (header_t header, const char *name, char *buffer, |
378 | if (total == 0) | 475 | if (total == 0) |
379 | { | 476 | { |
380 | err = ENOENT; | 477 | err = ENOENT; |
381 | #if 0 | ||
382 | /* No don't do this, the problem is we do not know if we have the | ||
383 | entire header value of part of it. */ | ||
384 | if (header->_get_value) | ||
385 | { | ||
386 | err = header->_get_value (header, name, buffer, buflen + 1, pn); | ||
387 | if (err == 0) | ||
388 | header_set_value (header, name, buffer, 0); | ||
389 | } | ||
390 | #endif | ||
391 | } | 478 | } |
392 | 479 | ||
393 | return err; | 480 | return err; |
... | @@ -471,8 +558,21 @@ header_size (header_t header, size_t *psize) | ... | @@ -471,8 +558,21 @@ header_size (header_t header, size_t *psize) |
471 | } | 558 | } |
472 | 559 | ||
473 | int | 560 | int |
561 | header_set_get_fvalue (header_t header, int (*_get_fvalue) | ||
562 | __P ((header_t, const char *, char *, size_t, size_t *)), | ||
563 | void *owner) | ||
564 | { | ||
565 | if (header == NULL) | ||
566 | return EINVAL; | ||
567 | if (header->owner != owner) | ||
568 | return EACCES; | ||
569 | header->_get_fvalue = _get_fvalue; | ||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | int | ||
474 | header_set_get_value (header_t header, int (*_get_value) | 574 | header_set_get_value (header_t header, int (*_get_value) |
475 | (header_t, const char *, char *, size_t, size_t *), | 575 | __P ((header_t, const char *, char *, size_t, size_t *)), |
476 | void *owner) | 576 | void *owner) |
477 | { | 577 | { |
478 | if (header == NULL) | 578 | if (header == NULL) |
... | @@ -527,18 +627,27 @@ fill_blurb (header_t header) | ... | @@ -527,18 +627,27 @@ fill_blurb (header_t header) |
527 | char buf[1024]; | 627 | char buf[1024]; |
528 | char *tbuf; | 628 | char *tbuf; |
529 | size_t nread = 0; | 629 | size_t nread = 0; |
630 | size_t i; | ||
530 | 631 | ||
531 | if (header->_fill == NULL && header->stream == NULL) | 632 | if (header->_fill == NULL) |
532 | return 0; | 633 | return 0; |
533 | 634 | ||
635 | /* Free any fast header, since we will load the entire headers. */ | ||
636 | for (i = 0; i < header->fhdr_count; i++) | ||
637 | { | ||
638 | if (header->fhdr[i].fn) | ||
639 | free (header->fhdr[i].fn); | ||
640 | if (header->fhdr[i].fv) | ||
641 | free (header->fhdr[i].fv); | ||
642 | } | ||
643 | if (header->fhdr) | ||
644 | free (header->fhdr); | ||
645 | header->_get_fvalue = NULL; | ||
646 | |||
534 | do | 647 | do |
535 | { | 648 | { |
536 | if (header->_fill) | 649 | status = header->_fill (header, buf, sizeof (buf), |
537 | status = header->_fill (header, buf, sizeof (buf), | 650 | header->temp_blurb_len, &nread) ; |
538 | header->temp_blurb_len, &nread) ; | ||
539 | else | ||
540 | status = stream_read (header->stream, buf, sizeof (buf), | ||
541 | header->temp_blurb_len, &nread); | ||
542 | if (status != 0) | 651 | if (status != 0) |
543 | { | 652 | { |
544 | if (status != EAGAIN && status != EINTR) | 653 | if (status != EAGAIN && status != EINTR) |
... | @@ -605,7 +714,7 @@ header_read (stream_t is, char *buf, size_t buflen, off_t off, size_t *pnread) | ... | @@ -605,7 +714,7 @@ header_read (stream_t is, char *buf, size_t buflen, off_t off, size_t *pnread) |
605 | return EINVAL; | 714 | return EINVAL; |
606 | 715 | ||
607 | /* Try to fill out the buffer, if we know how. */ | 716 | /* Try to fill out the buffer, if we know how. */ |
608 | if (header->blurb == NULL && header->_fill) | 717 | if (header->blurb == NULL) |
609 | { | 718 | { |
610 | int err = fill_blurb (header); | 719 | int err = fill_blurb (header); |
611 | if (err != 0) | 720 | if (err != 0) |
... | @@ -646,7 +755,7 @@ header_readline (stream_t is, char *buf, size_t buflen, off_t off, size_t *pn) | ... | @@ -646,7 +755,7 @@ header_readline (stream_t is, char *buf, size_t buflen, off_t off, size_t *pn) |
646 | } | 755 | } |
647 | 756 | ||
648 | /* Try to fill out the buffer, if we know how. */ | 757 | /* Try to fill out the buffer, if we know how. */ |
649 | if (header->blurb == NULL && header->_fill) | 758 | if (header->blurb == NULL) |
650 | { | 759 | { |
651 | int err = fill_blurb (header); | 760 | int err = fill_blurb (header); |
652 | if (err != 0) | 761 | if (err != 0) | ... | ... |
... | @@ -61,11 +61,14 @@ struct _header | ... | @@ -61,11 +61,14 @@ struct _header |
61 | size_t blurb_len; | 61 | size_t blurb_len; |
62 | size_t hdr_count; | 62 | size_t hdr_count; |
63 | struct _hdr *hdr; | 63 | struct _hdr *hdr; |
64 | size_t fhdr_count; | ||
65 | struct _hdr *fhdr; | ||
64 | int flags; | 66 | int flags; |
65 | 67 | ||
66 | /* Streams. */ | 68 | /* Streams. */ |
67 | stream_t stream; | 69 | stream_t stream; |
68 | int (*_get_value) __P ((header_t, const char *, char *, size_t , size_t *)); | 70 | int (*_get_value) __P ((header_t, const char *, char *, size_t , size_t *)); |
71 | int (*_get_fvalue) __P ((header_t, const char *, char *, size_t , size_t *)); | ||
69 | int (*_set_value) __P ((header_t, const char *, const char *, int)); | 72 | int (*_set_value) __P ((header_t, const char *, const char *, int)); |
70 | int (*_lines) __P ((header_t, size_t *)); | 73 | int (*_lines) __P ((header_t, size_t *)); |
71 | int (*_size) __P ((header_t, size_t *)); | 74 | int (*_size) __P ((header_t, size_t *)); | ... | ... |
... | @@ -69,7 +69,7 @@ struct _mailbox | ... | @@ -69,7 +69,7 @@ struct _mailbox |
69 | int (*_get_message) __P ((mailbox_t, size_t msgno, message_t *msg)); | 69 | int (*_get_message) __P ((mailbox_t, size_t msgno, message_t *msg)); |
70 | int (*_append_message) __P ((mailbox_t, message_t msg)); | 70 | int (*_append_message) __P ((mailbox_t, message_t msg)); |
71 | int (*_messages_count) __P ((mailbox_t, size_t *num)); | 71 | int (*_messages_count) __P ((mailbox_t, size_t *num)); |
72 | int (*_recent_count) __P ((mailbox_t, size_t *num)); | 72 | int (*_unseen_count) __P ((mailbox_t, size_t *num)); |
73 | int (*_expunge) __P ((mailbox_t)); | 73 | int (*_expunge) __P ((mailbox_t)); |
74 | 74 | ||
75 | int (*_scan) __P ((mailbox_t, size_t msgno, size_t *count)); | 75 | int (*_scan) __P ((mailbox_t, size_t msgno, size_t *count)); | ... | ... |
... | @@ -220,10 +220,10 @@ mailbox_messages_count (mailbox_t mbox, size_t *num) | ... | @@ -220,10 +220,10 @@ mailbox_messages_count (mailbox_t mbox, size_t *num) |
220 | } | 220 | } |
221 | 221 | ||
222 | int | 222 | int |
223 | mailbox_recent_count (mailbox_t mbox, size_t *num) | 223 | mailbox_unseen_count (mailbox_t mbox, size_t *num) |
224 | { | 224 | { |
225 | if (mbox && mbox->_recent_count) | 225 | if (mbox && mbox->_unseen_count) |
226 | return mbox->_recent_count (mbox, num); | 226 | return mbox->_unseen_count (mbox, num); |
227 | return mailbox_messages_count (mbox, num); | 227 | return mailbox_messages_count (mbox, num); |
228 | } | 228 | } |
229 | 229 | ... | ... |
... | @@ -36,6 +36,7 @@ static int mailbox_imap_close (mailbox_t); | ... | @@ -36,6 +36,7 @@ static int mailbox_imap_close (mailbox_t); |
36 | static int imap_expunge (mailbox_t); | 36 | static int imap_expunge (mailbox_t); |
37 | static int imap_get_message (mailbox_t, size_t, message_t *); | 37 | static int imap_get_message (mailbox_t, size_t, message_t *); |
38 | static int imap_messages_count (mailbox_t, size_t *); | 38 | static int imap_messages_count (mailbox_t, size_t *); |
39 | static int imap_unseen_count (mailbox_t, size_t *); | ||
39 | static int imap_scan (mailbox_t, size_t, size_t *); | 40 | static int imap_scan (mailbox_t, size_t, size_t *); |
40 | static int imap_is_updated (mailbox_t); | 41 | static int imap_is_updated (mailbox_t); |
41 | static int imap_append_message (mailbox_t, message_t); | 42 | static int imap_append_message (mailbox_t, message_t); |
... | @@ -63,7 +64,7 @@ static int imap_attr_set_flags (attribute_t, int); | ... | @@ -63,7 +64,7 @@ static int imap_attr_set_flags (attribute_t, int); |
63 | static int imap_attr_unset_flags (attribute_t, int); | 64 | static int imap_attr_unset_flags (attribute_t, int); |
64 | 65 | ||
65 | /* Header. */ | 66 | /* Header. */ |
66 | static int imap_header_read (stream_t, char*, size_t, off_t, size_t *); | 67 | static int imap_header_read (header_t, char*, size_t, off_t, size_t *); |
67 | static int imap_header_get_value (header_t, const char*, char *, size_t, size_t *); | 68 | static int imap_header_get_value (header_t, const char*, char *, size_t, size_t *); |
68 | static int imap_header_fd (stream_t, int *); | 69 | static int imap_header_fd (stream_t, int *); |
69 | 70 | ||
... | @@ -115,6 +116,7 @@ _mailbox_imap_init (mailbox_t mailbox) | ... | @@ -115,6 +116,7 @@ _mailbox_imap_init (mailbox_t mailbox) |
115 | mailbox->_get_message = imap_get_message; | 116 | mailbox->_get_message = imap_get_message; |
116 | mailbox->_append_message = imap_append_message; | 117 | mailbox->_append_message = imap_append_message; |
117 | mailbox->_messages_count = imap_messages_count; | 118 | mailbox->_messages_count = imap_messages_count; |
119 | mailbox->_unseen_count = imap_unseen_count; | ||
118 | mailbox->_expunge = imap_expunge; | 120 | mailbox->_expunge = imap_expunge; |
119 | 121 | ||
120 | mailbox->_scan = imap_scan; | 122 | mailbox->_scan = imap_scan; |
... | @@ -340,18 +342,12 @@ imap_get_message0 (msg_imap_t msg_imap, message_t *pmsg) | ... | @@ -340,18 +342,12 @@ imap_get_message0 (msg_imap_t msg_imap, message_t *pmsg) |
340 | /* Create the header. */ | 342 | /* Create the header. */ |
341 | { | 343 | { |
342 | header_t header = NULL; | 344 | header_t header = NULL; |
343 | stream_t stream = NULL; | 345 | if ((status = header_create (&header, NULL, 0, msg)) != 0) |
344 | if ((status = header_create (&header, NULL, 0, msg)) != 0 | ||
345 | || (status = stream_create (&stream, mailbox->flags, header)) != 0) | ||
346 | { | 346 | { |
347 | stream_destroy (&stream, header); | ||
348 | header_destroy (&header, msg); | ||
349 | message_destroy (&msg, msg_imap); | 347 | message_destroy (&msg, msg_imap); |
350 | return status; | 348 | return status; |
351 | } | 349 | } |
352 | stream_set_read (stream, imap_header_read, header); | 350 | header_set_fill (header, imap_header_read, msg); |
353 | stream_set_fd (stream, imap_header_fd, header); | ||
354 | header_set_stream (header, stream, msg); | ||
355 | header_set_get_value (header, imap_header_get_value, msg); | 351 | header_set_get_value (header, imap_header_get_value, msg); |
356 | message_set_header (msg, header, msg_imap); | 352 | message_set_header (msg, header, msg_imap); |
357 | } | 353 | } |
... | @@ -422,11 +418,17 @@ imap_get_message0 (msg_imap_t msg_imap, message_t *pmsg) | ... | @@ -422,11 +418,17 @@ imap_get_message0 (msg_imap_t msg_imap, message_t *pmsg) |
422 | return 0; | 418 | return 0; |
423 | } | 419 | } |
424 | 420 | ||
421 | static int | ||
422 | imap_unseen_count (mailbox_t mailbox, size_t *pnum) | ||
423 | { | ||
424 | m_imap_t m_imap = mailbox->data; | ||
425 | *pnum = m_imap->unseen; | ||
426 | return 0; | ||
427 | } | ||
425 | /* There is no explicit call to get the message count. The count is send on | 428 | /* There is no explicit call to get the message count. The count is send on |
426 | a SELECT/EXAMINE command it is also sent async, meaning it will be piggy | 429 | a SELECT/EXAMINE command it is also sent async, meaning it will be piggy |
427 | back on other server response as an untag "EXIST" response. But we still | 430 | back on other server response as an untag "EXIST" response. But we still |
428 | send a SELECT. */ | 431 | send a SELECT. */ |
429 | |||
430 | static int | 432 | static int |
431 | imap_messages_count (mailbox_t mailbox, size_t *pnum) | 433 | imap_messages_count (mailbox_t mailbox, size_t *pnum) |
432 | { | 434 | { |
... | @@ -1014,10 +1016,9 @@ imap_header_get_value (header_t header, const char *field, char * buffer, | ... | @@ -1014,10 +1016,9 @@ imap_header_get_value (header_t header, const char *field, char * buffer, |
1014 | } | 1016 | } |
1015 | 1017 | ||
1016 | static int | 1018 | static int |
1017 | imap_header_read (stream_t stream, char *buffer, size_t buflen, off_t offset, | 1019 | imap_header_read (header_t header, char *buffer, size_t buflen, off_t offset, |
1018 | size_t *plen) | 1020 | size_t *plen) |
1019 | { | 1021 | { |
1020 | header_t header = stream_get_owner (stream); | ||
1021 | message_t msg = header_get_owner (header); | 1022 | message_t msg = header_get_owner (header); |
1022 | msg_imap_t msg_imap = message_get_owner (msg); | 1023 | msg_imap_t msg_imap = message_get_owner (msg); |
1023 | m_imap_t m_imap = msg_imap->m_imap; | 1024 | m_imap_t m_imap = msg_imap->m_imap; | ... | ... |
... | @@ -58,6 +58,26 @@ struct _mbox_data; | ... | @@ -58,6 +58,26 @@ struct _mbox_data; |
58 | typedef struct _mbox_data* mbox_data_t; | 58 | typedef struct _mbox_data* mbox_data_t; |
59 | typedef struct _mbox_message* mbox_message_t; | 59 | typedef struct _mbox_message* mbox_message_t; |
60 | 60 | ||
61 | #define HDRSIZE 8 | ||
62 | const char *fhdr_table[] = | ||
63 | { | ||
64 | #define HFROM 0 | ||
65 | "From", | ||
66 | #define HTO 1 | ||
67 | "To", | ||
68 | #define HCC 2 | ||
69 | "Cc", | ||
70 | #define HSUBJECT 3 | ||
71 | "Subject", | ||
72 | #define HDATE 4 | ||
73 | "Date", | ||
74 | #define HX_UIDL 5 | ||
75 | "X-UIDL", | ||
76 | #define HX_UID 6 | ||
77 | "X-UID", | ||
78 | #define HCONTENT_TYPE 7 | ||
79 | "Content-Type", | ||
80 | }; | ||
61 | /* Keep the position of where the header and body starts and ends. | 81 | /* Keep the position of where the header and body starts and ends. |
62 | old_flags is the "Status:" message. */ | 82 | old_flags is the "Status:" message. */ |
63 | struct _mbox_message | 83 | struct _mbox_message |
... | @@ -71,6 +91,11 @@ struct _mbox_message | ... | @@ -71,6 +91,11 @@ struct _mbox_message |
71 | off_t body; | 91 | off_t body; |
72 | off_t body_end; | 92 | off_t body_end; |
73 | 93 | ||
94 | /* Fast header retrieve, we save here the most common header. Reasons this | ||
95 | will speed the header search. The header are copied on write or if we | ||
96 | the fast status failed. */ | ||
97 | char *fhdr[HDRSIZE]; | ||
98 | |||
74 | /* The old_flags contains the definition of Header. */ | 99 | /* The old_flags contains the definition of Header. */ |
75 | int old_flags; | 100 | int old_flags; |
76 | /* The new_flags holds the attributes changes for the current session. We | 101 | /* The new_flags holds the attributes changes for the current session. We |
... | @@ -122,7 +147,7 @@ static int mbox_close __P ((mailbox_t)); | ... | @@ -122,7 +147,7 @@ static int mbox_close __P ((mailbox_t)); |
122 | static int mbox_get_message __P ((mailbox_t, size_t, message_t *)); | 147 | static int mbox_get_message __P ((mailbox_t, size_t, message_t *)); |
123 | static int mbox_append_message __P ((mailbox_t, message_t)); | 148 | static int mbox_append_message __P ((mailbox_t, message_t)); |
124 | static int mbox_messages_count __P ((mailbox_t, size_t *)); | 149 | static int mbox_messages_count __P ((mailbox_t, size_t *)); |
125 | static int mbox_recent_count __P ((mailbox_t, size_t *)); | 150 | static int mbox_unseen_count __P ((mailbox_t, size_t *)); |
126 | static int mbox_expunge __P ((mailbox_t)); | 151 | static int mbox_expunge __P ((mailbox_t)); |
127 | static int mbox_scan __P ((mailbox_t, size_t, size_t *)); | 152 | static int mbox_scan __P ((mailbox_t, size_t, size_t *)); |
128 | static int mbox_is_updated __P ((mailbox_t)); | 153 | static int mbox_is_updated __P ((mailbox_t)); |
... | @@ -210,7 +235,7 @@ _mailbox_mbox_init (mailbox_t mailbox) | ... | @@ -210,7 +235,7 @@ _mailbox_mbox_init (mailbox_t mailbox) |
210 | mailbox->_get_message = mbox_get_message; | 235 | mailbox->_get_message = mbox_get_message; |
211 | mailbox->_append_message = mbox_append_message; | 236 | mailbox->_append_message = mbox_append_message; |
212 | mailbox->_messages_count = mbox_messages_count; | 237 | mailbox->_messages_count = mbox_messages_count; |
213 | mailbox->_recent_count = mbox_recent_count; | 238 | mailbox->_unseen_count = mbox_unseen_count; |
214 | mailbox->_expunge = mbox_expunge; | 239 | mailbox->_expunge = mbox_expunge; |
215 | 240 | ||
216 | mailbox->_scan = mbox_scan; | 241 | mailbox->_scan = mbox_scan; |
... | @@ -238,7 +263,11 @@ mbox_destroy (mailbox_t mailbox) | ... | @@ -238,7 +263,11 @@ mbox_destroy (mailbox_t mailbox) |
238 | mbox_message_t mum = mud->umessages[i]; | 263 | mbox_message_t mum = mud->umessages[i]; |
239 | if (mum) | 264 | if (mum) |
240 | { | 265 | { |
266 | size_t j; | ||
241 | message_destroy (&(mum->message), mum); | 267 | message_destroy (&(mum->message), mum); |
268 | for (j = 0; j < HDRSIZE; j++) | ||
269 | if (mum->fhdr[j]) | ||
270 | free (mum->fhdr[j]); | ||
242 | free (mum); | 271 | free (mum); |
243 | } | 272 | } |
244 | } | 273 | } |
... | @@ -347,7 +376,11 @@ mbox_close (mailbox_t mailbox) | ... | @@ -347,7 +376,11 @@ mbox_close (mailbox_t mailbox) |
347 | /* Destroy the attach messages. */ | 376 | /* Destroy the attach messages. */ |
348 | if (mum) | 377 | if (mum) |
349 | { | 378 | { |
379 | size_t j; | ||
350 | message_destroy (&(mum->message), mum); | 380 | message_destroy (&(mum->message), mum); |
381 | for (j = 0; j < HDRSIZE; j++) | ||
382 | if (mum->fhdr[j]) | ||
383 | free (mum->fhdr[j]); | ||
351 | free (mum); | 384 | free (mum); |
352 | } | 385 | } |
353 | } | 386 | } |
... | @@ -735,6 +768,11 @@ mbox_expunge (mailbox_t mailbox) | ... | @@ -735,6 +768,11 @@ mbox_expunge (mailbox_t mailbox) |
735 | //mum->header_status = mum->header_status_end = 0; | 768 | //mum->header_status = mum->header_status_end = 0; |
736 | //mum->body = mum->body_end = 0; | 769 | //mum->body = mum->body_end = 0; |
737 | //mum->header_lines = mum->body_lines = 0; | 770 | //mum->header_lines = mum->body_lines = 0; |
771 | for (i = 0; i < HDRSIZE; i++) | ||
772 | if (mum->fhdr[i]) | ||
773 | { | ||
774 | free (mum->fhdr[i]); | ||
775 | } | ||
738 | memset (mum, 0, sizeof (*mum)); | 776 | memset (mum, 0, sizeof (*mum)); |
739 | /* We are not free()ing the useless mum, but instead | 777 | /* We are not free()ing the useless mum, but instead |
740 | we put it back in the pool, to be reuse. */ | 778 | we put it back in the pool, to be reuse. */ |
... | @@ -903,6 +941,34 @@ mbox_header_fill (header_t header, char *buffer, size_t len, | ... | @@ -903,6 +941,34 @@ mbox_header_fill (header_t header, char *buffer, size_t len, |
903 | } | 941 | } |
904 | 942 | ||
905 | static int | 943 | static int |
944 | mbox_header_get_fvalue (header_t header, const char *name, char *buffer, | ||
945 | size_t buflen, size_t *pnread) | ||
946 | { | ||
947 | size_t i, fv_value = 0; | ||
948 | message_t msg = header_get_owner (header); | ||
949 | mbox_message_t mum = message_get_owner (msg); | ||
950 | int err = ENOENT; | ||
951 | for (i = 0; i < HDRSIZE; i++) | ||
952 | if (*name == *(fhdr_table[i]) && strcasecmp (fhdr_table[i], name) == 0) | ||
953 | { | ||
954 | fv_value = (mum->fhdr[i]) ? strlen (mum->fhdr[i]) : 0; | ||
955 | if (buffer && buflen > 0) | ||
956 | { | ||
957 | buflen--; | ||
958 | fv_value = (fv_value < buflen) ? fv_value : buflen; | ||
959 | memcpy (buffer, mum->fhdr[i], fv_value); | ||
960 | buffer[fv_value] = '\0'; | ||
961 | } | ||
962 | err = 0; | ||
963 | break; | ||
964 | } | ||
965 | |||
966 | if (pnread) | ||
967 | *pnread = fv_value; | ||
968 | return err; | ||
969 | } | ||
970 | |||
971 | static int | ||
906 | mbox_get_header_readstream (message_t msg, char *buffer, size_t len, | 972 | mbox_get_header_readstream (message_t msg, char *buffer, size_t len, |
907 | off_t off, size_t *pnread, int isreadline) | 973 | off_t off, size_t *pnread, int isreadline) |
908 | { | 974 | { |
... | @@ -1128,12 +1194,11 @@ mbox_get_message (mailbox_t mailbox, size_t msgno, message_t *pmsg) | ... | @@ -1128,12 +1194,11 @@ mbox_get_message (mailbox_t mailbox, size_t msgno, message_t *pmsg) |
1128 | status = header_create (&header, NULL, 0, msg); | 1194 | status = header_create (&header, NULL, 0, msg); |
1129 | if (status != 0) | 1195 | if (status != 0) |
1130 | { | 1196 | { |
1131 | //stream_destroy (&stream, header); | ||
1132 | header_destroy (&header, msg); | ||
1133 | message_destroy (&msg, mum); | 1197 | message_destroy (&msg, mum); |
1134 | return status; | 1198 | return status; |
1135 | } | 1199 | } |
1136 | header_set_fill (header, mbox_header_fill, msg); | 1200 | header_set_fill (header, mbox_header_fill, msg); |
1201 | header_set_get_fvalue (header, mbox_header_get_fvalue, msg); | ||
1137 | header_set_size (header, mbox_header_size, msg); | 1202 | header_set_size (header, mbox_header_size, msg); |
1138 | header_set_lines (header, mbox_header_lines, msg); | 1203 | header_set_lines (header, mbox_header_lines, msg); |
1139 | message_set_header (msg, header, mum); | 1204 | message_set_header (msg, header, mum); |
... | @@ -1537,7 +1602,7 @@ mbox_messages_count (mailbox_t mailbox, size_t *pcount) | ... | @@ -1537,7 +1602,7 @@ mbox_messages_count (mailbox_t mailbox, size_t *pcount) |
1537 | } | 1602 | } |
1538 | 1603 | ||
1539 | static int | 1604 | static int |
1540 | mbox_recent_count (mailbox_t mailbox, size_t *pcount) | 1605 | mbox_unseen_count (mailbox_t mailbox, size_t *pcount) |
1541 | { | 1606 | { |
1542 | mbox_data_t mud = mailbox->data; | 1607 | mbox_data_t mud = mailbox->data; |
1543 | mbox_message_t mum; | 1608 | mbox_message_t mum; | ... | ... |
1 | /* GNU mailutils - a suite of utilities for electronic mail | 1 | /* GNU mailutils - a suite of utilities for electronic mail |
2 | Copyright (C) 1999, 2000 Free Software Foundation, Inc. | 2 | Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. |
3 | 3 | ||
4 | This program is free software; you can redistribute it and/or modify | 4 | This program is free software; you can redistribute it and/or modify |
5 | it under the terms of the GNU General Library Public License as published by | 5 | it under the terms of the GNU General Library Public License as published by |
... | @@ -20,29 +20,21 @@ | ... | @@ -20,29 +20,21 @@ |
20 | */ | 20 | */ |
21 | 21 | ||
22 | /* Parsing. | 22 | /* Parsing. |
23 | * The approach is to detect the "From " as start of a | 23 | The approach is to detect the "From " as start of a new message, give the |
24 | * new message, give the position of the header and scan | 24 | position of the header and scan until "\n" then set header_end, set body |
25 | * until "\n" then set header_end, set body position, | 25 | position, scan until we it another "From " and set body_end. |
26 | * scan until we it another "From " and set body_end. | 26 | ************************************ |
27 | * | 27 | This is a classic case of premature optimisation being the root of all |
28 | ************************************ | 28 | Evil(Donald E. Knuth). But I'm under "pressure" ;-) to come with |
29 | * This is a classic case of premature optimisation | 29 | something "faster". I think it's wastefull * to spend time to gain a few |
30 | * being the root of all Evil(Donald E. Knuth). | 30 | seconds on 30Megs mailboxes ... but then again ... in computer time, 60 |
31 | * But I'm under "pressure" ;-) to come with | 31 | seconds, is eternity. If they use the event notification stuff to get |
32 | * something "faster". I think it's wastefull | 32 | some headers/messages early ... it's like pissing in the wind(sorry don't |
33 | * to spend time to gain a few seconds on 30Megs mailboxes | 33 | have the english equivalent). The worst is progress_bar it should be ... |
34 | * ... but then again ... in computer time, 60 seconds, is eternity. | 34 | &*($^ nuke. For the events, we have to remove the *.LCK file, release the |
35 | * | 35 | locks, flush the stream save the pointers etc ... hurry and wait... |
36 | * If they use the event notification stuff | 36 | I this point I'm pretty much ranting. */ |
37 | * to get some headers/messages early ... it's like pissing | 37 | |
38 | * in the wind(sorry don't have the english equivalent). | ||
39 | * The worst is progress_bar it should be ... &*($^ nuke. | ||
40 | * For the events, we have to remove the *.LCK file, | ||
41 | * release the locks, flush the stream save the pointers | ||
42 | * etc ... hurry and wait... | ||
43 | * I this point I'm pretty much ranting. | ||
44 | * | ||
45 | */ | ||
46 | 38 | ||
47 | /* From the C-Client, part of pine */ | 39 | /* From the C-Client, part of pine */ |
48 | /* You are not expected to understand this macro, but read the next page if | 40 | /* You are not expected to understand this macro, but read the next page if |
... | @@ -156,14 +148,6 @@ h | ... | @@ -156,14 +148,6 @@ h |
156 | } \ | 148 | } \ |
157 | } | 149 | } |
158 | 150 | ||
159 | #define STRLEN(s, i) \ | ||
160 | do \ | ||
161 | { \ | ||
162 | char *tmp = (s);\ | ||
163 | while (*tmp) tmp++; \ | ||
164 | i = tmp - s; \ | ||
165 | } while (0) | ||
166 | |||
167 | #define ATTRIBUTE_SET(buf,mum,c0,c1,type) \ | 151 | #define ATTRIBUTE_SET(buf,mum,c0,c1,type) \ |
168 | do \ | 152 | do \ |
169 | { \ | 153 | { \ |
... | @@ -178,13 +162,145 @@ do \ | ... | @@ -178,13 +162,145 @@ do \ |
178 | } \ | 162 | } \ |
179 | } while (0) | 163 | } while (0) |
180 | 164 | ||
165 | #define ISCONTENT_TYPE(buf) (\ | ||
166 | (buf[0] == 'C' || buf[0] == 'c') \ | ||
167 | && (buf[1] == 'O' || buf[1] == 'o') \ | ||
168 | && (buf[2] == 'N' || buf[2] == 'n') \ | ||
169 | && (buf[3] == 'T' || buf[3] == 't') \ | ||
170 | && (buf[4] == 'E' || buf[4] == 'e') \ | ||
171 | && (buf[5] == 'N' || buf[5] == 'n') \ | ||
172 | && (buf[6] == 'T' || buf[6] == 't') \ | ||
173 | && (buf[7] == '-') \ | ||
174 | && (buf[8] == 'T' || buf[8] == 't') \ | ||
175 | && (buf[9] == 'Y' || buf[9] == 'y') \ | ||
176 | && (buf[10] == 'P' || buf[10] == 'p') \ | ||
177 | && (buf[11] == 'E' || buf[11] == 'e') \ | ||
178 | && (buf[12] == ':' || buf[12] == ' ' || buf[12] == '\t')) | ||
179 | |||
180 | #define ISCC(buf) (\ | ||
181 | (buf[0] == 'C' || buf[0] == 'c') \ | ||
182 | && (buf[1] == 'C' || buf[1] == 'c') \ | ||
183 | && (buf[2] == ':' || buf[2] == ' ' || buf[2] == '\t')) | ||
184 | |||
185 | #define ISDATE(buf) (\ | ||
186 | (buf[0] == 'D' || buf[0] == 'd') \ | ||
187 | && (buf[1] == 'A' || buf[1] == 'a') \ | ||
188 | && (buf[2] == 'T' || buf[2] == 't') \ | ||
189 | && (buf[3] == 'E' || buf[3] == 'e') \ | ||
190 | && (buf[4] == ':' || buf[4] == ' ' || buf[4] == '\t')) | ||
191 | |||
192 | #define ISFROM(buf) (\ | ||
193 | (buf[0] == 'F' || buf[0] == 'f') \ | ||
194 | && (buf[1] == 'R' || buf[1] == 'r') \ | ||
195 | && (buf[2] == 'O' || buf[2] == 'o') \ | ||
196 | && (buf[3] == 'M' || buf[3] == 'm') \ | ||
197 | && (buf[4] == ':' || buf[4] == ' ' || buf[4] == '\t')) | ||
198 | |||
181 | #define ISSTATUS(buf) (\ | 199 | #define ISSTATUS(buf) (\ |
182 | (buf[0] == 'S' || buf[0] == 's') && \ | 200 | (buf[0] == 'S' || buf[0] == 's') \ |
183 | (buf[1] == 'T' || buf[1] == 't') && \ | 201 | && (buf[1] == 'T' || buf[1] == 't') \ |
184 | (buf[2] == 'A' || buf[2] == 'a') && \ | 202 | && (buf[2] == 'A' || buf[2] == 'a') \ |
185 | (buf[3] == 'T' || buf[3] == 't') && \ | 203 | && (buf[3] == 'T' || buf[3] == 't') \ |
186 | (buf[4] == 'U' || buf[4] == 'u') && \ | 204 | && (buf[4] == 'U' || buf[4] == 'u') \ |
187 | (buf[5] == 'S' || buf[5] == 's') && (buf[6] == ':')) | 205 | && (buf[5] == 'S' || buf[5] == 's') \ |
206 | && (buf[6] == ':' || buf[6] == ' ' || buf[6] == '\t')) | ||
207 | |||
208 | #define ISSUBJECT(buf) (\ | ||
209 | (buf[0] == 'S' || buf[0] == 's') \ | ||
210 | && (buf[1] == 'U' || buf[1] == 'u') \ | ||
211 | && (buf[2] == 'B' || buf[2] == 'b') \ | ||
212 | && (buf[3] == 'J' || buf[3] == 'j') \ | ||
213 | && (buf[4] == 'E' || buf[4] == 'e') \ | ||
214 | && (buf[5] == 'C' || buf[5] == 'c') \ | ||
215 | && (buf[6] == 'T' || buf[6] == 't') \ | ||
216 | && (buf[7] == ':' || buf[7] == ' ' || buf[7] == '\t')) | ||
217 | |||
218 | #define ISTO(buf) (\ | ||
219 | (buf[0] == 'T' || buf[0] == 't') \ | ||
220 | && (buf[1] == 'O' || buf[1] == 'o') \ | ||
221 | && (buf[2] == ':' || buf[2] == ' ' || buf[2] == '\t')) | ||
222 | |||
223 | #define ISX_UIDL(buf) (\ | ||
224 | (buf[0] == 'X' || buf[0] == 'x') \ | ||
225 | && (buf[1] == '-') \ | ||
226 | && (buf[2] == 'U' || buf[2] == 'u') \ | ||
227 | && (buf[3] == 'I' || buf[3] == 'i') \ | ||
228 | && (buf[4] == 'D' || buf[4] == 'd') \ | ||
229 | && (buf[5] == 'L' || buf[5] == 'l') \ | ||
230 | && (buf[6] == ':' || buf[6] == ' ' || buf[6] == '\t')) | ||
231 | |||
232 | #define ISX_UID(buf) (\ | ||
233 | (buf[0] == 'X' || buf[0] == 'x') \ | ||
234 | && (buf[1] == '-') \ | ||
235 | && (buf[2] == 'U' || buf[2] == 'u') \ | ||
236 | && (buf[3] == 'I' || buf[3] == 'i') \ | ||
237 | && (buf[4] == 'D' || buf[4] == 'd') \ | ||
238 | && (buf[5] == ':' || buf[5] == ' ' || buf[5] == '\t')) | ||
239 | |||
240 | /* Skip prepen spaces. */ | ||
241 | #define SKIPSPACE(p) while (*p == ' ') p++ | ||
242 | |||
243 | /* Save/concatenate the field-value in the field. */ | ||
244 | #define FAST_HEADER(field,buf,n) \ | ||
245 | do { \ | ||
246 | int i = 0; \ | ||
247 | char *s = field; \ | ||
248 | char *p = buf; \ | ||
249 | if (s) \ | ||
250 | while (*s++) i++; \ | ||
251 | else \ | ||
252 | p = memchr (buf, ':', n); \ | ||
253 | if (p) \ | ||
254 | { \ | ||
255 | int l; \ | ||
256 | char *tmp; \ | ||
257 | buf[n - 1] = '\0'; \ | ||
258 | p++; \ | ||
259 | if (!field) \ | ||
260 | SKIPSPACE(p); \ | ||
261 | l = n - (p - buf); \ | ||
262 | tmp = realloc (field, (l + i + 1) * sizeof (char)); \ | ||
263 | if (tmp) \ | ||
264 | { \ | ||
265 | field = tmp; \ | ||
266 | memcpy (field + i, p, l); \ | ||
267 | } \ | ||
268 | } \ | ||
269 | } while (0) | ||
270 | |||
271 | //fprintf (stderr, "%d %d <%s> <%s>\n", i, l, (i)?field:"", p); | ||
272 | |||
273 | #define FAST_HCONTENT_TYPE(mum,sf,buf,n) \ | ||
274 | FAST_HEADER(mum->fhdr[HCONTENT_TYPE],buf,n); \ | ||
275 | sf = &(mum->fhdr[HCONTENT_TYPE]) | ||
276 | |||
277 | #define FAST_HCC(mum,sf,buf,n) \ | ||
278 | FAST_HEADER(mum->fhdr[HCC],buf,n); \ | ||
279 | sf = &(mum->fhdr[HCC]) | ||
280 | |||
281 | #define FAST_HDATE(mum,sf,buf,n) \ | ||
282 | FAST_HEADER(mum->fhdr[HDATE],buf,n); \ | ||
283 | sf = &(mum->fhdr[HDATE]) | ||
284 | |||
285 | #define FAST_HFROM(mum,sf,buf,n) \ | ||
286 | FAST_HEADER(mum->fhdr[HFROM],buf,n); \ | ||
287 | sf = &(mum->fhdr[HFROM]) | ||
288 | |||
289 | #define FAST_HSUBJECT(mum,sf,buf,n) \ | ||
290 | FAST_HEADER(mum->fhdr[HSUBJECT],buf,n); \ | ||
291 | sf = &(mum->fhdr[HSUBJECT]) | ||
292 | |||
293 | #define FAST_HTO(mum,sf,buf,n) \ | ||
294 | FAST_HEADER(mum->fhdr[HTO],buf,n); \ | ||
295 | sf = &(mum->fhdr[HTO]) | ||
296 | |||
297 | #define FAST_HX_UIDL(mum,sf,buf,n) \ | ||
298 | FAST_HEADER(mum->fhdr[HX_UIDL],buf,n); \ | ||
299 | sf = &(mum->fhdr[HX_UIDL]) | ||
300 | |||
301 | #define FAST_HX_UID(mum,sf,buf,n) \ | ||
302 | FAST_HEADER(mum->fhdr[HX_UID],buf,n); \ | ||
303 | sf = &(mum->fhdr[HX_UID]) | ||
188 | 304 | ||
189 | /* Notifications ADD_MESG. */ | 305 | /* Notifications ADD_MESG. */ |
190 | #define DISPATCH_ADD_MSG(mbox,mud) \ | 306 | #define DISPATCH_ADD_MSG(mbox,mud) \ |
... | @@ -273,6 +389,8 @@ mbox_scan0 (mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -273,6 +389,8 @@ mbox_scan0 (mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) |
273 | size_t lines; | 389 | size_t lines; |
274 | int newline; | 390 | int newline; |
275 | size_t n = 0; | 391 | size_t n = 0; |
392 | stream_t stream; | ||
393 | char **sfield = NULL; | ||
276 | 394 | ||
277 | int zn, isfrom = 0; | 395 | int zn, isfrom = 0; |
278 | char *temp; | 396 | char *temp; |
... | @@ -315,6 +433,7 @@ mbox_scan0 (mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -315,6 +433,7 @@ mbox_scan0 (mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) |
315 | newline = 1; | 433 | newline = 1; |
316 | errno = lines = inheader = inbody = 0; | 434 | errno = lines = inheader = inbody = 0; |
317 | 435 | ||
436 | stream = mailbox->stream; | ||
318 | while ((status = stream_readline (mailbox->stream, buf, sizeof (buf), | 437 | while ((status = stream_readline (mailbox->stream, buf, sizeof (buf), |
319 | total, &n)) == 0 && n != 0) | 438 | total, &n)) == 0 && n != 0) |
320 | { | 439 | { |
... | @@ -329,13 +448,15 @@ mbox_scan0 (mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -329,13 +448,15 @@ mbox_scan0 (mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) |
329 | inheader = isfrom | ((!nl) & inheader); | 448 | inheader = isfrom | ((!nl) & inheader); |
330 | inbody = (!isfrom) & (!inheader); | 449 | inbody = (!isfrom) & (!inheader); |
331 | 450 | ||
332 | lines++; | 451 | if (buf[n - 1] == '\n') |
452 | lines++; | ||
333 | 453 | ||
334 | if (inheader) | 454 | if (inheader) |
335 | { | 455 | { |
336 | /* New message. */ | 456 | /* New message. */ |
337 | if (isfrom) | 457 | if (isfrom) |
338 | { | 458 | { |
459 | size_t j; | ||
339 | /* Signal the end of the body. */ | 460 | /* Signal the end of the body. */ |
340 | if (mum && !mum->body_end) | 461 | if (mum && !mum->body_end) |
341 | { | 462 | { |
... | @@ -354,8 +475,15 @@ mbox_scan0 (mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -354,8 +475,15 @@ mbox_scan0 (mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) |
354 | mum->header_from_end = total; | 475 | mum->header_from_end = total; |
355 | mum->body_end = mum->body = 0; | 476 | mum->body_end = mum->body = 0; |
356 | lines = 0; | 477 | lines = 0; |
478 | sfield = NULL; | ||
479 | for (j = 0; j < HDRSIZE; j++) | ||
480 | if (mum->fhdr[j]) | ||
481 | { | ||
482 | free (mum->fhdr[j]); | ||
483 | mum->fhdr[j] = NULL; | ||
484 | } | ||
357 | } | 485 | } |
358 | else if ((n > 7) && ISSTATUS(buf)) | 486 | else if (/*(n > 7) && */ ISSTATUS(buf)) |
359 | { | 487 | { |
360 | mum->header_status = total - n; | 488 | mum->header_status = total - n; |
361 | mum->header_status_end = total; | 489 | mum->header_status_end = total; |
... | @@ -363,6 +491,49 @@ mbox_scan0 (mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -363,6 +491,49 @@ mbox_scan0 (mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) |
363 | ATTRIBUTE_SET(buf, mum, 'o', 'O', MU_ATTRIBUTE_SEEN); | 491 | ATTRIBUTE_SET(buf, mum, 'o', 'O', MU_ATTRIBUTE_SEEN); |
364 | ATTRIBUTE_SET(buf, mum, 'a', 'A', MU_ATTRIBUTE_ANSWERED); | 492 | ATTRIBUTE_SET(buf, mum, 'a', 'A', MU_ATTRIBUTE_ANSWERED); |
365 | ATTRIBUTE_SET(buf, mum, 'd', 'D', MU_ATTRIBUTE_DELETED); | 493 | ATTRIBUTE_SET(buf, mum, 'd', 'D', MU_ATTRIBUTE_DELETED); |
494 | sfield = NULL; | ||
495 | } | ||
496 | else if (/*(n > 12) && */ ISCONTENT_TYPE(buf)) | ||
497 | { | ||
498 | FAST_HCONTENT_TYPE(mum, sfield, buf, n); | ||
499 | } | ||
500 | else if (/*(n > 3) && */ ISCC(buf)) | ||
501 | { | ||
502 | FAST_HCC(mum, sfield, buf, n); | ||
503 | } | ||
504 | else if (/*(n > 5) && */ ISDATE(buf)) | ||
505 | { | ||
506 | FAST_HDATE(mum, sfield, buf, n); | ||
507 | } | ||
508 | else if (/*(n > 5) && */ ISFROM(buf)) | ||
509 | { | ||
510 | FAST_HFROM(mum, sfield, buf, n); | ||
511 | } | ||
512 | else if (/*(n > 8) && */ ISSUBJECT(buf)) | ||
513 | { | ||
514 | FAST_HSUBJECT (mum, sfield, buf, n); | ||
515 | } | ||
516 | else if (/*(n > 3) && */ ISTO(buf)) | ||
517 | { | ||
518 | FAST_HTO (mum, sfield, buf, n); | ||
519 | } | ||
520 | else if (/*(n > 7) && */ ISX_UIDL(buf)) | ||
521 | { | ||
522 | FAST_HX_UIDL (mum, sfield, buf, n); | ||
523 | } | ||
524 | else if (/*(n > 6) && */ ISX_UID(buf)) | ||
525 | { | ||
526 | FAST_HX_UID (mum, sfield, buf, n); | ||
527 | } | ||
528 | else if (sfield && (buf[0] == ' ' || buf[0] == '\t')) | ||
529 | { | ||
530 | char *save = *sfield; | ||
531 | FAST_HEADER (save, buf, n); | ||
532 | *sfield = save; | ||
533 | } | ||
534 | else | ||
535 | { | ||
536 | sfield = NULL; | ||
366 | } | 537 | } |
367 | } | 538 | } |
368 | 539 | ... | ... |
... | @@ -85,8 +85,7 @@ static int pop_is_updated __P ((mailbox_t)); | ... | @@ -85,8 +85,7 @@ static int pop_is_updated __P ((mailbox_t)); |
85 | static int pop_user __P ((authority_t)); | 85 | static int pop_user __P ((authority_t)); |
86 | static int pop_size __P ((mailbox_t, off_t *)); | 86 | static int pop_size __P ((mailbox_t, off_t *)); |
87 | /* We use pop_top for retreiving headers. */ | 87 | /* We use pop_top for retreiving headers. */ |
88 | /* static int pop_header_read (stream_t, char *, size_t, off_t, size_t *); */ | 88 | /* static int pop_header_read (header_t, char *, size_t, off_t, size_t *); */ |
89 | static int pop_header_fd __P ((stream_t, int *)); | ||
90 | static int pop_body_fd __P ((stream_t, int *)); | 89 | static int pop_body_fd __P ((stream_t, int *)); |
91 | static int pop_body_size __P ((body_t, size_t *)); | 90 | static int pop_body_size __P ((body_t, size_t *)); |
92 | static int pop_body_lines __P ((body_t, size_t *)); | 91 | static int pop_body_lines __P ((body_t, size_t *)); |
... | @@ -94,7 +93,7 @@ static int pop_body_read __P ((stream_t, char *, size_t, off_t, size_t *)); | ... | @@ -94,7 +93,7 @@ static int pop_body_read __P ((stream_t, char *, size_t, off_t, size_t *)); |
94 | static int pop_message_read __P ((stream_t, char *, size_t, off_t, size_t *)); | 93 | static int pop_message_read __P ((stream_t, char *, size_t, off_t, size_t *)); |
95 | static int pop_message_size __P ((message_t, size_t *)); | 94 | static int pop_message_size __P ((message_t, size_t *)); |
96 | static int pop_message_fd __P ((stream_t, int *)); | 95 | static int pop_message_fd __P ((stream_t, int *)); |
97 | static int pop_top __P ((stream_t, char *, size_t, off_t, size_t *)); | 96 | static int pop_top __P ((header_t, char *, size_t, off_t, size_t *)); |
98 | static int pop_retr __P ((pop_message_t, char *, size_t, off_t, size_t *)); | 97 | static int pop_retr __P ((pop_message_t, char *, size_t, off_t, size_t *)); |
99 | static int pop_get_fd __P ((pop_message_t, int *)); | 98 | static int pop_get_fd __P ((pop_message_t, int *)); |
100 | static int pop_attr_flags __P ((attribute_t, int *)); | 99 | static int pop_attr_flags __P ((attribute_t, int *)); |
... | @@ -706,19 +705,13 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ... | @@ -706,19 +705,13 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
706 | /* Create the header. */ | 705 | /* Create the header. */ |
707 | { | 706 | { |
708 | header_t header = NULL; | 707 | header_t header = NULL; |
709 | stream_t stream = NULL; | 708 | if ((status = header_create (&header, NULL, 0, msg)) != 0) |
710 | if ((status = header_create (&header, NULL, 0, msg)) != 0 | ||
711 | || (status = stream_create (&stream, mbox->flags, header)) != 0) | ||
712 | { | 709 | { |
713 | stream_destroy (&stream, header); | ||
714 | header_destroy (&header, msg); | ||
715 | message_destroy (&msg, mpm); | 710 | message_destroy (&msg, mpm); |
716 | free (mpm); | 711 | free (mpm); |
717 | return status; | 712 | return status; |
718 | } | 713 | } |
719 | stream_set_read (stream, pop_top, header); | 714 | header_set_fill (header, pop_top, msg); |
720 | stream_set_fd (stream, pop_header_fd, header); | ||
721 | header_set_stream (header, stream, msg); | ||
722 | message_set_header (msg, header, mpm); | 715 | message_set_header (msg, header, mpm); |
723 | } | 716 | } |
724 | 717 | ||
... | @@ -1130,16 +1123,6 @@ pop_body_fd (stream_t stream, int *pfd) | ... | @@ -1130,16 +1123,6 @@ pop_body_fd (stream_t stream, int *pfd) |
1130 | return pop_get_fd (mpm, pfd); | 1123 | return pop_get_fd (mpm, pfd); |
1131 | } | 1124 | } |
1132 | 1125 | ||
1133 | /* Stub to call the fd from header object. */ | ||
1134 | static int | ||
1135 | pop_header_fd (stream_t stream, int *pfd) | ||
1136 | { | ||
1137 | header_t header = stream_get_owner (stream); | ||
1138 | message_t msg = header_get_owner (header); | ||
1139 | pop_message_t mpm = message_get_owner (msg); | ||
1140 | return pop_get_fd (mpm, pfd); | ||
1141 | } | ||
1142 | |||
1143 | /* Stub to call the fd from message object. */ | 1126 | /* Stub to call the fd from message object. */ |
1144 | static int | 1127 | static int |
1145 | pop_message_fd (stream_t stream, int *pfd) | 1128 | pop_message_fd (stream_t stream, int *pfd) |
... | @@ -1267,10 +1250,9 @@ pop_uid (message_t msg, char *buffer, size_t buflen, size_t *pnwriten) | ... | @@ -1267,10 +1250,9 @@ pop_uid (message_t msg, char *buffer, size_t buflen, size_t *pnwriten) |
1267 | on a socket but we better warn them, some stuff like mime_t may try to | 1250 | on a socket but we better warn them, some stuff like mime_t may try to |
1268 | read ahead, for example for the headers. */ | 1251 | read ahead, for example for the headers. */ |
1269 | static int | 1252 | static int |
1270 | pop_top (stream_t is, char *buffer, size_t buflen, | 1253 | pop_top (header_t header, char *buffer, size_t buflen, |
1271 | off_t offset, size_t *pnread) | 1254 | off_t offset, size_t *pnread) |
1272 | { | 1255 | { |
1273 | header_t header = stream_get_owner (is); | ||
1274 | message_t msg = header_get_owner (header); | 1256 | message_t msg = header_get_owner (header); |
1275 | pop_message_t mpm = message_get_owner (msg); | 1257 | pop_message_t mpm = message_get_owner (msg); |
1276 | pop_data_t mpd; | 1258 | pop_data_t mpd; |
... | @@ -1372,10 +1354,10 @@ pop_top (stream_t is, char *buffer, size_t buflen, | ... | @@ -1372,10 +1354,10 @@ pop_top (stream_t is, char *buffer, size_t buflen, |
1372 | #if 0 | 1354 | #if 0 |
1373 | /* Stub to call pop_retr (). Call form the stream object of the header. */ | 1355 | /* Stub to call pop_retr (). Call form the stream object of the header. */ |
1374 | static int | 1356 | static int |
1375 | pop_header_read (stream_t is, char *buffer, size_t buflen, off_t offset, | 1357 | pop_header_read (header_t header, char *buffer, size_t buflen, off_t offset, |
1376 | size_t *pnread) | 1358 | size_t *pnread) |
1377 | { | 1359 | { |
1378 | message_t msg = stream_get_owner (is); | 1360 | message_t msg = header_get_owner (header); |
1379 | pop_message_t mpm = message_get_owner (msg); | 1361 | pop_message_t mpm = message_get_owner (msg); |
1380 | pop_data_t mpd; | 1362 | pop_data_t mpd; |
1381 | void *func = (void *)pop_header_read; | 1363 | void *func = (void *)pop_header_read; | ... | ... |
-
Please register or sign in to post a comment