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