Commit dca7b761 dca7b761362545f359968be344267c3fd93cb935 by Sergey Poznyakoff

Fix mime creation and Sieve reject/redirect actions.

* examples/mta.c (finalize_option): New variable.
(message_finalize): Don't modify the message if finalize_option
is 0.
* include/mailutils/sys/message.h (_mu_message)
<orig_header_size>: New member.
* include/mailutils/sys/mime.h (_mu_mime) <part_stream>: New member.
* libmu_sieve/actions.c (mime_create_reason)
(mime_create_ds): Use mu_body_get_streamref.
(mime_create_quote): Use mu_body_get_streamref/mu_message_get_streamref.
(sieve_action_reject): Set the To: header.
* mailbox/message.c (mu_message_get_header): Set orig_header_size.
(mu_message_get_body): Use orig_header_size instead of relying
on mu_header_size.
* mailbox/mime.c (_mime_part_size): New static.
(_mime_body_stream_size): New method.
(_mime_body_seek): Rename to _mime_body_stream_seek.
(_mime_body_read): Rewrite and rename to _mime_body_stream_read.
(_mime_body_ioctl): Rename to _mime_body_stream_ioctl.
(create_mime_body_stream): Take mu_mime_t as the 2nd parameter.
Initialize sp->stream.size and sp->mime.
(_mime_body_size): Rewrite using _mime_part_size.
(mu_mime_destroy): Destroy part_stream.
* sieve/testsuite/Redirect: Reflect new mta behavior.
* sieve/testsuite/Reject: Likewise.
1 parent 66c992c3
...@@ -73,6 +73,18 @@ int dot = 1; /* Message is terminated by a lone dot on a line */ ...@@ -73,6 +73,18 @@ int dot = 1; /* Message is terminated by a lone dot on a line */
73 73
74 mu_address_t recipients = NULL; 74 mu_address_t recipients = NULL;
75 char *progname; 75 char *progname;
76 /* FIXME: If finalize_option is set, mta should try to finalize
77 received messages the way sendmail does, i.e. to add To: or
78 Cc: headers, if they are missing, etc. The code to do so is
79 already included, but the modified message is not reproduced
80 on diagnostic output because mta_send reads it from the stream,
81 which does not reflect modifications to the header.
82
83 Ideally, the mu_message_get_streamref function should notice the
84 change in the header (and/or the body) and return a temporary
85 stream, which will read the modified values. This is left as
86 as TODO for a later time. 2010-09-29, Sergey */
87 int finalize_option = 0;
76 88
77 int mta_stdin (int argc, char **argv); 89 int mta_stdin (int argc, char **argv);
78 int mta_smtp (int argc, char **argv); 90 int mta_smtp (int argc, char **argv);
...@@ -361,7 +373,7 @@ message_finalize (mu_message_t msg, int warn) ...@@ -361,7 +373,7 @@ message_finalize (mu_message_t msg, int warn)
361 373
362 mu_message_get_header (msg, &header); 374 mu_message_get_header (msg, &header);
363 375
364 if (warn && from_person) 376 if (finalize_option && warn && from_person)
365 { 377 {
366 struct passwd *pwd = getpwuid (getuid ()); 378 struct passwd *pwd = getpwuid (getuid ());
367 char *warn = malloc (strlen (pwd->pw_name) + 1 + 379 char *warn = malloc (strlen (pwd->pw_name) + 1 +
...@@ -400,7 +412,8 @@ message_finalize (mu_message_t msg, int warn) ...@@ -400,7 +412,8 @@ message_finalize (mu_message_t msg, int warn)
400 free (value); 412 free (value);
401 } 413 }
402 414
403 if (mu_header_aget_value (header, MU_HEADER_BCC, &value) == 0) 415 if (finalize_option &&
416 mu_header_aget_value (header, MU_HEADER_BCC, &value) == 0)
404 { 417 {
405 if (add_recipient (value)) 418 if (add_recipient (value))
406 { 419 {
...@@ -412,7 +425,7 @@ message_finalize (mu_message_t msg, int warn) ...@@ -412,7 +425,7 @@ message_finalize (mu_message_t msg, int warn)
412 } 425 }
413 } 426 }
414 427
415 if (!have_to) 428 if (finalize_option && !have_to)
416 { 429 {
417 size_t n; 430 size_t n;
418 int c; 431 int c;
......
...@@ -47,7 +47,8 @@ struct _mu_message ...@@ -47,7 +47,8 @@ struct _mu_message
47 mu_mime_t mime; 47 mu_mime_t mime;
48 mu_observable_t observable; 48 mu_observable_t observable;
49 mu_mailbox_t mailbox; 49 mu_mailbox_t mailbox;
50 50 size_t orig_header_size;
51
51 /* Reference count. */ 52 /* Reference count. */
52 int ref; 53 int ref;
53 54
......
...@@ -64,6 +64,7 @@ struct _mu_mime ...@@ -64,6 +64,7 @@ struct _mu_mime
64 size_t boundary_len; 64 size_t boundary_len;
65 size_t preamble; 65 size_t preamble;
66 size_t postamble; 66 size_t postamble;
67 mu_stream_t part_stream;
67 /* parser state */ 68 /* parser state */
68 char *cur_line; 69 char *cur_line;
69 ssize_t line_ndx; 70 ssize_t line_ndx;
......
...@@ -154,7 +154,7 @@ mime_create_reason (mu_mime_t mime, mu_message_t msg, const char *text) ...@@ -154,7 +154,7 @@ mime_create_reason (mu_mime_t mime, mu_message_t msg, const char *text)
154 154
155 mu_message_create (&newmsg, NULL); 155 mu_message_create (&newmsg, NULL);
156 mu_message_get_body (newmsg, &body); 156 mu_message_get_body (newmsg, &body);
157 mu_body_get_stream (body, &stream); 157 mu_body_get_streamref (body, &stream);
158 158
159 time (&t); 159 time (&t);
160 tm = localtime (&t); 160 tm = localtime (&t);
...@@ -171,6 +171,8 @@ mime_create_reason (mu_mime_t mime, mu_message_t msg, const char *text) ...@@ -171,6 +171,8 @@ mime_create_reason (mu_mime_t mime, mu_message_t msg, const char *text)
171 mu_stream_printf (stream, "Reason given was as follows:\n\n"); 171 mu_stream_printf (stream, "Reason given was as follows:\n\n");
172 mu_stream_printf (stream, "%s", text); 172 mu_stream_printf (stream, "%s", text);
173 mu_stream_close (stream); 173 mu_stream_close (stream);
174 mu_stream_destroy (&stream);
175
174 mu_header_create (&hdr, content_header, strlen (content_header)); 176 mu_header_create (&hdr, content_header, strlen (content_header));
175 mu_message_set_header (newmsg, hdr, NULL); 177 mu_message_set_header (newmsg, hdr, NULL);
176 mu_mime_add_part (mime, newmsg); 178 mu_mime_add_part (mime, newmsg);
...@@ -196,7 +198,7 @@ mime_create_ds (mu_mime_t mime, mu_message_t orig) ...@@ -196,7 +198,7 @@ mime_create_ds (mu_mime_t mime, mu_message_t orig)
196 mu_message_get_header (newmsg, &hdr); 198 mu_message_get_header (newmsg, &hdr);
197 mu_header_set_value (hdr, "Content-Type", "message/delivery-status", 1); 199 mu_header_set_value (hdr, "Content-Type", "message/delivery-status", 1);
198 mu_message_get_body (newmsg, &body); 200 mu_message_get_body (newmsg, &body);
199 mu_body_get_stream (body, &stream); 201 mu_body_get_streamref (body, &stream);
200 mu_stream_printf (stream, "Reporting-UA: sieve; %s\n", PACKAGE_STRING); 202 mu_stream_printf (stream, "Reporting-UA: sieve; %s\n", PACKAGE_STRING);
201 203
202 mu_message_get_envelope (orig, &env); 204 mu_message_get_envelope (orig, &env);
...@@ -226,7 +228,9 @@ mime_create_ds (mu_mime_t mime, mu_message_t orig) ...@@ -226,7 +228,9 @@ mime_create_ds (mu_mime_t mime, mu_message_t orig)
226 mu_stream_printf (stream, "Last-Attempt-Date: %s\n", datestr); 228 mu_stream_printf (stream, "Last-Attempt-Date: %s\n", datestr);
227 229
228 mu_stream_close (stream); 230 mu_stream_close (stream);
229 mu_mime_add_part(mime, newmsg); 231 mu_stream_destroy (&stream);
232
233 mu_mime_add_part (mime, newmsg);
230 mu_message_unref (newmsg); 234 mu_message_unref (newmsg);
231 } 235 }
232 236
...@@ -241,25 +245,30 @@ mime_create_quote (mu_mime_t mime, mu_message_t msg) ...@@ -241,25 +245,30 @@ mime_create_quote (mu_mime_t mime, mu_message_t msg)
241 size_t n; 245 size_t n;
242 char buffer[512]; 246 char buffer[512];
243 mu_body_t body; 247 mu_body_t body;
244 248 int rc;
249
245 mu_message_create (&newmsg, NULL); 250 mu_message_create (&newmsg, NULL);
246 mu_message_get_header (newmsg, &hdr); 251 mu_message_get_header (newmsg, &hdr);
247 mu_header_set_value (hdr, "Content-Type", "message/rfc822", 1); 252 mu_header_set_value (hdr, "Content-Type", "message/rfc822", 1);
248 mu_message_get_body (newmsg, &body); 253 mu_message_get_body (newmsg, &body);
249 mu_body_get_stream (body, &ostream); 254 mu_body_get_streamref (body, &ostream);
250 mu_message_get_stream (msg, &istream); 255 mu_message_get_streamref (msg, &istream);
251 256
257 rc = 0;/* FIXME: use mu_stream_copy */
252 while (mu_stream_read (istream, buffer, sizeof buffer - 1, &n) == 0 258 while (mu_stream_read (istream, buffer, sizeof buffer - 1, &n) == 0
253 && n != 0) 259 && n != 0)
254 { 260 {
255 int rc = mu_stream_write (ostream, buffer, n, NULL); 261 rc = mu_stream_write (ostream, buffer, n, NULL);
256 if (rc) 262 if (rc)
257 return EIO; 263 break;
258 } 264 }
265 mu_stream_destroy (&istream);
259 mu_stream_close (ostream); 266 mu_stream_close (ostream);
267 mu_stream_destroy (&ostream);
268
260 mu_mime_add_part (mime, newmsg); 269 mu_mime_add_part (mime, newmsg);
261 mu_message_unref (newmsg); 270 mu_message_unref (newmsg);
262 return 0; 271 return rc;
263 } 272 }
264 273
265 static int 274 static int
...@@ -292,6 +301,7 @@ sieve_action_reject (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags) ...@@ -292,6 +301,7 @@ sieve_action_reject (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
292 mu_message_t newmsg; 301 mu_message_t newmsg;
293 char *addrtext; 302 char *addrtext;
294 mu_address_t from, to; 303 mu_address_t from, to;
304 mu_header_t hdr;
295 305
296 mu_sieve_value_t *val = mu_sieve_value_get (args, 0); 306 mu_sieve_value_t *val = mu_sieve_value_get (args, 0);
297 if (!val) 307 if (!val)
...@@ -308,6 +318,9 @@ sieve_action_reject (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags) ...@@ -308,6 +318,9 @@ sieve_action_reject (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
308 mu_mime_get_message (mime, &newmsg); 318 mu_mime_get_message (mime, &newmsg);
309 319
310 mu_sieve_get_message_sender (mach->msg, &addrtext); 320 mu_sieve_get_message_sender (mach->msg, &addrtext);
321 mu_message_get_header (newmsg, &hdr);
322 mu_header_prepend (hdr, MU_HEADER_TO, addrtext);
323
311 rc = mu_address_create (&to, addrtext); 324 rc = mu_address_create (&to, addrtext);
312 if (rc) 325 if (rc)
313 { 326 {
......
...@@ -688,6 +688,9 @@ mu_message_get_header (mu_message_t msg, mu_header_t *phdr) ...@@ -688,6 +688,9 @@ mu_message_get_header (mu_message_t msg, mu_header_t *phdr)
688 return status; 688 return status;
689 if (msg->stream) 689 if (msg->stream)
690 mu_header_set_fill (header, message_header_fill, msg); 690 mu_header_set_fill (header, message_header_fill, msg);
691 status = mu_header_size (header, &msg->orig_header_size);
692 if (status)
693 return status;
691 msg->header = header; 694 msg->header = header;
692 } 695 }
693 *phdr = msg->header; 696 *phdr = msg->header;
...@@ -728,19 +731,15 @@ mu_message_get_body (mu_message_t msg, mu_body_t *pbody) ...@@ -728,19 +731,15 @@ mu_message_get_body (mu_message_t msg, mu_body_t *pbody)
728 /* FIXME: I'm not sure if the second condition is really needed */ 731 /* FIXME: I'm not sure if the second condition is really needed */
729 if (msg->stream/* && (msg->flags & MESSAGE_INTERNAL_STREAM)*/) 732 if (msg->stream/* && (msg->flags & MESSAGE_INTERNAL_STREAM)*/)
730 { 733 {
731 size_t size = 0;
732 mu_stream_t stream; 734 mu_stream_t stream;
733 int flags = 0; 735 int flags = 0;
734 736
735 /* FIXME: The size cannot be used as offset, because 737 /* FIXME: The actual mu_header_size cannot be used as offset,
736 the headers might have been modified in between. */ 738 because the headers might have been modified in between. */
737 status = mu_header_size (msg->header, &size);
738 if (status)
739 return status;
740 739
741 mu_stream_get_flags (msg->stream, &flags); 740 mu_stream_get_flags (msg->stream, &flags);
742 status = mu_streamref_create_abridged (&stream, msg->stream, 741 status = mu_streamref_create_abridged (&stream, msg->stream,
743 size, 0); 742 msg->orig_header_size, 0);
744 if (status) 743 if (status)
745 { 744 {
746 mu_body_destroy (&body, msg); 745 mu_body_destroy (&body, msg);
......
...@@ -536,15 +536,52 @@ _mime_set_content_type (mu_mime_t mime) ...@@ -536,15 +536,52 @@ _mime_set_content_type (mu_mime_t mime)
536 } 536 }
537 537
538 538
539 static int
540 _mime_part_size (mu_mime_t mime, size_t *psize)
541 {
542 int i, ret;
543 size_t size, total = 0;
544
545 if (mime->nmtp_parts == 0)
546 return EINVAL;
547
548 if ((ret = _mime_set_content_type (mime)) != 0)
549 return ret;
550 for (i = 0; i < mime->nmtp_parts; i++)
551 {
552 mu_message_size (mime->mtp_parts[i]->msg, &size);
553 total += size;
554 if (mime->nmtp_parts > 1) /* boundary line */
555 total += strlen (mime->boundary) + 3;
556 }
557 if (mime->nmtp_parts > 1) /* ending boundary line */
558 total += 2;
559 *psize = total;
560 return 0;
561 }
562
563
539 struct _mime_body_stream 564 struct _mime_body_stream
540 { 565 {
541 struct _mu_stream stream; 566 struct _mu_stream stream;
542 mu_mime_t mime; 567 mu_mime_t mime;
543 }; 568 };
544 569
570 static int
571 _mime_body_stream_size (mu_stream_t stream, mu_off_t *psize)
572 {
573 struct _mime_body_stream *mstr = (struct _mime_body_stream *)stream;
574 mu_mime_t mime = mstr->mime;
575 size_t sz;
576 int rc = _mime_part_size (mime, &sz);
577 if (rc == 0)
578 *psize = sz;
579 return rc;
580 }
581
545 /* FIXME: The seek method is defective */ 582 /* FIXME: The seek method is defective */
546 static int 583 static int
547 _mime_body_seek (mu_stream_t stream, mu_off_t off, mu_off_t *presult) 584 _mime_body_stream_seek (mu_stream_t stream, mu_off_t off, mu_off_t *presult)
548 { 585 {
549 struct _mime_body_stream *mstr = (struct _mime_body_stream *)stream; 586 struct _mime_body_stream *mstr = (struct _mime_body_stream *)stream;
550 mu_mime_t mime = mstr->mime; 587 mu_mime_t mime = mstr->mime;
...@@ -565,30 +602,39 @@ _mime_body_seek (mu_stream_t stream, mu_off_t off, mu_off_t *presult) ...@@ -565,30 +602,39 @@ _mime_body_seek (mu_stream_t stream, mu_off_t off, mu_off_t *presult)
565 return 0; 602 return 0;
566 } 603 }
567 604
568 #define ADD_CHAR(buf, c, offset, buflen, nbytes) do {\ 605 #define ADD_CHAR(buf, c, offset, buflen, total, nbytes) \
569 *(buf)++ = c;\ 606 do \
570 (offset)++;\ 607 { \
571 (nbytes)++;\ 608 *(buf)++ = c; \
572 if (--(buflen) == 0) return 0;\ 609 (offset)++; \
573 } while (0) 610 (total)++; \
611 if (--(buflen) == 0) \
612 { \
613 *(nbytes) = total; \
614 return 0; \
615 } \
616 } \
617 while (0)
574 618
575 static int 619 static int
576 _mime_body_read (mu_stream_t stream, char *buf, size_t buflen, size_t *nbytes) 620 _mime_body_stream_read (mu_stream_t stream, char *buf, size_t buflen, size_t *nbytes)
577 { 621 {
578 struct _mime_body_stream *mstr = (struct _mime_body_stream *)stream; 622 struct _mime_body_stream *mstr = (struct _mime_body_stream *)stream;
579 mu_mime_t mime = mstr->mime; 623 mu_mime_t mime = mstr->mime;
580 int ret = 0; 624 int ret = 0;
581 size_t part_nbytes = 0; 625 size_t total = 0;
582 mu_stream_t msg_stream = NULL; 626
583
584 if (mime->nmtp_parts == 0) 627 if (mime->nmtp_parts == 0)
585 return EINVAL; 628 return EINVAL;
586 629
587 if ((ret = _mime_set_content_type (mime)) == 0) 630 if ((ret = _mime_set_content_type (mime)) == 0)
588 { 631 {
589 do 632 do
590 { 633 {
591 mu_stream_destroy (&msg_stream); 634 size_t part_nbytes = 0;
635
636 if (buflen == 0)
637 break;
592 if (mime->nmtp_parts > 1) 638 if (mime->nmtp_parts > 1)
593 { 639 {
594 size_t len; 640 size_t len;
...@@ -606,7 +652,8 @@ _mime_body_read (mu_stream_t stream, char *buf, size_t buflen, size_t *nbytes) ...@@ -606,7 +652,8 @@ _mime_body_read (mu_stream_t stream, char *buf, size_t buflen, size_t *nbytes)
606 while (mime->preamble) 652 while (mime->preamble)
607 { 653 {
608 mime->preamble--; 654 mime->preamble--;
609 ADD_CHAR (buf, '-', mime->cur_offset, buflen, *nbytes); 655 ADD_CHAR (buf, '-', mime->cur_offset, buflen,
656 total, nbytes);
610 } 657 }
611 len = strlen (mime->boundary) - mime->boundary_len; 658 len = strlen (mime->boundary) - mime->boundary_len;
612 while (mime->boundary_len) 659 while (mime->boundary_len)
...@@ -614,57 +661,89 @@ _mime_body_read (mu_stream_t stream, char *buf, size_t buflen, size_t *nbytes) ...@@ -614,57 +661,89 @@ _mime_body_read (mu_stream_t stream, char *buf, size_t buflen, size_t *nbytes)
614 mime->boundary_len--; 661 mime->boundary_len--;
615 ADD_CHAR (buf, 662 ADD_CHAR (buf,
616 mime->boundary[len++], 663 mime->boundary[len++],
617 mime->cur_offset, buflen, *nbytes); 664 mime->cur_offset, buflen,
665 total, nbytes);
618 } 666 }
619 while (mime->postamble) 667 while (mime->postamble)
620 { 668 {
621 mime->postamble--; 669 mime->postamble--;
622 ADD_CHAR (buf, '-', mime->cur_offset, buflen, *nbytes); 670 ADD_CHAR (buf, '-', mime->cur_offset, buflen,
671 total, nbytes);
623 } 672 }
624 mime->flags &= 673 mime->flags &=
625 ~(MIME_INSERT_BOUNDARY | MIME_ADDING_BOUNDARY); 674 ~(MIME_INSERT_BOUNDARY | MIME_ADDING_BOUNDARY);
626 mime->part_offset = 0; 675 mime->part_offset = 0;
627 ADD_CHAR (buf, '\n', mime->cur_offset, buflen, *nbytes); 676 ADD_CHAR (buf, '\n', mime->cur_offset, buflen,
677 total, nbytes);
678 }
679
680 if (!mime->part_stream)
681 {
682 if (mime->cur_part >= mime->nmtp_parts)
683 {
684 *nbytes = total;
685 return 0;
686 }
687 ret = mu_message_get_streamref (mime->mtp_parts[mime->cur_part]->msg,
688 &mime->part_stream);
628 } 689 }
629 if (mime->cur_part >= mime->nmtp_parts)
630 return 0;
631 mu_message_get_streamref (mime->mtp_parts[mime->cur_part]->msg,
632 &msg_stream);
633 } 690 }
634 else 691 else if (!mime->part_stream)
635 { 692 {
636 mu_body_t part_body; 693 mu_body_t part_body;
637 694
638 if (mime->cur_part >= mime->nmtp_parts) 695 if (mime->cur_part >= mime->nmtp_parts)
639 return 0; 696 {
697 *nbytes = total;
698 return 0;
699 }
640 mu_message_get_body (mime->mtp_parts[mime->cur_part]->msg, 700 mu_message_get_body (mime->mtp_parts[mime->cur_part]->msg,
641 &part_body); 701 &part_body);
642 mu_body_get_streamref (part_body, &msg_stream); 702 ret = mu_body_get_streamref (part_body, &mime->part_stream);
643 } 703 }
644 mu_stream_seek (msg_stream, mime->part_offset, MU_SEEK_SET, NULL); 704 if (ret)
645 ret = mu_stream_read (msg_stream, buf, buflen, &part_nbytes); 705 break;
646 if (part_nbytes) 706 ret = mu_stream_seek (mime->part_stream, mime->part_offset,
707 MU_SEEK_SET, NULL);
708 if (ret)
647 { 709 {
648 mime->part_offset += part_nbytes; 710 mu_stream_destroy (&mime->part_stream);
649 mime->cur_offset += part_nbytes; 711 break;
650 if (nbytes)
651 *nbytes += part_nbytes;
652 } 712 }
653 if (ret == 0 && part_nbytes == 0) 713 while (buflen > 0 &&
714 (ret = mu_stream_read (mime->part_stream, buf, buflen,
715 &part_nbytes)) == 0)
654 { 716 {
655 mime->flags |= MIME_INSERT_BOUNDARY; 717 if (part_nbytes)
656 mime->cur_part++; 718 {
657 ADD_CHAR (buf, '\n', mime->cur_offset, buflen, *nbytes); 719 mime->part_offset += part_nbytes;
720 mime->cur_offset += part_nbytes;
721 total += part_nbytes;
722 buflen -= part_nbytes;
723 buf += part_nbytes;
724 }
725 else
726 {
727 mu_stream_destroy (&mime->part_stream);
728 mime->flags |= MIME_INSERT_BOUNDARY;
729 mime->cur_part++;
730 ADD_CHAR (buf, '\n', mime->cur_offset, buflen,
731 total, nbytes);
732 break;
733 }
658 } 734 }
659 } 735 }
660 while (ret == 0 && part_nbytes == 0 736 while (ret == 0 && mime->cur_part <= mime->nmtp_parts);
661 && mime->cur_part <= mime->nmtp_parts);
662 } 737 }
738 if (ret)
739 mu_stream_destroy (&mime->part_stream);
740
741 *nbytes = total;
663 return ret; 742 return ret;
664 } 743 }
665 744
666 static int 745 static int
667 _mime_body_ioctl (mu_stream_t stream, int code, void *arg) 746 _mime_body_stream_ioctl (mu_stream_t stream, int code, void *arg)
668 { 747 {
669 struct _mime_body_stream *mstr = (struct _mime_body_stream *)stream; 748 struct _mime_body_stream *mstr = (struct _mime_body_stream *)stream;
670 mu_mime_t mime = mstr->mime; 749 mu_mime_t mime = mstr->mime;
...@@ -694,16 +773,18 @@ _mime_body_ioctl (mu_stream_t stream, int code, void *arg) ...@@ -694,16 +773,18 @@ _mime_body_ioctl (mu_stream_t stream, int code, void *arg)
694 } 773 }
695 774
696 static int 775 static int
697 create_mime_body_stream (mu_stream_t *pstr) 776 create_mime_body_stream (mu_stream_t *pstr, mu_mime_t mime)
698 { 777 {
699 struct _mime_body_stream *sp = 778 struct _mime_body_stream *sp =
700 (struct _mime_body_stream *)_mu_stream_create (sizeof (*sp), 779 (struct _mime_body_stream *)_mu_stream_create (sizeof (*sp),
701 MU_STREAM_READ | MU_STREAM_SEEK); 780 MU_STREAM_READ | MU_STREAM_SEEK);
702 if (!sp) 781 if (!sp)
703 return ENOMEM; 782 return ENOMEM;
704 sp->stream.read = _mime_body_read; 783 sp->stream.read = _mime_body_stream_read;
705 sp->stream.seek = _mime_body_seek; 784 sp->stream.seek = _mime_body_stream_seek;
706 sp->stream.ctl = _mime_body_ioctl; 785 sp->stream.ctl = _mime_body_stream_ioctl;
786 sp->stream.size = _mime_body_stream_size;
787 sp->mime = mime;
707 *pstr = (mu_stream_t) sp; 788 *pstr = (mu_stream_t) sp;
708 return 0; 789 return 0;
709 } 790 }
...@@ -714,25 +795,7 @@ _mime_body_size (mu_body_t body, size_t *psize) ...@@ -714,25 +795,7 @@ _mime_body_size (mu_body_t body, size_t *psize)
714 { 795 {
715 mu_message_t msg = mu_body_get_owner (body); 796 mu_message_t msg = mu_body_get_owner (body);
716 mu_mime_t mime = mu_message_get_owner (msg); 797 mu_mime_t mime = mu_message_get_owner (msg);
717 int i, ret; 798 return _mime_part_size (mime, psize);
718 size_t size;
719
720 if (mime->nmtp_parts == 0)
721 return EINVAL;
722
723 if ((ret = _mime_set_content_type (mime)) != 0)
724 return ret;
725 for (i = 0; i < mime->nmtp_parts; i++)
726 {
727 mu_message_size (mime->mtp_parts[i]->msg, &size);
728 *psize += size;
729 if (mime->nmtp_parts > 1) /* boundary line */
730 *psize += strlen (mime->boundary) + 3;
731 }
732 if (mime->nmtp_parts > 1) /* ending boundary line */
733 *psize += 2;
734
735 return 0;
736 } 799 }
737 800
738 static int 801 static int
...@@ -851,6 +914,7 @@ mu_mime_destroy (mu_mime_t *pmime) ...@@ -851,6 +914,7 @@ mu_mime_destroy (mu_mime_t *pmime)
851 free (mime->mtp_parts); 914 free (mime->mtp_parts);
852 } 915 }
853 mu_stream_destroy (&mime->stream); 916 mu_stream_destroy (&mime->stream);
917 mu_stream_destroy (&mime->part_stream);
854 if (mime->msg && mime->flags & MIME_NEW_MESSAGE) 918 if (mime->msg && mime->flags & MIME_NEW_MESSAGE)
855 mu_message_destroy (&mime->msg, mime); 919 mu_message_destroy (&mime->msg, mime);
856 if (mime->content_type) 920 if (mime->content_type)
...@@ -973,7 +1037,7 @@ mu_mime_get_message (mu_mime_t mime, mu_message_t *msg) ...@@ -973,7 +1037,7 @@ mu_mime_get_message (mu_mime_t mime, mu_message_t *msg)
973 mu_message_set_body (mime->msg, body, mime); 1037 mu_message_set_body (mime->msg, body, mime);
974 mu_body_set_size (body, _mime_body_size, mime->msg); 1038 mu_body_set_size (body, _mime_body_size, mime->msg);
975 mu_body_set_lines (body, _mime_body_lines, mime->msg); 1039 mu_body_set_lines (body, _mime_body_lines, mime->msg);
976 ret = create_mime_body_stream (&body_stream); 1040 ret = create_mime_body_stream (&body_stream, mime);
977 if (ret == 0) 1041 if (ret == 0)
978 { 1042 {
979 mu_body_set_stream (body, body_stream, mime->msg); 1043 mu_body_set_stream (body, body_stream, mime->msg);
......
...@@ -26,62 +26,56 @@ PATTERN END ...@@ -26,62 +26,56 @@ PATTERN END
26 FILE BEGIN 26 FILE BEGIN
27 ENVELOPE FROM: coyote@desert.example.org 27 ENVELOPE FROM: coyote@desert.example.org
28 ENVELOPE TO: <gray@gnu.org> 28 ENVELOPE TO: <gray@gnu.org>
29 -re 29 0: X-Loop-Prevention: foobar@nonexistent.net
30 0: X-Authentication-Warning: [^ \t]+ set sender using -f flag 30 1: From: coyote@desert.example.org
31 1: X-Loop-Prevention: foobar@nonexistent.net 31 2: To: roadrunner@acme.example.com
32 2: From: coyote@desert.example.org 32 3: Subject: I have a present for you
33 3: To: roadrunner@acme.example.com 33 4: X-Caffeine: C8H10N4O2
34 4: Subject: I have a present for you 34 5:
35 5: X-Caffeine: C8H10N4O2 35 6: Look, I'm sorry about the whole anvil thing, and I really
36 6: 36 7: didn't mean to try and drop it on you from the top of the
37 7: Look, I'm sorry about the whole anvil thing, and I really 37 8: cliff. I want to try to make it up to you. I've got some
38 8: didn't mean to try and drop it on you from the top of the 38 9: great birdseed over here at my place--top of the line
39 9: cliff. I want to try to make it up to you. I've got some 39 10: stuff--and if you come by, I'll have it all wrapped up
40 10: great birdseed over here at my place--top of the line 40 11: for you. I'm really sorry for all the problems I've caused
41 11: stuff--and if you come by, I'll have it all wrapped up 41 12: for you over the years, but I know we can work this out.
42 12: for you. I'm really sorry for all the problems I've caused 42 13:
43 13: for you over the years, but I know we can work this out. 43 14: --
44 14: 44 15: Wile E. Coyote "Super Genius" coyote@desert.example.org
45 15: -- 45 16:
46 16: Wile E. Coyote "Super Genius" coyote@desert.example.org
47 17:
48 END OF MESSAGE 46 END OF MESSAGE
49 ENVELOPE FROM: b1ff@de.res.example.com 47 ENVELOPE FROM: b1ff@de.res.example.com
50 ENVELOPE TO: <gray@gnu.org> 48 ENVELOPE TO: <gray@gnu.org>
51 -re 49 0: X-Loop-Prevention: foobar@nonexistent.net
52 0: X-Authentication-Warning: [^ \t]+ set sender using -f flag 50 1: From: youcouldberich!@reply-by-postal-mail.invalid
53 1: X-Loop-Prevention: foobar@nonexistent.net 51 2: To: rube@landru.example.edu
54 2: From: youcouldberich!@reply-by-postal-mail.invalid 52 3: Subject: $$$ YOU, TOO, CAN BE A MILLIONAIRE! $$$
55 3: To: rube@landru.example.edu 53 4: Date: TBD
56 4: Subject: $$$ YOU, TOO, CAN BE A MILLIONAIRE! $$$ 54 5: X-Number: 0015
57 5: Date: TBD 55 6:
58 6: X-Number: 0015 56 7: YOU MAY HAVE ALREADY WON TEN MILLION DOLLARS, BUT I DOUBT
59 7: 57 8: IT! SO JUST POST THIS TO SIX HUNDRED NEWSGROUPS! IT WILL
60 8: YOU MAY HAVE ALREADY WON TEN MILLION DOLLARS, BUT I DOUBT 58 9: GUARANTEE THAT YOU GET AT LEAST FIVE RESPONSES WITH MONEY!
61 9: IT! SO JUST POST THIS TO SIX HUNDRED NEWSGROUPS! IT WILL 59 10: MONEY! MONEY! COLD HARD CASH! YOU WILL RECEIVE OVER
62 10: GUARANTEE THAT YOU GET AT LEAST FIVE RESPONSES WITH MONEY! 60 11: $20,000 IN LESS THAN TWO MONTHS! AND IT'S LEGAL!!!!!!!!!
63 11: MONEY! MONEY! COLD HARD CASH! YOU WILL RECEIVE OVER 61 12: !!!!!!!!!!!!!!!!!!111111111!!!!!!!11111111111!!1 JUST
64 12: $20,000 IN LESS THAN TWO MONTHS! AND IT'S LEGAL!!!!!!!!! 62 13: SEND $5 IN SMALL, UNMARKED BILLS TO THE ADDRESSES BELOW!
65 13: !!!!!!!!!!!!!!!!!!111111111!!!!!!!11111111111!!1 JUST 63 14:
66 14: SEND $5 IN SMALL, UNMARKED BILLS TO THE ADDRESSES BELOW!
67 15:
68 END OF MESSAGE 64 END OF MESSAGE
69 ENVELOPE FROM: bar@dontmailme.org 65 ENVELOPE FROM: bar@dontmailme.org
70 ENVELOPE TO: <gray@gnu.org> 66 ENVELOPE TO: <gray@gnu.org>
71 -re 67 0: X-Loop-Prevention: foobar@nonexistent.net
72 0: X-Authentication-Warning: [^ \t]+ set sender using -f flag 68 1: Received: (from bar@dontmailme.org)
73 1: X-Loop-Prevention: foobar@nonexistent.net 69 2: by dontmailme.org id fERKR9N16790
74 2: Received: (from bar@dontmailme.org) 70 3: for foobar@nonexistent.net; Fri, 28 Dec 2001 22:18:08 +0200
75 3: by dontmailme.org id fERKR9N16790 71 4: Date: Fri, 28 Dec 2001 23:28:08 +0200
76 4: for foobar@nonexistent.net; Fri, 28 Dec 2001 22:18:08 +0200 72 5: From: Bar <bar@dontmailme.org>
77 5: Date: Fri, 28 Dec 2001 23:28:08 +0200 73 6: To: Foo Bar <foobar@nonexistent.net>
78 6: From: Bar <bar@dontmailme.org> 74 7: Message-Id: <200112232808.fERKR9N16790@dontmailme.org>
79 7: To: Foo Bar <foobar@nonexistent.net> 75 8: Subject: Coffee
80 8: Message-Id: <200112232808.fERKR9N16790@dontmailme.org> 76 9:
81 9: Subject: Coffee 77 10: How about some coffee?
82 10: 78 11:
83 11: How about some coffee?
84 12:
85 END OF MESSAGE 79 END OF MESSAGE
86 FILE END 80 FILE END
87 TEST END 81 TEST END
......