Commit dab8df51 dab8df5151d9c781242c7ca7e945fc3bc2e11514 by Sergey Poznyakoff

Lots of bugfixes

1 parent be2c4771
Showing 1 changed file with 289 additions and 231 deletions
...@@ -52,7 +52,7 @@ static int fetch_uid __P ((struct fetch_command *, char**)); ...@@ -52,7 +52,7 @@ static int fetch_uid __P ((struct fetch_command *, char**));
52 static int fetch_envelope0 __P ((message_t)); 52 static int fetch_envelope0 __P ((message_t));
53 static int fetch_bodystructure0 __P ((message_t, int)); 53 static int fetch_bodystructure0 __P ((message_t, int));
54 static int bodystructure __P ((message_t, int)); 54 static int bodystructure __P ((message_t, int));
55 static int send_parameter_list __P ((char *)); 55 static void send_parameter_list __P ((char *));
56 static int fetch_operation __P ((message_t, char **, int)); 56 static int fetch_operation __P ((message_t, char **, int));
57 static int fetch_message __P ((message_t, unsigned long, unsigned long)); 57 static int fetch_message __P ((message_t, unsigned long, unsigned long));
58 static int fetch_header __P ((message_t, unsigned long, unsigned long)); 58 static int fetch_header __P ((message_t, unsigned long, unsigned long));
...@@ -528,6 +528,57 @@ fetch_body (struct fetch_command *command, char **arg) ...@@ -528,6 +528,57 @@ fetch_body (struct fetch_command *command, char **arg)
528 528
529 /* Helper Functions: Where the Beef is. */ 529 /* Helper Functions: Where the Beef is. */
530 530
531 static void
532 fetch_send_header_value (header_t header, const char *name,
533 const char *defval, int space)
534 {
535 char *buffer;
536
537 if (space)
538 util_send (" ");
539 if (header_aget_value (header, name, &buffer) == 0)
540 {
541 util_send_qstring (buffer);
542 free (buffer);
543 }
544 else
545 util_send (defval ? defval : "NIL");
546 }
547
548 static void
549 fetch_send_header_list (header_t header, const char *name,
550 const char *defval, int space)
551 {
552 char *buffer;
553
554 if (space)
555 util_send (" ");
556 if (header_aget_value (header, name, &buffer) == 0)
557 {
558 send_parameter_list (buffer);
559 free (buffer);
560 }
561 else
562 util_send (defval ? defval : "NIL");
563 }
564
565 static void
566 fetch_send_header_address (header_t header, const char *name,
567 const char *defval, int space)
568 {
569 char *buffer;
570
571 if (space)
572 util_send (" ");
573 if (header_aget_value (header, name, &buffer) == 0)
574 {
575 fetch_send_address (buffer);
576 free (buffer);
577 }
578 else
579 fetch_send_address (defval ? defval : "NIL");
580 }
581
531 /* ENVELOPE: 582 /* ENVELOPE:
532 The envelope structure of the message. This is computed by the server by 583 The envelope structure of the message. This is computed by the server by
533 parsing the [RFC-822] header into the component parts, defaulting various 584 parsing the [RFC-822] header into the component parts, defaulting various
...@@ -541,74 +592,27 @@ fetch_body (struct fetch_command *command, char **arg) ...@@ -541,74 +592,27 @@ fetch_body (struct fetch_command *command, char **arg)
541 static int 592 static int
542 fetch_envelope0 (message_t msg) 593 fetch_envelope0 (message_t msg)
543 { 594 {
544 char *buffer = NULL;
545 char *from = NULL; 595 char *from = NULL;
546 header_t header = NULL; 596 header_t header = NULL;
547 597
548 message_get_header (msg, &header); 598 message_get_header (msg, &header);
549 599
550 /* Date: */ 600 fetch_send_header_value (header, "Date", NULL, 0);
551 header_aget_value (header, "Date", &buffer); 601 fetch_send_header_value (header, "Subject", NULL, 1);
552 util_send_qstring (buffer);
553 free (buffer);
554 util_send (" ");
555
556 /* Subject: */
557 header_aget_value (header, "Subject", &buffer);
558 util_send_qstring (buffer);
559 free (buffer);
560 util_send (" ");
561 602
562 /* From: */ 603 /* From: */
563 header_aget_value (header, "From", &from); 604 header_aget_value (header, "From", &from);
564 fetch_send_address (from); 605 fetch_send_address (from);
565 util_send (" "); 606 util_send (" ");
566 607
567 /* Sender: */ 608 fetch_send_header_address (header, "Sender", from, 1);
568 /* Note that the server MUST default the reply-to and sender fields from 609 fetch_send_header_address (header, "Reply-to", from, 1);
569 the From field; a client is not expected to know to do this. */ 610 fetch_send_header_address (header, "To", NULL, 1);
570 header_aget_value (header, "Sender", &buffer); 611 fetch_send_header_address (header, "Cc", NULL, 1);
571 fetch_send_address (buffer ? buffer : from); 612 fetch_send_header_address (header, "Bcc", NULL, 1);
572 free (buffer); 613 fetch_send_header_value (header, "In-Reply-To", NULL, 1);
573 util_send (" "); 614 fetch_send_header_value (header, "Message-ID", NULL, 1);
574
575 /* Reply-To: */
576 /* Note that the server MUST default the reply-to and sender fields from
577 the From field; a client is not expected to know to do this. */
578 header_aget_value (header, "Reply-to", &buffer);
579 fetch_send_address (buffer ? buffer : from);
580 free (buffer);
581 util_send (" ");
582
583 /* To: */
584 header_aget_value (header, "To", &buffer);
585 fetch_send_address (buffer);
586 free (buffer);
587 util_send (" ");
588
589 /* Cc: */
590 header_aget_value (header, "Cc", &buffer);
591 fetch_send_address (buffer);
592 free (buffer);
593 util_send (" ");
594 615
595 /* Bcc: */
596 header_aget_value (header, "Bcc", &buffer);
597 fetch_send_address (buffer);
598 free (buffer);
599 util_send (" ");
600
601 /* In-Reply-To: */
602 header_aget_value (header, "In-Reply-To", &buffer);
603 util_send_qstring (buffer);
604 free (buffer);
605 util_send (" ");
606
607 /* Message-ID: */
608 header_aget_value (header, "Message-ID", &buffer);
609 util_send_qstring (buffer);
610
611 free (buffer);
612 free (from); 616 free (from);
613 return RESP_OK; 617 return RESP_OK;
614 } 618 }
...@@ -641,12 +645,11 @@ fetch_bodystructure0 (message_t message, int extension) ...@@ -641,12 +645,11 @@ fetch_bodystructure0 (message_t message, int extension)
641 size_t nparts = 1; 645 size_t nparts = 1;
642 size_t i; 646 size_t i;
643 int is_multipart = 0; 647 int is_multipart = 0;
648
644 message_is_multipart (message, &is_multipart); 649 message_is_multipart (message, &is_multipart);
645 if (is_multipart) 650 if (is_multipart)
646 { 651 {
647 char *buffer = NULL; 652 char *buffer = NULL;
648 char *s;
649 char *sp = NULL;
650 header_t header = NULL; 653 header_t header = NULL;
651 654
652 message_get_num_parts (message, &nparts); 655 message_get_num_parts (message, &nparts);
...@@ -663,67 +666,84 @@ fetch_bodystructure0 (message_t message, int extension) ...@@ -663,67 +666,84 @@ fetch_bodystructure0 (message_t message, int extension)
663 666
664 message_get_header (message, &header); 667 message_get_header (message, &header);
665 668
669
666 /* The subtype. */ 670 /* The subtype. */
667 if (header_aget_value (header, MU_HEADER_CONTENT_TYPE, &buffer) == 0) 671 if (header_aget_value (header, MU_HEADER_CONTENT_TYPE, &buffer) == 0)
668 { 672 {
669 s = strtok_r (buffer, " \t\r\n;", &sp); 673 int argc = 0;
670 if (s) 674 char **argv;
671 { 675 char *s;
672 s = strchr (s, '/'); 676
673 if (s) 677 argcv_get (buffer, " \t\r\n;=", NULL, &argc, &argv);
674 *s++ = '\0'; 678
675 } 679 s = strchr (argv[0], '/');
676 } 680 if (s)
677 util_send (" "); 681 s++;
678 util_send_qstring (s); 682 util_send (" ");
683 util_send_qstring (s);
679 684
680 /* The extension data for multipart. */ 685 /* The extension data for multipart. */
681 if (extension) 686 if (extension)
682 {
683 while (sp && *sp && isspace ((unsigned)*sp)) sp++;
684 /* body parameter parenthesized list: Content-type parameter list. */
685 if (sp && *sp)
686 { 687 {
688 int space = 0;
689 char *lvalue = NULL;
690
687 util_send (" ("); 691 util_send (" (");
688 { 692 for (i = 1; i < argc; i++)
689 int space = 0; 693 {
690 while ((s = strtok_r (NULL, " \t\r\n;", &sp))) 694 /* body parameter parenthesized list:
691 { 695 Content-type parameter list. */
692 char *p = strchr (s, '='); 696 if (lvalue)
693 if (p) 697 {
694 *p++ = '\0'; 698 if (space)
695 if (space)
696 util_send (" ");
697 space = 1;
698 util_send_qstring (s);
699 if (p)
700 {
701 util_send (" "); 699 util_send (" ");
702 util_unquote (&p); 700 util_send_qstring (lvalue);
703 util_send_qstring (p); 701 lvalue = NULL;
704 } 702 space = 1;
705 } 703 }
706 } 704
705 switch (argv[i][0])
706 {
707 case ';':
708 continue;
709
710 case '=':
711 if (++i < argc)
712 {
713 char *p = argv[i];
714 util_send (" ");
715 util_unquote (&p);
716 util_send_qstring (p);
717 }
718 break;
719
720 default:
721 lvalue = argv[i];
722 }
723 }
724 if (lvalue)
725 {
726 if (space)
727 util_send (" ");
728 util_send_qstring (lvalue);
729 }
707 util_send (")"); 730 util_send (")");
708 } 731 }
709 else 732 else
710 util_send (" NIL"); 733 util_send (" NIL");
734 argcv_free (argc, argv);
711 free (buffer); 735 free (buffer);
712 736 }
713 /* body disposition: Content-Disposition. */
714 header_aget_value (header, MU_HEADER_CONTENT_DISPOSITION, &buffer);
715 util_send (" ");
716 send_parameter_list (buffer);
717 free (buffer);
718
719 /* body language: Content-Language. */
720 header_aget_value (header, MU_HEADER_CONTENT_LANGUAGE, &buffer);
721 util_send (" ");
722 send_parameter_list (buffer);
723 free (buffer);
724 } /* extension */
725 else 737 else
726 free (buffer); 738 /* No content-type header */
739 util_send (" NIL");
740
741 /* body disposition: Content-Disposition. */
742 fetch_send_header_list (header, MU_HEADER_CONTENT_DISPOSITION,
743 NULL, 1);
744 /* body language: Content-Language. */
745 fetch_send_header_list (header, MU_HEADER_CONTENT_LANGUAGE,
746 NULL, 1);
727 } 747 }
728 else 748 else
729 bodystructure (message, extension); 749 bodystructure (message, extension);
...@@ -778,99 +798,114 @@ static int ...@@ -778,99 +798,114 @@ static int
778 bodystructure (message_t msg, int extension) 798 bodystructure (message_t msg, int extension)
779 { 799 {
780 header_t header = NULL; 800 header_t header = NULL;
781 char *sp = NULL;
782 char *buffer = NULL; 801 char *buffer = NULL;
783 char *s;
784 size_t blines = 0; 802 size_t blines = 0;
785 int message_rfc822 = 0; 803 int message_rfc822 = 0;
786 int text_plain = 0; 804 int text_plain = 0;
787 805
788 message_get_header (msg, &header); 806 message_get_header (msg, &header);
789 807
790 /* body type: Content-Type 808 if (header_aget_value (header, MU_HEADER_CONTENT_TYPE, &buffer) == 0)
791 body subtype: */
792 if (header_aget_value (header, MU_HEADER_CONTENT_TYPE, &buffer) == 0
793 && (s = strtok_r (buffer, " \t\r\n;", &sp)) != NULL)
794 { 809 {
795 char *p = strchr (s, '/'); 810 int argc = 0;
796 if (strcasecmp (s, "MESSAGE/RFC822") == 0) 811 char **argv;
812 char *s, *p;
813
814 argcv_get (buffer, " \t\r\n;=", NULL, &argc, &argv);
815
816 if (strcasecmp (argv[0], "MESSAGE/RFC822") == 0)
797 message_rfc822 = 1; 817 message_rfc822 = 1;
798 if (strcasecmp (s, "TEXT/PLAIN") == 0) 818 else if (strcasecmp (argv[0], "TEXT/PLAIN") == 0)
799 text_plain = 1; 819 text_plain = 1;
800 if (p) 820
801 *p++ = '\0'; 821 s = strchr (argv[0], '/');
802 /* MIME media type and subtype */ 822 if (s)
803 util_send_qstring (s); 823 *s++ = 0;
804 util_send (" "); 824 p = argv[0];
805 util_unquote (&p);
806 util_send_qstring (p); 825 util_send_qstring (p);
807 }
808 else
809 {
810 /* Default? If Content-Type is not present consider as text/plain. */
811 util_send_qstring ("TEXT");
812 util_send (" "); 826 util_send (" ");
813 util_send_qstring ("PLAIN"); 827 util_send_qstring (s);
814 text_plain = 1;
815 }
816
817 while (sp != NULL && *sp && isspace ((unsigned)*sp)) sp++;
818
819 /* body parameter parenthesized list: Content-type attributes */
820 if ((sp != NULL && *sp) || text_plain)
821 {
822 int space = 0;
823 int have_charset = 0;
824 828
825 util_send (" ("); 829 /* body parameter parenthesized list: Content-type attributes */
826 if (sp) 830 if (argc > 1 || text_plain)
827 { 831 {
828 /* Content-type parameter list. */ 832 int space = 0;
829 while ((s = strtok_r (NULL, " \t\r\n;", &sp))) 833 char *lvalue = NULL;
834 int have_charset = 0;
835 int i;
836
837 util_send (" (");
838 for (i = 1; i < argc; i++)
839 {
840 /* body parameter parenthesized list:
841 Content-type parameter list. */
842 if (lvalue)
843 {
844 if (space)
845 util_send (" ");
846 util_send_qstring (lvalue);
847 lvalue = NULL;
848 space = 1;
849 }
850
851 switch (argv[i][0])
852 {
853 case ';':
854 continue;
855
856 case '=':
857 if (++i < argc)
858 {
859 char *p = argv[i];
860 util_send (" ");
861 util_unquote (&p);
862 util_send_qstring (p);
863 }
864 break;
865
866 default:
867 lvalue = argv[i];
868 if (strcasecmp (lvalue, "charset") == 0)
869 have_charset = 1;
870
871 }
872 }
873
874 if (lvalue)
830 { 875 {
831 char *p = strchr (s, '=');
832 if (p)
833 *p++ = '\0';
834 if (space) 876 if (space)
835 util_send (" "); 877 util_send (" ");
836 util_send_qstring (s); 878 util_send_qstring (lvalue);
837 util_send (" ");
838 util_unquote (&p);
839 if (strcasecmp (s, "charset") == 0)
840 have_charset = 1;
841 util_send_qstring (p);
842 space = 1;
843 } 879 }
880
881 if (!have_charset && text_plain)
882 {
883 if (space)
884 util_send (" ");
885 util_send ("\"CHARSET\" \"US-ASCII\"");
886 }
887 util_send (")");
844 } 888 }
845 if (!have_charset && text_plain) 889 else
846 { 890 util_send (" NIL");
847 if (space) 891 argcv_free (argc, argv);
848 util_send (" "); 892 free (buffer);
849 util_send ("\"CHARSET\" \"US-ASCII\"");
850 }
851 util_send (")");
852 } 893 }
853 else 894 else
854 util_send (" NIL"); 895 {
855 free (buffer); 896 /* Default? If Content-Type is not present consider as text/plain. */
856 897 util_send ("TEXT PLAIN (\"CHARSET\" \"US-ASCII\")");
898 text_plain = 1;
899 }
900
857 /* body id: Content-ID. */ 901 /* body id: Content-ID. */
858 header_aget_value (header, MU_HEADER_CONTENT_ID, &buffer); 902 fetch_send_header_value (header, MU_HEADER_CONTENT_ID, NULL, 1);
859 util_send (" ");
860 util_send_qstring (buffer);
861 free (buffer);
862
863 /* body description: Content-Description. */ 903 /* body description: Content-Description. */
864 header_aget_value (header, MU_HEADER_CONTENT_DESCRIPTION, &buffer); 904 fetch_send_header_value (header, MU_HEADER_CONTENT_DESCRIPTION, NULL, 1);
865 util_send (" ");
866 util_send_qstring (buffer);
867 free (buffer);
868 905
869 /* body encoding: Content-Transfer-Encoding. */ 906 /* body encoding: Content-Transfer-Encoding. */
870 header_aget_value (header, MU_HEADER_CONTENT_TRANSFER_ENCODING, &buffer); 907 fetch_send_header_value (header, MU_HEADER_CONTENT_TRANSFER_ENCODING,
871 util_send (" "); 908 "7BIT", 1);
872 util_send_qstring (buffer ? buffer : "7BIT");
873 free (buffer);
874 909
875 /* body size RFC822 format. */ 910 /* body size RFC822 format. */
876 { 911 {
...@@ -910,22 +945,13 @@ bodystructure (message_t msg, int extension) ...@@ -910,22 +945,13 @@ bodystructure (message_t msg, int extension)
910 if (extension) 945 if (extension)
911 { 946 {
912 /* body MD5: Content-MD5. */ 947 /* body MD5: Content-MD5. */
913 header_aget_value (header, MU_HEADER_CONTENT_MD5, &buffer); 948 fetch_send_header_value (header, MU_HEADER_CONTENT_MD5, NULL, 1);
914 util_send (" ");
915 util_send_qstring (buffer);
916 free (buffer);
917 949
918 /* body disposition: Content-Disposition. */ 950 /* body disposition: Content-Disposition. */
919 header_aget_value (header, MU_HEADER_CONTENT_DISPOSITION, &buffer); 951 fetch_send_header_list (header, MU_HEADER_CONTENT_DISPOSITION, NULL, 1);
920 util_send (" ");
921 send_parameter_list (buffer);
922 free (buffer);
923 952
924 /* body language: Content-Language. */ 953 /* body language: Content-Language. */
925 header_aget_value (header, MU_HEADER_CONTENT_LANGUAGE, &buffer); 954 fetch_send_header_value (header, MU_HEADER_CONTENT_LANGUAGE, NULL, 1);
926 util_send (" ");
927 util_send_qstring (buffer);
928 free (buffer);
929 } 955 }
930 return RESP_OK; 956 return RESP_OK;
931 } 957 }
...@@ -1008,10 +1034,7 @@ fetch_operation (message_t msg, char **arg, int silent) ...@@ -1008,10 +1034,7 @@ fetch_operation (message_t msg, char **arg, int silent)
1008 see it as an extension. But according to IMAP4 we should 1034 see it as an extension. But according to IMAP4 we should
1009 have send an empty string: util_send (" \"\""); 1035 have send an empty string: util_send (" \"\"");
1010 */ 1036 */
1011 if (*section) 1037 util_send ("[%sHEADER]", section);
1012 util_send ("[%sHEADER]", section);
1013 else
1014 util_send ("[%s", *arg);
1015 } 1038 }
1016 (*arg) += 7; 1039 (*arg) += 7;
1017 fetch_header (msg, start, end); 1040 fetch_header (msg, start, end);
...@@ -1344,18 +1367,20 @@ fetch_header_fields_not (message_t msg, char **arg, unsigned long start, ...@@ -1344,18 +1367,20 @@ fetch_header_fields_not (message_t msg, char **arg, unsigned long start,
1344 } 1367 }
1345 } 1368 }
1346 1369
1347 header_aget_field_value (header, i, &value); 1370 if (header_aget_field_value (header, i, &value) == 0)
1348 /* Save the field. */ 1371 {
1349 n = asprintf (&buffer, "%s: %s\n", name, value); 1372 char *nl;
1350 status = stream_write (stream, buffer, n, off, &n); 1373
1351 off += n; 1374 /* Save the field. */
1352 /* count the lines. */ 1375 n = asprintf (&buffer, "%s: %s\n", name, value);
1353 { 1376 status = stream_write (stream, buffer, n, off, &n);
1354 char *nl = buffer; 1377 off += n;
1355 for (;(nl = strchr (nl, '\n')); nl++) 1378 /* count the lines. */
1356 lines++; 1379 for (nl = buffer;(nl = strchr (nl, '\n')); nl++)
1357 } 1380 lines++;
1358 free (value); 1381
1382 free (value);
1383 }
1359 free (name); 1384 free (name);
1360 free (buffer); 1385 free (buffer);
1361 buffer = NULL; 1386 buffer = NULL;
...@@ -1461,47 +1486,80 @@ fetch_send_address (char *addr) ...@@ -1461,47 +1486,80 @@ fetch_send_address (char *addr)
1461 } 1486 }
1462 1487
1463 /* Send parameter list for the bodystructure. */ 1488 /* Send parameter list for the bodystructure. */
1464 static int 1489 static void
1465 send_parameter_list (char *buffer) 1490 send_parameter_list (char *buffer)
1466 { 1491 {
1467 if (buffer) 1492 int argc = 0;
1468 while (*buffer && isspace ((unsigned)*buffer)) buffer++; 1493 char **argv;
1494
1495 if (!buffer)
1496 {
1497 util_send ("NIL");
1498 return;
1499 }
1469 1500
1470 if (buffer && *buffer) 1501 argcv_get (buffer, " \t\r\n;=", NULL, &argc, &argv);
1502
1503 if (argc == 0)
1504 util_send ("NIL");
1505 else
1471 { 1506 {
1472 char *sp = NULL; 1507 char *p;
1473 char *s; 1508
1474 util_send ("("); 1509 util_send ("(");
1475 s = strtok_r (buffer, " \t\r\n;", &sp); 1510
1476 util_send_qstring (s); 1511 p = argv[0];
1477 while (sp && *sp && isspace ((unsigned)*sp)) sp++; 1512 util_send_qstring (p);
1478 if (sp && *sp) 1513
1514 if (argc > 1)
1479 { 1515 {
1480 int space = 0; 1516 int i, space = 0;
1481 util_send (" ("); 1517 char *lvalue = NULL;
1482 while ((s = strtok_r (NULL, " \t\r\n;", &sp))) 1518
1519 util_send ("(");
1520 for (i = 1; i < argc; i++)
1483 { 1521 {
1484 char *p = strchr (s, '='); 1522 if (lvalue)
1485 if (p)
1486 *p++ = '\0';
1487 if (space)
1488 util_send (" ");
1489 space = 1;
1490 util_send_qstring (s);
1491 if (p)
1492 { 1523 {
1493 util_send (" "); 1524 if (space)
1494 util_unquote (&p); 1525 util_send (" ");
1495 util_send_qstring (p); 1526 util_send_qstring (lvalue);
1527 lvalue = NULL;
1528 space = 1;
1529 }
1530
1531 switch (argv[i][0])
1532 {
1533 case ';':
1534 continue;
1535
1536 case '=':
1537 if (++i < argc)
1538 {
1539 char *p = argv[i];
1540 util_send (" ");
1541 util_unquote (&p);
1542 util_send_qstring (p);
1543 }
1544 break;
1545
1546 default:
1547 lvalue = argv[i];
1496 } 1548 }
1497 } 1549 }
1550 if (lvalue)
1551 {
1552 if (space)
1553 util_send (" ");
1554 util_send_qstring (lvalue);
1555 }
1498 util_send (")"); 1556 util_send (")");
1499 } 1557 }
1500 else 1558 else
1501 util_send (" NIL"); 1559 util_send (" NIL");
1502 util_send (")"); 1560 util_send (")");
1503 } 1561 }
1504 else 1562 argcv_free (argc, argv);
1505 util_send ("NIL");
1506 return 0;
1507 } 1563 }
1564
1565
......