author | zautrix <zautrix> | 2004-07-03 16:33:12 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-07-03 16:33:12 (UTC) |
commit | e3b89230f065c48c84b48c88edb6eb088374c487 (patch) (unidiff) | |
tree | 162ea2ef909a6f82ccfcedf45d80d6c821174912 /kmicromail/libetpan/imap/mailimap_sender.c | |
parent | 2dd6ac0b2d24c91d35ce674a6c26351352df2b15 (diff) | |
download | kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.zip kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.tar.gz kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.tar.bz2 |
Initial revision
Diffstat (limited to 'kmicromail/libetpan/imap/mailimap_sender.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | kmicromail/libetpan/imap/mailimap_sender.c | 2743 |
1 files changed, 2743 insertions, 0 deletions
diff --git a/kmicromail/libetpan/imap/mailimap_sender.c b/kmicromail/libetpan/imap/mailimap_sender.c new file mode 100644 index 0000000..ac4bfe8 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_sender.c | |||
@@ -0,0 +1,2743 @@ | |||
1 | /* | ||
2 | * libEtPan! -- a mail stuff library | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 - DINH Viet Hoa | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the name of the libEtPan! project nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived | ||
17 | * from this software without specific prior written permission. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
29 | * SUCH DAMAGE. | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * $Id$ | ||
34 | */ | ||
35 | |||
36 | #include "mailstream.h" | ||
37 | #include "mailimap_keywords.h" | ||
38 | #include "mailimap_sender.h" | ||
39 | #include "clist.h" | ||
40 | #include "mail.h" | ||
41 | #include <string.h> | ||
42 | |||
43 | #include <stdio.h> | ||
44 | #include <ctype.h> | ||
45 | |||
46 | /* | ||
47 | TODO : | ||
48 | implement progression for literal | ||
49 | */ | ||
50 | |||
51 | /* ************************************************************************* */ | ||
52 | /* ************************************************************************* */ | ||
53 | /* ************************************************************************* */ | ||
54 | /* ************************************************************************* */ | ||
55 | /* ************************************************************************* */ | ||
56 | /* ************************************************************************* */ | ||
57 | |||
58 | |||
59 | |||
60 | |||
61 | static int mailimap_atom_send(mailstream * fd, const char * atom); | ||
62 | |||
63 | static int mailimap_auth_type_send(mailstream * fd, const char * auth_type); | ||
64 | |||
65 | static int mailimap_base64_send(mailstream * fd, const char * base64); | ||
66 | |||
67 | |||
68 | static int mailimap_date_send(mailstream * fd, | ||
69 | struct mailimap_date * date); | ||
70 | |||
71 | static int mailimap_date_day_send(mailstream * fd, int day); | ||
72 | |||
73 | static int mailimap_date_month_send(mailstream * fd, int month); | ||
74 | |||
75 | |||
76 | /* | ||
77 | static gboolean mailimap_date_text_send(mailstream * fd, | ||
78 | struct mailimap_date_text * date_text); | ||
79 | */ | ||
80 | |||
81 | |||
82 | static int mailimap_date_year_send(mailstream *fd, int year); | ||
83 | |||
84 | static int | ||
85 | mailimap_date_time_send(mailstream * fd, | ||
86 | struct mailimap_date_time * date_time); | ||
87 | |||
88 | static int mailimap_digit_send(mailstream * fd, int digit); | ||
89 | |||
90 | |||
91 | |||
92 | static int | ||
93 | mailimap_fetch_type_send(mailstream * fd, | ||
94 | struct mailimap_fetch_type * fetch_type); | ||
95 | |||
96 | |||
97 | static int mailimap_fetch_att_send(mailstream * fd, | ||
98 | struct mailimap_fetch_att * fetch_att); | ||
99 | |||
100 | |||
101 | static int mailimap_flag_send(mailstream * fd, | ||
102 | struct mailimap_flag * flag); | ||
103 | |||
104 | |||
105 | static int mailimap_flag_extension_send(mailstream * fd, | ||
106 | const char * flag_extension); | ||
107 | |||
108 | |||
109 | static int mailimap_flag_keyword_send(mailstream * fd, | ||
110 | const char * flag_keyword); | ||
111 | |||
112 | |||
113 | static int mailimap_flag_list_send(mailstream * fd, | ||
114 | struct mailimap_flag_list * flag_list); | ||
115 | |||
116 | |||
117 | |||
118 | static int mailimap_header_fld_name_send(mailstream * fd, const char * header); | ||
119 | |||
120 | |||
121 | static int | ||
122 | mailimap_header_list_send(mailstream * fd, | ||
123 | struct mailimap_header_list * header_list); | ||
124 | |||
125 | static int | ||
126 | mailimap_list_mailbox_send(mailstream * fd, const char * pattern); | ||
127 | |||
128 | |||
129 | static int mailimap_mailbox_send(mailstream * fd, const char * mb); | ||
130 | |||
131 | static int mailimap_number_send(mailstream * fd, uint32_t number); | ||
132 | |||
133 | static int mailimap_password_send(mailstream * fd, const char * pass); | ||
134 | |||
135 | static int mailimap_quoted_char_send(mailstream * fd, char ch); | ||
136 | |||
137 | static int mailimap_quoted_send(mailstream * fd, const char * quoted); | ||
138 | |||
139 | |||
140 | static int mailimap_search_key_send(mailstream * fd, | ||
141 | struct mailimap_search_key * key); | ||
142 | |||
143 | static int | ||
144 | mailimap_section_send(mailstream * fd, | ||
145 | struct mailimap_section * section); | ||
146 | |||
147 | static int | ||
148 | mailimap_section_msgtext_send(mailstream * fd, | ||
149 | struct mailimap_section_msgtext * | ||
150 | section_msgtext); | ||
151 | |||
152 | |||
153 | static int | ||
154 | mailimap_section_part_send(mailstream * fd, | ||
155 | struct mailimap_section_part * section); | ||
156 | |||
157 | |||
158 | static int | ||
159 | mailimap_section_spec_send(mailstream * fd, | ||
160 | struct mailimap_section_spec * section_spec); | ||
161 | |||
162 | |||
163 | static int | ||
164 | mailimap_section_text_send(mailstream * fd, | ||
165 | struct mailimap_section_text * section_text); | ||
166 | |||
167 | |||
168 | static int | ||
169 | mailimap_sequence_num_send(mailstream * fd, uint32_t sequence_num); | ||
170 | |||
171 | |||
172 | static int mailimap_set_item_send(mailstream * fd, | ||
173 | struct mailimap_set_item * item); | ||
174 | |||
175 | |||
176 | static int mailimap_set_send(mailstream * fd, | ||
177 | struct mailimap_set * set); | ||
178 | |||
179 | |||
180 | |||
181 | static int mailimap_status_att_send(mailstream * fd, int * status_att); | ||
182 | |||
183 | |||
184 | |||
185 | static int | ||
186 | mailimap_store_att_flags_send(mailstream * fd, | ||
187 | struct mailimap_store_att_flags * store_flags); | ||
188 | |||
189 | |||
190 | static int mailimap_userid_send(mailstream * fd, const char * user); | ||
191 | |||
192 | |||
193 | |||
194 | |||
195 | |||
196 | |||
197 | |||
198 | |||
199 | |||
200 | |||
201 | |||
202 | |||
203 | |||
204 | |||
205 | /* ************************************************************************* */ | ||
206 | /* ************************************************************************* */ | ||
207 | /* ************************************************************************* */ | ||
208 | /* ************************************************************************* */ | ||
209 | /* ************************************************************************* */ | ||
210 | /* ************************************************************************* */ | ||
211 | |||
212 | |||
213 | |||
214 | |||
215 | |||
216 | static int mailimap_sized_token_send(mailstream * fd, const char * atom, | ||
217 | size_t len) | ||
218 | { | ||
219 | if (mailstream_write(fd, atom, len) == -1) | ||
220 | return MAILIMAP_ERROR_STREAM; | ||
221 | |||
222 | return MAILIMAP_NO_ERROR; | ||
223 | } | ||
224 | |||
225 | static int mailimap_token_send(mailstream * fd, const char * atom) | ||
226 | { | ||
227 | if (mailstream_write(fd, atom, strlen(atom)) == -1) | ||
228 | return MAILIMAP_ERROR_STREAM; | ||
229 | |||
230 | return MAILIMAP_NO_ERROR; | ||
231 | } | ||
232 | |||
233 | static int mailimap_char_send(mailstream * fd, char ch) | ||
234 | { | ||
235 | if (mailstream_write(fd, &ch, 1) == -1) | ||
236 | return MAILIMAP_ERROR_STREAM; | ||
237 | |||
238 | return MAILIMAP_NO_ERROR; | ||
239 | } | ||
240 | |||
241 | typedef int mailimap_struct_sender(mailstream * fd, void * data); | ||
242 | |||
243 | static int | ||
244 | mailimap_struct_list_send(mailstream * fd, clist * list, | ||
245 | char symbol, | ||
246 | mailimap_struct_sender * sender) | ||
247 | { | ||
248 | clistiter * cur; | ||
249 | void * elt; | ||
250 | int r; | ||
251 | |||
252 | cur = clist_begin(list); | ||
253 | |||
254 | if (cur == NULL) | ||
255 | return MAILIMAP_NO_ERROR; | ||
256 | |||
257 | elt = clist_content(cur); | ||
258 | r = (* sender)(fd, elt); | ||
259 | if (r != MAILIMAP_NO_ERROR) | ||
260 | return r; | ||
261 | cur = clist_next(cur); | ||
262 | |||
263 | while (cur != NULL) { | ||
264 | r = mailimap_char_send(fd, symbol); | ||
265 | if (r != MAILIMAP_NO_ERROR) | ||
266 | return r; | ||
267 | elt = clist_content(cur); | ||
268 | r = (* sender)(fd, elt); | ||
269 | if (r != MAILIMAP_NO_ERROR) | ||
270 | return r; | ||
271 | cur = clist_next(cur); | ||
272 | } | ||
273 | |||
274 | return MAILIMAP_NO_ERROR; | ||
275 | } | ||
276 | |||
277 | |||
278 | static int | ||
279 | mailimap_struct_spaced_list_send(mailstream * fd, clist * list, | ||
280 | mailimap_struct_sender * sender) | ||
281 | { | ||
282 | return mailimap_struct_list_send(fd, list, ' ', sender); | ||
283 | } | ||
284 | |||
285 | int mailimap_space_send(mailstream * fd) | ||
286 | { | ||
287 | return mailimap_char_send(fd, ' '); | ||
288 | } | ||
289 | |||
290 | int mailimap_crlf_send(mailstream * fd) | ||
291 | { | ||
292 | int r; | ||
293 | |||
294 | r = mailimap_char_send(fd, '\r'); | ||
295 | if (r != MAILIMAP_NO_ERROR) | ||
296 | return r; | ||
297 | r = mailimap_char_send(fd, '\n'); | ||
298 | if (r != MAILIMAP_NO_ERROR) | ||
299 | return r; | ||
300 | |||
301 | return MAILIMAP_NO_ERROR; | ||
302 | } | ||
303 | |||
304 | static int mailimap_oparenth_send(mailstream * fd) | ||
305 | { | ||
306 | return mailimap_char_send(fd, '('); | ||
307 | } | ||
308 | |||
309 | static int mailimap_cparenth_send(mailstream * fd) | ||
310 | { | ||
311 | return mailimap_char_send(fd, ')'); | ||
312 | } | ||
313 | |||
314 | static int mailimap_dquote_send(mailstream * fd) | ||
315 | { | ||
316 | return mailimap_char_send(fd, '"'); | ||
317 | } | ||
318 | |||
319 | /* | ||
320 | address = "(" addr-name SP addr-adl SP addr-mailbox SP | ||
321 | addr-host ")" | ||
322 | |||
323 | addr-adl = nstring | ||
324 | ; Holds route from [RFC-822] route-addr if | ||
325 | ; non-NIL | ||
326 | |||
327 | addr-host = nstring | ||
328 | ; NIL indicates [RFC-822] group syntax. | ||
329 | ; Otherwise, holds [RFC-822] domain name | ||
330 | |||
331 | addr-mailbox = nstring | ||
332 | ; NIL indicates end of [RFC-822] group; if | ||
333 | ; non-NIL and addr-host is NIL, holds | ||
334 | ; [RFC-822] group name. | ||
335 | ; Otherwise, holds [RFC-822] local-part | ||
336 | ; after removing [RFC-822] quoting | ||
337 | |||
338 | addr-name = nstring | ||
339 | ; If non-NIL, holds phrase from [RFC-822] | ||
340 | ; mailbox after removing [RFC-822] quoting | ||
341 | */ | ||
342 | |||
343 | /* | ||
344 | => append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP | ||
345 | literal | ||
346 | */ | ||
347 | |||
348 | int mailimap_append_send(mailstream * fd, | ||
349 | const char * mailbox, | ||
350 | struct mailimap_flag_list * flag_list, | ||
351 | struct mailimap_date_time * date_time, | ||
352 | size_t literal_size) | ||
353 | { | ||
354 | int r; | ||
355 | |||
356 | r = mailimap_token_send(fd, "APPEND"); | ||
357 | if (r != MAILIMAP_NO_ERROR) | ||
358 | return r; | ||
359 | r = mailimap_space_send(fd); | ||
360 | if (r != MAILIMAP_NO_ERROR) | ||
361 | return r; | ||
362 | r = mailimap_mailbox_send(fd, mailbox); | ||
363 | if (r != MAILIMAP_NO_ERROR) | ||
364 | return r; | ||
365 | if (flag_list != NULL) { | ||
366 | r = mailimap_space_send(fd); | ||
367 | if (r != MAILIMAP_NO_ERROR) | ||
368 | return r; | ||
369 | r = mailimap_flag_list_send(fd, flag_list); | ||
370 | if (r != MAILIMAP_NO_ERROR) | ||
371 | return r; | ||
372 | } | ||
373 | if (date_time != NULL) { | ||
374 | r = mailimap_space_send(fd); | ||
375 | if (r != MAILIMAP_NO_ERROR) | ||
376 | return r; | ||
377 | r = mailimap_date_time_send(fd, date_time); | ||
378 | if (r != MAILIMAP_NO_ERROR) | ||
379 | return r; | ||
380 | } | ||
381 | |||
382 | r = mailimap_space_send(fd); | ||
383 | if (r != MAILIMAP_NO_ERROR) | ||
384 | return r; | ||
385 | r = mailimap_literal_count_send(fd, literal_size); | ||
386 | if (r != MAILIMAP_NO_ERROR) | ||
387 | return r; | ||
388 | |||
389 | return MAILIMAP_NO_ERROR; | ||
390 | } | ||
391 | |||
392 | /* | ||
393 | astring = 1*ASTRING-CHAR / string | ||
394 | |||
395 | => ASTRING-CHAR = ATOM-CHAR / resp-specials | ||
396 | */ | ||
397 | |||
398 | static int is_atom(const char * str) | ||
399 | { | ||
400 | if (* str == '\0') | ||
401 | return 0; | ||
402 | |||
403 | while (* str != '\0') { | ||
404 | unsigned char uch = (unsigned char) * str; | ||
405 | |||
406 | if (!isalnum(uch)) | ||
407 | return 0; | ||
408 | |||
409 | str ++; | ||
410 | } | ||
411 | |||
412 | return 1; | ||
413 | } | ||
414 | |||
415 | static int mailimap_astring_send(mailstream * fd, const char * astring) | ||
416 | { | ||
417 | /* | ||
418 | workaround for buggy Courier-IMAP that does not accept | ||
419 | quoted-strings for fields name but prefer atoms. | ||
420 | */ | ||
421 | if (is_atom(astring)) | ||
422 | return mailimap_atom_send(fd, astring); | ||
423 | else | ||
424 | return mailimap_quoted_send(fd, astring); | ||
425 | } | ||
426 | |||
427 | /* | ||
428 | => atom = 1*ATOM-CHAR | ||
429 | */ | ||
430 | |||
431 | static int mailimap_atom_send(mailstream * fd, const char * atom) | ||
432 | { | ||
433 | return mailimap_token_send(fd, atom); | ||
434 | } | ||
435 | |||
436 | /* | ||
437 | => ATOM-CHAR = <any CHAR except atom-specials> | ||
438 | */ | ||
439 | |||
440 | /* | ||
441 | => atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards / | ||
442 | quoted-specials / resp-specials | ||
443 | */ | ||
444 | |||
445 | /* | ||
446 | => authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64) | ||
447 | */ | ||
448 | |||
449 | int mailimap_authenticate_send(mailstream * fd, | ||
450 | const char * auth_type) | ||
451 | { | ||
452 | int r; | ||
453 | |||
454 | r = mailimap_token_send(fd, "AUTHENTICATE"); | ||
455 | if (r != MAILIMAP_NO_ERROR) | ||
456 | return r; | ||
457 | r = mailimap_space_send(fd); | ||
458 | if (r != MAILIMAP_NO_ERROR) | ||
459 | return r; | ||
460 | r = mailimap_auth_type_send(fd, auth_type); | ||
461 | if (r != MAILIMAP_NO_ERROR) | ||
462 | return r; | ||
463 | |||
464 | return MAILIMAP_NO_ERROR; | ||
465 | } | ||
466 | |||
467 | int mailimap_authenticate_resp_send(mailstream * fd, | ||
468 | const char * base64) | ||
469 | { | ||
470 | int r; | ||
471 | |||
472 | r = mailimap_base64_send(fd, base64); | ||
473 | if (r != MAILIMAP_NO_ERROR) | ||
474 | return r; | ||
475 | |||
476 | return MAILIMAP_NO_ERROR; | ||
477 | } | ||
478 | |||
479 | /* | ||
480 | => auth-type = atom | ||
481 | ; Defined by [SASL] | ||
482 | */ | ||
483 | |||
484 | static int mailimap_auth_type_send(mailstream * fd, const char * auth_type) | ||
485 | { | ||
486 | return mailimap_atom_send(fd, auth_type); | ||
487 | } | ||
488 | |||
489 | |||
490 | /* | ||
491 | => base64 = *(4base64-char) [base64-terminal] | ||
492 | */ | ||
493 | |||
494 | static int mailimap_base64_send(mailstream * fd, const char * base64) | ||
495 | { | ||
496 | return mailimap_token_send(fd, base64); | ||
497 | } | ||
498 | |||
499 | /* | ||
500 | => base64-char = ALPHA / DIGIT / "+" / "/" | ||
501 | ; Case-sensitive | ||
502 | |||
503 | base64-terminal = (2base64-char "==") / (3base64-char "=") | ||
504 | |||
505 | body = "(" (body-type-1part / body-type-mpart) ")" | ||
506 | |||
507 | body-extension = nstring / number / | ||
508 | "(" body-extension *(SP body-extension) ")" | ||
509 | ; Future expansion. Client implementations | ||
510 | ; MUST accept body-extension fields. Server | ||
511 | ; implementations MUST NOT generate | ||
512 | ; body-extension fields except as defined by | ||
513 | ; future standard or standards-track | ||
514 | ; revisions of this specification. | ||
515 | |||
516 | body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang | ||
517 | *(SP body-extension)]] | ||
518 | ; MUST NOT be returned on non-extensible | ||
519 | ; "BODY" fetch | ||
520 | |||
521 | body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang | ||
522 | *(SP body-extension)]] | ||
523 | ; MUST NOT be returned on non-extensible | ||
524 | ; "BODY" fetch | ||
525 | |||
526 | body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP | ||
527 | body-fld-enc SP body-fld-octets | ||
528 | |||
529 | body-fld-desc = nstring | ||
530 | |||
531 | body-fld-dsp = "(" string SP body-fld-param ")" / nil | ||
532 | |||
533 | body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ | ||
534 | "QUOTED-PRINTABLE") DQUOTE) / string | ||
535 | |||
536 | body-fld-id = nstring | ||
537 | |||
538 | body-fld-lang = nstring / "(" string *(SP string) ")" | ||
539 | |||
540 | body-fld-lines = number | ||
541 | |||
542 | body-fld-md5 = nstring | ||
543 | |||
544 | body-fld-octets = number | ||
545 | |||
546 | body-fld-param = "(" string SP string *(SP string SP string) ")" / nil | ||
547 | |||
548 | body-type-1part = (body-type-basic / body-type-msg / body-type-text) | ||
549 | [SP body-ext-1part] | ||
550 | |||
551 | body-type-basic = media-basic SP body-fields | ||
552 | ; MESSAGE subtype MUST NOT be "RFC822" | ||
553 | |||
554 | body-type-mpart = 1*body SP media-subtype | ||
555 | [SP body-ext-mpart] | ||
556 | |||
557 | body-type-msg = media-message SP body-fields SP envelope | ||
558 | SP body SP body-fld-lines | ||
559 | |||
560 | body-type-text = media-text SP body-fields SP body-fld-lines | ||
561 | |||
562 | capability = ("AUTH=" auth-type) / atom | ||
563 | ; New capabilities MUST begin with "X" or be | ||
564 | ; registered with IANA as standard or | ||
565 | ; standards-track | ||
566 | |||
567 | capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1" | ||
568 | *(SP capability) | ||
569 | ; IMAP4rev1 servers which offer RFC 1730 | ||
570 | ; compatibility MUST list "IMAP4" as the first | ||
571 | ; capability. | ||
572 | |||
573 | CHAR8 = %x01-ff | ||
574 | ; any OCTET except NUL, %x00 | ||
575 | */ | ||
576 | |||
577 | /* | ||
578 | => command = tag SP (command-any / command-auth / command-nonauth / | ||
579 | command-select) CRLF | ||
580 | ; Modal based on state | ||
581 | */ | ||
582 | |||
583 | /* | ||
584 | => command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command | ||
585 | ; Valid in all states | ||
586 | */ | ||
587 | |||
588 | int mailimap_capability_send(mailstream * fd) | ||
589 | { | ||
590 | int r; | ||
591 | |||
592 | r = mailimap_token_send(fd, "CAPABILITY"); | ||
593 | if (r != MAILIMAP_NO_ERROR) | ||
594 | return r; | ||
595 | |||
596 | return MAILIMAP_NO_ERROR; | ||
597 | } | ||
598 | |||
599 | int mailimap_logout_send(mailstream * fd) | ||
600 | { | ||
601 | int r; | ||
602 | |||
603 | r = mailimap_token_send(fd, "LOGOUT"); | ||
604 | if (r != MAILIMAP_NO_ERROR) | ||
605 | return r; | ||
606 | |||
607 | return MAILIMAP_NO_ERROR; | ||
608 | } | ||
609 | |||
610 | int mailimap_noop_send(mailstream * fd) | ||
611 | { | ||
612 | int r; | ||
613 | |||
614 | r = mailimap_token_send(fd, "NOOP"); | ||
615 | if (r != MAILIMAP_NO_ERROR) | ||
616 | return r; | ||
617 | |||
618 | return MAILIMAP_NO_ERROR; | ||
619 | } | ||
620 | |||
621 | /* | ||
622 | => command-auth = append / create / delete / examine / list / lsub / | ||
623 | rename / select / status / subscribe / unsubscribe | ||
624 | ; Valid only in Authenticated or Selected state | ||
625 | */ | ||
626 | |||
627 | /* | ||
628 | => command-nonauth = login / authenticate | ||
629 | ; Valid only when in Not Authenticated state | ||
630 | */ | ||
631 | |||
632 | /* | ||
633 | => command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store / | ||
634 | uid / search | ||
635 | ; Valid only when in Selected state | ||
636 | */ | ||
637 | |||
638 | int mailimap_check_send(mailstream * fd) | ||
639 | { | ||
640 | int r; | ||
641 | |||
642 | r = mailimap_token_send(fd, "CHECK"); | ||
643 | if (r != MAILIMAP_NO_ERROR) | ||
644 | return r; | ||
645 | |||
646 | return MAILIMAP_NO_ERROR; | ||
647 | } | ||
648 | |||
649 | int mailimap_close_send(mailstream * fd) | ||
650 | { | ||
651 | int r; | ||
652 | |||
653 | r = mailimap_token_send(fd, "CLOSE"); | ||
654 | if (r != MAILIMAP_NO_ERROR) | ||
655 | return r; | ||
656 | |||
657 | return MAILIMAP_NO_ERROR; | ||
658 | } | ||
659 | |||
660 | int mailimap_expunge_send(mailstream * fd) | ||
661 | { | ||
662 | int r; | ||
663 | |||
664 | r = mailimap_token_send(fd, "EXPUNGE"); | ||
665 | if (r != MAILIMAP_NO_ERROR) | ||
666 | return r; | ||
667 | |||
668 | return MAILIMAP_NO_ERROR; | ||
669 | } | ||
670 | |||
671 | /* | ||
672 | continue-req = "+" SP (resp-text / base64) CRLF | ||
673 | */ | ||
674 | |||
675 | /* | ||
676 | => copy = "COPY" SP set SP mailbox | ||
677 | */ | ||
678 | |||
679 | int mailimap_copy_send(mailstream * fd, | ||
680 | struct mailimap_set * set, | ||
681 | const char * mb) | ||
682 | { | ||
683 | int r; | ||
684 | |||
685 | r = mailimap_token_send(fd, "COPY"); | ||
686 | if (r != MAILIMAP_NO_ERROR) | ||
687 | return r; | ||
688 | |||
689 | r = mailimap_space_send(fd); | ||
690 | if (r != MAILIMAP_NO_ERROR) | ||
691 | return r; | ||
692 | |||
693 | r = mailimap_set_send(fd, set); | ||
694 | if (r != MAILIMAP_NO_ERROR) | ||
695 | return r; | ||
696 | |||
697 | r = mailimap_space_send(fd); | ||
698 | if (r != MAILIMAP_NO_ERROR) | ||
699 | return r; | ||
700 | |||
701 | r = mailimap_mailbox_send(fd, mb); | ||
702 | if (r != MAILIMAP_NO_ERROR) | ||
703 | return r; | ||
704 | |||
705 | return MAILIMAP_NO_ERROR; | ||
706 | } | ||
707 | |||
708 | int mailimap_uid_copy_send(mailstream * fd, | ||
709 | struct mailimap_set * set, | ||
710 | const char * mb) | ||
711 | { | ||
712 | int r; | ||
713 | |||
714 | r = mailimap_token_send(fd, "UID"); | ||
715 | if (r != MAILIMAP_NO_ERROR) | ||
716 | return r; | ||
717 | |||
718 | r = mailimap_space_send(fd); | ||
719 | if (r != MAILIMAP_NO_ERROR) | ||
720 | return r; | ||
721 | |||
722 | return mailimap_copy_send(fd, set, mb); | ||
723 | } | ||
724 | |||
725 | /* | ||
726 | => create = "CREATE" SP mailbox | ||
727 | ; Use of INBOX gives a NO error | ||
728 | */ | ||
729 | |||
730 | int mailimap_create_send(mailstream * fd, | ||
731 | const char * mb) | ||
732 | { | ||
733 | int r; | ||
734 | |||
735 | r = mailimap_token_send(fd, "CREATE"); | ||
736 | if (r != MAILIMAP_NO_ERROR) | ||
737 | return r; | ||
738 | |||
739 | r = mailimap_space_send(fd); | ||
740 | if (r != MAILIMAP_NO_ERROR) | ||
741 | return r; | ||
742 | |||
743 | r = mailimap_mailbox_send(fd, mb); | ||
744 | if (r != MAILIMAP_NO_ERROR) | ||
745 | return r; | ||
746 | |||
747 | return MAILIMAP_NO_ERROR; | ||
748 | } | ||
749 | |||
750 | /* | ||
751 | => date = date-text / DQUOTE date-text DQUOTE | ||
752 | */ | ||
753 | |||
754 | static int mailimap_date_send(mailstream * fd, | ||
755 | struct mailimap_date * date) | ||
756 | { | ||
757 | int r; | ||
758 | |||
759 | r = mailimap_date_day_send(fd, date->dt_day); | ||
760 | if (r != MAILIMAP_NO_ERROR) | ||
761 | return r; | ||
762 | |||
763 | r = mailimap_char_send(fd, '-'); | ||
764 | if (r != MAILIMAP_NO_ERROR) | ||
765 | return r; | ||
766 | |||
767 | r = mailimap_date_month_send(fd, date->dt_month); | ||
768 | if (r != MAILIMAP_NO_ERROR) | ||
769 | return r; | ||
770 | |||
771 | r = mailimap_char_send(fd, '-'); | ||
772 | if (r != MAILIMAP_NO_ERROR) | ||
773 | return r; | ||
774 | |||
775 | r = mailimap_date_year_send(fd, date->dt_year); | ||
776 | if (r != MAILIMAP_NO_ERROR) | ||
777 | return r; | ||
778 | |||
779 | return MAILIMAP_NO_ERROR; | ||
780 | } | ||
781 | |||
782 | /* | ||
783 | => date-day = 1*2DIGIT | ||
784 | ; Day of month | ||
785 | */ | ||
786 | |||
787 | static int mailimap_date_day_send(mailstream * fd, int day) | ||
788 | { | ||
789 | return mailimap_number_send(fd, day); | ||
790 | } | ||
791 | |||
792 | /* | ||
793 | => date-day-fixed = (SP DIGIT) / 2DIGIT | ||
794 | ; Fixed-format version of date-day | ||
795 | */ | ||
796 | |||
797 | static int mailimap_date_day_fixed_send(mailstream * fd, int day) | ||
798 | { | ||
799 | int r; | ||
800 | |||
801 | if (day < 10) { | ||
802 | r = mailimap_space_send(fd); | ||
803 | if (r != MAILIMAP_NO_ERROR) | ||
804 | return r; | ||
805 | |||
806 | r = mailimap_number_send(fd, day); | ||
807 | if (r != MAILIMAP_NO_ERROR) | ||
808 | return r; | ||
809 | |||
810 | return MAILIMAP_NO_ERROR; | ||
811 | } | ||
812 | else | ||
813 | return mailimap_number_send(fd, day); | ||
814 | } | ||
815 | |||
816 | /* | ||
817 | => date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / | ||
818 | "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" | ||
819 | */ | ||
820 | |||
821 | static int mailimap_date_month_send(mailstream * fd, int month) | ||
822 | { | ||
823 | const char * name; | ||
824 | int r; | ||
825 | |||
826 | name = mailimap_month_get_token_str(month); | ||
827 | |||
828 | if (name == NULL) | ||
829 | return MAILIMAP_ERROR_INVAL; | ||
830 | |||
831 | r = mailimap_token_send(fd, name); | ||
832 | if (r != MAILIMAP_NO_ERROR) | ||
833 | return r; | ||
834 | |||
835 | return MAILIMAP_NO_ERROR; | ||
836 | } | ||
837 | |||
838 | /* | ||
839 | => date-text = date-day "-" date-month "-" date-year | ||
840 | */ | ||
841 | |||
842 | /* | ||
843 | static gboolean mailimap_date_text_send(mailstream * fd, | ||
844 | struct mailimap_date_text * date_text) | ||
845 | { | ||
846 | if (!mailimap_date_day_send(fd, date_text->day)) | ||
847 | return FALSE; | ||
848 | if (!mailimap_char_send(fd, '-')) | ||
849 | return FALSE; | ||
850 | if (!mailimap_date_month_send(fd, date_text->month)) | ||
851 | return FALSE; | ||
852 | if (!mailimap_char_send(fd, '-')) | ||
853 | return FALSE; | ||
854 | if (!mailimap_date_year_send(fd, date_text->year)) | ||
855 | return FALSE; | ||
856 | |||
857 | return TRUE; | ||
858 | } | ||
859 | */ | ||
860 | |||
861 | /* | ||
862 | => date-year = 4DIGIT | ||
863 | */ | ||
864 | |||
865 | static int mailimap_fixed_digit_send(mailstream * fd, | ||
866 | int num, int count) | ||
867 | { | ||
868 | int r; | ||
869 | |||
870 | r = mailimap_fixed_digit_send(fd, num / 10, count); | ||
871 | if (r != MAILIMAP_NO_ERROR) | ||
872 | return r; | ||
873 | |||
874 | r = mailimap_digit_send(fd, num % 10); | ||
875 | if (r != MAILIMAP_NO_ERROR) | ||
876 | return r; | ||
877 | |||
878 | return MAILIMAP_NO_ERROR; | ||
879 | } | ||
880 | |||
881 | static int mailimap_date_year_send(mailstream *fd, int year) | ||
882 | { | ||
883 | int r; | ||
884 | |||
885 | r = mailimap_fixed_digit_send(fd, year, 4); | ||
886 | if (r != MAILIMAP_NO_ERROR) | ||
887 | return r; | ||
888 | |||
889 | return MAILIMAP_NO_ERROR; | ||
890 | } | ||
891 | |||
892 | /* | ||
893 | => date-time = DQUOTE date-day-fixed "-" date-month "-" date-year | ||
894 | SP time SP zone DQUOTE | ||
895 | */ | ||
896 | |||
897 | static int | ||
898 | mailimap_date_time_send(mailstream * fd, | ||
899 | struct mailimap_date_time * date_time) | ||
900 | { | ||
901 | int r; | ||
902 | |||
903 | r = mailimap_date_day_fixed_send(fd, date_time->dt_day); | ||
904 | if (r != MAILIMAP_NO_ERROR) | ||
905 | return r; | ||
906 | |||
907 | r = mailimap_char_send(fd, '-'); | ||
908 | if (r != MAILIMAP_NO_ERROR) | ||
909 | return r; | ||
910 | |||
911 | r = mailimap_date_month_send(fd, date_time->dt_month); | ||
912 | if (r != MAILIMAP_NO_ERROR) | ||
913 | return r; | ||
914 | |||
915 | r = mailimap_char_send(fd, '-'); | ||
916 | if (r != MAILIMAP_NO_ERROR) | ||
917 | return r; | ||
918 | |||
919 | r = mailimap_date_year_send(fd, date_time->dt_month); | ||
920 | if (r != MAILIMAP_NO_ERROR) | ||
921 | return r; | ||
922 | |||
923 | r = mailimap_space_send(fd); | ||
924 | if (r != MAILIMAP_NO_ERROR) | ||
925 | return r; | ||
926 | |||
927 | r = mailimap_fixed_digit_send(fd, date_time->dt_hour, 2); | ||
928 | if (r != MAILIMAP_NO_ERROR) | ||
929 | return r; | ||
930 | |||
931 | r = mailimap_char_send(fd, ':'); | ||
932 | if (r != MAILIMAP_NO_ERROR) | ||
933 | return r; | ||
934 | |||
935 | r = mailimap_fixed_digit_send(fd, date_time->dt_min, 2); | ||
936 | if (r != MAILIMAP_NO_ERROR) | ||
937 | return r; | ||
938 | |||
939 | r = mailimap_char_send(fd, ':'); | ||
940 | if (r != MAILIMAP_NO_ERROR) | ||
941 | return r; | ||
942 | |||
943 | r = mailimap_fixed_digit_send(fd, date_time->dt_sec, 2); | ||
944 | if (r != MAILIMAP_NO_ERROR) | ||
945 | return r; | ||
946 | |||
947 | return MAILIMAP_NO_ERROR; | ||
948 | } | ||
949 | |||
950 | /* | ||
951 | => delete = "DELETE" SP mailbox | ||
952 | ; Use of INBOX gives a NO error | ||
953 | */ | ||
954 | |||
955 | int mailimap_delete_send(mailstream * fd, const char * mb) | ||
956 | { | ||
957 | int r; | ||
958 | |||
959 | r = mailimap_token_send(fd, "DELETE"); | ||
960 | if (r != MAILIMAP_NO_ERROR) | ||
961 | return r; | ||
962 | |||
963 | r = mailimap_space_send(fd); | ||
964 | if (r != MAILIMAP_NO_ERROR) | ||
965 | return r; | ||
966 | |||
967 | r = mailimap_mailbox_send(fd, mb); | ||
968 | if (r != MAILIMAP_NO_ERROR) | ||
969 | return r; | ||
970 | |||
971 | return MAILIMAP_NO_ERROR; | ||
972 | } | ||
973 | |||
974 | /* | ||
975 | |||
976 | digit | ||
977 | |||
978 | digit-nz = %x31-39 | ||
979 | ; 1-9 | ||
980 | */ | ||
981 | |||
982 | static int mailimap_digit_send(mailstream * fd, int digit) | ||
983 | { | ||
984 | return mailimap_char_send(fd, digit + '0'); | ||
985 | } | ||
986 | |||
987 | |||
988 | /* | ||
989 | envelope = "(" env-date SP env-subject SP env-from SP env-sender SP | ||
990 | env-reply-to SP env-to SP env-cc SP env-bcc SP | ||
991 | env-in-reply-to SP env-message-id ")" | ||
992 | |||
993 | env-bcc = "(" 1*address ")" / nil | ||
994 | |||
995 | env-cc = "(" 1*address ")" / nil | ||
996 | |||
997 | env-date = nstring | ||
998 | |||
999 | env-from = "(" 1*address ")" / nil | ||
1000 | |||
1001 | env-in-reply-to = nstring | ||
1002 | |||
1003 | env-message-id = nstring | ||
1004 | |||
1005 | env-reply-to = "(" 1*address ")" / nil | ||
1006 | |||
1007 | env-sender = "(" 1*address ")" / nil | ||
1008 | |||
1009 | env-subject = nstring | ||
1010 | |||
1011 | env-to = "(" 1*address ")" / nil | ||
1012 | */ | ||
1013 | |||
1014 | /* | ||
1015 | => examine = "EXAMINE" SP mailbox | ||
1016 | */ | ||
1017 | |||
1018 | int mailimap_examine_send(mailstream * fd, const char * mb) | ||
1019 | { | ||
1020 | int r; | ||
1021 | |||
1022 | r = mailimap_token_send(fd, "EXAMINE"); | ||
1023 | if (r != MAILIMAP_NO_ERROR) | ||
1024 | return r; | ||
1025 | |||
1026 | r = mailimap_space_send(fd); | ||
1027 | if (r != MAILIMAP_NO_ERROR) | ||
1028 | return r; | ||
1029 | |||
1030 | r = mailimap_mailbox_send(fd, mb); | ||
1031 | if (r != MAILIMAP_NO_ERROR) | ||
1032 | return r; | ||
1033 | |||
1034 | return MAILIMAP_NO_ERROR; | ||
1035 | } | ||
1036 | |||
1037 | /* | ||
1038 | => fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att / | ||
1039 | "(" fetch-att *(SP fetch-att) ")") | ||
1040 | */ | ||
1041 | |||
1042 | static int | ||
1043 | mailimap_fetch_att_list_send(mailstream * fd, clist * fetch_att_list); | ||
1044 | |||
1045 | static int | ||
1046 | mailimap_fetch_type_send(mailstream * fd, | ||
1047 | struct mailimap_fetch_type * fetch_type) | ||
1048 | { | ||
1049 | switch (fetch_type->ft_type) { | ||
1050 | case MAILIMAP_FETCH_TYPE_ALL: | ||
1051 | return mailimap_token_send(fd, "ALL"); | ||
1052 | case MAILIMAP_FETCH_TYPE_FULL: | ||
1053 | return mailimap_token_send(fd, "FULL"); | ||
1054 | case MAILIMAP_FETCH_TYPE_FAST: | ||
1055 | return mailimap_token_send(fd, "FAST"); | ||
1056 | case MAILIMAP_FETCH_TYPE_FETCH_ATT: | ||
1057 | return mailimap_fetch_att_send(fd, fetch_type->ft_data.ft_fetch_att); | ||
1058 | case MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST: | ||
1059 | return mailimap_fetch_att_list_send(fd, | ||
1060 | fetch_type->ft_data.ft_fetch_att_list); | ||
1061 | default: | ||
1062 | /* should not happen */ | ||
1063 | return MAILIMAP_ERROR_INVAL; | ||
1064 | } | ||
1065 | } | ||
1066 | |||
1067 | int mailimap_fetch_send(mailstream * fd, | ||
1068 | struct mailimap_set * set, | ||
1069 | struct mailimap_fetch_type * fetch_type) | ||
1070 | { | ||
1071 | int r; | ||
1072 | |||
1073 | r = mailimap_token_send(fd, "FETCH"); | ||
1074 | if (r != MAILIMAP_NO_ERROR) | ||
1075 | return r; | ||
1076 | |||
1077 | r = mailimap_space_send(fd); | ||
1078 | if (r != MAILIMAP_NO_ERROR) | ||
1079 | return r; | ||
1080 | |||
1081 | r = mailimap_set_send(fd, set); | ||
1082 | if (r != MAILIMAP_NO_ERROR) | ||
1083 | return r; | ||
1084 | |||
1085 | r = mailimap_space_send(fd); | ||
1086 | if (r != MAILIMAP_NO_ERROR) | ||
1087 | return r; | ||
1088 | |||
1089 | r = mailimap_fetch_type_send(fd, fetch_type); | ||
1090 | if (r != MAILIMAP_NO_ERROR) | ||
1091 | return r; | ||
1092 | |||
1093 | return MAILIMAP_NO_ERROR; | ||
1094 | } | ||
1095 | |||
1096 | int | ||
1097 | mailimap_uid_fetch_send(mailstream * fd, | ||
1098 | struct mailimap_set * set, | ||
1099 | struct mailimap_fetch_type * fetch_type) | ||
1100 | { | ||
1101 | int r; | ||
1102 | |||
1103 | r = mailimap_token_send(fd, "UID"); | ||
1104 | if (r != MAILIMAP_NO_ERROR) | ||
1105 | return r; | ||
1106 | |||
1107 | r = mailimap_space_send(fd); | ||
1108 | if (r != MAILIMAP_NO_ERROR) | ||
1109 | return r; | ||
1110 | |||
1111 | return mailimap_fetch_send(fd, set, fetch_type); | ||
1112 | } | ||
1113 | |||
1114 | /* currently porting */ | ||
1115 | |||
1116 | static int | ||
1117 | mailimap_fetch_att_list_send(mailstream * fd, clist * fetch_att_list) | ||
1118 | { | ||
1119 | int r; | ||
1120 | |||
1121 | r = mailimap_oparenth_send(fd); | ||
1122 | if (r != MAILIMAP_NO_ERROR) | ||
1123 | return r; | ||
1124 | |||
1125 | r = mailimap_struct_spaced_list_send(fd, fetch_att_list, | ||
1126 | (mailimap_struct_sender *) | ||
1127 | mailimap_fetch_att_send); | ||
1128 | if (r != MAILIMAP_NO_ERROR) | ||
1129 | return r; | ||
1130 | |||
1131 | r = mailimap_cparenth_send(fd); | ||
1132 | if (r != MAILIMAP_NO_ERROR) | ||
1133 | return r; | ||
1134 | |||
1135 | return MAILIMAP_NO_ERROR; | ||
1136 | } | ||
1137 | |||
1138 | /* | ||
1139 | => fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" / | ||
1140 | "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] / | ||
1141 | "BODY" ["STRUCTURE"] / "UID" / | ||
1142 | "BODY" [".PEEK"] section ["<" number "." nz-number ">"] | ||
1143 | */ | ||
1144 | |||
1145 | static int mailimap_fetch_att_send(mailstream * fd, | ||
1146 | struct mailimap_fetch_att * fetch_att) | ||
1147 | { | ||
1148 | int r; | ||
1149 | |||
1150 | switch(fetch_att->att_type) { | ||
1151 | case MAILIMAP_FETCH_ATT_ENVELOPE: | ||
1152 | return mailimap_token_send(fd, "ENVELOPE"); | ||
1153 | |||
1154 | case MAILIMAP_FETCH_ATT_FLAGS: | ||
1155 | return mailimap_token_send(fd, "FLAGS"); | ||
1156 | |||
1157 | case MAILIMAP_FETCH_ATT_INTERNALDATE: | ||
1158 | return mailimap_token_send(fd, "INTERNALDATE"); | ||
1159 | |||
1160 | case MAILIMAP_FETCH_ATT_RFC822: | ||
1161 | return mailimap_token_send(fd, "RFC822"); | ||
1162 | |||
1163 | case MAILIMAP_FETCH_ATT_RFC822_HEADER: | ||
1164 | return mailimap_token_send(fd, "RFC822.HEADER"); | ||
1165 | |||
1166 | case MAILIMAP_FETCH_ATT_RFC822_SIZE: | ||
1167 | return mailimap_token_send(fd, "RFC822.SIZE"); | ||
1168 | |||
1169 | case MAILIMAP_FETCH_ATT_RFC822_TEXT: | ||
1170 | return mailimap_token_send(fd, "RFC822.TEXT"); | ||
1171 | |||
1172 | case MAILIMAP_FETCH_ATT_BODY: | ||
1173 | return mailimap_token_send(fd, "BODY"); | ||
1174 | |||
1175 | case MAILIMAP_FETCH_ATT_BODYSTRUCTURE: | ||
1176 | return mailimap_token_send(fd, "BODYSTRUCTURE"); | ||
1177 | |||
1178 | case MAILIMAP_FETCH_ATT_UID: | ||
1179 | return mailimap_token_send(fd, "UID"); | ||
1180 | |||
1181 | case MAILIMAP_FETCH_ATT_BODY_SECTION: | ||
1182 | |||
1183 | r = mailimap_token_send(fd, "BODY"); | ||
1184 | if (r != MAILIMAP_NO_ERROR) | ||
1185 | return r; | ||
1186 | r = mailimap_section_send(fd, fetch_att->att_section); | ||
1187 | if (r != MAILIMAP_NO_ERROR) | ||
1188 | return r; | ||
1189 | if (fetch_att->att_size != 0) { | ||
1190 | r = mailimap_char_send(fd, '<'); | ||
1191 | if (r != MAILIMAP_NO_ERROR) | ||
1192 | return r; | ||
1193 | r = mailimap_number_send(fd, fetch_att->att_offset); | ||
1194 | if (r != MAILIMAP_NO_ERROR) | ||
1195 | return r; | ||
1196 | r = mailimap_char_send(fd, '.'); | ||
1197 | if (r != MAILIMAP_NO_ERROR) | ||
1198 | return r; | ||
1199 | r = mailimap_number_send(fd, fetch_att->att_size); | ||
1200 | if (r != MAILIMAP_NO_ERROR) | ||
1201 | return r; | ||
1202 | r = mailimap_char_send(fd, '>'); | ||
1203 | if (r != MAILIMAP_NO_ERROR) | ||
1204 | return r; | ||
1205 | } | ||
1206 | |||
1207 | return MAILIMAP_NO_ERROR; | ||
1208 | |||
1209 | case MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION: | ||
1210 | r = mailimap_token_send(fd, "BODY.PEEK"); | ||
1211 | if (r != MAILIMAP_NO_ERROR) | ||
1212 | return r; | ||
1213 | r = mailimap_section_send(fd, fetch_att->att_section); | ||
1214 | if (r != MAILIMAP_NO_ERROR) | ||
1215 | return r; | ||
1216 | if (fetch_att->att_size != 0) { | ||
1217 | r = mailimap_char_send(fd, '<'); | ||
1218 | if (r != MAILIMAP_NO_ERROR) | ||
1219 | return r; | ||
1220 | r = mailimap_number_send(fd, fetch_att->att_offset); | ||
1221 | if (r != MAILIMAP_NO_ERROR) | ||
1222 | return r; | ||
1223 | r = mailimap_char_send(fd, '.'); | ||
1224 | if (r != MAILIMAP_NO_ERROR) | ||
1225 | return r; | ||
1226 | r = mailimap_number_send(fd, fetch_att->att_size); | ||
1227 | if (r != MAILIMAP_NO_ERROR) | ||
1228 | return r; | ||
1229 | r = mailimap_char_send(fd, '>'); | ||
1230 | if (r != MAILIMAP_NO_ERROR) | ||
1231 | return r; | ||
1232 | } | ||
1233 | return MAILIMAP_NO_ERROR; | ||
1234 | |||
1235 | default: | ||
1236 | /* should not happen */ | ||
1237 | return MAILIMAP_ERROR_INVAL; | ||
1238 | } | ||
1239 | } | ||
1240 | |||
1241 | /* | ||
1242 | => flag = "\Answered" / "\Flagged" / "\Deleted" / | ||
1243 | "\Seen" / "\Draft" / flag-keyword / flag-extension | ||
1244 | ; Does not include "\Recent" | ||
1245 | */ | ||
1246 | |||
1247 | /* | ||
1248 | enum { | ||
1249 | FLAG_ANSWERED, | ||
1250 | FLAG_FLAGGED, | ||
1251 | FLAG_DELETED, | ||
1252 | FLAG_SEEN, | ||
1253 | FLAG_DRAFT, | ||
1254 | FLAG_KEYWORD, | ||
1255 | FLAG_EXTENSION | ||
1256 | }; | ||
1257 | |||
1258 | struct mailimap_flag { | ||
1259 | gint type; | ||
1260 | gchar * flag_keyword; | ||
1261 | gchar * flag_extension; | ||
1262 | }; | ||
1263 | */ | ||
1264 | |||
1265 | static int mailimap_flag_send(mailstream * fd, | ||
1266 | struct mailimap_flag * flag) | ||
1267 | { | ||
1268 | switch(flag->fl_type) { | ||
1269 | case MAILIMAP_FLAG_ANSWERED: | ||
1270 | return mailimap_token_send(fd, "\\Answered"); | ||
1271 | case MAILIMAP_FLAG_FLAGGED: | ||
1272 | return mailimap_token_send(fd, "\\Flagged"); | ||
1273 | case MAILIMAP_FLAG_DELETED: | ||
1274 | return mailimap_token_send(fd, "\\Deleted"); | ||
1275 | case MAILIMAP_FLAG_SEEN: | ||
1276 | return mailimap_token_send(fd, "\\Seen"); | ||
1277 | case MAILIMAP_FLAG_DRAFT: | ||
1278 | return mailimap_token_send(fd, "\\Draft"); | ||
1279 | case MAILIMAP_FLAG_KEYWORD: | ||
1280 | return mailimap_flag_keyword_send(fd, flag->fl_data.fl_keyword); | ||
1281 | case MAILIMAP_FLAG_EXTENSION: | ||
1282 | return mailimap_flag_extension_send(fd, flag->fl_data.fl_extension); | ||
1283 | default: | ||
1284 | /* should not happen */ | ||
1285 | return MAILIMAP_ERROR_INVAL; | ||
1286 | } | ||
1287 | } | ||
1288 | |||
1289 | |||
1290 | /* | ||
1291 | => flag-extension = "\" atom | ||
1292 | ; Future expansion. Client implementations | ||
1293 | ; MUST accept flag-extension flags. Server | ||
1294 | ; implementations MUST NOT generate | ||
1295 | ; flag-extension flags except as defined by | ||
1296 | ; future standard or standards-track | ||
1297 | ; revisions of this specification. | ||
1298 | */ | ||
1299 | |||
1300 | static int mailimap_flag_extension_send(mailstream * fd, | ||
1301 | const char * flag_extension) | ||
1302 | { | ||
1303 | int r; | ||
1304 | |||
1305 | r = mailimap_char_send(fd, '\\'); | ||
1306 | if (r != MAILIMAP_NO_ERROR) | ||
1307 | return r; | ||
1308 | |||
1309 | r = mailimap_atom_send(fd, flag_extension); | ||
1310 | if (r != MAILIMAP_NO_ERROR) | ||
1311 | return r; | ||
1312 | |||
1313 | return MAILIMAP_NO_ERROR; | ||
1314 | } | ||
1315 | |||
1316 | /* | ||
1317 | flag-fetch = flag / "\Recent" | ||
1318 | */ | ||
1319 | |||
1320 | /* | ||
1321 | => flag-keyword = atom | ||
1322 | */ | ||
1323 | |||
1324 | static int mailimap_flag_keyword_send(mailstream * fd, | ||
1325 | const char * flag_keyword) | ||
1326 | { | ||
1327 | return mailimap_token_send(fd, flag_keyword); | ||
1328 | } | ||
1329 | |||
1330 | /* | ||
1331 | => flag-list = "(" [flag *(SP flag)] ")" | ||
1332 | */ | ||
1333 | |||
1334 | static int mailimap_flag_list_send(mailstream * fd, | ||
1335 | struct mailimap_flag_list * flag_list) | ||
1336 | { | ||
1337 | int r; | ||
1338 | |||
1339 | r = mailimap_oparenth_send(fd); | ||
1340 | if (r != MAILIMAP_NO_ERROR) | ||
1341 | return r; | ||
1342 | |||
1343 | if (flag_list->fl_list != NULL) { | ||
1344 | r = mailimap_struct_spaced_list_send(fd, flag_list->fl_list, | ||
1345 | (mailimap_struct_sender *) mailimap_flag_send); | ||
1346 | if (r != MAILIMAP_NO_ERROR) | ||
1347 | return r; | ||
1348 | } | ||
1349 | |||
1350 | r = mailimap_cparenth_send(fd); | ||
1351 | if (r != MAILIMAP_NO_ERROR) | ||
1352 | return r; | ||
1353 | |||
1354 | return MAILIMAP_NO_ERROR; | ||
1355 | } | ||
1356 | |||
1357 | /* | ||
1358 | flag-perm = flag / "\*" | ||
1359 | |||
1360 | greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF | ||
1361 | */ | ||
1362 | |||
1363 | /* | ||
1364 | => header-fld-name = astring | ||
1365 | */ | ||
1366 | |||
1367 | static int mailimap_header_fld_name_send(mailstream * fd, const char * header) | ||
1368 | { | ||
1369 | return mailimap_astring_send(fd, header); | ||
1370 | } | ||
1371 | |||
1372 | /* | ||
1373 | => header-list = "(" header-fld-name *(SP header-fld-name) ")" | ||
1374 | */ | ||
1375 | |||
1376 | static int | ||
1377 | mailimap_header_list_send(mailstream * fd, | ||
1378 | struct mailimap_header_list * header_list) | ||
1379 | { | ||
1380 | int r; | ||
1381 | |||
1382 | r = mailimap_oparenth_send(fd); | ||
1383 | if (r != MAILIMAP_NO_ERROR) | ||
1384 | return r; | ||
1385 | |||
1386 | r = mailimap_struct_spaced_list_send(fd, header_list->hdr_list, | ||
1387 | (mailimap_struct_sender *) mailimap_header_fld_name_send); | ||
1388 | if (r != MAILIMAP_NO_ERROR) | ||
1389 | return r; | ||
1390 | |||
1391 | r = mailimap_cparenth_send(fd); | ||
1392 | if (r != MAILIMAP_NO_ERROR) | ||
1393 | return r; | ||
1394 | |||
1395 | return MAILIMAP_NO_ERROR; | ||
1396 | } | ||
1397 | |||
1398 | /* | ||
1399 | => list = "LIST" SP mailbox SP list-mailbox | ||
1400 | */ | ||
1401 | |||
1402 | int mailimap_list_send(mailstream * fd, | ||
1403 | const char * mb, | ||
1404 | const char * list_mb) | ||
1405 | { | ||
1406 | int r; | ||
1407 | |||
1408 | r = mailimap_token_send(fd, "LIST"); | ||
1409 | if (r != MAILIMAP_NO_ERROR) | ||
1410 | return r; | ||
1411 | |||
1412 | r = mailimap_space_send(fd); | ||
1413 | if (r != MAILIMAP_NO_ERROR) | ||
1414 | return r; | ||
1415 | |||
1416 | r = mailimap_mailbox_send(fd, mb); | ||
1417 | if (r != MAILIMAP_NO_ERROR) | ||
1418 | return r; | ||
1419 | |||
1420 | r = mailimap_space_send(fd); | ||
1421 | if (r != MAILIMAP_NO_ERROR) | ||
1422 | return r; | ||
1423 | |||
1424 | r = mailimap_list_mailbox_send(fd, list_mb); | ||
1425 | if (r != MAILIMAP_NO_ERROR) | ||
1426 | return r; | ||
1427 | |||
1428 | return MAILIMAP_NO_ERROR; | ||
1429 | } | ||
1430 | |||
1431 | /* | ||
1432 | => list-mailbox = 1*list-char / string | ||
1433 | */ | ||
1434 | |||
1435 | static int | ||
1436 | mailimap_list_mailbox_send(mailstream * fd, const char * pattern) | ||
1437 | { | ||
1438 | return mailimap_quoted_send(fd, pattern); | ||
1439 | } | ||
1440 | |||
1441 | /* | ||
1442 | list-char = ATOM-CHAR / list-wildcards / resp-specials | ||
1443 | |||
1444 | list-wildcards = "%" / "*" | ||
1445 | */ | ||
1446 | |||
1447 | /* | ||
1448 | => literal = "{" number "}" CRLF *CHAR8 | ||
1449 | ; Number represents the number of CHAR8s | ||
1450 | */ | ||
1451 | |||
1452 | int | ||
1453 | mailimap_literal_send(mailstream * fd, const char * literal, | ||
1454 | size_t progr_rate, | ||
1455 | progress_function * progr_fun) | ||
1456 | { | ||
1457 | uint32_t len; | ||
1458 | int r; | ||
1459 | |||
1460 | len = strlen(literal); | ||
1461 | |||
1462 | r = mailimap_literal_count_send(fd, len); | ||
1463 | if (r != MAILIMAP_NO_ERROR) | ||
1464 | return r; | ||
1465 | r = mailimap_literal_data_send(fd, literal, len, progr_rate, progr_fun); | ||
1466 | if (r != MAILIMAP_NO_ERROR) | ||
1467 | return r; | ||
1468 | |||
1469 | return MAILIMAP_NO_ERROR; | ||
1470 | } | ||
1471 | |||
1472 | /* | ||
1473 | "{" number "}" CRLF | ||
1474 | */ | ||
1475 | |||
1476 | int | ||
1477 | mailimap_literal_count_send(mailstream * fd, uint32_t count) | ||
1478 | { | ||
1479 | int r; | ||
1480 | |||
1481 | r = mailimap_char_send(fd, '{'); | ||
1482 | if (r != MAILIMAP_NO_ERROR) | ||
1483 | return r; | ||
1484 | |||
1485 | r = mailimap_number_send(fd, count); | ||
1486 | if (r != MAILIMAP_NO_ERROR) | ||
1487 | return r; | ||
1488 | |||
1489 | r = mailimap_char_send(fd, '}'); | ||
1490 | if (r != MAILIMAP_NO_ERROR) | ||
1491 | return r; | ||
1492 | |||
1493 | r = mailimap_crlf_send(fd); | ||
1494 | if (r != MAILIMAP_NO_ERROR) | ||
1495 | return r; | ||
1496 | |||
1497 | return MAILIMAP_NO_ERROR; | ||
1498 | } | ||
1499 | |||
1500 | /* | ||
1501 | *CHAR8 | ||
1502 | */ | ||
1503 | |||
1504 | int | ||
1505 | mailimap_literal_data_send(mailstream * fd, const char * literal, uint32_t len, | ||
1506 | size_t progr_rate, | ||
1507 | progress_function * progr_fun) | ||
1508 | { | ||
1509 | int r; | ||
1510 | |||
1511 | r = mailimap_sized_token_send(fd, literal, len); | ||
1512 | if (r != MAILIMAP_NO_ERROR) | ||
1513 | return r; | ||
1514 | |||
1515 | return MAILIMAP_NO_ERROR; | ||
1516 | } | ||
1517 | |||
1518 | |||
1519 | /* | ||
1520 | => login = "LOGIN" SP userid SP password | ||
1521 | */ | ||
1522 | |||
1523 | int mailimap_login_send(mailstream * fd, | ||
1524 | const char * userid, const char * password) | ||
1525 | { | ||
1526 | int r; | ||
1527 | |||
1528 | r = mailimap_token_send(fd, "LOGIN"); | ||
1529 | if (r != MAILIMAP_NO_ERROR) | ||
1530 | return r; | ||
1531 | |||
1532 | r = mailimap_space_send(fd); | ||
1533 | if (r != MAILIMAP_NO_ERROR) | ||
1534 | return r; | ||
1535 | |||
1536 | r = mailimap_userid_send(fd, userid); | ||
1537 | if (r != MAILIMAP_NO_ERROR) | ||
1538 | return r; | ||
1539 | |||
1540 | r = mailimap_space_send(fd); | ||
1541 | if (r != MAILIMAP_NO_ERROR) | ||
1542 | return r; | ||
1543 | |||
1544 | r = mailimap_password_send(fd, password); | ||
1545 | if (r != MAILIMAP_NO_ERROR) | ||
1546 | return r; | ||
1547 | |||
1548 | return MAILIMAP_NO_ERROR; | ||
1549 | } | ||
1550 | |||
1551 | /* | ||
1552 | => lsub = "LSUB" SP mailbox SP list-mailbox | ||
1553 | */ | ||
1554 | |||
1555 | int mailimap_lsub_send(mailstream * fd, | ||
1556 | const char * mb, const char * list_mb) | ||
1557 | { | ||
1558 | int r; | ||
1559 | |||
1560 | r = mailimap_token_send(fd, "LSUB"); | ||
1561 | if (r != MAILIMAP_NO_ERROR) | ||
1562 | return r; | ||
1563 | |||
1564 | r = mailimap_space_send(fd); | ||
1565 | if (r != MAILIMAP_NO_ERROR) | ||
1566 | return r; | ||
1567 | |||
1568 | r = mailimap_mailbox_send(fd, mb); | ||
1569 | if (r != MAILIMAP_NO_ERROR) | ||
1570 | return r; | ||
1571 | |||
1572 | r = mailimap_space_send(fd); | ||
1573 | if (r != MAILIMAP_NO_ERROR) | ||
1574 | return r; | ||
1575 | |||
1576 | r = mailimap_list_mailbox_send(fd, list_mb); | ||
1577 | if (r != MAILIMAP_NO_ERROR) | ||
1578 | return r; | ||
1579 | |||
1580 | return MAILIMAP_NO_ERROR; | ||
1581 | } | ||
1582 | |||
1583 | /* | ||
1584 | mailbox = "INBOX" / astring | ||
1585 | ; INBOX is case-insensitive. All case variants of | ||
1586 | ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX | ||
1587 | ; not as an astring. An astring which consists of | ||
1588 | ; the case-insensitive sequence "I" "N" "B" "O" "X" | ||
1589 | ; is considered to be INBOX and not an astring. | ||
1590 | ; Refer to section 5.1 for further | ||
1591 | ; semantic details of mailbox names. | ||
1592 | */ | ||
1593 | |||
1594 | static int mailimap_mailbox_send(mailstream * fd, const char * mb) | ||
1595 | { | ||
1596 | return mailimap_astring_send(fd, mb); | ||
1597 | } | ||
1598 | |||
1599 | /* | ||
1600 | mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list / | ||
1601 | "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) / | ||
1602 | "STATUS" SP mailbox SP "(" | ||
1603 | [status-att SP number *(SP status-att SP number)] ")" / | ||
1604 | number SP "EXISTS" / number SP "RECENT" | ||
1605 | |||
1606 | mailbox-list = "(" [mbx-list-flags] ")" SP | ||
1607 | (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox | ||
1608 | |||
1609 | mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag | ||
1610 | *(SP mbx-list-oflag) / | ||
1611 | mbx-list-oflag *(SP mbx-list-oflag) | ||
1612 | |||
1613 | mbx-list-oflag = "\Noinferiors" / flag-extension | ||
1614 | ; Other flags; multiple possible per LIST response | ||
1615 | |||
1616 | mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked" | ||
1617 | ; Selectability flags; only one per LIST response | ||
1618 | |||
1619 | media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / | ||
1620 | "VIDEO") DQUOTE) / string) SP media-subtype | ||
1621 | ; Defined in [MIME-IMT] | ||
1622 | |||
1623 | media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE | ||
1624 | ; Defined in [MIME-IMT] | ||
1625 | |||
1626 | media-subtype = string | ||
1627 | ; Defined in [MIME-IMT] | ||
1628 | |||
1629 | media-text = DQUOTE "TEXT" DQUOTE SP media-subtype | ||
1630 | ; Defined in [MIME-IMT] | ||
1631 | |||
1632 | message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att)) | ||
1633 | |||
1634 | msg-att = "(" (msg-att-dynamic / msg-att-static) | ||
1635 | *(SP (msg-att-dynamic / msg-att-static)) ")" | ||
1636 | |||
1637 | msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")" | ||
1638 | ; MAY change for a message | ||
1639 | |||
1640 | msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time / | ||
1641 | "RFC822" [".HEADER" / ".TEXT"] SP nstring / | ||
1642 | "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body / | ||
1643 | "BODY" section ["<" number ">"] SP nstring / | ||
1644 | "UID" SP uniqueid | ||
1645 | ; MUST NOT change for a message | ||
1646 | |||
1647 | nil = "NIL" | ||
1648 | |||
1649 | nstring = string / nil | ||
1650 | */ | ||
1651 | |||
1652 | /* | ||
1653 | => number = 1*DIGIT | ||
1654 | ; Unsigned 32-bit integer | ||
1655 | ; (0 <= n < 4,294,967,296) | ||
1656 | */ | ||
1657 | |||
1658 | /* | ||
1659 | nz-number = digit-nz *DIGIT | ||
1660 | ; Non-zero unsigned 32-bit integer | ||
1661 | ; (0 < n < 4,294,967,296) | ||
1662 | */ | ||
1663 | |||
1664 | static int mailimap_number_send(mailstream * fd, uint32_t number) | ||
1665 | { | ||
1666 | int r; | ||
1667 | |||
1668 | if (number / 10 != 0) { | ||
1669 | r = mailimap_number_send(fd, number / 10); | ||
1670 | if (r != MAILIMAP_NO_ERROR) | ||
1671 | return r; | ||
1672 | } | ||
1673 | |||
1674 | r = mailimap_digit_send(fd, number % 10); | ||
1675 | if (r != MAILIMAP_NO_ERROR) | ||
1676 | return r; | ||
1677 | |||
1678 | return MAILIMAP_NO_ERROR; | ||
1679 | } | ||
1680 | |||
1681 | /* | ||
1682 | => password = astring | ||
1683 | */ | ||
1684 | |||
1685 | static int mailimap_password_send(mailstream * fd, const char * pass) | ||
1686 | { | ||
1687 | return mailimap_astring_send(fd, pass); | ||
1688 | } | ||
1689 | |||
1690 | /* | ||
1691 | => quoted = DQUOTE *QUOTED-CHAR DQUOTE | ||
1692 | |||
1693 | => QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> / | ||
1694 | "\" quoted-specials | ||
1695 | |||
1696 | => quoted-specials = DQUOTE / "\" | ||
1697 | */ | ||
1698 | |||
1699 | static int is_quoted_specials(char ch) | ||
1700 | { | ||
1701 | return (ch == '\"') || (ch == '\\'); | ||
1702 | } | ||
1703 | |||
1704 | static int mailimap_quoted_char_send(mailstream * fd, char ch) | ||
1705 | { | ||
1706 | int r; | ||
1707 | |||
1708 | if (is_quoted_specials(ch)) { | ||
1709 | r = mailimap_char_send(fd, '\\'); | ||
1710 | if (r != MAILIMAP_NO_ERROR) | ||
1711 | return r; | ||
1712 | r = mailimap_char_send(fd, ch); | ||
1713 | if (r != MAILIMAP_NO_ERROR) | ||
1714 | return r; | ||
1715 | |||
1716 | return MAILIMAP_NO_ERROR; | ||
1717 | } | ||
1718 | else | ||
1719 | return mailimap_char_send(fd, ch); | ||
1720 | } | ||
1721 | |||
1722 | static int mailimap_quoted_send(mailstream * fd, const char * quoted) | ||
1723 | { | ||
1724 | const char * pos; | ||
1725 | int r; | ||
1726 | |||
1727 | pos = quoted; | ||
1728 | |||
1729 | r = mailimap_dquote_send(fd); | ||
1730 | if (r != MAILIMAP_NO_ERROR) | ||
1731 | return r; | ||
1732 | |||
1733 | while (* pos != 0) { | ||
1734 | r = mailimap_quoted_char_send(fd, * pos); | ||
1735 | if (r != MAILIMAP_NO_ERROR) | ||
1736 | return r; | ||
1737 | pos ++; | ||
1738 | } | ||
1739 | |||
1740 | r = mailimap_dquote_send(fd); | ||
1741 | if (r != MAILIMAP_NO_ERROR) | ||
1742 | return r; | ||
1743 | |||
1744 | return MAILIMAP_NO_ERROR; | ||
1745 | } | ||
1746 | |||
1747 | /* | ||
1748 | => rename = "RENAME" SP mailbox SP mailbox | ||
1749 | ; Use of INBOX as a destination gives a NO error | ||
1750 | */ | ||
1751 | |||
1752 | int mailimap_rename_send(mailstream * fd, const char * mb, | ||
1753 | const char * new_name) | ||
1754 | { | ||
1755 | int r; | ||
1756 | |||
1757 | r = mailimap_token_send(fd, "RENAME"); | ||
1758 | if (r != MAILIMAP_NO_ERROR) | ||
1759 | return r; | ||
1760 | r = mailimap_space_send(fd); | ||
1761 | if (r != MAILIMAP_NO_ERROR) | ||
1762 | return r; | ||
1763 | r = mailimap_mailbox_send(fd, mb); | ||
1764 | if (r != MAILIMAP_NO_ERROR) | ||
1765 | return r; | ||
1766 | r = mailimap_space_send(fd); | ||
1767 | if (r != MAILIMAP_NO_ERROR) | ||
1768 | return r; | ||
1769 | r = mailimap_mailbox_send(fd, new_name); | ||
1770 | if (r != MAILIMAP_NO_ERROR) | ||
1771 | return r; | ||
1772 | |||
1773 | return MAILIMAP_NO_ERROR; | ||
1774 | } | ||
1775 | |||
1776 | /* | ||
1777 | response = *(continue-req / response-data) response-done | ||
1778 | |||
1779 | response-data = "*" SP (resp-cond-state / resp-cond-bye / | ||
1780 | mailbox-data / message-data / capability-data) CRLF | ||
1781 | |||
1782 | response-done = response-tagged / response-fatal | ||
1783 | |||
1784 | response-fatal = "*" SP resp-cond-bye CRLF | ||
1785 | ; Server closes connection immediately | ||
1786 | |||
1787 | response-tagged = tag SP resp-cond-state CRLF | ||
1788 | |||
1789 | resp-cond-auth = ("OK" / "PREAUTH") SP resp-text | ||
1790 | ; Authentication condition | ||
1791 | |||
1792 | resp-cond-bye = "BYE" SP resp-text | ||
1793 | |||
1794 | resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text | ||
1795 | ; Status condition | ||
1796 | |||
1797 | resp-specials = "]" | ||
1798 | |||
1799 | resp-text = ["[" resp-text-code "]" SP] text | ||
1800 | |||
1801 | resp-text-code = "ALERT" / | ||
1802 | "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / | ||
1803 | capability-data / "PARSE" / | ||
1804 | "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / | ||
1805 | "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / | ||
1806 | "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / | ||
1807 | "UNSEEN" SP nz-number / | ||
1808 | atom [SP 1*<any TEXT-CHAR except "]">] | ||
1809 | */ | ||
1810 | |||
1811 | /* | ||
1812 | => search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key) | ||
1813 | ; CHARSET argument to MUST be registered with IANA | ||
1814 | */ | ||
1815 | |||
1816 | int | ||
1817 | mailimap_search_send(mailstream * fd, const char * charset, | ||
1818 | struct mailimap_search_key * key) | ||
1819 | { | ||
1820 | int r; | ||
1821 | |||
1822 | r = mailimap_token_send(fd, "SEARCH"); | ||
1823 | if (r != MAILIMAP_NO_ERROR) | ||
1824 | return r; | ||
1825 | |||
1826 | if (charset != NULL) { | ||
1827 | r = mailimap_space_send(fd); | ||
1828 | if (r != MAILIMAP_NO_ERROR) | ||
1829 | return r; | ||
1830 | |||
1831 | r = mailimap_token_send(fd, "CHARSET"); | ||
1832 | if (r != MAILIMAP_NO_ERROR) | ||
1833 | return r; | ||
1834 | r = mailimap_space_send(fd); | ||
1835 | if (r != MAILIMAP_NO_ERROR) | ||
1836 | return r; | ||
1837 | r = mailimap_astring_send(fd, charset); | ||
1838 | if (r != MAILIMAP_NO_ERROR) | ||
1839 | return r; | ||
1840 | } | ||
1841 | |||
1842 | r = mailimap_space_send(fd); | ||
1843 | if (r != MAILIMAP_NO_ERROR) | ||
1844 | return r; | ||
1845 | |||
1846 | r = mailimap_search_key_send(fd, key); | ||
1847 | if (r != MAILIMAP_NO_ERROR) | ||
1848 | return r; | ||
1849 | |||
1850 | return MAILIMAP_NO_ERROR; | ||
1851 | } | ||
1852 | |||
1853 | int | ||
1854 | mailimap_uid_search_send(mailstream * fd, const char * charset, | ||
1855 | struct mailimap_search_key * key) | ||
1856 | { | ||
1857 | int r; | ||
1858 | |||
1859 | r = mailimap_token_send(fd, "UID"); | ||
1860 | if (r != MAILIMAP_NO_ERROR) | ||
1861 | return r; | ||
1862 | |||
1863 | r = mailimap_space_send(fd); | ||
1864 | if (r != MAILIMAP_NO_ERROR) | ||
1865 | return r; | ||
1866 | |||
1867 | return mailimap_search_send(fd, charset, key); | ||
1868 | } | ||
1869 | |||
1870 | |||
1871 | /* | ||
1872 | => search-key = "ALL" / "ANSWERED" / "BCC" SP astring / | ||
1873 | "BEFORE" SP date / "BODY" SP astring / | ||
1874 | "CC" SP astring / "DELETED" / "FLAGGED" / | ||
1875 | "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" / | ||
1876 | "OLD" / "ON" SP date / "RECENT" / "SEEN" / | ||
1877 | "SINCE" SP date / "SUBJECT" SP astring / | ||
1878 | "TEXT" SP astring / "TO" SP astring / | ||
1879 | "UNANSWERED" / "UNDELETED" / "UNFLAGGED" / | ||
1880 | "UNKEYWORD" SP flag-keyword / "UNSEEN" / | ||
1881 | ; Above this line were in [IMAP2] | ||
1882 | "DRAFT" / "HEADER" SP header-fld-name SP astring / | ||
1883 | "LARGER" SP number / "NOT" SP search-key / | ||
1884 | "OR" SP search-key SP search-key / | ||
1885 | "SENTBEFORE" SP date / "SENTON" SP date / | ||
1886 | "SENTSINCE" SP date / "SMALLER" SP number / | ||
1887 | "UID" SP set / "UNDRAFT" / set / | ||
1888 | "(" search-key *(SP search-key) ")" | ||
1889 | */ | ||
1890 | |||
1891 | |||
1892 | static int mailimap_search_key_send(mailstream * fd, | ||
1893 | struct mailimap_search_key * key) | ||
1894 | { | ||
1895 | int r; | ||
1896 | |||
1897 | switch (key->sk_type) { | ||
1898 | |||
1899 | case MAILIMAP_SEARCH_KEY_ALL: | ||
1900 | return mailimap_token_send(fd, "ALL"); | ||
1901 | |||
1902 | case MAILIMAP_SEARCH_KEY_ANSWERED: | ||
1903 | return mailimap_token_send(fd, "ANSWERED"); | ||
1904 | |||
1905 | case MAILIMAP_SEARCH_KEY_BCC: | ||
1906 | r = mailimap_token_send(fd, "BCC"); | ||
1907 | if (r != MAILIMAP_NO_ERROR) | ||
1908 | return r; | ||
1909 | r = mailimap_space_send(fd); | ||
1910 | if (r != MAILIMAP_NO_ERROR) | ||
1911 | return r; | ||
1912 | r = mailimap_astring_send(fd, key->sk_data.sk_bcc); | ||
1913 | if (r != MAILIMAP_NO_ERROR) | ||
1914 | return r; | ||
1915 | return MAILIMAP_NO_ERROR; | ||
1916 | |||
1917 | case MAILIMAP_SEARCH_KEY_BEFORE: | ||
1918 | r = mailimap_token_send(fd, "BEFORE"); | ||
1919 | if (r != MAILIMAP_NO_ERROR) | ||
1920 | return r; | ||
1921 | r = mailimap_space_send(fd); | ||
1922 | if (r != MAILIMAP_NO_ERROR) | ||
1923 | return r; | ||
1924 | r = mailimap_date_send(fd, key->sk_data.sk_before); | ||
1925 | if (r != MAILIMAP_NO_ERROR) | ||
1926 | return r; | ||
1927 | return MAILIMAP_NO_ERROR; | ||
1928 | |||
1929 | case MAILIMAP_SEARCH_KEY_BODY: | ||
1930 | r = mailimap_token_send(fd, "BODY"); | ||
1931 | if (r != MAILIMAP_NO_ERROR) | ||
1932 | return r; | ||
1933 | r = mailimap_space_send(fd); | ||
1934 | if (r != MAILIMAP_NO_ERROR) | ||
1935 | return r; | ||
1936 | r = mailimap_astring_send(fd, key->sk_data.sk_body); | ||
1937 | if (r != MAILIMAP_NO_ERROR) | ||
1938 | return r; | ||
1939 | return MAILIMAP_NO_ERROR; | ||
1940 | |||
1941 | case MAILIMAP_SEARCH_KEY_CC: | ||
1942 | r = mailimap_token_send(fd, "CC"); | ||
1943 | if (r != MAILIMAP_NO_ERROR) | ||
1944 | return r; | ||
1945 | r = mailimap_space_send(fd); | ||
1946 | if (r != MAILIMAP_NO_ERROR) | ||
1947 | return r; | ||
1948 | r = mailimap_astring_send(fd, key->sk_data.sk_cc); | ||
1949 | if (r != MAILIMAP_NO_ERROR) | ||
1950 | return r; | ||
1951 | return MAILIMAP_NO_ERROR; | ||
1952 | |||
1953 | case MAILIMAP_SEARCH_KEY_DELETED: | ||
1954 | return mailimap_token_send(fd, "DELETED"); | ||
1955 | |||
1956 | case MAILIMAP_SEARCH_KEY_FLAGGED: | ||
1957 | return mailimap_token_send(fd, "FLAGGED"); | ||
1958 | |||
1959 | case MAILIMAP_SEARCH_KEY_FROM: | ||
1960 | r = mailimap_token_send(fd, "FROM"); | ||
1961 | if (r != MAILIMAP_NO_ERROR) | ||
1962 | return r; | ||
1963 | r = mailimap_space_send(fd); | ||
1964 | if (r != MAILIMAP_NO_ERROR) | ||
1965 | return r; | ||
1966 | r = mailimap_astring_send(fd, key->sk_data.sk_from); | ||
1967 | if (r != MAILIMAP_NO_ERROR) | ||
1968 | return r; | ||
1969 | return MAILIMAP_NO_ERROR; | ||
1970 | |||
1971 | case MAILIMAP_SEARCH_KEY_KEYWORD: | ||
1972 | r = mailimap_token_send(fd, "KEYWORD"); | ||
1973 | if (r != MAILIMAP_NO_ERROR) | ||
1974 | return r; | ||
1975 | r = mailimap_space_send(fd); | ||
1976 | if (r != MAILIMAP_NO_ERROR) | ||
1977 | return r; | ||
1978 | r = mailimap_flag_keyword_send(fd, key->sk_data.sk_keyword); | ||
1979 | if (r != MAILIMAP_NO_ERROR) | ||
1980 | return r; | ||
1981 | return MAILIMAP_NO_ERROR; | ||
1982 | |||
1983 | case MAILIMAP_SEARCH_KEY_NEW: | ||
1984 | return mailimap_token_send(fd, "NEW"); | ||
1985 | |||
1986 | case MAILIMAP_SEARCH_KEY_OLD: | ||
1987 | return mailimap_token_send(fd, "OLD"); | ||
1988 | |||
1989 | case MAILIMAP_SEARCH_KEY_ON: | ||
1990 | r = mailimap_token_send(fd, "ON"); | ||
1991 | if (r != MAILIMAP_NO_ERROR) | ||
1992 | return r; | ||
1993 | r = mailimap_space_send(fd); | ||
1994 | if (r != MAILIMAP_NO_ERROR) | ||
1995 | return r; | ||
1996 | r = mailimap_date_send(fd, key->sk_data.sk_on); | ||
1997 | if (r != MAILIMAP_NO_ERROR) | ||
1998 | return r; | ||
1999 | return MAILIMAP_NO_ERROR; | ||
2000 | |||
2001 | case MAILIMAP_SEARCH_KEY_RECENT: | ||
2002 | return mailimap_token_send(fd, "RECENT"); | ||
2003 | |||
2004 | case MAILIMAP_SEARCH_KEY_SEEN: | ||
2005 | return mailimap_token_send(fd, "SEEN"); | ||
2006 | |||
2007 | case MAILIMAP_SEARCH_KEY_SINCE: | ||
2008 | r = mailimap_token_send(fd, "SINCE"); | ||
2009 | if (r != MAILIMAP_NO_ERROR) | ||
2010 | return r; | ||
2011 | r = mailimap_space_send(fd); | ||
2012 | if (r != MAILIMAP_NO_ERROR) | ||
2013 | return r; | ||
2014 | r = mailimap_date_send(fd, key->sk_data.sk_since); | ||
2015 | if (r != MAILIMAP_NO_ERROR) | ||
2016 | return r; | ||
2017 | return MAILIMAP_NO_ERROR; | ||
2018 | |||
2019 | case MAILIMAP_SEARCH_KEY_SUBJECT: | ||
2020 | r = mailimap_token_send(fd, "SUBJECT"); | ||
2021 | if (r != MAILIMAP_NO_ERROR) | ||
2022 | return r; | ||
2023 | r = mailimap_space_send(fd); | ||
2024 | if (r != MAILIMAP_NO_ERROR) | ||
2025 | return r; | ||
2026 | r = mailimap_astring_send(fd, key->sk_data.sk_subject); | ||
2027 | if (r != MAILIMAP_NO_ERROR) | ||
2028 | return r; | ||
2029 | return MAILIMAP_NO_ERROR; | ||
2030 | |||
2031 | case MAILIMAP_SEARCH_KEY_TEXT: | ||
2032 | r = mailimap_token_send(fd, "TEXT"); | ||
2033 | if (r != MAILIMAP_NO_ERROR) | ||
2034 | return r; | ||
2035 | r = mailimap_space_send(fd); | ||
2036 | if (r != MAILIMAP_NO_ERROR) | ||
2037 | return r; | ||
2038 | r = mailimap_astring_send(fd, key->sk_data.sk_text); | ||
2039 | if (r != MAILIMAP_NO_ERROR) | ||
2040 | return r; | ||
2041 | return MAILIMAP_NO_ERROR; | ||
2042 | |||
2043 | case MAILIMAP_SEARCH_KEY_TO: | ||
2044 | r = mailimap_token_send(fd, "TO"); | ||
2045 | if (r != MAILIMAP_NO_ERROR) | ||
2046 | return r; | ||
2047 | r = mailimap_space_send(fd); | ||
2048 | if (r != MAILIMAP_NO_ERROR) | ||
2049 | return r; | ||
2050 | r = mailimap_astring_send(fd, key->sk_data.sk_text); | ||
2051 | if (r != MAILIMAP_NO_ERROR) | ||
2052 | return r; | ||
2053 | return MAILIMAP_NO_ERROR; | ||
2054 | |||
2055 | case MAILIMAP_SEARCH_KEY_UNANSWERED: | ||
2056 | return mailimap_token_send(fd, "UNANSWERED"); | ||
2057 | |||
2058 | case MAILIMAP_SEARCH_KEY_UNDELETED: | ||
2059 | return mailimap_token_send(fd, "UNDELETED"); | ||
2060 | |||
2061 | case MAILIMAP_SEARCH_KEY_UNFLAGGED: | ||
2062 | return mailimap_token_send(fd, "UNFLAGGED"); | ||
2063 | |||
2064 | case MAILIMAP_SEARCH_KEY_UNKEYWORD: | ||
2065 | r = mailimap_token_send(fd, "UNKEYWORD"); | ||
2066 | if (r != MAILIMAP_NO_ERROR) | ||
2067 | return r; | ||
2068 | r = mailimap_space_send(fd); | ||
2069 | if (r != MAILIMAP_NO_ERROR) | ||
2070 | return r; | ||
2071 | r = mailimap_flag_keyword_send(fd, key->sk_data.sk_keyword); | ||
2072 | if (r != MAILIMAP_NO_ERROR) | ||
2073 | return r; | ||
2074 | return MAILIMAP_NO_ERROR; | ||
2075 | |||
2076 | case MAILIMAP_SEARCH_KEY_UNSEEN: | ||
2077 | return mailimap_token_send(fd, "UNSEEN"); | ||
2078 | |||
2079 | case MAILIMAP_SEARCH_KEY_DRAFT: | ||
2080 | return mailimap_token_send(fd, "DRAFT"); | ||
2081 | |||
2082 | case MAILIMAP_SEARCH_KEY_HEADER: | ||
2083 | r = mailimap_token_send(fd, "HEADER"); | ||
2084 | if (r != MAILIMAP_NO_ERROR) | ||
2085 | return r; | ||
2086 | r = mailimap_space_send(fd); | ||
2087 | if (r != MAILIMAP_NO_ERROR) | ||
2088 | return r; | ||
2089 | r = mailimap_header_fld_name_send(fd, | ||
2090 | key->sk_data.sk_header.sk_header_name); | ||
2091 | if (r != MAILIMAP_NO_ERROR) | ||
2092 | return r; | ||
2093 | r = mailimap_space_send(fd); | ||
2094 | if (r != MAILIMAP_NO_ERROR) | ||
2095 | return r; | ||
2096 | r = mailimap_astring_send(fd, | ||
2097 | key->sk_data.sk_header.sk_header_value); | ||
2098 | if (r != MAILIMAP_NO_ERROR) | ||
2099 | return r; | ||
2100 | return MAILIMAP_NO_ERROR; | ||
2101 | |||
2102 | case MAILIMAP_SEARCH_KEY_LARGER: | ||
2103 | r = mailimap_token_send(fd, "LARGER"); | ||
2104 | if (r != MAILIMAP_NO_ERROR) | ||
2105 | return r; | ||
2106 | r = mailimap_space_send(fd); | ||
2107 | if (r != MAILIMAP_NO_ERROR) | ||
2108 | return r; | ||
2109 | r = mailimap_number_send(fd, key->sk_data.sk_larger); | ||
2110 | if (r != MAILIMAP_NO_ERROR) | ||
2111 | return r; | ||
2112 | return MAILIMAP_NO_ERROR; | ||
2113 | |||
2114 | case MAILIMAP_SEARCH_KEY_NOT: | ||
2115 | r = mailimap_token_send(fd, "NOT"); | ||
2116 | if (r != MAILIMAP_NO_ERROR) | ||
2117 | return r; | ||
2118 | r = mailimap_space_send(fd); | ||
2119 | if (r != MAILIMAP_NO_ERROR) | ||
2120 | return r; | ||
2121 | r = mailimap_search_key_send(fd, key->sk_data.sk_not); | ||
2122 | if (r != MAILIMAP_NO_ERROR) | ||
2123 | return r; | ||
2124 | return MAILIMAP_NO_ERROR; | ||
2125 | |||
2126 | case MAILIMAP_SEARCH_KEY_OR: | ||
2127 | r = mailimap_token_send(fd, "OR"); | ||
2128 | if (r != MAILIMAP_NO_ERROR) | ||
2129 | return r; | ||
2130 | r = mailimap_space_send(fd); | ||
2131 | if (r != MAILIMAP_NO_ERROR) | ||
2132 | return r; | ||
2133 | r = mailimap_search_key_send(fd, key->sk_data.sk_or.sk_or1); | ||
2134 | if (r != MAILIMAP_NO_ERROR) | ||
2135 | return r; | ||
2136 | r = mailimap_space_send(fd); | ||
2137 | if (r != MAILIMAP_NO_ERROR) | ||
2138 | return r; | ||
2139 | r = mailimap_search_key_send(fd, key->sk_data.sk_or.sk_or2); | ||
2140 | if (r != MAILIMAP_NO_ERROR) | ||
2141 | return r; | ||
2142 | return TRUE; | ||
2143 | |||
2144 | case MAILIMAP_SEARCH_KEY_SENTBEFORE: | ||
2145 | r = mailimap_token_send(fd, "SENTBEFORE"); | ||
2146 | if (r != MAILIMAP_NO_ERROR) | ||
2147 | return r; | ||
2148 | r = mailimap_space_send(fd); | ||
2149 | if (r != MAILIMAP_NO_ERROR) | ||
2150 | return r; | ||
2151 | r = mailimap_date_send(fd, key->sk_data.sk_sentbefore); | ||
2152 | if (r != MAILIMAP_NO_ERROR) | ||
2153 | return r; | ||
2154 | return MAILIMAP_NO_ERROR; | ||
2155 | |||
2156 | case MAILIMAP_SEARCH_KEY_SENTON: | ||
2157 | r = mailimap_token_send(fd, "SENTON"); | ||
2158 | if (r != MAILIMAP_NO_ERROR) | ||
2159 | return r; | ||
2160 | r = mailimap_space_send(fd); | ||
2161 | if (r != MAILIMAP_NO_ERROR) | ||
2162 | return r; | ||
2163 | r = mailimap_date_send(fd, key->sk_data.sk_senton); | ||
2164 | if (r != MAILIMAP_NO_ERROR) | ||
2165 | return r; | ||
2166 | return MAILIMAP_NO_ERROR; | ||
2167 | |||
2168 | case MAILIMAP_SEARCH_KEY_SENTSINCE: | ||
2169 | r = mailimap_token_send(fd, "SENTSINCE"); | ||
2170 | if (r != MAILIMAP_NO_ERROR) | ||
2171 | return r; | ||
2172 | r = mailimap_space_send(fd); | ||
2173 | if (r != MAILIMAP_NO_ERROR) | ||
2174 | return r; | ||
2175 | r = mailimap_date_send(fd, key->sk_data.sk_sentsince); | ||
2176 | if (r != MAILIMAP_NO_ERROR) | ||
2177 | return r; | ||
2178 | return MAILIMAP_NO_ERROR; | ||
2179 | |||
2180 | case MAILIMAP_SEARCH_KEY_SMALLER: | ||
2181 | r = mailimap_token_send(fd, "SMALLER"); | ||
2182 | if (r != MAILIMAP_NO_ERROR) | ||
2183 | return r; | ||
2184 | r = mailimap_space_send(fd); | ||
2185 | if (r != MAILIMAP_NO_ERROR) | ||
2186 | return r; | ||
2187 | r = mailimap_number_send(fd, key->sk_data.sk_smaller); | ||
2188 | if (r != MAILIMAP_NO_ERROR) | ||
2189 | return r; | ||
2190 | return MAILIMAP_NO_ERROR; | ||
2191 | |||
2192 | case MAILIMAP_SEARCH_KEY_UID: | ||
2193 | r = mailimap_token_send(fd, "UID"); | ||
2194 | if (r != MAILIMAP_NO_ERROR) | ||
2195 | return r; | ||
2196 | r = mailimap_space_send(fd); | ||
2197 | if (r != MAILIMAP_NO_ERROR) | ||
2198 | return r; | ||
2199 | r = mailimap_set_send(fd, key->sk_data.sk_set); | ||
2200 | if (r != MAILIMAP_NO_ERROR) | ||
2201 | return r; | ||
2202 | return MAILIMAP_NO_ERROR; | ||
2203 | |||
2204 | case MAILIMAP_SEARCH_KEY_UNDRAFT: | ||
2205 | return mailimap_token_send(fd, "UNDRAFT"); | ||
2206 | |||
2207 | case MAILIMAP_SEARCH_KEY_SET: | ||
2208 | return mailimap_set_send(fd, key->sk_data.sk_set); | ||
2209 | |||
2210 | case MAILIMAP_SEARCH_KEY_MULTIPLE: | ||
2211 | r = mailimap_oparenth_send(fd); | ||
2212 | if (r != MAILIMAP_NO_ERROR) | ||
2213 | return r; | ||
2214 | |||
2215 | r = mailimap_struct_spaced_list_send(fd, key->sk_data.sk_multiple, | ||
2216 | (mailimap_struct_sender *) | ||
2217 | mailimap_search_key_send); | ||
2218 | if (r != MAILIMAP_NO_ERROR) | ||
2219 | return r; | ||
2220 | |||
2221 | r = mailimap_cparenth_send(fd); | ||
2222 | if (r != MAILIMAP_NO_ERROR) | ||
2223 | return r; | ||
2224 | |||
2225 | return MAILIMAP_NO_ERROR; | ||
2226 | default: | ||
2227 | /* should not happend */ | ||
2228 | return MAILIMAP_ERROR_INVAL; | ||
2229 | } | ||
2230 | } | ||
2231 | |||
2232 | /* | ||
2233 | => section = "[" [section-spec] "]" | ||
2234 | */ | ||
2235 | |||
2236 | static int | ||
2237 | mailimap_section_send(mailstream * fd, | ||
2238 | struct mailimap_section * section) | ||
2239 | { | ||
2240 | int r; | ||
2241 | |||
2242 | r = mailimap_char_send(fd, '['); | ||
2243 | if (r != MAILIMAP_NO_ERROR) | ||
2244 | return r; | ||
2245 | |||
2246 | if (section != NULL) { | ||
2247 | if (section->sec_spec != NULL) { | ||
2248 | r = mailimap_section_spec_send(fd, section->sec_spec); | ||
2249 | if (r != MAILIMAP_NO_ERROR) | ||
2250 | return r; | ||
2251 | } | ||
2252 | } | ||
2253 | |||
2254 | r = mailimap_char_send(fd, ']'); | ||
2255 | if (r != MAILIMAP_NO_ERROR) | ||
2256 | return r; | ||
2257 | |||
2258 | return MAILIMAP_NO_ERROR; | ||
2259 | } | ||
2260 | |||
2261 | /* | ||
2262 | => section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list / | ||
2263 | "TEXT" | ||
2264 | ; top-level or MESSAGE/RFC822 part | ||
2265 | */ | ||
2266 | |||
2267 | static int | ||
2268 | mailimap_section_msgtext_send(mailstream * fd, | ||
2269 | struct mailimap_section_msgtext * | ||
2270 | section_msgtext) | ||
2271 | { | ||
2272 | int r; | ||
2273 | |||
2274 | switch (section_msgtext->sec_type) { | ||
2275 | case MAILIMAP_SECTION_MSGTEXT_HEADER: | ||
2276 | return mailimap_token_send(fd, "HEADER"); | ||
2277 | |||
2278 | case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS: | ||
2279 | r = mailimap_token_send(fd, "HEADER.FIELDS"); | ||
2280 | if (r != MAILIMAP_NO_ERROR) | ||
2281 | return r; | ||
2282 | r = mailimap_space_send(fd); | ||
2283 | if (r != MAILIMAP_NO_ERROR) | ||
2284 | return r; | ||
2285 | r = mailimap_header_list_send(fd, section_msgtext->sec_header_list); | ||
2286 | if (r != MAILIMAP_NO_ERROR) | ||
2287 | return r; | ||
2288 | return MAILIMAP_NO_ERROR; | ||
2289 | |||
2290 | case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT: | ||
2291 | r = mailimap_token_send(fd, "HEADER.FIELDS.NOT"); | ||
2292 | if (r != MAILIMAP_NO_ERROR) | ||
2293 | return r; | ||
2294 | r = mailimap_space_send(fd); | ||
2295 | if (r != MAILIMAP_NO_ERROR) | ||
2296 | return r; | ||
2297 | r = mailimap_header_list_send(fd, section_msgtext->sec_header_list); | ||
2298 | if (r != MAILIMAP_NO_ERROR) | ||
2299 | return r; | ||
2300 | return MAILIMAP_NO_ERROR; | ||
2301 | |||
2302 | case MAILIMAP_SECTION_MSGTEXT_TEXT: | ||
2303 | return mailimap_token_send(fd, "TEXT"); | ||
2304 | |||
2305 | default: | ||
2306 | /* should not happend */ | ||
2307 | return MAILIMAP_ERROR_INVAL; | ||
2308 | } | ||
2309 | } | ||
2310 | |||
2311 | /* | ||
2312 | => section-part = nz-number *("." nz-number) | ||
2313 | ; body part nesting | ||
2314 | */ | ||
2315 | |||
2316 | static int | ||
2317 | mailimap_pnumber_send(mailstream * fd, uint32_t * pnumber) | ||
2318 | { | ||
2319 | return mailimap_number_send(fd, * pnumber); | ||
2320 | } | ||
2321 | |||
2322 | static int | ||
2323 | mailimap_section_part_send(mailstream * fd, | ||
2324 | struct mailimap_section_part * section) | ||
2325 | { | ||
2326 | int r; | ||
2327 | |||
2328 | r = mailimap_struct_list_send(fd, section->sec_id, '.', | ||
2329 | (mailimap_struct_sender *) mailimap_pnumber_send); | ||
2330 | if (r != MAILIMAP_NO_ERROR) | ||
2331 | return r; | ||
2332 | |||
2333 | return MAILIMAP_NO_ERROR; | ||
2334 | } | ||
2335 | |||
2336 | /* | ||
2337 | => section-spec = section-msgtext / (section-part ["." section-text]) | ||
2338 | */ | ||
2339 | |||
2340 | static int | ||
2341 | mailimap_section_spec_send(mailstream * fd, | ||
2342 | struct mailimap_section_spec * section_spec) | ||
2343 | { | ||
2344 | int r; | ||
2345 | |||
2346 | switch (section_spec->sec_type) { | ||
2347 | case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT: | ||
2348 | return mailimap_section_msgtext_send(fd, | ||
2349 | section_spec->sec_data.sec_msgtext); | ||
2350 | |||
2351 | case MAILIMAP_SECTION_SPEC_SECTION_PART: | ||
2352 | r = mailimap_section_part_send(fd, section_spec->sec_data.sec_part); | ||
2353 | if (r != MAILIMAP_NO_ERROR) | ||
2354 | return r; | ||
2355 | |||
2356 | if (section_spec->sec_text != NULL) { | ||
2357 | r = mailimap_char_send(fd, '.'); | ||
2358 | if (r != MAILIMAP_NO_ERROR) | ||
2359 | return r; | ||
2360 | r = mailimap_section_text_send(fd, | ||
2361 | section_spec->sec_text); | ||
2362 | if (r != MAILIMAP_NO_ERROR) | ||
2363 | return r; | ||
2364 | } | ||
2365 | |||
2366 | return MAILIMAP_NO_ERROR; | ||
2367 | |||
2368 | default: | ||
2369 | /* should not happen */ | ||
2370 | return MAILIMAP_ERROR_INVAL; | ||
2371 | } | ||
2372 | } | ||
2373 | |||
2374 | /* | ||
2375 | => section-text = section-msgtext / "MIME" | ||
2376 | ; text other than actual body part (headers, etc.) | ||
2377 | */ | ||
2378 | |||
2379 | static int | ||
2380 | mailimap_section_text_send(mailstream * fd, | ||
2381 | struct mailimap_section_text * section_text) | ||
2382 | { | ||
2383 | switch (section_text->sec_type) { | ||
2384 | case MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT: | ||
2385 | return mailimap_section_msgtext_send(fd, section_text->sec_msgtext); | ||
2386 | |||
2387 | case MAILIMAP_SECTION_TEXT_MIME: | ||
2388 | return mailimap_token_send(fd, "MIME"); | ||
2389 | |||
2390 | default: | ||
2391 | /* should not happen */ | ||
2392 | return MAILIMAP_NO_ERROR; | ||
2393 | } | ||
2394 | } | ||
2395 | |||
2396 | /* | ||
2397 | => select = "SELECT" SP mailbox | ||
2398 | */ | ||
2399 | |||
2400 | int | ||
2401 | mailimap_select_send(mailstream * fd, const char * mb) | ||
2402 | { | ||
2403 | int r; | ||
2404 | |||
2405 | r = mailimap_token_send(fd, "SELECT"); | ||
2406 | if (r != MAILIMAP_NO_ERROR) | ||
2407 | return r; | ||
2408 | r = mailimap_space_send(fd); | ||
2409 | if (r != MAILIMAP_NO_ERROR) | ||
2410 | return r; | ||
2411 | r = mailimap_mailbox_send(fd, mb); | ||
2412 | if (r != MAILIMAP_NO_ERROR) | ||
2413 | return r; | ||
2414 | |||
2415 | return MAILIMAP_NO_ERROR; | ||
2416 | } | ||
2417 | |||
2418 | /* | ||
2419 | => sequence-num = nz-number / "*" | ||
2420 | ; * is the largest number in use. For message | ||
2421 | ; sequence numbers, it is the number of messages | ||
2422 | ; in the mailbox. For unique identifiers, it is | ||
2423 | ; the unique identifier of the last message in | ||
2424 | ; the mailbox. | ||
2425 | */ | ||
2426 | |||
2427 | /* if sequence_num == 0 then "*" */ | ||
2428 | |||
2429 | static int | ||
2430 | mailimap_sequence_num_send(mailstream * fd, uint32_t sequence_num) | ||
2431 | { | ||
2432 | if (sequence_num == 0) | ||
2433 | return mailimap_char_send(fd, '*'); | ||
2434 | else | ||
2435 | return mailimap_number_send(fd, sequence_num); | ||
2436 | } | ||
2437 | |||
2438 | /* | ||
2439 | => set = sequence-num / (sequence-num ":" sequence-num) / | ||
2440 | (set "," set) | ||
2441 | ; Identifies a set of messages. For message | ||
2442 | ; sequence numbers, these are consecutive | ||
2443 | ; numbers from 1 to the number of messages in | ||
2444 | ; the mailbox | ||
2445 | ; Comma delimits individual numbers, colon | ||
2446 | ; delimits between two numbers inclusive. | ||
2447 | ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13, | ||
2448 | ; 14,15 for a mailbox with 15 messages. | ||
2449 | */ | ||
2450 | |||
2451 | static int mailimap_set_item_send(mailstream * fd, | ||
2452 | struct mailimap_set_item * item) | ||
2453 | { | ||
2454 | int r; | ||
2455 | |||
2456 | if (item->set_first == item->set_last) | ||
2457 | return mailimap_sequence_num_send(fd, item->set_first); | ||
2458 | else { | ||
2459 | r = mailimap_sequence_num_send(fd, item->set_first); | ||
2460 | if (r != MAILIMAP_NO_ERROR) | ||
2461 | return r; | ||
2462 | r = mailimap_char_send(fd, ':'); | ||
2463 | if (r != MAILIMAP_NO_ERROR) | ||
2464 | return r; | ||
2465 | r = mailimap_sequence_num_send(fd, item->set_last); | ||
2466 | if (r != MAILIMAP_NO_ERROR) | ||
2467 | return r; | ||
2468 | return MAILIMAP_NO_ERROR; | ||
2469 | } | ||
2470 | } | ||
2471 | |||
2472 | static int mailimap_set_send(mailstream * fd, | ||
2473 | struct mailimap_set * set) | ||
2474 | { | ||
2475 | return mailimap_struct_list_send(fd, set->set_list, ',', | ||
2476 | (mailimap_struct_sender *) mailimap_set_item_send); | ||
2477 | } | ||
2478 | |||
2479 | /* | ||
2480 | => status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")" | ||
2481 | */ | ||
2482 | |||
2483 | static int | ||
2484 | mailimap_status_att_list_send(mailstream * fd, | ||
2485 | struct mailimap_status_att_list * status_att_list) | ||
2486 | { | ||
2487 | return mailimap_struct_spaced_list_send(fd, status_att_list->att_list, | ||
2488 | (mailimap_struct_sender *) mailimap_status_att_send); | ||
2489 | } | ||
2490 | |||
2491 | int | ||
2492 | mailimap_status_send(mailstream * fd, const char * mb, | ||
2493 | struct mailimap_status_att_list * status_att_list) | ||
2494 | { | ||
2495 | int r; | ||
2496 | |||
2497 | r = mailimap_token_send(fd, "STATUS"); | ||
2498 | if (r != MAILIMAP_NO_ERROR) | ||
2499 | return r; | ||
2500 | |||
2501 | r = mailimap_space_send(fd); | ||
2502 | if (r != MAILIMAP_NO_ERROR) | ||
2503 | return r; | ||
2504 | |||
2505 | r = mailimap_mailbox_send(fd, mb); | ||
2506 | if (r != MAILIMAP_NO_ERROR) | ||
2507 | return r; | ||
2508 | |||
2509 | r = mailimap_space_send(fd); | ||
2510 | if (r != MAILIMAP_NO_ERROR) | ||
2511 | return r; | ||
2512 | |||
2513 | r = mailimap_char_send(fd, '('); | ||
2514 | if (r != MAILIMAP_NO_ERROR) | ||
2515 | return r; | ||
2516 | |||
2517 | r = mailimap_status_att_list_send(fd, status_att_list); | ||
2518 | if (r != MAILIMAP_NO_ERROR) | ||
2519 | return r; | ||
2520 | |||
2521 | r = mailimap_char_send(fd, ')'); | ||
2522 | if (r != MAILIMAP_NO_ERROR) | ||
2523 | return r; | ||
2524 | |||
2525 | return MAILIMAP_NO_ERROR; | ||
2526 | } | ||
2527 | |||
2528 | /* | ||
2529 | => status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / | ||
2530 | "UNSEEN" | ||
2531 | */ | ||
2532 | |||
2533 | |||
2534 | static int mailimap_status_att_send(mailstream * fd, int * status_att) | ||
2535 | { | ||
2536 | const char * token; | ||
2537 | |||
2538 | token = mailimap_status_att_get_token_str(* status_att); | ||
2539 | if (token == NULL) { | ||
2540 | /* should not happen */ | ||
2541 | return MAILIMAP_ERROR_INVAL; | ||
2542 | } | ||
2543 | |||
2544 | return mailimap_token_send(fd, token); | ||
2545 | } | ||
2546 | |||
2547 | /* | ||
2548 | => store = "STORE" SP set SP store-att-flags | ||
2549 | */ | ||
2550 | |||
2551 | int | ||
2552 | mailimap_store_send(mailstream * fd, | ||
2553 | struct mailimap_set * set, | ||
2554 | struct mailimap_store_att_flags * store_att_flags) | ||
2555 | { | ||
2556 | int r; | ||
2557 | |||
2558 | r = mailimap_token_send(fd, "STORE"); | ||
2559 | if (r != MAILIMAP_NO_ERROR) | ||
2560 | return r; | ||
2561 | r = mailimap_space_send(fd); | ||
2562 | if (r != MAILIMAP_NO_ERROR) | ||
2563 | return r; | ||
2564 | r = mailimap_set_send(fd, set); | ||
2565 | if (r != MAILIMAP_NO_ERROR) | ||
2566 | return r; | ||
2567 | r = mailimap_space_send(fd); | ||
2568 | if (r != MAILIMAP_NO_ERROR) | ||
2569 | return r; | ||
2570 | |||
2571 | r = mailimap_store_att_flags_send(fd, store_att_flags); | ||
2572 | if (r != MAILIMAP_NO_ERROR) | ||
2573 | return r; | ||
2574 | |||
2575 | return MAILIMAP_NO_ERROR; | ||
2576 | } | ||
2577 | |||
2578 | int | ||
2579 | mailimap_uid_store_send(mailstream * fd, | ||
2580 | struct mailimap_set * set, | ||
2581 | struct mailimap_store_att_flags * store_att_flags) | ||
2582 | { | ||
2583 | int r; | ||
2584 | |||
2585 | r = mailimap_token_send(fd, "UID"); | ||
2586 | if (r != MAILIMAP_NO_ERROR) | ||
2587 | return r; | ||
2588 | r = mailimap_space_send(fd); | ||
2589 | if (r != MAILIMAP_NO_ERROR) | ||
2590 | return r; | ||
2591 | |||
2592 | return mailimap_store_send(fd, set, store_att_flags); | ||
2593 | } | ||
2594 | |||
2595 | /* | ||
2596 | => store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP | ||
2597 | (flag-list / (flag *(SP flag))) | ||
2598 | */ | ||
2599 | |||
2600 | static int | ||
2601 | mailimap_store_att_flags_send(mailstream * fd, | ||
2602 | struct mailimap_store_att_flags * store_flags) | ||
2603 | { | ||
2604 | int r; | ||
2605 | |||
2606 | switch (store_flags->fl_sign) { | ||
2607 | case 1: | ||
2608 | r = mailimap_char_send(fd, '+'); | ||
2609 | if (r != MAILIMAP_NO_ERROR) | ||
2610 | return r; | ||
2611 | case -1: | ||
2612 | r = mailimap_char_send(fd, '-'); | ||
2613 | if (r != MAILIMAP_NO_ERROR) | ||
2614 | return r; | ||
2615 | } | ||
2616 | |||
2617 | r = mailimap_token_send(fd, "FLAGS"); | ||
2618 | if (r != MAILIMAP_NO_ERROR) | ||
2619 | return r; | ||
2620 | |||
2621 | if (store_flags->fl_silent) { | ||
2622 | r = mailimap_token_send(fd, ".SILENT"); | ||
2623 | if (r != MAILIMAP_NO_ERROR) | ||
2624 | return r; | ||
2625 | } | ||
2626 | |||
2627 | r = mailimap_space_send(fd); | ||
2628 | if (r != MAILIMAP_NO_ERROR) | ||
2629 | return r; | ||
2630 | |||
2631 | r = mailimap_flag_list_send(fd, store_flags->fl_flag_list); | ||
2632 | if (r != MAILIMAP_NO_ERROR) | ||
2633 | return r; | ||
2634 | |||
2635 | return MAILIMAP_NO_ERROR; | ||
2636 | } | ||
2637 | |||
2638 | /* | ||
2639 | string = quoted / literal | ||
2640 | */ | ||
2641 | |||
2642 | /* | ||
2643 | => subscribe = "SUBSCRIBE" SP mailbox | ||
2644 | */ | ||
2645 | |||
2646 | int mailimap_subscribe_send(mailstream * fd, const char * mb) | ||
2647 | { | ||
2648 | int r; | ||
2649 | |||
2650 | r = mailimap_token_send(fd, "SUBSCRIBE"); | ||
2651 | if (r != MAILIMAP_NO_ERROR) | ||
2652 | return r; | ||
2653 | |||
2654 | r = mailimap_space_send(fd); | ||
2655 | if (r != MAILIMAP_NO_ERROR) | ||
2656 | return r; | ||
2657 | |||
2658 | r = mailimap_mailbox_send(fd, mb); | ||
2659 | if (r != MAILIMAP_NO_ERROR) | ||
2660 | return r; | ||
2661 | |||
2662 | return MAILIMAP_NO_ERROR; | ||
2663 | } | ||
2664 | |||
2665 | /* | ||
2666 | => tag = 1*<any ASTRING-CHAR except "+"> | ||
2667 | */ | ||
2668 | |||
2669 | int mailimap_tag_send(mailstream * fd, const char * tag) | ||
2670 | { | ||
2671 | return mailimap_token_send(fd, tag); | ||
2672 | } | ||
2673 | |||
2674 | /* | ||
2675 | text = 1*TEXT-CHAR | ||
2676 | |||
2677 | TEXT-CHAR = <any CHAR except CR and LF> | ||
2678 | |||
2679 | time = 2DIGIT ":" 2DIGIT ":" 2DIGIT | ||
2680 | ; Hours minutes seconds | ||
2681 | */ | ||
2682 | |||
2683 | /* | ||
2684 | => uid = "UID" SP (copy / fetch / search / store) | ||
2685 | ; Unique identifiers used instead of message | ||
2686 | ; sequence numbers | ||
2687 | |||
2688 | functions uid_copy, uid_fetch ... | ||
2689 | */ | ||
2690 | |||
2691 | |||
2692 | /* | ||
2693 | uniqueid = nz-number | ||
2694 | ; Strictly ascending | ||
2695 | */ | ||
2696 | |||
2697 | /* | ||
2698 | => unsubscribe = "UNSUBSCRIBE" SP mailbox | ||
2699 | */ | ||
2700 | |||
2701 | int mailimap_unsubscribe_send(mailstream * fd, | ||
2702 | const char * mb) | ||
2703 | { | ||
2704 | int r; | ||
2705 | |||
2706 | r = mailimap_token_send(fd, "UNSUBSCRIBE"); | ||
2707 | if (r != MAILIMAP_NO_ERROR) | ||
2708 | return r; | ||
2709 | r = mailimap_space_send(fd); | ||
2710 | if (r != MAILIMAP_NO_ERROR) | ||
2711 | return r; | ||
2712 | r = mailimap_mailbox_send(fd, mb); | ||
2713 | if (r != MAILIMAP_NO_ERROR) | ||
2714 | return r; | ||
2715 | |||
2716 | return MAILIMAP_NO_ERROR; | ||
2717 | } | ||
2718 | |||
2719 | int mailimap_starttls_send(mailstream * fd) | ||
2720 | { | ||
2721 | return mailimap_token_send(fd, "STARTTLS"); | ||
2722 | } | ||
2723 | |||
2724 | /* | ||
2725 | => userid = astring | ||
2726 | */ | ||
2727 | |||
2728 | static int mailimap_userid_send(mailstream * fd, const char * user) | ||
2729 | { | ||
2730 | return mailimap_astring_send(fd, user); | ||
2731 | } | ||
2732 | |||
2733 | /* | ||
2734 | x-command = "X" atom <experimental command arguments> | ||
2735 | |||
2736 | zone = ("+" / "-") 4DIGIT | ||
2737 | ; Signed four-digit value of hhmm representing | ||
2738 | ; hours and minutes east of Greenwich (that is, | ||
2739 | ; the amount that the given time differs from | ||
2740 | ; Universal Time). Subtracting the timezone | ||
2741 | ; from the given time will give the UT form. | ||
2742 | ; The Universal Time zone is "+0000". | ||
2743 | */ | ||