Commit 7bfe0ed9 7bfe0ed907c5300d68fea2f2d4e53bac6dc78b60 by Sergey Poznyakoff

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.
1 parent 62c5c62a
...@@ -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"),
......
...@@ -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 {
......
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
......