Finish pop3 mailbox implementation.
* mailbox/msgscan.c: New file. * mailbox/Makefile.am (libmailutils_la_SOURCES): Add it. * include/mailutils/body.h (mu_body_set_get_stream): New prototype. * include/mailutils/message.h (MU_SCAN_SEEK, MU_SCAN_SIZE): New defines. (mu_message_scan): New structure. (mu_stream_scan_message): New prototype. (mu_message_set_get_stream): New prototype. * include/mailutils/stream.h (mu_stream_copy): Change signature: takes 4 arguments now. * include/mailutils/sys/body.h (_mu_body) <_get_stream>: New method. * include/mailutils/sys/message.h (_mu_message) <_get_stream>: New method. * mailbox/body.c (_body_get_stream): Call _get_stream, if provided. * mailbox/message.c (_message_get_stream): Call _get_stream, if provided. * mailbox/stream.c (_stream_flush_buffer): Avoid infinite recursion: call stream->seek directly. * mailbox/streamcpy.c (mu_stream_copy): Return the number of bytes actually copied in the fourth argument. All uses updated. * mailbox/streamref.c (streamref_return): Do not propagate internal flags. (_streamref_readdelim): Ensure there is enough buffer space for the mu_stream_readdelim call. * libproto/pop/mbox.c: Finish client implementation. * mail/print.c (mail_print_msg): Close pager before returning on error.
Showing
30 changed files
with
287 additions
and
93 deletions
... | @@ -55,7 +55,7 @@ c_copy (mu_stream_t out, mu_stream_t in) | ... | @@ -55,7 +55,7 @@ c_copy (mu_stream_t out, mu_stream_t in) |
55 | } | 55 | } |
56 | } | 56 | } |
57 | else | 57 | else |
58 | MU_ASSERT (mu_stream_copy (out, in, 0)); | 58 | MU_ASSERT (mu_stream_copy (out, in, 0, NULL)); |
59 | mu_stream_write (out, "\n", 1, NULL); | 59 | mu_stream_write (out, "\n", 1, NULL); |
60 | mu_stream_close (out); | 60 | mu_stream_close (out); |
61 | mu_stream_close (in); | 61 | mu_stream_close (in); | ... | ... |
... | @@ -69,14 +69,14 @@ main (int argc, char * argv []) | ... | @@ -69,14 +69,14 @@ main (int argc, char * argv []) |
69 | MU_ASSERT (mu_stream_seek (in, skip_off, MU_SEEK_SET, NULL)); | 69 | MU_ASSERT (mu_stream_seek (in, skip_off, MU_SEEK_SET, NULL)); |
70 | } | 70 | } |
71 | 71 | ||
72 | MU_ASSERT (mu_stream_copy (out, in, 0)); | 72 | MU_ASSERT (mu_stream_copy (out, in, 0, NULL)); |
73 | 73 | ||
74 | if (reread_option) | 74 | if (reread_option) |
75 | { | 75 | { |
76 | mu_stream_printf (out, "rereading from %lu:\n", | 76 | mu_stream_printf (out, "rereading from %lu:\n", |
77 | (unsigned long) reread_off); | 77 | (unsigned long) reread_off); |
78 | MU_ASSERT (mu_stream_seek (in, reread_off, MU_SEEK_SET, NULL)); | 78 | MU_ASSERT (mu_stream_seek (in, reread_off, MU_SEEK_SET, NULL)); |
79 | MU_ASSERT (mu_stream_copy (out, in, 0)); | 79 | MU_ASSERT (mu_stream_copy (out, in, 0, NULL)); |
80 | } | 80 | } |
81 | 81 | ||
82 | mu_stream_close (in); | 82 | mu_stream_close (in); | ... | ... |
... | @@ -152,7 +152,7 @@ sc2string (int rc) | ... | @@ -152,7 +152,7 @@ sc2string (int rc) |
152 | int | 152 | int |
153 | io_copy_out (mu_stream_t str, size_t size) | 153 | io_copy_out (mu_stream_t str, size_t size) |
154 | { | 154 | { |
155 | return mu_stream_copy (iostream, str, size); | 155 | return mu_stream_copy (iostream, str, size, NULL); |
156 | } | 156 | } |
157 | 157 | ||
158 | int | 158 | int | ... | ... |
... | @@ -36,7 +36,10 @@ extern int mu_body_get_stream (mu_body_t, mu_stream_t *) | ... | @@ -36,7 +36,10 @@ extern int mu_body_get_stream (mu_body_t, mu_stream_t *) |
36 | __attribute__ ((deprecated)); | 36 | __attribute__ ((deprecated)); |
37 | extern int mu_body_get_streamref (mu_body_t body, mu_stream_t *pstream); | 37 | extern int mu_body_get_streamref (mu_body_t body, mu_stream_t *pstream); |
38 | extern int mu_body_set_stream (mu_body_t, mu_stream_t, void *owner); | 38 | extern int mu_body_set_stream (mu_body_t, mu_stream_t, void *owner); |
39 | 39 | extern int mu_body_set_get_stream (mu_body_t, | |
40 | int (*) (mu_body_t, mu_stream_t *), | ||
41 | void *owner); | ||
42 | |||
40 | extern int mu_body_get_filename (mu_body_t, char *, size_t, size_t *); | 43 | extern int mu_body_get_filename (mu_body_t, char *, size_t, size_t *); |
41 | 44 | ||
42 | extern int mu_body_size (mu_body_t, size_t *); | 45 | extern int mu_body_size (mu_body_t, size_t *); | ... | ... |
... | @@ -26,6 +26,25 @@ | ... | @@ -26,6 +26,25 @@ |
26 | extern "C" { | 26 | extern "C" { |
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | #define MU_SCAN_SEEK 0x01 | ||
30 | #define MU_SCAN_SIZE 0x02 | ||
31 | |||
32 | struct mu_message_scan | ||
33 | { | ||
34 | int flags; | ||
35 | mu_off_t message_start; | ||
36 | mu_off_t message_size; | ||
37 | |||
38 | mu_off_t body_start; | ||
39 | mu_off_t body_end; | ||
40 | size_t header_lines; | ||
41 | size_t body_lines; | ||
42 | int attr_flags; | ||
43 | unsigned long uidvalidity; | ||
44 | }; | ||
45 | |||
46 | int mu_stream_scan_message (mu_stream_t stream, struct mu_message_scan *sp); | ||
47 | |||
29 | /* A message is considered to be a container for: | 48 | /* A message is considered to be a container for: |
30 | mu_header_t, mu_body_t, and its mu_attribute_t. */ | 49 | mu_header_t, mu_body_t, and its mu_attribute_t. */ |
31 | 50 | ||
... | @@ -34,7 +53,7 @@ extern void mu_message_destroy (mu_message_t *, void *owner); | ... | @@ -34,7 +53,7 @@ extern void mu_message_destroy (mu_message_t *, void *owner); |
34 | 53 | ||
35 | extern int mu_message_create_copy (mu_message_t *to, mu_message_t from); | 54 | extern int mu_message_create_copy (mu_message_t *to, mu_message_t from); |
36 | 55 | ||
37 | extern void * mu_message_get_owner (mu_message_t); | 56 | extern void *mu_message_get_owner (mu_message_t); |
38 | extern int mu_message_is_modified (mu_message_t); | 57 | extern int mu_message_is_modified (mu_message_t); |
39 | extern int mu_message_clear_modified (mu_message_t); | 58 | extern int mu_message_clear_modified (mu_message_t); |
40 | extern int mu_message_get_mailbox (mu_message_t, mu_mailbox_t *); | 59 | extern int mu_message_get_mailbox (mu_message_t, mu_mailbox_t *); |
... | @@ -64,6 +83,9 @@ extern int mu_message_set_attribute (mu_message_t, mu_attribute_t, void *); | ... | @@ -64,6 +83,9 @@ extern int mu_message_set_attribute (mu_message_t, mu_attribute_t, void *); |
64 | 83 | ||
65 | extern int mu_message_get_observable (mu_message_t, mu_observable_t *); | 84 | extern int mu_message_get_observable (mu_message_t, mu_observable_t *); |
66 | 85 | ||
86 | extern int mu_message_set_get_stream (mu_message_t, | ||
87 | int (*) (mu_message_t, mu_stream_t *), | ||
88 | void *); | ||
67 | extern int mu_message_is_multipart (mu_message_t, int *); | 89 | extern int mu_message_is_multipart (mu_message_t, int *); |
68 | extern int mu_message_set_is_multipart (mu_message_t, | 90 | extern int mu_message_set_is_multipart (mu_message_t, |
69 | int (*_is_multipart) (mu_message_t, | 91 | int (*_is_multipart) (mu_message_t, | ... | ... |
... | @@ -115,7 +115,8 @@ int mu_stream_clr_flags (mu_stream_t stream, int fl); | ... | @@ -115,7 +115,8 @@ int mu_stream_clr_flags (mu_stream_t stream, int fl); |
115 | int mu_stream_vprintf (mu_stream_t str, const char *fmt, va_list ap); | 115 | int mu_stream_vprintf (mu_stream_t str, const char *fmt, va_list ap); |
116 | int mu_stream_printf (mu_stream_t stream, const char *fmt, ...); | 116 | int mu_stream_printf (mu_stream_t stream, const char *fmt, ...); |
117 | 117 | ||
118 | int mu_stream_copy (mu_stream_t dst, mu_stream_t src, size_t size); | 118 | int mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size, |
119 | mu_off_t *pcsz); | ||
119 | 120 | ||
120 | 121 | ||
121 | int mu_file_stream_create (mu_stream_t *pstream, const char *filename, int flags); | 122 | int mu_file_stream_create (mu_stream_t *pstream, const char *filename, int flags); | ... | ... |
... | @@ -40,6 +40,7 @@ struct _mu_body | ... | @@ -40,6 +40,7 @@ struct _mu_body |
40 | 40 | ||
41 | int (*_size) (mu_body_t, size_t*); | 41 | int (*_size) (mu_body_t, size_t*); |
42 | int (*_lines) (mu_body_t, size_t*); | 42 | int (*_lines) (mu_body_t, size_t*); |
43 | int (*_get_stream) (mu_body_t, mu_stream_t *); | ||
43 | }; | 44 | }; |
44 | 45 | ||
45 | #ifdef __cplusplus | 46 | #ifdef __cplusplus | ... | ... |
... | @@ -52,6 +52,7 @@ struct _mu_message | ... | @@ -52,6 +52,7 @@ struct _mu_message |
52 | /* Reference count. */ | 52 | /* Reference count. */ |
53 | int ref; | 53 | int ref; |
54 | 54 | ||
55 | int (*_get_stream) (mu_message_t, mu_stream_t *); | ||
55 | int (*_get_uidl) (mu_message_t, char *, size_t, size_t *); | 56 | int (*_get_uidl) (mu_message_t, char *, size_t, size_t *); |
56 | int (*_get_uid) (mu_message_t, size_t *); | 57 | int (*_get_uid) (mu_message_t, size_t *); |
57 | int (*_get_qid) (mu_message_t, mu_message_qid_t *); | 58 | int (*_get_qid) (mu_message_t, mu_message_qid_t *); | ... | ... |
... | @@ -219,7 +219,7 @@ SCM_DEFINE_PUBLIC (scm_mu_message_copy, "mu-message-copy", 1, 0, 0, | ... | @@ -219,7 +219,7 @@ SCM_DEFINE_PUBLIC (scm_mu_message_copy, "mu-message-copy", 1, 0, 0, |
219 | "Cannot get output stream", SCM_BOOL_F); | 219 | "Cannot get output stream", SCM_BOOL_F); |
220 | } | 220 | } |
221 | 221 | ||
222 | status = mu_stream_copy (out, in, 0); | 222 | status = mu_stream_copy (out, in, 0, NULL); |
223 | mu_stream_destroy (&in); | 223 | mu_stream_destroy (&in); |
224 | mu_stream_destroy (&out); | 224 | mu_stream_destroy (&out); |
225 | if (status) | 225 | if (status) | ... | ... |
... | @@ -252,7 +252,7 @@ mime_create_quote (mu_mime_t mime, mu_message_t msg) | ... | @@ -252,7 +252,7 @@ mime_create_quote (mu_mime_t mime, mu_message_t msg) |
252 | mu_body_get_streamref (body, &ostream); | 252 | mu_body_get_streamref (body, &ostream); |
253 | mu_message_get_streamref (msg, &istream); | 253 | mu_message_get_streamref (msg, &istream); |
254 | 254 | ||
255 | rc = mu_stream_copy (ostream, istream, 0); | 255 | rc = mu_stream_copy (ostream, istream, 0, NULL); |
256 | 256 | ||
257 | mu_stream_destroy (&istream); | 257 | mu_stream_destroy (&istream); |
258 | mu_stream_close (ostream); | 258 | mu_stream_close (ostream); | ... | ... |
... | @@ -118,7 +118,7 @@ sieve_action_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags) | ... | @@ -118,7 +118,7 @@ sieve_action_pipe (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags) |
118 | ONERR (rc, _("stream write failed"), NULL); | 118 | ONERR (rc, _("stream write failed"), NULL); |
119 | } | 119 | } |
120 | 120 | ||
121 | rc = mu_stream_copy (pstr, mstr, 0); | 121 | rc = mu_stream_copy (pstr, mstr, 0, NULL); |
122 | ONERR (rc, _("command failed"), cmd); | 122 | ONERR (rc, _("command failed"), cmd); |
123 | } | 123 | } |
124 | while (0); | 124 | while (0); | ... | ... |
... | @@ -117,7 +117,7 @@ spamd_send_message (mu_stream_t stream, mu_message_t msg) | ... | @@ -117,7 +117,7 @@ spamd_send_message (mu_stream_t stream, mu_message_t msg) |
117 | return rc; | 117 | return rc; |
118 | } | 118 | } |
119 | 119 | ||
120 | rc = mu_stream_copy (stream, flt, 0); | 120 | rc = mu_stream_copy (stream, flt, 0, NULL); |
121 | 121 | ||
122 | mu_stream_destroy (&mstr); | 122 | mu_stream_destroy (&mstr); |
123 | mu_stream_destroy (&flt); | 123 | mu_stream_destroy (&flt); | ... | ... |
... | @@ -111,7 +111,7 @@ build_mime (mu_sieve_machine_t mach, mu_list_t tags, mu_mime_t *pmime, | ... | @@ -111,7 +111,7 @@ build_mime (mu_sieve_machine_t mach, mu_list_t tags, mu_mime_t *pmime, |
111 | } | 111 | } |
112 | 112 | ||
113 | mu_stream_seek (input, 0, MU_SEEK_SET, NULL); | 113 | mu_stream_seek (input, 0, MU_SEEK_SET, NULL); |
114 | rc = mu_stream_copy (stream, input, 0); | 114 | rc = mu_stream_copy (stream, input, 0, NULL); |
115 | if (rc) | 115 | if (rc) |
116 | { | 116 | { |
117 | mu_sieve_error (mach, | 117 | mu_sieve_error (mach, | ... | ... |
... | @@ -1086,7 +1086,7 @@ append_message_to_stream (mu_stream_t ostr, mu_message_t msg, | ... | @@ -1086,7 +1086,7 @@ append_message_to_stream (mu_stream_t ostr, mu_message_t msg, |
1086 | if (status) | 1086 | if (status) |
1087 | return status; | 1087 | return status; |
1088 | } | 1088 | } |
1089 | status = mu_stream_copy (ostr, istr, 0); | 1089 | status = mu_stream_copy (ostr, istr, 0, NULL); |
1090 | mu_stream_destroy (&istr); | 1090 | mu_stream_destroy (&istr); |
1091 | if (status == 0) | 1091 | if (status == 0) |
1092 | status = mu_stream_write (ostr, "\n", 1, NULL); | 1092 | status = mu_stream_write (ostr, "\n", 1, NULL); |
... | @@ -1264,7 +1264,7 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, | ... | @@ -1264,7 +1264,7 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, |
1264 | return status; | 1264 | return status; |
1265 | } | 1265 | } |
1266 | status = mu_stream_copy (tempstr, mailbox->stream, | 1266 | status = mu_stream_copy (tempstr, mailbox->stream, |
1267 | mum->body_end - mum->envel_from); | 1267 | mum->body_end - mum->envel_from, NULL); |
1268 | if (status) | 1268 | if (status) |
1269 | { | 1269 | { |
1270 | mu_error (_("%s:%d: error copying: %s"), | 1270 | mu_error (_("%s:%d: error copying: %s"), |
... | @@ -1295,7 +1295,7 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, | ... | @@ -1295,7 +1295,7 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, |
1295 | return status; | 1295 | return status; |
1296 | } | 1296 | } |
1297 | 1297 | ||
1298 | status = mu_stream_copy (tempstr, mailbox->stream, len); | 1298 | status = mu_stream_copy (tempstr, mailbox->stream, len, NULL); |
1299 | if (status) | 1299 | if (status) |
1300 | { | 1300 | { |
1301 | mu_error (_("%s:%d: error writing to temporary stream: %s"), | 1301 | mu_error (_("%s:%d: error writing to temporary stream: %s"), |
... | @@ -1342,7 +1342,7 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, | ... | @@ -1342,7 +1342,7 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, |
1342 | return status; | 1342 | return status; |
1343 | } | 1343 | } |
1344 | 1344 | ||
1345 | status = mu_stream_copy (mailbox->stream, tempstr, size); | 1345 | status = mu_stream_copy (mailbox->stream, tempstr, size, NULL); |
1346 | if (status) | 1346 | if (status) |
1347 | { | 1347 | { |
1348 | mu_error (_("%s:%d: copying from the temporary stream: %s"), | 1348 | mu_error (_("%s:%d: copying from the temporary stream: %s"), | ... | ... |
This diff is collapsed.
Click to expand it.
... | @@ -424,7 +424,7 @@ run_metamail (const char *mailcap_cmd, mu_message_t mesg) | ... | @@ -424,7 +424,7 @@ run_metamail (const char *mailcap_cmd, mu_message_t mesg) |
424 | mu_error ("mu_stream_open: %s", mu_strerror (status)); | 424 | mu_error ("mu_stream_open: %s", mu_strerror (status)); |
425 | break; | 425 | break; |
426 | } | 426 | } |
427 | mu_stream_copy (pstr, stream, 0); | 427 | mu_stream_copy (pstr, stream, 0, NULL); |
428 | mu_stream_close (pstr); | 428 | mu_stream_close (pstr); |
429 | mu_stream_destroy (&pstr); | 429 | mu_stream_destroy (&pstr); |
430 | exit (0); | 430 | exit (0); | ... | ... |
... | @@ -98,6 +98,8 @@ mail_print_msg (msgset_t *mspec, mu_message_t mesg, void *data) | ... | @@ -98,6 +98,8 @@ mail_print_msg (msgset_t *mspec, mu_message_t mesg, void *data) |
98 | if (status) | 98 | if (status) |
99 | { | 99 | { |
100 | mu_error (_("get_stream error: %s"), mu_strerror (status)); | 100 | mu_error (_("get_stream error: %s"), mu_strerror (status)); |
101 | if (out != ofile) | ||
102 | pclose (out); | ||
101 | return 0; | 103 | return 0; |
102 | } | 104 | } |
103 | 105 | ... | ... |
... | @@ -108,6 +108,7 @@ libmailutils_la_SOURCES = \ | ... | @@ -108,6 +108,7 @@ libmailutils_la_SOURCES = \ |
108 | mimehdr.c\ | 108 | mimehdr.c\ |
109 | mkfilename.c\ | 109 | mkfilename.c\ |
110 | monitor.c\ | 110 | monitor.c\ |
111 | msgscan.c\ | ||
111 | msrv.c\ | 112 | msrv.c\ |
112 | mu_auth.c\ | 113 | mu_auth.c\ |
113 | muctype.c\ | 114 | muctype.c\ | ... | ... |
... | @@ -161,36 +161,46 @@ _body_get_stream (mu_body_t body, mu_stream_t *pstream, int ref) | ... | @@ -161,36 +161,46 @@ _body_get_stream (mu_body_t body, mu_stream_t *pstream, int ref) |
161 | 161 | ||
162 | if (body->stream == NULL) | 162 | if (body->stream == NULL) |
163 | { | 163 | { |
164 | int status; | 164 | if (body->_get_stream) |
165 | struct _mu_body_stream *str = | 165 | { |
166 | (struct _mu_body_stream *) | 166 | int status = body->_get_stream (body, &body->stream); |
167 | _mu_stream_create (sizeof (*str), | 167 | if (status) |
168 | MU_STREAM_RDWR|MU_STREAM_SEEK); | 168 | return status; |
169 | if (!str) | 169 | } |
170 | return ENOMEM; | 170 | else |
171 | 171 | { | |
172 | /* Create the temporary file. */ | 172 | int status; |
173 | body->filename = mu_tempname (NULL); | 173 | struct _mu_body_stream *str = |
174 | status = mu_file_stream_create (&body->fstream, | 174 | (struct _mu_body_stream *) |
175 | body->filename, MU_STREAM_RDWR); | 175 | _mu_stream_create (sizeof (*str), |
176 | if (status != 0) | 176 | MU_STREAM_RDWR|MU_STREAM_SEEK); |
177 | return status; | 177 | if (!str) |
178 | status = mu_stream_open (body->fstream); | 178 | return ENOMEM; |
179 | if (status != 0) | 179 | |
180 | return status; | 180 | /* Create the temporary file. */ |
181 | str->stream.ctl = _body_ioctl; | 181 | body->filename = mu_tempname (NULL); |
182 | str->stream.read = _body_read; | 182 | status = mu_file_stream_create (&body->fstream, |
183 | str->stream.write = _body_write; | 183 | body->filename, MU_STREAM_RDWR); |
184 | str->stream.truncate = _body_truncate; | 184 | if (status != 0) |
185 | str->stream.size = _body_size; | 185 | return status; |
186 | str->stream.seek = _body_seek; | 186 | status = mu_stream_open (body->fstream); |
187 | str->stream.flush = _body_flush; | 187 | if (status != 0) |
188 | str->body = body; | 188 | return status; |
189 | body->stream = (mu_stream_t) str; | 189 | str->stream.ctl = _body_ioctl; |
190 | /* Override the defaults. */ | 190 | str->stream.read = _body_read; |
191 | body->_lines = _body_get_lines; | 191 | str->stream.write = _body_write; |
192 | body->_size = _body_get_size; | 192 | str->stream.truncate = _body_truncate; |
193 | str->stream.size = _body_size; | ||
194 | str->stream.seek = _body_seek; | ||
195 | str->stream.flush = _body_flush; | ||
196 | str->body = body; | ||
197 | body->stream = (mu_stream_t) str; | ||
198 | /* Override the defaults. */ | ||
199 | body->_lines = _body_get_lines; | ||
200 | body->_size = _body_get_size; | ||
201 | } | ||
193 | } | 202 | } |
203 | |||
194 | if (!ref) | 204 | if (!ref) |
195 | { | 205 | { |
196 | *pstream = body->stream; | 206 | *pstream = body->stream; |
... | @@ -227,7 +237,21 @@ mu_body_set_stream (mu_body_t body, mu_stream_t stream, void *owner) | ... | @@ -227,7 +237,21 @@ mu_body_set_stream (mu_body_t body, mu_stream_t stream, void *owner) |
227 | } | 237 | } |
228 | 238 | ||
229 | int | 239 | int |
230 | mu_body_set_lines (mu_body_t body, int (*_lines) (mu_body_t, size_t *), void *owner) | 240 | mu_body_set_get_stream (mu_body_t body, |
241 | int (*_getstr) (mu_body_t, mu_stream_t *), | ||
242 | void *owner) | ||
243 | { | ||
244 | if (body == NULL) | ||
245 | return EINVAL; | ||
246 | if (body->owner != owner) | ||
247 | return EACCES; | ||
248 | body->_get_stream = _getstr; | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | int | ||
253 | mu_body_set_lines (mu_body_t body, int (*_lines) (mu_body_t, size_t *), | ||
254 | void *owner) | ||
231 | { | 255 | { |
232 | if (body == NULL) | 256 | if (body == NULL) |
233 | return EINVAL; | 257 | return EINVAL; | ... | ... |
... | @@ -597,7 +597,7 @@ mu_message_create_copy (mu_message_t *to, mu_message_t from) | ... | @@ -597,7 +597,7 @@ mu_message_create_copy (mu_message_t *to, mu_message_t from) |
597 | return status; | 597 | return status; |
598 | } | 598 | } |
599 | 599 | ||
600 | status = mu_stream_copy (tmp, fromstr, 0); | 600 | status = mu_stream_copy (tmp, fromstr, 0, NULL); |
601 | if (status == 0) | 601 | if (status == 0) |
602 | { | 602 | { |
603 | status = mu_message_create (to, NULL); | 603 | status = mu_message_create (to, NULL); |
... | @@ -797,6 +797,8 @@ mu_message_set_stream (mu_message_t msg, mu_stream_t stream, void *owner) | ... | @@ -797,6 +797,8 @@ mu_message_set_stream (mu_message_t msg, mu_stream_t stream, void *owner) |
797 | static int | 797 | static int |
798 | _message_get_stream (mu_message_t msg, mu_stream_t *pstream, int ref) | 798 | _message_get_stream (mu_message_t msg, mu_stream_t *pstream, int ref) |
799 | { | 799 | { |
800 | int status; | ||
801 | |||
800 | if (msg == NULL) | 802 | if (msg == NULL) |
801 | return EINVAL; | 803 | return EINVAL; |
802 | if (pstream == NULL) | 804 | if (pstream == NULL) |
... | @@ -804,25 +806,33 @@ _message_get_stream (mu_message_t msg, mu_stream_t *pstream, int ref) | ... | @@ -804,25 +806,33 @@ _message_get_stream (mu_message_t msg, mu_stream_t *pstream, int ref) |
804 | 806 | ||
805 | if (msg->stream == NULL) | 807 | if (msg->stream == NULL) |
806 | { | 808 | { |
807 | int status; | 809 | if (msg->_get_stream) |
808 | mu_header_t hdr; | 810 | { |
809 | mu_body_t body; | 811 | status = msg->_get_stream (msg, &msg->stream); |
812 | if (status) | ||
813 | return status; | ||
814 | } | ||
815 | else | ||
816 | { | ||
817 | mu_header_t hdr; | ||
818 | mu_body_t body; | ||
810 | 819 | ||
811 | /* FIXME: Kind of a kludge: make sure the message has header | 820 | /* FIXME: Kind of a kludge: make sure the message has header |
812 | and body initialized. */ | 821 | and body initialized. */ |
813 | status = mu_message_get_header (msg, &hdr); | 822 | status = mu_message_get_header (msg, &hdr); |
814 | if (status) | 823 | if (status) |
815 | return status; | 824 | return status; |
816 | status = mu_message_get_body (msg, &body); | 825 | status = mu_message_get_body (msg, &body); |
817 | if (status) | 826 | if (status) |
818 | return status; | 827 | return status; |
819 | 828 | ||
820 | status = _message_stream_create (&msg->stream, msg, MU_STREAM_RDWR); | 829 | status = _message_stream_create (&msg->stream, msg, MU_STREAM_RDWR); |
821 | if (status) | 830 | if (status) |
822 | return status; | 831 | return status; |
823 | msg->flags |= MESSAGE_INTERNAL_STREAM; | 832 | msg->flags |= MESSAGE_INTERNAL_STREAM; |
833 | } | ||
824 | } | 834 | } |
825 | 835 | ||
826 | if (!ref) | 836 | if (!ref) |
827 | { | 837 | { |
828 | *pstream = msg->stream; | 838 | *pstream = msg->stream; |
... | @@ -845,6 +855,19 @@ mu_message_get_streamref (mu_message_t msg, mu_stream_t *pstream) | ... | @@ -845,6 +855,19 @@ mu_message_get_streamref (mu_message_t msg, mu_stream_t *pstream) |
845 | } | 855 | } |
846 | 856 | ||
847 | int | 857 | int |
858 | mu_message_set_get_stream (mu_message_t msg, | ||
859 | int (*_getstr) (mu_message_t, mu_stream_t *), | ||
860 | void *owner) | ||
861 | { | ||
862 | if (msg == NULL) | ||
863 | return EINVAL; | ||
864 | if (msg->owner != owner) | ||
865 | return EACCES; | ||
866 | msg->_get_stream = _getstr; | ||
867 | return 0; | ||
868 | } | ||
869 | |||
870 | int | ||
848 | mu_message_set_lines (mu_message_t msg, int (*_lines) | 871 | mu_message_set_lines (mu_message_t msg, int (*_lines) |
849 | (mu_message_t, size_t *), void *owner) | 872 | (mu_message_t, size_t *), void *owner) |
850 | { | 873 | { | ... | ... |
mailbox/msgscan.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2009, 2010 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | GNU Mailutils is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | |||
21 | #include <string.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <mailutils/types.h> | ||
24 | #include <mailutils/stream.h> | ||
25 | #include <mailutils/message.h> | ||
26 | #include <mailutils/attribute.h> | ||
27 | #include <mailutils/cstr.h> | ||
28 | |||
29 | int | ||
30 | mu_stream_scan_message (mu_stream_t stream, struct mu_message_scan *sp) | ||
31 | { | ||
32 | char buf[1024]; | ||
33 | mu_off_t off; | ||
34 | size_t n; | ||
35 | int status; | ||
36 | int in_header = 1; | ||
37 | size_t hlines = 0; | ||
38 | size_t blines = 0; | ||
39 | size_t body_start = 0; | ||
40 | int attr_flags = 0; | ||
41 | unsigned long uidvalidity = 0; | ||
42 | |||
43 | if (sp->flags & MU_SCAN_SEEK) | ||
44 | { | ||
45 | status = mu_stream_seek (stream, sp->message_start, MU_SEEK_SET, NULL); | ||
46 | if (status) | ||
47 | return status; | ||
48 | } | ||
49 | |||
50 | off = 0; | ||
51 | while (1) | ||
52 | { | ||
53 | size_t rdsize; | ||
54 | |||
55 | status = mu_stream_readline (stream, buf, sizeof (buf), &n); | ||
56 | if (status || n == 0) | ||
57 | break; | ||
58 | |||
59 | if (sp->flags & MU_SCAN_SIZE) | ||
60 | { | ||
61 | rdsize = sp->message_size - off; | ||
62 | if (n > rdsize) | ||
63 | n = rdsize; | ||
64 | } | ||
65 | |||
66 | if (in_header) | ||
67 | { | ||
68 | if (buf[0] == '\n') | ||
69 | { | ||
70 | in_header = 0; | ||
71 | body_start = off + 1; | ||
72 | } | ||
73 | if (buf[n - 1] == '\n') | ||
74 | hlines++; | ||
75 | |||
76 | /* Process particular attributes */ | ||
77 | if (mu_c_strncasecmp (buf, "status:", 7) == 0) | ||
78 | mu_string_to_flags (buf, &attr_flags); | ||
79 | else if (mu_c_strncasecmp (buf, "x-imapbase:", 11) == 0) | ||
80 | { | ||
81 | char *p; | ||
82 | uidvalidity = strtoul (buf + 11, &p, 10); | ||
83 | /* second number is next uid. Ignored */ | ||
84 | } | ||
85 | } | ||
86 | else | ||
87 | { | ||
88 | if (buf[n - 1] == '\n') | ||
89 | blines++; | ||
90 | } | ||
91 | off += n; | ||
92 | } | ||
93 | |||
94 | if (status == 0) | ||
95 | { | ||
96 | if (!body_start) | ||
97 | body_start = off; | ||
98 | sp->body_start = body_start; | ||
99 | sp->body_end = off; | ||
100 | sp->header_lines = hlines; | ||
101 | sp->body_lines = blines; | ||
102 | sp->attr_flags = attr_flags; | ||
103 | sp->uidvalidity = uidvalidity; | ||
104 | } | ||
105 | return status; | ||
106 | } |
... | @@ -48,7 +48,7 @@ rdcache_read (struct _mu_stream *str, char *buf, size_t size, size_t *pnbytes) | ... | @@ -48,7 +48,7 @@ rdcache_read (struct _mu_stream *str, char *buf, size_t size, size_t *pnbytes) |
48 | status = mu_stream_seek (sp->cache, 0, MU_SEEK_END, NULL); | 48 | status = mu_stream_seek (sp->cache, 0, MU_SEEK_END, NULL); |
49 | if (status) | 49 | if (status) |
50 | return status; | 50 | return status; |
51 | status = mu_stream_copy (sp->cache, sp->transport, left); | 51 | status = mu_stream_copy (sp->cache, sp->transport, left, NULL); |
52 | if (status) | 52 | if (status) |
53 | return status; | 53 | return status; |
54 | sp->size = sp->offset; | 54 | sp->size = sp->offset; | ... | ... |
... | @@ -153,9 +153,13 @@ _stream_flush_buffer (struct _mu_stream *stream, int all) | ... | @@ -153,9 +153,13 @@ _stream_flush_buffer (struct _mu_stream *stream, int all) |
153 | 153 | ||
154 | if (stream->flags & _MU_STR_DIRTY) | 154 | if (stream->flags & _MU_STR_DIRTY) |
155 | { | 155 | { |
156 | if ((stream->flags & MU_STREAM_SEEK) | 156 | if ((stream->flags & MU_STREAM_SEEK) && stream->seek) |
157 | && (rc = mu_stream_seek (stream, stream->offset, MU_SEEK_SET, NULL))) | 157 | { |
158 | return rc; | 158 | mu_off_t off; |
159 | rc = stream->seek (stream, stream->offset, &off); | ||
160 | if (rc) | ||
161 | return rc; | ||
162 | } | ||
159 | 163 | ||
160 | switch (stream->buftype) | 164 | switch (stream->buftype) |
161 | { | 165 | { | ... | ... |
... | @@ -31,22 +31,22 @@ | ... | @@ -31,22 +31,22 @@ |
31 | /* Copy SIZE bytes from SRC to DST. If SIZE is 0, copy everything up to | 31 | /* Copy SIZE bytes from SRC to DST. If SIZE is 0, copy everything up to |
32 | EOF. */ | 32 | EOF. */ |
33 | int | 33 | int |
34 | mu_stream_copy (mu_stream_t dst, mu_stream_t src, size_t size) | 34 | mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size, |
35 | mu_off_t *pcsz) | ||
35 | { | 36 | { |
36 | int status; | 37 | int status; |
37 | size_t bufsize, n; | 38 | size_t bufsize, n; |
38 | char *buf; | 39 | char *buf; |
39 | 40 | mu_off_t total = 0; | |
41 | |||
42 | if (pcsz) | ||
43 | *pcsz = 0; | ||
40 | if (size == 0) | 44 | if (size == 0) |
41 | { | 45 | { |
42 | mu_off_t strsize; | 46 | status = mu_stream_size (src, &size); |
43 | status = mu_stream_size (src, &strsize); | ||
44 | switch (status) | 47 | switch (status) |
45 | { | 48 | { |
46 | case 0: | 49 | case 0: |
47 | size = strsize; | ||
48 | if ((mu_off_t)size != strsize) | ||
49 | return ERANGE; | ||
50 | break; | 50 | break; |
51 | 51 | ||
52 | case ENOSYS: | 52 | case ENOSYS: |
... | @@ -105,6 +105,7 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, size_t size) | ... | @@ -105,6 +105,7 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, size_t size) |
105 | if (status) | 105 | if (status) |
106 | break; | 106 | break; |
107 | size -= rdsize; | 107 | size -= rdsize; |
108 | total += rdsize; | ||
108 | } | 109 | } |
109 | else | 110 | else |
110 | while ((status = mu_stream_read (src, buf, bufsize, &n)) == 0 | 111 | while ((status = mu_stream_read (src, buf, bufsize, &n)) == 0 |
... | @@ -113,8 +114,11 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, size_t size) | ... | @@ -113,8 +114,11 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, size_t size) |
113 | status = mu_stream_write (dst, buf, n, NULL); | 114 | status = mu_stream_write (dst, buf, n, NULL); |
114 | if (status) | 115 | if (status) |
115 | break; | 116 | break; |
117 | total += n; | ||
116 | } | 118 | } |
117 | 119 | ||
120 | if (pcsz) | ||
121 | *pcsz = total; | ||
118 | free (buf); | 122 | free (buf); |
119 | return status; | 123 | return status; |
120 | } | 124 | } | ... | ... |
... | @@ -24,13 +24,15 @@ | ... | @@ -24,13 +24,15 @@ |
24 | #include <mailutils/errno.h> | 24 | #include <mailutils/errno.h> |
25 | #include <mailutils/sys/streamref.h> | 25 | #include <mailutils/sys/streamref.h> |
26 | 26 | ||
27 | #define _MU_STR_ERRMASK (_MU_STR_ERR|_MU_STR_EOF) | ||
28 | |||
27 | static int | 29 | static int |
28 | streamref_return (struct _mu_streamref *sp, int rc) | 30 | streamref_return (struct _mu_streamref *sp, int rc) |
29 | { | 31 | { |
30 | if (rc) | 32 | if (rc) |
31 | sp->stream.last_err = sp->transport->last_err; | 33 | sp->stream.last_err = sp->transport->last_err; |
32 | sp->stream.flags = (sp->stream.flags & ~_MU_STR_INTERN_MASK) | | 34 | sp->stream.flags = (sp->stream.flags & ~_MU_STR_ERRMASK) | |
33 | (sp->transport->flags & _MU_STR_INTERN_MASK); | 35 | (sp->transport->flags & _MU_STR_ERRMASK); |
34 | return rc; | 36 | return rc; |
35 | } | 37 | } |
36 | 38 | ||
... | @@ -80,15 +82,15 @@ _streamref_readdelim (struct _mu_stream *str, char *buf, size_t bufsize, | ... | @@ -80,15 +82,15 @@ _streamref_readdelim (struct _mu_stream *str, char *buf, size_t bufsize, |
80 | rc = mu_stream_seek (sp->transport, sp->offset, MU_SEEK_SET, &off); | 82 | rc = mu_stream_seek (sp->transport, sp->offset, MU_SEEK_SET, &off); |
81 | if (rc == 0) | 83 | if (rc == 0) |
82 | { | 84 | { |
83 | if (sp->end) | ||
84 | { | ||
85 | size_t size = sp->end - off + 2; /* extra 1 to account for \0 */ | ||
86 | if (size < bufsize) | ||
87 | bufsize = size; | ||
88 | } | ||
89 | rc = mu_stream_readdelim (sp->transport, buf, bufsize, delim, &nread); | 85 | rc = mu_stream_readdelim (sp->transport, buf, bufsize, delim, &nread); |
90 | if (rc == 0) | 86 | if (rc == 0) |
91 | { | 87 | { |
88 | if (sp->end) | ||
89 | { | ||
90 | size_t size = sp->end - off + 1; | ||
91 | if (nread > size) | ||
92 | nread = size; | ||
93 | } | ||
92 | sp->offset += nread; | 94 | sp->offset += nread; |
93 | *pnread = nread; | 95 | *pnread = nread; |
94 | } | 96 | } | ... | ... |
... | @@ -496,7 +496,7 @@ msg_copy (size_t num, const char *file) | ... | @@ -496,7 +496,7 @@ msg_copy (size_t num, const char *file) |
496 | mu_mailbox_get_message (tmpbox, num, &msg); | 496 | mu_mailbox_get_message (tmpbox, num, &msg); |
497 | mu_message_get_streamref (msg, &istream); | 497 | mu_message_get_streamref (msg, &istream); |
498 | /* FIXME: Implement RFC 934 FSA? */ | 498 | /* FIXME: Implement RFC 934 FSA? */ |
499 | rc = mu_stream_copy (ostream, istream, 0); | 499 | rc = mu_stream_copy (ostream, istream, 0, NULL); |
500 | if (rc) | 500 | if (rc) |
501 | { | 501 | { |
502 | mu_error (_("copy stream error: %s"), mu_strerror (rc)); | 502 | mu_error (_("copy stream error: %s"), mu_strerror (rc)); | ... | ... |
... | @@ -171,7 +171,7 @@ copy_message (mu_mailbox_t mbox, size_t n, const char *file) | ... | @@ -171,7 +171,7 @@ copy_message (mu_mailbox_t mbox, size_t n, const char *file) |
171 | return rc; | 171 | return rc; |
172 | } | 172 | } |
173 | 173 | ||
174 | rc = mu_stream_copy (out, in, 0); | 174 | rc = mu_stream_copy (out, in, 0, NULL); |
175 | mu_stream_destroy (&in); | 175 | mu_stream_destroy (&in); |
176 | mu_stream_close (out); | 176 | mu_stream_close (out); |
177 | mu_stream_destroy (&out); | 177 | mu_stream_destroy (&out); | ... | ... |
... | @@ -1259,7 +1259,7 @@ show_internal (mu_message_t msg, msg_part_t part, char *encoding, mu_stream_t ou | ... | @@ -1259,7 +1259,7 @@ show_internal (mu_message_t msg, msg_part_t part, char *encoding, mu_stream_t ou |
1259 | MU_FILTER_DECODE, MU_STREAM_READ); | 1259 | MU_FILTER_DECODE, MU_STREAM_READ); |
1260 | if (rc == 0) | 1260 | if (rc == 0) |
1261 | bstr = dstr; | 1261 | bstr = dstr; |
1262 | rc = mu_stream_copy (out, bstr, 0); | 1262 | rc = mu_stream_copy (out, bstr, 0, NULL); |
1263 | mu_stream_destroy (&bstr); | 1263 | mu_stream_destroy (&bstr); |
1264 | return rc; | 1264 | return rc; |
1265 | } | 1265 | } |
... | @@ -2004,7 +2004,7 @@ finish_text_msg (struct compose_env *env, mu_message_t *msg, int ascii) | ... | @@ -2004,7 +2004,7 @@ finish_text_msg (struct compose_env *env, mu_message_t *msg, int ascii) |
2004 | MU_STREAM_READ); | 2004 | MU_STREAM_READ); |
2005 | if (rc == 0) | 2005 | if (rc == 0) |
2006 | { | 2006 | { |
2007 | mu_stream_copy (output, fstr, 0); | 2007 | mu_stream_copy (output, fstr, 0, NULL); |
2008 | mu_stream_destroy (&fstr); | 2008 | mu_stream_destroy (&fstr); |
2009 | mu_message_unref (*msg); | 2009 | mu_message_unref (*msg); |
2010 | *msg = newmsg; | 2010 | *msg = newmsg; |
... | @@ -2064,7 +2064,7 @@ edit_extern (char *cmd, struct compose_env *env, mu_message_t *msg, int level) | ... | @@ -2064,7 +2064,7 @@ edit_extern (char *cmd, struct compose_env *env, mu_message_t *msg, int level) |
2064 | free (id); | 2064 | free (id); |
2065 | 2065 | ||
2066 | mu_header_get_streamref (hdr2, &in); | 2066 | mu_header_get_streamref (hdr2, &in); |
2067 | mu_stream_copy (out, in, 0); | 2067 | mu_stream_copy (out, in, 0, NULL); |
2068 | mu_stream_destroy (&in); | 2068 | mu_stream_destroy (&in); |
2069 | mu_stream_close (out); | 2069 | mu_stream_close (out); |
2070 | mu_stream_destroy (&out); | 2070 | mu_stream_destroy (&out); |
... | @@ -2295,7 +2295,7 @@ edit_mime (char *cmd, struct compose_env *env, mu_message_t *msg, int level) | ... | @@ -2295,7 +2295,7 @@ edit_mime (char *cmd, struct compose_env *env, mu_message_t *msg, int level) |
2295 | 2295 | ||
2296 | mu_message_get_body (*msg, &body); | 2296 | mu_message_get_body (*msg, &body); |
2297 | mu_body_get_streamref (body, &out); | 2297 | mu_body_get_streamref (body, &out); |
2298 | mu_stream_copy (out, fstr, 0); | 2298 | mu_stream_copy (out, fstr, 0, NULL); |
2299 | 2299 | ||
2300 | mu_stream_close (out); | 2300 | mu_stream_close (out); |
2301 | mu_stream_destroy (&out); | 2301 | mu_stream_destroy (&out); |
... | @@ -2660,7 +2660,7 @@ mhn_compose () | ... | @@ -2660,7 +2660,7 @@ mhn_compose () |
2660 | mhn_header (message, msg); | 2660 | mhn_header (message, msg); |
2661 | copy_header_to_stream (message, stream); | 2661 | copy_header_to_stream (message, stream); |
2662 | mu_message_get_streamref (msg, &in); | 2662 | mu_message_get_streamref (msg, &in); |
2663 | mu_stream_copy (stream, in, 0); | 2663 | mu_stream_copy (stream, in, 0, NULL); |
2664 | mu_stream_destroy (&in); | 2664 | mu_stream_destroy (&in); |
2665 | mu_stream_destroy (&stream); | 2665 | mu_stream_destroy (&stream); |
2666 | 2666 | ... | ... |
... | @@ -46,7 +46,7 @@ pop3d_retr (char *arg) | ... | @@ -46,7 +46,7 @@ pop3d_retr (char *arg) |
46 | return ERR_UNKNOWN; | 46 | return ERR_UNKNOWN; |
47 | 47 | ||
48 | pop3d_outf ("+OK\n"); | 48 | pop3d_outf ("+OK\n"); |
49 | mu_stream_copy (iostream, stream, 0); | 49 | mu_stream_copy (iostream, stream, 0, NULL); |
50 | mu_stream_destroy (&stream); | 50 | mu_stream_destroy (&stream); |
51 | 51 | ||
52 | if (!mu_attribute_is_read (attr)) | 52 | if (!mu_attribute_is_read (attr)) | ... | ... |
... | @@ -62,7 +62,7 @@ pop3d_top (char *arg) | ... | @@ -62,7 +62,7 @@ pop3d_top (char *arg) |
62 | return ERR_UNKNOWN; | 62 | return ERR_UNKNOWN; |
63 | pop3d_outf ("+OK\n"); | 63 | pop3d_outf ("+OK\n"); |
64 | 64 | ||
65 | mu_stream_copy (iostream, stream, 0); | 65 | mu_stream_copy (iostream, stream, 0, NULL); |
66 | pop3d_outf ("\n"); | 66 | pop3d_outf ("\n"); |
67 | mu_stream_destroy (&stream); | 67 | mu_stream_destroy (&stream); |
68 | 68 | ... | ... |
-
Please register or sign in to post a comment