Commit 9f739684 9f73968409cff3e3d5b59dbb5b841d5fcffca582 by Alain Magloire

* mailbox/Makefile.am: filter_trans.c added, trans_stream.c deleted.

	* mailbox/attachment.c (message_create_attachment): use
	filter_create().
	(message_save_attachment): use filter_create().
	* mailbox/body.c (body_set_lines): Wrong comparison for the owner.
	* mailbox/mbx_mbox.c: Do not count the line separtor of part
	of the mailbox.

	* mailbox/url.c (url_is_same_sheme): New function.
	(url_is_same_user): New function.
	(url_is_same_path): New function.
	(url_is_same_host): New function.
	(url_is_same_port): New function.
	* mailbox/folder.c : Moved the is_same_*() functions in url.c
	they can be generally usefull.
	(is_same_sheme): Removed.
	(is_same_user): Removed.
	(is_same_path): Removed.
	(is_same_host): Removed.
	(is_same_port): Removed.

	* mailbox/folder_imap.c (folder_imap_create): New function,
	CREATE a new mailbox.
	(folder_imap_open): Calls folder_imap_create when the MU_STREAM_CREAT
	flag is set.
	* mailbox/mbx_imap.c: Appending messages implemented, if the message
	comes from the same imap folder, it is COPY otherwise APPEND.
	(is_same_folder): New function.
	(imap_append_message): Implemented.
	(attribute_string): New functions.
	(imap_copy_message): New function.
	* mailbox/include/imap0.h: New enum, IMAP_APPEND, IMAP_APPEND_ACK,
	IMAP_APPEND_CONT, IMAP_APPEND_SEND, IMAP_COPY, IMAP_COPY_ACK,
	IMAP_CREATE, IMAP_CREATE_ACK.


* mailbox/parse822.c: New parser.
	* include/mailutils/parse822.h: New file.
	* mailbox/address.c (address_create): Remove the old parsing and use
	parse822 as the underlying engine.
	(address_parse): Removed.
	(gettoken): Removed.
	(quotes): Removed.
	(address_get_personal): Remove the code to unquote, parse822 takes
	care if it. Return value when no field is ENOENT.
	(address_get_comments): Reutrn value when no field ENOENT.
	(address_get_local_part): Reutrn value when no field ENOENT.
	(address_get_domain): Reutrn value when no field ENOENT.
	(address_get_email): Reutrn value when no field ENOENT.
	(address_get_route): Reutrn value when no field ENOENT.
	* mailbox/message.c (message_sender): Use parse822 to retrieve
	the email from the From: field.
	(message_set_mailbox): New function.
	* mailbox/misc.c : Removed the old parsing code.
	(gettoken): Removed.
	(parseaddr): Removed.
	* mailbox/include/misc.h : Removed parseaddr() prototypes.
	From Sam Roberts, the new parse822 parser..
