The code for IMAP, is a pain, the rewrite should clean all those
hacks. Something to remember for the mailbox2 is to do some smart caching, the current buffered stream is not good enough. * configure.in: VERSION is set to 0.0.9a for the alpha. * frm/frm.c: Protype for usage(). get_personal() should use const char *. * mail/mail.c (main): Use mailbox_scan() instead of mailbox_messages_count () it is faster for IMAP. * mailbox/mbx_imap.c(imap_get_message0): Remove the stream_setbufsiz() it is no longer used. (imap_message_readline imap_body_readline): Bug fix, readline will only consume up to '\n' even though the buffer is bigger. So we have to adjust the offset/lines/size to reflect what we consume. This is not very good for example doing: { off_t offset = 14; char buffer[512]; stream_readline (stream, buffer, sizeof buffer, offset, NULL); ... } Will send to the impap server. C: g445 FETCH 4 BODY.PEEK[2]<0.2048> S: * 4 FETCH (BODY[2]<0> {739} S: g445 OK FETCH completed This is waste since the first line is only 37 bytes. We will have to come up on the second API with some smart caching. * mailbox/memory_stream.c (_memory_write): Nasty bug was not updating the stream size. * mailbox/stream.c(stream_readline): Take care of known case where the buflen is 0 or 1.
Showing
7 changed files
with
203 additions
and
49 deletions
1 | 2001-10-14 Alain Magloire | 1 | 2001-10-14 Alain Magloire |
2 | 2 | ||
3 | The code for property.c has been change for a more simple approach, | 3 | The code for IMAP, is a pain, the rewrite should clean all those |
4 | it is the same approach as in mail/util.c(environment) settings. | 4 | hacks. Something to remember for the mailbox2 is to do some |
5 | The old code was simply overkill, property_t was seldomly use | 5 | smart caching, the current buffered stream is not good enough. |
6 | if at all and no need for heavy hash table and all that jazz. | 6 | |
7 | * configure.in: VERSION is set to 0.0.9a for the alpha. | ||
8 | * frm/frm.c: Protype for usage(). get_personal() should use | ||
9 | const char *. | ||
10 | * mail/mail.c (main): Use mailbox_scan() instead of | ||
11 | mailbox_messages_count () it is faster for IMAP. | ||
12 | |||
13 | * mailbox/mbx_imap.c(imap_get_message0): Remove the | ||
14 | stream_setbufsiz() it is no longer used. | ||
15 | (imap_message_readline imap_body_readline): | ||
16 | Bug fix, readline will only consume up to '\n' even though the | ||
17 | buffer is bigger. So we have to adjust the offset/lines/size | ||
18 | to reflect what we consume. This is not very good for example | ||
19 | doing: | ||
20 | { | ||
21 | off_t offset = 14; | ||
22 | char buffer[512]; | ||
23 | stream_readline (stream, buffer, sizeof buffer, offset, NULL); | ||
24 | ... | ||
25 | } | ||
26 | Will send to the impap server. | ||
27 | C: g445 FETCH 4 BODY.PEEK[2]<0.2048> | ||
28 | S: * 4 FETCH (BODY[2]<0> {739} | ||
29 | S: g445 OK FETCH completed | ||
30 | |||
31 | This is waste since the first line is only 37 bytes. We will | ||
32 | have to come up on the second API with some smart caching. | ||
33 | |||
34 | * mailbox/memory_stream.c (_memory_write): Nasty bug | ||
35 | was not updating the stream size. | ||
36 | * mailbox/stream.c(stream_readline): Take care of known | ||
37 | case where the buflen is 0 or 1. | ||
7 | 38 | ||
8 | * mailbox/property.c: New code, the same as mail/util.c | 39 | 2001-10-14 Alain Magloire |
9 | environment. | 40 | |
41 | The code for property.c has been changed for a more simple approach, | ||
42 | it is the same approach as mail/util.c(environment) settings. | ||
43 | The old code was simply overkill, property_t was seldomly used, | ||
44 | if at all, no need for heavy hash table and all that jazz. | ||
45 | |||
46 | * mailbox/property.c: New code, the same as mail/util.c environment. | ||
10 | * mailbox/mbx_mbox.c (_mbx_init): Remove property_add_defaults() etc .. | 47 | * mailbox/mbx_mbox.c (_mbx_init): Remove property_add_defaults() etc .. |
11 | no longer in use in the initialisation code. | 48 | no longer in use in the initialisation code. |
12 | * mailbox/mbx_imap.c: Likewised | 49 | * mailbox/mbx_imap.c: Likewised |
13 | * mailbox/mbx_pop.c: Likewised | 50 | * mailbox/mbx_pop.c: Likewised |
14 | * mailbox/mbx_mh.c: Likewised | 51 | * mailbox/mbx_mh.c: Likewised |
15 | * mailbox/header.c: Remove property code. | 52 | * mailbox/header.c: Removed property code. |
16 | * mailbox/body.c: Remove property code. | 53 | * mailbox/body.c: Removed property code. |
17 | * mailbox/message.c: Remove property code. | 54 | * mailbox/message.c: Removed property code. |
18 | * mailbox/filter.c: Change the code according to the new property_t. | 55 | * mailbox/filter.c: Changed the code according to the new property_t. |
19 | * mailbox/filter_rfc822.c: Change the code according to the new | 56 | * mailbox/filter_rfc822.c: Changed the code according to the new |
20 | property_t. | 57 | property_t structure. |
21 | * include/mailutils/header.h: Remove property. | 58 | * include/mailutils/header.h: Removed property. |
22 | * include/mailutils/body.h: Remove property. | 59 | * include/mailutils/body.h: Removed property. |
23 | * include/mailutils/message.h: Remove property. | 60 | * include/mailutils/message.h: Removed property. |
24 | * include/mailutils/property.h: Remove property_add_defaults() | 61 | * include/mailutils/property.h: Removed property_add_defaults() |
25 | property_set_valued () takes one more argument for overwrite. | 62 | property_set_valued () takes one more argument for overwrite. |
26 | * mailbox/include/header0.hy: Remove property field. | 63 | * mailbox/include/header0.hy: Removed property field. |
27 | * mailbox/include/body0.hy: Remove property field. | 64 | * mailbox/include/body0.hy: Removed property field. |
28 | * mailbox/include/message0.hy: Remove property field. | 65 | * mailbox/include/message0.hy: Removed property field. |
29 | * mailbox/mailbox.c(mailbox_get_property mailbox_set_property): | 66 | * mailbox/mailbox.c(mailbox_get_property mailbox_set_property): |
30 | Changed Property code. | 67 | Changed Property code. |
31 | * mailbox/mailer.c(mailer_set_property mailer_get_property): | 68 | * mailbox/mailer.c(mailer_set_property mailer_get_property): |
32 | Changed Property code. | 69 | Changed Property code. |
33 | 70 | ||
34 | * mailbox/folder_imap.c (imap_search imap_expunge imap_status): Stubs | 71 | * mailbox/folder_imap.c (imap_search imap_expunge imap_status): Stubs |
35 | Search is not implemented yet, STATUS neither and EXPUNGE is not used. | 72 | SEARCH is not implemented yet, STATUS neither and EXPUNGE is not used. |
36 | 73 | ||
37 | * mailbox/list.c: Rename variable index to indx to shutup | 74 | * mailbox/list.c: Renamed variable index to indx to shutup |
38 | gcc whos confusing with index() when warning level was high. | 75 | gcc whos confusing with index() when warning level was high. |
39 | * mailbox/md5-rsa.c: Likewised. | 76 | * mailbox/md5-rsa.c: Likewised. |
40 | 77 | ||
... | @@ -42,8 +79,8 @@ | ... | @@ -42,8 +79,8 @@ |
42 | The debug object was being set on the folder not the mailbox. | 79 | The debug object was being set on the folder not the mailbox. |
43 | 80 | ||
44 | * mailbox/mbx_imap.c (imap_messages_count): Attempt to reconnect | 81 | * mailbox/mbx_imap.c (imap_messages_count): Attempt to reconnect |
45 | if the connection timeout. Is this wise ? | 82 | if the connection timeout. Is this wise? |
46 | (imap_scan0): Move gut of imap_scan() code tho here. | 83 | (imap_scan0): Moved gut of imap_scan() code here. |
47 | (imap_scan): Stub calling imap_scan0() with notification enable. | 84 | (imap_scan): Stub calling imap_scan0() with notification enable. |
48 | (imap_expunge): After CLOSE, call imap_scan0() wiht notification | 85 | (imap_expunge): After CLOSE, call imap_scan0() wiht notification |
49 | disable. | 86 | disable. |
... | @@ -52,13 +89,12 @@ | ... | @@ -52,13 +89,12 @@ |
52 | of the recursive nature of the algorithm. Sam should buy me | 89 | of the recursive nature of the algorithm. Sam should buy me |
53 | a beer for this. | 90 | a beer for this. |
54 | 91 | ||
55 | * mailbox/parse822.c: Use more assert to catch errors. | 92 | * mailbox/parse822.c: Used more assert to catch errors. |
56 | (parse822_group): phrase was not free() in case of failure. | 93 | (parse822_group): phrase was not free() in case of failure. |
57 | (parse822_mail_box): Dead if branch remove and free phrase. | 94 | (parse822_mail_box): Dead "else if" branch removed and free phrase. |
58 | (parse822_route): accumulator was not being freed. | 95 | (parse822_route): accumulator was not being freed. |
59 | (parse822_local_part): Move down st_free(more). | 96 | (parse822_local_part): Moved down st_free(more). |
60 | (parse822_domain): Move down st_free(more). | 97 | (parse822_domain): Moved down st_free(more). |
61 | |||
62 | 98 | ||
63 | 2001-10-14 Sergey Poznyakoff | 99 | 2001-10-14 Sergey Poznyakoff |
64 | 100 | ... | ... |
1 | dnl Process this file with autoconf to procude a configure script. | 1 | dnl Process this file with autoconf to procude a configure script. |
2 | AC_INIT(mailbox/mailbox.c) | 2 | AC_INIT(mailbox/mailbox.c) |
3 | AM_INIT_AUTOMAKE(mailutils, 0.0.9) | 3 | AM_INIT_AUTOMAKE(mailutils, 0.0.9a) |
4 | AM_CONFIG_HEADER(config.h) | 4 | AM_CONFIG_HEADER(config.h) |
5 | 5 | ||
6 | dnl Check for programs | 6 | dnl Check for programs |
... | @@ -247,9 +247,9 @@ fi | ... | @@ -247,9 +247,9 @@ fi |
247 | 247 | ||
248 | dnl Output Makefiles | 248 | dnl Output Makefiles |
249 | AC_OUTPUT(Makefile mailutils.spec include/Makefile include/mailutils/Makefile | 249 | AC_OUTPUT(Makefile mailutils.spec include/Makefile include/mailutils/Makefile |
250 | m4/Makefile doc/Makefile doc/rfc/Makefile doc/texinfo/Makefile argp/Makefile | 250 | m4/Makefile doc/Makefile doc/rfc/Makefile doc/texinfo/Makefile argp/Makefile |
251 | lib/Makefile lib/posix/Makefile mailbox/Makefile imap4d/Makefile | 251 | lib/Makefile lib/posix/Makefile mailbox/Makefile imap4d/Makefile |
252 | mailbox/include/Makefile from/Makefile mail/Makefile pop3d/Makefile | 252 | mailbox/include/Makefile from/Makefile mail/Makefile pop3d/Makefile |
253 | frm/Makefile sieve/Makefile messages/Makefile scripts/Makefile | 253 | frm/Makefile sieve/Makefile messages/Makefile scripts/Makefile |
254 | libmu_scm/Makefile guimb/Makefile guimb/scm/Makefile | 254 | libmu_scm/Makefile guimb/Makefile guimb/scm/Makefile |
255 | MySql/Makefile) | 255 | MySql/Makefile) | ... | ... |
... | @@ -33,6 +33,7 @@ | ... | @@ -33,6 +33,7 @@ |
33 | #include <mailutils/address.h> | 33 | #include <mailutils/address.h> |
34 | 34 | ||
35 | static int action (observer_t, size_t); | 35 | static int action (observer_t, size_t); |
36 | static void usage (const char *argv); | ||
36 | 37 | ||
37 | static struct option long_options[] = | 38 | static struct option long_options[] = |
38 | { | 39 | { |
... | @@ -71,7 +72,7 @@ static int selected; | ... | @@ -71,7 +72,7 @@ static int selected; |
71 | 72 | ||
72 | /* Retrieve the Personal Name from the header To: or From: */ | 73 | /* Retrieve the Personal Name from the header To: or From: */ |
73 | static int | 74 | static int |
74 | get_personal (header_t hdr, char *field, char *personal, size_t buflen) | 75 | get_personal (header_t hdr, const char *field, char *personal, size_t buflen) |
75 | { | 76 | { |
76 | char hfield[512]; | 77 | char hfield[512]; |
77 | int status; | 78 | int status; |
... | @@ -193,7 +194,7 @@ action (observer_t o, size_t type) | ... | @@ -193,7 +194,7 @@ action (observer_t o, size_t type) |
193 | return 0; | 194 | return 0; |
194 | } | 195 | } |
195 | 196 | ||
196 | void | 197 | static void |
197 | usage (const char *argv) | 198 | usage (const char *argv) |
198 | { | 199 | { |
199 | printf ("GNU Mailutils.\n"); | 200 | printf ("GNU Mailutils.\n"); |
... | @@ -323,7 +324,6 @@ main(int argc, char **argv) | ... | @@ -323,7 +324,6 @@ main(int argc, char **argv) |
323 | mailbox_t mbox; | 324 | mailbox_t mbox; |
324 | observer_t observer; | 325 | observer_t observer; |
325 | observable_t observable; | 326 | observable_t observable; |
326 | int status; | ||
327 | 327 | ||
328 | if ((status = mailbox_create_default (&mbox, mailbox_name) != 0) | 328 | if ((status = mailbox_create_default (&mbox, mailbox_name) != 0) |
329 | || (status = mailbox_open (mbox, MU_STREAM_READ) != 0)) | 329 | || (status = mailbox_open (mbox, MU_STREAM_READ) != 0)) | ... | ... |
... | @@ -359,7 +359,7 @@ main (int argc, char **argv) | ... | @@ -359,7 +359,7 @@ main (int argc, char **argv) |
359 | exit (EXIT_FAILURE); | 359 | exit (EXIT_FAILURE); |
360 | } | 360 | } |
361 | 361 | ||
362 | if (mailbox_messages_count (mbox, &total) != 0) | 362 | if (mailbox_scan (mbox, 1, &total) != 0) |
363 | { | 363 | { |
364 | util_error ("Can not read mailbox"); | 364 | util_error ("Can not read mailbox"); |
365 | exit (EXIT_FAILURE); | 365 | exit (EXIT_FAILURE); | ... | ... |
... | @@ -62,6 +62,8 @@ static int imap_message_size __P ((message_t, size_t *)); | ... | @@ -62,6 +62,8 @@ static int imap_message_size __P ((message_t, size_t *)); |
62 | static int imap_message_lines __P ((message_t, size_t *)); | 62 | static int imap_message_lines __P ((message_t, size_t *)); |
63 | static int imap_message_fd __P ((stream_t, int *)); | 63 | static int imap_message_fd __P ((stream_t, int *)); |
64 | static int imap_message_read __P ((stream_t , char *, size_t, off_t, size_t *)); | 64 | static int imap_message_read __P ((stream_t , char *, size_t, off_t, size_t *)); |
65 | static int imap_message_readline __P ((stream_t, char *, size_t, off_t, | ||
66 | size_t *)); | ||
65 | static int imap_message_uid __P ((message_t, size_t *)); | 67 | static int imap_message_uid __P ((message_t, size_t *)); |
66 | 68 | ||
67 | /* mime_t API. */ | 69 | /* mime_t API. */ |
... | @@ -84,7 +86,10 @@ static int imap_header_get_value __P ((header_t, const char*, char *, size_t, s | ... | @@ -84,7 +86,10 @@ static int imap_header_get_value __P ((header_t, const char*, char *, size_t, s |
84 | static int imap_header_get_fvalue __P ((header_t, const char*, char *, size_t, size_t *)); | 86 | static int imap_header_get_fvalue __P ((header_t, const char*, char *, size_t, size_t *)); |
85 | 87 | ||
86 | /* body_t API. */ | 88 | /* body_t API. */ |
87 | static int imap_body_read __P ((stream_t, char *, size_t, off_t, size_t *)); | 89 | static int imap_body_read __P ((stream_t, char *, size_t, off_t, |
90 | size_t *)); | ||
91 | static int imap_body_readline __P ((stream_t, char *, size_t, off_t, | ||
92 | size_t *)); | ||
88 | static int imap_body_size __P ((body_t, size_t *)); | 93 | static int imap_body_size __P ((body_t, size_t *)); |
89 | static int imap_body_lines __P ((body_t, size_t *)); | 94 | static int imap_body_lines __P ((body_t, size_t *)); |
90 | static int imap_body_fd __P ((stream_t, int *)); | 95 | static int imap_body_fd __P ((stream_t, int *)); |
... | @@ -372,9 +377,8 @@ imap_get_message0 (msg_imap_t msg_imap, message_t *pmsg) | ... | @@ -372,9 +377,8 @@ imap_get_message0 (msg_imap_t msg_imap, message_t *pmsg) |
372 | message_destroy (&msg, msg_imap); | 377 | message_destroy (&msg, msg_imap); |
373 | return status; | 378 | return status; |
374 | } | 379 | } |
375 | /* We want the buffering. */ | ||
376 | stream_setbufsiz (stream, 128); | ||
377 | stream_set_read (stream, imap_message_read, msg); | 380 | stream_set_read (stream, imap_message_read, msg); |
381 | stream_set_readline (stream, imap_message_readline, msg); | ||
378 | stream_set_fd (stream, imap_message_fd, msg); | 382 | stream_set_fd (stream, imap_message_fd, msg); |
379 | message_set_stream (msg, stream, msg_imap); | 383 | message_set_stream (msg, stream, msg_imap); |
380 | message_set_size (msg, imap_message_size, msg_imap); | 384 | message_set_size (msg, imap_message_size, msg_imap); |
... | @@ -422,9 +426,8 @@ imap_get_message0 (msg_imap_t msg_imap, message_t *pmsg) | ... | @@ -422,9 +426,8 @@ imap_get_message0 (msg_imap_t msg_imap, message_t *pmsg) |
422 | message_destroy (&msg, msg_imap); | 426 | message_destroy (&msg, msg_imap); |
423 | return status; | 427 | return status; |
424 | } | 428 | } |
425 | /* We want the buffering. */ | ||
426 | stream_setbufsiz (stream, 128); | ||
427 | stream_set_read (stream, imap_body_read, body); | 429 | stream_set_read (stream, imap_body_read, body); |
430 | stream_set_readline (stream, imap_body_readline, body); | ||
428 | stream_set_fd (stream, imap_body_fd, body); | 431 | stream_set_fd (stream, imap_body_fd, body); |
429 | body_set_size (body, imap_body_size, msg); | 432 | body_set_size (body, imap_body_size, msg); |
430 | body_set_lines (body, imap_body_lines, msg); | 433 | body_set_lines (body, imap_body_lines, msg); |
... | @@ -947,6 +950,41 @@ imap_copy_message (mailbox_t mailbox, message_t msg) | ... | @@ -947,6 +950,41 @@ imap_copy_message (mailbox_t mailbox, message_t msg) |
947 | 950 | ||
948 | /* Message read overload */ | 951 | /* Message read overload */ |
949 | static int | 952 | static int |
953 | imap_message_readline (stream_t stream, char *buffer, size_t buflen, | ||
954 | off_t offset, size_t *plen) | ||
955 | { | ||
956 | message_t msg = stream_get_owner (stream); | ||
957 | msg_imap_t msg_imap = message_get_owner (msg); | ||
958 | m_imap_t m_imap = msg_imap->m_imap; | ||
959 | size_t lines = msg_imap->message_lines; | ||
960 | int status; | ||
961 | size_t len = 0; | ||
962 | char *nl = buffer; | ||
963 | |||
964 | /* Start over. */ | ||
965 | if (offset == 0) | ||
966 | lines = 0; | ||
967 | |||
968 | buflen--; /* for the NULL. */ | ||
969 | status = imap_message_read (stream, buffer, buflen, offset, &len); | ||
970 | if (len) | ||
971 | { | ||
972 | nl = memchr (buffer, '\n', len); | ||
973 | if (nl) | ||
974 | { | ||
975 | nl++; | ||
976 | *nl = '\0'; | ||
977 | msg_imap->message_lines = lines + 1; | ||
978 | } | ||
979 | else | ||
980 | nl = buffer + len; | ||
981 | } | ||
982 | if (plen) | ||
983 | *plen = nl - buffer; | ||
984 | return status; | ||
985 | } | ||
986 | |||
987 | static int | ||
950 | imap_message_read (stream_t stream, char *buffer, size_t buflen, | 988 | imap_message_read (stream_t stream, char *buffer, size_t buflen, |
951 | off_t offset, size_t *plen) | 989 | off_t offset, size_t *plen) |
952 | { | 990 | { |
... | @@ -954,6 +992,22 @@ imap_message_read (stream_t stream, char *buffer, size_t buflen, | ... | @@ -954,6 +992,22 @@ imap_message_read (stream_t stream, char *buffer, size_t buflen, |
954 | msg_imap_t msg_imap = message_get_owner (msg); | 992 | msg_imap_t msg_imap = message_get_owner (msg); |
955 | m_imap_t m_imap = msg_imap->m_imap; | 993 | m_imap_t m_imap = msg_imap->m_imap; |
956 | f_imap_t f_imap = m_imap->f_imap; | 994 | f_imap_t f_imap = m_imap->f_imap; |
995 | char *oldbuf = NULL; | ||
996 | char newbuf[2]; | ||
997 | int status; | ||
998 | |||
999 | /* This is so annoying, a buffer len of 1 is a killer. If you have for | ||
1000 | example "\n" to retrieve from the server, IMAP will transform this to | ||
1001 | "\r\n" and since you ask for only 1, the server will send '\r' only. | ||
1002 | And ... '\r' will be stripped by (imap_readline()) the number of char | ||
1003 | read will be 0 which means we're done .... sigh ... So we guard by at | ||
1004 | least ask for 2 chars. */ | ||
1005 | if (buflen == 1) | ||
1006 | { | ||
1007 | oldbuf = buffer; | ||
1008 | buffer = newbuf; | ||
1009 | buflen = 2; | ||
1010 | } | ||
957 | 1011 | ||
958 | /* Start over. */ | 1012 | /* Start over. */ |
959 | if (offset == 0) | 1013 | if (offset == 0) |
... | @@ -963,7 +1017,7 @@ imap_message_read (stream_t stream, char *buffer, size_t buflen, | ... | @@ -963,7 +1017,7 @@ imap_message_read (stream_t stream, char *buffer, size_t buflen, |
963 | if (f_imap->state == IMAP_NO_STATE) | 1017 | if (f_imap->state == IMAP_NO_STATE) |
964 | { | 1018 | { |
965 | char *section = NULL; | 1019 | char *section = NULL; |
966 | int status = imap_messages_count (m_imap->mailbox, NULL); | 1020 | status = imap_messages_count (m_imap->mailbox, NULL); |
967 | if (status != 0) | 1021 | if (status != 0) |
968 | return status; | 1022 | return status; |
969 | 1023 | ||
... | @@ -983,7 +1037,11 @@ imap_message_read (stream_t stream, char *buffer, size_t buflen, | ... | @@ -983,7 +1037,11 @@ imap_message_read (stream_t stream, char *buffer, size_t buflen, |
983 | MAILBOX_DEBUG0 (m_imap->mailbox, MU_DEBUG_PROT, f_imap->buffer); | 1037 | MAILBOX_DEBUG0 (m_imap->mailbox, MU_DEBUG_PROT, f_imap->buffer); |
984 | f_imap->state = IMAP_FETCH; | 1038 | f_imap->state = IMAP_FETCH; |
985 | } | 1039 | } |
986 | return fetch_operation (f_imap, msg_imap, buffer, buflen, plen); | 1040 | status = fetch_operation (f_imap, msg_imap, buffer, buflen, plen); |
1041 | |||
1042 | if (oldbuf) | ||
1043 | oldbuf[0] = buffer[0]; | ||
1044 | return status; | ||
987 | } | 1045 | } |
988 | 1046 | ||
989 | static int | 1047 | static int |
... | @@ -1585,6 +1643,22 @@ imap_header_read (header_t header, char *buffer, size_t buflen, off_t offset, | ... | @@ -1585,6 +1643,22 @@ imap_header_read (header_t header, char *buffer, size_t buflen, off_t offset, |
1585 | msg_imap_t msg_imap = message_get_owner (msg); | 1643 | msg_imap_t msg_imap = message_get_owner (msg); |
1586 | m_imap_t m_imap = msg_imap->m_imap; | 1644 | m_imap_t m_imap = msg_imap->m_imap; |
1587 | f_imap_t f_imap = m_imap->f_imap; | 1645 | f_imap_t f_imap = m_imap->f_imap; |
1646 | char *oldbuf = NULL; | ||
1647 | char newbuf[2]; | ||
1648 | int status; | ||
1649 | |||
1650 | /* This is so annoying, a buffer len of 1 is a killer. If you have for | ||
1651 | example "\n" to retrieve from the server, IMAP will transform this to | ||
1652 | "\r\n" and since you ask for only 1, the server will send '\r' only. | ||
1653 | And ... '\r' will be stripped by (imap_readline()) the number of char | ||
1654 | read will be 0 which means we're done .... sigh ... So we guard by at | ||
1655 | least ask for 2 chars. */ | ||
1656 | if (buflen == 1) | ||
1657 | { | ||
1658 | oldbuf = buffer; | ||
1659 | buffer = newbuf; | ||
1660 | buflen = 2; | ||
1661 | } | ||
1588 | 1662 | ||
1589 | /* Start over. */ | 1663 | /* Start over. */ |
1590 | if (offset == 0) | 1664 | if (offset == 0) |
... | @@ -1593,7 +1667,7 @@ imap_header_read (header_t header, char *buffer, size_t buflen, off_t offset, | ... | @@ -1593,7 +1667,7 @@ imap_header_read (header_t header, char *buffer, size_t buflen, off_t offset, |
1593 | /* Select first. */ | 1667 | /* Select first. */ |
1594 | if (f_imap->state == IMAP_NO_STATE) | 1668 | if (f_imap->state == IMAP_NO_STATE) |
1595 | { | 1669 | { |
1596 | int status = imap_messages_count (m_imap->mailbox, NULL); | 1670 | status = imap_messages_count (m_imap->mailbox, NULL); |
1597 | if (status != 0) | 1671 | if (status != 0) |
1598 | return status; | 1672 | return status; |
1599 | /* We strip the \r, but the offset/size on the imap server is with that | 1673 | /* We strip the \r, but the offset/size on the imap server is with that |
... | @@ -1619,7 +1693,10 @@ imap_header_read (header_t header, char *buffer, size_t buflen, off_t offset, | ... | @@ -1619,7 +1693,10 @@ imap_header_read (header_t header, char *buffer, size_t buflen, off_t offset, |
1619 | f_imap->state = IMAP_FETCH; | 1693 | f_imap->state = IMAP_FETCH; |
1620 | 1694 | ||
1621 | } | 1695 | } |
1622 | return fetch_operation (f_imap, msg_imap, buffer, buflen, plen); | 1696 | status = fetch_operation (f_imap, msg_imap, buffer, buflen, plen); |
1697 | if (oldbuf) | ||
1698 | oldbuf[0] = buffer[0]; | ||
1699 | return status; | ||
1623 | } | 1700 | } |
1624 | 1701 | ||
1625 | /* Body. */ | 1702 | /* Body. */ |
... | @@ -1661,6 +1738,41 @@ imap_body_lines (body_t body, size_t *plines) | ... | @@ -1661,6 +1738,41 @@ imap_body_lines (body_t body, size_t *plines) |
1661 | return 0; | 1738 | return 0; |
1662 | } | 1739 | } |
1663 | 1740 | ||
1741 | static int | ||
1742 | imap_body_readline (stream_t stream, char *buffer, size_t buflen, off_t offset, | ||
1743 | size_t *plen) | ||
1744 | { | ||
1745 | message_t msg = stream_get_owner (stream); | ||
1746 | msg_imap_t msg_imap = message_get_owner (msg); | ||
1747 | m_imap_t m_imap = msg_imap->m_imap; | ||
1748 | size_t lines = msg_imap->body_lines; | ||
1749 | int status; | ||
1750 | size_t len = 0; | ||
1751 | char *nl = buffer; | ||
1752 | |||
1753 | /* Start over. */ | ||
1754 | if (offset == 0) | ||
1755 | lines = 0; | ||
1756 | |||
1757 | buflen--; /* for the NULL. */ | ||
1758 | status = imap_body_read (stream, buffer, buflen, offset, &len); | ||
1759 | if (len) | ||
1760 | { | ||
1761 | nl = memchr (buffer, '\n', len); | ||
1762 | if (nl) | ||
1763 | { | ||
1764 | nl++; | ||
1765 | *nl = '\0'; | ||
1766 | msg_imap->body_lines = lines + 1; | ||
1767 | } | ||
1768 | else | ||
1769 | nl = buffer + len; | ||
1770 | } | ||
1771 | if (plen) | ||
1772 | *plen = nl - buffer; | ||
1773 | return status; | ||
1774 | } | ||
1775 | |||
1664 | /* FIXME: Send EISPIPE if trying to seek back. */ | 1776 | /* FIXME: Send EISPIPE if trying to seek back. */ |
1665 | static int | 1777 | static int |
1666 | imap_body_read (stream_t stream, char *buffer, size_t buflen, off_t offset, | 1778 | imap_body_read (stream_t stream, char *buffer, size_t buflen, off_t offset, |
... | @@ -1673,7 +1785,7 @@ imap_body_read (stream_t stream, char *buffer, size_t buflen, off_t offset, | ... | @@ -1673,7 +1785,7 @@ imap_body_read (stream_t stream, char *buffer, size_t buflen, off_t offset, |
1673 | f_imap_t f_imap = m_imap->f_imap; | 1785 | f_imap_t f_imap = m_imap->f_imap; |
1674 | char *oldbuf = NULL; | 1786 | char *oldbuf = NULL; |
1675 | char newbuf[2]; | 1787 | char newbuf[2]; |
1676 | int status = 0; | 1788 | int status; |
1677 | 1789 | ||
1678 | /* This is so annoying, a buffer len of 1 is a killer. If you have for | 1790 | /* This is so annoying, a buffer len of 1 is a killer. If you have for |
1679 | example "\n" to retrieve from the server, IMAP will transform this to | 1791 | example "\n" to retrieve from the server, IMAP will transform this to | ... | ... |
... | @@ -105,10 +105,10 @@ _memory_write (stream_t stream, const char *iptr, size_t isize, | ... | @@ -105,10 +105,10 @@ _memory_write (stream_t stream, const char *iptr, size_t isize, |
105 | if (tmp == NULL) | 105 | if (tmp == NULL) |
106 | return ENOMEM; | 106 | return ENOMEM; |
107 | mfs->ptr = tmp; | 107 | mfs->ptr = tmp; |
108 | mfs->size = offset + isize; | ||
109 | mfs->capacity = newsize; | 108 | mfs->capacity = newsize; |
110 | } | 109 | } |
111 | 110 | ||
111 | mfs->size = offset + isize; | ||
112 | memcpy (mfs->ptr + offset, iptr, isize); | 112 | memcpy (mfs->ptr + offset, iptr, isize); |
113 | if (nbytes) | 113 | if (nbytes) |
114 | *nbytes = isize; | 114 | *nbytes = isize; | ... | ... |
... | @@ -262,8 +262,14 @@ stream_readline (stream_t is, char *buf, size_t count, | ... | @@ -262,8 +262,14 @@ stream_readline (stream_t is, char *buf, size_t count, |
262 | 262 | ||
263 | is->state = MU_STREAM_STATE_READ; | 263 | is->state = MU_STREAM_STATE_READ; |
264 | 264 | ||
265 | if (count == 0) | 265 | switch (count) |
266 | { | 266 | { |
267 | case 1: | ||
268 | /* why would they do a thing like that? | ||
269 | stream_readline() is __always null terminated. */ | ||
270 | if (buf) | ||
271 | *buf = '\0'; | ||
272 | case 0: /* Buffer is empty noop. */ | ||
267 | if (pnread) | 273 | if (pnread) |
268 | *pnread = 0; | 274 | *pnread = 0; |
269 | return 0; | 275 | return 0; | ... | ... |
-
Please register or sign in to post a comment