Commit 9e5cc947 9e5cc947b01d31d06e6d431273ee8f84d2e7795d by Alain Magloire

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.
1 parent a738518b
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;
......