* mail/mail.c: Possibility to enable debuging output.
It should probably be a runtime option via set debug=1 or something for now it is disable between if (0) {...}. More cleanup in the IMAP code. A memory stream buffer is use to save the string literal sended by the IMAP server. The allocation is handle by the memory_stream which simplifies the code. * folder_imap.c (folder_imap.c): Create a memory stream to hold the literal or quoted string send by the IMAP server. (folder_imap_list folder_imap_lsub): There is no callback field the struct folder_list is in struct _f_imap now. (imap_literal_string imap_quoted_string imap_string): Use the memory string stream to save the result. (imap_body): Still need to be clean, but creates the cache header when doing the scan. (imap_parse): Do not use alloca().
Showing
7 changed files
with
255 additions
and
138 deletions
1 | 2001-10-13 Jeff Bailey <jbailey@outpost.dnsalias.org> | 1 | 2001-10-13 Alain Malgoire |
2 | |||
3 | * mail/mail.c: Possibility to enable debuging output. | ||
4 | It should probably be a runtime option via set debug=1 or something | ||
5 | for now it is disable between if (0) {...}. | ||
6 | |||
7 | More cleanup in the IMAP code. A memory stream buffer is | ||
8 | use to save the string literal sended by the IMAP server. | ||
9 | The allocation is handle by the memory_stream which simplifies | ||
10 | the code. | ||
11 | |||
12 | * folder_imap.c (folder_imap.c): Create a memory stream to | ||
13 | hold the literal or quoted string send by the IMAP server. | ||
14 | (folder_imap_list folder_imap_lsub): There is no callback | ||
15 | field the struct folder_list is in struct _f_imap now. | ||
16 | (imap_literal_string imap_quoted_string imap_string): Use the | ||
17 | memory string stream to save the result. | ||
18 | (imap_body): Still need to be clean, but creates the cache | ||
19 | header when doing the scan. | ||
20 | (imap_parse): Do not use alloca(). | ||
21 | |||
22 | 2001-10-13 Jeff Bailey | ||
2 | 23 | ||
3 | * guimb/Makefile.am: Remove GNU Makeism. | 24 | * guimb/Makefile.am: Remove GNU Makeism. |
4 | 25 | ||
5 | * libmu_scm/Makefile.am: Remove GNU Makeism. | 26 | * libmu_scm/Makefile.am: Remove GNU Makeism. |
6 | 27 | ||
7 | 2001-10-12 Jeff Bailey <jbailey@outpost.dnsalias.org> | 28 | 2001-10-12 Jeff Bailey |
8 | 29 | ||
9 | * libmu_scm/Makefile.am: Fixes for RO srcdir. | 30 | * libmu_scm/Makefile.am: Fixes for RO srcdir. |
10 | 31 | ... | ... |
... | @@ -345,6 +345,14 @@ main (int argc, char **argv) | ... | @@ -345,6 +345,14 @@ main (int argc, char **argv) |
345 | exit (EXIT_FAILURE); | 345 | exit (EXIT_FAILURE); |
346 | } | 346 | } |
347 | 347 | ||
348 | /* Could we enable this at runtime, via the a set environment? */ | ||
349 | if (0) | ||
350 | { | ||
351 | mu_debug_t debug = NULL; | ||
352 | mailbox_get_debug (mbox, &debug); | ||
353 | mu_debug_set_level (debug, MU_DEBUG_TRACE|MU_DEBUG_PROT); | ||
354 | } | ||
355 | |||
348 | if (mailbox_open (mbox, MU_STREAM_RDWR) != 0) | 356 | if (mailbox_open (mbox, MU_STREAM_RDWR) != 0) |
349 | { | 357 | { |
350 | util_error ("Can not open mailbox"); | 358 | util_error ("Can not open mailbox"); | ... | ... |
... | @@ -264,11 +264,15 @@ folder_imap_open (folder_t folder, int flags) | ... | @@ -264,11 +264,15 @@ folder_imap_open (folder_t folder, int flags) |
264 | { | 264 | { |
265 | CHECK_ERROR (f_imap, ENOMEM); | 265 | CHECK_ERROR (f_imap, ENOMEM); |
266 | } | 266 | } |
267 | memory_stream_create (&f_imap->string.stream); | ||
267 | } | 268 | } |
268 | else | 269 | else |
269 | { | 270 | { |
270 | /* Clear from any residue. */ | 271 | /* Clear from any residue. */ |
271 | memset (f_imap->buffer, '\0', f_imap->buflen); | 272 | memset (f_imap->buffer, '\0', f_imap->buflen); |
273 | stream_truncate (f_imap->string.stream, 0); | ||
274 | f_imap->string.offset = 0; | ||
275 | f_imap->string.nleft = 0; | ||
272 | } | 276 | } |
273 | f_imap->ptr = f_imap->buffer; | 277 | f_imap->ptr = f_imap->buffer; |
274 | 278 | ||
... | @@ -598,10 +602,10 @@ folder_imap_list (folder_t folder, const char *ref, const char *name, | ... | @@ -598,10 +602,10 @@ folder_imap_list (folder_t folder, const char *ref, const char *name, |
598 | } | 602 | } |
599 | 603 | ||
600 | /* Build the folder list. */ | 604 | /* Build the folder list. */ |
601 | if (f_imap->callback.flist.num > 0) | 605 | if (f_imap->flist.num > 0) |
602 | { | 606 | { |
603 | struct list_response **plist = NULL; | 607 | struct list_response **plist = NULL; |
604 | size_t num = f_imap->callback.flist.num; | 608 | size_t num = f_imap->flist.num; |
605 | size_t j = 0; | 609 | size_t j = 0; |
606 | plist = calloc (num, sizeof (*plist)); | 610 | plist = calloc (num, sizeof (*plist)); |
607 | if (plist) | 611 | if (plist) |
... | @@ -609,7 +613,7 @@ folder_imap_list (folder_t folder, const char *ref, const char *name, | ... | @@ -609,7 +613,7 @@ folder_imap_list (folder_t folder, const char *ref, const char *name, |
609 | size_t i; | 613 | size_t i; |
610 | for (i = 0; i < num; i++) | 614 | for (i = 0; i < num; i++) |
611 | { | 615 | { |
612 | struct list_response *lr = f_imap->callback.flist.element[i]; | 616 | struct list_response *lr = f_imap->flist.element[i]; |
613 | /* printf ("%s --> %s\n", lr->name, name); */ | 617 | /* printf ("%s --> %s\n", lr->name, name); */ |
614 | if (fnmatch (name, lr->name, 0) == 0) | 618 | if (fnmatch (name, lr->name, 0) == 0) |
615 | { | 619 | { |
... | @@ -628,7 +632,7 @@ folder_imap_list (folder_t folder, const char *ref, const char *name, | ... | @@ -628,7 +632,7 @@ folder_imap_list (folder_t folder, const char *ref, const char *name, |
628 | pflist->element = plist; | 632 | pflist->element = plist; |
629 | pflist->num = j; | 633 | pflist->num = j; |
630 | } | 634 | } |
631 | folder_list_destroy (&(f_imap->callback.flist)); | 635 | folder_list_destroy (&(f_imap->flist)); |
632 | f_imap->state = IMAP_NO_STATE; | 636 | f_imap->state = IMAP_NO_STATE; |
633 | return status; | 637 | return status; |
634 | } | 638 | } |
... | @@ -671,10 +675,10 @@ folder_imap_lsub (folder_t folder, const char *ref, const char *name, | ... | @@ -671,10 +675,10 @@ folder_imap_lsub (folder_t folder, const char *ref, const char *name, |
671 | } | 675 | } |
672 | 676 | ||
673 | /* Build the folder list. */ | 677 | /* Build the folder list. */ |
674 | if (f_imap->callback.flist.num > 0) | 678 | if (f_imap->flist.num > 0) |
675 | { | 679 | { |
676 | struct list_response **plist = NULL; | 680 | struct list_response **plist = NULL; |
677 | size_t num = f_imap->callback.flist.num; | 681 | size_t num = f_imap->flist.num; |
678 | size_t j = 0; | 682 | size_t j = 0; |
679 | plist = calloc (num, sizeof (*plist)); | 683 | plist = calloc (num, sizeof (*plist)); |
680 | if (plist) | 684 | if (plist) |
... | @@ -682,7 +686,7 @@ folder_imap_lsub (folder_t folder, const char *ref, const char *name, | ... | @@ -682,7 +686,7 @@ folder_imap_lsub (folder_t folder, const char *ref, const char *name, |
682 | size_t i; | 686 | size_t i; |
683 | for (i = 0; i < num; i++) | 687 | for (i = 0; i < num; i++) |
684 | { | 688 | { |
685 | struct list_response *lr = f_imap->callback.flist.element[i]; | 689 | struct list_response *lr = f_imap->flist.element[i]; |
686 | /* printf ("%s --> %s\n", lr->name, name); */ | 690 | /* printf ("%s --> %s\n", lr->name, name); */ |
687 | plist[i] = calloc (1, sizeof (**plist)); | 691 | plist[i] = calloc (1, sizeof (**plist)); |
688 | if (plist[i] == NULL | 692 | if (plist[i] == NULL |
... | @@ -697,7 +701,7 @@ folder_imap_lsub (folder_t folder, const char *ref, const char *name, | ... | @@ -697,7 +701,7 @@ folder_imap_lsub (folder_t folder, const char *ref, const char *name, |
697 | } | 701 | } |
698 | pflist->element = plist; | 702 | pflist->element = plist; |
699 | pflist->num = j; | 703 | pflist->num = j; |
700 | folder_list_destroy (&(f_imap->callback.flist)); | 704 | folder_list_destroy (&(f_imap->flist)); |
701 | } | 705 | } |
702 | f_imap->state = IMAP_NO_STATE; | 706 | f_imap->state = IMAP_NO_STATE; |
703 | f_imap->state = IMAP_NO_STATE; | 707 | f_imap->state = IMAP_NO_STATE; |
... | @@ -811,8 +815,7 @@ folder_imap_unsubscribe (folder_t folder, const char *name) | ... | @@ -811,8 +815,7 @@ folder_imap_unsubscribe (folder_t folder, const char *name) |
811 | /* A literal is a sequence of zero or more octets (including CR and LF), | 815 | /* A literal is a sequence of zero or more octets (including CR and LF), |
812 | prefix-quoted with an octet count in the form of an open brace ("{"), | 816 | prefix-quoted with an octet count in the form of an open brace ("{"), |
813 | the number of octets, close brace ("}"), and CRLF. The sequence is read | 817 | the number of octets, close brace ("}"), and CRLF. The sequence is read |
814 | and put in the callback buffer, hopefully the callee did have enough | 818 | and put in the string buffer. */ |
815 | room. */ | ||
816 | static int | 819 | static int |
817 | imap_literal_string (f_imap_t f_imap, char **ptr) | 820 | imap_literal_string (f_imap_t f_imap, char **ptr) |
818 | { | 821 | { |
... | @@ -820,7 +823,7 @@ imap_literal_string (f_imap_t f_imap, char **ptr) | ... | @@ -820,7 +823,7 @@ imap_literal_string (f_imap_t f_imap, char **ptr) |
820 | int status = 0; | 823 | int status = 0; |
821 | int nl; | 824 | int nl; |
822 | /* The (len + 1) in the for is to count the strip '\r' by imap_readline. */ | 825 | /* The (len + 1) in the for is to count the strip '\r' by imap_readline. */ |
823 | for (len0 = len = total = 0; total < f_imap->callback.nleft; total += (len + 1)) | 826 | for (len0 = len = total = 0; total < f_imap->string.nleft; total += (len + 1)) |
824 | { | 827 | { |
825 | status = imap_readline (f_imap); | 828 | status = imap_readline (f_imap); |
826 | /*fprintf (stderr, "%d: %s", strlen (f_imap->buffer), f_imap->buffer);*/ | 829 | /*fprintf (stderr, "%d: %s", strlen (f_imap->buffer), f_imap->buffer);*/ |
... | @@ -834,12 +837,12 @@ imap_literal_string (f_imap_t f_imap, char **ptr) | ... | @@ -834,12 +837,12 @@ imap_literal_string (f_imap_t f_imap, char **ptr) |
834 | /* How much ? */ | 837 | /* How much ? */ |
835 | len0 = len = f_imap->nl - f_imap->buffer; | 838 | len0 = len = f_imap->nl - f_imap->buffer; |
836 | /* Check if the last read did not finish on a line, if yes do not copy in | 839 | /* Check if the last read did not finish on a line, if yes do not copy in |
837 | callback buffer the terminating sequence ")\r\n". We are doing this | 840 | string buffer the terminating sequence ")\r\n". We are doing this |
838 | by checking if the amount(total) we got so far + the len of the line | 841 | by checking if the amount(total) we got so far + the len of the line |
839 | +1 (taking to account the strip '\r') goes behond the request. */ | 842 | +1 (taking to account the strip '\r') goes behond the request. */ |
840 | if ((total + len + 1) > f_imap->callback.nleft) | 843 | if ((total + len + 1) > f_imap->string.nleft) |
841 | { | 844 | { |
842 | len0 = len = f_imap->callback.nleft - total; | 845 | len0 = len = f_imap->string.nleft - total; |
843 | /* ALERT: if we ask for a substring, for example we have : | 846 | /* ALERT: if we ask for a substring, for example we have : |
844 | "123456\n", and ask for body[]<0.7> the server will send | 847 | "123456\n", and ask for body[]<0.7> the server will send |
845 | body[] {7} --> "123456\r". There was not enough space | 848 | body[] {7} --> "123456\r". There was not enough space |
... | @@ -848,35 +851,29 @@ imap_literal_string (f_imap_t f_imap, char **ptr) | ... | @@ -848,35 +851,29 @@ imap_literal_string (f_imap_t f_imap, char **ptr) |
848 | len0--; | 851 | len0--; |
849 | } | 852 | } |
850 | 853 | ||
851 | if (f_imap->callback.total < f_imap->callback.buflen) | 854 | stream_write (f_imap->string.stream, f_imap->buffer, |
852 | { | 855 | len0, f_imap->string.offset, NULL); |
853 | /* Check how much we can fill the callback buffer. */ | 856 | f_imap->string.offset += len0; |
854 | int x = (f_imap->callback.buflen - f_imap->callback.total) - len0; | ||
855 | x = (x >= 0) ? len0 : (x + len0); | ||
856 | if (f_imap->callback.buffer) | ||
857 | memcpy (f_imap->callback.buffer + f_imap->callback.total, | ||
858 | f_imap->buffer, x); | ||
859 | f_imap->callback.total += x; | ||
860 | 857 | ||
861 | /* Depending on the type of request we incremente the xxxx_lines | 858 | /* Depending on the type of request we incremente the xxxx_lines |
862 | and xxxx_sizes. */ | 859 | and xxxx_sizes. */ |
863 | nl = (memchr (f_imap->buffer, '\n', len0)) ? 1 : 0; | 860 | nl = (memchr (f_imap->buffer, '\n', len0)) ? 1 : 0; |
864 | if (f_imap->callback.msg_imap) | 861 | if (f_imap->string.msg_imap) |
865 | { | 862 | { |
866 | switch (f_imap->callback.type) | 863 | switch (f_imap->string.type) |
867 | { | 864 | { |
868 | case IMAP_HEADER: | 865 | case IMAP_HEADER: |
869 | f_imap->callback.msg_imap->header_lines += nl; | 866 | f_imap->string.msg_imap->header_lines += nl; |
870 | f_imap->callback.msg_imap->header_size += x; | 867 | f_imap->string.msg_imap->header_size += len0; |
871 | break; | 868 | break; |
872 | 869 | ||
873 | case IMAP_BODY: | 870 | case IMAP_BODY: |
874 | f_imap->callback.msg_imap->body_lines += nl; | 871 | f_imap->string.msg_imap->body_lines += nl; |
875 | f_imap->callback.msg_imap->body_size += x; | 872 | f_imap->string.msg_imap->body_size += len0; |
876 | break; | 873 | break; |
877 | 874 | ||
878 | case IMAP_MESSAGE: | 875 | case IMAP_MESSAGE: |
879 | f_imap->callback.msg_imap->message_lines += nl; | 876 | f_imap->string.msg_imap->message_lines += nl; |
880 | /* The message size is known by sending RFC822.SIZE. */ | 877 | /* The message size is known by sending RFC822.SIZE. */ |
881 | 878 | ||
882 | default: | 879 | default: |
... | @@ -884,9 +881,9 @@ imap_literal_string (f_imap_t f_imap, char **ptr) | ... | @@ -884,9 +881,9 @@ imap_literal_string (f_imap_t f_imap, char **ptr) |
884 | } | 881 | } |
885 | } | 882 | } |
886 | } | 883 | } |
887 | } | 884 | f_imap->string.nleft -= total; |
888 | f_imap->callback.nleft -= total; | 885 | /* We may have trailing junk like the closing ")\r\n" from a literal string |
889 | /* Move the command buffer, or do a full readline. */ | 886 | glob it by moving the command buffer, or doing a full readline. */ |
890 | if (len == (size_t)(f_imap->nl - f_imap->buffer)) | 887 | if (len == (size_t)(f_imap->nl - f_imap->buffer)) |
891 | { | 888 | { |
892 | len = 0; | 889 | len = 0; |
... | @@ -899,12 +896,14 @@ imap_literal_string (f_imap_t f_imap, char **ptr) | ... | @@ -899,12 +896,14 @@ imap_literal_string (f_imap_t f_imap, char **ptr) |
899 | /* A quoted string is a sequence of zero or more 7-bit characters, | 896 | /* A quoted string is a sequence of zero or more 7-bit characters, |
900 | excluding CR and LF, with double quote (<">) characters at each end. | 897 | excluding CR and LF, with double quote (<">) characters at each end. |
901 | Same thing as the literal, diferent format the result is put in the | 898 | Same thing as the literal, diferent format the result is put in the |
902 | callback buffer for the mailbox/callee. */ | 899 | string buffer for the mailbox/callee. */ |
903 | static int | 900 | static int |
904 | imap_quoted_string (f_imap_t f_imap, char **ptr) | 901 | imap_quoted_string (f_imap_t f_imap, char **ptr) |
905 | { | 902 | { |
906 | char *bquote; | 903 | char *bquote; |
907 | int escaped = 0; | 904 | int escaped = 0; |
905 | size_t len; | ||
906 | |||
908 | (*ptr)++; | 907 | (*ptr)++; |
909 | bquote = *ptr; | 908 | bquote = *ptr; |
910 | while (**ptr && (**ptr != '"' || escaped)) | 909 | while (**ptr && (**ptr != '"' || escaped)) |
... | @@ -912,23 +911,18 @@ imap_quoted_string (f_imap_t f_imap, char **ptr) | ... | @@ -912,23 +911,18 @@ imap_quoted_string (f_imap_t f_imap, char **ptr) |
912 | escaped = (**ptr == '\\') ? 1 : 0; | 911 | escaped = (**ptr == '\\') ? 1 : 0; |
913 | (*ptr)++; | 912 | (*ptr)++; |
914 | } | 913 | } |
915 | f_imap->callback.total = *ptr - bquote; | 914 | |
916 | if (f_imap->callback.buffer) | 915 | len = *ptr - bquote; |
917 | free (f_imap->callback.buffer); | 916 | stream_write (f_imap->string.stream, bquote, len, |
918 | f_imap->callback.buffer = calloc (f_imap->callback.total + 1, 1); | 917 | f_imap->string.offset, NULL); |
919 | f_imap->callback.buflen = f_imap->callback.total; | 918 | f_imap->string.offset += len; |
920 | /* Fill the call back buffer. The if is redundant there should always | ||
921 | be enough room since the request is base on the buffer size. */ | ||
922 | if (f_imap->callback.total <= f_imap->callback.buflen | ||
923 | && f_imap->callback.buffer) | ||
924 | memcpy (f_imap->callback.buffer, bquote, f_imap->callback.total); | ||
925 | if (**ptr == '"') | 919 | if (**ptr == '"') |
926 | (*ptr)++; | 920 | (*ptr)++; |
927 | return 0; | 921 | return 0; |
928 | } | 922 | } |
929 | 923 | ||
930 | /* Find which type of string the response is: literal or quoted and let the | 924 | /* Find which type of string the response is: literal or quoted and let the |
931 | function fill the callback buffer. */ | 925 | function fill the string buffer. */ |
932 | static int | 926 | static int |
933 | imap_string (f_imap_t f_imap, char **ptr) | 927 | imap_string (f_imap_t f_imap, char **ptr) |
934 | { | 928 | { |
... | @@ -940,15 +934,11 @@ imap_string (f_imap_t f_imap, char **ptr) | ... | @@ -940,15 +934,11 @@ imap_string (f_imap_t f_imap, char **ptr) |
940 | switch (**ptr) | 934 | switch (**ptr) |
941 | { | 935 | { |
942 | case '{': | 936 | case '{': |
943 | f_imap->callback.nleft = strtol ((*ptr) + 1, ptr, 10); | 937 | f_imap->string.nleft = strtol ((*ptr) + 1, ptr, 10); |
944 | if (**ptr == '}') | 938 | if (**ptr == '}') |
945 | { | 939 | { |
946 | (*ptr)++; | 940 | (*ptr)++; |
947 | /* Reset the buffer to the beginning. */ | 941 | /* Reset the buffer to the beginning. */ |
948 | if (f_imap->callback.buffer) | ||
949 | free (f_imap->callback.buffer); | ||
950 | f_imap->callback.buffer = calloc (f_imap->callback.nleft + 1, 1); | ||
951 | f_imap->callback.buflen = f_imap->callback.nleft; | ||
952 | f_imap->ptr = f_imap->buffer; | 942 | f_imap->ptr = f_imap->buffer; |
953 | status = imap_literal_string (f_imap, ptr); | 943 | status = imap_literal_string (f_imap, ptr); |
954 | } | 944 | } |
... | @@ -984,15 +974,15 @@ imap_list (f_imap_t f_imap) | ... | @@ -984,15 +974,15 @@ imap_list (f_imap_t f_imap) |
984 | buffer = alloca (len); | 974 | buffer = alloca (len); |
985 | memcpy (buffer, f_imap->buffer, len); | 975 | memcpy (buffer, f_imap->buffer, len); |
986 | buffer[len] = '\0'; | 976 | buffer[len] = '\0'; |
987 | plr = realloc (f_imap->callback.flist.element, | 977 | plr = realloc (f_imap->flist.element, |
988 | (f_imap->callback.flist.num + 1) * sizeof (*plr)); | 978 | (f_imap->flist.num + 1) * sizeof (*plr)); |
989 | if (plr == NULL) | 979 | if (plr == NULL) |
990 | return ENOMEM; | 980 | return ENOMEM; |
991 | f_imap->callback.flist.element = plr; | 981 | f_imap->flist.element = plr; |
992 | lr = plr[f_imap->callback.flist.num] = calloc (1, sizeof (*lr)); | 982 | lr = plr[f_imap->flist.num] = calloc (1, sizeof (*lr)); |
993 | if (lr == NULL) | 983 | if (lr == NULL) |
994 | return ENOMEM; | 984 | return ENOMEM; |
995 | (f_imap->callback.flist.num)++; | 985 | (f_imap->flist.num)++; |
996 | 986 | ||
997 | /* Glob untag. */ | 987 | /* Glob untag. */ |
998 | tok = strtok_r (buffer, " ", &sp); | 988 | tok = strtok_r (buffer, " ", &sp); |
... | @@ -1215,7 +1205,7 @@ imap_bodystructure0 (msg_imap_t msg_imap, char **ptr) | ... | @@ -1215,7 +1205,7 @@ imap_bodystructure0 (msg_imap_t msg_imap, char **ptr) |
1215 | static int | 1205 | static int |
1216 | imap_bodystructure (f_imap_t f_imap, char **ptr) | 1206 | imap_bodystructure (f_imap_t f_imap, char **ptr) |
1217 | { | 1207 | { |
1218 | return imap_bodystructure0 (f_imap->callback.msg_imap, ptr); | 1208 | return imap_bodystructure0 (f_imap->string.msg_imap, ptr); |
1219 | } | 1209 | } |
1220 | 1210 | ||
1221 | /* The Format for a FLAG response is : | 1211 | /* The Format for a FLAG response is : |
... | @@ -1241,10 +1231,10 @@ imap_bodystructure (f_imap_t f_imap, char **ptr) | ... | @@ -1241,10 +1231,10 @@ imap_bodystructure (f_imap_t f_imap, char **ptr) |
1241 | static int | 1231 | static int |
1242 | imap_flags (f_imap_t f_imap, char **ptr) | 1232 | imap_flags (f_imap_t f_imap, char **ptr) |
1243 | { | 1233 | { |
1244 | char *start_flag; | 1234 | char *start; |
1245 | char *end_flag; | 1235 | char *end; |
1246 | /* msg_imap may be null for an untag response deal with it. */ | 1236 | /* msg_imap may be null for an untag response deal with it. */ |
1247 | msg_imap_t msg_imap = f_imap->callback.msg_imap; | 1237 | msg_imap_t msg_imap = f_imap->string.msg_imap; |
1248 | 1238 | ||
1249 | /* Skip space. */ | 1239 | /* Skip space. */ |
1250 | while (**ptr == ' ') | 1240 | while (**ptr == ' ') |
... | @@ -1262,21 +1252,21 @@ imap_flags (f_imap_t f_imap, char **ptr) | ... | @@ -1262,21 +1252,21 @@ imap_flags (f_imap_t f_imap, char **ptr) |
1262 | (*ptr)++; | 1252 | (*ptr)++; |
1263 | 1253 | ||
1264 | /* Save the beginning of the word. */ | 1254 | /* Save the beginning of the word. */ |
1265 | start_flag = *ptr; | 1255 | start = *ptr; |
1266 | 1256 | ||
1267 | /* Get the next word boundary. */ | 1257 | /* Get the next word boundary. */ |
1268 | while (**ptr && **ptr != ' ' && **ptr != ')') | 1258 | while (**ptr && **ptr != ' ' && **ptr != ')') |
1269 | ++(*ptr); | 1259 | ++(*ptr); |
1270 | 1260 | ||
1271 | /* Make a C string for the strcasecmp. */ | 1261 | /* Make a C string for the strcasecmp. */ |
1272 | end_flag = *ptr; | 1262 | end = *ptr; |
1273 | 1263 | ||
1274 | /* Bail out. */ | 1264 | /* Bail out. */ |
1275 | if (*start_flag == '\0') | 1265 | if (*start == '\0') |
1276 | break; | 1266 | break; |
1277 | 1267 | ||
1278 | /* Guess the flag. */ | 1268 | /* Guess the flag. */ |
1279 | if (strncasecmp (start_flag, "\\Seen", end_flag - start_flag) == 0) | 1269 | if (strncasecmp (start, "\\Seen", end - start) == 0) |
1280 | { | 1270 | { |
1281 | if (msg_imap) | 1271 | if (msg_imap) |
1282 | { | 1272 | { |
... | @@ -1286,28 +1276,28 @@ imap_flags (f_imap_t f_imap, char **ptr) | ... | @@ -1286,28 +1276,28 @@ imap_flags (f_imap_t f_imap, char **ptr) |
1286 | else | 1276 | else |
1287 | f_imap->flags |= MU_ATTRIBUTE_SEEN; | 1277 | f_imap->flags |= MU_ATTRIBUTE_SEEN; |
1288 | } | 1278 | } |
1289 | else if (strncasecmp (start_flag, "\\Answered", end_flag - start_flag) == 0) | 1279 | else if (strncasecmp (start, "\\Answered", end - start) == 0) |
1290 | { | 1280 | { |
1291 | if (msg_imap) | 1281 | if (msg_imap) |
1292 | msg_imap->flags |= MU_ATTRIBUTE_ANSWERED; | 1282 | msg_imap->flags |= MU_ATTRIBUTE_ANSWERED; |
1293 | else | 1283 | else |
1294 | f_imap->flags |= MU_ATTRIBUTE_ANSWERED; | 1284 | f_imap->flags |= MU_ATTRIBUTE_ANSWERED; |
1295 | } | 1285 | } |
1296 | else if (strncasecmp (start_flag, "\\Flagged", end_flag - start_flag) == 0) | 1286 | else if (strncasecmp (start, "\\Flagged", end - start) == 0) |
1297 | { | 1287 | { |
1298 | if (msg_imap) | 1288 | if (msg_imap) |
1299 | msg_imap->flags |= MU_ATTRIBUTE_FLAGGED; | 1289 | msg_imap->flags |= MU_ATTRIBUTE_FLAGGED; |
1300 | else | 1290 | else |
1301 | f_imap->flags |= MU_ATTRIBUTE_FLAGGED; | 1291 | f_imap->flags |= MU_ATTRIBUTE_FLAGGED; |
1302 | } | 1292 | } |
1303 | else if (strncasecmp (start_flag, "\\Deleted", end_flag - start_flag) == 0) | 1293 | else if (strncasecmp (start, "\\Deleted", end - start) == 0) |
1304 | { | 1294 | { |
1305 | if (msg_imap) | 1295 | if (msg_imap) |
1306 | msg_imap->flags |= MU_ATTRIBUTE_DELETED; | 1296 | msg_imap->flags |= MU_ATTRIBUTE_DELETED; |
1307 | else | 1297 | else |
1308 | f_imap->flags |= MU_ATTRIBUTE_DELETED; | 1298 | f_imap->flags |= MU_ATTRIBUTE_DELETED; |
1309 | } | 1299 | } |
1310 | else if (strncasecmp (start_flag, "\\Draft", end_flag - start_flag) == 0) | 1300 | else if (strncasecmp (start, "\\Draft", end - start) == 0) |
1311 | { | 1301 | { |
1312 | if (msg_imap) | 1302 | if (msg_imap) |
1313 | msg_imap->flags |= MU_ATTRIBUTE_DRAFT; | 1303 | msg_imap->flags |= MU_ATTRIBUTE_DRAFT; |
... | @@ -1343,20 +1333,20 @@ imap_body (f_imap_t f_imap, char **ptr) | ... | @@ -1343,20 +1333,20 @@ imap_body (f_imap_t f_imap, char **ptr) |
1343 | section[len] = '\0'; | 1333 | section[len] = '\0'; |
1344 | /* strupper. */ | 1334 | /* strupper. */ |
1345 | for (; *p; p++) if (isupper((unsigned)*p)) *p = toupper ((unsigned)*p); | 1335 | for (; *p; p++) if (isupper((unsigned)*p)) *p = toupper ((unsigned)*p); |
1346 | /* Set the callback type to update the correct line count. */ | 1336 | /* Set the string type to update the correct line count. */ |
1347 | //if (!strstr (section, "FIELD")) | 1337 | //if (!strstr (section, "FIELD")) |
1348 | { | 1338 | { |
1349 | if (strstr (section, "MIME") || (strstr (section, "HEADER"))) | 1339 | if (strstr (section, "MIME") || (strstr (section, "HEADER"))) |
1350 | { | 1340 | { |
1351 | f_imap->callback.type = IMAP_HEADER; | 1341 | f_imap->string.type = IMAP_HEADER; |
1352 | } | 1342 | } |
1353 | else if (strstr (section, "TEXT") || len > 0) | 1343 | else if (strstr (section, "TEXT") || len > 0) |
1354 | { | 1344 | { |
1355 | f_imap->callback.type = IMAP_BODY; | 1345 | f_imap->string.type = IMAP_BODY; |
1356 | } | 1346 | } |
1357 | else if (len == 0) /* body[] */ | 1347 | else if (len == 0) /* body[] */ |
1358 | { | 1348 | { |
1359 | f_imap->callback.type = IMAP_MESSAGE; | 1349 | f_imap->string.type = IMAP_MESSAGE; |
1360 | } | 1350 | } |
1361 | } | 1351 | } |
1362 | sep++; /* Move pass the ']' */ | 1352 | sep++; /* Move pass the ']' */ |
... | @@ -1379,16 +1369,19 @@ imap_body (f_imap_t f_imap, char **ptr) | ... | @@ -1379,16 +1369,19 @@ imap_body (f_imap_t f_imap, char **ptr) |
1379 | /* If the state scan. Catch it here. */ | 1369 | /* If the state scan. Catch it here. */ |
1380 | if (f_imap->state == IMAP_SCAN_ACK) | 1370 | if (f_imap->state == IMAP_SCAN_ACK) |
1381 | { | 1371 | { |
1382 | if (f_imap->callback.msg_imap->fheader) | 1372 | char *buffer; |
1383 | header_destroy (&f_imap->callback.msg_imap->fheader, NULL); | 1373 | off_t total = 0; |
1384 | status = header_create (&f_imap->callback.msg_imap->fheader, | 1374 | if (f_imap->string.msg_imap && f_imap->string.msg_imap->fheader) |
1385 | f_imap->callback.buffer, f_imap->callback.total, | 1375 | header_destroy (&f_imap->string.msg_imap->fheader, NULL); |
1386 | NULL); | 1376 | stream_size (f_imap->string.stream, &total); |
1387 | free (f_imap->callback.buffer); | 1377 | buffer = malloc (total + 1); |
1388 | f_imap->callback.buffer = NULL; | 1378 | stream_read (f_imap->string.stream, buffer, total, 0, NULL); |
1389 | f_imap->callback.buflen = 0; | 1379 | status = header_create (&f_imap->string.msg_imap->fheader, |
1390 | f_imap->callback.total = 0; | 1380 | buffer, total, NULL); |
1391 | f_imap->callback.nleft = 0; | 1381 | free (buffer); |
1382 | stream_truncate (f_imap->string.stream, 0); | ||
1383 | f_imap->string.offset = 0; | ||
1384 | f_imap->string.nleft = 0; | ||
1392 | } | 1385 | } |
1393 | return status; | 1386 | return status; |
1394 | } | 1387 | } |
... | @@ -1404,8 +1397,8 @@ imap_uid (f_imap_t f_imap, char **ptr) | ... | @@ -1404,8 +1397,8 @@ imap_uid (f_imap_t f_imap, char **ptr) |
1404 | { | 1397 | { |
1405 | char token[128]; | 1398 | char token[128]; |
1406 | imap_token (token, sizeof (token), ptr); | 1399 | imap_token (token, sizeof (token), ptr); |
1407 | if (f_imap->callback.msg_imap) | 1400 | if (f_imap->string.msg_imap) |
1408 | f_imap->callback.msg_imap->uid = strtoul (token, NULL, 10); | 1401 | f_imap->string.msg_imap->uid = strtoul (token, NULL, 10); |
1409 | return 0; | 1402 | return 0; |
1410 | } | 1403 | } |
1411 | 1404 | ||
... | @@ -1413,9 +1406,9 @@ static int | ... | @@ -1413,9 +1406,9 @@ static int |
1413 | imap_rfc822 (f_imap_t f_imap, char **ptr) | 1406 | imap_rfc822 (f_imap_t f_imap, char **ptr) |
1414 | { | 1407 | { |
1415 | int status; | 1408 | int status; |
1416 | f_imap->callback.type = IMAP_MESSAGE; | 1409 | f_imap->string.type = IMAP_MESSAGE; |
1417 | status = imap_body (f_imap, ptr); | 1410 | status = imap_body (f_imap, ptr); |
1418 | f_imap->callback.type = 0; | 1411 | f_imap->string.type = 0; |
1419 | return status; | 1412 | return status; |
1420 | } | 1413 | } |
1421 | 1414 | ||
... | @@ -1424,8 +1417,8 @@ imap_rfc822_size (f_imap_t f_imap, char **ptr) | ... | @@ -1424,8 +1417,8 @@ imap_rfc822_size (f_imap_t f_imap, char **ptr) |
1424 | { | 1417 | { |
1425 | char token[128]; | 1418 | char token[128]; |
1426 | imap_token (token, sizeof (token), ptr); | 1419 | imap_token (token, sizeof (token), ptr); |
1427 | if (f_imap->callback.msg_imap) | 1420 | if (f_imap->string.msg_imap) |
1428 | f_imap->callback.msg_imap->message_size = strtoul (token, NULL, 10); | 1421 | f_imap->string.msg_imap->message_size = strtoul (token, NULL, 10); |
1429 | return 0; | 1422 | return 0; |
1430 | } | 1423 | } |
1431 | 1424 | ||
... | @@ -1433,9 +1426,9 @@ static int | ... | @@ -1433,9 +1426,9 @@ static int |
1433 | imap_rfc822_header (f_imap_t f_imap, char **ptr) | 1426 | imap_rfc822_header (f_imap_t f_imap, char **ptr) |
1434 | { | 1427 | { |
1435 | int status; | 1428 | int status; |
1436 | f_imap->callback.type = IMAP_HEADER; | 1429 | f_imap->string.type = IMAP_HEADER; |
1437 | status = imap_string (f_imap, ptr); | 1430 | status = imap_string (f_imap, ptr); |
1438 | f_imap->callback.type = 0; | 1431 | f_imap->string.type = 0; |
1439 | return status; | 1432 | return status; |
1440 | } | 1433 | } |
1441 | 1434 | ||
... | @@ -1443,9 +1436,9 @@ static int | ... | @@ -1443,9 +1436,9 @@ static int |
1443 | imap_rfc822_text (f_imap_t f_imap, char **ptr) | 1436 | imap_rfc822_text (f_imap_t f_imap, char **ptr) |
1444 | { | 1437 | { |
1445 | int status; | 1438 | int status; |
1446 | f_imap->callback.type = IMAP_HEADER; | 1439 | f_imap->string.type = IMAP_HEADER; |
1447 | status = imap_string (f_imap, ptr); | 1440 | status = imap_string (f_imap, ptr); |
1448 | f_imap->callback.type = 0; | 1441 | f_imap->string.type = 0; |
1449 | return status; | 1442 | return status; |
1450 | } | 1443 | } |
1451 | 1444 | ||
... | @@ -1493,8 +1486,8 @@ imap_fetch (f_imap_t f_imap) | ... | @@ -1493,8 +1486,8 @@ imap_fetch (f_imap_t f_imap) |
1493 | /* It is actually possible, but higly unlikely that we do not have the | 1486 | /* It is actually possible, but higly unlikely that we do not have the |
1494 | message yet, for example a "FETCH (FLAGS (\Recent))" notification | 1487 | message yet, for example a "FETCH (FLAGS (\Recent))" notification |
1495 | for a newly messsage. */ | 1488 | for a newly messsage. */ |
1496 | if (f_imap->callback.msg_imap == NULL | 1489 | if (f_imap->string.msg_imap == NULL |
1497 | || f_imap->callback.msg_imap->num != msgno) | 1490 | || f_imap->string.msg_imap->num != msgno) |
1498 | { | 1491 | { |
1499 | /* Find the imap mesg struct. */ | 1492 | /* Find the imap mesg struct. */ |
1500 | size_t i; | 1493 | size_t i; |
... | @@ -1504,7 +1497,7 @@ imap_fetch (f_imap_t f_imap) | ... | @@ -1504,7 +1497,7 @@ imap_fetch (f_imap_t f_imap) |
1504 | { | 1497 | { |
1505 | if (m_imap->imessages[i] && m_imap->imessages[i]->num == msgno) | 1498 | if (m_imap->imessages[i] && m_imap->imessages[i]->num == msgno) |
1506 | { | 1499 | { |
1507 | f_imap->callback.msg_imap = m_imap->imessages[i]; | 1500 | f_imap->string.msg_imap = m_imap->imessages[i]; |
1508 | break; | 1501 | break; |
1509 | } | 1502 | } |
1510 | } | 1503 | } |
... | @@ -1767,6 +1760,7 @@ imap_parse (f_imap_t f_imap) | ... | @@ -1767,6 +1760,7 @@ imap_parse (f_imap_t f_imap) |
1767 | int done = 0; | 1760 | int done = 0; |
1768 | int status = 0; | 1761 | int status = 0; |
1769 | char empty[2]; | 1762 | char empty[2]; |
1763 | char *buffer = NULL; | ||
1770 | 1764 | ||
1771 | /* We use that moronic hack to not check null for the tockenize strings. */ | 1765 | /* We use that moronic hack to not check null for the tockenize strings. */ |
1772 | empty[0] = '\0'; | 1766 | empty[0] = '\0'; |
... | @@ -1774,7 +1768,7 @@ imap_parse (f_imap_t f_imap) | ... | @@ -1774,7 +1768,7 @@ imap_parse (f_imap_t f_imap) |
1774 | while (! done) | 1768 | while (! done) |
1775 | { | 1769 | { |
1776 | char *tag, *response, *remainder; | 1770 | char *tag, *response, *remainder; |
1777 | char *buffer; | 1771 | |
1778 | status = imap_readline (f_imap); | 1772 | status = imap_readline (f_imap); |
1779 | if (status != 0) | 1773 | if (status != 0) |
1780 | { | 1774 | { |
... | @@ -1787,17 +1781,24 @@ imap_parse (f_imap_t f_imap) | ... | @@ -1787,17 +1781,24 @@ imap_parse (f_imap_t f_imap) |
1787 | 1781 | ||
1788 | /* We do not want to step over f_imap->buffer since it can be use | 1782 | /* We do not want to step over f_imap->buffer since it can be use |
1789 | further down the chain. */ | 1783 | further down the chain. */ |
1790 | buffer = alloca ((f_imap->ptr - f_imap->buffer) + 1); | 1784 | if (buffer) |
1791 | memcpy (buffer, f_imap->buffer, (f_imap->ptr - f_imap->buffer) + 1); | 1785 | { |
1786 | free (buffer); | ||
1787 | buffer = NULL; | ||
1788 | } | ||
1789 | buffer = calloc ((f_imap->ptr - f_imap->buffer) + 1, 1); | ||
1790 | memcpy (buffer, f_imap->buffer, (f_imap->ptr - f_imap->buffer)); | ||
1792 | 1791 | ||
1793 | /* Tokenize the string. */ | 1792 | /* Tokenize the string. */ |
1794 | { | 1793 | { |
1795 | char *sp = NULL; | 1794 | char *sp = NULL; |
1796 | tag = strtok_r (buffer, " ", &sp); | 1795 | tag = strtok_r (buffer, " ", &sp); |
1797 | response = strtok_r (NULL, " ", &sp); | 1796 | response = strtok_r (NULL, " ", &sp); |
1798 | if (!response) response = empty; | 1797 | if (!response) |
1798 | response = empty; | ||
1799 | remainder = strtok_r (NULL, "\n", &sp); | 1799 | remainder = strtok_r (NULL, "\n", &sp); |
1800 | if (!remainder) remainder = empty; | 1800 | if (!remainder) |
1801 | remainder = empty; | ||
1801 | } | 1802 | } |
1802 | 1803 | ||
1803 | /* Is the response untagged ? */ | 1804 | /* Is the response untagged ? */ |
... | @@ -1831,6 +1832,7 @@ imap_parse (f_imap_t f_imap) | ... | @@ -1831,6 +1832,7 @@ imap_parse (f_imap_t f_imap) |
1831 | is not supported by this implementation. If the | 1832 | is not supported by this implementation. If the |
1832 | optional list of charsets is given, this lists the | 1833 | optional list of charsets is given, this lists the |
1833 | charsets that are supported by this implementation. */ | 1834 | charsets that are supported by this implementation. */ |
1835 | mu_error ("BADCHARSET: %s\n", (sp) ? sp : ""); | ||
1834 | } | 1836 | } |
1835 | else if (strcasecmp (subtag, "CAPABILITY") == 0) | 1837 | else if (strcasecmp (subtag, "CAPABILITY") == 0) |
1836 | { | 1838 | { |
... | @@ -1851,12 +1853,14 @@ imap_parse (f_imap_t f_imap) | ... | @@ -1851,12 +1853,14 @@ imap_parse (f_imap_t f_imap) |
1851 | mailbox name. This is a hint to the client that the | 1853 | mailbox name. This is a hint to the client that the |
1852 | operation can succeed if the SELECT or EXAMINE is | 1854 | operation can succeed if the SELECT or EXAMINE is |
1853 | reissued with the new mailbox name. */ | 1855 | reissued with the new mailbox name. */ |
1856 | mu_error ("NEWNAME: %s\n", (sp) ? sp : ""); | ||
1854 | } | 1857 | } |
1855 | else if (strcasecmp (subtag, "PARSE") == 0) | 1858 | else if (strcasecmp (subtag, "PARSE") == 0) |
1856 | { | 1859 | { |
1857 | /* The human-readable text represents an error in | 1860 | /* The human-readable text represents an error in |
1858 | parsing the [RFC-822] header or [MIME-IMB] headers | 1861 | parsing the [RFC-822] header or [MIME-IMB] headers |
1859 | of a message in the mailbox. */ | 1862 | of a message in the mailbox. */ |
1863 | mu_error ("PARSE: %s\n", (sp) ? sp : ""); | ||
1860 | } | 1864 | } |
1861 | else if (strcasecmp (subtag, "PERMANENTFLAGS") == 0) | 1865 | else if (strcasecmp (subtag, "PERMANENTFLAGS") == 0) |
1862 | { | 1866 | { |
... | @@ -1892,6 +1896,7 @@ imap_parse (f_imap_t f_imap) | ... | @@ -1892,6 +1896,7 @@ imap_parse (f_imap_t f_imap) |
1892 | other reason). This is a hint to the client that | 1896 | other reason). This is a hint to the client that |
1893 | the operation can succeed if the mailbox is first | 1897 | the operation can succeed if the mailbox is first |
1894 | created by the CREATE command. */ | 1898 | created by the CREATE command. */ |
1899 | mu_error ("TRYCREATE: %s\n", (sp) ? sp : ""); | ||
1895 | } | 1900 | } |
1896 | else if (strcasecmp (subtag, "UIDNEXT") == 0) | 1901 | else if (strcasecmp (subtag, "UIDNEXT") == 0) |
1897 | { | 1902 | { |
... | @@ -2031,5 +2036,8 @@ imap_parse (f_imap_t f_imap) | ... | @@ -2031,5 +2036,8 @@ imap_parse (f_imap_t f_imap) |
2031 | } | 2036 | } |
2032 | f_imap->ptr = f_imap->buffer; | 2037 | f_imap->ptr = f_imap->buffer; |
2033 | } | 2038 | } |
2039 | |||
2040 | if (buffer) | ||
2041 | free (buffer); | ||
2034 | return status; | 2042 | return status; |
2035 | } | 2043 | } | ... | ... |
... | @@ -140,10 +140,24 @@ struct _f_imap | ... | @@ -140,10 +140,24 @@ struct _f_imap |
140 | size_t seq; /* Sequence number to build a tag. */ | 140 | size_t seq; /* Sequence number to build a tag. */ |
141 | char *capa; /* Cabilities of the server. */ | 141 | char *capa; /* Cabilities of the server. */ |
142 | size_t flags; | 142 | size_t flags; |
143 | struct literal_string callback; | 143 | |
144 | /* IO use to hold the literal and quoted strings send by | ||
145 | the IMAP server. */ | ||
146 | struct | ||
147 | { | ||
148 | stream_t stream; | ||
149 | off_t offset; | ||
150 | size_t nleft; /* nleft to read in the literal. */ | ||
151 | msg_imap_t msg_imap; | ||
152 | enum imap_state type; | ||
153 | } string; | ||
154 | |||
155 | /* Use for LIST and LSUB. */ | ||
156 | struct folder_list flist; | ||
144 | 157 | ||
145 | int isopen; | 158 | int isopen; |
146 | /* Buffer I/O */ | 159 | |
160 | /* Server channel buffer I/O */ | ||
147 | size_t buflen; | 161 | size_t buflen; |
148 | char *buffer; | 162 | char *buffer; |
149 | char *ptr; | 163 | char *ptr; |
... | @@ -155,7 +169,6 @@ struct _f_imap | ... | @@ -155,7 +169,6 @@ struct _f_imap |
155 | /* Login */ | 169 | /* Login */ |
156 | char *user; | 170 | char *user; |
157 | char *passwd; | 171 | char *passwd; |
158 | |||
159 | }; | 172 | }; |
160 | 173 | ||
161 | struct _m_imap | 174 | struct _m_imap |
... | @@ -187,6 +200,7 @@ struct _msg_imap | ... | @@ -187,6 +200,7 @@ struct _msg_imap |
187 | size_t uid; | 200 | size_t uid; |
188 | 201 | ||
189 | header_t fheader; | 202 | header_t fheader; |
203 | char *internal_date; | ||
190 | 204 | ||
191 | size_t message_size; | 205 | size_t message_size; |
192 | size_t message_lines; | 206 | size_t message_lines; | ... | ... |
... | @@ -174,6 +174,8 @@ free_subparts (msg_imap_t msg_imap) | ... | @@ -174,6 +174,8 @@ free_subparts (msg_imap_t msg_imap) |
174 | free (msg_imap->parts); | 174 | free (msg_imap->parts); |
175 | if (msg_imap->fheader) | 175 | if (msg_imap->fheader) |
176 | header_destroy (&msg_imap->fheader, NULL); | 176 | header_destroy (&msg_imap->fheader, NULL); |
177 | if (msg_imap->internal_date) | ||
178 | free (msg_imap->internal_date); | ||
177 | free(msg_imap); | 179 | free(msg_imap); |
178 | } | 180 | } |
179 | 181 | ||
... | @@ -672,9 +674,15 @@ imap_expunge (mailbox_t mailbox) | ... | @@ -672,9 +674,15 @@ imap_expunge (mailbox_t mailbox) |
672 | { | 674 | { |
673 | case IMAP_NO_STATE: | 675 | case IMAP_NO_STATE: |
674 | { | 676 | { |
675 | char *set; | 677 | char *set = NULL; |
676 | status = delete_to_string (m_imap, &set); | 678 | status = delete_to_string (m_imap, &set); |
677 | CHECK_ERROR (f_imap, status); | 679 | CHECK_ERROR (f_imap, status); |
680 | if (set == NULL || *set == '\0') | ||
681 | { | ||
682 | if (set) | ||
683 | free (set); | ||
684 | return 0; | ||
685 | } | ||
678 | status = imap_writeline (f_imap, | 686 | status = imap_writeline (f_imap, |
679 | "g%d STORE %s +FLAGS.SILENT (\\Deleted)\r\n", | 687 | "g%d STORE %s +FLAGS.SILENT (\\Deleted)\r\n", |
680 | f_imap->seq++, set); | 688 | f_imap->seq++, set); |
... | @@ -1224,6 +1232,9 @@ imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen, | ... | @@ -1224,6 +1232,9 @@ imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen, |
1224 | const char** datep = &date; | 1232 | const char** datep = &date; |
1225 | /* reserve as much space as we need for internal-date */ | 1233 | /* reserve as much space as we need for internal-date */ |
1226 | int status; | 1234 | int status; |
1235 | |||
1236 | if (msg_imap->internal_date == NULL) | ||
1237 | { | ||
1227 | if (f_imap->state == IMAP_NO_STATE) | 1238 | if (f_imap->state == IMAP_NO_STATE) |
1228 | { | 1239 | { |
1229 | /* Select first. */ | 1240 | /* Select first. */ |
... | @@ -1237,9 +1248,17 @@ imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen, | ... | @@ -1237,9 +1248,17 @@ imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen, |
1237 | MAILBOX_DEBUG0 (m_imap->mailbox, MU_DEBUG_PROT, f_imap->buffer); | 1248 | MAILBOX_DEBUG0 (m_imap->mailbox, MU_DEBUG_PROT, f_imap->buffer); |
1238 | f_imap->state = IMAP_FETCH; | 1249 | f_imap->state = IMAP_FETCH; |
1239 | } | 1250 | } |
1240 | status = fetch_operation (f_imap, msg_imap, datebuf, sizeof datebuf, NULL); | 1251 | status = fetch_operation (f_imap, msg_imap, datebuf, |
1252 | sizeof datebuf, NULL); | ||
1241 | if (status != 0) | 1253 | if (status != 0) |
1242 | return status; | 1254 | return status; |
1255 | msg_imap->internal_date = strdup (datebuf); | ||
1256 | } | ||
1257 | else | ||
1258 | { | ||
1259 | date = msg_imap->internal_date; | ||
1260 | datep = &date; | ||
1261 | } | ||
1243 | 1262 | ||
1244 | if (mu_parse_imap_date_time(datep, &tm, &tz) != 0) | 1263 | if (mu_parse_imap_date_time(datep, &tm, &tz) != 0) |
1245 | now = (time_t)-1; | 1264 | now = (time_t)-1; |
... | @@ -1323,6 +1342,10 @@ imap_attr_set_flags (attribute_t attribute, int flag) | ... | @@ -1323,6 +1342,10 @@ imap_attr_set_flags (attribute_t attribute, int flag) |
1323 | f_imap_t f_imap = m_imap->f_imap; | 1342 | f_imap_t f_imap = m_imap->f_imap; |
1324 | int status = 0; | 1343 | int status = 0; |
1325 | 1344 | ||
1345 | /* If already set don't bother. */ | ||
1346 | if (msg_imap->flags & flag) | ||
1347 | return 0; | ||
1348 | |||
1326 | /* The delete FLAG is not pass yet but only on the expunge. */ | 1349 | /* The delete FLAG is not pass yet but only on the expunge. */ |
1327 | if (flag & MU_ATTRIBUTE_DELETED) | 1350 | if (flag & MU_ATTRIBUTE_DELETED) |
1328 | { | 1351 | { |
... | @@ -1705,13 +1728,11 @@ fetch_operation (f_imap_t f_imap, msg_imap_t msg_imap, char *buffer, | ... | @@ -1705,13 +1728,11 @@ fetch_operation (f_imap_t f_imap, msg_imap_t msg_imap, char *buffer, |
1705 | case IMAP_FETCH: | 1728 | case IMAP_FETCH: |
1706 | status = imap_send (f_imap); | 1729 | status = imap_send (f_imap); |
1707 | CHECK_EAGAIN (f_imap, status); | 1730 | CHECK_EAGAIN (f_imap, status); |
1708 | if (f_imap->callback.buffer) | 1731 | stream_truncate (f_imap->string.stream, 0); |
1709 | free (f_imap->callback.buffer); | 1732 | f_imap->string.offset = 0; |
1710 | f_imap->callback.buffer = NULL; | 1733 | f_imap->string.nleft = 0; |
1711 | f_imap->callback.buflen = 0; | 1734 | f_imap->string.type = IMAP_NO_STATE; |
1712 | f_imap->callback.total = 0; | 1735 | f_imap->string.msg_imap = msg_imap; |
1713 | f_imap->callback.nleft = 0; | ||
1714 | f_imap->callback.msg_imap = msg_imap; | ||
1715 | f_imap->state = IMAP_FETCH_ACK; | 1736 | f_imap->state = IMAP_FETCH_ACK; |
1716 | 1737 | ||
1717 | case IMAP_FETCH_ACK: | 1738 | case IMAP_FETCH_ACK: |
... | @@ -1725,25 +1746,21 @@ fetch_operation (f_imap_t f_imap, msg_imap_t msg_imap, char *buffer, | ... | @@ -1725,25 +1746,21 @@ fetch_operation (f_imap_t f_imap, msg_imap_t msg_imap, char *buffer, |
1725 | break; | 1746 | break; |
1726 | } | 1747 | } |
1727 | 1748 | ||
1728 | if (status == 0 && f_imap->isopen == 0 && f_imap->callback.total == 0) | 1749 | f_imap->state = IMAP_NO_STATE; |
1750 | |||
1751 | /* The server may have timeout any case connection is gone away. */ | ||
1752 | if (status == 0 && f_imap->isopen == 0 && f_imap->string.offset == 0) | ||
1729 | status = EBADF; | 1753 | status = EBADF; |
1730 | 1754 | ||
1731 | buflen = min (buflen, f_imap->callback.total); | ||
1732 | if (f_imap->callback.buffer) | ||
1733 | { | ||
1734 | if (buffer) | 1755 | if (buffer) |
1735 | memcpy (buffer, f_imap->callback.buffer, buflen); | 1756 | stream_read (f_imap->string.stream, buffer, buflen, 0, plen); |
1736 | free (f_imap->callback.buffer); | 1757 | else if (plen) |
1737 | } | 1758 | *plen = 0; |
1738 | if (plen) | 1759 | stream_truncate (f_imap->string.stream, 0); |
1739 | *plen = buflen; | 1760 | f_imap->string.offset = 0; |
1740 | f_imap->callback.buffer = NULL; | 1761 | f_imap->string.nleft = 0; |
1741 | f_imap->callback.buflen = 0; | 1762 | f_imap->string.type = IMAP_NO_STATE; |
1742 | f_imap->callback.total = 0; | 1763 | f_imap->string.msg_imap = NULL; |
1743 | f_imap->callback.nleft = 0; | ||
1744 | f_imap->callback.type = 0; | ||
1745 | f_imap->callback.msg_imap = NULL; | ||
1746 | f_imap->state = IMAP_NO_STATE; | ||
1747 | return status; | 1764 | return status; |
1748 | } | 1765 | } |
1749 | 1766 | ... | ... |
... | @@ -22,15 +22,24 @@ | ... | @@ -22,15 +22,24 @@ |
22 | #include <errno.h> | 22 | #include <errno.h> |
23 | #include <stdlib.h> | 23 | #include <stdlib.h> |
24 | #include <string.h> | 24 | #include <string.h> |
25 | #include <sys/stat.h> | ||
26 | #include <unistd.h> | ||
27 | #include <stdio.h> | ||
25 | 28 | ||
26 | #include <sys/types.h> | 29 | #include <sys/types.h> |
27 | 30 | ||
28 | #include <mailutils/stream.h> | 31 | #include <mailutils/stream.h> |
29 | 32 | ||
33 | #undef min | ||
34 | #define min(a,b) ((a) < (b) ? (a) : (b)) | ||
35 | |||
36 | #define MU_STREAM_MEMORY_BLOCKSIZE 128 | ||
37 | |||
30 | struct _memory_stream | 38 | struct _memory_stream |
31 | { | 39 | { |
32 | char *ptr; | 40 | char *ptr; |
33 | size_t size; | 41 | size_t size; |
42 | size_t capacity; | ||
34 | }; | 43 | }; |
35 | 44 | ||
36 | static void | 45 | static void |
... | @@ -71,7 +80,7 @@ _memory_readline (stream_t stream, char *optr, size_t osize, | ... | @@ -71,7 +80,7 @@ _memory_readline (stream_t stream, char *optr, size_t osize, |
71 | osize--; | 80 | osize--; |
72 | nl = memchr (mfs->ptr + offset, '\n', mfs->size - offset); | 81 | nl = memchr (mfs->ptr + offset, '\n', mfs->size - offset); |
73 | n = (nl) ? (size_t)(nl - (mfs->ptr + offset) + 1) : mfs->size - offset; | 82 | n = (nl) ? (size_t)(nl - (mfs->ptr + offset) + 1) : mfs->size - offset; |
74 | n = (n > osize) ? osize : n; | 83 | n = min (n, osize); |
75 | memcpy (optr, mfs->ptr + offset, n); | 84 | memcpy (optr, mfs->ptr + offset, n); |
76 | optr[n] = '\0'; | 85 | optr[n] = '\0'; |
77 | } | 86 | } |
... | @@ -87,13 +96,17 @@ _memory_write (stream_t stream, const char *iptr, size_t isize, | ... | @@ -87,13 +96,17 @@ _memory_write (stream_t stream, const char *iptr, size_t isize, |
87 | struct _memory_stream *mfs = stream_get_owner (stream); | 96 | struct _memory_stream *mfs = stream_get_owner (stream); |
88 | 97 | ||
89 | /* Bigger we have to realloc. */ | 98 | /* Bigger we have to realloc. */ |
90 | if (mfs->size < (offset + isize)) | 99 | if (mfs->capacity < (offset + isize)) |
91 | { | 100 | { |
92 | char *tmp = realloc (mfs->ptr, offset + isize); | 101 | /* Realloc by fixed blocks of 128. */ |
102 | int newsize = MU_STREAM_MEMORY_BLOCKSIZE * | ||
103 | (((offset + isize)/MU_STREAM_MEMORY_BLOCKSIZE) + 1); | ||
104 | char *tmp = realloc (mfs->ptr, newsize); | ||
93 | if (tmp == NULL) | 105 | if (tmp == NULL) |
94 | return ENOMEM; | 106 | return ENOMEM; |
95 | mfs->ptr = tmp; | 107 | mfs->ptr = tmp; |
96 | mfs->size = offset + isize; | 108 | mfs->size = offset + isize; |
109 | mfs->capacity = newsize; | ||
97 | } | 110 | } |
98 | 111 | ||
99 | memcpy (mfs->ptr + offset, iptr, isize); | 112 | memcpy (mfs->ptr + offset, iptr, isize); |
... | @@ -109,6 +122,7 @@ _memory_truncate (stream_t stream, off_t len) | ... | @@ -109,6 +122,7 @@ _memory_truncate (stream_t stream, off_t len) |
109 | 122 | ||
110 | if (len == 0) | 123 | if (len == 0) |
111 | { | 124 | { |
125 | if (mfs->ptr) | ||
112 | free (mfs->ptr); | 126 | free (mfs->ptr); |
113 | mfs->ptr = NULL; | 127 | mfs->ptr = NULL; |
114 | } | 128 | } |
... | @@ -120,6 +134,7 @@ _memory_truncate (stream_t stream, off_t len) | ... | @@ -120,6 +134,7 @@ _memory_truncate (stream_t stream, off_t len) |
120 | mfs->ptr = tmp; | 134 | mfs->ptr = tmp; |
121 | } | 135 | } |
122 | mfs->size = len; | 136 | mfs->size = len; |
137 | mfs->capacity = len; | ||
123 | return 0; | 138 | return 0; |
124 | } | 139 | } |
125 | 140 | ||
... | @@ -137,11 +152,10 @@ _memory_close (stream_t stream) | ... | @@ -137,11 +152,10 @@ _memory_close (stream_t stream) |
137 | { | 152 | { |
138 | struct _memory_stream *mfs = stream_get_owner (stream); | 153 | struct _memory_stream *mfs = stream_get_owner (stream); |
139 | if (mfs->ptr) | 154 | if (mfs->ptr) |
140 | { | ||
141 | free (mfs->ptr); | 155 | free (mfs->ptr); |
142 | mfs->ptr = NULL; | 156 | mfs->ptr = NULL; |
143 | mfs->size = 0; | 157 | mfs->size = 0; |
144 | } | 158 | mfs->capacity = 0; |
145 | return 0; | 159 | return 0; |
146 | } | 160 | } |
147 | 161 | ||
... | @@ -149,6 +163,7 @@ static int | ... | @@ -149,6 +163,7 @@ static int |
149 | _memory_open (stream_t stream, const char *filename, int port, int flags) | 163 | _memory_open (stream_t stream, const char *filename, int port, int flags) |
150 | { | 164 | { |
151 | struct _memory_stream *mfs = stream_get_owner (stream); | 165 | struct _memory_stream *mfs = stream_get_owner (stream); |
166 | int status = 0; | ||
152 | 167 | ||
153 | (void)port; /* Ignored. */ | 168 | (void)port; /* Ignored. */ |
154 | (void)filename; /* Ignored. */ | 169 | (void)filename; /* Ignored. */ |
... | @@ -156,13 +171,47 @@ _memory_open (stream_t stream, const char *filename, int port, int flags) | ... | @@ -156,13 +171,47 @@ _memory_open (stream_t stream, const char *filename, int port, int flags) |
156 | 171 | ||
157 | /* Close any previous file. */ | 172 | /* Close any previous file. */ |
158 | if (mfs->ptr) | 173 | if (mfs->ptr) |
174 | free (mfs->ptr); | ||
175 | mfs->ptr = NULL; | ||
176 | mfs->size = 0; | ||
177 | mfs->capacity = 0; | ||
178 | stream_set_flags (stream, flags |MU_STREAM_NO_CHECK); | ||
179 | if (filename) | ||
180 | { | ||
181 | struct stat statbuf; | ||
182 | if (stat (filename, &statbuf) == 0) | ||
183 | { | ||
184 | mfs->ptr = calloc (statbuf.st_size, 1); | ||
185 | if (mfs->ptr) | ||
186 | { | ||
187 | FILE *fp; | ||
188 | mfs->capacity = statbuf.st_size; | ||
189 | mfs->size = statbuf.st_size; | ||
190 | fp = fopen (filename, "r"); | ||
191 | if (fp) | ||
192 | { | ||
193 | size_t r = fread (mfs->ptr, mfs->size, 1, fp); | ||
194 | if (r != mfs->size) | ||
195 | status = EIO; | ||
196 | fclose (fp); | ||
197 | } | ||
198 | else | ||
199 | status = errno; | ||
200 | if (status != 0) | ||
159 | { | 201 | { |
160 | free (mfs->ptr); | 202 | free (mfs->ptr); |
161 | mfs->ptr = NULL; | 203 | mfs->ptr = NULL; |
204 | mfs->capacity = 0; | ||
162 | mfs->size = 0; | 205 | mfs->size = 0; |
163 | } | 206 | } |
164 | stream_set_flags (stream, flags |MU_STREAM_NO_CHECK); | 207 | } |
165 | return 0; | 208 | else |
209 | status = ENOMEM; | ||
210 | } | ||
211 | else | ||
212 | status = EIO; | ||
213 | } | ||
214 | return status; | ||
166 | } | 215 | } |
167 | 216 | ||
168 | int | 217 | int | ... | ... |
... | @@ -60,8 +60,7 @@ _stream_memory_read (stream_t stream, void *optr, size_t osize, | ... | @@ -60,8 +60,7 @@ _stream_memory_read (stream_t stream, void *optr, size_t osize, |
60 | mu_refcount_lock (mem->refcount); | 60 | mu_refcount_lock (mem->refcount); |
61 | if (mem->ptr != NULL && (offset < (off_t)mem->size)) | 61 | if (mem->ptr != NULL && (offset < (off_t)mem->size)) |
62 | { | 62 | { |
63 | n = ((offset + osize) > mem->size) ? | 63 | n = ((offset + osize) > mem->size) ? mem->size - offset : osize; |
64 | mem->size - offset : osize; | ||
65 | memcpy (optr, mem->ptr + offset, n); | 64 | memcpy (optr, mem->ptr + offset, n); |
66 | } | 65 | } |
67 | mu_refcount_unlock (mem->refcount); | 66 | mu_refcount_unlock (mem->refcount); |
... | @@ -130,6 +129,7 @@ _stream_memory_truncate (stream_t stream, off_t len) | ... | @@ -130,6 +129,7 @@ _stream_memory_truncate (stream_t stream, off_t len) |
130 | mu_refcount_lock (mem->refcount); | 129 | mu_refcount_lock (mem->refcount); |
131 | if (len == 0) | 130 | if (len == 0) |
132 | { | 131 | { |
132 | if (mem->ptr) | ||
133 | free (mem->ptr); | 133 | free (mem->ptr); |
134 | mem->ptr = NULL; | 134 | mem->ptr = NULL; |
135 | } | 135 | } | ... | ... |
-
Please register or sign in to post a comment