1 parent f9979c0e
...@@ -22,6 +22,7 @@ envelope.c \ ...@@ -22,6 +22,7 @@ envelope.c \
22 file_stream.c \ 22 file_stream.c \
23 filter.c \ 23 filter.c \
24 filter_rfc822.c \ 24 filter_rfc822.c \
25 filter_trans.c \
25 folder.c \ 26 folder.c \
26 folder_imap.c \ 27 folder_imap.c \
27 folder_mbox.c \ 28 folder_mbox.c \
...@@ -50,7 +51,6 @@ sendmail.c \ ...@@ -50,7 +51,6 @@ sendmail.c \
50 smtp.c \ 51 smtp.c \
51 stream.c \ 52 stream.c \
52 tcp.c \ 53 tcp.c \
53 trans_stream.c \
54 url.c \ 54 url.c \
55 url_file.c \ 55 url_file.c \
56 url_imap.c \ 56 url_imap.c \
......
...@@ -27,297 +27,38 @@ ...@@ -27,297 +27,38 @@
27 #include <stdlib.h> 27 #include <stdlib.h>
28 #include <errno.h> 28 #include <errno.h>
29 29
30 #include <address0.h> 30 #include <mailutils/parse822.h>
31 #include <misc.h> 31 #include <misc.h>
32 32 #include <address0.h>
33 /*
34 * parseaddr.c Read a valid RFC822 address with all the comments
35 * etc in it, and return _just_ the email address.
36 *
37 * Version: @(#)parseaddr.c 1.00 02-Apr-1999 miquels@cistron.nl
38 *
39 */
40
41 struct token
42 {
43 struct token *next;
44 char word[1];
45 };
46
47 #define SKIPSPACE(p) do { while(*p && isspace((unsigned char)*p)) p++; } while(0)
48
49 /* Skip everything between quotes. */
50 static void
51 quotes (const char **ptr)
52 {
53 const char *p = *ptr;
54
55 p++;
56 while (*p && *p != '"')
57 {
58 if (*p == '\\' && p[1])
59 p++;
60 p++;
61 }
62 *ptr = p;
63 }
64
65 /* Return the next token. A token can be "<>()," or any "word". */
66 static struct token *
67 gettoken (const char **ptr)
68 {
69 struct token *tok;
70 const char *p = *ptr;
71 const char *begin;
72 int l, quit = 0;
73
74 SKIPSPACE(p);
75 begin = p;
76
77 while (!quit)
78 {
79 switch (*p)
80 {
81 case 0:
82 case ' ':
83 case '\t':
84 case '\n':
85 quit = 1;
86 break;
87 case '(':
88 case ')':
89 case '<':
90 case '>':
91 case ',':
92 if (p == begin)
93 p++;
94 quit = 1;
95 break;
96 case '\\':
97 if (p[1])
98 p++;
99 break;
100 case '"':
101 quotes (&p);
102 break;
103 }
104 if (!quit)
105 p++;
106 }
107
108 l = p - begin;
109 if (l == 0)
110 return NULL;
111 tok = malloc (sizeof (struct token) + l);
112 if (tok == NULL)
113 return NULL;
114 tok->next = NULL;
115 strncpy (tok->word, begin, l);
116 tok->word[l] = 0;
117
118 SKIPSPACE (p);
119 *ptr = p;
120
121 return tok;
122 }
123 33
124 /* Get email address from rfc822 address. */ 34 /* Get email address from rfc822 address. */
125 /* Note: This again as for header.c an awfull way of doing things.
126 Meaning I need a correct rfc822 Parser. This one does not
127 understand group. There is not doubt a better way to do this. */
128
129 static int
130 address_parse (address_t *paddress, const char **paddr)
131 {
132 const char *p;
133 struct token *t, *tok, *last;
134 struct token *brace = NULL;
135 struct token *comments = NULL;
136 struct token *start_comments = NULL;
137 address_t address;
138 int in_comment = 0;
139 int status = 0;
140
141 tok = last = NULL;
142
143 address = *paddress = calloc (1, sizeof (*address));
144 if (address == NULL)
145 return ENOMEM;
146
147 /* Read address, remove comments right away. */
148 p = *paddr;
149 while ((t = gettoken(&p)) != NULL && (t->word[0] != ',' || in_comment))
150 {
151 if (t->word[0] == '(' || t->word[0] == ')' || in_comment)
152 {
153 if (t->word[0] == '(')
154 in_comment++;
155 if (t->word[0] == ')')
156 in_comment--;
157 if (!start_comments)
158 comments = start_comments = t;
159 else
160 {
161 comments->next = t;
162 comments = t;
163 }
164 continue;
165 }
166
167 if (t->word[0] == '<')
168 brace = t;
169
170 if (tok)
171 last->next = t;
172 else
173 tok = t;
174 last = t;
175 }
176
177 if (t != NULL)
178 free (t);
179
180 /* Put extracted address into email */
181 t = brace ? brace->next : tok;
182 for (; t && t->word[0] != ',' && t->word[0] != '>'; t = t->next)
183 {
184 char *tmp;
185 if (address->email
186 && (tmp = realloc (address->email, strlen (address->email)
187 + strlen (t->word) + 1)) != NULL)
188 {
189 address->email = tmp;
190 strcat (address->email, t->word);
191 }
192 else if ((tmp = calloc (strlen (t->word) + 1, sizeof (char))) != NULL)
193 {
194 address->email = tmp;
195 strcat (address->email, t->word);
196 }
197 else
198 {
199 address_destroy (&address);
200 status = ENOMEM;
201 goto freenodes;
202 }
203 }
204
205 /* Extract Comments. */
206 for (t = start_comments; t ; t = t->next)
207 {
208 char *tmp;
209 if (t->word[0] == '(' || t->word[0] == ')')
210 continue;
211 if (address->comments
212 && (tmp = realloc (address->comments, strlen (address->comments)
213 + strlen (t->word) + 2)) != NULL)
214 {
215 address->comments = tmp;
216 strcat (address->comments, " ");
217 strcat (address->comments, t->word);
218 }
219 else if ((tmp = calloc (strlen (t->word) + 1, sizeof (char))) != NULL)
220 {
221 address->comments = tmp;
222 strcat (address->comments, t->word);
223 }
224 else
225 {
226 address_destroy (&address);
227 status = ENOMEM;
228 goto freenodes;
229 }
230 }
231
232 /* Extract Personal. */
233 if (brace == NULL)
234 {
235 address->personal = strdup ("");
236 }
237 else
238 {
239 int in_brace = 0;
240 for (t = tok; t ; t = t->next)
241 {
242 char *tmp;
243 if (t->word[0] == '<' || t->word[0] == '>' || in_brace)
244 {
245 if (t->word[0] == '<')
246 in_brace++;
247 else if (t->word[0] == '>')
248 in_brace--;
249 continue;
250 }
251 if (address->personal
252 && (tmp = realloc (address->personal, strlen (address->personal)
253 + strlen (t->word) + 2)) != NULL)
254 {
255 address->personal = tmp;
256 strcat (address->personal, " ");
257 strcat (address->personal, t->word);
258 }
259 else if ((tmp = calloc (strlen (t->word) + 1, sizeof (char))) != NULL)
260 {
261 address->personal = tmp;
262 strcat (address->personal, t->word);
263 }
264 else
265 {
266 address_destroy (&address);
267 status = ENOMEM;
268 goto freenodes;
269 }
270 }
271 }
272
273 /* Free list of tokens. */
274 freenodes:
275 for (t = tok; t; t = last)
276 {
277 last = t->next;
278 free (t);
279 }
280 for (t = start_comments; t; t = last)
281 {
282 last = t->next;
283 free (t);
284 }
285
286 *paddr = p;
287 return status;
288 }
289
290 int 35 int
291 address_create (address_t *paddress, const char *addr) 36 address_create (address_t *a, const char *s)
292 { 37 {
293 address_t address = NULL; 38 /* 'paddress' must exist, and can't already have been initialized
294 address_t current = NULL; 39 */
295 address_t head = NULL; 40 int status;
296 const char *p = addr;
297 int status = 0;
298 41
299 if (paddress == NULL) 42 if (!a)
300 return EINVAL; 43 return EINVAL;
301 if (addr) 44
45 *a = NULL;
46 status = parse822_address_list (a, (char*) s);
47 if (status == 0)
302 { 48 {
303 while (*addr != 0) 49 /* There was a group that got parsed correctly, but had
50 * no addresses...
51 */
52 if (!*a)
53 return ENOENT;
54
55 (*a)->addr = strdup (s);
56 if (!(*a)->addr)
304 { 57 {
305 status = address_parse (&address, &addr); 58 address_destroy (a);
306 if (status == 0) 59 return ENOMEM;
307 { 60 }
308 if (head == NULL)
309 {
310 head = address;
311 head->addr = strdup (p);
312 }
313 else
314 current->next = address;
315 current = address;
316 p = addr;
317 }
318 }
319 } 61 }
320 *paddress = head;
321 return status; 62 return status;
322 } 63 }
323 64
...@@ -356,7 +97,7 @@ address_get_personal (address_t addr, size_t no, char *buf, size_t len, ...@@ -356,7 +97,7 @@ address_get_personal (address_t addr, size_t no, char *buf, size_t len,
356 size_t *n) 97 size_t *n)
357 { 98 {
358 size_t i, j; 99 size_t i, j;
359 int status = EINVAL; 100 int status = ENOENT;
360 if (addr == NULL) 101 if (addr == NULL)
361 return EINVAL; 102 return EINVAL;
362 for (i = 0, j = 1; addr; addr = addr->next, j++) 103 for (i = 0, j = 1; addr; addr = addr->next, j++)
...@@ -368,18 +109,6 @@ address_get_personal (address_t addr, size_t no, char *buf, size_t len, ...@@ -368,18 +109,6 @@ address_get_personal (address_t addr, size_t no, char *buf, size_t len,
368 break; 109 break;
369 } 110 }
370 } 111 }
371 /* Remove the leading doublequotes. */
372 if (i && buf && *buf == '"')
373 {
374 memmove (buf, buf + 1, i - 1);
375 i--;
376 }
377 /* Remove the trailing doublequotes. */
378 if (i && buf && buf[i - 1] == '"')
379 {
380 buf[i - 1] = '\0';
381 i--;
382 }
383 if (n) 112 if (n)
384 *n = i; 113 *n = i;
385 return status; 114 return status;
...@@ -390,7 +119,7 @@ address_get_comments (address_t addr, size_t no, char *buf, size_t len, ...@@ -390,7 +119,7 @@ address_get_comments (address_t addr, size_t no, char *buf, size_t len,
390 size_t *n) 119 size_t *n)
391 { 120 {
392 size_t i, j; 121 size_t i, j;
393 int status = EINVAL; 122 int status = ENOENT;
394 if (addr == NULL) 123 if (addr == NULL)
395 return EINVAL; 124 return EINVAL;
396 for (j = 1; addr; addr = addr->next, j++) 125 for (j = 1; addr; addr = addr->next, j++)
...@@ -411,7 +140,7 @@ int ...@@ -411,7 +140,7 @@ int
411 address_get_email (address_t addr, size_t no, char *buf, size_t len, size_t *n) 140 address_get_email (address_t addr, size_t no, char *buf, size_t len, size_t *n)
412 { 141 {
413 size_t i, j; 142 size_t i, j;
414 int status = EINVAL; 143 int status = ENOENT;
415 if (addr == NULL) 144 if (addr == NULL)
416 return EINVAL; 145 return EINVAL;
417 for (j = 1; addr; addr = addr->next, j++) 146 for (j = 1; addr; addr = addr->next, j++)
...@@ -432,7 +161,7 @@ int ...@@ -432,7 +161,7 @@ int
432 address_get_local_part (address_t addr, size_t no, char *buf, size_t len, size_t *n) 161 address_get_local_part (address_t addr, size_t no, char *buf, size_t len, size_t *n)
433 { 162 {
434 size_t i, j; 163 size_t i, j;
435 int status = EINVAL; 164 int status = ENOENT;
436 if (addr == NULL) 165 if (addr == NULL)
437 return EINVAL; 166 return EINVAL;
438 for (j = 1; addr; addr = addr->next, j++) 167 for (j = 1; addr; addr = addr->next, j++)
...@@ -453,7 +182,7 @@ int ...@@ -453,7 +182,7 @@ int
453 address_get_domain (address_t addr, size_t no, char *buf, size_t len, size_t *n) 182 address_get_domain (address_t addr, size_t no, char *buf, size_t len, size_t *n)
454 { 183 {
455 size_t i, j; 184 size_t i, j;
456 int status = EINVAL; 185 int status = ENOENT;
457 if (addr == NULL) 186 if (addr == NULL)
458 return EINVAL; 187 return EINVAL;
459 for (j = 1; addr; addr = addr->next, j++) 188 for (j = 1; addr; addr = addr->next, j++)
...@@ -474,7 +203,7 @@ int ...@@ -474,7 +203,7 @@ int
474 address_get_route (address_t addr, size_t no, char *buf, size_t len, size_t *n) 203 address_get_route (address_t addr, size_t no, char *buf, size_t len, size_t *n)
475 { 204 {
476 size_t i, j; 205 size_t i, j;
477 int status = EINVAL; 206 int status = ENOENT;
478 if (addr == NULL) 207 if (addr == NULL)
479 return EINVAL; 208 return EINVAL;
480 for (j = 1; addr; addr = addr->next, j++) 209 for (j = 1; addr; addr = addr->next, j++)
......
...@@ -23,9 +23,11 @@ ...@@ -23,9 +23,11 @@
23 #include <stdio.h> 23 #include <stdio.h>
24 #include <stdlib.h> 24 #include <stdlib.h>
25 #include <string.h> 25 #include <string.h>
26 #include <unistd.h>
26 #include <ctype.h> 27 #include <ctype.h>
27 28
28 #include <mailutils/message.h> 29 #include <mailutils/message.h>
30 #include <mailutils/filter.h>
29 #include <mailutils/stream.h> 31 #include <mailutils/stream.h>
30 32
31 #define MAX_HDR_LEN 256 33 #define MAX_HDR_LEN 256
...@@ -75,7 +77,7 @@ int message_create_attachment(const char *content_type, const char *encoding, co ...@@ -75,7 +77,7 @@ int message_create_attachment(const char *content_type, const char *encoding, co
75 message_get_body(*newmsg, &body); 77 message_get_body(*newmsg, &body);
76 if ( ( ret = file_stream_create(&fstream) ) == 0 ) { 78 if ( ( ret = file_stream_create(&fstream) ) == 0 ) {
77 if ( ( ret = stream_open(fstream, filename, 0, MU_STREAM_READ) ) == 0 ) { 79 if ( ( ret = stream_open(fstream, filename, 0, MU_STREAM_READ) ) == 0 ) {
78 if ( ( ret = encoder_stream_create(&tstream, fstream, encoding) ) == 0 ) { 80 if ( ( ret = filter_create(&tstream, fstream, encoding, MU_FILTER_ENCODE, MU_STREAM_READ) ) == 0 ) {
79 body_set_stream(body, tstream, *newmsg); 81 body_set_stream(body, tstream, *newmsg);
80 message_set_header(*newmsg, hdr, NULL); 82 message_set_header(*newmsg, hdr, NULL);
81 } 83 }
...@@ -245,7 +247,7 @@ int message_save_attachment(message_t msg, const char *filename, void **data) ...@@ -245,7 +247,7 @@ int message_save_attachment(message_t msg, const char *filename, void **data)
245 header_get_value(hdr, "Content-Transfer-Encoding", content_encoding, size+1, 0); 247 header_get_value(hdr, "Content-Transfer-Encoding", content_encoding, size+1, 0);
246 } else 248 } else
247 content_encoding = (char *)"7bit"; 249 content_encoding = (char *)"7bit";
248 ret = decoder_stream_create(&info->ostream, fstream, content_encoding); 250 ret = filter_create(&info->ostream, fstream, content_encoding, MU_FILTER_DECODE, MU_STREAM_READ);
249 } 251 }
250 } 252 }
251 } 253 }
......
...@@ -211,7 +211,7 @@ body_set_lines (body_t body, int (*_lines)(body_t, size_t *), void *owner) ...@@ -211,7 +211,7 @@ body_set_lines (body_t body, int (*_lines)(body_t, size_t *), void *owner)
211 { 211 {
212 if (body == NULL) 212 if (body == NULL)
213 return EINVAL; 213 return EINVAL;
214 if (body->owner == owner) 214 if (body->owner != owner)
215 return EACCES; 215 return EACCES;
216 body->_lines = _lines; 216 body->_lines = _lines;
217 return 0; 217 return 0;
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
28 # include <pthread.h> 28 # include <pthread.h>
29 #endif 29 #endif
30 30
31 #include <mailutils/filter.h> 31 #include <filter0.h>
32 #include <mailutils/property.h> 32 #include <mailutils/property.h>
33 33
34 static int rfc822_property __P ((property_t, const char *, const char *)); 34 static int rfc822_property __P ((property_t, const char *, const char *));
...@@ -46,23 +46,17 @@ struct rfc822 ...@@ -46,23 +46,17 @@ struct rfc822
46 int residue; 46 int residue;
47 }; 47 };
48 48
49 static struct _filter _rfc822_filter = 49 static struct _filter_record _rfc822_filter =
50 { 50 {
51 "RFC822", 51 "RFC822",
52 rfc822_init, 52 rfc822_init,
53 rfc822_read,
54 rfc822_readline,
55 NULL, 53 NULL,
56 rfc822_destroy,
57 NULL, 54 NULL,
58 NULL, 55 NULL,
59 NULL,
60 0,
61 NULL
62 }; 56 };
63 57
64 /* Exported. */ 58 /* Exported. */
65 filter_t rfc822_filter = &_rfc822_filter; 59 filter_record_t rfc822_filter = &_rfc822_filter;
66 60
67 static int 61 static int
68 rfc822_property (property_t property, const char *key, const char *value) 62 rfc822_property (property_t property, const char *key, const char *value)
...@@ -82,6 +76,11 @@ rfc822_init (filter_t filter) ...@@ -82,6 +76,11 @@ rfc822_init (filter_t filter)
82 filter->data = calloc (1, sizeof (struct rfc822)); 76 filter->data = calloc (1, sizeof (struct rfc822));
83 if (filter->data == NULL) 77 if (filter->data == NULL)
84 return ENOMEM; 78 return ENOMEM;
79
80 filter->_read = rfc822_read;
81 filter->_readline = rfc822_readline;
82 filter->_destroy = rfc822_destroy;
83
85 /* We are interested in this property. */ 84 /* We are interested in this property. */
86 if ((status = stream_get_property (filter->filter_stream, &property) != 0) 85 if ((status = stream_get_property (filter->filter_stream, &property) != 0)
87 || (status = property_add_defaults (property, "LINES", "0", 86 || (status = property_add_defaults (property, "LINES", "0",
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17 17
18 /* Notes: 18 /* Notes:
19 19 First Draft: Dave Inglis.
20 */ 20 */
21 21
22 #ifdef HAVE_CONFIG_H 22 #ifdef HAVE_CONFIG_H
...@@ -28,18 +28,72 @@ ...@@ -28,18 +28,72 @@
28 #include <stdlib.h> 28 #include <stdlib.h>
29 #include <string.h> 29 #include <string.h>
30 30
31 #include <mailutils/stream.h> 31 #include <filter0.h>
32 32
33 #define MU_TRANS_DECODE 1 33 #define MU_TRANS_DECODE 1
34 #define MU_TRANS_ENCODE 2 34 #define MU_TRANS_ENCODE 2
35 #define MU_TRANS_BSIZE 2048 35 #define MU_TRANS_BSIZE 2048
36 36
37 static int qp_init __P ((filter_t));
38 static int base64_init __P ((filter_t));
39
40 static struct _filter_record _qp_filter =
41 {
42 "quoted-printable",
43 qp_init,
44 NULL,
45 NULL,
46 NULL
47 };
48
49 static struct _filter_record _base64_filter =
50 {
51 "base64",
52 base64_init,
53 NULL,
54 NULL,
55 NULL
56 };
57
58 static struct _filter_record _bit8_filter =
59 {
60 "8bit",
61 NULL,
62 NULL,
63 NULL,
64 NULL
65 };
66
67 static struct _filter_record _bit7_filter =
68 {
69 "7bit",
70 NULL,
71 NULL,
72 NULL,
73 NULL
74 };
75
76 static struct _filter_record _binary_filter =
77 {
78 "binary",
79 NULL,
80 NULL,
81 NULL,
82 NULL
83 };
84
85 /* Export. */
86 filter_record_t qp_filter = &_qp_filter;
87 filter_record_t base64_filter = &_base64_filter;
88 filter_record_t binary_filter = &_binary_filter;
89 filter_record_t bit8_filter = &_bit8_filter;
90 filter_record_t bit7_filter = &_bit7_filter;
91
37 struct _trans_stream 92 struct _trans_stream
38 { 93 {
39 stream_t stream; /* encoder/decoder read/writes data to/from here */ 94 int t_offset; /* Orignal stream offset. */
40 int t_offset;
41 95
42 int min_size; 96 size_t min_size;
43 int s_offset; 97 int s_offset;
44 char *s_buf; /* Used when read if not big enough to handle min_size 98 char *s_buf; /* Used when read if not big enough to handle min_size
45 for decoder/encoder */ 99 for decoder/encoder */
...@@ -55,53 +109,30 @@ struct _trans_stream ...@@ -55,53 +109,30 @@ struct _trans_stream
55 size_t osize, size_t *nbytes, int *line_len)); 109 size_t osize, size_t *nbytes, int *line_len));
56 }; 110 };
57 111
58 struct _ts_desc 112 static int base64_decode __P ((const char *iptr, size_t isize, char *optr,
59 {
60 const char *encoding;
61
62 int (*_init) __P ((struct _trans_stream *ts, int type));
63 int (*_decode) __P ((const char *iptr, size_t isize, char *optr,
64 size_t osize, size_t *nbytes, int *line_len));
65 int (*_encode) __P ((const char *iptr, size_t isize, char *optr,
66 size_t osize, size_t *nbytes, int *line_len));
67 };
68
69 static int _base64_init __P ((struct _trans_stream *ts, int type));
70 static int _base64_decode __P ((const char *iptr, size_t isize, char *optr,
71 size_t osize, size_t *nbytes, int *line_len)); 113 size_t osize, size_t *nbytes, int *line_len));
72 static int _base64_encode __P ((const char *iptr, size_t isize, char *optr, 114 static int base64_encode __P ((const char *iptr, size_t isize, char *optr,
73 size_t osize, size_t *nbytes, int *line_len)); 115 size_t osize, size_t *nbytes, int *line_len));
74 116
75 static int _qp_init __P ((struct _trans_stream *ts, int type)); 117 static int qp_decode __P ((const char *iptr, size_t isize, char *optr,
76 static int _qp_decode __P ((const char *iptr, size_t isize, char *optr,
77 size_t osize, size_t *nbytes, int *line_len)); 118 size_t osize, size_t *nbytes, int *line_len));
78 static int _qp_encode __P ((const char *iptr, size_t isize, char *optr, 119 static int qp_encode __P ((const char *iptr, size_t isize, char *optr,
79 size_t osize, size_t *nbytes, int *line_len)); 120 size_t osize, size_t *nbytes, int *line_len));
80 121
81 /* #define NUM_TRANSCODERS 6 */
82 /* struct _ts_desc tslist[NUM_TRANSCODERS] = */
83 struct _ts_desc tslist[] =
84 {
85 { "base64", _base64_init, _base64_decode, _base64_encode },
86 { "quoted-printable", _qp_init, _qp_decode, _qp_encode },
87 { "7bit", NULL, NULL, NULL },
88 { "8bit", NULL, NULL, NULL },
89 { "binary", NULL, NULL, NULL }
90 };
91
92 static void 122 static void
93 _trans_destroy (stream_t stream) 123 trans_destroy (filter_t filter)
94 { 124 {
95 struct _trans_stream *ts = stream_get_owner (stream); 125 struct _trans_stream *ts = filter->data;
96 stream_destroy (&(ts->stream), NULL); 126 if (ts->s_buf)
127 free (ts->s_buf);
97 free (ts); 128 free (ts);
98 } 129 }
99 130
100 static int 131 static int
101 _trans_read (stream_t stream, char *optr, size_t osize, off_t offset, 132 trans_read (filter_t filter, char *optr, size_t osize, off_t offset,
102 size_t *n_bytes) 133 size_t *n_bytes)
103 { 134 {
104 struct _trans_stream *ts = stream_get_owner (stream); 135 struct _trans_stream *ts = filter->data;
105 size_t obytes, wbytes; 136 size_t obytes, wbytes;
106 int ret = 0, i; 137 int ret = 0, i;
107 size_t bytes, *nbytes = &bytes; 138 size_t bytes, *nbytes = &bytes;
...@@ -109,9 +140,6 @@ _trans_read (stream_t stream, char *optr, size_t osize, off_t offset, ...@@ -109,9 +140,6 @@ _trans_read (stream_t stream, char *optr, size_t osize, off_t offset,
109 if (optr == NULL || osize == 0) 140 if (optr == NULL || osize == 0)
110 return EINVAL; 141 return EINVAL;
111 142
112 if (ts->transcoder == NULL)
113 return stream_read (ts->stream, optr, osize, offset, n_bytes);
114
115 if (n_bytes) 143 if (n_bytes)
116 nbytes = n_bytes; 144 nbytes = n_bytes;
117 *nbytes = 0; 145 *nbytes = 0;
...@@ -125,12 +153,12 @@ _trans_read (stream_t stream, char *optr, size_t osize, off_t offset, ...@@ -125,12 +153,12 @@ _trans_read (stream_t stream, char *optr, size_t osize, off_t offset,
125 153
126 while (*nbytes < osize) 154 while (*nbytes < osize)
127 { 155 {
128 if ((ts->w_rhd + ts->min_size) >= ts->w_whd) 156 if ((ts->w_rhd + (int)ts->min_size) >= ts->w_whd)
129 { 157 {
130 memmove (ts->w_buf, ts->w_buf + ts->w_rhd, ts->w_whd - ts->w_rhd); 158 memmove (ts->w_buf, ts->w_buf + ts->w_rhd, ts->w_whd - ts->w_rhd);
131 ts->w_whd = ts->w_whd - ts->w_rhd; 159 ts->w_whd = ts->w_whd - ts->w_rhd;
132 ts->w_rhd = 0; 160 ts->w_rhd = 0;
133 ret = stream_read (ts->stream, ts->w_buf + ts->w_whd, 161 ret = stream_read (filter->stream, ts->w_buf + ts->w_whd,
134 MU_TRANS_BSIZE - ts->w_whd, ts->offset, 162 MU_TRANS_BSIZE - ts->w_whd, ts->offset,
135 &wbytes ); 163 &wbytes );
136 if (ret != 0) 164 if (ret != 0)
...@@ -182,62 +210,23 @@ _trans_read (stream_t stream, char *optr, size_t osize, off_t offset, ...@@ -182,62 +210,23 @@ _trans_read (stream_t stream, char *optr, size_t osize, off_t offset,
182 return ret; 210 return ret;
183 } 211 }
184 212
213 #if 0
185 static int 214 static int
186 _trans_write (stream_t stream, const char *iptr, size_t isize, off_t offset, 215 trans_write (stream_t stream, const char *iptr, size_t isize, off_t offset,
187 size_t *nbytes) 216 size_t *nbytes)
188 { 217 {
189 struct _trans_stream *ts = stream_get_owner (stream); 218 struct _trans_stream *ts = stream_get_owner (stream);
190 return stream_write (ts->stream, iptr, isize, offset, nbytes); 219 return stream_write (ts->stream, iptr, isize, offset, nbytes);
191 } 220 }
221 #endif
192 222
193 static int
194 _trans_open (stream_t stream, const char *filename, int port, int flags)
195 {
196 struct _trans_stream *ts = stream_get_owner (stream);
197 return stream_open (ts->stream, filename, port, flags);
198 }
199
200 static int
201 _trans_truncate (stream_t stream, off_t len)
202 {
203 struct _trans_stream *ts = stream_get_owner (stream);
204 return stream_truncate (ts->stream, len);
205 }
206
207 static int
208 _trans_size (stream_t stream, off_t *psize)
209 {
210 struct _trans_stream *ts = stream_get_owner (stream);
211 return stream_size (ts->stream, psize);
212 }
213
214 static int
215 _trans_flush (stream_t stream)
216 {
217 struct _trans_stream *ts = stream_get_owner(stream);
218 return stream_flush (ts->stream);
219 }
220
221 static int
222 _trans_get_fd (stream_t stream, int *pfd)
223 {
224 struct _trans_stream *ts = stream_get_owner (stream);
225 return stream_get_fd (ts->stream, pfd);
226 }
227
228 static int
229 _trans_close (stream_t stream)
230 {
231 struct _trans_stream *ts = stream_get_owner (stream);
232 return stream_close (ts->stream);
233 }
234 223
235 /*------------------------------------------------------ 224 /*------------------------------------------------------
236 * base64 encode/decode 225 * base64 encode/decode
237 *----------------------------------------------------*/ 226 *----------------------------------------------------*/
238 227
239 static int 228 static int
240 _b64_input (char c) 229 b64_input (char c)
241 { 230 {
242 const char table[64] = 231 const char table[64] =
243 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 232 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
...@@ -252,29 +241,43 @@ _b64_input (char c) ...@@ -252,29 +241,43 @@ _b64_input (char c)
252 } 241 }
253 242
254 static int 243 static int
255 _base64_init (struct _trans_stream *ts, int type) 244 base64_init (filter_t filter)
256 { 245 {
246 struct _trans_stream *ts;
247 ts = calloc (sizeof (*ts), 1);
248 if (ts == NULL)
249 return ENOMEM;
250
257 ts->min_size = 4; 251 ts->min_size = 4;
258 ts->s_buf = calloc (4, 1); 252 ts->s_buf = calloc (4, 1);
259 if (ts->s_buf == NULL) 253 if (ts->s_buf == NULL)
260 return ENOMEM; 254 {
255 free (ts);
256 return ENOMEM;
257 }
258 ts->transcoder = (filter->type == MU_FILTER_DECODE) ? base64_decode : base64_encode;
259
260 filter->_read = trans_read;
261 filter->_destroy = trans_destroy;
262 filter->data = ts;
261 return 0; 263 return 0;
262 } 264 }
263 265
264 static int 266 static int
265 _base64_decode (const char *iptr, size_t isize, char *optr, size_t osize, 267 base64_decode (const char *iptr, size_t isize, char *optr, size_t osize,
266 size_t *nbytes, int *line_len) 268 size_t *nbytes, int *line_len)
267 { 269 {
268 int i = 0, tmp = 0, pad = 0; 270 int i = 0, tmp = 0, pad = 0;
269 size_t consumed = 0; 271 size_t consumed = 0;
270 char data[4]; 272 char data[4];
271 273
274 (void) line_len;
272 *nbytes = 0; 275 *nbytes = 0;
273 while (consumed < isize && (*nbytes)+3 < osize) 276 while (consumed < isize && (*nbytes)+3 < osize)
274 { 277 {
275 while (( i < 4 ) && (consumed < isize)) 278 while (( i < 4 ) && (consumed < isize))
276 { 279 {
277 tmp = _b64_input (*iptr++); 280 tmp = b64_input (*iptr++);
278 consumed++; 281 consumed++;
279 if (tmp != -1) 282 if (tmp != -1)
280 data[i++] = tmp; 283 data[i++] = tmp;
...@@ -306,8 +309,8 @@ _base64_decode (const char *iptr, size_t isize, char *optr, size_t osize, ...@@ -306,8 +309,8 @@ _base64_decode (const char *iptr, size_t isize, char *optr, size_t osize,
306 309
307 #define BASE64_LINE_MAX 77 310 #define BASE64_LINE_MAX 77
308 static int 311 static int
309 _base64_encode (const char *iptr, size_t isize, char *optr, size_t osize, 312 base64_encode (const char *iptr, size_t isize, char *optr, size_t osize,
310 size_t *nbytes, int *line_len) 313 size_t *nbytes, int *line_len)
311 { 314 {
312 size_t consumed = 0; 315 size_t consumed = 0;
313 int pad = 0; 316 int pad = 0;
...@@ -348,23 +351,37 @@ _base64_encode (const char *iptr, size_t isize, char *optr, size_t osize, ...@@ -348,23 +351,37 @@ _base64_encode (const char *iptr, size_t isize, char *optr, size_t osize,
348 static const char _hexdigits[16] = "0123456789ABCDEF"; 351 static const char _hexdigits[16] = "0123456789ABCDEF";
349 352
350 static int 353 static int
351 _qp_init (struct _trans_stream *ts, int type) 354 qp_init (filter_t filter)
352 { 355 {
356 struct _trans_stream *ts;
357 ts = calloc (sizeof (*ts), 1);
358 if (ts == NULL)
359 return ENOMEM;
360
353 ts->min_size = 4; 361 ts->min_size = 4;
354 ts->s_buf = calloc (4, 1); 362 ts->s_buf = calloc (4, 1);
355 if (ts->s_buf == NULL) 363 if (ts->s_buf == NULL)
356 return ENOMEM; 364 {
365 free (ts);
366 return ENOMEM;
367 }
368 ts->transcoder = (filter->type == MU_FILTER_DECODE) ? qp_decode : qp_encode;
369
370 filter->_read = trans_read;
371 filter->_destroy = trans_destroy;
372 filter->data = ts;
357 return 0; 373 return 0;
358 } 374 }
359 375
360 static int 376 static int
361 _qp_decode (const char *iptr, size_t isize, char *optr, size_t osize, 377 qp_decode (const char *iptr, size_t isize, char *optr, size_t osize,
362 size_t *nbytes, int *line_len) 378 size_t *nbytes, int *line_len)
363 { 379 {
364 char c; 380 char c;
365 int last_char = 0; 381 int last_char = 0;
366 size_t consumed = 0; 382 size_t consumed = 0;
367 383
384 (void)line_len;
368 *nbytes = 0; 385 *nbytes = 0;
369 while (consumed < isize && *nbytes < osize) 386 while (consumed < isize && *nbytes < osize)
370 { 387 {
...@@ -430,15 +447,15 @@ _qp_decode (const char *iptr, size_t isize, char *optr, size_t osize, ...@@ -430,15 +447,15 @@ _qp_decode (const char *iptr, size_t isize, char *optr, size_t osize,
430 return consumed; 447 return consumed;
431 } 448 }
432 449
433
434 static int 450 static int
435 _qp_encode (const char *iptr, size_t isize, char *optr, size_t osize, 451 qp_encode (const char *iptr, size_t isize, char *optr, size_t osize,
436 size_t *nbytes, int *line_len) 452 size_t *nbytes, int *line_len)
437 { 453 {
438 #define QP_LINE_MAX 76 454 #define QP_LINE_MAX 76
439 int c; 455 int c;
440 size_t consumed = 0; 456 size_t consumed = 0;
441 457
458 (void)osize;
442 *nbytes = 0; 459 *nbytes = 0;
443 while (consumed < isize && (*nbytes + 4) < isize) 460 while (consumed < isize && (*nbytes + 4) < isize)
444 { 461 {
...@@ -484,119 +501,3 @@ _qp_encode (const char *iptr, size_t isize, char *optr, size_t osize, ...@@ -484,119 +501,3 @@ _qp_encode (const char *iptr, size_t isize, char *optr, size_t osize,
484 } 501 }
485 return consumed; 502 return consumed;
486 } 503 }
487
488 int
489 encoder_stream_create (stream_t *stream, stream_t iostream,
490 const char *encoding)
491 {
492 struct _trans_stream *ts;
493 int i, ret;
494 int NUM_TRANSCODERS = sizeof (tslist)/sizeof (*tslist);
495
496 if (stream == NULL || iostream == NULL || encoding == NULL)
497 return EINVAL;
498
499 ts = calloc (sizeof (struct _trans_stream), 1);
500 if (ts == NULL)
501 return ENOMEM;
502
503 for (i = 0; i < NUM_TRANSCODERS; i++)
504 {
505 if (strcasecmp (encoding, tslist[i].encoding) == 0)
506 break;
507 }
508
509 if (i == NUM_TRANSCODERS)
510 {
511 free (ts);
512 return ENOTSUP;
513 }
514
515 if (tslist[i]._init != NULL)
516 {
517 ret = tslist[i]._init (ts, MU_TRANS_ENCODE);
518 if (ret != 0)
519 {
520 free (ts);
521 return ret;
522 }
523 }
524
525 ret = stream_create (stream, MU_STREAM_RDWR | MU_STREAM_NO_CHECK, ts);
526 if (ret != 0)
527 {
528 free (ts);
529 return ret;
530 }
531
532 ts->transcoder = tslist[i]._encode;
533 ts->stream = iostream;
534 stream_set_open (*stream, _trans_open, ts);
535 stream_set_close (*stream, _trans_close, ts);
536 stream_set_fd (*stream, _trans_get_fd, ts);
537 stream_set_truncate (*stream, _trans_truncate, ts);
538 stream_set_size (*stream, _trans_size, ts);
539 stream_set_flush (*stream, _trans_flush, ts);
540 stream_set_read (*stream, _trans_read, ts);
541 stream_set_write (*stream, _trans_write, ts);
542 stream_set_destroy (*stream, _trans_destroy, ts);
543 return ret;
544 }
545
546 int
547 decoder_stream_create (stream_t *stream, stream_t iostream,
548 const char *encoding)
549 {
550 struct _trans_stream *ts;
551 int i, ret;
552 int NUM_TRANSCODERS = sizeof (tslist)/sizeof (*tslist);
553
554 if (stream == NULL || iostream == NULL || encoding == NULL)
555 return EINVAL;
556
557 ts = calloc (sizeof (struct _trans_stream), 1);
558 if (ts == NULL )
559 return ENOMEM;
560
561 for (i = 0; i < NUM_TRANSCODERS; i++)
562 {
563 if (strcasecmp (encoding, tslist[i].encoding) == 0)
564 break;
565 }
566
567 if (i == NUM_TRANSCODERS)
568 {
569 free (ts);
570 return ENOTSUP;
571 }
572
573 if (tslist[i]._init != NULL)
574 {
575 ret = tslist[i]._init (ts, MU_TRANS_DECODE);
576 if (ret != 0)
577 {
578 free (ts);
579 return ret;
580 }
581 }
582
583 ret = stream_create (stream, MU_STREAM_RDWR | MU_STREAM_NO_CHECK, ts);
584 if (ret != 0)
585 {
586 free (ts);
587 return ret;
588 }
589
590 ts->transcoder = tslist[i]._decode;
591 ts->stream = iostream;
592 stream_set_open (*stream, _trans_open, ts );
593 stream_set_close (*stream, _trans_close, ts );
594 stream_set_fd (*stream, _trans_get_fd, ts );
595 stream_set_truncate (*stream, _trans_truncate, ts );
596 stream_set_size (*stream, _trans_size, ts );
597 stream_set_flush (*stream, _trans_flush, ts );
598 stream_set_read (*stream, _trans_read, ts);
599 stream_set_write (*stream, _trans_write, ts);
600 stream_set_destroy (*stream, _trans_destroy, ts);
601 return ret;
602 }
......
...@@ -34,11 +34,6 @@ ...@@ -34,11 +34,6 @@
34 /* Internal folder list. */ 34 /* Internal folder list. */
35 static list_t known_folder_list; 35 static list_t known_folder_list;
36 static int is_known_folder __P ((url_t, folder_t *)); 36 static int is_known_folder __P ((url_t, folder_t *));
37 static int is_same_scheme __P ((url_t, url_t));
38 static int is_same_user __P ((url_t, url_t));
39 static int is_same_path __P ((url_t, url_t));
40 static int is_same_host __P ((url_t, url_t));
41 static int is_same_port __P ((url_t, url_t));
42 37
43 /* Static folder lock. */ 38 /* Static folder lock. */
44 static struct _monitor folder_lock = MU_MONITOR_INITIALIZER; 39 static struct _monitor folder_lock = MU_MONITOR_INITIALIZER;
...@@ -200,6 +195,7 @@ folder_destroy (folder_t *pfolder) ...@@ -200,6 +195,7 @@ folder_destroy (folder_t *pfolder)
200 if (folder->stream) 195 if (folder->stream)
201 stream_destroy (&(folder->stream), folder); 196 stream_destroy (&(folder->stream), folder);
202 if (folder->url) 197 if (folder->url)
198
203 url_destroy (&(folder->url)); 199 url_destroy (&(folder->url));
204 free (folder); 200 free (folder);
205 } 201 }
...@@ -210,7 +206,6 @@ folder_destroy (folder_t *pfolder) ...@@ -210,7 +206,6 @@ folder_destroy (folder_t *pfolder)
210 } 206 }
211 } 207 }
212 208
213
214 /* Cover functions. */ 209 /* Cover functions. */
215 int 210 int
216 folder_open (folder_t folder, int flags) 211 folder_open (folder_t folder, int flags)
...@@ -410,8 +405,6 @@ folder_get_url (folder_t folder, url_t *purl) ...@@ -410,8 +405,6 @@ folder_get_url (folder_t folder, url_t *purl)
410 return 0; 405 return 0;
411 } 406 }
412 407
413 /* ---------------------- Private ---------------------- */
414
415 static int is_known_folder (url_t url, folder_t *pfolder) 408 static int is_known_folder (url_t url, folder_t *pfolder)
416 { 409 {
417 int ret = 0; 410 int ret = 0;
...@@ -430,126 +423,18 @@ static int is_known_folder (url_t url, folder_t *pfolder) ...@@ -430,126 +423,18 @@ static int is_known_folder (url_t url, folder_t *pfolder)
430 iterator_current (iterator, (void **)&folder); 423 iterator_current (iterator, (void **)&folder);
431 /* Check if the same URL type. */ 424 /* Check if the same URL type. */
432 if (folder && folder->url 425 if (folder && folder->url
433 && is_same_scheme (url, folder->url) 426 && url_is_same_scheme (url, folder->url)
434 && is_same_user (url, folder->url) 427 && url_is_same_user (url, folder->url)
435 && is_same_path (url, folder->url) 428 && url_is_same_host (url, folder->url)
436 && is_same_host (url, folder->url) 429 /*&& url_is_same_path (url, folder->url) */
437 && is_same_port (url, folder->url)) 430 && url_is_same_port (url, folder->url))
438 { 431 {
439 ret = 1; 432 ret = 1;
440 break; 433 break;
441 } 434 }
442 } 435 }
436 if (ret)
437 *pfolder = folder;
443 iterator_destroy (&iterator); 438 iterator_destroy (&iterator);
444 return ret; 439 return ret;
445 } 440 }
446
447 static int
448 is_same_scheme (url_t url1, url_t url2)
449 {
450 size_t i = 0, j = 0;
451 char *s1, *s2;
452 int ret = 1;
453
454 url_get_scheme (url1, NULL, 0, &i);
455 url_get_scheme (url2, NULL, 0, &j);
456 s1 = calloc (i + 1, sizeof (char));
457 if (s1)
458 {
459 url_get_scheme (url1, s1, i + 1, NULL);
460 s2 = calloc (j + 1, sizeof (char));
461 if (s2)
462 {
463 url_get_scheme (url2, s2, j + 1, NULL);
464 ret = !strcasecmp (s1, s2);
465 free (s2);
466 }
467 free (s1);
468 }
469 return ret;
470 }
471
472 static int
473 is_same_user (url_t url1, url_t url2)
474 {
475 size_t i = 0, j = 0;
476 char *s1, *s2;
477 int ret = 0;
478
479 url_get_user (url1, NULL, 0, &i);
480 url_get_user (url2, NULL, 0, &j);
481 s1 = calloc (i + 1, sizeof (char));
482 if (s1)
483 {
484 url_get_user (url1, s1, i + 1, NULL);
485 s2 = calloc (j + 1, sizeof (char));
486 if (s2)
487 {
488 url_get_user (url2, s2, j + 1, NULL);
489 ret = !strcasecmp (s1, s2);
490 free (s2);
491 }
492 free (s1);
493 }
494 return ret;
495 }
496
497 static int
498 is_same_path (url_t url1, url_t url2)
499 {
500 size_t i = 0, j = 0;
501 char *s1, *s2;
502 int ret = 0;
503
504 url_get_path (url1, NULL, 0, &i);
505 url_get_path (url2, NULL, 0, &j);
506 s1 = calloc (i + 1, sizeof (char));
507 if (s1)
508 {
509 url_get_path (url1, s1, i + 1, NULL);
510 s2 = calloc (j + 1, sizeof (char));
511 if (s2)
512 {
513 url_get_path (url2, s2, j + 1, NULL);
514 ret = !strcasecmp (s1, s2);
515 free (s2);
516 }
517 free (s1);
518 }
519 return ret;
520 }
521
522 static int
523 is_same_host (url_t url1, url_t url2)
524 {
525 size_t i = 0, j = 0;
526 char *s1, *s2;
527 int ret = 0;
528
529 url_get_host (url1, NULL, 0, &i);
530 url_get_host (url2, NULL, 0, &j);
531 s1 = calloc (i + 1, sizeof (char));
532 if (s1)
533 {
534 url_get_host (url1, s1, i + 1, NULL);
535 s2 = calloc (j + 1, sizeof (char));
536 if (s2)
537 {
538 url_get_host (url2, s2, j + 1, NULL);
539 ret = !strcasecmp (s1, s2);
540 free (s2);
541 }
542 free (s1);
543 }
544 return ret;
545 }
546
547 static int
548 is_same_port (url_t url1, url_t url2)
549 {
550 long p1 = 0, p2 = 0;
551
552 url_get_port (url1, &p1);
553 url_get_port (url2, &p2);
554 return (p1 == p2);
555 }
......
...@@ -53,6 +53,7 @@ record_t imap_record = &_imap_record; ...@@ -53,6 +53,7 @@ record_t imap_record = &_imap_record;
53 53
54 /* Concrete IMAP implementation. */ 54 /* Concrete IMAP implementation. */
55 static int folder_imap_open __P ((folder_t, int)); 55 static int folder_imap_open __P ((folder_t, int));
56 static int folder_imap_create __P ((folder_t));
56 static int folder_imap_close __P ((folder_t)); 57 static int folder_imap_close __P ((folder_t));
57 static void folder_imap_destroy __P ((folder_t)); 58 static void folder_imap_destroy __P ((folder_t));
58 static int folder_imap_delete __P ((folder_t, const char *)); 59 static int folder_imap_delete __P ((folder_t, const char *));
...@@ -211,7 +212,9 @@ folder_imap_open (folder_t folder, int flags) ...@@ -211,7 +212,9 @@ folder_imap_open (folder_t folder, int flags)
211 monitor_wrlock (folder->monitor); 212 monitor_wrlock (folder->monitor);
212 if (f_imap->isopen) 213 if (f_imap->isopen)
213 { 214 {
214 monitor_wrlock (folder->monitor); 215 monitor_unlock (folder->monitor);
216 if (flags & MU_STREAM_CREAT)
217 status = folder_imap_create (folder);
215 return 0; 218 return 0;
216 } 219 }
217 monitor_unlock (folder->monitor); 220 monitor_unlock (folder->monitor);
...@@ -324,6 +327,11 @@ folder_imap_open (folder_t folder, int flags) ...@@ -324,6 +327,11 @@ folder_imap_open (folder_t folder, int flags)
324 monitor_wrlock (folder->monitor); 327 monitor_wrlock (folder->monitor);
325 f_imap->isopen++; 328 f_imap->isopen++;
326 monitor_unlock (folder->monitor); 329 monitor_unlock (folder->monitor);
330 if (flags & MU_STREAM_CREAT)
331 {
332 status = folder_imap_create (folder);
333 CHECK_EAGAIN (f_imap, status);
334 }
327 return 0; 335 return 0;
328 } 336 }
329 337
...@@ -372,6 +380,51 @@ folder_imap_close (folder_t folder) ...@@ -372,6 +380,51 @@ folder_imap_close (folder_t folder)
372 return 0; 380 return 0;
373 } 381 }
374 382
383 /* Create a folder/mailbox. */
384 static int
385 folder_imap_create (folder_t folder)
386 {
387 f_imap_t f_imap = folder->data;
388 int status = 0;
389
390 switch (f_imap->state)
391 {
392 case IMAP_NO_STATE:
393 {
394 char *path;
395 size_t len;
396 url_get_path (folder->url, NULL, 0, &len);
397 if (len == 0)
398 return 0;
399 path = calloc (len + 1, sizeof (*path));
400 if (path == NULL)
401 return ENOMEM;
402 url_get_path (folder->url, path, len + 1, NULL);
403 status = imap_writeline (f_imap, "g%d CREATE %s\r\n", f_imap->seq++,
404 path);
405 free (path);
406 CHECK_ERROR (f_imap, status);
407 FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, f_imap->buffer);
408 f_imap->state = IMAP_CREATE;
409 }
410
411 case IMAP_CREATE:
412 status = imap_send (f_imap);
413 CHECK_EAGAIN (f_imap, status);
414 f_imap->state = IMAP_DELETE_ACK;
415
416 case IMAP_CREATE_ACK:
417 status = imap_parse (f_imap);
418 CHECK_EAGAIN (f_imap, status);
419 FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, f_imap->buffer);
420
421 default:
422 break;
423 }
424 f_imap->state = IMAP_NO_STATE;
425 return status;
426 }
427
375 /* Remove a mailbox. */ 428 /* Remove a mailbox. */
376 static int 429 static int
377 folder_imap_delete (folder_t folder, const char *name) 430 folder_imap_delete (folder_t folder, const char *name)
...@@ -1528,9 +1581,9 @@ int ...@@ -1528,9 +1581,9 @@ int
1528 imap_send (f_imap_t f_imap) 1581 imap_send (f_imap_t f_imap)
1529 { 1582 {
1530 int status = 0; 1583 int status = 0;
1531 size_t len;
1532 if (f_imap->ptr > f_imap->buffer) 1584 if (f_imap->ptr > f_imap->buffer)
1533 { 1585 {
1586 size_t len;
1534 len = f_imap->ptr - f_imap->buffer; 1587 len = f_imap->ptr - f_imap->buffer;
1535 status = stream_write (f_imap->folder->stream, f_imap->buffer, len, 1588 status = stream_write (f_imap->folder->stream, f_imap->buffer, len,
1536 0, &len); 1589 0, &len);
...@@ -1543,7 +1596,6 @@ imap_send (f_imap_t f_imap) ...@@ -1543,7 +1596,6 @@ imap_send (f_imap_t f_imap)
1543 else 1596 else
1544 { 1597 {
1545 f_imap->ptr = f_imap->buffer; 1598 f_imap->ptr = f_imap->buffer;
1546 len = 0;
1547 } 1599 }
1548 return status; 1600 return status;
1549 } 1601 }
...@@ -1823,18 +1875,18 @@ imap_parse (f_imap_t f_imap) ...@@ -1823,18 +1875,18 @@ imap_parse (f_imap_t f_imap)
1823 { 1875 {
1824 /* Not sure why we would get an untagged ok...but we do... */ 1876 /* Not sure why we would get an untagged ok...but we do... */
1825 /* Still should we be verbose about is ? */ 1877 /* Still should we be verbose about is ? */
1826 printf("Untagged OK: %s\n", remainder); 1878 fprintf (stderr, "Untagged OK: %s\n", remainder);
1827 } 1879 }
1828 } 1880 }
1829 else if (strcasecmp (response, "NO") == 0) 1881 else if (strcasecmp (response, "NO") == 0)
1830 { 1882 {
1831 /* This does not mean failure but rather a strong warning. */ 1883 /* This does not mean failure but rather a strong warning. */
1832 printf ("Untagged NO: %s\n", remainder); 1884 fprintf (stderr, "Untagged NO: %s\n", remainder);
1833 } 1885 }
1834 else if (strcasecmp (response, "BAD") == 0) 1886 else if (strcasecmp (response, "BAD") == 0)
1835 { 1887 {
1836 /* We're dead, protocol/syntax error. */ 1888 /* We're dead, protocol/syntax error. */
1837 printf ("Untagged BAD: %s\n", remainder); 1889 fprintf (stderr, "Untagged BAD: %s\n", remainder);
1838 } 1890 }
1839 else if (strcasecmp (response, "PREAUTH") == 0) 1891 else if (strcasecmp (response, "PREAUTH") == 0)
1840 { 1892 {
...@@ -1893,8 +1945,8 @@ imap_parse (f_imap_t f_imap) ...@@ -1893,8 +1945,8 @@ imap_parse (f_imap_t f_imap)
1893 else 1945 else
1894 { 1946 {
1895 /* Once again, check for something strange. */ 1947 /* Once again, check for something strange. */
1896 printf("unknown untagged response: \"%s\" %s\n", 1948 fprintf (stderr, "unknown untagged response: \"%s\" %s\n",
1897 response, remainder); 1949 response, remainder);
1898 } 1950 }
1899 } 1951 }
1900 /* Continuation token ???. */ 1952 /* Continuation token ???. */
...@@ -1917,7 +1969,7 @@ imap_parse (f_imap_t f_imap) ...@@ -1917,7 +1969,7 @@ imap_parse (f_imap_t f_imap)
1917 folder_get_observable (f_imap->folder, &observable); 1969 folder_get_observable (f_imap->folder, &observable);
1918 observable_notify (observable, MU_EVT_AUTHORITY_FAILED); 1970 observable_notify (observable, MU_EVT_AUTHORITY_FAILED);
1919 } 1971 }
1920 printf("NO/Bad Tagged: %s %s\n", response, remainder); 1972 fprintf (stderr, "NO/Bad Tagged: %s %s\n", response, remainder);
1921 status = EINVAL; 1973 status = EINVAL;
1922 } 1974 }
1923 } 1975 }
......
...@@ -5,6 +5,7 @@ auth0.h \ ...@@ -5,6 +5,7 @@ auth0.h \
5 body0.h \ 5 body0.h \
6 debug0.h \ 6 debug0.h \
7 envelope0.h \ 7 envelope0.h \
8 filter0.h \
8 folder0.h \ 9 folder0.h \
9 header0.h \ 10 header0.h \
10 iterator0.h \ 11 iterator0.h \
......
1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Library Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 /* Notes:
19
20 */
21
22 #ifndef _FILTER0_H
23 #define _FILTER0_H
24
25 #include <mailutils/filter.h>
26 #include <mailutils/list.h>
27 #include <mailutils/monitor.h>
28 #include <mailutils/property.h>
29
30 #ifndef __P
31 # ifdef __STDC__
32 # define __P(args) args
33 # else
34 # define __P(args) ()
35 # endif
36 #endif /*__P */
37
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41
42 struct _filter
43 {
44 stream_t stream;
45 stream_t filter_stream;
46 property_t property;
47 int direction;
48 int type;
49 void *data;
50 int (*_read) __P ((filter_t, char *, size_t, off_t, size_t *));
51 int (*_readline) __P ((filter_t, char *, size_t, off_t, size_t *));
52 int (*_write) __P ((filter_t, const char *, size_t, off_t, size_t *));
53 void (*_destroy) __P ((filter_t));
54 };
55
56 #ifdef __cplusplus
57 }
58 #endif
59
60 #endif /* _FILTER0_H */
...@@ -93,8 +93,11 @@ enum imap_state ...@@ -93,8 +93,11 @@ enum imap_state
93 { 93 {
94 IMAP_NO_STATE=0, 94 IMAP_NO_STATE=0,
95 IMAP_AUTH, IMAP_AUTH_DONE, 95 IMAP_AUTH, IMAP_AUTH_DONE,
96 IMAP_APPEND, IMAP_APPEND_CONT, IMAP_APPEND_SEND, IMAP_APPEND_ACK,
96 IMAP_BODY, 97 IMAP_BODY,
97 IMAP_CLOSE, IMAP_CLOSE_ACK, 98 IMAP_CLOSE, IMAP_CLOSE_ACK,
99 IMAP_COPY, IMAP_COPY_ACK,
100 IMAP_CREATE, IMAP_CREATE_ACK,
98 IMAP_DELETE, IMAP_DELETE_ACK, 101 IMAP_DELETE, IMAP_DELETE_ACK,
99 IMAP_FETCH, IMAP_FETCH_ACK, 102 IMAP_FETCH, IMAP_FETCH_ACK,
100 IMAP_GREETINGS, 103 IMAP_GREETINGS,
......
1 /* GNU mailutils - a suite of utilities for electronic mail 1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3 3
4 This program is free software; you can redistribute it and/or modify 4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Library Public License as published by 5 it under the terms of the GNU General Library Public License as published by
...@@ -39,8 +39,8 @@ extern "C" { ...@@ -39,8 +39,8 @@ extern "C" {
39 # define __P(x) 39 # define __P(x)
40 # endif 40 # endif
41 #endif 41 #endif
42
42 extern size_t _cpystr __P ((char *dst, const char *src, size_t size)); 43 extern size_t _cpystr __P ((char *dst, const char *src, size_t size));
43 extern int parseaddr __P ((const char *addr, char *buf, size_t bufsz));
44 44
45 #ifdef __cplusplus 45 #ifdef __cplusplus
46 } 46 }
......
...@@ -69,7 +69,7 @@ mailbox_create (mailbox_t *pmbox, const char *name) ...@@ -69,7 +69,7 @@ mailbox_create (mailbox_t *pmbox, const char *name)
69 if (found) 69 if (found)
70 { 70 {
71 url_t url = NULL; 71 url_t url = NULL;
72 mailbox_t mbox = NULL; 72 mailbox_t mbox;
73 73
74 /* Allocate memory for mbox. */ 74 /* Allocate memory for mbox. */
75 mbox = calloc (1, sizeof (*mbox)); 75 mbox = calloc (1, sizeof (*mbox));
......
...@@ -34,58 +34,59 @@ ...@@ -34,58 +34,59 @@
34 #include <imap0.h> 34 #include <imap0.h>
35 35
36 /* Functions to overload the mailbox_t API. */ 36 /* Functions to overload the mailbox_t API. */
37 static void mailbox_imap_destroy (mailbox_t); 37 static void mailbox_imap_destroy __P ((mailbox_t));
38 static int mailbox_imap_open (mailbox_t, int); 38 static int mailbox_imap_open __P ((mailbox_t, int));
39 static int mailbox_imap_close (mailbox_t); 39 static int mailbox_imap_close __P ((mailbox_t));
40 static int imap_uidvalidity (mailbox_t, unsigned long *); 40 static int imap_uidvalidity __P ((mailbox_t, unsigned long *));
41 static int imap_uidnext (mailbox_t, size_t *); 41 static int imap_uidnext __P ((mailbox_t, size_t *));
42 static int imap_expunge (mailbox_t); 42 static int imap_expunge __P ((mailbox_t));
43 static int imap_get_message (mailbox_t, size_t, message_t *); 43 static int imap_get_message __P ((mailbox_t, size_t, message_t *));
44 static int imap_messages_count (mailbox_t, size_t *); 44 static int imap_messages_count __P ((mailbox_t, size_t *));
45 static int imap_messages_recent (mailbox_t, size_t *); 45 static int imap_messages_recent __P ((mailbox_t, size_t *));
46 static int imap_message_unseen (mailbox_t, size_t *); 46 static int imap_message_unseen __P ((mailbox_t, size_t *));
47 static int imap_scan (mailbox_t, size_t, size_t *); 47 static int imap_scan __P ((mailbox_t, size_t, size_t *));
48 static int imap_is_updated (mailbox_t); 48 static int imap_is_updated __P ((mailbox_t));
49 static int imap_append_message (mailbox_t, message_t); 49 static int imap_append_message __P ((mailbox_t, message_t));
50 static int imap_copy_message __P ((mailbox_t, message_t));
50 51
51 /* Message API. */ 52 /* Message API. */
52 53
53 static int imap_submessage_size (msg_imap_t, size_t *); 54 static int imap_submessage_size __P ((msg_imap_t, size_t *));
54 static int imap_message_size (message_t, size_t *); 55 static int imap_message_size __P ((message_t, size_t *));
55 static int imap_message_lines (message_t, size_t *); 56 static int imap_message_lines __P ((message_t, size_t *));
56 static int imap_message_fd (stream_t, int *); 57 static int imap_message_fd __P ((stream_t, int *));
57 static int imap_message_read (stream_t , char *, size_t, off_t, size_t *); 58 static int imap_message_read __P ((stream_t , char *, size_t, off_t, size_t *));
58 static int imap_message_uid (message_t, size_t *); 59 static int imap_message_uid __P ((message_t, size_t *));
59 60
60 /* Mime handling. */ 61 /* Mime handling. */
61 static int imap_is_multipart (message_t, int *); 62 static int imap_is_multipart __P ((message_t, int *));
62 static int imap_get_num_parts (message_t, size_t *); 63 static int imap_get_num_parts __P ((message_t, size_t *));
63 static int imap_get_part (message_t, size_t, message_t *); 64 static int imap_get_part __P ((message_t, size_t, message_t *));
64 65
65 /* Envelope. */ 66 /* Envelope. */
66 static int imap_envelope_sender (envelope_t, char *, size_t, size_t *); 67 static int imap_envelope_sender __P ((envelope_t, char *, size_t, size_t *));
67 static int imap_envelope_date (envelope_t, char *, size_t, size_t *); 68 static int imap_envelope_date __P ((envelope_t, char *, size_t, size_t *));
68 69
69 /* Attributes. */ 70 /* Attributes. */
70 static int imap_attr_get_flags (attribute_t, int *); 71 static int imap_attr_get_flags __P ((attribute_t, int *));
71 static int imap_attr_set_flags (attribute_t, int); 72 static int imap_attr_set_flags __P ((attribute_t, int));
72 static int imap_attr_unset_flags (attribute_t, int); 73 static int imap_attr_unset_flags __P ((attribute_t, int));
73 74
74 /* Header. */ 75 /* Header. */
75 static int imap_header_read (header_t, char*, size_t, off_t, size_t *); 76 static int imap_header_read __P ((header_t, char*, size_t, off_t, size_t *));
76 static int imap_header_get_value (header_t, const char*, char *, size_t, size_t *); 77 static int imap_header_get_value __P ((header_t, const char*, char *, size_t, size_t *));
77 78
78 /* Body. */ 79 /* Body. */
79 static int imap_body_read (stream_t, char *, size_t, off_t, size_t *); 80 static int imap_body_read __P ((stream_t, char *, size_t, off_t, size_t *));
80 static int imap_body_size (body_t, size_t *); 81 static int imap_body_size __P ((body_t, size_t *));
81 static int imap_body_lines (body_t, size_t *); 82 static int imap_body_lines __P ((body_t, size_t *));
82 static int imap_body_fd (stream_t, int *); 83 static int imap_body_fd __P ((stream_t, int *));
83 84
84 /* Private. */ 85 /* Private. */
85 static int imap_get_fd (msg_imap_t, int *); 86 static int imap_get_fd __P ((msg_imap_t, int *));
86 static int imap_get_message0 (msg_imap_t, message_t *); 87 static int imap_get_message0 __P ((msg_imap_t, message_t *));
87 static int message_operation (f_imap_t, msg_imap_t, char *, size_t, size_t *); 88 static int message_operation __P ((f_imap_t, msg_imap_t, char *, size_t, size_t *));
88 static void free_subparts (msg_imap_t); 89 static void free_subparts __P ((msg_imap_t));
89 90
90 static const char *MONTHS[] = 91 static const char *MONTHS[] =
91 { 92 {
...@@ -650,12 +651,275 @@ imap_expunge (mailbox_t mailbox) ...@@ -650,12 +651,275 @@ imap_expunge (mailbox_t mailbox)
650 } 651 }
651 652
652 static int 653 static int
653 imap_append_message (mailbox_t mailbox, message_t msg) 654 attribute_string (attribute_t attribute, char **pbuf)
654 { 655 {
655 (void)mailbox; (void)msg; 656 char *abuf = *pbuf;
657 if (attribute_is_deleted (attribute))
658 {
659 char *tmp = realloc (abuf, strlen (abuf) + strlen ("\\Deleted") + 2);
660 if (tmp == NULL)
661 {
662 free (abuf);
663 return ENOMEM;
664 }
665 abuf = tmp;
666 if (*abuf)
667 strcat (abuf, " ");
668 strcat (abuf, "\\Deleted");
669 }
670 if (attribute_is_seen (attribute))
671 {
672 char *tmp = realloc (abuf, strlen (abuf) + strlen ("\\Seen") + 2);
673 if (tmp == NULL)
674 {
675 free (abuf);
676 return ENOMEM;
677 }
678 abuf = tmp;
679 if (*abuf)
680 strcat (abuf, " ");
681 strcat (abuf, "\\Seen");
682 }
683 if (attribute_is_answered (attribute))
684 {
685 char *tmp = realloc (abuf, strlen (abuf) + strlen ("\\Answered") + 2);
686 if (tmp == NULL)
687 {
688 free (abuf);
689 return ENOMEM;
690 }
691 abuf = tmp;
692 if (*abuf)
693 strcat (abuf, " ");
694 strcat (abuf, "\\Answered");
695 }
696 if (attribute_is_draft (attribute))
697 {
698 char *tmp = realloc (abuf, strlen (abuf) + strlen ("\\Draft") + 2);
699 if (tmp == NULL)
700 {
701 free (abuf);
702 return ENOMEM;
703 }
704 abuf = tmp;
705 if (*abuf)
706 strcat (abuf, " ");
707 strcat (abuf, "\\Draft");
708 }
709 if (attribute_is_flagged (attribute))
710 {
711 char *tmp = realloc (abuf, strlen (abuf) + strlen ("\\Flagged") + 2);
712 if (tmp == NULL)
713 {
714 free (abuf);
715 return ENOMEM;
716 }
717 abuf = tmp;
718 if (*abuf)
719 strcat (abuf, " ");
720 strcat (abuf, "\\Flagged");
721 }
722 *pbuf = abuf;
656 return 0; 723 return 0;
657 } 724 }
658 725
726 static int
727 is_same_folder (mailbox_t mailbox, message_t msg)
728 {
729 mailbox_t mbox = NULL;
730 message_get_mailbox (msg, &mbox);
731 return (mbox != NULL && mbox->url != NULL
732 && url_is_same_scheme (mbox->url, mailbox->url)
733 && url_is_same_host (mbox->url, mailbox->url)
734 && url_is_same_port (mbox->url, mailbox->url));
735 }
736
737 /* Not Nonblocking safe. */
738 /* DANGER: The message_t object makes no guarenty the size and the lines
739 that it returns are exact if its pointing to non-local file messages.
740 FIXME: So we should download the message to a floating message so to
741 make sure that we know the exacte size then transmit it back the IMAP
742 server. */
743 static int
744 imap_append_message (mailbox_t mailbox, message_t msg)
745 {
746 size_t total;
747 int status;
748 m_imap_t m_imap = mailbox->data;
749 f_imap_t f_imap = m_imap->f_imap;
750
751 /* FIXME: Can we append to self. */
752
753 /* Check to see if we are selected. If the message was not modified
754 and came from the imap folder. use COPY.*/
755 if (f_imap->selected != m_imap && !message_is_modified (msg)
756 && is_same_folder (mailbox, msg))
757 return imap_copy_message (mailbox, msg);
758
759 /* FIXME: Do we need to get the envelope_date? */
760
761 switch (f_imap->state)
762 {
763 case IMAP_NO_STATE:
764 {
765 size_t lines, size;
766 char *path;
767 char *abuf = malloc (1);
768 /* Get the desired flags attribute. */
769 if (abuf == NULL)
770 return ENOMEM;
771 *abuf = '\0';
772 {
773 attribute_t attribute = NULL;
774 message_get_attribute (msg, &attribute);
775 status = attribute_string (attribute, &abuf);
776 if (status != 0)
777 return status;
778 if (*abuf != '\0')
779 {
780 char *tmp = calloc (strlen (abuf) + 3, 1);
781 if (tmp == NULL)
782 {
783 free (abuf);
784 return ENOMEM;
785 }
786 sprintf (tmp, "(%s)", abuf);
787 free (abuf);
788 abuf = tmp;
789 }
790 }
791 {
792 size_t n = 0;
793 url_get_path (mailbox->url, NULL, 0, &n);
794 if (n == 0)
795 return EINVAL;
796 path = calloc (n + 1, sizeof (*path));
797 if (path == NULL)
798 return ENOMEM;
799 url_get_path (mailbox->url, path, n + 1, NULL);
800 }
801 lines = size = 0;
802 message_size (msg, &size);
803 message_lines (msg, &lines);
804 total = size + lines;
805 status = imap_writeline (f_imap, "g%d APPEND %s %s {%d}\r\n",
806 f_imap->seq++, path, abuf, size + lines);
807 free (abuf);
808 free (path);
809 CHECK_ERROR (f_imap, status);
810 MAILBOX_DEBUG0 (mailbox, MU_DEBUG_PROT, f_imap->buffer);
811 f_imap->state = IMAP_APPEND;
812 }
813
814 case IMAP_APPEND:
815 status = imap_send (f_imap);
816 CHECK_EAGAIN (f_imap, status);
817 MAILBOX_DEBUG0 (m_imap->mailbox, MU_DEBUG_PROT, f_imap->buffer);
818 f_imap->state = IMAP_APPEND_CONT;
819
820 case IMAP_APPEND_CONT:
821 status = imap_parse (f_imap);
822 CHECK_EAGAIN (f_imap, status);
823 MAILBOX_DEBUG0 (mailbox, MU_DEBUG_PROT, f_imap->buffer);
824 /* If we did not receive the continuation token, it is an error
825 bail out. */
826 if (f_imap->buffer[0] != '+')
827 {
828 status = EACCES;
829 break;
830 }
831 f_imap->state = IMAP_APPEND_SEND;
832
833 case IMAP_APPEND_SEND:
834 {
835 stream_t stream = NULL;
836 off_t off = 0;
837 size_t n = 0;
838 char buffer[255];
839 message_get_stream (msg, &stream);
840 while (stream_readline (stream, buffer, sizeof (buffer), off, &n) == 0
841 && n > 0)
842 {
843 if (buffer[n - 1] == '\n')
844 {
845 buffer[n - 1] = '\0';
846 status = imap_writeline (f_imap, "%s\r\n", buffer);
847 }
848 else
849 imap_writeline (f_imap, "%s", buffer);
850 off += n;
851 status = imap_send (f_imap);
852 }
853 f_imap->state = IMAP_APPEND_ACK;
854 }
855 /* !@#%$ UW-IMAP server hack: insists on the last line. */
856 imap_writeline (f_imap, "\n");
857 imap_send (f_imap);
858
859 case IMAP_APPEND_ACK:
860 status = imap_parse (f_imap);
861 CHECK_EAGAIN (f_imap, status);
862 MAILBOX_DEBUG0 (m_imap->mailbox, MU_DEBUG_PROT, f_imap->buffer);
863
864 default:
865 /* fprintf (stderr, "imap_expunge: unknow state\n"); */
866 break;
867 }
868 f_imap->state = IMAP_NO_STATE;
869 return status;
870 }
871
872 /* Not Nonblocking safe. */
873 static int
874 imap_copy_message (mailbox_t mailbox, message_t msg)
875 {
876 m_imap_t m_imap = mailbox->data;
877 f_imap_t f_imap = m_imap->f_imap;
878 msg_imap_t msg_imap = message_get_owner (msg);
879 int status = 0;
880
881 switch (f_imap->state)
882 {
883 case IMAP_NO_STATE:
884 {
885 char *path;
886 /* Check for a valid mailbox name. */
887 {
888 size_t n = 0;
889 url_get_path (mailbox->url, NULL, 0, &n);
890 if (n == 0)
891 return EINVAL;
892 path = calloc (n + 1, sizeof (*path));
893 if (path == NULL)
894 return ENOMEM;
895 url_get_path (mailbox->url, path, n + 1, NULL);
896 }
897 status = imap_writeline (f_imap, "g%d COPY %d %s\r\n", f_imap->seq++,
898 msg_imap->num, path);
899 free (path);
900 CHECK_ERROR (f_imap, status);
901 MAILBOX_DEBUG0 (mailbox, MU_DEBUG_PROT, f_imap->buffer);
902 f_imap->state = IMAP_COPY;
903 }
904
905 case IMAP_COPY:
906 status = imap_send (f_imap);
907 CHECK_EAGAIN (f_imap, status);
908 MAILBOX_DEBUG0 (mailbox, MU_DEBUG_PROT, f_imap->buffer);
909 f_imap->state = IMAP_COPY_ACK;
910
911 case IMAP_COPY_ACK:
912 status = imap_parse (f_imap);
913 CHECK_EAGAIN (f_imap, status);
914 MAILBOX_DEBUG0 (mailbox, MU_DEBUG_PROT, f_imap->buffer);
915
916 default:
917 break;
918 }
919 f_imap->state = IMAP_NO_STATE;
920 return status;
921 }
922
659 /* Message. */ 923 /* Message. */
660 static int 924 static int
661 imap_message_read (stream_t stream, char *buffer, size_t buflen, 925 imap_message_read (stream_t stream, char *buffer, size_t buflen,
...@@ -1075,8 +1339,6 @@ imap_attr_set_flags (attribute_t attribute, int flags) ...@@ -1075,8 +1339,6 @@ imap_attr_set_flags (attribute_t attribute, int flags)
1075 status = imap_writeline (f_imap, "g%d STORE %d +FLAGS.SILENT (%s %s %s %s)\r\n", 1339 status = imap_writeline (f_imap, "g%d STORE %d +FLAGS.SILENT (%s %s %s %s)\r\n",
1076 f_imap->seq++, msg_imap->num, 1340 f_imap->seq++, msg_imap->num,
1077 (flags & MU_ATTRIBUTE_ANSWERED) ? "\\Answered" : "", 1341 (flags & MU_ATTRIBUTE_ANSWERED) ? "\\Answered" : "",
1078 (flags & MU_ATTRIBUTE_RECENT) ? "\\Recent" : "",
1079 (flags & MU_ATTRIBUTE_READ) ? "\\Read" : "",
1080 (flags & MU_ATTRIBUTE_SEEN) ? "\\Seen" : "", 1342 (flags & MU_ATTRIBUTE_SEEN) ? "\\Seen" : "",
1081 (flags & MU_ATTRIBUTE_DRAFT) ? "\\Draft" : "", 1343 (flags & MU_ATTRIBUTE_DRAFT) ? "\\Draft" : "",
1082 (flags & MU_ATTRIBUTE_FLAGGED) ? "\\Flagged" : ""); 1344 (flags & MU_ATTRIBUTE_FLAGGED) ? "\\Flagged" : "");
......
...@@ -1124,7 +1124,7 @@ mbox_body_size (body_t body, size_t *psize) ...@@ -1124,7 +1124,7 @@ mbox_body_size (body_t body, size_t *psize)
1124 if (mum == NULL) 1124 if (mum == NULL)
1125 return EINVAL; 1125 return EINVAL;
1126 if (psize) 1126 if (psize)
1127 *psize = mum->body_end - mum->body + 1; 1127 *psize = mum->body_end - mum->body;
1128 return 0; 1128 return 0;
1129 } 1129 }
1130 1130
......
...@@ -1770,9 +1770,9 @@ static int ...@@ -1770,9 +1770,9 @@ static int
1770 pop_write (pop_data_t mpd) 1770 pop_write (pop_data_t mpd)
1771 { 1771 {
1772 int status = 0; 1772 int status = 0;
1773 size_t len;
1774 if (mpd->ptr > mpd->buffer) 1773 if (mpd->ptr > mpd->buffer)
1775 { 1774 {
1775 size_t len;
1776 len = mpd->ptr - mpd->buffer; 1776 len = mpd->ptr - mpd->buffer;
1777 status = stream_write (mpd->mbox->stream, mpd->buffer, len, 0, &len); 1777 status = stream_write (mpd->mbox->stream, mpd->buffer, len, 0, &len);
1778 if (status == 0) 1778 if (status == 0)
...@@ -1782,10 +1782,7 @@ pop_write (pop_data_t mpd) ...@@ -1782,10 +1782,7 @@ pop_write (pop_data_t mpd)
1782 } 1782 }
1783 } 1783 }
1784 else 1784 else
1785 { 1785 mpd->ptr = mpd->buffer;
1786 mpd->ptr = mpd->buffer;
1787 len = 0;
1788 }
1789 return status; 1786 return status;
1790 } 1787 }
1791 1788
......
...@@ -30,8 +30,8 @@ ...@@ -30,8 +30,8 @@
30 30
31 #include "md5.h" 31 #include "md5.h"
32 32
33 #include <misc.h>
34 #include <message0.h> 33 #include <message0.h>
34 #include <mailutils/address.h>
35 35
36 static int message_read __P ((stream_t is, char *buf, size_t buflen, 36 static int message_read __P ((stream_t is, char *buf, size_t buflen,
37 off_t off, size_t *pnread )); 37 off_t off, size_t *pnread ));
...@@ -213,6 +213,15 @@ message_get_property (message_t msg, property_t *pproperty) ...@@ -213,6 +213,15 @@ message_get_property (message_t msg, property_t *pproperty)
213 } 213 }
214 214
215 int 215 int
216 message_get_mailbox (message_t msg, mailbox_t *pmailbox)
217 {
218 if (msg == NULL || pmailbox == NULL)
219 return EINVAL;
220 *pmailbox = msg->mailbox;
221 return 0;
222 }
223
224 int
216 message_set_mailbox (message_t msg, mailbox_t mailbox, void *owner) 225 message_set_mailbox (message_t msg, mailbox_t mailbox, void *owner)
217 { 226 {
218 if (msg == NULL) 227 if (msg == NULL)
...@@ -894,34 +903,16 @@ message_sender (envelope_t envelope, char *buf, size_t len, size_t *pnwrite) ...@@ -894,34 +903,16 @@ message_sender (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
894 if (status == 0 && n != 0) 903 if (status == 0 && n != 0)
895 { 904 {
896 char *sender; 905 char *sender;
897 char *addr; 906 address_t address = NULL;
898 sender = calloc (1, n + 1); 907 sender = calloc (1, n + 1);
899 if (sender == NULL) 908 if (sender == NULL)
900 return ENOMEM; 909 return ENOMEM;
901 addr = calloc (1, n + 1);
902 if (addr == NULL)
903 {
904 free (sender);
905 return ENOMEM;
906 }
907 header_get_value (header, MU_HEADER_FROM, sender, n + 1, NULL); 910 header_get_value (header, MU_HEADER_FROM, sender, n + 1, NULL);
908 if (parseaddr (sender, addr, n + 1) == 0) 911 if (address_create (&address, sender) == 0)
909 { 912 address_get_email (address, 1, buf, n + 1, pnwrite);
910 size_t i = strlen (addr);
911 n = (i > len) ? len : i;
912 if (buf && len > 0)
913 {
914 memcpy (buf, addr, n);
915 buf[n] = '\0';
916 }
917 free (addr);
918 free (sender);
919 if (pnwrite)
920 *pnwrite = n;
921 return 0;
922 }
923 free (addr);
924 free (sender); 913 free (sender);
914 address_destroy (&address);
915 return 0;
925 } 916 }
926 else if (status == EAGAIN) 917 else if (status == EAGAIN)
927 return status; 918 return status;
......
1 /* GNU mailutils - a suite of utilities for electronic mail 1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3 3
4 This program is free software; you can redistribute it and/or modify 4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Library Public License as published by 5 it under the terms of the GNU General Library Public License as published by
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
27 #include <ctype.h> 27 #include <ctype.h>
28 #include <stdlib.h> 28 #include <stdlib.h>
29 29
30 /* Smart strncpy that always add the null and returns the number of bytes
31 written. */
30 size_t 32 size_t
31 _cpystr (char *dst, const char *src, size_t size) 33 _cpystr (char *dst, const char *src, size_t size)
32 { 34 {
...@@ -39,153 +41,3 @@ _cpystr (char *dst, const char *src, size_t size) ...@@ -39,153 +41,3 @@ _cpystr (char *dst, const char *src, size_t size)
39 dst[len] = '\0'; 41 dst[len] = '\0';
40 return len; 42 return len;
41 } 43 }
42
43 /*
44 * parseaddr.c Read a valid RFC822 address with all the comments
45 * etc in it, and return _just_ the email address.
46 *
47 * Version: @(#)parseaddr.c 1.00 02-Apr-1999 miquels@cistron.nl
48 *
49 */
50
51
52 struct token
53 {
54 struct token *next;
55 char word[1];
56 };
57
58 #define SKIPSPACE(p) do { while(*p && isspace((unsigned char)*p)) p++; } while(0)
59
60 /* Skip everything between quotes. */
61 static void
62 quotes (const char **ptr)
63 {
64 const char *p = *ptr;
65
66 p++;
67 while (*p && *p != '"')
68 {
69 if (*p == '\\' && p[1])
70 p++;
71 p++;
72 }
73 *ptr = p;
74 }
75
76 /* Return the next token. A token can be "<>()," or any "word". */
77 static struct token *
78 gettoken (const char **ptr)
79 {
80 struct token *tok;
81 const char *p = *ptr;
82 const char *begin;
83 int l, quit = 0;
84
85 SKIPSPACE(p);
86 begin = p;
87
88 while (!quit)
89 {
90 switch (*p)
91 {
92 case 0:
93 case ' ':
94 case '\t':
95 case '\n':
96 quit = 1;
97 break;
98 case '(':
99 case ')':
100 case '<':
101 case '>':
102 case ',':
103 if (p == begin)
104 p++;
105 quit = 1;
106 break;
107 case '\\':
108 if (p[1])
109 p++;
110 break;
111 case '"':
112 quotes (&p);
113 break;
114 }
115 if (!quit)
116 p++;
117 }
118
119 l = p - begin;
120 if (l == 0)
121 return NULL;
122 tok = malloc (sizeof (struct token) + l);
123 if (tok == NULL)
124 return NULL;
125 tok->next = NULL;
126 strncpy (tok->word, begin, l);
127 tok->word[l] = 0;
128
129 SKIPSPACE (p);
130 *ptr = p;
131
132 return tok;
133 }
134
135 /* Get email address from rfc822 address. */
136 int
137 parseaddr (const char *addr, char *buf, size_t bufsz)
138 {
139 const char *p;
140 struct token *t, *tok, *last;
141 struct token *brace = NULL;
142 int comment = 0;
143 int status = 0;
144
145 tok = last = NULL;
146
147 /* Read address, remove comments right away. */
148 p = addr;
149 while ((t = gettoken(&p)) != NULL && t->word[0] != ',')
150 {
151 if (t->word[0] == '(' || t->word[0] == ')' || comment)
152 {
153 free (t);
154 if (t->word[0] == '(')
155 comment++;
156 if (t->word[0] == ')')
157 comment--;
158 continue;
159 }
160 if (t->word[0] == '<')
161 brace = t;
162 if (tok)
163 last->next = t;
164 else
165 tok = t;
166 last = t;
167 }
168
169 /* Put extracted address into "buf" */
170 buf[0] = 0;
171 t = brace ? brace->next : tok;
172 for (; t && t->word[0] != ',' && t->word[0] != '>'; t = t->next)
173 {
174 if (strlen (t->word) >= bufsz)
175 {
176 status = -1;
177 break;
178 }
179 bufsz -= strlen (t->word);
180 strcat (buf, t->word);
181 }
182
183 /* Free list of tokens. */
184 for (t = tok; t; t = last)
185 {
186 last = t->next;
187 free (t);
188 }
189
190 return status;
191 }
......
...@@ -95,7 +95,7 @@ static int str_append_n(char** to, const char* from, size_t n) ...@@ -95,7 +95,7 @@ static int str_append_n(char** to, const char* from, size_t n)
95 if(!bigger) { 95 if(!bigger) {
96 return ENOMEM; 96 return ENOMEM;
97 } 97 }
98 98
99 *to = bigger; 99 *to = bigger;
100 } else { 100 } else {
101 *to = malloc(n + 1); 101 *to = malloc(n + 1);
...@@ -283,7 +283,7 @@ int parse822_comment(const char** p, const char* e, char** comment) ...@@ -283,7 +283,7 @@ int parse822_comment(const char** p, const char* e, char** comment)
283 if((rc = parse822_special(p, e, '('))) { 283 if((rc = parse822_special(p, e, '('))) {
284 return rc; 284 return rc;
285 } 285 }
286 286
287 while(*p != e) { 287 while(*p != e) {
288 char c = **p; 288 char c = **p;
289 289
...@@ -307,7 +307,7 @@ int parse822_comment(const char** p, const char* e, char** comment) ...@@ -307,7 +307,7 @@ int parse822_comment(const char** p, const char* e, char** comment)
307 if(rc != EOK) 307 if(rc != EOK)
308 break; 308 break;
309 } 309 }
310 310
311 if(*p == e) { 311 if(*p == e) {
312 rc = EPARSE; /* end-of-comment not found */ 312 rc = EPARSE; /* end-of-comment not found */
313 } 313 }
...@@ -536,6 +536,8 @@ static int fill_mb( ...@@ -536,6 +536,8 @@ static int fill_mb(
536 return rc; 536 return rc;
537 } 537 }
538 538
539 /* FIXME: Delete this one. adddress.c do the work now. */
540 #if 0
539 int address_create0 (address_t* a, const char* s) 541 int address_create0 (address_t* a, const char* s)
540 { 542 {
541 /* 'a' must exist, and can't already have been initialized 543 /* 'a' must exist, and can't already have been initialized
...@@ -546,7 +548,7 @@ int address_create0 (address_t* a, const char* s) ...@@ -546,7 +548,7 @@ int address_create0 (address_t* a, const char* s)
546 if(!a || *a) { 548 if(!a || *a) {
547 return EINVAL; 549 return EINVAL;
548 } 550 }
549 551
550 status = parse822_address_list(a, (char*) s); 552 status = parse822_address_list(a, (char*) s);
551 553
552 if(status == EOK) { 554 if(status == EOK) {
...@@ -566,6 +568,7 @@ int address_create0 (address_t* a, const char* s) ...@@ -566,6 +568,7 @@ int address_create0 (address_t* a, const char* s)
566 568
567 return status; 569 return status;
568 } 570 }
571 #endif
569 572
570 int parse822_address_list(address_t* a, const char* s) 573 int parse822_address_list(address_t* a, const char* s)
571 { 574 {
...@@ -585,7 +588,7 @@ int parse822_address_list(address_t* a, const char* s) ...@@ -585,7 +588,7 @@ int parse822_address_list(address_t* a, const char* s)
585 { 588 {
586 /* An address can contain a group, so an entire 589 /* An address can contain a group, so an entire
587 * list of addresses may have been appended, or no 590 * list of addresses may have been appended, or no
588 * addresses at all. Walk to the end. 591 * addresses at all. Walk to the end.
589 */ 592 */
590 while(*n) { 593 while(*n) {
591 n = &(*n)->next; 594 n = &(*n)->next;
...@@ -626,7 +629,7 @@ int parse822_address(const char** p, const char* e, address_t* a) ...@@ -626,7 +629,7 @@ int parse822_address(const char** p, const char* e, address_t* a)
626 /* address = mailbox / group */ 629 /* address = mailbox / group */
627 630
628 int rc; 631 int rc;
629 632
630 if((rc = parse822_mail_box(p, e, a)) == EPARSE) 633 if((rc = parse822_mail_box(p, e, a)) == EPARSE)
631 rc = parse822_group(p, e, a); 634 rc = parse822_group(p, e, a);
632 635
...@@ -672,7 +675,7 @@ int parse822_group(const char** p, const char* e, address_t* a) ...@@ -672,7 +675,7 @@ int parse822_group(const char** p, const char* e, address_t* a)
672 } else if(rc != EPARSE) { 675 } else if(rc != EPARSE) {
673 break; 676 break;
674 } 677 }
675 678
676 if((rc = parse822_special(p, e, ','))) { 679 if((rc = parse822_special(p, e, ','))) {
677 /* the commas aren't optional */ 680 /* the commas aren't optional */
678 break; 681 break;
...@@ -785,7 +788,7 @@ int parse822_route_addr(const char** p, const char* e, address_t* a) ...@@ -785,7 +788,7 @@ int parse822_route_addr(const char** p, const char* e, address_t* a)
785 *p = save; 788 *p = save;
786 789
787 address_destroy(a); 790 address_destroy(a);
788 791
789 return rc; 792 return rc;
790 } 793 }
791 794
...@@ -898,7 +901,7 @@ int parse822_local_part(const char** p, const char* e, char** local_part) ...@@ -898,7 +901,7 @@ int parse822_local_part(const char** p, const char* e, char** local_part)
898 return rc; 901 return rc;
899 } 902 }
900 /* We've got a local-part, but keep looking for more. */ 903 /* We've got a local-part, but keep looking for more. */
901 904
902 parse822_skip_comments(p, e); 905 parse822_skip_comments(p, e);
903 906
904 /* If we get a parse error, we roll back to save2, but if 907 /* If we get a parse error, we roll back to save2, but if
...@@ -992,7 +995,7 @@ int parse822_sub_domain(const char** p, const char* e, char** sub_domain) ...@@ -992,7 +995,7 @@ int parse822_sub_domain(const char** p, const char* e, char** sub_domain)
992 */ 995 */
993 996
994 int rc; 997 int rc;
995 998
996 if((rc = parse822_domain_ref(p, e, sub_domain)) == EPARSE) 999 if((rc = parse822_domain_ref(p, e, sub_domain)) == EPARSE)
997 rc = parse822_domain_literal(p, e, sub_domain); 1000 rc = parse822_domain_literal(p, e, sub_domain);
998 1001
...@@ -1157,6 +1160,4 @@ int parse822_field_body(const char** p, const char* e, Rope& fieldbody) ...@@ -1157,6 +1160,4 @@ int parse822_field_body(const char** p, const char* e, Rope& fieldbody)
1157 1160
1158 return 1; 1161 return 1;
1159 } 1162 }
1160
1161 #endif 1163 #endif
1162
......
1 /* GNU mailutils - a suite of utilities for electronic mail 1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3 3
4 This program is free software; you can redistribute it and/or modify 4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Library Public License as published by 5 it under the terms of the GNU General Library Public License as published by
...@@ -196,3 +196,113 @@ url_to_string (const url_t url) ...@@ -196,3 +196,113 @@ url_to_string (const url_t url)
196 return ""; 196 return "";
197 return url->name; 197 return url->name;
198 } 198 }
199
200 int
201 url_is_same_scheme (url_t url1, url_t url2)
202 {
203 size_t i = 0, j = 0;
204 char *s1, *s2;
205 int ret = 1;
206
207 url_get_scheme (url1, NULL, 0, &i);
208 url_get_scheme (url2, NULL, 0, &j);
209 s1 = calloc (i + 1, sizeof (char));
210 if (s1)
211 {
212 url_get_scheme (url1, s1, i + 1, NULL);
213 s2 = calloc (j + 1, sizeof (char));
214 if (s2)
215 {
216 url_get_scheme (url2, s2, j + 1, NULL);
217 ret = !strcasecmp (s1, s2);
218 free (s2);
219 }
220 free (s1);
221 }
222 return ret;
223 }
224
225 int
226 url_is_same_user (url_t url1, url_t url2)
227 {
228 size_t i = 0, j = 0;
229 char *s1, *s2;
230 int ret = 0;
231
232 url_get_user (url1, NULL, 0, &i);
233 url_get_user (url2, NULL, 0, &j);
234 s1 = calloc (i + 1, sizeof (char));
235 if (s1)
236 {
237 url_get_user (url1, s1, i + 1, NULL);
238 s2 = calloc (j + 1, sizeof (char));
239 if (s2)
240 {
241 url_get_user (url2, s2, j + 1, NULL);
242 ret = !strcasecmp (s1, s2);
243 free (s2);
244 }
245 free (s1);
246 }
247 return ret;
248 }
249
250 int
251 url_is_same_path (url_t url1, url_t url2)
252 {
253 size_t i = 0, j = 0;
254 char *s1, *s2;
255 int ret = 0;
256
257 url_get_path (url1, NULL, 0, &i);
258 url_get_path (url2, NULL, 0, &j);
259 s1 = calloc (i + 1, sizeof (char));
260 if (s1)
261 {
262 url_get_path (url1, s1, i + 1, NULL);
263 s2 = calloc (j + 1, sizeof (char));
264 if (s2)
265 {
266 url_get_path (url2, s2, j + 1, NULL);
267 ret = !strcasecmp (s1, s2);
268 free (s2);
269 }
270 free (s1);
271 }
272 return ret;
273 }
274
275 int
276 url_is_same_host (url_t url1, url_t url2)
277 {
278 size_t i = 0, j = 0;
279 char *s1, *s2;
280 int ret = 0;
281
282 url_get_host (url1, NULL, 0, &i);
283 url_get_host (url2, NULL, 0, &j);
284 s1 = calloc (i + 1, sizeof (char));
285 if (s1)
286 {
287 url_get_host (url1, s1, i + 1, NULL);
288 s2 = calloc (j + 1, sizeof (char));
289 if (s2)
290 {
291 url_get_host (url2, s2, j + 1, NULL);
292 ret = !strcasecmp (s1, s2);
293 free (s2);
294 }
295 free (s1);
296 }
297 return ret;
298 }
299
300 int
301 url_is_same_port (url_t url1, url_t url2)
302 {
303 long p1 = 0, p2 = 0;
304
305 url_get_port (url1, &p1);
306 url_get_port (url2, &p2);
307 return (p1 == p2);
308 }
......