* 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..
Showing
20 changed files
with
743 additions
and
898 deletions
... | @@ -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 | } | ... | ... |
mailbox/include/filter0.h
0 → 100644
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 | } | ... | ... |
-
Please register or sign in to post a comment