summaryrefslogtreecommitdiffabout
path: root/kmicromail/libetpan/imap/mailimap_sender.c
Unidiff
Diffstat (limited to 'kmicromail/libetpan/imap/mailimap_sender.c') (more/less context) (show whitespace changes)
-rw-r--r--kmicromail/libetpan/imap/mailimap_sender.c2743
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
61static int mailimap_atom_send(mailstream * fd, const char * atom);
62
63static int mailimap_auth_type_send(mailstream * fd, const char * auth_type);
64
65static int mailimap_base64_send(mailstream * fd, const char * base64);
66
67
68static int mailimap_date_send(mailstream * fd,
69 struct mailimap_date * date);
70
71static int mailimap_date_day_send(mailstream * fd, int day);
72
73static int mailimap_date_month_send(mailstream * fd, int month);
74
75
76/*
77static gboolean mailimap_date_text_send(mailstream * fd,
78 struct mailimap_date_text * date_text);
79*/
80
81
82static int mailimap_date_year_send(mailstream *fd, int year);
83
84static int
85mailimap_date_time_send(mailstream * fd,
86 struct mailimap_date_time * date_time);
87
88static int mailimap_digit_send(mailstream * fd, int digit);
89
90
91
92static int
93mailimap_fetch_type_send(mailstream * fd,
94 struct mailimap_fetch_type * fetch_type);
95
96
97static int mailimap_fetch_att_send(mailstream * fd,
98 struct mailimap_fetch_att * fetch_att);
99
100
101static int mailimap_flag_send(mailstream * fd,
102 struct mailimap_flag * flag);
103
104
105static int mailimap_flag_extension_send(mailstream * fd,
106 const char * flag_extension);
107
108
109static int mailimap_flag_keyword_send(mailstream * fd,
110 const char * flag_keyword);
111
112
113static int mailimap_flag_list_send(mailstream * fd,
114 struct mailimap_flag_list * flag_list);
115
116
117
118static int mailimap_header_fld_name_send(mailstream * fd, const char * header);
119
120
121static int
122mailimap_header_list_send(mailstream * fd,
123 struct mailimap_header_list * header_list);
124
125static int
126mailimap_list_mailbox_send(mailstream * fd, const char * pattern);
127
128
129static int mailimap_mailbox_send(mailstream * fd, const char * mb);
130
131static int mailimap_number_send(mailstream * fd, uint32_t number);
132
133static int mailimap_password_send(mailstream * fd, const char * pass);
134
135static int mailimap_quoted_char_send(mailstream * fd, char ch);
136
137static int mailimap_quoted_send(mailstream * fd, const char * quoted);
138
139
140static int mailimap_search_key_send(mailstream * fd,
141 struct mailimap_search_key * key);
142
143static int
144mailimap_section_send(mailstream * fd,
145 struct mailimap_section * section);
146
147static int
148mailimap_section_msgtext_send(mailstream * fd,
149 struct mailimap_section_msgtext *
150 section_msgtext);
151
152
153static int
154mailimap_section_part_send(mailstream * fd,
155 struct mailimap_section_part * section);
156
157
158static int
159mailimap_section_spec_send(mailstream * fd,
160 struct mailimap_section_spec * section_spec);
161
162
163static int
164mailimap_section_text_send(mailstream * fd,
165 struct mailimap_section_text * section_text);
166
167
168static int
169mailimap_sequence_num_send(mailstream * fd, uint32_t sequence_num);
170
171
172static int mailimap_set_item_send(mailstream * fd,
173 struct mailimap_set_item * item);
174
175
176static int mailimap_set_send(mailstream * fd,
177 struct mailimap_set * set);
178
179
180
181static int mailimap_status_att_send(mailstream * fd, int * status_att);
182
183
184
185static int
186mailimap_store_att_flags_send(mailstream * fd,
187 struct mailimap_store_att_flags * store_flags);
188
189
190static 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
216static 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
225static 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
233static 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
241typedef int mailimap_struct_sender(mailstream * fd, void * data);
242
243static int
244mailimap_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
278static int
279mailimap_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
285int mailimap_space_send(mailstream * fd)
286{
287 return mailimap_char_send(fd, ' ');
288}
289
290int 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
304static int mailimap_oparenth_send(mailstream * fd)
305{
306 return mailimap_char_send(fd, '(');
307}
308
309static int mailimap_cparenth_send(mailstream * fd)
310{
311 return mailimap_char_send(fd, ')');
312}
313
314static 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
348int 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
398static 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
415static 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
431static 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
449int 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
467int 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
484static 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
494static 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
588int 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
599int 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
610int 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
638int 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
649int 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
660int 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
679int 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
708int 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
730int 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
754static 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
787static 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
797static 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
821static 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/*
843static 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
865static 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
881static 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
897static int
898mailimap_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
955int 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
976digit
977
978digit-nz = %x31-39
979 ; 1-9
980*/
981
982static 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
1018int 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
1042static int
1043mailimap_fetch_att_list_send(mailstream * fd, clist * fetch_att_list);
1044
1045static int
1046mailimap_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
1067int 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
1096int
1097mailimap_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
1116static int
1117mailimap_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
1145static 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/*
1248enum {
1249 FLAG_ANSWERED,
1250 FLAG_FLAGGED,
1251 FLAG_DELETED,
1252 FLAG_SEEN,
1253 FLAG_DRAFT,
1254 FLAG_KEYWORD,
1255 FLAG_EXTENSION
1256};
1257
1258struct mailimap_flag {
1259 gint type;
1260 gchar * flag_keyword;
1261 gchar * flag_extension;
1262};
1263*/
1264
1265static 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
1300static 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
1324static 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
1334static 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
1367static 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
1376static int
1377mailimap_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
1402int 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
1435static int
1436mailimap_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
1452int
1453mailimap_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
1476int
1477mailimap_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
1504int
1505mailimap_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
1523int 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
1555int 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
1594static 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
1664static 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
1685static 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
1699static int is_quoted_specials(char ch)
1700{
1701 return (ch == '\"') || (ch == '\\');
1702}
1703
1704static 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
1722static 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
1752int 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
1816int
1817mailimap_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
1853int
1854mailimap_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
1892static 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
2236static int
2237mailimap_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
2267static int
2268mailimap_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
2316static int
2317mailimap_pnumber_send(mailstream * fd, uint32_t * pnumber)
2318{
2319 return mailimap_number_send(fd, * pnumber);
2320}
2321
2322static int
2323mailimap_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
2340static int
2341mailimap_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
2379static int
2380mailimap_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
2400int
2401mailimap_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
2429static int
2430mailimap_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
2451static 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
2472static 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
2483static int
2484mailimap_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
2491int
2492mailimap_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
2534static 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
2551int
2552mailimap_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
2578int
2579mailimap_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
2600static int
2601mailimap_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
2646int 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
2669int 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
2688functions 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
2701int 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
2719int mailimap_starttls_send(mailstream * fd)
2720{
2721 return mailimap_token_send(fd, "STARTTLS");
2722}
2723
2724/*
2725=> userid = astring
2726*/
2727
2728static 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*/