Commit 1270a9f6 1270a9f683827885e91a39e4088d2297af4b5987 by Sergey Poznyakoff

Various fixes in imap4d.

Imap4d successfully passes all tests.

* imap4d/close.c (imap4d_close0): Fix improper use of MU_STREAM_READ
(flags changed their semantics since then).
* imap4d/fetch.c: Send \n terminated lines, rely on filters to recode
line terminators to \r\n.
(fetch_io): Rewrite using CRLF encoder and util_copy_out.
(_frt_header_fields): Rewind memory stream before reading from it.

* imap4d/auth_gsasl.c: Send \n terminated lines, rely on filters
to recode line terminators to \r\n.
* imap4d/auth_gss.c: Likewise.
* imap4d/capability.c: Likewise.
* imap4d/copy.c: Likewise.
* imap4d/id.c: Likewise.
* imap4d/idle.c: Likewise.
* imap4d/list.c: Likewise.
* imap4d/namespace.c: Likewise.
* imap4d/preauth.c: Likewise.
* imap4d/search.c: Likewise.
* imap4d/status.c: Likewise.
* imap4d/store.c: Likewise.
* imap4d/select.c: Likewise.
(imap4d_select_status): Fix improper use of MU_STREAM_READ.

* imap4d/util.c: Send \n terminated lines, rely on filters
to recode line terminators to \r\n.
(util_setio): Apply CRLF filters to both input and output streams
(in opposite directions).
(util_copy_out): New function.
(remove_cr): Remove.
* imap4d/imap4d.h (util_copy_out): New prototype.
1 parent 012b6c7f
...@@ -95,7 +95,7 @@ auth_gsasl (struct imap4d_command *command, char *auth_type, char **username) ...@@ -95,7 +95,7 @@ auth_gsasl (struct imap4d_command *command, char *auth_type, char **username)
95 while ((rc = gsasl_step64 (sess_ctx, input_str, &output)) 95 while ((rc = gsasl_step64 (sess_ctx, input_str, &output))
96 == GSASL_NEEDS_MORE) 96 == GSASL_NEEDS_MORE)
97 { 97 {
98 util_send ("+ %s\r\n", output); 98 util_send ("+ %s\n", output);
99 imap4d_getline (&input_str, &input_size, &input_len); 99 imap4d_getline (&input_str, &input_size, &input_len);
100 } 100 }
101 101
...@@ -112,7 +112,7 @@ auth_gsasl (struct imap4d_command *command, char *auth_type, char **username) ...@@ -112,7 +112,7 @@ auth_gsasl (struct imap4d_command *command, char *auth_type, char **username)
112 returned, and clients must respond with an empty response. */ 112 returned, and clients must respond with an empty response. */
113 if (output[0]) 113 if (output[0])
114 { 114 {
115 util_send ("+ %s\r\n", output); 115 util_send ("+ %s\n", output);
116 imap4d_getline (&input_str, &input_size, &input_len); 116 imap4d_getline (&input_str, &input_size, &input_len);
117 if (input_len != 0) 117 if (input_len != 0)
118 { 118 {
......
...@@ -163,7 +163,7 @@ auth_gssapi (struct imap4d_command *command, ...@@ -163,7 +163,7 @@ auth_gssapi (struct imap4d_command *command,
163 163
164 /* Start the dialogue */ 164 /* Start the dialogue */
165 165
166 util_send ("+ \r\n"); 166 util_send ("+ \n");
167 util_flush_output (); 167 util_flush_output ();
168 168
169 context = GSS_C_NO_CONTEXT; 169 context = GSS_C_NO_CONTEXT;
...@@ -192,7 +192,7 @@ auth_gssapi (struct imap4d_command *command, ...@@ -192,7 +192,7 @@ auth_gssapi (struct imap4d_command *command,
192 if (outbuf.length) 192 if (outbuf.length)
193 { 193 {
194 mu_base64_encode (outbuf.value, outbuf.length, &tmp, &size); 194 mu_base64_encode (outbuf.value, outbuf.length, &tmp, &size);
195 util_send ("+ %s\r\n", tmp); 195 util_send ("+ %s\n", tmp);
196 free (tmp); 196 free (tmp);
197 gss_release_buffer (&min_stat, &outbuf); 197 gss_release_buffer (&min_stat, &outbuf);
198 } 198 }
...@@ -212,7 +212,7 @@ auth_gssapi (struct imap4d_command *command, ...@@ -212,7 +212,7 @@ auth_gssapi (struct imap4d_command *command,
212 if (outbuf.length) 212 if (outbuf.length)
213 { 213 {
214 mu_base64_encode (outbuf.value, outbuf.length, &tmp, &size); 214 mu_base64_encode (outbuf.value, outbuf.length, &tmp, &size);
215 util_send ("+ %s\r\n", tmp); 215 util_send ("+ %s\n", tmp);
216 free (tmp); 216 free (tmp);
217 gss_release_buffer (&min_stat, &outbuf); 217 gss_release_buffer (&min_stat, &outbuf);
218 imap4d_getline (&token_str, &token_size, &token_len); 218 imap4d_getline (&token_str, &token_size, &token_len);
...@@ -232,7 +232,7 @@ auth_gssapi (struct imap4d_command *command, ...@@ -232,7 +232,7 @@ auth_gssapi (struct imap4d_command *command,
232 } 232 }
233 233
234 mu_base64_encode (outbuf.value, outbuf.length, &tmp, &size); 234 mu_base64_encode (outbuf.value, outbuf.length, &tmp, &size);
235 util_send ("+ %s\r\n", tmp); 235 util_send ("+ %s\n", tmp);
236 free (tmp); 236 free (tmp);
237 237
238 imap4d_getline (&token_str, &token_size, &token_len); 238 imap4d_getline (&token_str, &token_size, &token_len);
......
...@@ -80,7 +80,7 @@ imap4d_capability (struct imap4d_command *command, imap4d_tokbuf_t tok) ...@@ -80,7 +80,7 @@ imap4d_capability (struct imap4d_command *command, imap4d_tokbuf_t tok)
80 mu_list_do (capa_list, print_capa, NULL); 80 mu_list_do (capa_list, print_capa, NULL);
81 81
82 imap4d_auth_capability (); 82 imap4d_auth_capability ();
83 util_send ("\r\n"); 83 util_send ("\n");
84 84
85 return util_finish (command, RESP_OK, "Completed"); 85 return util_finish (command, RESP_OK, "Completed");
86 } 86 }
......
...@@ -30,7 +30,7 @@ imap4d_close0 (struct imap4d_command *command, imap4d_tokbuf_t tok, ...@@ -30,7 +30,7 @@ imap4d_close0 (struct imap4d_command *command, imap4d_tokbuf_t tok,
30 return util_finish (command, RESP_BAD, "Invalid arguments"); 30 return util_finish (command, RESP_BAD, "Invalid arguments");
31 31
32 mu_mailbox_get_flags (mbox, &flags); 32 mu_mailbox_get_flags (mbox, &flags);
33 if ((flags & MU_STREAM_READ) == 0) 33 if (flags & MU_STREAM_WRITE)
34 { 34 {
35 status = mu_mailbox_flush (mbox, expunge); 35 status = mu_mailbox_flush (mbox, expunge);
36 if (status) 36 if (status)
......
...@@ -52,7 +52,7 @@ imap4d_copy (struct imap4d_command *command, imap4d_tokbuf_t tok) ...@@ -52,7 +52,7 @@ imap4d_copy (struct imap4d_command *command, imap4d_tokbuf_t tok)
52 int new_state = (rc == RESP_OK) ? command->success : command->failure; 52 int new_state = (rc == RESP_OK) ? command->success : command->failure;
53 if (new_state != STATE_NONE) 53 if (new_state != STATE_NONE)
54 state = new_state; 54 state = new_state;
55 return util_send ("%s %s\r\n", command->tag, text); 55 return util_send ("%s %s\n", command->tag, text);
56 } 56 }
57 return util_finish (command, rc, "%s", text); 57 return util_finish (command, rc, "%s", text);
58 } 58 }
......
...@@ -690,39 +690,36 @@ static int ...@@ -690,39 +690,36 @@ static int
690 fetch_io (mu_stream_t stream, size_t start, size_t size, size_t max) 690 fetch_io (mu_stream_t stream, size_t start, size_t size, size_t max)
691 { 691 {
692 mu_stream_t rfc = NULL; 692 mu_stream_t rfc = NULL;
693
693 size_t n = 0; 694 size_t n = 0;
694 695
695 mu_filter_create (&rfc, stream, "rfc822", MU_FILTER_ENCODE, 696 mu_filter_create (&rfc, stream, "rfc822", MU_FILTER_ENCODE,
696 MU_STREAM_READ|MU_STREAM_NO_CHECK|MU_STREAM_NO_CLOSE); 697 MU_STREAM_READ|MU_STREAM_SEEK|MU_STREAM_NO_CLOSE);
697 698
698 if (start == 0 && size == (size_t) -1) 699 if (start == 0 && size == (size_t) -1)
699 { 700 {
700 char *buffer;
701 size_t bufsize;
702 int rc; 701 int rc;
703 702
704 for (bufsize = max; (buffer = malloc (bufsize)) == NULL; bufsize /= 2)
705 if (bufsize < 512)
706 imap4d_bye (ERR_NO_MEM);
707
708 rc = mu_stream_seek (rfc, 0, MU_SEEK_SET, NULL); 703 rc = mu_stream_seek (rfc, 0, MU_SEEK_SET, NULL);
709 if (rc) 704 if (rc)
710 { 705 {
711 mu_error ("seek error: %s", mu_stream_strerror (rfc, rc)); 706 mu_error ("seek error: %s", mu_stream_strerror (stream, rc));
712 return RESP_BAD; 707 return RESP_BAD;
713 } 708 }
714 if (max) 709 if (max)
715 { 710 {
716 util_send (" {%lu}\r\n", (unsigned long) max); 711 util_send (" {%lu}\n", (unsigned long) max);
717 while (mu_stream_read (rfc, buffer, bufsize, &n) == 0 && n > 0) 712 util_copy_out (rfc, max);
718 util_send_bytes (buffer, n);
719
720 /* FIXME: Make sure exactly max bytes were sent */ 713 /* FIXME: Make sure exactly max bytes were sent */
721 free (buffer);
722 } 714 }
723 else 715 else
724 util_send (" \"\""); 716 util_send (" \"\"");
725 } 717 }
718 else if (start > max)
719 {
720 util_send ("<%lu>", (unsigned long) start);
721 util_send (" \"\"");
722 }
726 else if (size + 2 < size) /* Check for integer overflow */ 723 else if (size + 2 < size) /* Check for integer overflow */
727 { 724 {
728 mu_stream_destroy (&rfc); 725 mu_stream_destroy (&rfc);
...@@ -738,16 +735,17 @@ fetch_io (mu_stream_t stream, size_t start, size_t size, size_t max) ...@@ -738,16 +735,17 @@ fetch_io (mu_stream_t stream, size_t start, size_t size, size_t max)
738 if (!p) 735 if (!p)
739 imap4d_bye (ERR_NO_MEM); 736 imap4d_bye (ERR_NO_MEM);
740 737
741 rc = mu_stream_seek (stream, start, MU_SEEK_SET, NULL); 738 rc = mu_stream_seek (rfc, start, MU_SEEK_SET, NULL);
742 if (rc) 739 if (rc)
743 { 740 {
744 mu_error ("seek error: %s", mu_stream_strerror (rfc, rc)); 741 mu_error ("seek error: %s", mu_stream_strerror (rfc, rc));
745 free (buffer); 742 free (buffer);
743 mu_stream_destroy (&rfc);
746 return RESP_BAD; 744 return RESP_BAD;
747 } 745 }
748 746
749 while (total < size 747 while (total < size
750 && mu_stream_read (rfc, p, size - total + 1, &n) == 0 748 && mu_stream_read (rfc, p, size - total, &n) == 0
751 && n > 0) 749 && n > 0)
752 { 750 {
753 total += n; 751 total += n;
...@@ -757,7 +755,7 @@ fetch_io (mu_stream_t stream, size_t start, size_t size, size_t max) ...@@ -757,7 +755,7 @@ fetch_io (mu_stream_t stream, size_t start, size_t size, size_t max)
757 util_send ("<%lu>", (unsigned long) start); 755 util_send ("<%lu>", (unsigned long) start);
758 if (total) 756 if (total)
759 { 757 {
760 util_send (" {%lu}\r\n", (unsigned long) total); 758 util_send (" {%lu}\n", (unsigned long) total);
761 util_send_bytes (buffer, total); 759 util_send_bytes (buffer, total);
762 } 760 }
763 else 761 else
...@@ -1071,6 +1069,7 @@ _frt_header_fields (struct fetch_function_closure *ffc, ...@@ -1071,6 +1069,7 @@ _frt_header_fields (struct fetch_function_closure *ffc,
1071 1069
1072 /* Output collected data */ 1070 /* Output collected data */
1073 mu_stream_size (stream, &size); 1071 mu_stream_size (stream, &size);
1072 mu_stream_seek (stream, 0, MU_SEEK_SET, NULL);
1074 status = fetch_io (stream, ffc->start, ffc->size, size + lines); 1073 status = fetch_io (stream, ffc->start, ffc->size, size + lines);
1075 mu_stream_destroy (&stream); 1074 mu_stream_destroy (&stream);
1076 1075
...@@ -1648,7 +1647,7 @@ imap4d_fetch0 (imap4d_tokbuf_t tok, int isuid, char **err_text) ...@@ -1648,7 +1647,7 @@ imap4d_fetch0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
1648 util_send ("* %lu FETCH (", (unsigned long) frc.msgno); 1647 util_send ("* %lu FETCH (", (unsigned long) frc.msgno);
1649 frc.eltno = 0; 1648 frc.eltno = 0;
1650 rc = mu_list_do (pclos.fnlist, _do_fetch, &frc); 1649 rc = mu_list_do (pclos.fnlist, _do_fetch, &frc);
1651 util_send (")\r\n"); 1650 util_send (")\n");
1652 } 1651 }
1653 } 1652 }
1654 } 1653 }
...@@ -1684,4 +1683,3 @@ imap4d_fetch (struct imap4d_command *command, imap4d_tokbuf_t tok) ...@@ -1684,4 +1683,3 @@ imap4d_fetch (struct imap4d_command *command, imap4d_tokbuf_t tok)
1684 rc = imap4d_fetch0 (tok, 0, &err_text); 1683 rc = imap4d_fetch0 (tok, 0, &err_text);
1685 return util_finish (command, rc, "%s", err_text); 1684 return util_finish (command, rc, "%s", err_text);
1686 } 1685 }
1687
......
...@@ -202,7 +202,7 @@ imap4d_id (struct imap4d_command *command, imap4d_tokbuf_t tok) ...@@ -202,7 +202,7 @@ imap4d_id (struct imap4d_command *command, imap4d_tokbuf_t tok)
202 } 202 }
203 mu_iterator_destroy (&itr); 203 mu_iterator_destroy (&itr);
204 if (outcnt) 204 if (outcnt)
205 util_send (")\r\n"); 205 util_send (")\n");
206 } 206 }
207 return util_finish (command, RESP_OK, "Completed"); 207 return util_finish (command, RESP_OK, "Completed");
208 } 208 }
......
...@@ -32,7 +32,7 @@ imap4d_idle (struct imap4d_command *command, imap4d_tokbuf_t tok) ...@@ -32,7 +32,7 @@ imap4d_idle (struct imap4d_command *command, imap4d_tokbuf_t tok)
32 if (util_wait_input (0) == -1) 32 if (util_wait_input (0) == -1)
33 return util_finish (command, RESP_NO, "Cannot idle"); 33 return util_finish (command, RESP_NO, "Cannot idle");
34 34
35 util_send ("+ idling\r\n"); 35 util_send ("+ idling\n");
36 util_flush_output (); 36 util_flush_output ();
37 37
38 start = time (NULL); 38 start = time (NULL);
......
...@@ -202,7 +202,7 @@ extern int imap4d_transcript; ...@@ -202,7 +202,7 @@ extern int imap4d_transcript;
202 extern mu_list_t imap4d_id_list; 202 extern mu_list_t imap4d_id_list;
203 extern int imap4d_argc; 203 extern int imap4d_argc;
204 extern char **imap4d_argv; 204 extern char **imap4d_argv;
205 205
206 #ifndef HAVE_STRTOK_R 206 #ifndef HAVE_STRTOK_R
207 extern char *strtok_r (char *s, const char *delim, char **save_ptr); 207 extern char *strtok_r (char *s, const char *delim, char **save_ptr);
208 #endif 208 #endif
...@@ -334,6 +334,8 @@ extern int util_send (const char *, ...) MU_PRINTFLIKE(1,2); ...@@ -334,6 +334,8 @@ extern int util_send (const char *, ...) MU_PRINTFLIKE(1,2);
334 extern int util_send_bytes (const char *buf, size_t size); 334 extern int util_send_bytes (const char *buf, size_t size);
335 extern int util_send_qstring (const char *); 335 extern int util_send_qstring (const char *);
336 extern int util_send_literal (const char *); 336 extern int util_send_literal (const char *);
337 extern int util_copy_out (mu_stream_t str, size_t size);
338
337 extern int util_start (char *); 339 extern int util_start (char *);
338 extern int util_finish (struct imap4d_command *, int, const char *, ...) 340 extern int util_finish (struct imap4d_command *, int, const char *, ...)
339 MU_PRINTFLIKE(3,4); 341 MU_PRINTFLIKE(3,4);
......
...@@ -97,11 +97,11 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data) ...@@ -97,11 +97,11 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data)
97 name = refinfo->buf; 97 name = refinfo->buf;
98 98
99 if (strpbrk (name, "\"{}")) 99 if (strpbrk (name, "\"{}"))
100 util_send ("{%lu}\r\n%s\r\n", (unsigned long) strlen (name), name); 100 util_send ("{%lu}\n%s\n", (unsigned long) strlen (name), name);
101 else if (is_atom (name)) 101 else if (is_atom (name))
102 util_send ("%s\r\n", name); 102 util_send ("%s\n", name);
103 else 103 else
104 util_send ("\"%s\"\r\n", name); 104 util_send ("\"%s\"\n", name);
105 return 0; 105 return 0;
106 } 106 }
107 107
......
...@@ -126,7 +126,7 @@ imap4d_namespace (struct imap4d_command *command, imap4d_tokbuf_t tok) ...@@ -126,7 +126,7 @@ imap4d_namespace (struct imap4d_command *command, imap4d_tokbuf_t tok)
126 print_namespace (NS_OTHER); 126 print_namespace (NS_OTHER);
127 util_send (" "); 127 util_send (" ");
128 print_namespace (NS_SHARED); 128 print_namespace (NS_SHARED);
129 util_send ("\r\n"); 129 util_send ("\n");
130 130
131 return util_finish (command, RESP_OK, "Completed"); 131 return util_finish (command, RESP_OK, "Completed");
132 } 132 }
......
...@@ -366,7 +366,7 @@ do_preauth_ident (struct sockaddr *clt_sa, struct sockaddr *srv_sa) ...@@ -366,7 +366,7 @@ do_preauth_ident (struct sockaddr *clt_sa, struct sockaddr *srv_sa)
366 return NULL; 366 return NULL;
367 } 367 }
368 368
369 mu_stream_printf (stream, "%u , %u\r\n", 369 mu_stream_printf (stream, "%u , %u\n",
370 ntohs (clt_addr->sin_port), 370 ntohs (clt_addr->sin_port),
371 ntohs (srv_addr->sin_port)); 371 ntohs (srv_addr->sin_port));
372 mu_stream_shutdown (stream, MU_STREAM_WRITE); 372 mu_stream_shutdown (stream, MU_STREAM_WRITE);
......
...@@ -363,7 +363,7 @@ do_search (struct parsebuf *pb) ...@@ -363,7 +363,7 @@ do_search (struct parsebuf *pb)
363 util_send (" %s", mu_umaxtostr (0, pb->msgno)); 363 util_send (" %s", mu_umaxtostr (0, pb->msgno));
364 } 364 }
365 } 365 }
366 util_send ("\r\n"); 366 util_send ("\n");
367 } 367 }
368 368
369 /* Parse buffer functions */ 369 /* Parse buffer functions */
......
...@@ -74,9 +74,9 @@ imap4d_select0 (struct imap4d_command *command, const char *mboxname, ...@@ -74,9 +74,9 @@ imap4d_select0 (struct imap4d_command *command, const char *mboxname,
74 { 74 {
75 free (mailbox_name); 75 free (mailbox_name);
76 /* Need to set the state explicitely for select. */ 76 /* Need to set the state explicitely for select. */
77 return util_send ("%s OK [%s] %s Completed\r\n", command->tag, 77 return util_send ("%s OK [%s] %s Completed\n", command->tag,
78 (flags & MU_STREAM_READ) ? 78 ((flags & MU_STREAM_RDWR) == MU_STREAM_RDWR) ?
79 "READ-ONLY" : "READ-WRITE", command->name); 79 "READ-WRITE" : "READ-ONLY", command->name);
80 } 80 }
81 } 81 }
82 82
...@@ -119,7 +119,7 @@ imap4d_select_status () ...@@ -119,7 +119,7 @@ imap4d_select_status ()
119 /* FIXME: 119 /* FIXME:
120 - '\*' can be supported if we use the attribute_set userflag() 120 - '\*' can be supported if we use the attribute_set userflag()
121 - Answered is still not set in the mailbox code. */ 121 - Answered is still not set in the mailbox code. */
122 if (select_flags & MU_STREAM_READ) 122 if (!(select_flags & MU_STREAM_WRITE))
123 util_out (RESP_OK, "[PERMANENTFLAGS ()] No Permanent flags"); 123 util_out (RESP_OK, "[PERMANENTFLAGS ()] No Permanent flags");
124 else 124 else
125 util_out (RESP_OK, "[PERMANENTFLAGS (%s)] Permanent flags", pflags); 125 util_out (RESP_OK, "[PERMANENTFLAGS (%s)] Permanent flags", pflags);
......
...@@ -136,7 +136,7 @@ imap4d_status (struct imap4d_command *command, imap4d_tokbuf_t tok) ...@@ -136,7 +136,7 @@ imap4d_status (struct imap4d_command *command, imap4d_tokbuf_t tok)
136 136
137 137
138 if (count > 0) 138 if (count > 0)
139 util_send (")\r\n"); 139 util_send (")\n");
140 mu_mailbox_close (smbox); 140 mu_mailbox_close (smbox);
141 } 141 }
142 mu_mailbox_destroy (&smbox); 142 mu_mailbox_destroy (&smbox);
......
...@@ -157,7 +157,7 @@ imap4d_store0 (imap4d_tokbuf_t tok, int isuid, char **ptext) ...@@ -157,7 +157,7 @@ imap4d_store0 (imap4d_tokbuf_t tok, int isuid, char **ptext)
157 util_send ("UID %lu ", (unsigned long) msgno); 157 util_send ("UID %lu ", (unsigned long) msgno);
158 util_send ("FLAGS ("); 158 util_send ("FLAGS (");
159 util_print_flags (attr); 159 util_print_flags (attr);
160 util_send ("))\r\n"); 160 util_send ("))\n");
161 } 161 }
162 /* Update the flags of uid table. */ 162 /* Update the flags of uid table. */
163 imap4d_sync_flags (pclos.set[i]); 163 imap4d_sync_flags (pclos.set[i]);
......
...@@ -270,6 +270,12 @@ util_msgset (char *s, size_t ** set, int *n, int isuid) ...@@ -270,6 +270,12 @@ util_msgset (char *s, size_t ** set, int *n, int isuid)
270 } 270 }
271 271
272 int 272 int
273 util_copy_out (mu_stream_t str, size_t size)
274 {
275 return mu_stream_copy (ostream, str, size);
276 }
277
278 int
273 util_send_bytes (const char *buf, size_t size) 279 util_send_bytes (const char *buf, size_t size)
274 { 280 {
275 return mu_stream_write (ostream, buf, size, NULL); 281 return mu_stream_write (ostream, buf, size, NULL);
...@@ -325,7 +331,7 @@ util_send_qstring (const char *buffer) ...@@ -325,7 +331,7 @@ util_send_qstring (const char *buffer)
325 int 331 int
326 util_send_literal (const char *buffer) 332 util_send_literal (const char *buffer)
327 { 333 {
328 return util_send ("{%lu}\r\n%s", (unsigned long) strlen (buffer), buffer); 334 return util_send ("{%lu}\n%s", (unsigned long) strlen (buffer), buffer);
329 } 335 }
330 336
331 /* Send an unsolicited response. */ 337 /* Send an unsolicited response. */
...@@ -337,7 +343,7 @@ util_out (int rc, const char *format, ...) ...@@ -337,7 +343,7 @@ util_out (int rc, const char *format, ...)
337 int status = 0; 343 int status = 0;
338 va_list ap; 344 va_list ap;
339 345
340 asprintf (&tempbuf, "* %s%s\r\n", sc2string (rc), format); 346 asprintf (&tempbuf, "* %s%s\n", sc2string (rc), format);
341 va_start (ap, format); 347 va_start (ap, format);
342 vasprintf (&buf, tempbuf, ap); 348 vasprintf (&buf, tempbuf, ap);
343 va_end (ap); 349 va_end (ap);
...@@ -346,7 +352,7 @@ util_out (int rc, const char *format, ...) ...@@ -346,7 +352,7 @@ util_out (int rc, const char *format, ...)
346 352
347 if (imap4d_transcript) 353 if (imap4d_transcript)
348 { 354 {
349 int len = strcspn (buf, "\r\n"); 355 int len = strcspn (buf, "\n");
350 mu_diag_output (MU_DIAG_DEBUG, "sent: %*.*s", len, len, buf); 356 mu_diag_output (MU_DIAG_DEBUG, "sent: %*.*s", len, len, buf);
351 } 357 }
352 358
...@@ -393,7 +399,7 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...) ...@@ -393,7 +399,7 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...)
393 399
394 mu_stream_write (ostream, buf, strlen (buf), NULL); 400 mu_stream_write (ostream, buf, strlen (buf), NULL);
395 free (buf); 401 free (buf);
396 mu_stream_write (ostream, "\r\n", 2, NULL); 402 mu_stream_write (ostream, "\n", 2, NULL);
397 403
398 /* Reset the state. */ 404 /* Reset the state. */
399 if (rc == RESP_OK) 405 if (rc == RESP_OK)
...@@ -800,16 +806,24 @@ util_uidvalidity (mu_mailbox_t smbox, unsigned long *uidvp) ...@@ -800,16 +806,24 @@ util_uidvalidity (mu_mailbox_t smbox, unsigned long *uidvp)
800 void 806 void
801 util_setio (FILE *in, FILE *out) 807 util_setio (FILE *in, FILE *out)
802 { 808 {
809 mu_stream_t tmp;
810
803 if (!in) 811 if (!in)
804 imap4d_bye (ERR_NO_IFILE); 812 imap4d_bye (ERR_NO_IFILE);
805 if (!out) 813 if (!out)
806 imap4d_bye (ERR_NO_OFILE); 814 imap4d_bye (ERR_NO_OFILE);
807 815
808 if (mu_stdio_stream_create (&istream, fileno (in), MU_STREAM_NO_CLOSE)) 816 if (mu_stdio_stream_create (&tmp, fileno (in), MU_STREAM_NO_CLOSE))
809 imap4d_bye (ERR_NO_IFILE); 817 imap4d_bye (ERR_NO_IFILE);
810 if (mu_stdio_stream_create (&ostream, fileno (out), MU_STREAM_NO_CLOSE)) 818 mu_stream_set_buffer (tmp, mu_buffer_line, 1024);
811 imap4d_bye (ERR_NO_OFILE); 819 mu_filter_create (&istream, tmp, "rfc822", MU_FILTER_DECODE, MU_STREAM_READ);
812 mu_stream_set_buffer (istream, mu_buffer_line, 1024); 820 mu_stream_set_buffer (istream, mu_buffer_line, 1024);
821
822 if (mu_stdio_stream_create (&tmp, fileno (out), MU_STREAM_NO_CLOSE))
823 imap4d_bye (ERR_NO_OFILE);
824 mu_stream_set_buffer (tmp, mu_buffer_line, 1024);
825 mu_filter_create (&ostream, tmp, "rfc822", MU_FILTER_ENCODE,
826 MU_STREAM_WRITE);
813 mu_stream_set_buffer (ostream, mu_buffer_line, 1024); 827 mu_stream_set_buffer (ostream, mu_buffer_line, 1024);
814 } 828 }
815 829
...@@ -917,7 +931,7 @@ void ...@@ -917,7 +931,7 @@ void
917 util_bye () 931 util_bye ()
918 { 932 {
919 int rc = istream != ostream; 933 int rc = istream != ostream;
920 934
921 mu_stream_close (istream); 935 mu_stream_close (istream);
922 mu_stream_destroy (&istream); 936 mu_stream_destroy (&istream);
923 937
...@@ -926,7 +940,6 @@ util_bye () ...@@ -926,7 +940,6 @@ util_bye ()
926 mu_stream_close (ostream); 940 mu_stream_close (ostream);
927 mu_stream_destroy (&ostream); 941 mu_stream_destroy (&ostream);
928 } 942 }
929
930 mu_list_do (atexit_list, atexit_run, 0); 943 mu_list_do (atexit_list, atexit_run, 0);
931 } 944 }
932 945
...@@ -1021,30 +1034,6 @@ is_atom (const char *s) ...@@ -1021,30 +1034,6 @@ is_atom (const char *s)
1021 1034
1022 1035
1023 static size_t 1036 static size_t
1024 remove_cr (char *line, size_t len)
1025 {
1026 char *prev = NULL;
1027 size_t rlen = len;
1028 char *p;
1029 while ((p = memchr (line, '\r', len)))
1030 {
1031 if (prev)
1032 {
1033 memmove (prev, line, p - line);
1034 prev += p - line;
1035 }
1036 else
1037 prev = p;
1038 rlen--;
1039 len -= p - line + 1;
1040 line = p + 1;
1041 }
1042 if (prev)
1043 memmove (prev, line, len);
1044 return rlen;
1045 }
1046
1047 static size_t
1048 unquote (char *line, size_t len) 1037 unquote (char *line, size_t len)
1049 { 1038 {
1050 char *prev = NULL; 1039 char *prev = NULL;
...@@ -1318,7 +1307,7 @@ imap4d_readline (struct imap4d_tokbuf *tok) ...@@ -1318,7 +1307,7 @@ imap4d_readline (struct imap4d_tokbuf *tok)
1318 /* Client can ask for non-synchronised literal, 1307 /* Client can ask for non-synchronised literal,
1319 if a '+' is appended to the octet count. */ 1308 if a '+' is appended to the octet count. */
1320 if (*sp == '}') 1309 if (*sp == '}')
1321 util_send ("+ GO AHEAD\r\n"); 1310 util_send ("+ GO AHEAD\n");
1322 else if (*sp != '+') 1311 else if (*sp != '+')
1323 break; 1312 break;
1324 imap4d_tokbuf_expand (tok, number + 1); 1313 imap4d_tokbuf_expand (tok, number + 1);
...@@ -1334,7 +1323,6 @@ imap4d_readline (struct imap4d_tokbuf *tok) ...@@ -1334,7 +1323,6 @@ imap4d_readline (struct imap4d_tokbuf *tok)
1334 len += sz; 1323 len += sz;
1335 } 1324 }
1336 check_input_err (rc, len); 1325 check_input_err (rc, len);
1337 len = remove_cr (buf, len);
1338 imap4d_tokbuf_unquote (tok, &off, &len); 1326 imap4d_tokbuf_unquote (tok, &off, &len);
1339 tok->level += len; 1327 tok->level += len;
1340 tok->buffer[tok->level++] = 0; 1328 tok->buffer[tok->level++] = 0;
......