The big change: For getting the header we use "TOP # 0" but since TOP is an
optionnal command, we fallback to RETR and ignore the body part. This ugly and wastefull and it made the code unnecessary complexe. But fortunately I do not know of any POP server that does not have TOP. It's a mess. The other stuff was little cleanups.
Showing
10 changed files
with
617 additions
and
299 deletions
1 | The current maintainer Alain Magloire <alainm@rcsm.ece.mcgill.ca> | 1 | The current maintainer Alain Magloire <alainm@gnu.org> |
2 | 2 | ||
3 | Brian Edmond <briane@qnx.com> | ||
4 | Dave Inglis <dinglis@qnx.com> | ||
3 | Jakob Kaivo <jkaivo@ndn.net> | 5 | Jakob Kaivo <jkaivo@ndn.net> |
4 | Jeff Bailey <jbailey@gnu.org> | 6 | Jeff Bailey <jbailey@gnu.org> |
5 | Sean 'Shaleh' Perry <shaleh@debian.org> | 7 | Sean 'Shaleh' Perry <shaleh@debian.org> |
8 | ... | ... |
... | @@ -47,13 +47,11 @@ extern int body_get_filename __P ((body_t, char *, size_t, size_t *)); | ... | @@ -47,13 +47,11 @@ extern int body_get_filename __P ((body_t, char *, size_t, size_t *)); |
47 | extern int body_set_filename __P ((body_t, const char*)); | 47 | extern int body_set_filename __P ((body_t, const char*)); |
48 | 48 | ||
49 | extern int body_size __P ((body_t, size_t*)); | 49 | extern int body_size __P ((body_t, size_t*)); |
50 | extern int body_set_size __P ((body_t, | 50 | extern int body_set_size __P ((body_t, int (*_size) |
51 | int (*_size) __P ((body_t, size_t*)), | 51 | __P ((body_t, size_t*)), void *owner)); |
52 | void *owner)); | ||
53 | extern int body_lines __P ((body_t, size_t *)); | 52 | extern int body_lines __P ((body_t, size_t *)); |
54 | extern int body_set_lines __P ((body_t, | 53 | extern int body_set_lines __P ((body_t, int (*_lines) |
55 | int (*_lines) __P ((body_t, size_t*)), | 54 | __P ((body_t, size_t*)), void *owner)); |
56 | void *owner)); | ||
57 | 55 | ||
58 | #ifdef _cplusplus | 56 | #ifdef _cplusplus |
59 | } | 57 | } | ... | ... |
... | @@ -70,24 +70,29 @@ typedef struct _header * header_t; | ... | @@ -70,24 +70,29 @@ typedef struct _header * header_t; |
70 | extern int header_create __P ((header_t *, const char *, | 70 | extern int header_create __P ((header_t *, const char *, |
71 | size_t, void *)); | 71 | size_t, void *)); |
72 | extern void header_destroy __P ((header_t *, void *)); | 72 | extern void header_destroy __P ((header_t *, void *)); |
73 | |||
73 | extern int header_set_value __P ((header_t, const char *, | 74 | extern int header_set_value __P ((header_t, const char *, |
74 | const char *, int)); | 75 | const char *, int)); |
76 | extern int header_set_set_value __P ((header_t, int (*_set_value) | ||
77 | __P ((header_t, const char *, | ||
78 | const char *, int)), void *)); | ||
79 | |||
75 | extern int header_get_value __P ((header_t, const char *, char *, | 80 | extern int header_get_value __P ((header_t, const char *, char *, |
76 | size_t, size_t *)); | 81 | size_t, size_t *)); |
77 | extern int header_get_stream __P ((header_t, stream_t *)); | 82 | extern int header_set_get_value __P ((header_t, int (*_get_value) |
78 | extern int header_size __P ((header_t, size_t *)); | 83 | __P ((header_t, const char *, char *, |
79 | extern int header_lines __P ((header_t, size_t *)); | 84 | size_t, size_t *)), void *)); |
80 | 85 | ||
86 | extern int header_get_stream __P ((header_t, stream_t *)); | ||
81 | extern int header_set_stream __P ((header_t, stream_t, void *)); | 87 | extern int header_set_stream __P ((header_t, stream_t, void *)); |
82 | 88 | ||
83 | extern int header_set_set_value __P ((header_t, int (*_set_value) | 89 | extern int header_size __P ((header_t, size_t *)); |
84 | __P ((header_t, const char *, | 90 | extern int header_set_size __P ((header_t, int (*_size) |
85 | const char *, int)), | 91 | __P ((header_t, size_t *)), void *)); |
86 | void *)); | 92 | |
87 | extern int header_set_get_value __P ((header_t, int (*_get_value) | 93 | extern int header_lines __P ((header_t, size_t *)); |
88 | __P ((header_t, const char *, | 94 | extern int header_set_lines __P ((header_t, int (*_lines) |
89 | char *, size_t, size_t *)), | 95 | __P ((header_t, size_t *)), void *)); |
90 | void *)); | ||
91 | 96 | ||
92 | #ifdef _cplusplus | 97 | #ifdef _cplusplus |
93 | } | 98 | } | ... | ... |
... | @@ -55,39 +55,49 @@ extern int message_get_body __P ((message_t, body_t *)); | ... | @@ -55,39 +55,49 @@ extern int message_get_body __P ((message_t, body_t *)); |
55 | extern int message_set_body __P ((message_t, body_t, void *owner)); | 55 | extern int message_set_body __P ((message_t, body_t, void *owner)); |
56 | 56 | ||
57 | extern int message_get_stream __P ((message_t, stream_t *)); | 57 | extern int message_get_stream __P ((message_t, stream_t *)); |
58 | extern int message_set_stream __P ((message_t, stream_t, void *owner)); | ||
58 | 59 | ||
59 | extern int message_is_mime __P ((message_t)); | 60 | extern int message_is_multipart __P ((message_t, int *)); |
61 | extern int message_set_is_multipart __P ((message_t, int (*_is_multipart) | ||
62 | __P ((message_t, int *)), void *)); | ||
60 | 63 | ||
61 | extern int message_size __P ((message_t, size_t *)); | 64 | extern int message_size __P ((message_t, size_t *)); |
65 | extern int message_set_size __P ((message_t, int (*_size) | ||
66 | __P ((message_t, size_t *)), | ||
67 | void *owner)); | ||
68 | |||
62 | extern int message_lines __P ((message_t, size_t *)); | 69 | extern int message_lines __P ((message_t, size_t *)); |
70 | extern int message_set_lines __P ((message_t, int (*_lines) | ||
71 | __P ((message_t, size_t *)), | ||
72 | void *owner)); | ||
63 | 73 | ||
64 | extern int message_from __P ((message_t, char *, size_t, size_t *)); | 74 | extern int message_from __P ((message_t, char *, size_t, size_t *)); |
65 | extern int message_set_from __P ((message_t, | 75 | extern int message_set_from __P ((message_t, int (*_from) |
66 | int (*_from) __P ((message_t, char *, | 76 | __P ((message_t, char *, size_t, |
67 | size_t, size_t *)), | 77 | size_t *)), void *owner)); |
68 | void *owner)); | 78 | |
69 | extern int message_received __P ((message_t, char *, size_t, size_t *)); | 79 | extern int message_received __P ((message_t, char *, size_t, size_t *)); |
70 | extern int message_set_received __P ((message_t, int (*_received) | 80 | extern int message_set_received __P ((message_t, int (*_received) |
71 | __P ((message_t, char *, size_t, | 81 | __P ((message_t, char *, size_t, |
72 | size_t *)), void *owner)); | 82 | size_t *)), void *owner)); |
73 | 83 | ||
74 | extern int message_get_attribute __P ((message_t, attribute_t *)); | 84 | extern int message_get_attribute __P ((message_t, attribute_t *)); |
75 | extern int message_set_attribute __P ((message_t, attribute_t, void *owner)); | 85 | extern int message_set_attribute __P ((message_t, attribute_t, void *)); |
76 | 86 | ||
77 | extern int message_get_num_parts __P ((message_t, size_t *nparts)); | 87 | extern int message_get_num_parts __P ((message_t, size_t *nparts)); |
78 | extern int message_set_get_num_parts __P ((message_t, int (*_getNum_parts) | 88 | extern int message_set_get_num_parts __P ((message_t, int (*_get_num_parts) |
79 | __P ((message_t, size_t *)), | 89 | __P ((message_t, size_t *)), |
80 | void *owner)); | 90 | void *owner)); |
81 | 91 | ||
82 | extern int message_get_part __P ((message_t, size_t part, message_t *msg)); | 92 | extern int message_get_part __P ((message_t, size_t, message_t *)); |
83 | extern int message_set_get_part __P ((message_t, int (*_get_part) | 93 | extern int message_set_get_part __P ((message_t, int (*_get_part) |
84 | __P ((message_t, size_t, message_t *)), | 94 | __P ((message_t, size_t, |
85 | void *owner)); | 95 | message_t *)), void *owner)); |
86 | 96 | ||
87 | extern int message_get_uidl __P ((message_t, char *buffer, size_t, size_t *)); | 97 | extern int message_get_uidl __P ((message_t, char *, size_t, size_t *)); |
88 | extern int message_set_uidl __P ((message_t, int (*_get_uidl) | 98 | extern int message_set_uidl __P ((message_t, int (*_get_uidl) |
89 | __P ((message_t, char *, size_t, size_t *)), | 99 | __P ((message_t, char *, size_t, |
90 | void *owner)); | 100 | size_t *)), void *owner)); |
91 | 101 | ||
92 | /* events */ | 102 | /* events */ |
93 | #define MU_EVT_MSG_DESTROY 32 | 103 | #define MU_EVT_MSG_DESTROY 32 | ... | ... |
... | @@ -198,7 +198,8 @@ header_set_value (header_t header, const char *fn, const char *fv, int replace) | ... | @@ -198,7 +198,8 @@ header_set_value (header_t header, const char *fn, const char *fv, int replace) |
198 | if (header == NULL || fn == NULL || fv == NULL) | 198 | if (header == NULL || fn == NULL || fv == NULL) |
199 | return EINVAL; | 199 | return EINVAL; |
200 | 200 | ||
201 | if (header->_set_value != NULL) | 201 | /* Overload. */ |
202 | if (header->_set_value) | ||
202 | return header->_set_value (header, fn, fv, replace); | 203 | return header->_set_value (header, fn, fv, replace); |
203 | 204 | ||
204 | /* Try to fill out the buffer, if we know how. */ | 205 | /* Try to fill out the buffer, if we know how. */ |
... | @@ -268,7 +269,8 @@ header_get_value (header_t header, const char *name, char *buffer, | ... | @@ -268,7 +269,8 @@ header_get_value (header_t header, const char *name, char *buffer, |
268 | if (header == NULL || name == NULL) | 269 | if (header == NULL || name == NULL) |
269 | return EINVAL; | 270 | return EINVAL; |
270 | 271 | ||
271 | if (header->_get_value != NULL) | 272 | /* Overload. */ |
273 | if (header->_get_value) | ||
272 | return header->_get_value (header, name, buffer, buflen, pn); | 274 | return header->_get_value (header, name, buffer, buflen, pn); |
273 | 275 | ||
274 | /* Try to fill out the buffer, if we know how. */ | 276 | /* Try to fill out the buffer, if we know how. */ |
... | @@ -320,27 +322,36 @@ header_get_value (header_t header, const char *name, char *buffer, | ... | @@ -320,27 +322,36 @@ header_get_value (header_t header, const char *name, char *buffer, |
320 | if (pn) | 322 | if (pn) |
321 | *pn = total; | 323 | *pn = total; |
322 | 324 | ||
323 | /* Check if they provided a hook. */ | ||
324 | if (total == 0) | 325 | if (total == 0) |
325 | { | ||
326 | err = ENOENT; | 326 | err = ENOENT; |
327 | if (header->_get_value != NULL) | 327 | |
328 | err = header->_get_value (header, name, buffer, buflen, pn); | ||
329 | /* Success. Cache it locally. */ | ||
330 | if (err == 0) | ||
331 | header_set_value (header, name, buffer, 0); | ||
332 | } | ||
333 | return err; | 328 | return err; |
334 | } | 329 | } |
335 | 330 | ||
336 | int | 331 | int |
332 | header_set_lines (header_t header, int (*_lines) | ||
333 | (header_t, size_t *), void *owner) | ||
334 | { | ||
335 | if (header == NULL) | ||
336 | return EINVAL; | ||
337 | if (header->owner != owner) | ||
338 | return EACCES; | ||
339 | header->_lines = _lines; | ||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | int | ||
337 | header_lines (header_t header, size_t *plines) | 344 | header_lines (header_t header, size_t *plines) |
338 | { | 345 | { |
339 | int n; | 346 | int n; |
340 | size_t lines = 0; | 347 | size_t lines = 0; |
341 | if (header == NULL) | 348 | if (header == NULL || plines == NULL) |
342 | return EINVAL; | 349 | return EINVAL; |
343 | 350 | ||
351 | /* Overload. */ | ||
352 | if (header->_lines) | ||
353 | return header->_lines (header, plines); | ||
354 | |||
344 | /* Try to fill out the buffer, if we know how. */ | 355 | /* Try to fill out the buffer, if we know how. */ |
345 | if (header->blurb == NULL) | 356 | if (header->blurb == NULL) |
346 | { | 357 | { |
... | @@ -360,11 +371,27 @@ header_lines (header_t header, size_t *plines) | ... | @@ -360,11 +371,27 @@ header_lines (header_t header, size_t *plines) |
360 | } | 371 | } |
361 | 372 | ||
362 | int | 373 | int |
363 | header_size (header_t header, size_t *pnum) | 374 | header_set_size (header_t header, int (*_size) |
375 | (header_t, size_t *), void *owner) | ||
376 | { | ||
377 | if (header == NULL) | ||
378 | return EINVAL; | ||
379 | if (header->owner != owner) | ||
380 | return EACCES; | ||
381 | header->_size = _size; | ||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | int | ||
386 | header_size (header_t header, size_t *psize) | ||
364 | { | 387 | { |
365 | if (header == NULL) | 388 | if (header == NULL) |
366 | return EINVAL; | 389 | return EINVAL; |
367 | 390 | ||
391 | /* Overload. */ | ||
392 | if (header->_size) | ||
393 | return header->_size (header, psize); | ||
394 | |||
368 | /* Try to fill out the buffer, if we know how. */ | 395 | /* Try to fill out the buffer, if we know how. */ |
369 | if (header->blurb == NULL) | 396 | if (header->blurb == NULL) |
370 | { | 397 | { |
... | @@ -373,8 +400,8 @@ header_size (header_t header, size_t *pnum) | ... | @@ -373,8 +400,8 @@ header_size (header_t header, size_t *pnum) |
373 | return err; | 400 | return err; |
374 | } | 401 | } |
375 | 402 | ||
376 | if (pnum) | 403 | if (psize) |
377 | *pnum = header->blurb_len; | 404 | *psize = header->blurb_len; |
378 | return 0; | 405 | return 0; |
379 | } | 406 | } |
380 | 407 | ... | ... |
... | @@ -43,6 +43,9 @@ mailbox_create (mailbox_t *pmbox, const char *name, int id) | ... | @@ -43,6 +43,9 @@ mailbox_create (mailbox_t *pmbox, const char *name, int id) |
43 | struct mailbox_registrar *mreg; | 43 | struct mailbox_registrar *mreg; |
44 | url_t url = NULL; | 44 | url_t url = NULL; |
45 | 45 | ||
46 | if (pmbox == NULL) | ||
47 | return EINVAL; | ||
48 | |||
46 | url_create (&url, name); | 49 | url_create (&url, name); |
47 | 50 | ||
48 | /* 1st guest: if an ID is specify, shortcut */ | 51 | /* 1st guest: if an ID is specify, shortcut */ |
... | @@ -151,6 +154,14 @@ mailbox_scan (mailbox_t mbox, size_t msgno, size_t *pcount) | ... | @@ -151,6 +154,14 @@ mailbox_scan (mailbox_t mbox, size_t msgno, size_t *pcount) |
151 | return mbox->_scan (mbox, msgno, pcount); | 154 | return mbox->_scan (mbox, msgno, pcount); |
152 | } | 155 | } |
153 | 156 | ||
157 | int | ||
158 | mailbox_size (mailbox_t mbox, off_t *psize) | ||
159 | { | ||
160 | if (mbox == NULL || mbox->_size == NULL) | ||
161 | return 0; | ||
162 | return mbox->_size (mbox, psize); | ||
163 | } | ||
164 | |||
154 | /* locking */ | 165 | /* locking */ |
155 | int | 166 | int |
156 | mailbox_set_locker (mailbox_t mbox, locker_t locker) | 167 | mailbox_set_locker (mailbox_t mbox, locker_t locker) | ... | ... |
... | @@ -32,14 +32,20 @@ | ... | @@ -32,14 +32,20 @@ |
32 | #include <header0.h> | 32 | #include <header0.h> |
33 | #include <attribute0.h> | 33 | #include <attribute0.h> |
34 | 34 | ||
35 | /* Advance declarations. */ | ||
36 | struct _pop_data; | ||
37 | struct _pop_message; | ||
38 | struct _bio; | ||
35 | 39 | ||
36 | /* The different possible states of a Pop client, it maps to the POP3 commands. | 40 | typedef struct _pop_data * pop_data_t; |
37 | Note that POP3 is not reentrant. It is only one channel. */ | 41 | typedef struct _pop_message * pop_message_t; |
42 | typedef struct _bio *bio_t; | ||
43 | |||
44 | /* The different possible states of a Pop client, Note that POP3 is not | ||
45 | reentrant. It is only one channel. */ | ||
38 | enum pop_state | 46 | enum pop_state |
39 | { | 47 | { |
40 | /* The initialisation of POP_NO_STATE is redundant but it is here for | 48 | POP_NO_STATE = 0, POP_STATE_DONE, |
41 | info purposes meaning 0 is the starting state. */ | ||
42 | POP_NO_STATE = 0, | ||
43 | POP_OPEN_CONNECTION, | 49 | POP_OPEN_CONNECTION, |
44 | POP_GREETINGS, | 50 | POP_GREETINGS, |
45 | POP_APOP_TX, POP_APOP_ACK, | 51 | POP_APOP_TX, POP_APOP_ACK, |
... | @@ -54,8 +60,6 @@ enum pop_state | ... | @@ -54,8 +60,6 @@ enum pop_state |
54 | POP_TOP_TX, POP_TOP_ACK, POP_TOP_RX, | 60 | POP_TOP_TX, POP_TOP_ACK, POP_TOP_RX, |
55 | POP_UIDL_TX, POP_UIDL_ACK, | 61 | POP_UIDL_TX, POP_UIDL_ACK, |
56 | POP_USER_TX, POP_USER_ACK, | 62 | POP_USER_TX, POP_USER_ACK, |
57 | POP_CLOSE_CONNECTION /* I do not think a shutdown of a connection will | ||
58 | block. More for the symmetry. */ | ||
59 | }; | 63 | }; |
60 | 64 | ||
61 | /* Those two are exportable funtions i.e. they are visible/call when you | 65 | /* Those two are exportable funtions i.e. they are visible/call when you |
... | @@ -82,13 +86,17 @@ static int pop_is_updated (mailbox_t); | ... | @@ -82,13 +86,17 @@ static int pop_is_updated (mailbox_t); |
82 | 86 | ||
83 | /* The implementation of message_t */ | 87 | /* The implementation of message_t */ |
84 | static int pop_size (mailbox_t, off_t *); | 88 | static int pop_size (mailbox_t, off_t *); |
85 | static int pop_readstream (stream_t, char *, size_t, off_t, size_t *); | 89 | static int pop_top (stream_t, char *, size_t, off_t, size_t *); |
90 | static int pop_read_header (stream_t, char *, size_t, off_t, size_t *); | ||
91 | static int pop_read_body (stream_t, char *, size_t, off_t, size_t *); | ||
92 | static int pop_read_message (stream_t, char *, size_t, off_t, size_t *); | ||
93 | static int pop_retr (pop_message_t, char *, size_t, off_t, size_t *); | ||
86 | static int pop_get_fd (stream_t, int *); | 94 | static int pop_get_fd (stream_t, int *); |
87 | static int pop_get_flags (attribute_t, int *); | 95 | static int pop_get_flags (attribute_t, int *); |
88 | static int pop_body_size (body_t, size_t *); | 96 | static int pop_body_size (body_t, size_t *); |
89 | static int pop_body_lines (body_t body, size_t *plines); | 97 | static int pop_body_lines (body_t body, size_t *plines); |
90 | static int pop_header_read (stream_t, char *, size_t, off_t, size_t *); | ||
91 | static int pop_uidl (message_t, char *, size_t, size_t *); | 98 | static int pop_uidl (message_t, char *, size_t, size_t *); |
99 | static int fill_buffer (bio_t bio, char *buffer, size_t buflen); | ||
92 | 100 | ||
93 | /* According to the rfc: | 101 | /* According to the rfc: |
94 | RFC 2449 POP3 Extension Mechanism November 1998 | 102 | RFC 2449 POP3 Extension Mechanism November 1998 |
... | @@ -130,7 +138,6 @@ struct _bio | ... | @@ -130,7 +138,6 @@ struct _bio |
130 | char *ptr; | 138 | char *ptr; |
131 | char *nl; | 139 | char *nl; |
132 | }; | 140 | }; |
133 | typedef struct _bio *bio_t; | ||
134 | 141 | ||
135 | static int bio_create (bio_t *, stream_t); | 142 | static int bio_create (bio_t *, stream_t); |
136 | static void bio_destroy (bio_t *); | 143 | static void bio_destroy (bio_t *); |
... | @@ -138,12 +145,6 @@ static int bio_readline (bio_t); | ... | @@ -138,12 +145,6 @@ static int bio_readline (bio_t); |
138 | static int bio_read (bio_t); | 145 | static int bio_read (bio_t); |
139 | static int bio_write (bio_t); | 146 | static int bio_write (bio_t); |
140 | 147 | ||
141 | /* Advance declarations. */ | ||
142 | struct _pop_data; | ||
143 | struct _pop_message; | ||
144 | |||
145 | typedef struct _pop_data * pop_data_t; | ||
146 | typedef struct _pop_message * pop_message_t; | ||
147 | 148 | ||
148 | /* This structure holds the info when for a pop_get_message() the | 149 | /* This structure holds the info when for a pop_get_message() the |
149 | pop_message_t type will serve as the owner of the message_t and contains | 150 | pop_message_t type will serve as the owner of the message_t and contains |
... | @@ -156,6 +157,8 @@ typedef struct _pop_message * pop_message_t; | ... | @@ -156,6 +157,8 @@ typedef struct _pop_message * pop_message_t; |
156 | struct _pop_message | 157 | struct _pop_message |
157 | { | 158 | { |
158 | int inbody; | 159 | int inbody; |
160 | int skip_header; | ||
161 | int skip_body; | ||
159 | size_t body_size; | 162 | size_t body_size; |
160 | size_t body_lines; | 163 | size_t body_lines; |
161 | size_t num; | 164 | size_t num; |
... | @@ -215,7 +218,7 @@ pop_create (mailbox_t *pmbox, const char *name) | ... | @@ -215,7 +218,7 @@ pop_create (mailbox_t *pmbox, const char *name) |
215 | size_t name_len; | 218 | size_t name_len; |
216 | 219 | ||
217 | /* Sanity check. */ | 220 | /* Sanity check. */ |
218 | if (pmbox == NULL || name == NULL || *name == '\0') | 221 | if (name == NULL || *name == '\0') |
219 | return EINVAL; | 222 | return EINVAL; |
220 | 223 | ||
221 | name_len = strlen (name); | 224 | name_len = strlen (name); |
... | @@ -394,7 +397,7 @@ pop_authenticate (auth_t auth, char **user, char **passwd) | ... | @@ -394,7 +397,7 @@ pop_authenticate (auth_t auth, char **user, char **passwd) |
394 | static int | 397 | static int |
395 | pop_open (mailbox_t mbox, int flags) | 398 | pop_open (mailbox_t mbox, int flags) |
396 | { | 399 | { |
397 | pop_data_t mpd; | 400 | pop_data_t mpd = mbox->data; |
398 | int status; | 401 | int status; |
399 | bio_t bio; | 402 | bio_t bio; |
400 | void *func = (void *)pop_open; | 403 | void *func = (void *)pop_open; |
... | @@ -402,7 +405,7 @@ pop_open (mailbox_t mbox, int flags) | ... | @@ -402,7 +405,7 @@ pop_open (mailbox_t mbox, int flags) |
402 | long port; | 405 | long port; |
403 | 406 | ||
404 | /* Sanity checks. */ | 407 | /* Sanity checks. */ |
405 | if (mbox == NULL || mbox->url == NULL || (mpd = mbox->data) == NULL) | 408 | if (mbox->url == NULL || mpd == NULL) |
406 | return EINVAL; | 409 | return EINVAL; |
407 | 410 | ||
408 | /* Fetch the pop server name and the port in the url_t. */ | 411 | /* Fetch the pop server name and the port in the url_t. */ |
... | @@ -549,13 +552,13 @@ pop_open (mailbox_t mbox, int flags) | ... | @@ -549,13 +552,13 @@ pop_open (mailbox_t mbox, int flags) |
549 | static int | 552 | static int |
550 | pop_close (mailbox_t mbox) | 553 | pop_close (mailbox_t mbox) |
551 | { | 554 | { |
552 | pop_data_t mpd; | 555 | pop_data_t mpd = mbox->data; |
553 | void *func = (void *)pop_close; | 556 | void *func = (void *)pop_close; |
554 | int status; | 557 | int status; |
555 | bio_t bio; | 558 | bio_t bio; |
556 | size_t i; | 559 | size_t i; |
557 | 560 | ||
558 | if (mbox == NULL || (mpd = mbox->data) == NULL) | 561 | if (mpd == NULL) |
559 | return EINVAL; | 562 | return EINVAL; |
560 | 563 | ||
561 | if (mpd->func && mpd->func != func) | 564 | if (mpd->func && mpd->func != func) |
... | @@ -623,13 +626,13 @@ pop_close (mailbox_t mbox) | ... | @@ -623,13 +626,13 @@ pop_close (mailbox_t mbox) |
623 | static int | 626 | static int |
624 | pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | 627 | pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
625 | { | 628 | { |
626 | pop_data_t mpd; | 629 | pop_data_t mpd = mbox->data; |
627 | int status; | 630 | int status; |
628 | pop_message_t mpm; | 631 | pop_message_t mpm; |
629 | size_t i; | 632 | size_t i; |
630 | 633 | ||
631 | /* Sanity. */ | 634 | /* Sanity. */ |
632 | if (mbox == NULL || pmsg == NULL || (mpd = mbox->data) == NULL) | 635 | if (pmsg == NULL || mpd == NULL) |
633 | return EINVAL; | 636 | return EINVAL; |
634 | 637 | ||
635 | /* See if we have already this message. */ | 638 | /* See if we have already this message. */ |
... | @@ -655,12 +658,15 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ... | @@ -655,12 +658,15 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
655 | /* Create the message. */ | 658 | /* Create the message. */ |
656 | { | 659 | { |
657 | message_t msg; | 660 | message_t msg; |
658 | status = message_create (&msg, mpm); | 661 | stream_t is; |
659 | if (status != 0) | 662 | if ((status = message_create (&msg, mpm)) != 0 |
663 | || (status = stream_create (&is, MU_STREAM_READ, mpm)) != 0) | ||
660 | { | 664 | { |
661 | free (mpm); | 665 | free (mpm); |
662 | return status; | 666 | return status; |
663 | } | 667 | } |
668 | stream_set_read (is, pop_read_message, mpm); | ||
669 | message_set_stream (msg, is, mpm); | ||
664 | /* The message. */ | 670 | /* The message. */ |
665 | mpm->message = msg; | 671 | mpm->message = msg; |
666 | } | 672 | } |
... | @@ -676,7 +682,8 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ... | @@ -676,7 +682,8 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
676 | free (mpm); | 682 | free (mpm); |
677 | return status; | 683 | return status; |
678 | } | 684 | } |
679 | stream_set_read (stream, pop_header_read, mpm); | 685 | //stream_set_read (stream, pop_read_header, mpm); |
686 | stream_set_read (stream, pop_top, mpm); | ||
680 | stream_set_fd (stream, pop_get_fd, mpm); | 687 | stream_set_fd (stream, pop_get_fd, mpm); |
681 | stream_set_flags (stream, MU_STREAM_READ, mpm); | 688 | stream_set_flags (stream, MU_STREAM_READ, mpm); |
682 | header_set_stream (header, stream, mpm); | 689 | header_set_stream (header, stream, mpm); |
... | @@ -701,21 +708,14 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ... | @@ -701,21 +708,14 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
701 | { | 708 | { |
702 | stream_t stream; | 709 | stream_t stream; |
703 | body_t body; | 710 | body_t body; |
704 | status = body_create (&body, mpm); | 711 | if ((status = body_create (&body, mpm)) != 0 |
705 | if (status != 0) | 712 | || (status = stream_create (&stream, MU_STREAM_READ, mpm)) != 0) |
706 | { | ||
707 | message_destroy (&(mpm->message), mpm); | ||
708 | free (mpm); | ||
709 | return status; | ||
710 | } | ||
711 | status = stream_create (&stream, MU_STREAM_READ, mpm); | ||
712 | if (status != 0) | ||
713 | { | 713 | { |
714 | message_destroy (&(mpm->message), mpm); | 714 | message_destroy (&(mpm->message), mpm); |
715 | free (mpm); | 715 | free (mpm); |
716 | return status; | 716 | return status; |
717 | } | 717 | } |
718 | stream_set_read (stream, pop_readstream, mpm); | 718 | stream_set_read (stream, pop_read_body, mpm); |
719 | stream_set_fd (stream, pop_get_fd, mpm); | 719 | stream_set_fd (stream, pop_get_fd, mpm); |
720 | stream_set_flags (stream, mpd->flags, mpm); | 720 | stream_set_flags (stream, mpd->flags, mpm); |
721 | body_set_size (body, pop_body_size, mpm); | 721 | body_set_size (body, pop_body_size, mpm); |
... | @@ -750,12 +750,12 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ... | @@ -750,12 +750,12 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
750 | static int | 750 | static int |
751 | pop_messages_count (mailbox_t mbox, size_t *pcount) | 751 | pop_messages_count (mailbox_t mbox, size_t *pcount) |
752 | { | 752 | { |
753 | pop_data_t mpd; | 753 | pop_data_t mpd = mbox->data; |
754 | int status; | 754 | int status; |
755 | void *func = (void *)pop_messages_count; | 755 | void *func = (void *)pop_messages_count; |
756 | bio_t bio; | 756 | bio_t bio; |
757 | 757 | ||
758 | if (mbox == NULL || (mpd = (pop_data_t)mbox->data) == NULL) | 758 | if (mpd == NULL) |
759 | return EINVAL; | 759 | return EINVAL; |
760 | 760 | ||
761 | if (pop_is_updated (mbox)) | 761 | if (pop_is_updated (mbox)) |
... | @@ -817,8 +817,8 @@ pop_messages_count (mailbox_t mbox, size_t *pcount) | ... | @@ -817,8 +817,8 @@ pop_messages_count (mailbox_t mbox, size_t *pcount) |
817 | static int | 817 | static int |
818 | pop_is_updated (mailbox_t mbox) | 818 | pop_is_updated (mailbox_t mbox) |
819 | { | 819 | { |
820 | pop_data_t mpd; | 820 | pop_data_t mpd = mbox->data; |
821 | if ((mpd = (pop_data_t)mbox->data) == NULL) | 821 | if (mpd == NULL) |
822 | return 0; | 822 | return 0; |
823 | return mpd->is_updated; | 823 | return mpd->is_updated; |
824 | } | 824 | } |
... | @@ -826,11 +826,11 @@ pop_is_updated (mailbox_t mbox) | ... | @@ -826,11 +826,11 @@ pop_is_updated (mailbox_t mbox) |
826 | static int | 826 | static int |
827 | pop_num_deleted (mailbox_t mbox, size_t *pnum) | 827 | pop_num_deleted (mailbox_t mbox, size_t *pnum) |
828 | { | 828 | { |
829 | pop_data_t mpd; | 829 | pop_data_t mpd = mbox->data; |
830 | size_t i, total; | 830 | size_t i, total; |
831 | attribute_t attr; | 831 | attribute_t attr; |
832 | 832 | ||
833 | if (mbox == NULL || (mpd = (pop_data_t) mbox->data) == NULL) | 833 | if (mpd == NULL) |
834 | return EINVAL; | 834 | return EINVAL; |
835 | 835 | ||
836 | for (i = total = 0; i < mpd->messages_count; i++) | 836 | for (i = total = 0; i < mpd->messages_count; i++) |
... | @@ -867,14 +867,14 @@ pop_scan (mailbox_t mbox, size_t msgno, size_t *pcount) | ... | @@ -867,14 +867,14 @@ pop_scan (mailbox_t mbox, size_t msgno, size_t *pcount) |
867 | static int | 867 | static int |
868 | pop_expunge (mailbox_t mbox) | 868 | pop_expunge (mailbox_t mbox) |
869 | { | 869 | { |
870 | pop_data_t mpd; | 870 | pop_data_t mpd = mbox->data; |
871 | size_t i; | 871 | size_t i; |
872 | attribute_t attr; | 872 | attribute_t attr; |
873 | bio_t bio; | 873 | bio_t bio; |
874 | int status; | 874 | int status; |
875 | void *func = (void *)pop_expunge; | 875 | void *func = (void *)pop_expunge; |
876 | 876 | ||
877 | if (mbox == NULL || (mpd = (pop_data_t) mbox->data) == NULL) | 877 | if (mpd == NULL) |
878 | return EINVAL; | 878 | return EINVAL; |
879 | 879 | ||
880 | /* Busy ? */ | 880 | /* Busy ? */ |
... | @@ -958,10 +958,10 @@ pop_expunge (mailbox_t mbox) | ... | @@ -958,10 +958,10 @@ pop_expunge (mailbox_t mbox) |
958 | static int | 958 | static int |
959 | pop_size (mailbox_t mbox, off_t *psize) | 959 | pop_size (mailbox_t mbox, off_t *psize) |
960 | { | 960 | { |
961 | pop_data_t mpd; | 961 | pop_data_t mpd = mbox->data; |
962 | int status = 0; | 962 | int status = 0; |
963 | 963 | ||
964 | if (mbox == NULL || (mpd = (pop_data_t)mbox->data) == NULL) | 964 | if (mpd == NULL) |
965 | return EINVAL; | 965 | return EINVAL; |
966 | 966 | ||
967 | if (! pop_is_updated (mbox)) | 967 | if (! pop_is_updated (mbox)) |
... | @@ -974,8 +974,8 @@ pop_size (mailbox_t mbox, off_t *psize) | ... | @@ -974,8 +974,8 @@ pop_size (mailbox_t mbox, off_t *psize) |
974 | static int | 974 | static int |
975 | pop_body_size (body_t body, size_t *psize) | 975 | pop_body_size (body_t body, size_t *psize) |
976 | { | 976 | { |
977 | pop_message_t mpm; | 977 | pop_message_t mpm = body->owner; |
978 | if (body == NULL || (mpm = body->owner) == NULL) | 978 | if (mpm == NULL) |
979 | return EINVAL; | 979 | return EINVAL; |
980 | if (psize) | 980 | if (psize) |
981 | *psize = mpm->body_size; | 981 | *psize = mpm->body_size; |
... | @@ -985,8 +985,8 @@ pop_body_size (body_t body, size_t *psize) | ... | @@ -985,8 +985,8 @@ pop_body_size (body_t body, size_t *psize) |
985 | static int | 985 | static int |
986 | pop_body_lines (body_t body, size_t *plines) | 986 | pop_body_lines (body_t body, size_t *plines) |
987 | { | 987 | { |
988 | pop_message_t mpm; | 988 | pop_message_t mpm = body->owner; |
989 | if (body == NULL || (mpm = body->owner) == NULL) | 989 | if (mpm == NULL) |
990 | return EINVAL; | 990 | return EINVAL; |
991 | if (plines) | 991 | if (plines) |
992 | *plines = mpm->body_lines; | 992 | *plines = mpm->body_lines; |
... | @@ -996,12 +996,12 @@ pop_body_lines (body_t body, size_t *plines) | ... | @@ -996,12 +996,12 @@ pop_body_lines (body_t body, size_t *plines) |
996 | static int | 996 | static int |
997 | pop_get_flags (attribute_t attr, int *pflags) | 997 | pop_get_flags (attribute_t attr, int *pflags) |
998 | { | 998 | { |
999 | pop_message_t mpm; | 999 | pop_message_t mpm = attr->owner; |
1000 | char hdr_status[64]; | 1000 | char hdr_status[64]; |
1001 | header_t header = NULL; | 1001 | header_t header = NULL; |
1002 | int err; | 1002 | int err; |
1003 | 1003 | ||
1004 | if (attr == NULL || (mpm = attr->owner) == NULL) | 1004 | if (mpm == NULL) |
1005 | return EINVAL; | 1005 | return EINVAL; |
1006 | hdr_status[0] = '\0'; | 1006 | hdr_status[0] = '\0'; |
1007 | message_get_header (mpm->message, &header); | 1007 | message_get_header (mpm->message, &header); |
... | @@ -1015,8 +1015,8 @@ pop_get_flags (attribute_t attr, int *pflags) | ... | @@ -1015,8 +1015,8 @@ pop_get_flags (attribute_t attr, int *pflags) |
1015 | static int | 1015 | static int |
1016 | pop_get_fd (stream_t stream, int *pfd) | 1016 | pop_get_fd (stream_t stream, int *pfd) |
1017 | { | 1017 | { |
1018 | pop_message_t mpm; | 1018 | pop_message_t mpm = stream->owner; |
1019 | if (stream == NULL || (mpm = stream->owner) == NULL) | 1019 | if (mpm == NULL) |
1020 | return EINVAL; | 1020 | return EINVAL; |
1021 | if (mpm->mpd->bio) | 1021 | if (mpm->mpd->bio) |
1022 | return stream_get_fd (mpm->mpd->bio->stream, pfd); | 1022 | return stream_get_fd (mpm->mpd->bio->stream, pfd); |
... | @@ -1026,7 +1026,7 @@ pop_get_fd (stream_t stream, int *pfd) | ... | @@ -1026,7 +1026,7 @@ pop_get_fd (stream_t stream, int *pfd) |
1026 | static int | 1026 | static int |
1027 | pop_uidl (message_t msg, char *buffer, size_t buflen, size_t *pnwriten) | 1027 | pop_uidl (message_t msg, char *buffer, size_t buflen, size_t *pnwriten) |
1028 | { | 1028 | { |
1029 | pop_message_t mpm; | 1029 | pop_message_t mpm = msg->owner; |
1030 | pop_data_t mpd; | 1030 | pop_data_t mpd; |
1031 | bio_t bio; | 1031 | bio_t bio; |
1032 | int status = 0; | 1032 | int status = 0; |
... | @@ -1035,7 +1035,7 @@ pop_uidl (message_t msg, char *buffer, size_t buflen, size_t *pnwriten) | ... | @@ -1035,7 +1035,7 @@ pop_uidl (message_t msg, char *buffer, size_t buflen, size_t *pnwriten) |
1035 | /* According to the RFC uidl's are no longer then 70 chars. */ | 1035 | /* According to the RFC uidl's are no longer then 70 chars. */ |
1036 | char uniq[128]; | 1036 | char uniq[128]; |
1037 | 1037 | ||
1038 | if (msg == NULL || (mpm = msg->owner) == NULL) | 1038 | if (mpm == NULL) |
1039 | return EINVAL; | 1039 | return EINVAL; |
1040 | 1040 | ||
1041 | mpd = mpm->mpd; | 1041 | mpd = mpm->mpd; |
... | @@ -1099,19 +1099,20 @@ pop_uidl (message_t msg, char *buffer, size_t buflen, size_t *pnwriten) | ... | @@ -1099,19 +1099,20 @@ pop_uidl (message_t msg, char *buffer, size_t buflen, size_t *pnwriten) |
1099 | } | 1099 | } |
1100 | 1100 | ||
1101 | static int | 1101 | static int |
1102 | pop_header_read (stream_t is, char *buffer, size_t buflen, | 1102 | pop_top (stream_t is, char *buffer, size_t buflen, |
1103 | off_t offset, size_t *pnread) | 1103 | off_t offset, size_t *pnread) |
1104 | { | 1104 | { |
1105 | pop_message_t mpm; | 1105 | pop_message_t mpm = is->owner; |
1106 | pop_data_t mpd; | 1106 | pop_data_t mpd; |
1107 | bio_t bio; | 1107 | bio_t bio; |
1108 | size_t nread = 0; | 1108 | size_t nread = 0; |
1109 | int status = 0; | 1109 | int status = 0; |
1110 | void *func = (void *)pop_header_read; | 1110 | void *func = (void *)pop_top; |
1111 | 1111 | ||
1112 | if (is == NULL || (mpm = is->owner) == NULL) | 1112 | if (mpm == NULL) |
1113 | return EINVAL; | 1113 | return EINVAL; |
1114 | 1114 | ||
1115 | /* We do not carry the offset(for pop), should be doc somewhere. */ | ||
1115 | (void)offset; | 1116 | (void)offset; |
1116 | mpd = mpm->mpd; | 1117 | mpd = mpm->mpd; |
1117 | bio = mpd->bio; | 1118 | bio = mpd->bio; |
... | @@ -1147,9 +1148,12 @@ pop_header_read (stream_t is, char *buffer, size_t buflen, | ... | @@ -1147,9 +1148,12 @@ pop_header_read (stream_t is, char *buffer, size_t buflen, |
1147 | mailbox_debug (mpd->mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | 1148 | mailbox_debug (mpd->mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); |
1148 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) | 1149 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) |
1149 | { | 1150 | { |
1150 | fprintf (stderr, "TOP not implmented\n"); | 1151 | /* fprintf (stderr, "TOP not implmented\n"); */ |
1151 | CLEAR_STATE (mpd); | 1152 | /* Fall back to RETR call. */ |
1152 | return ENOSYS; | 1153 | mpd->state = POP_NO_STATE; |
1154 | mpm->skip_header = 0; | ||
1155 | mpm->skip_body = 1; | ||
1156 | return pop_retr (mpm, buffer, buflen, offset, pnread); | ||
1153 | } | 1157 | } |
1154 | mpd->state = POP_TOP_RX; | 1158 | mpd->state = POP_TOP_RX; |
1155 | bio->current = bio->nl; | 1159 | bio->current = bio->nl; |
... | @@ -1185,8 +1189,10 @@ pop_header_read (stream_t is, char *buffer, size_t buflen, | ... | @@ -1185,8 +1189,10 @@ pop_header_read (stream_t is, char *buffer, size_t buflen, |
1185 | } | 1189 | } |
1186 | break; | 1190 | break; |
1187 | default: | 1191 | default: |
1188 | /* fprintf (stderr, "pop_header_blurb unknown state\n"); */ | 1192 | /* Probabaly TOP was not supported so we fall back to RETR. */ |
1189 | break; | 1193 | mpm->skip_header = 0; |
1194 | mpm->skip_body = 1; | ||
1195 | return pop_retr (mpm, buffer, buflen, offset, pnread); | ||
1190 | } /* switch (state) */ | 1196 | } /* switch (state) */ |
1191 | 1197 | ||
1192 | if (nread == 0) | 1198 | if (nread == 0) |
... | @@ -1199,41 +1205,114 @@ pop_header_read (stream_t is, char *buffer, size_t buflen, | ... | @@ -1199,41 +1205,114 @@ pop_header_read (stream_t is, char *buffer, size_t buflen, |
1199 | } | 1205 | } |
1200 | 1206 | ||
1201 | static int | 1207 | static int |
1202 | pop_readstream (stream_t is, char *buffer, size_t buflen, | 1208 | pop_read_header (stream_t is, char *buffer, size_t buflen, off_t offset, |
1203 | off_t offset, size_t *pnread) | 1209 | size_t *pnread) |
1210 | { | ||
1211 | pop_message_t mpm = is->owner; | ||
1212 | pop_data_t mpd; | ||
1213 | void *func = (void *)pop_read_header; | ||
1214 | |||
1215 | if (mpm == NULL) | ||
1216 | return EINVAL; | ||
1217 | /* Busy ? */ | ||
1218 | if (mpd->func && mpd->func != func) | ||
1219 | return EBUSY; | ||
1220 | mpd->func = func; | ||
1221 | |||
1222 | mpm->skip_header = 0; | ||
1223 | mpm->skip_body = 1; | ||
1224 | return pop_retr (mpm, buffer, buflen, offset, pnread); | ||
1225 | } | ||
1226 | |||
1227 | static int | ||
1228 | pop_read_body (stream_t is, char *buffer, size_t buflen, off_t offset, | ||
1229 | size_t *pnread) | ||
1230 | { | ||
1231 | pop_message_t mpm = is->owner; | ||
1232 | pop_data_t mpd; | ||
1233 | void *func = (void *)pop_read_body; | ||
1234 | |||
1235 | if (mpm == NULL) | ||
1236 | return EINVAL; | ||
1237 | /* Busy ? */ | ||
1238 | if (mpd->func && mpd->func != func) | ||
1239 | return EBUSY; | ||
1240 | mpd->func = func; | ||
1241 | |||
1242 | mpm->skip_header = 1; | ||
1243 | mpm->skip_body = 0; | ||
1244 | return pop_retr (mpm, buffer, buflen, offset, pnread); | ||
1245 | } | ||
1246 | |||
1247 | static int | ||
1248 | pop_read_message (stream_t is, char *buffer, size_t buflen, off_t offset, | ||
1249 | size_t *pnread) | ||
1250 | { | ||
1251 | pop_message_t mpm = is->owner; | ||
1252 | pop_data_t mpd; | ||
1253 | void *func = (void *)pop_read_message; | ||
1254 | |||
1255 | if (mpm == NULL) | ||
1256 | return EINVAL; | ||
1257 | mpd = mpm->mpd; | ||
1258 | /* Busy ? */ | ||
1259 | if (mpd->func && mpd->func != func) | ||
1260 | return EBUSY; | ||
1261 | mpd->func = func; | ||
1262 | |||
1263 | mpm->skip_header = mpm->skip_body = 0; | ||
1264 | return pop_retr (mpm, buffer, buflen, offset, pnread); | ||
1265 | } | ||
1266 | |||
1267 | static int | ||
1268 | fill_buffer (bio_t bio, char *buffer, size_t buflen) | ||
1269 | { | ||
1270 | int nleft, n, nread = 0; | ||
1271 | n = bio->nl - bio->current; | ||
1272 | nleft = buflen - n; | ||
1273 | /* We got more then requested. */ | ||
1274 | if (nleft <= 0) | ||
1275 | { | ||
1276 | memcpy (buffer, bio->current, buflen); | ||
1277 | bio->current += buflen; | ||
1278 | nread = buflen; | ||
1279 | } | ||
1280 | else | ||
1281 | { | ||
1282 | /* Drain the buffer. */ | ||
1283 | memcpy (buffer, bio->current, n); | ||
1284 | bio->current += n; | ||
1285 | nread = n; | ||
1286 | } | ||
1287 | return nread; | ||
1288 | } | ||
1289 | |||
1290 | static int | ||
1291 | pop_retr (pop_message_t mpm, char *buffer, size_t buflen, off_t offset, | ||
1292 | size_t *pnread) | ||
1204 | { | 1293 | { |
1205 | pop_message_t mpm; | ||
1206 | pop_data_t mpd; | 1294 | pop_data_t mpd; |
1207 | size_t nread = 0; | 1295 | size_t nread = 0; |
1208 | bio_t bio; | 1296 | bio_t bio; |
1209 | int status = 0; | 1297 | int status = 0; |
1210 | void *func = (void *)pop_readstream; | ||
1211 | 1298 | ||
1212 | (void)offset; | 1299 | (void)offset; |
1213 | if (is == NULL || (mpm = is->owner) == NULL) | ||
1214 | return EINVAL; | ||
1215 | 1300 | ||
1216 | /* Take care of the obvious. */ | ||
1217 | if (buffer == NULL || buflen == 0) | ||
1218 | { | ||
1219 | if (pnread) | 1301 | if (pnread) |
1220 | *pnread = nread; | 1302 | *pnread = nread; |
1303 | /* Take care of the obvious. */ | ||
1304 | if (buffer == NULL || buflen == 0) | ||
1221 | return 0; | 1305 | return 0; |
1222 | } | ||
1223 | 1306 | ||
1224 | mpd = mpm->mpd; | 1307 | mpd = mpm->mpd; |
1225 | bio = mpd->bio; | 1308 | bio = mpd->bio; |
1226 | 1309 | ||
1227 | /* Busy ? */ | ||
1228 | if (mpd->func && mpd->func != func) | ||
1229 | return EBUSY; | ||
1230 | |||
1231 | mpd->func = func; | ||
1232 | |||
1233 | switch (mpd->state) | 1310 | switch (mpd->state) |
1234 | { | 1311 | { |
1235 | case POP_NO_STATE: | 1312 | case POP_NO_STATE: |
1313 | mpm->body_lines = mpm->body_size = 0; | ||
1236 | bio->len = sprintf (bio->buffer, "RETR %d\r\n", mpm->num); | 1314 | bio->len = sprintf (bio->buffer, "RETR %d\r\n", mpm->num); |
1315 | bio->ptr = bio->buffer; | ||
1237 | mpd->state = POP_RETR_TX; | 1316 | mpd->state = POP_RETR_TX; |
1238 | 1317 | ||
1239 | case POP_RETR_TX: | 1318 | case POP_RETR_TX: |
... | @@ -1251,14 +1330,33 @@ pop_readstream (stream_t is, char *buffer, size_t buflen, | ... | @@ -1251,14 +1330,33 @@ pop_readstream (stream_t is, char *buffer, size_t buflen, |
1251 | CLEAR_STATE (mpd); | 1330 | CLEAR_STATE (mpd); |
1252 | return EACCES; | 1331 | return EACCES; |
1253 | } | 1332 | } |
1333 | bio->current = bio->nl; | ||
1254 | mpd->state = POP_RETR_RX_HDR; | 1334 | mpd->state = POP_RETR_RX_HDR; |
1255 | 1335 | ||
1256 | case POP_RETR_RX_HDR: | 1336 | case POP_RETR_RX_HDR: |
1257 | /* Skip the header. */ | 1337 | /* Skip the header. */ |
1258 | while (!mpm->inbody) | 1338 | while (!mpm->inbody) |
1259 | { | 1339 | { |
1340 | /* Do we need to fill up. */ | ||
1341 | if (bio->current >= bio->nl) | ||
1342 | { | ||
1343 | bio->current = bio->buffer; | ||
1260 | status = bio_readline (bio); | 1344 | status = bio_readline (bio); |
1261 | CHECK_NON_RECOVERABLE (mpd, status); | 1345 | CHECK_NON_RECOVERABLE (mpd, status); |
1346 | } | ||
1347 | if (mpm->skip_header == 0) | ||
1348 | { | ||
1349 | nread = fill_buffer (bio, buffer, buflen); | ||
1350 | if (pnread) | ||
1351 | *pnread += nread; | ||
1352 | buflen -= nread ; | ||
1353 | if (buflen > 0) | ||
1354 | buffer += nread; | ||
1355 | else | ||
1356 | return 0; | ||
1357 | } | ||
1358 | else | ||
1359 | bio->current = bio->nl; | ||
1262 | if (bio->buffer[0] == '\n') | 1360 | if (bio->buffer[0] == '\n') |
1263 | { | 1361 | { |
1264 | mpm->inbody = 1; | 1362 | mpm->inbody = 1; |
... | @@ -1266,50 +1364,58 @@ pop_readstream (stream_t is, char *buffer, size_t buflen, | ... | @@ -1266,50 +1364,58 @@ pop_readstream (stream_t is, char *buffer, size_t buflen, |
1266 | } | 1364 | } |
1267 | } | 1365 | } |
1268 | /* Skip the newline. */ | 1366 | /* Skip the newline. */ |
1269 | bio_readline (bio); | 1367 | //bio_readline (bio); |
1270 | bio->current = bio->current; | ||
1271 | mpd->state = POP_RETR_RX_BODY; | 1368 | mpd->state = POP_RETR_RX_BODY; |
1272 | 1369 | ||
1273 | case POP_RETR_RX_BODY: | 1370 | case POP_RETR_RX_BODY: |
1274 | /* Start taking the body. */ | 1371 | /* Start taking the body. */ |
1275 | { | 1372 | { |
1276 | int nleft, n; | 1373 | while (mpm->inbody) |
1374 | { | ||
1277 | /* Do we need to fill up. */ | 1375 | /* Do we need to fill up. */ |
1278 | if (bio->current >= bio->nl) | 1376 | if (bio->current >= bio->nl) |
1279 | { | 1377 | { |
1280 | bio->current = bio->buffer; | 1378 | bio->current = bio->buffer; |
1281 | status = bio_readline (bio); | 1379 | status = bio_readline (bio); |
1282 | CHECK_NON_RECOVERABLE (mpd, status); | 1380 | CHECK_NON_RECOVERABLE (mpd, status); |
1381 | mpm->body_lines++; | ||
1283 | } | 1382 | } |
1284 | n = bio->nl - bio->current; | 1383 | if (mpm->skip_body == 0) |
1285 | nleft = buflen - n; | ||
1286 | /* We got more then requested. */ | ||
1287 | if (nleft <= 0) | ||
1288 | { | 1384 | { |
1289 | memcpy (buffer, bio->current, buflen); | 1385 | nread = fill_buffer (bio, buffer, buflen); |
1290 | bio->current += buflen; | 1386 | mpm->body_size += nread; |
1291 | nread = buflen; | 1387 | if (pnread) |
1388 | *pnread += nread; | ||
1389 | buflen -= nread ; | ||
1390 | if (buflen > 0) | ||
1391 | buffer += nread; | ||
1392 | else | ||
1393 | return 0; | ||
1292 | } | 1394 | } |
1293 | else | 1395 | else |
1294 | { | 1396 | { |
1295 | /* Drain the buffer. */ | 1397 | mpm->body_size += (bio->nl - bio->current); |
1296 | memcpy (buffer, bio->current, n); | 1398 | bio->current = bio->nl; |
1297 | bio->current += n; | ||
1298 | nread = n; | ||
1299 | } | 1399 | } |
1400 | if (bio->buffer[0] == '\0') | ||
1401 | { | ||
1402 | mpm->inbody = 0; | ||
1300 | break; | 1403 | break; |
1301 | } | 1404 | } |
1405 | } | ||
1406 | } | ||
1407 | mpd->state = POP_STATE_DONE; | ||
1408 | return 0; | ||
1409 | case POP_STATE_DONE: | ||
1410 | /* A convenient break, this is here so we can return 0 read on next | ||
1411 | call meaning we're done. */ | ||
1302 | default: | 1412 | default: |
1303 | /* fprintf (stderr, "pop_readstream unknow state\n"); */ | 1413 | /* fprintf (stderr, "pop_retr unknow state\n"); */ |
1304 | break; | 1414 | break; |
1305 | } /* Switch state. */ | 1415 | } /* Switch state. */ |
1306 | 1416 | ||
1307 | if (nread == 0) | ||
1308 | { | ||
1309 | CLEAR_STATE (mpd); | 1417 | CLEAR_STATE (mpd); |
1310 | } | 1418 | mpm->skip_header = mpm->skip_body = 0; |
1311 | if (pnread) | ||
1312 | *pnread = nread; | ||
1313 | return 0; | 1419 | return 0; |
1314 | } | 1420 | } |
1315 | 1421 | ... | ... |
... | @@ -23,6 +23,7 @@ | ... | @@ -23,6 +23,7 @@ |
23 | #include <url0.h> | 23 | #include <url0.h> |
24 | #include <stream0.h> | 24 | #include <stream0.h> |
25 | #include <body0.h> | 25 | #include <body0.h> |
26 | #include <header0.h> | ||
26 | #include <attribute0.h> | 27 | #include <attribute0.h> |
27 | #include <mailutils/header.h> | 28 | #include <mailutils/header.h> |
28 | #include <mailutils/auth.h> | 29 | #include <mailutils/auth.h> |
... | @@ -103,13 +104,20 @@ typedef struct _unix_data | ... | @@ -103,13 +104,20 @@ typedef struct _unix_data |
103 | size_t umessages_count; | 104 | size_t umessages_count; |
104 | size_t messages_count; | 105 | size_t messages_count; |
105 | stream_t stream; | 106 | stream_t stream; |
106 | char *dirname; | ||
107 | char *basename; | ||
108 | #ifdef HAVE_PTHREAD_H | 107 | #ifdef HAVE_PTHREAD_H |
109 | pthread_mutex_t mutex; | 108 | pthread_mutex_t mutex; |
110 | #endif | 109 | #endif |
111 | off_t size; | 110 | off_t size; |
112 | 111 | ||
112 | /* The variables below are use to hold the state when appending messages. */ | ||
113 | enum unix_state | ||
114 | { | ||
115 | UNIX_NO_STATE=0, UNIX_STATE_FROM, UNIX_STATE_DATE, UNIX_STATE_APPEND | ||
116 | } state ; | ||
117 | char *from; | ||
118 | char *date; | ||
119 | off_t off; | ||
120 | |||
113 | } *unix_data_t; | 121 | } *unix_data_t; |
114 | 122 | ||
115 | static int unix_open (mailbox_t mbox, int flag); | 123 | static int unix_open (mailbox_t mbox, int flag); |
... | @@ -134,6 +142,8 @@ static int unix_set_flags (attribute_t, int); | ... | @@ -134,6 +142,8 @@ static int unix_set_flags (attribute_t, int); |
134 | static int unix_unset_flags (attribute_t, int); | 142 | static int unix_unset_flags (attribute_t, int); |
135 | static int unix_readstream (stream_t is, char *buffer, size_t buflen, | 143 | static int unix_readstream (stream_t is, char *buffer, size_t buflen, |
136 | off_t off, size_t *pnread); | 144 | off_t off, size_t *pnread); |
145 | static int unix_header_size (header_t header, size_t *psize); | ||
146 | static int unix_header_lines (header_t header, size_t *plines); | ||
137 | static int unix_body_size (body_t body, size_t *psize); | 147 | static int unix_body_size (body_t body, size_t *psize); |
138 | static int unix_body_lines (body_t body, size_t *plines); | 148 | static int unix_body_lines (body_t body, size_t *plines); |
139 | static int unix_msg_from (message_t msg, char *buf, size_t len, | 149 | static int unix_msg_from (message_t msg, char *buf, size_t len, |
... | @@ -155,7 +165,6 @@ unix_create (mailbox_t *pmbox, const char *name) | ... | @@ -155,7 +165,6 @@ unix_create (mailbox_t *pmbox, const char *name) |
155 | { | 165 | { |
156 | mailbox_t mbox; | 166 | mailbox_t mbox; |
157 | unix_data_t mud; | 167 | unix_data_t mud; |
158 | const char *sep; | ||
159 | size_t name_len; | 168 | size_t name_len; |
160 | 169 | ||
161 | /* Sanity check. */ | 170 | /* Sanity check. */ |
... | @@ -169,18 +178,18 @@ unix_create (mailbox_t *pmbox, const char *name) | ... | @@ -169,18 +178,18 @@ unix_create (mailbox_t *pmbox, const char *name) |
169 | #define SEPARATOR '/' | 178 | #define SEPARATOR '/' |
170 | 179 | ||
171 | /* Skip the url scheme. */ | 180 | /* Skip the url scheme. */ |
172 | if (name_len > UNIX_SCHEME_LEN && | 181 | if (name_len > UNIX_SCHEME_LEN |
173 | (name[0] == 'u' || name[0] == 'U') && | 182 | && (name[0] == 'u' || name[0] == 'U') |
174 | (name[1] == 'n' || name[1] == 'N') && | 183 | && (name[1] == 'n' || name[1] == 'N') |
175 | (name[2] == 'i' || name[2] == 'i') && | 184 | && (name[2] == 'i' || name[2] == 'i') |
176 | (name[3] == 'x' || name[3] == 'x' ) && | 185 | && (name[3] == 'x' || name[3] == 'x' ) |
177 | name[4] == ':') | 186 | && name[4] == ':') |
178 | { | 187 | { |
179 | name += UNIX_SCHEME_LEN; | 188 | name += UNIX_SCHEME_LEN; |
180 | name_len -= UNIX_SCHEME_LEN; | 189 | name_len -= UNIX_SCHEME_LEN; |
181 | } | 190 | } |
182 | 191 | ||
183 | /* Allocate memory for mbox. */ | 192 | /* Allocate memory for mbox (mailbox_t). */ |
184 | mbox = calloc (1, sizeof (*mbox)); | 193 | mbox = calloc (1, sizeof (*mbox)); |
185 | if (mbox == NULL) | 194 | if (mbox == NULL) |
186 | return ENOMEM; | 195 | return ENOMEM; |
... | @@ -193,7 +202,14 @@ unix_create (mailbox_t *pmbox, const char *name) | ... | @@ -193,7 +202,14 @@ unix_create (mailbox_t *pmbox, const char *name) |
193 | return ENOMEM; | 202 | return ENOMEM; |
194 | } | 203 | } |
195 | 204 | ||
196 | /* Copy the name. */ | 205 | /* Copy the name. |
206 | We do not do any further interpretation after the scheme "unix:" | ||
207 | Because for example on distributed system like QnX4 a file name is | ||
208 | //390/etc/passwd. So the best approach is to let the OS handle it | ||
209 | for example if we receive: "unix:///var/mail/alain" the mailbox name | ||
210 | will be "///var/mail/alain" we let open() do the right thing. | ||
211 | So it will let things like this "unix://390/var/mail/alain" where | ||
212 | "//390/var/mail/alain" _is_ the filename, pass correctely. */ | ||
197 | mbox->name = calloc (name_len + 1, sizeof (char)); | 213 | mbox->name = calloc (name_len + 1, sizeof (char)); |
198 | if (mbox->name == NULL) | 214 | if (mbox->name == NULL) |
199 | { | 215 | { |
... | @@ -202,50 +218,6 @@ unix_create (mailbox_t *pmbox, const char *name) | ... | @@ -202,50 +218,6 @@ unix_create (mailbox_t *pmbox, const char *name) |
202 | } | 218 | } |
203 | memcpy (mbox->name, name, name_len); | 219 | memcpy (mbox->name, name, name_len); |
204 | 220 | ||
205 | /* Save the basename and dirname. We split the name, but this should | ||
206 | probably be supported via "maildir:" or the mailbox mgr. */ | ||
207 | sep = strrchr (name, SEPARATOR); | ||
208 | if (sep) | ||
209 | { | ||
210 | /* Split it into two. */ | ||
211 | mud->dirname = calloc ((sep - name) + 1, sizeof (char)); | ||
212 | if (mud->dirname == NULL) | ||
213 | { | ||
214 | unix_destroy (&mbox); | ||
215 | return ENOMEM; | ||
216 | } | ||
217 | memcpy (mud->dirname, name, sep - name); | ||
218 | |||
219 | ++sep; | ||
220 | mud->basename = calloc (name_len - (sep - name) + 1, sizeof (char)); | ||
221 | if (mud->basename == NULL) | ||
222 | { | ||
223 | unix_destroy (&mbox); | ||
224 | return ENOMEM; | ||
225 | } | ||
226 | memcpy (mud->basename, sep, name_len - (sep - name)); | ||
227 | } | ||
228 | else | ||
229 | { | ||
230 | /* Use the relative directory ".". */ | ||
231 | /* FIXME: should we call getcwd () instead ? */ | ||
232 | mud->dirname = calloc (2 , sizeof (char)); | ||
233 | if (mud->dirname == NULL) | ||
234 | { | ||
235 | unix_destroy (&mbox); | ||
236 | return ENOMEM; | ||
237 | } | ||
238 | mud->dirname[0] = '.'; | ||
239 | |||
240 | mud->basename = calloc (name_len + 1, sizeof (char)); | ||
241 | if (mud->basename == NULL) | ||
242 | { | ||
243 | unix_destroy (&mbox); | ||
244 | return ENOMEM; | ||
245 | } | ||
246 | memcpy (mud->basename, name, name_len); | ||
247 | } | ||
248 | |||
249 | #ifdef HAVE_PHTREAD_H | 221 | #ifdef HAVE_PHTREAD_H |
250 | /* Mutex when accessing the structure fields. */ | 222 | /* Mutex when accessing the structure fields. */ |
251 | /* FIXME: should we use rdwr locks instead ?? */ | 223 | /* FIXME: should we use rdwr locks instead ?? */ |
... | @@ -270,8 +242,8 @@ unix_create (mailbox_t *pmbox, const char *name) | ... | @@ -270,8 +242,8 @@ unix_create (mailbox_t *pmbox, const char *name) |
270 | 242 | ||
271 | mbox->_size = unix_size; | 243 | mbox->_size = unix_size; |
272 | 244 | ||
273 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, "unix_create (%s/%s)\n", | 245 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, "unix_create(%s)\n", |
274 | mud->dirname, mud->basename); | 246 | mbox->name); |
275 | (*pmbox) = mbox; | 247 | (*pmbox) = mbox; |
276 | 248 | ||
277 | return 0; /* okdoke */ | 249 | return 0; /* okdoke */ |
... | @@ -289,10 +261,7 @@ unix_destroy (mailbox_t *pmbox) | ... | @@ -289,10 +261,7 @@ unix_destroy (mailbox_t *pmbox) |
289 | size_t i; | 261 | size_t i; |
290 | unix_data_t mud = mbox->data; | 262 | unix_data_t mud = mbox->data; |
291 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, | 263 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, |
292 | "unix_destroy (%s/%s)\n", | 264 | "unix_destroy (%s/%s)\n", mbox->name); |
293 | mud->dirname, mud->basename); | ||
294 | free (mud->dirname); | ||
295 | free (mud->basename); | ||
296 | for (i = 0; i < mud->umessages_count; i++) | 265 | for (i = 0; i < mud->umessages_count; i++) |
297 | { | 266 | { |
298 | unix_message_t mum = mud->umessages[i]; | 267 | unix_message_t mum = mud->umessages[i]; |
... | @@ -331,11 +300,10 @@ unix_destroy (mailbox_t *pmbox) | ... | @@ -331,11 +300,10 @@ unix_destroy (mailbox_t *pmbox) |
331 | static int | 300 | static int |
332 | unix_open (mailbox_t mbox, int flags) | 301 | unix_open (mailbox_t mbox, int flags) |
333 | { | 302 | { |
334 | unix_data_t mud; | 303 | unix_data_t mud = mbox->data; |
335 | int status = 0; | 304 | int status = 0; |
336 | 305 | ||
337 | if (mbox == NULL || | 306 | if (mud == NULL) |
338 | (mud = (unix_data_t)mbox->data) == NULL) | ||
339 | return EINVAL; | 307 | return EINVAL; |
340 | 308 | ||
341 | /* Authentication prologues. */ | 309 | /* Authentication prologues. */ |
... | @@ -384,10 +352,10 @@ unix_open (mailbox_t mbox, int flags) | ... | @@ -384,10 +352,10 @@ unix_open (mailbox_t mbox, int flags) |
384 | static int | 352 | static int |
385 | unix_close (mailbox_t mbox) | 353 | unix_close (mailbox_t mbox) |
386 | { | 354 | { |
387 | unix_data_t mud; | 355 | unix_data_t mud = mbox->data; |
388 | size_t i; | 356 | size_t i; |
389 | 357 | ||
390 | if (mbox == NULL || (mud = (unix_data_t)mbox->data) == NULL) | 358 | if (mud == NULL) |
391 | return EINVAL; | 359 | return EINVAL; |
392 | 360 | ||
393 | /* Make sure we do not hold any lock for that file. */ | 361 | /* Make sure we do not hold any lock for that file. */ |
... | @@ -428,13 +396,15 @@ unix_scan (mailbox_t mbox, size_t msgno, size_t *pcount) | ... | @@ -428,13 +396,15 @@ unix_scan (mailbox_t mbox, size_t msgno, size_t *pcount) |
428 | 396 | ||
429 | /* FIXME: How to handle a shrink ? meaning, the &^$^@%#@^& user start two | 397 | /* FIXME: How to handle a shrink ? meaning, the &^$^@%#@^& user start two |
430 | browsers and delete files in one. My views is that we should scream | 398 | browsers and delete files in one. My views is that we should scream |
431 | bloody murder and hunt them with a machette. */ | 399 | bloody murder and hunt them with a machette. But for now just play dumb, |
400 | but maybe the best approach is to pack our things and leave .i.e exit(). */ | ||
432 | static int | 401 | static int |
433 | unix_is_updated (mailbox_t mbox) | 402 | unix_is_updated (mailbox_t mbox) |
434 | { | 403 | { |
435 | off_t size; | 404 | off_t size; |
436 | unix_data_t mud; | 405 | unix_data_t mud = mbox->data; |
437 | if (mbox == NULL || (mud = (unix_data_t) mbox->data) == NULL) | 406 | |
407 | if (mud == NULL) | ||
438 | return EINVAL; | 408 | return EINVAL; |
439 | if (stream_size (mbox->stream, &size) != 0) | 409 | if (stream_size (mbox->stream, &size) != 0) |
440 | return 0; | 410 | return 0; |
... | @@ -444,10 +414,10 @@ unix_is_updated (mailbox_t mbox) | ... | @@ -444,10 +414,10 @@ unix_is_updated (mailbox_t mbox) |
444 | static int | 414 | static int |
445 | unix_num_deleted (mailbox_t mbox, size_t *pnum) | 415 | unix_num_deleted (mailbox_t mbox, size_t *pnum) |
446 | { | 416 | { |
447 | unix_data_t mud; | 417 | unix_data_t mud = mbox->data; |
448 | unix_message_t mum; | 418 | unix_message_t mum; |
449 | size_t i, total; | 419 | size_t i, total; |
450 | if (mbox == NULL || (mud = (unix_data_t) mbox->data) == NULL) | 420 | if (mud == NULL) |
451 | return EINVAL; | 421 | return EINVAL; |
452 | for (i = total = 0; i < mud->messages_count; i++) | 422 | for (i = total = 0; i < mud->messages_count; i++) |
453 | { | 423 | { |
... | @@ -462,15 +432,14 @@ unix_num_deleted (mailbox_t mbox, size_t *pnum) | ... | @@ -462,15 +432,14 @@ unix_num_deleted (mailbox_t mbox, size_t *pnum) |
462 | } | 432 | } |
463 | 433 | ||
464 | /* FIXME: the use of tmpfile() on some system can lead to race condition, We | 434 | /* FIXME: the use of tmpfile() on some system can lead to race condition, We |
465 | should use a safer approach. We take a very naive approach for this, it | 435 | should use a safer approach. */ |
466 | involves unfortunately two copies. */ | ||
467 | static FILE * | 436 | static FILE * |
468 | unix_tmpfile (mailbox_t mbox, char **pbox) | 437 | unix_tmpfile (mailbox_t mbox, char **pbox) |
469 | { | 438 | { |
470 | const char *tmpdir; | 439 | const char *tmpdir; |
471 | int fd; | 440 | int fd; |
472 | FILE *fp; | 441 | FILE *fp; |
473 | unix_data_t mud = (unix_data_t)mbox->data; | 442 | const char *basename; |
474 | 443 | ||
475 | /* P_tmpdir should be define in <stdio.h>. */ | 444 | /* P_tmpdir should be define in <stdio.h>. */ |
476 | #ifndef P_tmpdir | 445 | #ifndef P_tmpdir |
... | @@ -478,11 +447,16 @@ unix_tmpfile (mailbox_t mbox, char **pbox) | ... | @@ -478,11 +447,16 @@ unix_tmpfile (mailbox_t mbox, char **pbox) |
478 | #endif | 447 | #endif |
479 | 448 | ||
480 | tmpdir = getenv ("TEMPDIR") ? getenv ("TEMPDIR") : P_tmpdir; | 449 | tmpdir = getenv ("TEMPDIR") ? getenv ("TEMPDIR") : P_tmpdir; |
481 | *pbox = calloc (1, strlen (tmpdir) + strlen ("MBOX_") + | 450 | basename = strrchr (mbox->name, '/'); |
482 | strlen (mud->basename) + 1); | 451 | if (basename) |
452 | basename++; | ||
453 | else | ||
454 | basename = mbox->name; | ||
455 | *pbox = calloc (strlen (tmpdir) + strlen ("MBOX_") + | ||
456 | strlen (basename) + 1, sizeof (char)); | ||
483 | if (*pbox == NULL) | 457 | if (*pbox == NULL) |
484 | return NULL; | 458 | return NULL; |
485 | sprintf (*pbox, "%s/%s%s", tmpdir, "MBOX_", mud->basename); | 459 | sprintf (*pbox, "%s/%s%s", tmpdir, "MBOX_", basename); |
486 | 460 | ||
487 | /* FIXME: I don't think this is the righ approach, creating an anonymous | 461 | /* FIXME: I don't think this is the righ approach, creating an anonymous |
488 | file would be better ? no trace left behind. */ | 462 | file would be better ? no trace left behind. */ |
... | @@ -508,10 +482,21 @@ unix_tmpfile (mailbox_t mbox, char **pbox) | ... | @@ -508,10 +482,21 @@ unix_tmpfile (mailbox_t mbox, char **pbox) |
508 | return fp; | 482 | return fp; |
509 | } | 483 | } |
510 | 484 | ||
485 | /* For the expunge bits we took a very cautionnary approach, meaning | ||
486 | we create temporary file in the tmpdir copy all the file not mark deleted, | ||
487 | and skip the deleted ones, truncate the real mailbox to the desired size | ||
488 | and overwrite with the tmp mailbox. The approach to do everyting | ||
489 | in core is tempting but require to much memory, it is not rare now | ||
490 | a day to have 30 Megs mailbox, also there is danger for filesystems | ||
491 | with quotas, or some program may not respect the advisory lock and | ||
492 | decide to append a new message while your expunging etc ... | ||
493 | The real downside to the approach we take is that when things go wrong | ||
494 | the temporary file bay be left in /tmp, which is not all that bad | ||
495 | because at least have something to recuparate when failure. */ | ||
511 | static int | 496 | static int |
512 | unix_expunge (mailbox_t mbox) | 497 | unix_expunge (mailbox_t mbox) |
513 | { | 498 | { |
514 | unix_data_t mud; | 499 | unix_data_t mud = mbox->data; |
515 | unix_message_t mum; | 500 | unix_message_t mum; |
516 | int status = 0; | 501 | int status = 0; |
517 | sigset_t sigset; | 502 | sigset_t sigset; |
... | @@ -523,7 +508,7 @@ unix_expunge (mailbox_t mbox) | ... | @@ -523,7 +508,7 @@ unix_expunge (mailbox_t mbox) |
523 | char buffer [BUFSIZ]; | 508 | char buffer [BUFSIZ]; |
524 | char *tmpmbox = NULL; | 509 | char *tmpmbox = NULL; |
525 | 510 | ||
526 | if (mbox == NULL || (mud = (unix_data_t)mbox->data) == NULL) | 511 | if (mud == NULL) |
527 | return EINVAL; | 512 | return EINVAL; |
528 | 513 | ||
529 | /* Noop. */ | 514 | /* Noop. */ |
... | @@ -569,7 +554,11 @@ unix_expunge (mailbox_t mbox) | ... | @@ -569,7 +554,11 @@ unix_expunge (mailbox_t mbox) |
569 | /* Create a tempory file. */ | 554 | /* Create a tempory file. */ |
570 | tempfile = unix_tmpfile (mbox, &tmpmbox); | 555 | tempfile = unix_tmpfile (mbox, &tmpmbox); |
571 | if (tempfile == NULL) | 556 | if (tempfile == NULL) |
557 | { | ||
558 | fprintf (stderr, "Failed to create temporary file when expunging.\n"); | ||
559 | free (tmpmbox); | ||
572 | return errno; | 560 | return errno; |
561 | } | ||
573 | 562 | ||
574 | /* Get the lock. */ | 563 | /* Get the lock. */ |
575 | if (unix_lock (mbox, MU_LOCKER_WRLOCK) < 0) | 564 | if (unix_lock (mbox, MU_LOCKER_WRLOCK) < 0) |
... | @@ -640,9 +629,9 @@ unix_expunge (mailbox_t mbox) | ... | @@ -640,9 +629,9 @@ unix_expunge (mailbox_t mbox) |
640 | { | 629 | { |
641 | if (status == 0) | 630 | if (status == 0) |
642 | status = errno; | 631 | status = errno; |
643 | fprintf (stderr, "expunge:%d: (%s)\n", __LINE__, | 632 | fprintf (stderr, "Error expunge:%d: (%s)\n", __LINE__, |
644 | strerror (status)); | 633 | strerror (status)); |
645 | goto bailout; | 634 | goto bailout0; |
646 | } | 635 | } |
647 | len -= n; | 636 | len -= n; |
648 | total += n; | 637 | total += n; |
... | @@ -676,9 +665,9 @@ unix_expunge (mailbox_t mbox) | ... | @@ -676,9 +665,9 @@ unix_expunge (mailbox_t mbox) |
676 | { | 665 | { |
677 | if (status == 0) | 666 | if (status == 0) |
678 | status = errno; | 667 | status = errno; |
679 | fprintf (stderr, "expunge:%d: %s", __LINE__, | 668 | fprintf (stderr, "Error expunge:%d: %s", __LINE__, |
680 | strerror (status)); | 669 | strerror (status)); |
681 | goto bailout; | 670 | goto bailout0; |
682 | } | 671 | } |
683 | len -= n; | 672 | len -= n; |
684 | total += n; | 673 | total += n; |
... | @@ -701,9 +690,9 @@ unix_expunge (mailbox_t mbox) | ... | @@ -701,9 +690,9 @@ unix_expunge (mailbox_t mbox) |
701 | { | 690 | { |
702 | if (status == 0) | 691 | if (status == 0) |
703 | status = errno; | 692 | status = errno; |
704 | fprintf (stderr, "expunge:%d: %s", __LINE__, | 693 | fprintf (stderr, "Error expunge:%d: %s", __LINE__, |
705 | strerror (status)); | 694 | strerror (status)); |
706 | goto bailout; | 695 | goto bailout0; |
707 | } | 696 | } |
708 | len -= n; | 697 | len -= n; |
709 | total += n; | 698 | total += n; |
... | @@ -731,9 +720,9 @@ unix_expunge (mailbox_t mbox) | ... | @@ -731,9 +720,9 @@ unix_expunge (mailbox_t mbox) |
731 | { | 720 | { |
732 | if (status == 0) | 721 | if (status == 0) |
733 | status = errno; | 722 | status = errno; |
734 | fprintf (stderr, "expunge:%d: %s", __LINE__, | 723 | fprintf (stderr, "Error expunge:%d: %s", __LINE__, |
735 | strerror (status)); | 724 | strerror (status)); |
736 | goto bailout; | 725 | goto bailout0; |
737 | } | 726 | } |
738 | len -= n; | 727 | len -= n; |
739 | total += n; | 728 | total += n; |
... | @@ -755,7 +744,11 @@ unix_expunge (mailbox_t mbox) | ... | @@ -755,7 +744,11 @@ unix_expunge (mailbox_t mbox) |
755 | { | 744 | { |
756 | status = stream_write (mbox->stream, buffer, nread, offset, &n); | 745 | status = stream_write (mbox->stream, buffer, nread, offset, &n); |
757 | if (status != 0) | 746 | if (status != 0) |
747 | { | ||
748 | fprintf (stderr, "Error expunge:%d: %s\n", __LINE__, | ||
749 | strerror (status)); | ||
758 | goto bailout; | 750 | goto bailout; |
751 | } | ||
759 | nread -= n; | 752 | nread -= n; |
760 | offset += n; | 753 | offset += n; |
761 | } | 754 | } |
... | @@ -770,12 +763,12 @@ unix_expunge (mailbox_t mbox) | ... | @@ -770,12 +763,12 @@ unix_expunge (mailbox_t mbox) |
770 | status = stream_truncate (mbox->stream, total); | 763 | status = stream_truncate (mbox->stream, total); |
771 | if (status != 0) | 764 | if (status != 0) |
772 | { | 765 | { |
773 | fprintf (stderr, "expunge:%d: %s", __LINE__, | 766 | fprintf (stderr, "Error expunging:%d: %s", __LINE__, strerror (status)); |
774 | strerror (status)); | ||
775 | goto bailout; | 767 | goto bailout; |
776 | } | 768 | } |
777 | 769 | ||
778 | /* Don't remove the tmp mbox in case of errors. */ | 770 | bailout0: |
771 | /* Don't remove the tmp mbox in case of errors, when writing back. */ | ||
779 | remove (tmpmbox); | 772 | remove (tmpmbox); |
780 | 773 | ||
781 | bailout: | 774 | bailout: |
... | @@ -814,7 +807,7 @@ unix_expunge (mailbox_t mbox) | ... | @@ -814,7 +807,7 @@ unix_expunge (mailbox_t mbox) |
814 | mum->body = mum->body_end = 0; | 807 | mum->body = mum->body_end = 0; |
815 | mum->header_lines = mum->body_lines = 0; | 808 | mum->header_lines = mum->body_lines = 0; |
816 | } | 809 | } |
817 | /* This is should reset the messages_count, the last * argument 0 means | 810 | /* This is should reset the messages_count, the last argument 0 means |
818 | not to send event notification. */ | 811 | not to send event notification. */ |
819 | unix_scan0 (mbox, dirty, NULL, 0); | 812 | unix_scan0 (mbox, dirty, NULL, 0); |
820 | } | 813 | } |
... | @@ -824,9 +817,9 @@ unix_expunge (mailbox_t mbox) | ... | @@ -824,9 +817,9 @@ unix_expunge (mailbox_t mbox) |
824 | static int | 817 | static int |
825 | unix_get_fd (stream_t is, int *pfd) | 818 | unix_get_fd (stream_t is, int *pfd) |
826 | { | 819 | { |
827 | unix_message_t mum; | 820 | unix_message_t mum = is->owner; |
828 | 821 | ||
829 | if (is == NULL || (mum = is->owner) == NULL) | 822 | if (mum == NULL) |
830 | return EINVAL; | 823 | return EINVAL; |
831 | 824 | ||
832 | return stream_get_fd (mum->stream, pfd); | 825 | return stream_get_fd (mum->stream, pfd); |
... | @@ -835,9 +828,9 @@ unix_get_fd (stream_t is, int *pfd) | ... | @@ -835,9 +828,9 @@ unix_get_fd (stream_t is, int *pfd) |
835 | static int | 828 | static int |
836 | unix_get_flags (attribute_t attr, int *pflags) | 829 | unix_get_flags (attribute_t attr, int *pflags) |
837 | { | 830 | { |
838 | unix_message_t mum; | 831 | unix_message_t mum = attr->owner; |
839 | 832 | ||
840 | if (attr == NULL || (mum = attr->owner) == NULL) | 833 | if (mum == NULL) |
841 | return EINVAL; | 834 | return EINVAL; |
842 | 835 | ||
843 | if (pflags) | 836 | if (pflags) |
... | @@ -848,9 +841,9 @@ unix_get_flags (attribute_t attr, int *pflags) | ... | @@ -848,9 +841,9 @@ unix_get_flags (attribute_t attr, int *pflags) |
848 | static int | 841 | static int |
849 | unix_set_flags (attribute_t attr, int flags) | 842 | unix_set_flags (attribute_t attr, int flags) |
850 | { | 843 | { |
851 | unix_message_t mum; | 844 | unix_message_t mum = attr->owner; |
852 | 845 | ||
853 | if (attr == NULL || (mum = attr->owner) == NULL) | 846 | if (mum == NULL) |
854 | return EINVAL; | 847 | return EINVAL; |
855 | 848 | ||
856 | mum->new_flags |= flags; | 849 | mum->new_flags |= flags; |
... | @@ -860,12 +853,12 @@ unix_set_flags (attribute_t attr, int flags) | ... | @@ -860,12 +853,12 @@ unix_set_flags (attribute_t attr, int flags) |
860 | static int | 853 | static int |
861 | unix_unset_flags (attribute_t attr, int flags) | 854 | unix_unset_flags (attribute_t attr, int flags) |
862 | { | 855 | { |
863 | unix_message_t mum; | 856 | unix_message_t mum = attr->owner; |
864 | 857 | ||
865 | if (attr == NULL || (mum = attr->owner) == NULL) | 858 | if (mum == NULL) |
866 | return EINVAL; | 859 | return EINVAL; |
867 | 860 | ||
868 | mum->new_flags &= flags; | 861 | mum->new_flags &= ~flags; |
869 | return 0; | 862 | return 0; |
870 | } | 863 | } |
871 | 864 | ||
... | @@ -873,10 +866,10 @@ static int | ... | @@ -873,10 +866,10 @@ static int |
873 | unix_readstream (stream_t is, char *buffer, size_t buflen, | 866 | unix_readstream (stream_t is, char *buffer, size_t buflen, |
874 | off_t off, size_t *pnread) | 867 | off_t off, size_t *pnread) |
875 | { | 868 | { |
876 | unix_message_t mum; | 869 | unix_message_t mum = is->owner; |
877 | size_t nread = 0; | 870 | size_t nread = 0; |
878 | 871 | ||
879 | if (is == NULL || (mum = (unix_message_t)is->owner) == NULL) | 872 | if (mum == NULL) |
880 | return EINVAL; | 873 | return EINVAL; |
881 | 874 | ||
882 | if (buffer == NULL || buflen == 0) | 875 | if (buffer == NULL || buflen == 0) |
... | @@ -909,12 +902,12 @@ static int | ... | @@ -909,12 +902,12 @@ static int |
909 | unix_get_header_read (stream_t is, char *buffer, size_t len, | 902 | unix_get_header_read (stream_t is, char *buffer, size_t len, |
910 | off_t off, size_t *pnread) | 903 | off_t off, size_t *pnread) |
911 | { | 904 | { |
912 | unix_message_t mum; | 905 | unix_message_t mum = is->owner; |
913 | size_t nread = 0; | 906 | size_t nread = 0; |
914 | int status = 0; | 907 | int status = 0; |
915 | off_t ln; | 908 | off_t ln; |
916 | 909 | ||
917 | if (is == NULL || (mum = is->owner) == NULL) | 910 | if (mum == NULL) |
918 | return EINVAL; | 911 | return EINVAL; |
919 | 912 | ||
920 | ln = mum->body - (mum->header_from_end + off); | 913 | ln = mum->body - (mum->header_from_end + off); |
... | @@ -931,13 +924,35 @@ unix_get_header_read (stream_t is, char *buffer, size_t len, | ... | @@ -931,13 +924,35 @@ unix_get_header_read (stream_t is, char *buffer, size_t len, |
931 | } | 924 | } |
932 | 925 | ||
933 | static int | 926 | static int |
927 | unix_header_size (header_t header, size_t *psize) | ||
928 | { | ||
929 | unix_message_t mum = header->owner; | ||
930 | if (mum == NULL) | ||
931 | return EINVAL; | ||
932 | if (psize) | ||
933 | *psize = mum->body - mum->header_from_end; | ||
934 | return 0; | ||
935 | } | ||
936 | |||
937 | static int | ||
938 | unix_header_lines (header_t header, size_t *plines) | ||
939 | { | ||
940 | unix_message_t mum = header->owner; | ||
941 | if (mum == NULL) | ||
942 | return EINVAL; | ||
943 | if (plines) | ||
944 | *plines = mum->header_lines; | ||
945 | return 0; | ||
946 | } | ||
947 | |||
948 | static int | ||
934 | unix_body_size (body_t body, size_t *psize) | 949 | unix_body_size (body_t body, size_t *psize) |
935 | { | 950 | { |
936 | unix_message_t mum = body->owner; | 951 | unix_message_t mum = body->owner; |
937 | if (mum == NULL) | 952 | if (mum == NULL) |
938 | return EINVAL; | 953 | return EINVAL; |
939 | if (psize) | 954 | if (psize) |
940 | *psize = mum->body_end - mum->body; | 955 | *psize = mum->body_end - mum->body + 1; |
941 | return 0; | 956 | return 0; |
942 | } | 957 | } |
943 | 958 | ||
... | @@ -1046,13 +1061,12 @@ static int | ... | @@ -1046,13 +1061,12 @@ static int |
1046 | unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | 1061 | unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
1047 | { | 1062 | { |
1048 | int status; | 1063 | int status; |
1049 | unix_data_t mud; | 1064 | unix_data_t mud = mbox->data; |
1050 | unix_message_t mum; | 1065 | unix_message_t mum; |
1051 | message_t msg = NULL; | 1066 | message_t msg = NULL; |
1052 | 1067 | ||
1053 | /* Sanity checks. */ | 1068 | /* Sanity checks. */ |
1054 | if (mbox == NULL || pmsg == NULL || (mud = (unix_data_t)mbox->data) == NULL | 1069 | if (pmsg == NULL || mud == NULL || (!(mud->messages_count > 0 && msgno > 0 |
1055 | || (!(mud->messages_count > 0 && msgno > 0 | ||
1056 | && msgno <= mud->messages_count))) | 1070 | && msgno <= mud->messages_count))) |
1057 | return EINVAL; | 1071 | return EINVAL; |
1058 | 1072 | ||
... | @@ -1088,6 +1102,8 @@ unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ... | @@ -1088,6 +1102,8 @@ unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
1088 | stream_set_fd (stream, unix_get_fd, mum); | 1102 | stream_set_fd (stream, unix_get_fd, mum); |
1089 | stream_set_flags (stream, MU_STREAM_READ, mum); | 1103 | stream_set_flags (stream, MU_STREAM_READ, mum); |
1090 | header_set_stream (header, stream, mum); | 1104 | header_set_stream (header, stream, mum); |
1105 | header_set_size (header, unix_header_size, mum); | ||
1106 | header_set_lines (header, unix_header_lines, mum); | ||
1091 | message_set_header (msg, header, mum); | 1107 | message_set_header (msg, header, mum); |
1092 | } | 1108 | } |
1093 | 1109 | ||
... | @@ -1143,9 +1159,8 @@ unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ... | @@ -1143,9 +1159,8 @@ unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
1143 | static int | 1159 | static int |
1144 | unix_append_message (mailbox_t mbox, message_t msg) | 1160 | unix_append_message (mailbox_t mbox, message_t msg) |
1145 | { | 1161 | { |
1146 | unix_data_t mud; | 1162 | unix_data_t mud = mbox->data; |
1147 | if (mbox == NULL || msg == NULL || | 1163 | if (msg == NULL || mud == NULL) |
1148 | (mud = (unix_data_t)mbox->data) == NULL) | ||
1149 | return EINVAL; | 1164 | return EINVAL; |
1150 | 1165 | ||
1151 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, | 1166 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, |
... | @@ -1166,53 +1181,129 @@ unix_append_message (mailbox_t mbox, message_t msg) | ... | @@ -1166,53 +1181,129 @@ unix_append_message (mailbox_t mbox, message_t msg) |
1166 | return status; | 1181 | return status; |
1167 | } | 1182 | } |
1168 | 1183 | ||
1184 | switch (mud->state) | ||
1185 | { | ||
1186 | case UNIX_NO_STATE: | ||
1187 | mud->from = calloc (128, sizeof (char)); | ||
1188 | if (mud->from == NULL) | ||
1189 | { | ||
1190 | unix_unlock (mbox); | ||
1191 | return ENOMEM; | ||
1192 | } | ||
1193 | mud->date = calloc (128, sizeof (char)); | ||
1194 | if (mud->date == NULL) | ||
1195 | { | ||
1196 | free (mud->from); | ||
1197 | mud->from = NULL; | ||
1198 | mud->state = UNIX_NO_STATE; | ||
1199 | unix_unlock (mbox); | ||
1200 | return ENOMEM; | ||
1201 | } | ||
1202 | mud->off = 0; | ||
1203 | mud->state = UNIX_STATE_FROM; | ||
1204 | |||
1205 | case UNIX_STATE_FROM: | ||
1169 | /* Generate a "From " separator. */ | 1206 | /* Generate a "From " separator. */ |
1170 | { | 1207 | { |
1171 | char from[128]; | ||
1172 | char date[128]; | ||
1173 | char *s; | 1208 | char *s; |
1174 | size_t f = 0, d = 0; | 1209 | size_t len = 0; |
1175 | *date = *from = '\0'; | 1210 | status = message_from (msg, mud->from, 127, &len); |
1176 | message_from (msg, from, sizeof (from), &f); | 1211 | if (status != 0) |
1177 | s = memchr (from, nl, f); | ||
1178 | if (s) | ||
1179 | { | 1212 | { |
1180 | *s = '\0'; | 1213 | if (status != EAGAIN) |
1181 | f--; | 1214 | { |
1215 | free (mud->from); | ||
1216 | free (mud->date); | ||
1217 | mud->date = mud->from = NULL; | ||
1218 | mud->state = UNIX_NO_STATE; | ||
1219 | unix_unlock (mbox); | ||
1182 | } | 1220 | } |
1183 | message_received (msg, date, sizeof (date), &d); | 1221 | return status; |
1184 | s = memchr (date, nl, d); | 1222 | } |
1223 | /* Nuke trailing newline. */ | ||
1224 | s = memchr (mud->from, nl, len); | ||
1185 | if (s) | 1225 | if (s) |
1186 | { | ||
1187 | *s = '\0'; | 1226 | *s = '\0'; |
1188 | d--; | 1227 | mud->state = UNIX_STATE_DATE; |
1228 | } | ||
1229 | |||
1230 | case UNIX_STATE_DATE: | ||
1231 | /* Generate a date for the "From " separator. */ | ||
1232 | { | ||
1233 | char *s; | ||
1234 | size_t len = 0; | ||
1235 | status = message_received (msg, mud->date, 127, &len); | ||
1236 | if (status != 0) | ||
1237 | { | ||
1238 | if (status != EAGAIN) | ||
1239 | { | ||
1240 | free (mud->from); | ||
1241 | free (mud->date); | ||
1242 | mud->date = mud->from = NULL; | ||
1243 | mud->state = UNIX_NO_STATE; | ||
1244 | unix_unlock (mbox); | ||
1245 | } | ||
1246 | return status; | ||
1189 | } | 1247 | } |
1190 | stream_write (mbox->stream, "From ", 5, size, &n); size += n; | 1248 | /* Nuke trailing newline. */ |
1191 | stream_write (mbox->stream, from, f, size, &n); size += n; | 1249 | s = memchr (mud->date, nl, len); |
1192 | stream_write (mbox->stream, " ", 1, size, &n); size += n; | 1250 | if (s) |
1193 | stream_write (mbox->stream, date, d, size, &n); size += n; | 1251 | *s = '\0'; |
1194 | stream_write (mbox->stream, &nl , 1, size, &n); size += n; | 1252 | /* Write the separator to the mailbox. */ |
1253 | stream_write (mbox->stream, "From ", 5, size, &n); | ||
1254 | size += n; | ||
1255 | stream_write (mbox->stream, mud->from, strlen (mud->from), size, &n); | ||
1256 | size += n; | ||
1257 | stream_write (mbox->stream, " ", 1, size, &n); | ||
1258 | size += n; | ||
1259 | stream_write (mbox->stream, mud->date, strlen (mud->date), size, &n); | ||
1260 | size += n; | ||
1261 | stream_write (mbox->stream, &nl , 1, size, &n); | ||
1262 | size += n; | ||
1263 | free (mud->from); | ||
1264 | free (mud->date); | ||
1265 | mud->from = mud->date = NULL; | ||
1266 | mud->state = UNIX_STATE_APPEND; | ||
1195 | } | 1267 | } |
1196 | 1268 | ||
1269 | case UNIX_STATE_APPEND: | ||
1197 | /* Append the Message. */ | 1270 | /* Append the Message. */ |
1198 | { | 1271 | { |
1199 | char buffer[BUFSIZ]; | 1272 | char buffer[BUFSIZ]; |
1200 | size_t nread = 0; | 1273 | size_t nread = 0; |
1201 | off_t off = 0; | ||
1202 | stream_t is; | 1274 | stream_t is; |
1203 | message_get_stream (msg, &is); | 1275 | message_get_stream (msg, &is); |
1204 | do | 1276 | do |
1205 | { | 1277 | { |
1206 | stream_read (is, buffer, sizeof (buffer), off, &nread); | 1278 | status = stream_read (is, buffer, sizeof (buffer), mud->off, |
1279 | &nread); | ||
1280 | if (status != 0) | ||
1281 | { | ||
1282 | if (status != EAGAIN) | ||
1283 | { | ||
1284 | free (mud->from); | ||
1285 | free (mud->date); | ||
1286 | mud->date = mud->from = NULL; | ||
1287 | mud->state = UNIX_NO_STATE; | ||
1288 | unix_unlock (mbox); | ||
1289 | } | ||
1290 | stream_flush (mbox->stream); | ||
1291 | return status; | ||
1292 | } | ||
1207 | stream_write (mbox->stream, buffer, nread, size, &n); | 1293 | stream_write (mbox->stream, buffer, nread, size, &n); |
1208 | off += nread; | 1294 | mud->off += nread; |
1209 | size += n; | 1295 | size += n; |
1210 | } | 1296 | } |
1211 | while (nread > 0); | 1297 | while (nread > 0); |
1212 | stream_write (mbox->stream, &nl, 1, size, &n); | 1298 | stream_write (mbox->stream, &nl, 1, size, &n); |
1213 | } | 1299 | } |
1300 | |||
1301 | default: | ||
1302 | break; | ||
1303 | } | ||
1214 | } | 1304 | } |
1215 | stream_flush (mbox->stream); | 1305 | stream_flush (mbox->stream); |
1306 | mud->state = UNIX_NO_STATE; | ||
1216 | unix_unlock (mbox); | 1307 | unix_unlock (mbox); |
1217 | return 0; | 1308 | return 0; |
1218 | } | 1309 | } |
... | @@ -1238,8 +1329,8 @@ unix_size (mailbox_t mbox, off_t *psize) | ... | @@ -1238,8 +1329,8 @@ unix_size (mailbox_t mbox, off_t *psize) |
1238 | static int | 1329 | static int |
1239 | unix_messages_count (mailbox_t mbox, size_t *pcount) | 1330 | unix_messages_count (mailbox_t mbox, size_t *pcount) |
1240 | { | 1331 | { |
1241 | unix_data_t mud; | 1332 | unix_data_t mud = mbox->data; |
1242 | if (mbox == NULL || (mud = (unix_data_t) mbox->data) == NULL) | 1333 | if (mud == NULL) |
1243 | return EINVAL; | 1334 | return EINVAL; |
1244 | 1335 | ||
1245 | if (! unix_is_updated (mbox)) | 1336 | if (! unix_is_updated (mbox)) | ... | ... |
... | @@ -153,6 +153,17 @@ message_set_body (message_t msg, body_t body, void *owner) | ... | @@ -153,6 +153,17 @@ message_set_body (message_t msg, body_t body, void *owner) |
153 | } | 153 | } |
154 | 154 | ||
155 | int | 155 | int |
156 | message_set_stream (message_t msg, stream_t stream, void *owner) | ||
157 | { | ||
158 | if (msg == NULL) | ||
159 | return EINVAL; | ||
160 | if (msg->owner != owner) | ||
161 | return EACCES; | ||
162 | msg->stream = stream; | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | int | ||
156 | message_get_stream (message_t msg, stream_t *pstream) | 167 | message_get_stream (message_t msg, stream_t *pstream) |
157 | { | 168 | { |
158 | if (msg == NULL || pstream == NULL) | 169 | if (msg == NULL || pstream == NULL) |
... | @@ -177,11 +188,26 @@ message_get_stream (message_t msg, stream_t *pstream) | ... | @@ -177,11 +188,26 @@ message_get_stream (message_t msg, stream_t *pstream) |
177 | } | 188 | } |
178 | 189 | ||
179 | int | 190 | int |
191 | message_set_lines (message_t msg, int (*_lines) | ||
192 | (message_t, size_t *), void *owner) | ||
193 | { | ||
194 | if (msg == NULL) | ||
195 | return EINVAL; | ||
196 | if (msg->owner != owner) | ||
197 | return EACCES; | ||
198 | msg->_lines = _lines; | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | int | ||
180 | message_lines (message_t msg, size_t *plines) | 203 | message_lines (message_t msg, size_t *plines) |
181 | { | 204 | { |
182 | size_t hlines, blines; | 205 | size_t hlines, blines; |
183 | if (msg == NULL) | 206 | if (msg == NULL) |
184 | return EINVAL; | 207 | return EINVAL; |
208 | /* Overload */ | ||
209 | if (msg->_lines) | ||
210 | return msg->_lines (msg, plines); | ||
185 | if (plines) | 211 | if (plines) |
186 | { | 212 | { |
187 | hlines = blines = 0; | 213 | hlines = blines = 0; |
... | @@ -193,11 +219,26 @@ message_lines (message_t msg, size_t *plines) | ... | @@ -193,11 +219,26 @@ message_lines (message_t msg, size_t *plines) |
193 | } | 219 | } |
194 | 220 | ||
195 | int | 221 | int |
222 | message_set_size (message_t msg, int (*_size) | ||
223 | (message_t, size_t *), void *owner) | ||
224 | { | ||
225 | if (msg == NULL) | ||
226 | return EINVAL; | ||
227 | if (msg->owner != owner) | ||
228 | return EACCES; | ||
229 | msg->_size = _size; | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | int | ||
196 | message_size (message_t msg, size_t *psize) | 234 | message_size (message_t msg, size_t *psize) |
197 | { | 235 | { |
198 | size_t hsize, bsize; | 236 | size_t hsize, bsize; |
199 | if (msg == NULL) | 237 | if (msg == NULL) |
200 | return EINVAL; | 238 | return EINVAL; |
239 | /* Overload ? */ | ||
240 | if (msg->_size) | ||
241 | return msg->_size (msg, psize); | ||
201 | if (psize) | 242 | if (psize) |
202 | { | 243 | { |
203 | hsize = bsize = 0; | 244 | hsize = bsize = 0; |
... | @@ -235,14 +276,14 @@ message_from (message_t msg, char *buf, size_t len, size_t *pnwrite) | ... | @@ -235,14 +276,14 @@ message_from (message_t msg, char *buf, size_t len, size_t *pnwrite) |
235 | if (msg->_from) | 276 | if (msg->_from) |
236 | return msg->_from (msg, buf, len, pnwrite); | 277 | return msg->_from (msg, buf, len, pnwrite); |
237 | 278 | ||
238 | /* can it be extracted from the FROM: */ | 279 | /* can it be extracted from the From: */ |
239 | message_get_header (msg, &header); | 280 | message_get_header (msg, &header); |
240 | status = header_get_value (header, "FROM", NULL, 0, &n); | 281 | status = header_get_value (header, MU_HEADER_FROM, NULL, 0, &n); |
241 | if (status == 0 && n != 0) | 282 | if (status == 0 && n != 0) |
242 | { | 283 | { |
243 | char *from = calloc (1, n + 1); | 284 | char *from = calloc (1, n + 1); |
244 | char *addr; | 285 | char *addr; |
245 | header_get_value (header, "FROM", from, n + 1, NULL); | 286 | header_get_value (header, MU_HEADER_FROM, from, n + 1, NULL); |
246 | if (extract_addr (from, n, &addr, &n) == 0) | 287 | if (extract_addr (from, n, &addr, &n) == 0) |
247 | { | 288 | { |
248 | n = (n > len) ? len : n; | 289 | n = (n > len) ? len : n; |
... | @@ -258,6 +299,8 @@ message_from (message_t msg, char *buf, size_t len, size_t *pnwrite) | ... | @@ -258,6 +299,8 @@ message_from (message_t msg, char *buf, size_t len, size_t *pnwrite) |
258 | return 0; | 299 | return 0; |
259 | } | 300 | } |
260 | } | 301 | } |
302 | else if (status == EAGAIN) | ||
303 | return status; | ||
261 | 304 | ||
262 | /* oops */ | 305 | /* oops */ |
263 | n = (7 > len) ? len: 7; | 306 | n = (7 > len) ? len: 7; |
... | @@ -374,16 +417,43 @@ message_set_uidl (message_t msg, int (* _get_uidl) | ... | @@ -374,16 +417,43 @@ message_set_uidl (message_t msg, int (* _get_uidl) |
374 | } | 417 | } |
375 | 418 | ||
376 | int | 419 | int |
377 | message_is_mime (message_t msg) | 420 | message_set_is_multipart (message_t msg, int (*_is_multipart) |
421 | __P ((message_t, int *)), void *owner) | ||
422 | { | ||
423 | if (msg == NULL) | ||
424 | return EINVAL; | ||
425 | if (msg->owner != owner) | ||
426 | return EACCES; | ||
427 | msg->_is_multipart = _is_multipart; | ||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | int | ||
432 | message_is_multipart (message_t msg, int *p_is_mp) | ||
378 | { | 433 | { |
379 | header_t header; | 434 | header_t header; |
380 | int status; | 435 | int status; |
436 | size_t len = 0; | ||
381 | 437 | ||
382 | status = message_get_header(msg, &header); | 438 | if (msg == NULL || p_is_mp) |
383 | if (status != 0) | 439 | return EINVAL; |
440 | |||
441 | message_get_header(msg, &header); | ||
442 | status = header_get_value (header, "Content-Type", NULL, 0, &len); | ||
443 | if (status == 0) | ||
444 | { | ||
445 | char *content_type = calloc (len + 1, sizeof (char)); | ||
446 | if (content_type == NULL) | ||
447 | return ENOMEM; | ||
448 | status = header_get_value (header, "Content-Type", content_type, | ||
449 | len, NULL); | ||
450 | *p_is_mp = strncasecmp ("multipart", content_type, | ||
451 | strlen ("multipart")) ? 0: 1; | ||
452 | free (content_type); | ||
453 | } | ||
454 | else | ||
455 | *p_is_mp = 0; | ||
384 | return status; | 456 | return status; |
385 | status = header_get_value (header, "Mime-Version", NULL, 0, NULL); | ||
386 | return (status == 0); | ||
387 | } | 457 | } |
388 | 458 | ||
389 | int | 459 | int |
... | @@ -422,6 +492,7 @@ message_get_part (message_t msg, size_t part, message_t *pmsg) | ... | @@ -422,6 +492,7 @@ message_get_part (message_t msg, size_t part, message_t *pmsg) |
422 | if (msg == NULL || pmsg == NULL) | 492 | if (msg == NULL || pmsg == NULL) |
423 | return EINVAL; | 493 | return EINVAL; |
424 | 494 | ||
495 | /* Overload. */ | ||
425 | if (msg->_get_part) | 496 | if (msg->_get_part) |
426 | return msg->_get_part (msg, part, pmsg); | 497 | return msg->_get_part (msg, part, pmsg); |
427 | 498 | ||
... | @@ -518,12 +589,11 @@ static int | ... | @@ -518,12 +589,11 @@ static int |
518 | message_read (stream_t is, char *buf, size_t buflen, | 589 | message_read (stream_t is, char *buf, size_t buflen, |
519 | off_t off, size_t *pnread ) | 590 | off_t off, size_t *pnread ) |
520 | { | 591 | { |
521 | message_t msg; | 592 | message_t msg = is->owner; |
522 | stream_t his, bis; | 593 | stream_t his, bis; |
523 | size_t hread, hsize, bread, bsize; | 594 | size_t hread, hsize, bread, bsize; |
524 | 595 | ||
525 | 596 | if (msg == NULL) | |
526 | if (is == NULL || (msg = is->owner) == NULL) | ||
527 | return EINVAL; | 597 | return EINVAL; |
528 | 598 | ||
529 | bsize = hsize = bread = hread = 0; | 599 | bsize = hsize = bread = hread = 0; |
... | @@ -536,16 +606,10 @@ message_read (stream_t is, char *buf, size_t buflen, | ... | @@ -536,16 +606,10 @@ message_read (stream_t is, char *buf, size_t buflen, |
536 | until you start reading them. So by checking hsize == bsize == 0, | 606 | until you start reading them. So by checking hsize == bsize == 0, |
537 | this kludge is a way of detecting the anomalie and start by the | 607 | this kludge is a way of detecting the anomalie and start by the |
538 | header. */ | 608 | header. */ |
539 | if ((size_t)off <= hsize || (hsize == 0 && bsize == 0)) | 609 | if ((size_t)off < hsize || (hsize == 0 && bsize == 0)) |
540 | { | 610 | { |
541 | header_get_stream (msg->header, &his); | 611 | header_get_stream (msg->header, &his); |
542 | stream_read (his, buf, buflen, off, &hread); | 612 | stream_read (his, buf, buflen, off, &hread); |
543 | /* still room left for some body, .. a pun ;-) */ | ||
544 | if ((buflen - hread) > 0) | ||
545 | { | ||
546 | body_get_stream (msg->body, &bis); | ||
547 | stream_read (bis, buf + hread, buflen - hread, 0, &bread); | ||
548 | } | ||
549 | } | 613 | } |
550 | else | 614 | else |
551 | { | 615 | { | ... | ... |
-
Please register or sign in to post a comment