summaryrefslogtreecommitdiffabout
path: root/libetpan/src/low-level/imap/mailimap_parser.c
Unidiff
Diffstat (limited to 'libetpan/src/low-level/imap/mailimap_parser.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/low-level/imap/mailimap_parser.c9506
1 files changed, 9506 insertions, 0 deletions
diff --git a/libetpan/src/low-level/imap/mailimap_parser.c b/libetpan/src/low-level/imap/mailimap_parser.c
new file mode 100644
index 0000000..ab4db67
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_parser.c
@@ -0,0 +1,9506 @@
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 <string.h>
37#include <stdlib.h>
38#include <stdio.h>
39
40#include "mailstream.h"
41#include "mailimap_keywords.h"
42#include "mailimap_parser.h"
43#include "mmapstring.h"
44#include "mail.h"
45
46#ifndef UNSTRICT_SYNTAX
47#define UNSTRICT_SYNTAX
48#endif
49
50/*
51 Document: internet-drafts/draft-crispin-imapv-15.txt
52 RFC 2060 (IMAP but rather used draft)
53 RFC 2234 for all token that are not defined such as ALPHA
54*/
55
56
57
58/* ************************************************************************* */
59/* ************************************************************************* */
60/* ************************************************************************* */
61/* ************************************************************************* */
62/* ************************************************************************* */
63/* ************************************************************************* */
64
65
66
67
68static int mailimap_address_parse(mailstream * fd, MMAPString * buffer,
69 size_t * index,
70 struct mailimap_address ** result,
71 size_t progr_rate,
72 progress_function * progr_fun);
73
74static int mailimap_addr_adl_parse(mailstream * fd, MMAPString * buffer,
75 size_t * index, char ** result,
76 size_t progr_rate,
77 progress_function * progr_fun);
78
79static int mailimap_addr_host_parse(mailstream * fd, MMAPString * buffer,
80 size_t * index, char ** result,
81 size_t progr_rate,
82 progress_function * progr_fun);
83
84static int mailimap_addr_mailbox_parse(mailstream * fd, MMAPString * buffer,
85 size_t * index, char ** result,
86 size_t progr_rate,
87 progress_function * progr_fun);
88
89static int mailimap_addr_name_parse(mailstream * fd, MMAPString * buffer,
90 size_t * index, char ** result,
91 size_t progr_rate,
92 progress_function * progr_fun);
93
94
95static int
96mailimap_astring_parse(mailstream * fd, MMAPString * buffer,
97 size_t * index,
98 char ** result,
99 size_t progr_rate,
100 progress_function * progr_fun);
101
102static int mailimap_atom_parse(mailstream * fd, MMAPString * buffer,
103 size_t * index, char ** result,
104 size_t progr_rate,
105 progress_function * progr_fun);
106
107static int mailimap_auth_type_parse(mailstream * fd, MMAPString * buffer,
108 size_t * index, char ** result,
109 size_t progr_rate,
110 progress_function * progr_fun);
111
112static int mailimap_base64_parse(mailstream * fd, MMAPString * buffer,
113 size_t * index, char ** result,
114 size_t progr_rate,
115 progress_function * progr_fun);
116
117static int mailimap_body_parse(mailstream * fd, MMAPString * buffer,
118 size_t * index,
119 struct mailimap_body ** result,
120 size_t progr_rate,
121 progress_function * progr_fun);
122
123
124static int
125mailimap_body_extension_parse(mailstream * fd, MMAPString * buffer,
126 size_t * index,
127 struct mailimap_body_extension ** result,
128 size_t progr_rate,
129 progress_function * progr_fun);
130
131
132static int
133mailimap_body_ext_1part_parse(mailstream * fd, MMAPString * buffer,
134 size_t * index,
135 struct mailimap_body_ext_1part ** result,
136 size_t progr_rate,
137 progress_function * progr_fun);
138
139
140
141static int
142mailimap_body_ext_mpart_parse(mailstream * fd, MMAPString * buffer,
143 size_t * index,
144 struct mailimap_body_ext_mpart ** result,
145 size_t progr_rate,
146 progress_function * progr_fun);
147
148
149static int
150mailimap_body_fields_parse(mailstream * fd, MMAPString * buffer,
151 size_t * index,
152 struct mailimap_body_fields ** result,
153 size_t progr_rate,
154 progress_function * progr_fun);
155
156static int mailimap_body_fld_desc_parse(mailstream * fd, MMAPString * buffer,
157 size_t * index, char ** result,
158 size_t progr_rate,
159 progress_function * progr_fun);
160
161
162static int
163mailimap_body_fld_dsp_parse(mailstream * fd, MMAPString * buffer,
164 size_t * index,
165 struct mailimap_body_fld_dsp ** result,
166 size_t progr_rate,
167 progress_function * progr_fun);
168
169
170
171static int
172mailimap_body_fld_enc_parse(mailstream * fd, MMAPString * buffer,
173 size_t * index,
174 struct mailimap_body_fld_enc ** result,
175 size_t progr_rate,
176 progress_function * progr_fun);
177
178
179
180static int mailimap_body_fld_id_parse(mailstream * fd, MMAPString * buffer,
181 size_t * index, char ** result,
182 size_t progr_rate,
183 progress_function * progr_fun);
184
185
186static int
187mailimap_body_fld_lang_parse(mailstream * fd, MMAPString * buffer,
188 size_t * index,
189 struct mailimap_body_fld_lang ** result,
190 size_t progr_rate,
191 progress_function * progr_fun);
192
193static int mailimap_body_fld_lines_parse(mailstream * fd,
194 MMAPString * buffer, size_t * index,
195 uint32_t * result);
196
197static int mailimap_body_fld_md5_parse(mailstream * fd, MMAPString * buffer,
198 size_t * index, char ** result,
199 size_t progr_rate,
200 progress_function * progr_fun);
201
202static int mailimap_body_fld_octets_parse(mailstream * fd,
203 MMAPString * buffer, size_t * index,
204 uint32_t * result);
205
206static int
207mailimap_body_fld_param_parse(mailstream * fd,
208 MMAPString * buffer, size_t * index,
209 struct mailimap_body_fld_param ** result,
210 size_t progr_rate,
211 progress_function * progr_fun);
212
213
214
215static int
216mailimap_body_type_1part_parse(mailstream * fd, MMAPString * buffer,
217 size_t * index,
218 struct mailimap_body_type_1part ** result,
219 size_t progr_rate,
220 progress_function * progr_fun);
221
222
223
224static int
225mailimap_body_type_basic_parse(mailstream * fd, MMAPString * buffer,
226 size_t * index,
227 struct mailimap_body_type_basic ** result,
228 size_t progr_rate,
229 progress_function * progr_fun);
230
231
232
233static int
234mailimap_body_type_mpart_parse(mailstream * fd,
235 MMAPString * buffer,
236 size_t * index,
237 struct mailimap_body_type_mpart ** result,
238 size_t progr_rate,
239 progress_function * progr_fun);
240
241
242
243static int
244mailimap_body_type_msg_parse(mailstream * fd, MMAPString * buffer,
245 size_t * index,
246 struct mailimap_body_type_msg ** result,
247 size_t progr_rate,
248 progress_function * progr_fun);
249
250
251
252static int
253mailimap_body_type_text_parse(mailstream * fd, MMAPString * buffer,
254 size_t * index,
255 struct mailimap_body_type_text **
256 result,
257 size_t progr_rate,
258 progress_function * progr_fun);
259
260
261
262static int
263mailimap_capability_parse(mailstream * fd, MMAPString * buffer,
264 size_t * index,
265 struct mailimap_capability ** result,
266 size_t progr_rate,
267 progress_function * progr_fun);
268
269
270
271static int
272mailimap_capability_data_parse(mailstream * fd, MMAPString * buffer,
273 size_t * index,
274 struct mailimap_capability_data ** result,
275 size_t progr_rate,
276 progress_function * progr_fun);
277
278
279/*
280static gboolean mailimap_date_day_parse(mailstream * fd,
281 MMAPString * buffer,
282 guint32 * index,
283 gint * result);
284*/
285static int mailimap_date_day_fixed_parse(mailstream * fd,
286 MMAPString * buffer,
287 size_t * index,
288 int * result);
289
290static int mailimap_date_month_parse(mailstream * fd, MMAPString * buffer,
291 size_t * index, int * result);
292
293/*
294struct mailimap_date_text {
295 gint day;
296 gint month;
297 gint year;
298};
299
300static gboolean
301mailimap_date_text_parse(mailstream * fd, MMAPString * buffer,
302 guint32 * index, struct mailimap_date_text ** result);
303static void mailimap_date_text_free(struct mailimap_date_text * date_text);
304*/
305
306static int mailimap_date_year_parse(mailstream * fd, MMAPString * buffer,
307 size_t * index, int * result);
308
309static int mailimap_date_time_parse(mailstream * fd, MMAPString * buffer,
310 size_t * index,
311 struct mailimap_date_time ** t,
312 size_t progr_rate,
313 progress_function * progr_fun);
314
315#ifndef UNSTRICT_SYNTAX
316static int mailimap_digit_nz_parse(mailstream * fd, MMAPString * buffer,
317 size_t * index, int * result);
318#endif
319
320
321static int mailimap_envelope_parse(mailstream * fd, MMAPString * buffer,
322 size_t * index,
323 struct mailimap_envelope ** result,
324 size_t progr_rate,
325 progress_function * progr_fun);
326
327
328static int
329mailimap_env_bcc_parse(mailstream * fd, MMAPString * buffer,
330 size_t * index, struct mailimap_env_bcc ** result,
331 size_t progr_rate,
332 progress_function * progr_fun);
333
334
335static int
336mailimap_env_cc_parse(mailstream * fd, MMAPString * buffer,
337 size_t * index, struct mailimap_env_cc ** result,
338 size_t progr_rate,
339 progress_function * progr_fun);
340
341static int mailimap_env_date_parse(mailstream * fd, MMAPString * buffer,
342 size_t * index, char ** result,
343 size_t progr_rate,
344 progress_function * progr_fun);
345
346
347static int
348mailimap_env_from_parse(mailstream * fd, MMAPString * buffer,
349 size_t * index, struct mailimap_env_from ** result,
350 size_t progr_rate,
351 progress_function * progr_fun);
352
353
354static int mailimap_env_in_reply_to_parse(mailstream * fd,
355 MMAPString * buffer,
356 size_t * index, char ** result,
357 size_t progr_rate,
358 progress_function * progr_fun);
359
360static int mailimap_env_message_id_parse(mailstream * fd,
361 MMAPString * buffer,
362 size_t * index, char ** result,
363 size_t progr_rate,
364 progress_function * progr_fun);
365
366static int
367mailimap_env_reply_to_parse(mailstream * fd, MMAPString * buffer,
368 size_t * index,
369 struct mailimap_env_reply_to ** result,
370 size_t progr_rate,
371 progress_function * progr_fun);
372
373
374
375static int
376mailimap_env_sender_parse(mailstream * fd, MMAPString * buffer,
377 size_t * index, struct mailimap_env_sender ** result,
378 size_t progr_rate,
379 progress_function * progr_fun);
380
381static int mailimap_env_subject_parse(mailstream * fd, MMAPString * buffer,
382 size_t * index, char ** result,
383 size_t progr_rate,
384 progress_function * progr_fun);
385
386
387static int
388mailimap_env_to_parse(mailstream * fd, MMAPString * buffer,
389 size_t * index,
390 struct mailimap_env_to ** result,
391 size_t progr_rate,
392 progress_function * progr_fun);
393
394
395static int mailimap_flag_parse(mailstream * fd, MMAPString * buffer,
396 size_t * index,
397 struct mailimap_flag ** result,
398 size_t progr_rate,
399 progress_function * progr_fun);
400
401static int mailimap_flag_extension_parse(mailstream * fd,
402 MMAPString * buffer,
403 size_t * index,
404 char ** result,
405 size_t progr_rate,
406 progress_function * progr_fun);
407
408
409
410
411static int
412mailimap_flag_fetch_parse(mailstream * fd, MMAPString * buffer,
413 size_t * index,
414 struct mailimap_flag_fetch ** result,
415 size_t progr_rate,
416 progress_function * progr_fun);
417
418
419
420static int
421mailimap_flag_perm_parse(mailstream * fd, MMAPString * buffer,
422 size_t * index,
423 struct mailimap_flag_perm ** result,
424 size_t progr_rate,
425 progress_function * progr_fun);
426
427
428static int mailimap_flag_keyword_parse(mailstream * fd, MMAPString * buffer,
429 size_t * index,
430 char ** result,
431 size_t progr_rate,
432 progress_function * progr_fun);
433
434
435static int mailimap_flag_list_parse(mailstream * fd, MMAPString * buffer,
436 size_t * index,
437 struct mailimap_flag_list ** result,
438 size_t progr_rate,
439 progress_function * progr_fun);
440
441
442static int
443mailimap_header_fld_name_parse(mailstream * fd,
444 MMAPString * buffer,
445 size_t * index,
446 char ** result,
447 size_t progr_rate,
448 progress_function * progr_fun);
449
450
451
452
453static int
454mailimap_header_list_parse(mailstream * fd, MMAPString * buffer,
455 size_t * index,
456 struct mailimap_header_list ** result,
457 size_t progr_rate,
458 progress_function * progr_fun);
459
460static int mailimap_literal_parse(mailstream * fd, MMAPString * buffer,
461 size_t * index, char ** result,
462 size_t * result_len,
463 size_t progr_rate,
464 progress_function * progr_fun);
465
466
467static int
468mailimap_mailbox_parse(mailstream * fd, MMAPString * buffer,
469 size_t * index, char ** result,
470 size_t progr_rate,
471 progress_function * progr_fun);
472
473
474
475
476static int
477mailimap_mailbox_data_parse(mailstream * fd, MMAPString * buffer,
478 size_t * index,
479 struct mailimap_mailbox_data ** result,
480 size_t progr_rate,
481 progress_function * progr_fun);
482
483
484static int
485mailimap_mbx_list_flags_parse(mailstream * fd, MMAPString * buffer,
486 size_t * index,
487 struct mailimap_mbx_list_flags ** result,
488 size_t progr_rate,
489 progress_function * progr_fun);
490
491
492static int
493mailimap_mbx_list_oflag_parse(mailstream * fd, MMAPString * buffer,
494 size_t * index,
495 struct mailimap_mbx_list_oflag ** result,
496 size_t progr_rate,
497 progress_function * progr_fun);
498
499static int
500mailimap_mbx_list_oflag_no_sflag_parse(mailstream * fd, MMAPString * buffer,
501 size_t * index,
502 struct mailimap_mbx_list_oflag ** result,
503 size_t progr_rate,
504 progress_function * progr_fun);
505
506static int
507mailimap_mbx_list_sflag_parse(mailstream * fd, MMAPString * buffer,
508 size_t * index,
509 int * result);
510
511
512static int
513mailimap_mailbox_list_parse(mailstream * fd, MMAPString * buffer,
514 size_t * index,
515 struct mailimap_mailbox_list ** result,
516 size_t progr_rate,
517 progress_function * progr_fun);
518
519
520
521static int
522mailimap_media_basic_parse(mailstream * fd, MMAPString * buffer,
523 size_t * index,
524 struct mailimap_media_basic ** result,
525 size_t progr_rate,
526 progress_function * progr_fun);
527
528static int
529mailimap_media_message_parse(mailstream * fd, MMAPString * buffer,
530 size_t * index);
531
532static int
533mailimap_media_subtype_parse(mailstream * fd, MMAPString * buffer,
534 size_t * index,
535 char ** result,
536 size_t progr_rate,
537 progress_function * progr_fun);
538
539static int mailimap_media_text_parse(mailstream * fd, MMAPString * buffer,
540 size_t * index,
541 char ** result,
542 size_t progr_rate,
543 progress_function * progr_fun);
544
545
546
547static int
548mailimap_message_data_parse(mailstream * fd, MMAPString * buffer,
549 size_t * index,
550 struct mailimap_message_data ** result,
551 size_t progr_rate,
552 progress_function * progr_fun);
553
554
555
556
557
558static int
559mailimap_msg_att_parse(mailstream * fd, MMAPString * buffer,
560 size_t * index, struct mailimap_msg_att ** result,
561 size_t progr_rate,
562 progress_function * progr_fun);
563
564
565
566static int
567mailimap_msg_att_dynamic_parse(mailstream * fd, MMAPString * buffer,
568 size_t * index,
569 struct mailimap_msg_att_dynamic ** result,
570 size_t progr_rate,
571 progress_function * progr_fun);
572
573
574static int
575mailimap_msg_att_static_parse(mailstream * fd, MMAPString * buffer,
576 size_t * index,
577 struct mailimap_msg_att_static ** result,
578 size_t progr_rate,
579 progress_function * progr_fun);
580
581static int mailimap_nil_parse(mailstream * fd, MMAPString * buffer,
582 size_t * index);
583
584static int mailimap_nstring_parse(mailstream * fd, MMAPString * buffer,
585 size_t * index, char ** result,
586 size_t * result_len,
587 size_t progr_rate,
588 progress_function * progr_fun);
589
590static int
591mailimap_number_parse(mailstream * fd, MMAPString * buffer,
592 size_t * index, uint32_t * result);
593
594static int
595mailimap_nz_number_parse(mailstream * fd, MMAPString * buffer,
596 size_t * index, uint32_t * result);
597
598
599static int
600mailimap_quoted_parse(mailstream * fd, MMAPString * buffer,
601 size_t * index, char ** result,
602 size_t progr_rate,
603 progress_function * progr_fun);
604
605static int
606mailimap_quoted_char_parse(mailstream * fd, MMAPString * buffer,
607 size_t * index, char * result);
608
609
610static int
611mailimap_quoted_specials_parse(mailstream * fd, MMAPString * buffer,
612 size_t * index, char * result);
613
614
615
616
617
618static int
619mailimap_response_data_parse(mailstream * fd, MMAPString * buffer,
620 size_t * index,
621 struct mailimap_response_data ** result,
622 size_t progr_rate,
623 progress_function * progr_fun);
624
625
626
627
628static int
629mailimap_response_done_parse(mailstream * fd, MMAPString * buffer,
630 size_t * index,
631 struct mailimap_response_done ** result,
632 size_t progr_rate,
633 progress_function * progr_fun);
634
635static int
636mailimap_response_fatal_parse(mailstream * fd, MMAPString * buffer,
637 size_t * index,
638 struct mailimap_response_fatal ** result,
639 size_t progr_rate,
640 progress_function * progr_fun);
641
642
643static int
644mailimap_response_tagged_parse(mailstream * fd, MMAPString * buffer,
645 size_t * index,
646 struct mailimap_response_tagged ** result,
647 size_t progr_rate,
648 progress_function * progr_fun);
649
650
651static int
652mailimap_resp_cond_auth_parse(mailstream * fd, MMAPString * buffer,
653 size_t * index,
654 struct mailimap_resp_cond_auth ** result,
655 size_t progr_rate,
656 progress_function * progr_fun);
657
658static int
659mailimap_resp_cond_bye_parse(mailstream * fd, MMAPString * buffer,
660 size_t * index,
661 struct mailimap_resp_cond_bye ** result,
662 size_t progr_rate,
663 progress_function * progr_fun);
664
665
666static int
667mailimap_resp_cond_state_parse(mailstream * fd, MMAPString * buffer,
668 size_t * index,
669 struct mailimap_resp_cond_state ** result,
670 size_t progr_rate,
671 progress_function * progr_fun);
672
673
674static int
675mailimap_resp_text_parse(mailstream * fd, MMAPString * buffer,
676 size_t * index,
677 struct mailimap_resp_text ** result,
678 size_t progr_rate,
679 progress_function * progr_fun);
680
681
682static int
683mailimap_resp_text_code_parse(mailstream * fd, MMAPString * buffer,
684 size_t * index,
685 struct mailimap_resp_text_code ** result,
686 size_t progr_rate,
687 progress_function * progr_fun);
688
689
690static int
691mailimap_section_parse(mailstream * fd, MMAPString * buffer,
692 size_t * index,
693 struct mailimap_section ** result,
694 size_t progr_rate,
695 progress_function * progr_fun);
696
697
698static int
699mailimap_section_msgtext_parse(mailstream * fd, MMAPString * buffer,
700 size_t * index,
701 struct mailimap_section_msgtext ** result,
702 size_t progr_rate,
703 progress_function * progr_fun);
704
705
706static int
707mailimap_section_part_parse(mailstream * fd, MMAPString * buffer,
708 size_t * index,
709 struct mailimap_section_part ** result,
710 size_t progr_rate,
711 progress_function * progr_fun);
712
713
714
715
716static int
717mailimap_section_spec_parse(mailstream * fd, MMAPString * buffer,
718 size_t * index,
719 struct mailimap_section_spec ** result,
720 size_t progr_rate,
721 progress_function * progr_fun);
722
723
724static int
725mailimap_section_text_parse(mailstream * fd, MMAPString * buffer,
726 size_t * index,
727 struct mailimap_section_text ** result,
728 size_t progr_rate,
729 progress_function * progr_fun);
730
731
732static int mailimap_status_att_parse(mailstream * fd, MMAPString * buffer,
733 size_t * index, int * result);
734
735static int
736mailimap_string_parse(mailstream * fd, MMAPString * buffer,
737 size_t * index, char ** result,
738 size_t * result_len,
739 size_t progr_rate,
740 progress_function * progr_fun);
741
742static int mailimap_tag_parse(mailstream * fd, MMAPString * buffer,
743 size_t * index, char ** result,
744 size_t progr_rate,
745 progress_function * progr_fun);
746
747static int mailimap_text_parse(mailstream * fd, MMAPString * buffer,
748 size_t * index, char ** result,
749 size_t progr_rate,
750 progress_function * progr_fun);
751
752static int mailimap_time_parse(mailstream * fd, MMAPString * buffer,
753 size_t * index,
754 int * phour, int * pmin, int * psec);
755
756static int mailimap_uniqueid_parse(mailstream * fd, MMAPString * buffer,
757 size_t * index, uint32_t * result);
758
759static int mailimap_zone_parse(mailstream * fd, MMAPString * buffer,
760 size_t * index, int * result);
761
762
763
764/* ************************************************************************* */
765/* ************************************************************************* */
766/* ************************************************************************* */
767/* ************************************************************************* */
768/* ************************************************************************* */
769/* ************************************************************************* */
770
771
772
773
774
775/* ******************** TOOLS **************************** */
776
777
778static int mailimap_unstrict_char_parse(mailstream * fd, MMAPString * buffer,
779 size_t * index, char token)
780{
781 size_t cur_token;
782 int r;
783
784 cur_token = * index;
785
786#ifdef UNSTRICT_SYNTAX
787 /* can accept unstrict syntax */
788
789 mailimap_space_parse(fd, buffer, &cur_token);
790 if (token == ' ') {
791 * index = cur_token;
792 return MAILIMAP_NO_ERROR;
793 }
794#endif
795
796 r = mailimap_char_parse(fd, buffer, &cur_token, token);
797 if (r != MAILIMAP_NO_ERROR)
798 return r;
799
800 * index = cur_token;
801
802 return MAILIMAP_NO_ERROR;
803}
804
805static int mailimap_oparenth_parse(mailstream * fd, MMAPString * buffer,
806 size_t * index)
807{
808 return mailimap_unstrict_char_parse(fd, buffer, index, '(');
809}
810
811static int mailimap_cparenth_parse(mailstream * fd, MMAPString * buffer,
812 size_t * index)
813{
814 return mailimap_unstrict_char_parse(fd, buffer, index, ')');
815}
816
817static int mailimap_oaccolade_parse(mailstream * fd, MMAPString * buffer,
818 size_t * index)
819{
820 return mailimap_unstrict_char_parse(fd, buffer, index, '{');
821}
822
823static int mailimap_caccolade_parse(mailstream * fd, MMAPString * buffer,
824 size_t * index)
825{
826 return mailimap_unstrict_char_parse(fd, buffer, index, '}');
827}
828
829static int mailimap_plus_parse(mailstream * fd, MMAPString * buffer,
830 size_t * index)
831{
832 return mailimap_unstrict_char_parse(fd, buffer, index, '+');
833}
834
835static int mailimap_minus_parse(mailstream * fd, MMAPString * buffer,
836 size_t * index)
837{
838 return mailimap_unstrict_char_parse(fd, buffer, index, '-');
839}
840
841static int mailimap_star_parse(mailstream * fd, MMAPString * buffer,
842 size_t * index)
843{
844 return mailimap_unstrict_char_parse(fd, buffer, index, '*');
845}
846
847static int mailimap_dot_parse(mailstream * fd, MMAPString * buffer,
848 size_t * index)
849{
850 return mailimap_unstrict_char_parse(fd, buffer, index, '.');
851}
852
853static int mailimap_colon_parse(mailstream * fd, MMAPString * buffer,
854 size_t * index)
855{
856 return mailimap_unstrict_char_parse(fd, buffer, index, ':');
857}
858
859static int mailimap_lower_parse(mailstream * fd, MMAPString * buffer,
860 size_t * index)
861{
862 return mailimap_unstrict_char_parse(fd, buffer, index, '<');
863}
864
865static int mailimap_greater_parse(mailstream * fd, MMAPString * buffer,
866 size_t * index)
867{
868 return mailimap_unstrict_char_parse(fd, buffer, index, '>');
869}
870
871static int mailimap_obracket_parse(mailstream * fd, MMAPString * buffer,
872 size_t * index)
873{
874 return mailimap_unstrict_char_parse(fd, buffer, index, '[');
875}
876
877static int mailimap_cbracket_parse(mailstream * fd, MMAPString * buffer,
878 size_t * index)
879{
880 return mailimap_unstrict_char_parse(fd, buffer, index, ']');
881}
882
883static int mailimap_dquote_parse(mailstream * fd, MMAPString * buffer,
884 size_t * index)
885{
886 return mailimap_char_parse(fd, buffer, index, '\"');
887}
888
889static int mailimap_crlf_parse(mailstream * fd, MMAPString * buffer,
890 size_t * index)
891{
892 size_t cur_token = * index;
893
894#ifdef UNSTRICT_SYNTAX
895 mailimap_space_parse(fd, buffer, &cur_token);
896#endif
897
898 if (mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "\r\n")) {
899 * index = cur_token;
900 return MAILIMAP_NO_ERROR;
901 }
902
903#ifdef UNSTRICT_SYNTAX
904 else if (mailimap_unstrict_char_parse(fd, buffer, &cur_token, '\n')) {
905 * index = cur_token;
906 return MAILIMAP_NO_ERROR;
907 }
908#endif
909
910 else
911 return MAILIMAP_ERROR_PARSE;
912}
913
914typedef int mailimap_struct_parser(mailstream * fd, MMAPString * buffer,
915 size_t * index, void * result,
916 size_t progr_rate,
917 progress_function * progr_fun);
918typedef int mailimap_struct_destructor(void * result);
919
920
921static int
922mailimap_struct_multiple_parse(mailstream * fd, MMAPString * buffer,
923 size_t * index, clist ** result,
924 mailimap_struct_parser * parser,
925 mailimap_struct_destructor * destructor,
926 size_t progr_rate,
927 progress_function * progr_fun)
928{
929 clist * struct_list;
930 size_t cur_token;
931 void * value;
932 int r;
933 int res;
934
935 cur_token = * index;
936
937 r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun);
938 if (r != MAILIMAP_NO_ERROR) {
939 res = r;
940 goto err;
941 }
942
943 struct_list = clist_new();
944 if (struct_list == NULL) {
945 destructor(value);
946 res = MAILIMAP_ERROR_MEMORY;
947 goto err;
948 }
949
950 r = clist_append(struct_list, value);
951 if (r < 0) {
952 destructor(value);
953 res = MAILIMAP_ERROR_MEMORY;
954 goto free_list;
955 }
956
957 while (1) {
958 r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun);
959 if (r == MAILIMAP_ERROR_PARSE)
960 break;
961 if (r != MAILIMAP_NO_ERROR) {
962 res = r;
963 goto free_list;
964 }
965
966 r = clist_append(struct_list, value);
967 if (r < 0) {
968 destructor(value);
969 res = MAILIMAP_ERROR_MEMORY;
970 goto free_list;
971 }
972 }
973
974 * result = struct_list;
975 * index = cur_token;
976
977 return MAILIMAP_NO_ERROR;
978
979 free_list:
980 clist_foreach(struct_list, (clist_func) destructor, NULL);
981 clist_free(struct_list);
982 err:
983 return res;
984}
985
986static int
987mailimap_struct_list_parse(mailstream * fd, MMAPString * buffer,
988 size_t * index, clist ** result,
989 char symbol,
990 mailimap_struct_parser * parser,
991 mailimap_struct_destructor * destructor,
992 size_t progr_rate,
993 progress_function * progr_fun)
994{
995 clist * struct_list;
996 size_t cur_token;
997 void * value;
998 size_t final_token;
999 int r;
1000 int res;
1001
1002 cur_token = * index;
1003 struct_list = NULL;
1004
1005 r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun);
1006 if (r != MAILIMAP_NO_ERROR) {
1007 res = r;
1008 goto err;
1009 }
1010
1011 struct_list = clist_new();
1012 if (struct_list == NULL) {
1013 destructor(value);
1014 res = MAILIMAP_ERROR_MEMORY;
1015 goto err;
1016 }
1017
1018 r = clist_append(struct_list, value);
1019 if (r < 0) {
1020 destructor(value);
1021 res = MAILIMAP_ERROR_MEMORY;
1022 goto free_list;
1023 }
1024
1025 final_token = cur_token;
1026
1027 while (1) {
1028 r = mailimap_unstrict_char_parse(fd, buffer, &cur_token, symbol);
1029 if (r == MAILIMAP_ERROR_PARSE)
1030 break;
1031 if (r != MAILIMAP_NO_ERROR) {
1032 res = r;
1033 goto free_list;
1034 }
1035
1036 r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun);
1037 if (r == MAILIMAP_ERROR_PARSE)
1038 break;
1039
1040 if (r != MAILIMAP_NO_ERROR) {
1041 res = r;
1042 goto free_list;
1043 }
1044
1045 r = clist_append(struct_list, value);
1046 if (r < 0) {
1047 destructor(value);
1048 res = MAILIMAP_ERROR_MEMORY;
1049 goto free_list;
1050 }
1051
1052 final_token = cur_token;
1053 }
1054
1055 * result = struct_list;
1056 * index = final_token;
1057
1058 return MAILIMAP_NO_ERROR;
1059
1060 free_list:
1061 clist_foreach(struct_list, (clist_func) destructor, NULL);
1062 clist_free(struct_list);
1063 err:
1064 return res;
1065}
1066
1067static int
1068mailimap_struct_spaced_list_parse(mailstream * fd, MMAPString * buffer,
1069 size_t * index, clist ** result,
1070 mailimap_struct_parser * parser,
1071 mailimap_struct_destructor * destructor,
1072 size_t progr_rate,
1073 progress_function * progr_fun)
1074{
1075 return mailimap_struct_list_parse(fd, buffer, index, result,
1076 ' ', parser, destructor,
1077 progr_rate, progr_fun);
1078}
1079
1080
1081
1082static int
1083mailimap_custom_string_parse(mailstream * fd, MMAPString * buffer,
1084 size_t * index, char ** result,
1085 int (* is_custom_char)(char))
1086{
1087 size_t begin;
1088 size_t end;
1089 char * gstr;
1090
1091 begin = * index;
1092
1093#ifdef UNSTRICT_SYNTAX
1094 mailimap_space_parse(fd, buffer, &begin);
1095#endif
1096
1097 end = begin;
1098
1099 while (is_custom_char(buffer->str[end]))
1100 end ++;
1101
1102 if (end != begin) {
1103 gstr = malloc(end - begin + 1);
1104 if (gstr == NULL)
1105 return MAILIMAP_ERROR_MEMORY;
1106
1107 strncpy(gstr, buffer->str + begin, end - begin);
1108 gstr[end - begin] = '\0';
1109
1110 * index = end;
1111 * result = gstr;
1112 return MAILIMAP_NO_ERROR;
1113 }
1114 else
1115 return MAILIMAP_ERROR_PARSE;
1116}
1117
1118
1119
1120static int
1121mailimap_nz_number_alloc_parse(mailstream * fd, MMAPString * buffer,
1122 size_t * index,
1123 uint32_t ** result,
1124 size_t progr_rate,
1125 progress_function * progr_fun)
1126{
1127 uint32_t number;
1128 uint32_t * number_alloc;
1129 size_t cur_token;
1130 int r;
1131
1132 cur_token = * index;
1133
1134 r = mailimap_nz_number_parse(fd, buffer, &cur_token, &number);
1135 if (r != MAILIMAP_NO_ERROR)
1136 return r;
1137
1138 number_alloc = mailimap_number_alloc_new(number);
1139 if (number_alloc == NULL)
1140 return MAILIMAP_ERROR_MEMORY;
1141
1142 * index = cur_token;
1143 * result = number_alloc;
1144
1145 return MAILIMAP_NO_ERROR;
1146}
1147
1148
1149static int is_ctl(char ch)
1150{
1151 unsigned char uch = (unsigned char) ch;
1152
1153 return (uch <= 0x1F);
1154}
1155
1156static int is_char(char ch)
1157{
1158#ifdef UNSTRICT_SYNTAX
1159 return (ch != 0);
1160#else
1161 unsigned char uch = ch;
1162
1163 return (uch >= 0x01) && (uch <= 0x7f);
1164#endif
1165}
1166
1167static int is_alpha(char ch)
1168{
1169 return ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && (ch <= 'z')));
1170}
1171
1172static int is_digit(char ch)
1173{
1174 return (ch >= '0') && (ch <= '9');
1175}
1176
1177static int mailimap_digit_parse(mailstream * fd, MMAPString * buffer,
1178 size_t * index, int * result)
1179{
1180 size_t cur_token;
1181
1182 cur_token = * index;
1183
1184 if (is_digit(buffer->str[cur_token])) {
1185 * result = buffer->str[cur_token] - '0';
1186 cur_token ++;
1187 * index = cur_token;
1188 return MAILIMAP_NO_ERROR;
1189 }
1190 else
1191 return MAILIMAP_ERROR_PARSE;
1192}
1193
1194
1195/* ******************** parser **************************** */
1196
1197/*
1198 address = "(" addr-name SP addr-adl SP addr-mailbox SP
1199 addr-host ")"
1200*/
1201
1202static int mailimap_address_parse(mailstream * fd, MMAPString * buffer,
1203 size_t * index,
1204 struct mailimap_address ** result,
1205 size_t progr_rate,
1206 progress_function * progr_fun)
1207{
1208 size_t cur_token;
1209 char * addr_name;
1210 char * addr_adl;
1211 char * addr_mailbox;
1212 char * addr_host;
1213 struct mailimap_address * addr;
1214 int r;
1215 int res;
1216
1217 cur_token = * index;
1218
1219 addr_name = NULL;
1220 addr_adl = NULL;
1221 addr_mailbox = NULL;
1222 addr_host = NULL;
1223
1224 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
1225 if (r != MAILIMAP_NO_ERROR) {
1226 res = r;
1227 goto err;
1228 }
1229
1230 r = mailimap_addr_name_parse(fd, buffer, &cur_token, &addr_name,
1231 progr_rate, progr_fun);
1232 if (r != MAILIMAP_NO_ERROR) {
1233 res = r;
1234 goto err;
1235 }
1236
1237 r = mailimap_space_parse(fd, buffer, &cur_token);
1238 if (r != MAILIMAP_NO_ERROR) {
1239 res = r;
1240 goto addr_name_free;
1241 }
1242
1243 r = mailimap_addr_adl_parse(fd, buffer, &cur_token, &addr_adl,
1244 progr_rate, progr_fun);
1245 if (r != MAILIMAP_NO_ERROR) {
1246 res = r;
1247 goto addr_name_free;
1248 }
1249
1250 r = mailimap_space_parse(fd, buffer, &cur_token);
1251 if (r != MAILIMAP_NO_ERROR) {
1252 res = r;
1253 goto addr_adl_free;
1254 }
1255
1256 r = mailimap_addr_mailbox_parse(fd, buffer, &cur_token, &addr_mailbox,
1257 progr_rate, progr_fun);
1258 if (r != MAILIMAP_NO_ERROR) {
1259 res = r;
1260 goto addr_adl_free;
1261 }
1262
1263 r = mailimap_space_parse(fd, buffer, &cur_token);
1264 if (r != MAILIMAP_NO_ERROR) {
1265 res = r;
1266 goto addr_mailbox_free;
1267 }
1268
1269 r = mailimap_addr_host_parse(fd, buffer, &cur_token, &addr_host,
1270 progr_rate, progr_fun);
1271 if (r != MAILIMAP_NO_ERROR) {
1272 res = r;
1273 goto addr_mailbox_free;
1274 }
1275
1276 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
1277 if (r != MAILIMAP_NO_ERROR) {
1278 res = r;
1279 goto addr_host_free;
1280 }
1281
1282 addr = mailimap_address_new(addr_name, addr_adl, addr_mailbox, addr_host);
1283
1284 if (addr == NULL) {
1285 res = MAILIMAP_ERROR_MEMORY;
1286 goto addr_host_free;
1287 }
1288
1289 * result = addr;
1290 * index = cur_token;
1291
1292 return MAILIMAP_NO_ERROR;
1293
1294 addr_host_free:
1295 mailimap_addr_host_free(addr_host);
1296 addr_mailbox_free:
1297 mailimap_addr_mailbox_free(addr_mailbox);
1298 addr_adl_free:
1299 mailimap_addr_adl_free(addr_adl);
1300 addr_name_free:
1301 mailimap_addr_name_free(addr_name);
1302 err:
1303 return res;
1304}
1305
1306/*
1307 addr-adl = nstring
1308 ; Holds route from [RFC-822] route-addr if
1309 ; non-NIL
1310*/
1311
1312static int mailimap_addr_adl_parse(mailstream * fd, MMAPString * buffer,
1313 size_t * index, char ** result,
1314 size_t progr_rate,
1315 progress_function * progr_fun)
1316{
1317 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
1318 progr_rate, progr_fun);
1319}
1320
1321/*
1322 addr-host = nstring
1323 ; NIL indicates [RFC-822] group syntax.
1324 ; Otherwise, holds [RFC-822] domain name
1325*/
1326
1327static int mailimap_addr_host_parse(mailstream * fd, MMAPString * buffer,
1328 size_t * index, char ** result,
1329 size_t progr_rate,
1330 progress_function * progr_fun)
1331{
1332 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
1333 progr_rate, progr_fun);
1334}
1335
1336/*
1337 addr-mailbox = nstring
1338 ; NIL indicates end of [RFC-822] group; if
1339 ; non-NIL and addr-host is NIL, holds
1340 ; [RFC-822] group name.
1341 ; Otherwise, holds [RFC-822] local-part
1342 ; after removing [RFC-822] quoting
1343 */
1344
1345static int mailimap_addr_mailbox_parse(mailstream * fd, MMAPString * buffer,
1346 size_t * index, char ** result,
1347 size_t progr_rate,
1348 progress_function * progr_fun)
1349{
1350 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
1351 progr_rate, progr_fun);
1352}
1353
1354
1355/*
1356 addr-name = nstring
1357 ; If non-NIL, holds phrase from [RFC-822]
1358 ; mailbox after removing [RFC-822] quoting
1359*/
1360
1361static int mailimap_addr_name_parse(mailstream * fd, MMAPString * buffer,
1362 size_t * index, char ** result,
1363 size_t progr_rate,
1364 progress_function * progr_fun)
1365{
1366 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
1367 progr_rate, progr_fun);
1368}
1369
1370
1371/*
1372 NOT IMPLEMENTED
1373 append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP
1374 literal
1375*/
1376
1377/*
1378 astring = 1*ASTRING-CHAR / string
1379*/
1380
1381static int is_astring_char(char ch);
1382
1383static int
1384mailimap_atom_astring_parse(mailstream * fd, MMAPString * buffer,
1385 size_t * index, char ** result,
1386 size_t progr_rate,
1387 progress_function * progr_fun)
1388{
1389 return mailimap_custom_string_parse(fd, buffer, index, result,
1390 is_astring_char);
1391}
1392
1393static int
1394mailimap_astring_parse(mailstream * fd, MMAPString * buffer,
1395 size_t * index,
1396 char ** result,
1397 size_t progr_rate,
1398 progress_function * progr_fun)
1399{
1400 size_t cur_token;
1401 char * astring;
1402 int r;
1403
1404 cur_token = * index;
1405
1406 r = mailimap_atom_astring_parse(fd, buffer, &cur_token, &astring,
1407 progr_rate, progr_fun);
1408 switch (r) {
1409 case MAILIMAP_NO_ERROR:
1410 break;
1411
1412 case MAILIMAP_ERROR_PARSE:
1413 r = mailimap_string_parse(fd, buffer, &cur_token, &astring, NULL,
1414 progr_rate, progr_fun);
1415 if (r != MAILIMAP_NO_ERROR)
1416 return r;
1417 break;
1418
1419 default:
1420 return r;
1421 }
1422
1423 * result = astring;
1424 * index = cur_token;
1425
1426 return MAILIMAP_NO_ERROR;
1427}
1428
1429/*
1430 ASTRING-CHAR = ATOM-CHAR / resp-specials
1431*/
1432
1433static int is_atom_char(char ch);
1434static int is_resp_specials(char ch);
1435
1436static int is_astring_char(char ch)
1437{
1438 if (is_atom_char(ch))
1439 return TRUE;
1440 if (is_resp_specials(ch))
1441 return TRUE;
1442 return FALSE;
1443}
1444
1445/*
1446 atom = 1*ATOM-CHAR
1447*/
1448
1449static int mailimap_atom_parse(mailstream * fd, MMAPString * buffer,
1450 size_t * index, char ** result,
1451 size_t progr_rate,
1452 progress_function * progr_fun)
1453{
1454 return mailimap_custom_string_parse(fd, buffer, index, result,
1455 is_atom_char);
1456}
1457
1458/*
1459 ATOM-CHAR = <any CHAR except atom-specials>
1460*/
1461
1462static int is_atom_specials(char ch);
1463
1464static int is_atom_char(char ch)
1465{
1466 if (is_atom_specials(ch))
1467 return FALSE;
1468
1469 return is_char(ch);
1470}
1471
1472/*
1473 atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards /
1474 quoted-specials / resp-specials
1475
1476no "}" because there is no need (Mark Crispin)
1477*/
1478
1479static int is_quoted_specials(char ch);
1480static int is_list_wildcards(char ch);
1481
1482static int is_atom_specials(char ch)
1483{
1484 switch (ch) {
1485 case '(':
1486 case ')':
1487 case '{':
1488 case ' ':
1489 return TRUE;
1490 };
1491 if (is_ctl(ch))
1492 return TRUE;
1493 if (is_list_wildcards(ch))
1494 return TRUE;
1495 if (is_resp_specials(ch))
1496 return TRUE;
1497
1498 return is_quoted_specials(ch);
1499}
1500
1501/*
1502 NOT IMPLEMENTED
1503 authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64)
1504*/
1505
1506/*
1507 auth-type = atom
1508 ; Defined by [SASL]
1509*/
1510
1511static int mailimap_auth_type_parse(mailstream * fd, MMAPString * buffer,
1512 size_t * index, char ** result,
1513 size_t progr_rate,
1514 progress_function * progr_fun)
1515{
1516 return mailimap_atom_parse(fd, buffer, index, result,
1517 progr_rate, progr_fun);
1518}
1519
1520/*
1521 base64 = *(4base64-char) [base64-terminal]
1522*/
1523
1524static int is_base64_4char(char * str);
1525static int is_base64_terminal(char * str);
1526
1527static int mailimap_base64_parse(mailstream * fd, MMAPString * buffer,
1528 size_t * index, char ** result,
1529 size_t progr_rate,
1530 progress_function * progr_fun)
1531{
1532 size_t begin;
1533 size_t end;
1534 char * gstr;
1535
1536 begin = * index;
1537 end = begin;
1538
1539 while (is_base64_4char(buffer->str + end))
1540 end += 4;
1541 if (is_base64_terminal(buffer->str + end))
1542 end += 4;
1543 else
1544 return MAILIMAP_ERROR_PARSE;
1545
1546 gstr = malloc(end - begin + 1);
1547 if (gstr == NULL)
1548 return MAILIMAP_ERROR_MEMORY;
1549 strncpy(gstr, buffer->str + begin, end - begin);
1550 gstr[end - begin] = '\0';
1551
1552 * result = gstr;
1553 * index = end;
1554
1555 return MAILIMAP_NO_ERROR;
1556}
1557
1558/*
1559 base64-char = ALPHA / DIGIT / "+" / "/"
1560 ; Case-sensitive
1561*/
1562
1563static int is_base64_char(char ch)
1564{
1565 return (is_alpha(ch) || is_digit(ch) || ch == '+' || ch == '/');
1566}
1567
1568static int is_base64_4char(char * str)
1569{
1570 size_t i;
1571
1572 for (i = 0 ; i < 4 ; i++)
1573 if (!is_base64_char(str[i]))
1574 return FALSE;
1575 return TRUE;
1576}
1577
1578/*
1579 base64-terminal = (2base64-char "==") / (3base64-char "=")
1580*/
1581
1582static int is_base64_terminal(char * str)
1583{
1584 if (str[0] == 0)
1585 return FALSE;
1586 if (str[1] == 0)
1587 return FALSE;
1588 if (str[2] == 0)
1589 return FALSE;
1590 if (str[3] == 0)
1591 return FALSE;
1592
1593 if (is_base64_char(str[0]) || is_base64_char(str[1])
1594 || str[2] == '=' || str[3] == '=')
1595 return TRUE;
1596 if (is_base64_char(str[0]) || is_base64_char(str[1])
1597 || is_base64_char(str[2]) || str[3] == '=')
1598 return TRUE;
1599 return FALSE;
1600}
1601
1602
1603/*
1604 body = "(" (body-type-1part / body-type-mpart) ")"
1605*/
1606
1607static int mailimap_body_parse(mailstream * fd, MMAPString * buffer,
1608 size_t * index,
1609 struct mailimap_body ** result,
1610 size_t progr_rate,
1611 progress_function * progr_fun)
1612{
1613 struct mailimap_body_type_1part * body_type_1part;
1614 struct mailimap_body_type_mpart * body_type_mpart;
1615 struct mailimap_body * body;
1616 size_t cur_token;
1617 int type;
1618 int r;
1619 int res;
1620
1621 cur_token = * index;
1622
1623 body_type_1part = NULL;
1624 body_type_mpart = NULL;
1625
1626 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
1627 if (r != MAILIMAP_NO_ERROR) {
1628 res = r;
1629 goto err;
1630 }
1631
1632 type = MAILIMAP_BODY_ERROR; /* XXX - removes a gcc warning */
1633
1634 r = mailimap_body_type_1part_parse(fd, buffer, &cur_token, &body_type_1part,
1635 progr_rate, progr_fun);
1636 if (r == MAILIMAP_NO_ERROR)
1637 type = MAILIMAP_BODY_1PART;
1638
1639 if (r == MAILIMAP_ERROR_PARSE) {
1640 r = mailimap_body_type_mpart_parse(fd, buffer, &cur_token,
1641 &body_type_mpart,
1642 progr_rate, progr_fun);
1643
1644 if (r == MAILIMAP_NO_ERROR)
1645 type = MAILIMAP_BODY_MPART;
1646 }
1647
1648 if (r != MAILIMAP_NO_ERROR) {
1649 res = r;
1650 goto err;
1651 }
1652
1653 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
1654 if (r != MAILIMAP_NO_ERROR) {
1655 res = r;
1656 goto free;
1657 }
1658
1659 body = mailimap_body_new(type, body_type_1part, body_type_mpart);
1660 if (body == NULL) {
1661 res = MAILIMAP_ERROR_MEMORY;
1662 goto free;
1663 }
1664
1665 * result = body;
1666 * index = cur_token;
1667
1668 return MAILIMAP_NO_ERROR;
1669
1670 free:
1671 if (body_type_1part)
1672 mailimap_body_type_1part_free(body_type_1part);
1673 if (body_type_mpart)
1674 mailimap_body_type_mpart_free(body_type_mpart);
1675 err:
1676 return res;
1677}
1678
1679/*
1680 body-extension = nstring / number /
1681 "(" body-extension *(SP body-extension) ")"
1682 ; Future expansion. Client implementations
1683 ; MUST accept body-extension fields. Server
1684 ; implementations MUST NOT generate
1685 ; body-extension fields except as defined by
1686 ; future standard or standards-track
1687 ; revisions of this specification.
1688*/
1689
1690/*
1691 "(" body-extension *(SP body-extension) ")"
1692*/
1693
1694static int
1695mailimap_body_ext_list_parse(mailstream * fd, MMAPString * buffer,
1696 size_t * index,
1697 clist ** result,
1698 size_t progr_rate,
1699 progress_function * progr_fun)
1700{
1701 size_t cur_token;
1702 clist * list;
1703 int r;
1704 int res;
1705
1706 cur_token = * index;
1707
1708 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
1709 if (r != MAILIMAP_NO_ERROR) {
1710 res = r;
1711 goto err;
1712 }
1713
1714 r = mailimap_struct_spaced_list_parse(fd, buffer,
1715 &cur_token, &list,
1716 (mailimap_struct_parser * )
1717 mailimap_body_extension_parse,
1718 (mailimap_struct_destructor * )
1719 mailimap_body_extension_free,
1720 progr_rate, progr_fun);
1721 if (r != MAILIMAP_NO_ERROR) {
1722 res = r;
1723 goto err;
1724 }
1725
1726 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
1727 if (r != MAILIMAP_NO_ERROR) {
1728 res = r;
1729 goto free_list;
1730 }
1731
1732 * index = cur_token;
1733 * result = list;
1734
1735 return MAILIMAP_NO_ERROR;
1736
1737 free_list:
1738 clist_foreach(list, (clist_func) mailimap_body_extension_free, NULL);
1739 clist_free(list);
1740 err:
1741 return res;
1742}
1743
1744/*
1745 body-extension = nstring / number /
1746 "(" body-extension *(SP body-extension) ")"
1747 ; Future expansion. Client implementations
1748 ; MUST accept body-extension fields. Server
1749 ; implementations MUST NOT generate
1750 ; body-extension fields except as defined by
1751 ; future standard or standards-track
1752 ; revisions of this specification.
1753*/
1754
1755static int
1756mailimap_body_extension_parse(mailstream * fd, MMAPString * buffer,
1757 size_t * index,
1758 struct mailimap_body_extension ** result,
1759 size_t progr_rate,
1760 progress_function * progr_fun)
1761{
1762 size_t cur_token;
1763 uint32_t number;
1764 char * nstring;
1765 clist * body_extension_list;
1766 struct mailimap_body_extension * body_extension;
1767 int type;
1768 int r;
1769 int res;
1770
1771 cur_token = * index;
1772
1773 nstring = NULL;
1774 number = 0;
1775 body_extension_list = NULL;
1776 type = MAILIMAP_BODY_EXTENSION_ERROR; /* XXX - removes a gcc warning */
1777
1778 r = mailimap_nstring_parse(fd, buffer, &cur_token, &nstring, NULL,
1779 progr_rate, progr_fun);
1780 if (r == MAILIMAP_NO_ERROR)
1781 type = MAILIMAP_BODY_EXTENSION_NSTRING;
1782
1783 if (r == MAILIMAP_ERROR_PARSE) {
1784 r = mailimap_number_parse(fd, buffer, &cur_token, &number);
1785
1786 if (r == MAILIMAP_NO_ERROR)
1787 type = MAILIMAP_BODY_EXTENSION_NUMBER;
1788 }
1789
1790 if (r == MAILIMAP_ERROR_PARSE) {
1791 r = mailimap_body_ext_list_parse(fd, buffer, &cur_token,
1792 &body_extension_list,
1793 progr_rate, progr_fun);
1794
1795 if (r == MAILIMAP_NO_ERROR)
1796 type = MAILIMAP_BODY_EXTENSION_LIST;
1797 }
1798
1799 if (r != MAILIMAP_NO_ERROR) {
1800 res = r;
1801 goto err;
1802 }
1803
1804 body_extension = mailimap_body_extension_new(type, nstring, number,
1805 body_extension_list);
1806
1807 if (body_extension == NULL) {
1808 res = MAILIMAP_ERROR_MEMORY;
1809 goto free;
1810 }
1811
1812 * result = body_extension;
1813 * index = cur_token;
1814
1815 return MAILIMAP_NO_ERROR;
1816
1817 free:
1818 if (nstring != NULL)
1819 mailimap_nstring_free(nstring);
1820 if (body_extension_list) {
1821 clist_foreach(body_extension_list,
1822 (clist_func) mailimap_body_extension_free,
1823 NULL);
1824 clist_free(body_extension_list);
1825 }
1826 err:
1827 return res;
1828}
1829
1830/*
1831 body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang
1832 *(SP body-extension)]]
1833 ; MUST NOT be returned on non-extensible
1834 ; "BODY" fetch
1835*/
1836
1837/*
1838 *(SP body-extension)
1839*/
1840
1841static int
1842mailimap_body_ext_1part_3_parse(mailstream * fd, MMAPString * buffer,
1843 size_t * index,
1844 clist ** body_ext_list,
1845 size_t progr_rate,
1846 progress_function * progr_fun)
1847{
1848 size_t cur_token;
1849 int r;
1850
1851 cur_token = * index;
1852 * body_ext_list = NULL;
1853
1854 r = mailimap_space_parse(fd, buffer, &cur_token);
1855 if (r != MAILIMAP_NO_ERROR)
1856 return r;
1857
1858 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token,
1859 body_ext_list,
1860 (mailimap_struct_parser *)
1861 mailimap_body_extension_parse,
1862 (mailimap_struct_destructor *)
1863 mailimap_body_extension_free,
1864 progr_rate, progr_fun);
1865 if (r != MAILIMAP_NO_ERROR)
1866 return r;
1867
1868 * index = cur_token;
1869
1870 return MAILIMAP_NO_ERROR;
1871}
1872
1873
1874/*
1875 [SP body-fld-lang
1876 *(SP body-extension)]]
1877*/
1878
1879static int
1880mailimap_body_ext_1part_2_parse(mailstream * fd, MMAPString * buffer,
1881 size_t * index,
1882 struct mailimap_body_fld_lang ** fld_lang,
1883 clist ** body_ext_list,
1884 size_t progr_rate,
1885 progress_function * progr_fun)
1886{
1887 size_t cur_token;
1888 int r;
1889
1890 cur_token = * index;
1891 * fld_lang = NULL;
1892 * body_ext_list = NULL;
1893
1894 r = mailimap_space_parse(fd, buffer, &cur_token);
1895 if (r != MAILIMAP_NO_ERROR)
1896 return r;
1897
1898 r = mailimap_body_fld_lang_parse(fd, buffer, &cur_token, fld_lang,
1899 progr_rate, progr_fun);
1900 if (r != MAILIMAP_NO_ERROR)
1901 return r;
1902
1903 r = mailimap_body_ext_1part_3_parse(fd, buffer, &cur_token,
1904 body_ext_list, progr_rate, progr_fun);
1905 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE))
1906 return r;
1907
1908 * index = cur_token;
1909
1910 return MAILIMAP_NO_ERROR;
1911}
1912
1913
1914/*
1915 SP body-fld-dsp [SP body-fld-lang
1916 *(SP body-extension)]]
1917*/
1918
1919static int
1920mailimap_body_ext_1part_1_parse(mailstream * fd, MMAPString * buffer,
1921 size_t * index,
1922 struct mailimap_body_fld_dsp ** fld_dsp,
1923 struct mailimap_body_fld_lang ** fld_lang,
1924 clist ** body_ext_list,
1925 size_t progr_rate,
1926 progress_function * progr_fun)
1927{
1928 size_t cur_token;
1929 int r;
1930
1931 cur_token = * index;
1932 * fld_dsp = NULL;
1933 * fld_lang = NULL;
1934 * body_ext_list = NULL;
1935
1936 r = mailimap_space_parse(fd, buffer, &cur_token);
1937 if (r != MAILIMAP_NO_ERROR)
1938 return r;
1939
1940 r = mailimap_body_fld_dsp_parse(fd, buffer, &cur_token, fld_dsp,
1941 progr_rate, progr_fun);
1942 if (r != MAILIMAP_NO_ERROR)
1943 return r;
1944
1945 r = mailimap_body_ext_1part_2_parse(fd, buffer, &cur_token,
1946 fld_lang, body_ext_list,
1947 progr_rate, progr_fun);
1948 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE))
1949 return r;
1950
1951 * index = cur_token;
1952
1953 return MAILIMAP_NO_ERROR;
1954}
1955
1956/*
1957 body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang
1958 *(SP body-extension)]]
1959 ; MUST NOT be returned on non-extensible
1960 ; "BODY" fetch
1961*/
1962
1963static int
1964mailimap_body_ext_1part_parse(mailstream * fd, MMAPString * buffer,
1965 size_t * index,
1966 struct mailimap_body_ext_1part ** result,
1967 size_t progr_rate,
1968 progress_function * progr_fun)
1969{
1970 size_t cur_token;
1971
1972 char * fld_md5;
1973 struct mailimap_body_fld_dsp * fld_dsp;
1974 struct mailimap_body_fld_lang * fld_lang;
1975 clist * body_ext_list;
1976 int r;
1977 int res;
1978
1979 struct mailimap_body_ext_1part * ext_1part;
1980
1981 cur_token = * index;
1982
1983 fld_md5 = NULL;
1984 fld_dsp = NULL;
1985 fld_lang = NULL;
1986 body_ext_list = NULL;
1987
1988 r = mailimap_body_fld_md5_parse(fd, buffer, &cur_token, &fld_md5,
1989 progr_rate, progr_fun);
1990 if (r != MAILIMAP_NO_ERROR) {
1991 res = r;
1992 goto err;
1993 }
1994
1995 r = mailimap_body_ext_1part_1_parse(fd, buffer, &cur_token,
1996 &fld_dsp,
1997 &fld_lang,
1998 &body_ext_list,
1999 progr_rate, progr_fun);
2000 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
2001 res = r;
2002 goto free;
2003 }
2004
2005 ext_1part = mailimap_body_ext_1part_new(fld_md5, fld_dsp, fld_lang,
2006 body_ext_list);
2007
2008 if (ext_1part == NULL) {
2009 res = MAILIMAP_ERROR_MEMORY;
2010 goto free;
2011 }
2012
2013 * result = ext_1part;
2014 * index = cur_token;
2015
2016 return MAILIMAP_NO_ERROR;
2017
2018 free:
2019 if (body_ext_list) {
2020 clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free,
2021 NULL);
2022 clist_free(body_ext_list);
2023 }
2024 if (fld_lang)
2025 mailimap_body_fld_lang_free(fld_lang);
2026 if (fld_dsp)
2027 mailimap_body_fld_dsp_free(fld_dsp);
2028 mailimap_body_fld_md5_free(fld_md5);
2029 err:
2030 return res;
2031}
2032
2033
2034/*
2035 body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang
2036 *(SP body-extension)]]
2037 ; MUST NOT be returned on non-extensible
2038 ; "BODY" fetch
2039*/
2040
2041static int
2042mailimap_body_ext_mpart_parse(mailstream * fd, MMAPString * buffer,
2043 size_t * index,
2044 struct mailimap_body_ext_mpart ** result,
2045 size_t progr_rate,
2046 progress_function * progr_fun)
2047{
2048 size_t cur_token;
2049
2050 struct mailimap_body_fld_dsp * fld_dsp;
2051 struct mailimap_body_fld_lang * fld_lang;
2052 struct mailimap_body_fld_param * fld_param;
2053 clist * body_ext_list;
2054
2055 struct mailimap_body_ext_mpart * ext_mpart;
2056 int r;
2057 int res;
2058
2059 cur_token = * index;
2060
2061 fld_param = NULL;
2062 fld_dsp = NULL;
2063 fld_lang = NULL;
2064 body_ext_list = NULL;
2065
2066 r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, &fld_param,
2067 progr_rate, progr_fun);
2068 if (r != MAILIMAP_NO_ERROR) {
2069 res = r;
2070 goto err;
2071 }
2072
2073 r = mailimap_body_ext_1part_1_parse(fd, buffer, &cur_token,
2074 &fld_dsp,
2075 &fld_lang,
2076 &body_ext_list,
2077 progr_rate, progr_fun);
2078 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
2079 res = r;
2080 goto free;
2081 }
2082
2083 ext_mpart = mailimap_body_ext_mpart_new(fld_param, fld_dsp, fld_lang,
2084 body_ext_list);
2085 if (ext_mpart == NULL) {
2086 res = MAILIMAP_ERROR_MEMORY;
2087 goto free;
2088 }
2089
2090 * result = ext_mpart;
2091 * index = cur_token;
2092
2093 return MAILIMAP_NO_ERROR;
2094
2095 free:
2096 if (body_ext_list) {
2097 clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free,
2098 NULL);
2099 clist_free(body_ext_list);
2100 }
2101 if (fld_lang)
2102 mailimap_body_fld_lang_free(fld_lang);
2103 if (fld_dsp)
2104 mailimap_body_fld_dsp_free(fld_dsp);
2105 if (fld_param != NULL)
2106 mailimap_body_fld_param_free(fld_param);
2107 err:
2108 return res;
2109}
2110
2111/*
2112 body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP
2113 body-fld-enc SP body-fld-octets
2114*/
2115
2116static int
2117mailimap_body_fields_parse(mailstream * fd, MMAPString * buffer,
2118 size_t * index,
2119 struct mailimap_body_fields ** result,
2120 size_t progr_rate,
2121 progress_function * progr_fun)
2122{
2123 struct mailimap_body_fields * body_fields;
2124 size_t cur_token;
2125 struct mailimap_body_fld_param * body_fld_param;
2126 char * body_fld_id;
2127 char * body_fld_desc;
2128 struct mailimap_body_fld_enc * body_fld_enc;
2129 uint32_t body_fld_octets;
2130 int r;
2131 int res;
2132
2133 body_fld_param = NULL;
2134 body_fld_id = NULL;
2135 body_fld_desc = NULL;
2136 body_fld_enc = NULL;
2137 body_fld_octets = 0;
2138
2139 cur_token = * index;
2140
2141 r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, &body_fld_param,
2142 progr_rate, progr_fun);
2143 if (r != MAILIMAP_NO_ERROR) {
2144 res = r;
2145 goto err;
2146 }
2147
2148 r = mailimap_space_parse(fd, buffer, &cur_token);
2149 if (r != MAILIMAP_NO_ERROR) {
2150 res = r;
2151 goto fld_param_free;
2152 }
2153
2154 r = mailimap_body_fld_id_parse(fd, buffer, &cur_token, &body_fld_id,
2155 progr_rate, progr_fun);
2156 if (r != MAILIMAP_NO_ERROR) {
2157 res = r;
2158 goto fld_param_free;
2159 }
2160
2161 r = mailimap_space_parse(fd, buffer, &cur_token);
2162 if (r != MAILIMAP_NO_ERROR) {
2163 res = r;
2164 goto fld_id_free;
2165 }
2166
2167 r = mailimap_body_fld_desc_parse(fd, buffer, &cur_token, &body_fld_desc,
2168 progr_rate, progr_fun);
2169 if (r != MAILIMAP_NO_ERROR) {
2170 res = r;
2171 goto fld_id_free;
2172 }
2173
2174 r = mailimap_space_parse(fd, buffer, &cur_token);
2175 if (r != MAILIMAP_NO_ERROR) {
2176 res = r;
2177 goto fld_desc_free;
2178 }
2179
2180 r = mailimap_body_fld_enc_parse(fd, buffer, &cur_token, &body_fld_enc,
2181 progr_rate, progr_fun);
2182 if (r != MAILIMAP_NO_ERROR) {
2183 res = r;
2184 goto fld_desc_free;
2185 }
2186
2187 r = mailimap_space_parse(fd, buffer, &cur_token);
2188 if (r != MAILIMAP_NO_ERROR) {
2189 res = r;
2190 goto fld_enc_free;
2191 }
2192
2193 r = mailimap_body_fld_octets_parse(fd, buffer, &cur_token,
2194 &body_fld_octets);
2195 if (r != MAILIMAP_NO_ERROR) {
2196 res = r;
2197 goto fld_enc_free;
2198 }
2199
2200 body_fields = mailimap_body_fields_new(body_fld_param,
2201 body_fld_id,
2202 body_fld_desc,
2203 body_fld_enc,
2204 body_fld_octets);
2205 if (body_fields == NULL) {
2206 res = MAILIMAP_ERROR_MEMORY;
2207 goto fld_enc_free;
2208 }
2209
2210 * result = body_fields;
2211 * index = cur_token;
2212
2213 return MAILIMAP_NO_ERROR;
2214
2215 fld_enc_free:
2216 mailimap_body_fld_enc_free(body_fld_enc);
2217 fld_desc_free:
2218 mailimap_body_fld_desc_free(body_fld_desc);
2219 fld_id_free:
2220 mailimap_body_fld_id_free(body_fld_id);
2221 fld_param_free:
2222 if (body_fld_param != NULL)
2223 mailimap_body_fld_param_free(body_fld_param);
2224 err:
2225 return res;
2226}
2227
2228/*
2229 body-fld-desc = nstring
2230*/
2231
2232static int mailimap_body_fld_desc_parse(mailstream * fd, MMAPString * buffer,
2233 size_t * index, char ** result,
2234 size_t progr_rate,
2235 progress_function * progr_fun)
2236{
2237 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
2238 progr_rate, progr_fun);
2239}
2240
2241/*
2242 body-fld-dsp = "(" string SP body-fld-param ")" / nil
2243*/
2244
2245static int
2246mailimap_body_fld_dsp_parse(mailstream * fd, MMAPString * buffer,
2247 size_t * index,
2248 struct mailimap_body_fld_dsp ** result,
2249 size_t progr_rate,
2250 progress_function * progr_fun)
2251{
2252 size_t cur_token;
2253 char * name;
2254 struct mailimap_body_fld_param * body_fld_param;
2255 struct mailimap_body_fld_dsp * body_fld_dsp;
2256 int res;
2257 int r;
2258
2259 cur_token = * index;
2260 name = NULL;
2261 body_fld_param = NULL;
2262
2263 r = mailimap_nil_parse(fd, buffer, &cur_token);
2264 if (r == MAILIMAP_NO_ERROR) {
2265 * result = NULL;
2266 * index = cur_token;
2267 return MAILIMAP_NO_ERROR;
2268 }
2269
2270 if (r != MAILIMAP_ERROR_PARSE) {
2271 res = r;
2272 goto err;
2273 }
2274
2275 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
2276 if (r != MAILIMAP_NO_ERROR) {
2277 res = r;
2278 goto err;
2279 }
2280
2281 r = mailimap_string_parse(fd, buffer, &cur_token, &name, NULL,
2282 progr_rate, progr_fun);
2283 if (r != MAILIMAP_NO_ERROR) {
2284 res = r;
2285 goto err;
2286 }
2287
2288 r = mailimap_space_parse(fd, buffer, &cur_token);
2289 if (r != MAILIMAP_NO_ERROR) {
2290 res = r;
2291 goto string_free;
2292 }
2293
2294 r = mailimap_body_fld_param_parse(fd, buffer, &cur_token,
2295 &body_fld_param,
2296 progr_rate, progr_fun);
2297 if (r != MAILIMAP_NO_ERROR) {
2298 res = r;
2299 goto string_free;
2300 }
2301
2302 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
2303 if (r != MAILIMAP_NO_ERROR) {
2304 res = r;
2305 goto string_free;
2306 }
2307
2308 body_fld_dsp = mailimap_body_fld_dsp_new(name, body_fld_param);
2309 if (body_fld_dsp == NULL) {
2310 res = MAILIMAP_ERROR_MEMORY;
2311 goto fld_param_free;
2312 }
2313
2314 * index = cur_token;
2315 * result = body_fld_dsp;
2316
2317 return MAILIMAP_NO_ERROR;
2318
2319 fld_param_free:
2320 if (body_fld_param != NULL)
2321 mailimap_body_fld_param_free(body_fld_param);
2322 string_free:
2323 mailimap_string_free(name);
2324 err:
2325 return res;
2326}
2327
2328/*
2329 body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/
2330 "QUOTED-PRINTABLE") DQUOTE) / string
2331*/
2332
2333static inline int
2334mailimap_body_fld_known_enc_parse(mailstream * fd, MMAPString * buffer,
2335 size_t * index,
2336 int * result,
2337 size_t progr_rate,
2338 progress_function * progr_fun)
2339{
2340 size_t cur_token;
2341 int type;
2342 int r;
2343 int res;
2344
2345 cur_token = * index;
2346
2347 r = mailimap_dquote_parse(fd, buffer, &cur_token);
2348 if (r != MAILIMAP_NO_ERROR) {
2349 res = r;
2350 goto err;
2351 }
2352
2353 type = mailimap_encoding_get_token_value(fd, buffer, &cur_token);
2354
2355 if (type == -1) {
2356 res = MAILIMAP_ERROR_PARSE;
2357 goto err;
2358 }
2359
2360 r = mailimap_dquote_parse(fd, buffer, &cur_token);
2361 if (r != MAILIMAP_NO_ERROR) {
2362 res = r;
2363 goto err;
2364 }
2365
2366 * result = type;
2367 * index = cur_token;
2368
2369 return MAILIMAP_NO_ERROR;
2370
2371 err:
2372 return res;
2373}
2374
2375static int
2376mailimap_body_fld_enc_parse(mailstream * fd, MMAPString * buffer,
2377 size_t * index,
2378 struct mailimap_body_fld_enc ** result,
2379 size_t progr_rate,
2380 progress_function * progr_fun)
2381{
2382 size_t cur_token;
2383 int type;
2384 char * value;
2385 struct mailimap_body_fld_enc * body_fld_enc;
2386 int r;
2387 int res;
2388
2389 cur_token = * index;
2390
2391 r = mailimap_body_fld_known_enc_parse(fd, buffer, &cur_token,
2392 &type, progr_rate, progr_fun);
2393 if (r == MAILIMAP_NO_ERROR) {
2394 value = NULL;
2395 }
2396 else if (r == MAILIMAP_ERROR_PARSE) {
2397 type = MAILIMAP_BODY_FLD_ENC_OTHER;
2398
2399 r = mailimap_string_parse(fd, buffer, &cur_token, &value, NULL,
2400 progr_rate, progr_fun);
2401 if (r != MAILIMAP_NO_ERROR) {
2402 res = r;
2403 goto err;
2404 }
2405 }
2406 else {
2407 res = r;
2408 goto err;
2409 }
2410
2411 body_fld_enc = mailimap_body_fld_enc_new(type, value);
2412 if (body_fld_enc == NULL) {
2413 res = MAILIMAP_ERROR_MEMORY;
2414 goto value_free;
2415 }
2416
2417 * result = body_fld_enc;
2418 * index = cur_token;
2419
2420 return MAILIMAP_NO_ERROR;
2421
2422 value_free:
2423 if (value)
2424 mailimap_string_free(value);
2425 err:
2426 return res;
2427}
2428
2429/*
2430 body-fld-id = nstring
2431*/
2432
2433static int mailimap_body_fld_id_parse(mailstream * fd, MMAPString * buffer,
2434 size_t * index, char ** result,
2435 size_t progr_rate,
2436 progress_function * progr_fun)
2437{
2438 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
2439 progr_rate, progr_fun);
2440}
2441
2442
2443/*
2444 body-fld-lang = nstring / "(" string *(SP string) ")"
2445*/
2446
2447/*
2448"(" string *(SP string) ")"
2449*/
2450
2451static int
2452mailimap_body_fld_lang_list_parse(mailstream * fd, MMAPString * buffer,
2453 size_t * index, clist ** result,
2454 size_t progr_rate,
2455 progress_function * progr_fun)
2456{
2457 size_t cur_token;
2458 clist * list;
2459 int r;
2460 int res;
2461
2462 cur_token = * index;
2463
2464 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
2465 if (r != MAILIMAP_NO_ERROR) {
2466 res = r;
2467 goto err;
2468 }
2469
2470 list = clist_new();
2471 if (list == NULL) {
2472 res = MAILIMAP_ERROR_MEMORY;
2473 goto err;
2474 }
2475
2476 while (1) {
2477 char * elt;
2478
2479 r = mailimap_string_parse(fd, buffer, &cur_token, &elt, NULL,
2480 progr_rate, progr_fun);
2481 if (r != MAILIMAP_ERROR_PARSE)
2482 break;
2483 else if (r == MAILIMAP_NO_ERROR) {
2484 r = clist_append(list, elt);
2485 if (r < 0) {
2486 mailimap_string_free(elt);
2487 res = r;
2488 goto list_free;
2489 }
2490 }
2491 else {
2492 res = r;
2493 goto list_free;
2494 }
2495 }
2496
2497 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
2498 if (r != MAILIMAP_NO_ERROR) {
2499 res = r;
2500 goto list_free;
2501 }
2502
2503 * index = cur_token;
2504 * result = list;
2505
2506 return MAILIMAP_NO_ERROR;
2507
2508 list_free:
2509 clist_foreach(list, (clist_func) mailimap_string_free, NULL);
2510 clist_free(list);
2511 err:
2512 return res;
2513}
2514
2515/*
2516 body-fld-lang = nstring / "(" string *(SP string) ")"
2517*/
2518
2519static int
2520mailimap_body_fld_lang_parse(mailstream * fd, MMAPString * buffer,
2521 size_t * index,
2522 struct mailimap_body_fld_lang ** result,
2523 size_t progr_rate,
2524 progress_function * progr_fun)
2525{
2526 char * value;
2527 clist * list;
2528 struct mailimap_body_fld_lang * fld_lang;
2529 int type;
2530 int r;
2531 int res;
2532
2533 size_t cur_token;
2534
2535 cur_token = * index;
2536
2537 value = NULL;
2538 list = NULL;
2539 type = MAILIMAP_BODY_FLD_LANG_ERROR; /* XXX - removes a gcc warning */
2540
2541 r = mailimap_nstring_parse(fd, buffer, &cur_token, &value, NULL,
2542 progr_rate, progr_fun);
2543 if (r == MAILIMAP_NO_ERROR)
2544 type = MAILIMAP_BODY_FLD_LANG_SINGLE;
2545
2546 if (r == MAILIMAP_ERROR_PARSE) {
2547 r = mailimap_body_fld_lang_list_parse(fd, buffer, &cur_token, &list,
2548 progr_rate, progr_fun);
2549 if (r == MAILIMAP_NO_ERROR)
2550 type = MAILIMAP_BODY_FLD_LANG_LIST;
2551 }
2552
2553 if (r != MAILIMAP_NO_ERROR) {
2554 res = r;
2555 goto err;
2556 }
2557
2558 fld_lang = mailimap_body_fld_lang_new(type, value, list);
2559 if (fld_lang == NULL) {
2560 res = MAILIMAP_ERROR_MEMORY;
2561 goto free;
2562 }
2563
2564 * index = cur_token;
2565 * result = fld_lang;
2566
2567 return MAILIMAP_NO_ERROR;
2568
2569 free:
2570 if (value)
2571 mailimap_nstring_free(value);
2572 if (list) {
2573 clist_foreach(list, (clist_func) mailimap_string_free, NULL);
2574 clist_free(list);
2575 }
2576 err:
2577 return res;
2578}
2579
2580/*
2581 body-fld-lines = number
2582*/
2583
2584static int mailimap_body_fld_lines_parse(mailstream * fd,
2585 MMAPString * buffer, size_t * index,
2586 uint32_t * result)
2587{
2588 return mailimap_number_parse(fd, buffer, index, result);
2589}
2590
2591/*
2592 body-fld-md5 = nstring
2593*/
2594
2595static int mailimap_body_fld_md5_parse(mailstream * fd, MMAPString * buffer,
2596 size_t * index, char ** result,
2597 size_t progr_rate,
2598 progress_function * progr_fun)
2599{
2600 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
2601 progr_rate, progr_fun);
2602}
2603
2604/*
2605 body-fld-octets = number
2606*/
2607
2608static int mailimap_body_fld_octets_parse(mailstream * fd,
2609 MMAPString * buffer, size_t * index,
2610 uint32_t * result)
2611{
2612 return mailimap_number_parse(fd, buffer, index, result);
2613}
2614
2615/*
2616 body-fld-param = "(" string SP string *(SP string SP string) ")" / nil
2617*/
2618
2619/*
2620 string SP string
2621*/
2622
2623static int
2624mailimap_single_body_fld_param_parse(mailstream * fd, MMAPString * buffer,
2625 size_t * index,
2626 struct mailimap_single_body_fld_param **
2627 result,
2628 size_t progr_rate,
2629 progress_function * progr_fun)
2630{
2631 struct mailimap_single_body_fld_param * param;
2632 char * name;
2633 char * value;
2634 size_t cur_token;
2635 int r;
2636 int res;
2637
2638 cur_token = * index;
2639
2640 name = NULL;
2641 value = NULL;
2642
2643 r = mailimap_string_parse(fd, buffer, &cur_token, &name, NULL,
2644 progr_rate, progr_fun);
2645 if (r != MAILIMAP_NO_ERROR) {
2646 res = r;
2647 goto err;
2648 }
2649
2650 r = mailimap_space_parse(fd, buffer, &cur_token);
2651 if (r != MAILIMAP_NO_ERROR) {
2652 res = r;
2653 goto free_name;
2654 }
2655
2656 r = mailimap_string_parse(fd, buffer, &cur_token, &value, NULL,
2657 progr_rate, progr_fun);
2658 if (r != MAILIMAP_NO_ERROR) {
2659 res = r;
2660 goto free_name;
2661 }
2662
2663 param = mailimap_single_body_fld_param_new(name, value);
2664 if (param == NULL) {
2665 res = MAILIMAP_ERROR_MEMORY;
2666 goto free_value;
2667 }
2668
2669 * result = param;
2670 * index = cur_token;
2671
2672 return MAILIMAP_NO_ERROR;
2673
2674 free_value:
2675 mailimap_string_free(name);
2676 free_name:
2677 mailimap_string_free(value);
2678 err:
2679 return res;
2680}
2681
2682/*
2683 body-fld-param = "(" string SP string *(SP string SP string) ")" / nil
2684*/
2685
2686static int
2687mailimap_body_fld_param_parse(mailstream * fd,
2688 MMAPString * buffer, size_t * index,
2689 struct mailimap_body_fld_param ** result,
2690 size_t progr_rate,
2691 progress_function * progr_fun)
2692{
2693 size_t cur_token;
2694 clist * param_list;
2695 struct mailimap_body_fld_param * fld_param;
2696 int r;
2697 int res;
2698
2699 param_list = NULL;
2700 cur_token = * index;
2701
2702 r = mailimap_nil_parse(fd, buffer, &cur_token);
2703 if (r == MAILIMAP_NO_ERROR) {
2704 * result = NULL;
2705 * index = cur_token;
2706 return MAILIMAP_NO_ERROR;
2707 }
2708
2709 if (r != MAILIMAP_ERROR_PARSE) {
2710 res = r;
2711 goto err;
2712 }
2713
2714 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
2715 if (r != MAILIMAP_NO_ERROR) {
2716 res = r;
2717 goto err;
2718 }
2719
2720 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &param_list,
2721 (mailimap_struct_parser *)
2722 mailimap_single_body_fld_param_parse,
2723 (mailimap_struct_destructor *)
2724 mailimap_single_body_fld_param_free,
2725 progr_rate, progr_fun);
2726 if (r != MAILIMAP_NO_ERROR) {
2727 res = r;
2728 goto err;
2729 }
2730
2731 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
2732 if (r != MAILIMAP_NO_ERROR) {
2733 res = r;
2734 goto free;
2735 }
2736
2737 fld_param = mailimap_body_fld_param_new(param_list);
2738 if (fld_param == NULL) {
2739 res = MAILIMAP_ERROR_MEMORY;
2740 goto free;
2741 }
2742
2743 * index = cur_token;
2744 * result = fld_param;
2745
2746 return MAILIMAP_NO_ERROR;
2747
2748 free:
2749 clist_foreach(param_list,
2750 (clist_func) mailimap_single_body_fld_param_free,
2751 NULL);
2752 clist_free(param_list);
2753 err:
2754 return res;
2755}
2756
2757/*
2758 body-type-1part = (body-type-basic / body-type-msg / body-type-text)
2759 [SP body-ext-1part]
2760*/
2761
2762static int
2763mailimap_body_type_1part_parse(mailstream * fd, MMAPString * buffer,
2764 size_t * index,
2765 struct mailimap_body_type_1part ** result,
2766 size_t progr_rate,
2767 progress_function * progr_fun)
2768{
2769 size_t cur_token;
2770 struct mailimap_body_type_1part * body_type_1part;
2771 struct mailimap_body_type_basic * body_type_basic;
2772 struct mailimap_body_type_msg * body_type_msg;
2773 struct mailimap_body_type_text * body_type_text;
2774 struct mailimap_body_ext_1part * body_ext_1part;
2775 int type;
2776 size_t final_token;
2777 int r;
2778 int res;
2779
2780 cur_token = * index;
2781
2782 body_type_basic = NULL;
2783 body_type_msg = NULL;
2784 body_type_text = NULL;
2785 body_ext_1part = NULL;
2786
2787 type = MAILIMAP_BODY_TYPE_1PART_ERROR; /* XXX - removes a gcc warning */
2788
2789 r = mailimap_body_type_msg_parse(fd, buffer, &cur_token,
2790 &body_type_msg,
2791 progr_rate, progr_fun);
2792 if (r == MAILIMAP_NO_ERROR)
2793 type = MAILIMAP_BODY_TYPE_1PART_MSG;
2794
2795 if (r == MAILIMAP_ERROR_PARSE) {
2796 r = mailimap_body_type_text_parse(fd, buffer, &cur_token,
2797 &body_type_text,
2798 progr_rate, progr_fun);
2799 if (r == MAILIMAP_NO_ERROR)
2800 type = MAILIMAP_BODY_TYPE_1PART_TEXT;
2801 }
2802
2803 if (r == MAILIMAP_ERROR_PARSE) {
2804 r = mailimap_body_type_basic_parse(fd, buffer, &cur_token,
2805 &body_type_basic,
2806 progr_rate, progr_fun);
2807 if (r == MAILIMAP_NO_ERROR)
2808 type = MAILIMAP_BODY_TYPE_1PART_BASIC;
2809 }
2810
2811 if (r != MAILIMAP_NO_ERROR) {
2812 res = r;
2813 goto err;
2814 }
2815
2816 final_token = cur_token;
2817 body_ext_1part = NULL;
2818
2819 r = mailimap_space_parse(fd, buffer, &cur_token);
2820
2821 if (r == MAILIMAP_NO_ERROR) {
2822 r = mailimap_body_ext_1part_parse(fd, buffer, &cur_token, &body_ext_1part,
2823 progr_rate, progr_fun);
2824 if (r == MAILIMAP_NO_ERROR)
2825 final_token = cur_token;
2826 else if (r == MAILIMAP_ERROR_PARSE) {
2827 /* do nothing */
2828 }
2829 else {
2830 res = r;
2831 goto free;
2832 }
2833 }
2834 else if (r == MAILIMAP_ERROR_PARSE) {
2835 /* do nothing */
2836 }
2837 else {
2838 res = r;
2839 goto free;
2840 }
2841
2842 body_type_1part = mailimap_body_type_1part_new(type, body_type_basic,
2843 body_type_msg, body_type_text,
2844 body_ext_1part);
2845 if (body_type_1part == NULL) {
2846 res = MAILIMAP_ERROR_MEMORY;
2847 goto free;
2848 }
2849
2850 * index = final_token;
2851 * result = body_type_1part;
2852
2853 return MAILIMAP_NO_ERROR;
2854
2855 free:
2856 if (body_type_basic)
2857 mailimap_body_type_basic_free(body_type_basic);
2858 if (body_type_msg)
2859 mailimap_body_type_msg_free(body_type_msg);
2860 if (body_type_text)
2861 mailimap_body_type_text_free(body_type_text);
2862 if (body_ext_1part)
2863 mailimap_body_ext_1part_free(body_ext_1part);
2864 err:
2865 return res;
2866}
2867
2868/*
2869 body-type-basic = media-basic SP body-fields
2870 ; MESSAGE subtype MUST NOT be "RFC822"
2871*/
2872
2873static int
2874mailimap_body_type_basic_parse(mailstream * fd, MMAPString * buffer,
2875 size_t * index,
2876 struct mailimap_body_type_basic ** result,
2877 size_t progr_rate,
2878 progress_function * progr_fun)
2879{
2880 size_t cur_token;
2881 struct mailimap_body_type_basic * body_type_basic;
2882 struct mailimap_media_basic * media_basic;
2883 struct mailimap_body_fields * body_fields;
2884 int r;
2885 int res;
2886
2887 cur_token = * index;
2888
2889 media_basic = NULL;
2890 body_fields = NULL;
2891
2892 r = mailimap_media_basic_parse(fd, buffer, &cur_token, &media_basic,
2893 progr_rate, progr_fun);
2894 if (r != MAILIMAP_NO_ERROR) {
2895 res = r;
2896 goto err;
2897 }
2898
2899 r = mailimap_space_parse(fd, buffer, &cur_token);
2900 if (r != MAILIMAP_NO_ERROR) {
2901 res = r;
2902 goto free_media_basic;
2903 }
2904
2905 r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields,
2906 progr_rate, progr_fun);
2907 if (r != MAILIMAP_NO_ERROR) {
2908 res = r;
2909 goto free_media_basic;
2910 }
2911
2912 body_type_basic = mailimap_body_type_basic_new(media_basic, body_fields);
2913 if (body_type_basic == NULL) {
2914 res = MAILIMAP_ERROR_MEMORY;
2915 goto free_body_fields;
2916 }
2917
2918 * index = cur_token;
2919 * result = body_type_basic;
2920
2921 return MAILIMAP_NO_ERROR;
2922
2923 free_body_fields:
2924 mailimap_body_fields_free(body_fields);
2925 free_media_basic:
2926 mailimap_media_basic_free(media_basic);
2927 err:
2928 return res;
2929}
2930
2931/*
2932 body-type-mpart = 1*body SP media-subtype
2933 [SP body-ext-mpart]
2934*/
2935
2936static int
2937mailimap_body_type_mpart_parse(mailstream * fd,
2938 MMAPString * buffer,
2939 size_t * index,
2940 struct mailimap_body_type_mpart ** result,
2941 size_t progr_rate,
2942 progress_function * progr_fun)
2943{
2944 struct mailimap_body_type_mpart * body_type_mpart;
2945 clist * body_list;
2946 size_t cur_token;
2947 size_t final_token;
2948 char * media_subtype;
2949 struct mailimap_body_ext_mpart * body_ext_mpart;
2950 int r;
2951 int res;
2952
2953 cur_token = * index;
2954
2955 body_list = NULL;
2956 media_subtype = NULL;
2957 body_ext_mpart = NULL;
2958
2959 r = mailimap_struct_multiple_parse(fd, buffer, &cur_token,
2960 &body_list,
2961 (mailimap_struct_parser *)
2962 mailimap_body_parse,
2963 (mailimap_struct_destructor *)
2964 mailimap_body_free,
2965 progr_rate, progr_fun);
2966 if (r != MAILIMAP_NO_ERROR) {
2967 res = r;
2968 goto err;
2969 }
2970
2971 r = mailimap_space_parse(fd, buffer, &cur_token);
2972 if (r != MAILIMAP_NO_ERROR) {
2973 res = r;
2974 goto free_body_list;
2975 }
2976
2977 r = mailimap_media_subtype_parse(fd, buffer, &cur_token, &media_subtype,
2978 progr_rate, progr_fun);
2979 if (r != MAILIMAP_NO_ERROR) {
2980 res = r;
2981 goto free_body_list;
2982 }
2983
2984 final_token = cur_token;
2985
2986 body_ext_mpart = NULL;
2987
2988 r = mailimap_space_parse(fd, buffer, &cur_token);
2989 if (r == MAILIMAP_NO_ERROR) {
2990 r = mailimap_body_ext_mpart_parse(fd, buffer, &cur_token, &body_ext_mpart,
2991 progr_rate, progr_fun);
2992 if (r == MAILIMAP_NO_ERROR)
2993 final_token = cur_token;
2994 else if (r == MAILIMAP_ERROR_PARSE) {
2995 /* do nothing */
2996 }
2997 else {
2998 res = r;
2999 goto free_body_list;
3000 }
3001 }
3002 else if (r == MAILIMAP_ERROR_PARSE) {
3003 /* do nothing */
3004 }
3005 else {
3006 res = r;
3007 goto free_body_list;
3008 }
3009
3010 body_type_mpart = mailimap_body_type_mpart_new(body_list, media_subtype,
3011 body_ext_mpart);
3012 if (body_type_mpart == NULL) {
3013 res = MAILIMAP_ERROR_MEMORY;
3014 goto free_body_ext_mpart;
3015 }
3016
3017 * result = body_type_mpart;
3018 * index = final_token;
3019
3020 return MAILIMAP_NO_ERROR;
3021
3022 free_body_ext_mpart:
3023 if (body_ext_mpart)
3024 mailimap_body_ext_mpart_free(body_ext_mpart);
3025 mailimap_media_subtype_free(media_subtype);
3026 free_body_list:
3027 clist_foreach(body_list, (clist_func) mailimap_body_free, NULL);
3028 clist_free(body_list);
3029 err:
3030 return res;
3031}
3032
3033/*
3034 body-type-msg = media-message SP body-fields SP envelope
3035 SP body SP body-fld-lines
3036*/
3037
3038static int
3039mailimap_body_type_msg_parse(mailstream * fd, MMAPString * buffer,
3040 size_t * index,
3041 struct mailimap_body_type_msg ** result,
3042 size_t progr_rate,
3043 progress_function * progr_fun)
3044{
3045 struct mailimap_body_fields * body_fields;
3046 struct mailimap_envelope * envelope;
3047 struct mailimap_body * body;
3048 uint32_t body_fld_lines;
3049 struct mailimap_body_type_msg * body_type_msg;
3050 size_t cur_token;
3051 int r;
3052 int res;
3053
3054 cur_token = * index;
3055
3056 body_fields = NULL;
3057 envelope = NULL;
3058 body = NULL;
3059 body_fld_lines = 0;
3060
3061 r = mailimap_media_message_parse(fd, buffer, &cur_token);
3062 if (r != MAILIMAP_NO_ERROR) {
3063 res = r;
3064 goto err;
3065 }
3066
3067 r = mailimap_space_parse(fd, buffer, &cur_token);
3068 if (r != MAILIMAP_NO_ERROR) {
3069 res = r;
3070 goto err;
3071 }
3072
3073 r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields,
3074 progr_rate, progr_fun);
3075 if (r != MAILIMAP_NO_ERROR) {
3076 res = r;
3077 goto err;
3078 }
3079
3080 r = mailimap_space_parse(fd, buffer, &cur_token);
3081 if (r != MAILIMAP_NO_ERROR) {
3082 res = r;
3083 goto body_fields;
3084 }
3085
3086 r = mailimap_envelope_parse(fd, buffer, &cur_token, &envelope,
3087 progr_rate, progr_fun);
3088 if (r != MAILIMAP_NO_ERROR) {
3089 res = r;
3090 goto body_fields;
3091 }
3092
3093 r = mailimap_space_parse(fd, buffer, &cur_token);
3094 if (r != MAILIMAP_NO_ERROR) {
3095 res = r;
3096 goto envelope;
3097 }
3098
3099 r = mailimap_body_parse(fd, buffer, &cur_token, &body,
3100 progr_rate, progr_fun);
3101 if (r != MAILIMAP_NO_ERROR) {
3102 res = r;
3103 goto envelope;
3104 }
3105
3106 r = mailimap_space_parse(fd, buffer, &cur_token);
3107 if (r != MAILIMAP_NO_ERROR) {
3108 res = r;
3109 goto body;
3110 }
3111
3112 r = mailimap_body_fld_lines_parse(fd, buffer, &cur_token,
3113 &body_fld_lines);
3114 if (r != MAILIMAP_NO_ERROR) {
3115 res = r;
3116 goto body;
3117 }
3118
3119 body_type_msg = mailimap_body_type_msg_new(body_fields, envelope,
3120 body, body_fld_lines);
3121 if (body_type_msg == NULL) {
3122 res = MAILIMAP_ERROR_MEMORY;
3123 goto body;
3124 }
3125
3126 * result = body_type_msg;
3127 * index = cur_token;
3128
3129 return MAILIMAP_NO_ERROR;
3130
3131 body:
3132 mailimap_body_free(body);
3133 envelope:
3134 mailimap_envelope_free(envelope);
3135 body_fields:
3136 mailimap_body_fields_free(body_fields);
3137 err:
3138 return res;
3139}
3140
3141/*
3142 body-type-text = media-text SP body-fields SP body-fld-lines
3143*/
3144
3145static int
3146mailimap_body_type_text_parse(mailstream * fd, MMAPString * buffer,
3147 size_t * index,
3148 struct mailimap_body_type_text **
3149 result,
3150 size_t progr_rate,
3151 progress_function * progr_fun)
3152{
3153 char * media_text;
3154 struct mailimap_body_fields * body_fields;
3155 uint32_t body_fld_lines;
3156 struct mailimap_body_type_text * body_type_text;
3157 size_t cur_token;
3158 int r;
3159 int res;
3160
3161 media_text = NULL;
3162 body_fields = NULL;
3163 body_fld_lines = 0;
3164
3165 cur_token = * index;
3166
3167 r = mailimap_media_text_parse(fd, buffer, &cur_token, &media_text,
3168 progr_rate, progr_fun);
3169 if (r != MAILIMAP_NO_ERROR) {
3170 res = r;
3171 goto err;
3172 }
3173
3174 r = mailimap_space_parse(fd, buffer, &cur_token);
3175 if (r != MAILIMAP_NO_ERROR) {
3176 res = r;
3177 goto free_media_text;
3178 }
3179
3180 r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields,
3181 progr_rate, progr_fun);
3182 if (r != MAILIMAP_NO_ERROR) {
3183 res = r;
3184 goto free_media_text;
3185 }
3186
3187 r = mailimap_space_parse(fd, buffer, &cur_token);
3188 if (r != MAILIMAP_NO_ERROR) {
3189 res = r;
3190 goto free_body_fields;
3191 }
3192
3193 r = mailimap_body_fld_lines_parse(fd, buffer, &cur_token, &body_fld_lines);
3194 if (r != MAILIMAP_NO_ERROR) {
3195 res = r;
3196 goto free_body_fields;
3197 }
3198
3199 body_type_text = mailimap_body_type_text_new(media_text, body_fields,
3200 body_fld_lines);
3201 if (body_type_text == NULL) {
3202 res = MAILIMAP_ERROR_MEMORY;
3203 goto free_body_fields;
3204 }
3205
3206 * result = body_type_text;
3207 * index = cur_token;
3208
3209 return MAILIMAP_NO_ERROR;
3210
3211 free_body_fields:
3212 mailimap_body_fields_free(body_fields);
3213 free_media_text:
3214 mailimap_media_text_free(media_text);
3215 err:
3216 return res;
3217}
3218
3219
3220/*
3221 capability = ("AUTH=" auth-type) / atom
3222 ; New capabilities MUST begin with "X" or be
3223 ; registered with IANA as standard or
3224 ; standards-track
3225*/
3226
3227static int
3228mailimap_capability_parse(mailstream * fd, MMAPString * buffer,
3229 size_t * index,
3230 struct mailimap_capability ** result,
3231 size_t progr_rate,
3232 progress_function * progr_fun)
3233{
3234 size_t cur_token;
3235 int type;
3236 char * auth_type;
3237 char * atom;
3238 struct mailimap_capability * cap;
3239 int r;
3240 int res;
3241
3242 cur_token = * index;
3243
3244 auth_type = NULL;
3245 atom = NULL;
3246
3247 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "AUTH=");
3248 switch (r) {
3249 case MAILIMAP_NO_ERROR:
3250 type = MAILIMAP_CAPABILITY_AUTH_TYPE;
3251
3252 r = mailimap_auth_type_parse(fd, buffer, &cur_token, &auth_type,
3253 progr_rate, progr_fun);
3254 if (r != MAILIMAP_NO_ERROR) {
3255 res = r;
3256 goto err;
3257 }
3258 break;
3259
3260 case MAILIMAP_ERROR_PARSE:
3261 r = mailimap_atom_parse(fd, buffer, &cur_token, &atom,
3262 progr_rate, progr_fun);
3263 if (r != MAILIMAP_NO_ERROR) {
3264 res = r;
3265 goto err;
3266 }
3267
3268 type = MAILIMAP_CAPABILITY_NAME;
3269 break;
3270
3271 default:
3272 res = r;
3273 goto err;
3274 }
3275
3276 cap = mailimap_capability_new(type, auth_type, atom);
3277 if (cap == NULL) {
3278 res = MAILIMAP_ERROR_MEMORY;
3279 goto free;
3280 }
3281
3282 * result = cap;
3283 * index = cur_token;
3284
3285 return MAILIMAP_NO_ERROR;
3286
3287 free:
3288 if (auth_type)
3289 mailimap_auth_type_free(auth_type);
3290 if (atom)
3291 mailimap_atom_free(atom);
3292 err:
3293 return res;
3294}
3295
3296/*
3297 capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1"
3298 *(SP capability)
3299 ; IMAP4rev1 servers which offer RFC 1730
3300 ; compatibility MUST list "IMAP4" as the first
3301 ; capability.
3302*/
3303
3304/*
3305 SP capability *(SP capability)
3306*/
3307
3308static int mailimap_capability_list_parse(mailstream * fd,
3309 MMAPString * buffer,
3310 size_t * index,
3311 clist ** result,
3312 size_t progr_rate,
3313 progress_function * progr_fun)
3314{
3315 size_t cur_token;
3316 clist * list;
3317 int r;
3318
3319 cur_token = * index;
3320
3321 r = mailimap_space_parse(fd, buffer, &cur_token);
3322 if (r != MAILIMAP_NO_ERROR)
3323 return r;
3324
3325 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list,
3326 (mailimap_struct_parser *)
3327 mailimap_capability_parse,
3328 (mailimap_struct_destructor *)
3329 mailimap_capability_free,
3330 progr_rate, progr_fun);
3331 if (r != MAILIMAP_NO_ERROR)
3332 return r;
3333
3334 * index = cur_token;
3335 * result = list;
3336
3337 return MAILIMAP_NO_ERROR;
3338}
3339
3340static int
3341mailimap_capability_data_parse(mailstream * fd, MMAPString * buffer,
3342 size_t * index,
3343 struct mailimap_capability_data ** result,
3344 size_t progr_rate,
3345 progress_function * progr_fun)
3346{
3347 size_t cur_token;
3348 clist * cap_list;
3349#if 0
3350 clist * cap_list_2;
3351#endif
3352 struct mailimap_capability_data * cap_data;
3353 int r;
3354 int res;
3355
3356 cur_token = * index;
3357
3358 cap_list = NULL;
3359#if 0
3360 cap_list_2 = NULL;
3361#endif
3362
3363 r = mailimap_token_case_insensitive_parse(fd, buffer,
3364 &cur_token, "CAPABILITY");
3365 if (r != MAILIMAP_NO_ERROR) {
3366 res = r;
3367 goto err;
3368 }
3369
3370 r = mailimap_capability_list_parse(fd, buffer, &cur_token,
3371 &cap_list,
3372 progr_rate, progr_fun);
3373
3374 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
3375 res = r;
3376 goto err;
3377 }
3378
3379#if 0
3380 if (!mailimap_space_parse(fd, buffer, &cur_token)) {
3381 res = r;
3382 goto free_list;
3383 }
3384
3385 if (!mailimap_token_case_insensitive_parse(fd, buffer,
3386 &cur_token, "IMAP4rev1"))
3387 goto free_list;
3388
3389 r = mailimap_capability_list_parse(fd, buffer, &cur_token,
3390 &cap_list_2,
3391 progr_rate, progr_fun);
3392
3393 cap_list = g_list_concat(cap_list, cap_list_2);
3394#endif
3395
3396 cap_data = mailimap_capability_data_new(cap_list);
3397 if (cap_data == NULL) {
3398 res = MAILIMAP_ERROR_MEMORY;
3399 goto free_list;
3400 }
3401
3402 * result = cap_data;
3403 * index = cur_token;
3404
3405 return MAILIMAP_NO_ERROR;
3406
3407 free_list:
3408 if (cap_list) {
3409 clist_foreach(cap_list, (clist_func) mailimap_capability_free, NULL);
3410 clist_free(cap_list);
3411 }
3412 err:
3413 return res;
3414}
3415
3416/*
3417 UNIMPLEMENTED BECAUSE UNUSED (only in literal)
3418 CHAR8 = %x01-ff
3419 ; any OCTET except NUL, %x00
3420*/
3421
3422/*
3423static gboolean is_char8(gchar ch)
3424{
3425 return (ch != 0x00);
3426}
3427*/
3428
3429
3430/*
3431UNIMPLEMENTED
3432 command = tag SP (command-any / command-auth / command-nonauth /
3433 command-select) CRLF
3434 ; Modal based on state
3435*/
3436
3437/*
3438UNIMPLEMENTED
3439 command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command
3440 ; Valid in all states
3441*/
3442
3443/*
3444UNIMPLEMENTED
3445 command-auth = append / create / delete / examine / list / lsub /
3446 rename / select / status / subscribe / unsubscribe
3447 ; Valid only in Authenticated or Selected state
3448*/
3449
3450/*
3451UNIMPLEMENTED
3452 command-nonauth = login / authenticate
3453 ; Valid only when in Not Authenticated state
3454*/
3455
3456/*
3457UNIMPLEMENTED
3458 command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store /
3459 uid / search
3460 ; Valid only when in Selected state
3461*/
3462
3463/*
3464 continue-req = "+" SP (resp-text / base64) CRLF
3465*/
3466
3467int
3468mailimap_continue_req_parse(mailstream * fd, MMAPString * buffer,
3469 size_t * index,
3470 struct mailimap_continue_req ** result,
3471 size_t progr_rate,
3472 progress_function * progr_fun)
3473{
3474 struct mailimap_resp_text * resp_text;
3475 size_t cur_token;
3476 struct mailimap_continue_req * cont_req;
3477 char * base64;
3478 int type;
3479 int r;
3480 int res;
3481
3482 cur_token = * index;
3483
3484 r = mailimap_plus_parse(fd, buffer, &cur_token);
3485 if (r != MAILIMAP_NO_ERROR)
3486 return r;
3487
3488 r = mailimap_space_parse(fd, buffer, &cur_token);
3489 if (r != MAILIMAP_NO_ERROR)
3490 return r;
3491
3492 resp_text = NULL;
3493 base64 = NULL;
3494
3495 type = MAILIMAP_CONTINUE_REQ_ERROR; /* XXX - removes a gcc warning */
3496
3497 r = mailimap_base64_parse(fd, buffer, &cur_token, &base64,
3498 progr_rate, progr_fun);
3499
3500 if (r == MAILIMAP_NO_ERROR)
3501 type = MAILIMAP_CONTINUE_REQ_BASE64;
3502
3503 if (r == MAILIMAP_ERROR_PARSE) {
3504 r = mailimap_resp_text_parse(fd, buffer, &cur_token, &resp_text,
3505 progr_rate, progr_fun);
3506
3507 if (r == MAILIMAP_NO_ERROR)
3508 type = MAILIMAP_CONTINUE_REQ_TEXT;
3509 }
3510
3511 if (r != MAILIMAP_NO_ERROR) {
3512 res = r;
3513 goto err;
3514 }
3515
3516 r = mailimap_crlf_parse(fd, buffer, &cur_token);
3517 if (r != MAILIMAP_NO_ERROR) {
3518 res = r;
3519 goto free;
3520 }
3521
3522 cont_req = mailimap_continue_req_new(type, resp_text, base64);
3523 if (cont_req == NULL) {
3524 res = MAILIMAP_ERROR_MEMORY;
3525 goto free;
3526 }
3527
3528 * result = cont_req;
3529 * index = cur_token;
3530
3531 return MAILIMAP_NO_ERROR;
3532
3533 free:
3534 if (base64 != NULL)
3535 mailimap_base64_free(base64);
3536 if (resp_text != NULL)
3537 mailimap_resp_text_free(resp_text);
3538 err:
3539 return res;
3540}
3541
3542/*
3543 UNIMPLEMENTED
3544 copy = "COPY" SP set SP mailbox
3545*/
3546
3547/*
3548 UNIMPLEMENTED
3549 create = "CREATE" SP mailbox
3550 ; Use of INBOX gives a NO error
3551*/
3552
3553/*
3554 UNIMPLEMENTED
3555 date = date-text / DQUOTE date-text DQUOTE
3556*/
3557
3558/*
3559 UNIMPLEMENTED
3560 date-day = 1*2DIGIT
3561 ; Day of month
3562*/
3563
3564/*
3565static gboolean mailimap_date_day_parse(mailstream * fd,
3566 MMAPString * buffer,
3567 guint32 * index,
3568 gint * result)
3569{
3570 guint32 cur_token;
3571 gint digit;
3572 gint number;
3573
3574 cur_token = * index;
3575
3576 if (!mailimap_digit_parse(fd, buffer, &cur_token, &digit))
3577 return FALSE;
3578
3579 number = digit;
3580
3581 if (mailimap_digit_parse(fd, buffer, &cur_token, &digit))
3582 number = number * 10 + digit;
3583
3584 * result = number;
3585 * index = cur_token;
3586
3587 return TRUE;
3588}
3589*/
3590
3591/*
3592 date-day-fixed = (SP DIGIT) / 2DIGIT
3593 ; Fixed-format version of date-day
3594*/
3595
3596static int mailimap_date_day_fixed_parse(mailstream * fd,
3597 MMAPString * buffer,
3598 size_t * index,
3599 int * result)
3600{
3601#ifdef UNSTRICT_SYNTAX
3602 size_t cur_token;
3603 uint32_t day;
3604 int r;
3605
3606 cur_token = * index;
3607
3608 r = mailimap_number_parse(fd, buffer, &cur_token, &day);
3609 if (r != MAILIMAP_NO_ERROR)
3610 return r;
3611
3612 * index = cur_token;
3613 * result = day;
3614
3615 return MAILIMAP_NO_ERROR;
3616
3617#else
3618 size_t cur_token;
3619 int r;
3620
3621 cur_token = * index;
3622
3623 if (mailimap_space_parse(fd, buffer, &cur_token)) {
3624 int digit;
3625
3626 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit);
3627 if (r != MAILIMAP_NO_ERROR)
3628 return r;
3629
3630 * result = digit;
3631 * index = cur_token;
3632
3633 return MAILIMAP_NO_ERROR;
3634 }
3635 else {
3636 int digit1;
3637 int digit2;
3638
3639 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit1);
3640 if (r != MAILIMAP_NO_ERROR)
3641 return r;
3642 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit2);
3643 if (r != MAILIMAP_NO_ERROR)
3644 return r;
3645
3646 * result = digit1 * 10 + digit2;
3647 * index = cur_token;
3648
3649 return MAILIMAP_NO_ERROR;
3650 }
3651#endif
3652}
3653
3654
3655/*
3656 date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" /
3657 "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
3658*/
3659
3660static int mailimap_date_month_parse(mailstream * fd, MMAPString * buffer,
3661 size_t * index, int * result)
3662{
3663 size_t cur_token;
3664 int month;
3665
3666 cur_token = * index;
3667
3668 month = mailimap_month_get_token_value(fd, buffer, &cur_token);
3669 if (month == -1)
3670 return MAILIMAP_ERROR_PARSE;
3671
3672 * result = month;
3673 * index = cur_token;
3674
3675 return MAILIMAP_NO_ERROR;
3676}
3677
3678/*
3679 UNIMPLEMENTED
3680 date-text = date-day "-" date-month "-" date-year
3681*/
3682
3683/*
3684static struct mailimap_date_text *
3685mailimap_date_text_new(gint day, gint month, gint year)
3686{
3687 struct mailimap_date_text * date_text;
3688
3689 date_text = g_new(struct mailimap_date_text, 1);
3690 if (date_text == NULL)
3691 return NULL;
3692
3693 date_text->day = day;
3694 date_text->month = month;
3695 date_text->year = year;
3696
3697 return date_text;
3698}
3699
3700static void mailimap_date_text_free(struct mailimap_date_text * date_text)
3701{
3702 g_free(date_text);
3703}
3704
3705static gboolean
3706mailimap_date_text_parse(mailstream * fd, MMAPString * buffer,
3707 guint32 * index, struct mailimap_date_text ** result)
3708{
3709 struct mailimap_date_text * date_text;
3710 gint day;
3711 gint month;
3712 gint year;
3713 guint32 cur_token;
3714
3715 cur_token = * index;
3716
3717 if (!mailimap_date_day_parse(fd, buffer, &cur_token, &day))
3718 return FALSE;
3719
3720 if (!mailimap_minus_parse(fd, buffer, &cur_token))
3721 return FALSE;
3722
3723 if (!mailimap_date_month_parse(fd, buffer, &cur_token, &month))
3724 return FALSE;
3725
3726 if (!mailimap_minus_parse(fd, buffer, &cur_token))
3727 return FALSE;
3728
3729 if (!mailimap_date_year_parse(fd, buffer, &cur_token, &year))
3730 return FALSE;
3731
3732 date_text = mailimap_date_text_new(day, month, year);
3733 if (date_text == NULL)
3734 return FALSE;
3735
3736 * result = date_text;
3737 * index = cur_token;
3738
3739 return TRUE;
3740}
3741*/
3742
3743/*
3744 date-year = 4DIGIT
3745*/
3746
3747static int mailimap_date_year_parse(mailstream * fd, MMAPString * buffer,
3748 size_t * index, int * result)
3749{
3750#ifdef UNSTRICT_SYNTAX
3751 uint32_t year;
3752 int r;
3753 size_t cur_token;
3754
3755 cur_token = * index;
3756
3757 r = mailimap_number_parse(fd, buffer, &cur_token, &year);
3758 if (r != MAILIMAP_NO_ERROR)
3759 return r;
3760
3761 * result = year;
3762 * index = cur_token;
3763
3764 return MAILIMAP_NO_ERROR;
3765#else
3766 int i;
3767 size_t cur_token;
3768 int year;
3769 int digit;
3770 int r;
3771
3772 cur_token = * index;
3773 year = 0;
3774
3775 for(i = 0 ; i < 4 ; i ++) {
3776 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit);
3777 if (r != MAILIMAP_NO_ERROR)
3778 return r;
3779 year = year * 10 + digit;
3780 }
3781
3782 * result = year;
3783 * index = cur_token;
3784
3785 return MAILIMAP_NO_ERROR;
3786#endif
3787}
3788
3789/*
3790 date-time = DQUOTE date-day-fixed "-" date-month "-" date-year
3791 SP time SP zone DQUOTE
3792*/
3793
3794static int mailimap_date_time_parse(mailstream * fd, MMAPString * buffer,
3795 size_t * index,
3796 struct mailimap_date_time ** result,
3797 size_t progr_rate,
3798 progress_function * progr_fun)
3799{
3800 int day;
3801 int month;
3802 int year;
3803 int hour;
3804 int min;
3805 int sec;
3806 struct mailimap_date_time * date_time;
3807 size_t cur_token;
3808 int zone;
3809 int r;
3810
3811 cur_token = * index;
3812
3813 r = mailimap_dquote_parse(fd, buffer, &cur_token);
3814 if (r != MAILIMAP_NO_ERROR)
3815 return r;
3816
3817 r = mailimap_date_day_fixed_parse(fd, buffer, &cur_token, &day);
3818 if (r != MAILIMAP_NO_ERROR)
3819 return r;
3820
3821 r = mailimap_minus_parse(fd, buffer, &cur_token);
3822 if (r != MAILIMAP_NO_ERROR)
3823 return r;
3824
3825 r = mailimap_date_month_parse(fd, buffer, &cur_token, &month);
3826 if (r != MAILIMAP_NO_ERROR)
3827 return r;
3828
3829 r = mailimap_minus_parse(fd, buffer, &cur_token);
3830 if (r != MAILIMAP_NO_ERROR)
3831 return r;
3832
3833 r = mailimap_date_year_parse(fd, buffer, &cur_token, &year);
3834 if (r != MAILIMAP_NO_ERROR)
3835 return r;
3836
3837 r = mailimap_space_parse(fd, buffer, &cur_token);
3838 if (r != MAILIMAP_NO_ERROR)
3839 return r;
3840
3841 r = mailimap_time_parse(fd, buffer, &cur_token, &hour, &min, &sec);
3842 if (r != MAILIMAP_NO_ERROR)
3843 return r;
3844
3845 r = mailimap_space_parse(fd, buffer, &cur_token);
3846 if (r != MAILIMAP_NO_ERROR)
3847 return r;
3848
3849 r = mailimap_zone_parse(fd, buffer, &cur_token, &zone);
3850 if (r != MAILIMAP_NO_ERROR)
3851 return r;
3852
3853 r = mailimap_dquote_parse(fd, buffer, &cur_token);
3854 if (r != MAILIMAP_NO_ERROR)
3855 return r;
3856
3857 date_time = mailimap_date_time_new(day, month, year, hour, min, sec, zone);
3858 if (date_time == NULL)
3859 return MAILIMAP_ERROR_MEMORY;
3860
3861 * result = date_time;
3862 * index = cur_token;
3863
3864 return MAILIMAP_NO_ERROR;
3865}
3866
3867
3868/*
3869 UNIMPLEMENTED
3870 delete = "DELETE" SP mailbox
3871 ; Use of INBOX gives a NO error
3872*/
3873
3874/*
3875 digit-nz = %x31-39
3876 ; 1-9
3877*/
3878
3879#ifndef UNSTRICT_SYNTAX
3880static int is_digit_nz(char ch)
3881{
3882 return (ch >= '1') && (ch <= '9');
3883}
3884
3885static int mailimap_digit_nz_parse(mailstream * fd, MMAPString * buffer,
3886 size_t * index, int * result)
3887{
3888 size_t cur_token;
3889
3890 cur_token = * index;
3891
3892 if (is_digit_nz(buffer->str[cur_token])) {
3893 * result = buffer->str[cur_token] - '0';
3894 cur_token ++;
3895 * index = cur_token;
3896 return MAILIMAP_NO_ERROR;
3897 }
3898 else
3899 return MAILIMAP_ERROR_PARSE;
3900}
3901#endif
3902
3903/*
3904 envelope = "(" env-date SP env-subject SP env-from SP env-sender SP
3905 env-reply-to SP env-to SP env-cc SP env-bcc SP
3906 env-in-reply-to SP env-message-id ")"
3907*/
3908
3909static int mailimap_envelope_parse(mailstream * fd, MMAPString * buffer,
3910 size_t * index,
3911 struct mailimap_envelope ** result,
3912 size_t progr_rate,
3913 progress_function * progr_fun)
3914{
3915 size_t cur_token;
3916 char * date;
3917 char * subject;
3918 struct mailimap_env_from * from;
3919 struct mailimap_env_sender * sender;
3920 struct mailimap_env_reply_to * reply_to;
3921 struct mailimap_env_to * to;
3922 struct mailimap_env_cc * cc;
3923 struct mailimap_env_bcc * bcc;
3924 char * in_reply_to;
3925 char * message_id;
3926 struct mailimap_envelope * envelope;
3927 int r;
3928 int res;
3929
3930 date = NULL;
3931 subject = NULL;
3932 from = NULL;
3933 sender = NULL;
3934 reply_to = NULL;
3935 to = NULL;
3936 cc = NULL;
3937 bcc = NULL;
3938 in_reply_to = NULL;
3939 message_id = NULL;
3940
3941 cur_token = * index;
3942
3943 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
3944 if (r != MAILIMAP_NO_ERROR) {
3945 res = r;
3946 goto err;
3947 }
3948
3949 r = mailimap_env_date_parse(fd, buffer, &cur_token, &date,
3950 progr_rate, progr_fun);
3951 if (r != MAILIMAP_NO_ERROR) {
3952 res = r;
3953 goto err;
3954 }
3955
3956 r = mailimap_space_parse(fd, buffer, &cur_token);
3957 if (r != MAILIMAP_NO_ERROR) {
3958 res = r;
3959 goto date;
3960 }
3961
3962 r = mailimap_env_subject_parse(fd, buffer, &cur_token, &subject,
3963 progr_rate, progr_fun);
3964 if (r != MAILIMAP_NO_ERROR) {
3965 res = r;
3966 goto date;
3967 }
3968
3969 r = mailimap_space_parse(fd, buffer, &cur_token);
3970 if (r != MAILIMAP_NO_ERROR) {
3971 res = r;
3972 goto subject;
3973 }
3974
3975 r = mailimap_env_from_parse(fd, buffer, &cur_token, &from,
3976 progr_rate, progr_fun);
3977 if (r != MAILIMAP_NO_ERROR) {
3978 res = r;
3979 goto subject;
3980 }
3981
3982 r = mailimap_space_parse(fd, buffer, &cur_token);
3983 if (r != MAILIMAP_NO_ERROR) {
3984 res = r;
3985 goto from;
3986 }
3987
3988 r = mailimap_env_sender_parse(fd, buffer, &cur_token, &sender,
3989 progr_rate, progr_fun);
3990 if (r != MAILIMAP_NO_ERROR) {
3991 res = r;
3992 goto from;
3993 }
3994
3995 r = mailimap_space_parse(fd, buffer, &cur_token);
3996 if (r != MAILIMAP_NO_ERROR) {
3997 res = r;
3998 goto sender;
3999 }
4000
4001 r = mailimap_env_reply_to_parse(fd, buffer, &cur_token, &reply_to,
4002 progr_rate, progr_fun);
4003 if (r != MAILIMAP_NO_ERROR) {
4004 res = r;
4005 goto sender;
4006 }
4007
4008 r = mailimap_space_parse(fd, buffer, &cur_token);
4009 if (r != MAILIMAP_NO_ERROR) {
4010 res = r;
4011 goto reply_to;
4012 }
4013
4014 r = mailimap_env_to_parse(fd, buffer, &cur_token, &to,
4015 progr_rate, progr_fun);
4016 if (r != MAILIMAP_NO_ERROR) {
4017 res = r;
4018 goto reply_to;
4019 }
4020
4021 r = mailimap_space_parse(fd, buffer, &cur_token);
4022 if (r != MAILIMAP_NO_ERROR) {
4023 res = r;
4024 goto to;
4025 }
4026
4027 r = mailimap_env_cc_parse(fd, buffer, &cur_token, &cc,
4028 progr_rate, progr_fun);
4029 if (r != MAILIMAP_NO_ERROR) {
4030 res = r;
4031 goto to;
4032 }
4033
4034 r = mailimap_space_parse(fd, buffer, &cur_token);
4035 if (r != MAILIMAP_NO_ERROR) {
4036 res = r;
4037 goto cc;
4038 }
4039
4040 r = mailimap_env_bcc_parse(fd, buffer, &cur_token, &bcc,
4041 progr_rate, progr_fun);
4042 if (r != MAILIMAP_NO_ERROR) {
4043 res = r;
4044 goto cc;
4045 }
4046
4047 r = mailimap_space_parse(fd, buffer, &cur_token);
4048 if (r != MAILIMAP_NO_ERROR) {
4049 res = r;
4050 goto bcc;
4051 }
4052
4053 r = mailimap_env_in_reply_to_parse(fd, buffer, &cur_token, &in_reply_to,
4054 progr_rate, progr_fun);
4055 if (r != MAILIMAP_NO_ERROR) {
4056 res = r;
4057 goto bcc;
4058 }
4059
4060 r = mailimap_space_parse(fd, buffer, &cur_token);
4061 if (r != MAILIMAP_NO_ERROR) {
4062 res = r;
4063 goto in_reply_to;
4064 }
4065
4066 r = mailimap_env_message_id_parse(fd, buffer, &cur_token, &message_id,
4067 progr_rate, progr_fun);
4068 if (r != MAILIMAP_NO_ERROR) {
4069 res = r;
4070 goto in_reply_to;
4071 }
4072
4073 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
4074 if (r != MAILIMAP_NO_ERROR) {
4075 res = r;
4076 goto message_id;
4077 }
4078
4079 envelope = mailimap_envelope_new(date, subject, from, sender, reply_to, to,
4080 cc, bcc, in_reply_to, message_id);
4081 if (envelope == NULL) {
4082 res = MAILIMAP_ERROR_MEMORY;
4083 goto message_id;
4084 }
4085
4086 * result = envelope;
4087 * index = cur_token;
4088
4089 return MAILIMAP_NO_ERROR;
4090
4091 message_id:
4092 mailimap_env_message_id_free(message_id);
4093 in_reply_to:
4094 mailimap_env_in_reply_to_free(in_reply_to);
4095 bcc:
4096 mailimap_env_bcc_free(bcc);
4097 cc:
4098 mailimap_env_cc_free(cc);
4099 to:
4100 mailimap_env_to_free(to);
4101 reply_to:
4102 mailimap_env_reply_to_free(reply_to);
4103 sender:
4104 mailimap_env_sender_free(sender);
4105 from:
4106 mailimap_env_from_free(from);
4107 subject:
4108 mailimap_env_subject_free(date);
4109 date:
4110 mailimap_env_date_free(date);
4111 err:
4112 return res;
4113}
4114
4115/*
4116 "(" 1*address ")"
4117*/
4118
4119static int mailimap_address_list_parse(mailstream * fd, MMAPString * buffer,
4120 size_t * index,
4121 clist ** result,
4122 size_t progr_rate,
4123 progress_function * progr_fun)
4124{
4125 size_t cur_token;
4126 clist * address_list;
4127 int r;
4128 int res;
4129
4130 cur_token = * index;
4131
4132 address_list = NULL;
4133
4134 r = mailimap_nil_parse(fd, buffer, &cur_token);
4135 switch (r) {
4136 case MAILIMAP_NO_ERROR:
4137 address_list = NULL;
4138 break;
4139
4140 case MAILIMAP_ERROR_PARSE:
4141 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
4142 if (r != MAILIMAP_NO_ERROR) {
4143 res = r;
4144 goto err;
4145 }
4146
4147 r = mailimap_struct_multiple_parse(fd, buffer, &cur_token, &address_list,
4148 (mailimap_struct_parser *)
4149 mailimap_address_parse,
4150 (mailimap_struct_destructor *)
4151 mailimap_address_free,
4152 progr_rate, progr_fun);
4153 if (r != MAILIMAP_NO_ERROR) {
4154 res = r;
4155 goto err;
4156 }
4157
4158 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
4159 if (r != MAILIMAP_NO_ERROR) {
4160 res = r;
4161 goto address_list;
4162 }
4163
4164 break;
4165
4166 default:
4167 res = r;
4168 goto err;
4169 }
4170
4171 * result = address_list;
4172 * index = cur_token;
4173
4174 return MAILIMAP_NO_ERROR;
4175
4176 address_list:
4177 if (address_list) {
4178 clist_foreach(address_list, (clist_func) mailimap_address_free, NULL);
4179 clist_free(address_list);
4180 }
4181 err:
4182 return res;
4183}
4184
4185/*
4186 env-bcc = "(" 1*address ")" / nil
4187*/
4188
4189static int
4190mailimap_env_bcc_parse(mailstream * fd, MMAPString * buffer,
4191 size_t * index, struct mailimap_env_bcc ** result,
4192 size_t progr_rate,
4193 progress_function * progr_fun)
4194{
4195 clist * list;
4196 size_t cur_token;
4197 struct mailimap_env_bcc * env_bcc;
4198 int r;
4199 int res;
4200
4201 cur_token = * index;
4202 list = NULL;
4203
4204 r = mailimap_address_list_parse(fd, buffer, &cur_token, &list,
4205 progr_rate, progr_fun);
4206 if (r != MAILIMAP_NO_ERROR) {
4207 res = r;
4208 goto err;
4209 }
4210
4211 env_bcc = mailimap_env_bcc_new(list);
4212 if (env_bcc == NULL) {
4213 res = MAILIMAP_ERROR_MEMORY;
4214 goto free;
4215 }
4216
4217 * index = cur_token;
4218 * result = env_bcc;
4219
4220 return MAILIMAP_NO_ERROR;
4221
4222 free:
4223 clist_foreach(list, (clist_func) mailimap_address_free, NULL);
4224 clist_free(list);
4225 err:
4226 return res;
4227}
4228
4229/*
4230 env-cc = "(" 1*address ")" / nil
4231*/
4232
4233static int
4234mailimap_env_cc_parse(mailstream * fd, MMAPString * buffer,
4235 size_t * index, struct mailimap_env_cc ** result,
4236 size_t progr_rate,
4237 progress_function * progr_fun)
4238{
4239 clist * list;
4240 size_t cur_token;
4241 struct mailimap_env_cc * env_cc;
4242 int r;
4243 int res;
4244
4245 cur_token = * index;
4246 list = NULL;
4247
4248 r = mailimap_address_list_parse(fd, buffer, &cur_token, &list,
4249 progr_rate, progr_fun);
4250 if (r != MAILIMAP_NO_ERROR) {
4251 res = r;
4252 goto err;
4253 }
4254
4255 env_cc = mailimap_env_cc_new(list);
4256 if (env_cc == NULL) {
4257 res = MAILIMAP_ERROR_MEMORY;
4258 goto free;
4259 }
4260
4261 * index = cur_token;
4262 * result = env_cc;
4263
4264 return MAILIMAP_NO_ERROR;
4265
4266 free:
4267 clist_foreach(list, (clist_func) mailimap_address_free, NULL);
4268 clist_free(list);
4269 err:
4270 return res;
4271}
4272
4273/*
4274 env-date = nstring
4275*/
4276
4277static int mailimap_env_date_parse(mailstream * fd, MMAPString * buffer,
4278 size_t * index, char ** result,
4279 size_t progr_rate,
4280 progress_function * progr_fun)
4281{
4282 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
4283 progr_rate, progr_fun);
4284}
4285
4286/*
4287 env-from = "(" 1*address ")" / nil
4288*/
4289
4290static int
4291mailimap_env_from_parse(mailstream * fd, MMAPString * buffer,
4292 size_t * index, struct mailimap_env_from ** result,
4293 size_t progr_rate,
4294 progress_function * progr_fun)
4295{
4296 clist * list;
4297 size_t cur_token;
4298 struct mailimap_env_from * env_from;
4299 int r;
4300 int res;
4301
4302 cur_token = * index;
4303 list = NULL;
4304
4305 r = mailimap_address_list_parse(fd, buffer, &cur_token, &list,
4306 progr_rate, progr_fun);
4307 if (r != MAILIMAP_NO_ERROR) {
4308 res = r;
4309 goto err;
4310 }
4311
4312 env_from = mailimap_env_from_new(list);
4313 if (env_from == NULL) {
4314 res = MAILIMAP_ERROR_MEMORY;
4315 goto free;
4316 }
4317
4318 * index = cur_token;
4319 * result = env_from;
4320
4321 return MAILIMAP_NO_ERROR;
4322
4323 free:
4324 clist_foreach(list, (clist_func) mailimap_address_free, NULL);
4325 clist_free(list);
4326 err:
4327 return res;
4328}
4329
4330/*
4331 env-in-reply-to = nstring
4332*/
4333
4334static int mailimap_env_in_reply_to_parse(mailstream * fd,
4335 MMAPString * buffer,
4336 size_t * index, char ** result,
4337 size_t progr_rate,
4338 progress_function * progr_fun)
4339{
4340 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
4341 progr_rate, progr_fun);
4342}
4343
4344/*
4345 env-message-id = nstring
4346*/
4347
4348static int mailimap_env_message_id_parse(mailstream * fd,
4349 MMAPString * buffer,
4350 size_t * index, char ** result,
4351 size_t progr_rate,
4352 progress_function * progr_fun)
4353{
4354 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
4355 progr_rate, progr_fun);
4356}
4357
4358/*
4359 env-reply-to = "(" 1*address ")" / nil
4360*/
4361
4362static int
4363mailimap_env_reply_to_parse(mailstream * fd, MMAPString * buffer,
4364 size_t * index,
4365 struct mailimap_env_reply_to ** result,
4366 size_t progr_rate,
4367 progress_function * progr_fun)
4368{
4369 clist * list;
4370 size_t cur_token;
4371 struct mailimap_env_reply_to * env_reply_to;
4372 int r;
4373 int res;
4374
4375 cur_token = * index;
4376 list = NULL;
4377
4378 r = mailimap_address_list_parse(fd, buffer, &cur_token, &list,
4379 progr_rate, progr_fun);
4380 if (r != MAILIMAP_NO_ERROR) {
4381 res = r;
4382 goto err;
4383 }
4384
4385 env_reply_to = mailimap_env_reply_to_new(list);
4386 if (env_reply_to == NULL) {
4387 res = MAILIMAP_ERROR_MEMORY;
4388 goto free;
4389 }
4390
4391 * index = cur_token;
4392 * result = env_reply_to;
4393
4394 return MAILIMAP_NO_ERROR;
4395
4396 free:
4397 clist_foreach(list, (clist_func) mailimap_address_free, NULL);
4398 clist_free(list);
4399 err:
4400 return res;
4401}
4402
4403/*
4404 env-sender = "(" 1*address ")" / nil
4405*/
4406
4407
4408static int
4409mailimap_env_sender_parse(mailstream * fd, MMAPString * buffer,
4410 size_t * index, struct mailimap_env_sender ** result,
4411 size_t progr_rate,
4412 progress_function * progr_fun)
4413{
4414 clist * list;
4415 size_t cur_token;
4416 struct mailimap_env_sender * env_sender;
4417 int r;
4418 int res;
4419
4420 cur_token = * index;
4421 list = NULL;
4422
4423 r = mailimap_address_list_parse(fd, buffer, &cur_token, &list,
4424 progr_rate, progr_fun);
4425 if (r != MAILIMAP_NO_ERROR) {
4426 res = r;
4427 goto err;
4428 }
4429
4430 env_sender = mailimap_env_sender_new(list);
4431 if (env_sender == NULL) {
4432 res = MAILIMAP_ERROR_MEMORY;
4433 goto free;
4434 }
4435
4436 * index = cur_token;
4437 * result = env_sender;
4438
4439 return MAILIMAP_NO_ERROR;
4440
4441 free:
4442 clist_foreach(list, (clist_func) mailimap_address_free, NULL);
4443 clist_free(list);
4444 err:
4445 return res;
4446}
4447
4448
4449/*
4450 env-subject = nstring
4451*/
4452
4453static int mailimap_env_subject_parse(mailstream * fd, MMAPString * buffer,
4454 size_t * index, char ** result,
4455 size_t progr_rate,
4456 progress_function * progr_fun)
4457{
4458 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
4459 progr_rate, progr_fun);
4460}
4461
4462
4463/*
4464 env-to = "(" 1*address ")" / nil
4465*/
4466
4467static int mailimap_env_to_parse(mailstream * fd, MMAPString * buffer,
4468 size_t * index,
4469 struct mailimap_env_to ** result,
4470 size_t progr_rate,
4471 progress_function * progr_fun)
4472{
4473 clist * list;
4474 size_t cur_token;
4475 struct mailimap_env_to * env_to;
4476 int r;
4477 int res;
4478
4479 cur_token = * index;
4480 list = NULL;
4481
4482 r = mailimap_address_list_parse(fd, buffer, &cur_token, &list,
4483 progr_rate, progr_fun);
4484 if (r != MAILIMAP_NO_ERROR) {
4485 res = r;
4486 goto err;
4487 }
4488
4489 env_to = mailimap_env_to_new(list);
4490 if (env_to == NULL) {
4491 res = MAILIMAP_ERROR_MEMORY;
4492 goto free;
4493 }
4494
4495 * index = cur_token;
4496 * result = env_to;
4497
4498 return MAILIMAP_NO_ERROR;
4499
4500 free:
4501 clist_foreach(list, (clist_func) mailimap_address_free, NULL);
4502 clist_free(list);
4503 err:
4504 return res;
4505}
4506
4507
4508/*
4509 UNIMPLEMENTED
4510 examine = "EXAMINE" SP mailbox
4511*/
4512
4513/*
4514 UNIMPLEMENTED
4515 fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att /
4516 "(" fetch-att *(SP fetch-att) ")")
4517*/
4518
4519/*
4520 UNIMPLEMENTED
4521 fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" /
4522 "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] /
4523 "BODY" ["STRUCTURE"] / "UID" /
4524 "BODY" [".PEEK"] section ["<" number "." nz-number ">"]
4525*/
4526
4527/*
4528 flag = "\Answered" / "\Flagged" / "\Deleted" /
4529 "\Seen" / "\Draft" / flag-keyword / flag-extension
4530 ; Does not include "\Recent"
4531*/
4532
4533static int mailimap_flag_parse(mailstream * fd, MMAPString * buffer,
4534 size_t * index,
4535 struct mailimap_flag ** result,
4536 size_t progr_rate,
4537 progress_function * progr_fun)
4538{
4539 struct mailimap_flag * flag;
4540 size_t cur_token;
4541 char * flag_keyword;
4542 char * flag_extension;
4543 int type;
4544 int r;
4545 int res;
4546
4547 cur_token = * index;
4548
4549 flag_keyword = NULL;
4550 flag_extension = NULL;
4551
4552 type = mailimap_flag_get_token_value(fd, buffer, &cur_token);
4553 if (type == -1) {
4554 r = mailimap_flag_keyword_parse(fd, buffer, &cur_token, &flag_keyword,
4555 progr_rate, progr_fun);
4556 if (r == MAILIMAP_NO_ERROR)
4557 type = MAILIMAP_FLAG_KEYWORD;
4558
4559 if (r == MAILIMAP_ERROR_PARSE) {
4560 r = mailimap_flag_extension_parse(fd, buffer, &cur_token,
4561 &flag_extension,
4562 progr_rate, progr_fun);
4563 type = MAILIMAP_FLAG_EXTENSION;
4564 }
4565
4566 if (r != MAILIMAP_NO_ERROR) {
4567 res = r;
4568 goto err;
4569 }
4570 }
4571
4572 flag = mailimap_flag_new(type, flag_keyword, flag_extension);
4573 if (flag == NULL) {
4574 res = MAILIMAP_ERROR_MEMORY;
4575 goto free;
4576 }
4577
4578 * result = flag;
4579 * index = cur_token;
4580
4581 return MAILIMAP_NO_ERROR;
4582
4583 free:
4584 if (flag_keyword != NULL)
4585 mailimap_flag_keyword_free(flag_keyword);
4586 if (flag_extension != NULL)
4587 mailimap_flag_extension_free(flag_extension);
4588 err:
4589 return res;
4590}
4591
4592/*
4593 flag-extension = "\" atom
4594 ; Future expansion. Client implementations
4595 ; MUST accept flag-extension flags. Server
4596 ; implementations MUST NOT generate
4597 ; flag-extension flags except as defined by
4598 ; future standard or standards-track
4599 ; revisions of this specification.
4600*/
4601
4602static int mailimap_flag_extension_parse(mailstream * fd,
4603 MMAPString * buffer,
4604 size_t * index,
4605 char ** result,
4606 size_t progr_rate,
4607 progress_function * progr_fun)
4608{
4609 size_t cur_token;
4610 char * atom;
4611 int r;
4612
4613 cur_token = * index;
4614
4615 r = mailimap_char_parse(fd, buffer, &cur_token, '\\');
4616 if (r != MAILIMAP_NO_ERROR)
4617 return r;
4618
4619 r = mailimap_atom_parse(fd, buffer, &cur_token, &atom,
4620 progr_rate, progr_fun);
4621 if (r != MAILIMAP_NO_ERROR)
4622 return r;
4623
4624 * result = atom;
4625 * index = cur_token;
4626
4627 return MAILIMAP_NO_ERROR;
4628}
4629
4630/*
4631 flag-fetch = flag / "\Recent"
4632*/
4633
4634static int
4635mailimap_flag_fetch_parse(mailstream * fd, MMAPString * buffer,
4636 size_t * index,
4637 struct mailimap_flag_fetch ** result,
4638 size_t progr_rate,
4639 progress_function * progr_fun)
4640{
4641 size_t cur_token;
4642 struct mailimap_flag * flag;
4643 struct mailimap_flag_fetch * flag_fetch;
4644 int type;
4645 int r;
4646 int res;
4647
4648 cur_token = * index;
4649
4650 flag = NULL;
4651
4652 type = MAILIMAP_FLAG_FETCH_ERROR; /* XXX - removes a gcc warning */
4653
4654 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
4655 "\\Recent");
4656 if (r == MAILIMAP_NO_ERROR)
4657 type = MAILIMAP_FLAG_FETCH_RECENT;
4658
4659 if (r == MAILIMAP_ERROR_PARSE) {
4660 r = mailimap_flag_parse(fd, buffer, &cur_token, &flag,
4661 progr_rate, progr_fun);
4662 if (r == MAILIMAP_NO_ERROR)
4663 type = MAILIMAP_FLAG_FETCH_OTHER;
4664 }
4665
4666 if (r != MAILIMAP_NO_ERROR) {
4667 res = r;
4668 goto err;
4669 }
4670
4671 flag_fetch = mailimap_flag_fetch_new(type, flag);
4672 if (flag_fetch == NULL) {
4673 res = MAILIMAP_ERROR_MEMORY;
4674 goto free;
4675 }
4676
4677 * index = cur_token;
4678 * result = flag_fetch;
4679
4680 return MAILIMAP_NO_ERROR;
4681
4682 free:
4683 if (flag != NULL)
4684 mailimap_flag_free(flag);
4685 err:
4686 return res;
4687}
4688
4689/*
4690 flag-keyword = atom
4691*/
4692
4693static int mailimap_flag_keyword_parse(mailstream * fd, MMAPString * buffer,
4694 size_t * index,
4695 char ** result,
4696 size_t progr_rate,
4697 progress_function * progr_fun)
4698{
4699 return mailimap_atom_parse(fd, buffer, index, result,
4700 progr_rate, progr_fun);
4701}
4702
4703/*
4704 flag-list = "(" [flag *(SP flag)] ")"
4705*/
4706
4707static int mailimap_flag_list_parse(mailstream * fd, MMAPString * buffer,
4708 size_t * index,
4709 struct mailimap_flag_list ** result,
4710 size_t progr_rate,
4711 progress_function * progr_fun)
4712{
4713 size_t cur_token;
4714 clist * list;
4715 struct mailimap_flag_list * flag_list;
4716 int r;
4717 int res;
4718
4719 list = NULL;
4720 cur_token = * index;
4721
4722 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
4723 if (r != MAILIMAP_NO_ERROR) {
4724 res = r;
4725 goto err;
4726 }
4727
4728 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list,
4729 (mailimap_struct_parser *)
4730 mailimap_flag_parse,
4731 (mailimap_struct_destructor *)
4732 mailimap_flag_free,
4733 progr_rate, progr_fun);
4734
4735 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
4736 res = r;
4737 goto err;
4738 }
4739
4740 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
4741 if (r != MAILIMAP_NO_ERROR) {
4742 res = r;
4743 goto free;
4744 }
4745
4746 flag_list = mailimap_flag_list_new(list);
4747 if (flag_list == NULL) {
4748 res = MAILIMAP_ERROR_MEMORY;
4749 goto free;
4750 }
4751
4752 * result = flag_list;
4753 * index = cur_token;
4754
4755 return MAILIMAP_NO_ERROR;
4756
4757 free:
4758 if (list != NULL) {
4759 clist_foreach(list, (clist_func) mailimap_flag_free, NULL);
4760 clist_free(list);
4761 }
4762 err:
4763 return res;
4764}
4765
4766/*
4767 flag-perm = flag / "\*"
4768*/
4769
4770static int
4771mailimap_flag_perm_parse(mailstream * fd, MMAPString * buffer,
4772 size_t * index,
4773 struct mailimap_flag_perm ** result,
4774 size_t progr_rate,
4775 progress_function * progr_fun)
4776{
4777 size_t cur_token;
4778 struct mailimap_flag_perm * flag_perm;
4779 struct mailimap_flag * flag;
4780 int type;
4781 int r;
4782 int res;
4783
4784 flag = NULL;
4785 cur_token = * index;
4786 type = MAILIMAP_FLAG_PERM_ERROR; /* XXX - removes a gcc warning */
4787
4788 r = mailimap_flag_parse(fd, buffer, &cur_token, &flag,
4789 progr_rate, progr_fun);
4790 if (r == MAILIMAP_NO_ERROR)
4791 type = MAILIMAP_FLAG_PERM_FLAG;
4792
4793 if (r == MAILIMAP_ERROR_PARSE) {
4794 r = mailimap_token_case_insensitive_parse(fd, buffer,
4795 &cur_token, "\\*");
4796 if (r == MAILIMAP_NO_ERROR)
4797 type = MAILIMAP_FLAG_PERM_ALL;
4798 }
4799
4800 if (r != MAILIMAP_NO_ERROR) {
4801 res = r;
4802 goto err;
4803 }
4804
4805 flag_perm = mailimap_flag_perm_new(type, flag);
4806 if (flag_perm == NULL) {
4807 res = MAILIMAP_ERROR_MEMORY;
4808 goto free;
4809 }
4810
4811 * result = flag_perm;
4812 * index = cur_token;
4813
4814 return MAILIMAP_NO_ERROR;
4815
4816 free:
4817 if (flag != NULL)
4818 mailimap_flag_free(flag);
4819 err:
4820 return res;
4821}
4822
4823/*
4824 greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF
4825*/
4826
4827int mailimap_greeting_parse(mailstream * fd, MMAPString * buffer,
4828 size_t * index,
4829 struct mailimap_greeting ** result,
4830 size_t progr_rate,
4831 progress_function * progr_fun)
4832{
4833 size_t cur_token;
4834 struct mailimap_resp_cond_auth * resp_cond_auth;
4835 struct mailimap_resp_cond_bye * resp_cond_bye;
4836 struct mailimap_greeting * greeting;
4837 int type;
4838 int r;
4839 int res;
4840
4841 cur_token = * index;
4842 resp_cond_bye = NULL;
4843 resp_cond_auth = NULL;
4844
4845 r = mailimap_star_parse(fd, buffer, &cur_token);
4846 if (r != MAILIMAP_NO_ERROR) {
4847 res = r;
4848 goto err;
4849 }
4850
4851 r = mailimap_space_parse(fd, buffer, &cur_token);
4852 if (r != MAILIMAP_NO_ERROR) {
4853 res = r;
4854 goto err;
4855 }
4856
4857 type = MAILIMAP_GREETING_RESP_COND_ERROR; /* XXX - removes a gcc warning */
4858
4859 r = mailimap_resp_cond_auth_parse(fd, buffer, &cur_token, &resp_cond_auth,
4860 progr_rate, progr_fun);
4861 if (r == MAILIMAP_NO_ERROR)
4862 type = MAILIMAP_GREETING_RESP_COND_AUTH;
4863
4864 if (r == MAILIMAP_ERROR_PARSE) {
4865 r = mailimap_resp_cond_bye_parse(fd, buffer, &cur_token,
4866 &resp_cond_bye,
4867 progr_rate, progr_fun);
4868 if (r == MAILIMAP_NO_ERROR)
4869 type = MAILIMAP_GREETING_RESP_COND_BYE;
4870 }
4871
4872 if (r != MAILIMAP_NO_ERROR) {
4873 res = r;
4874 goto err;
4875 }
4876
4877 r = mailimap_crlf_parse(fd, buffer, &cur_token);
4878 if (r != MAILIMAP_NO_ERROR) {
4879 res = r;
4880 goto free;
4881 }
4882
4883 greeting = mailimap_greeting_new(type, resp_cond_auth, resp_cond_bye);
4884 if (greeting == NULL) {
4885 res = MAILIMAP_ERROR_MEMORY;
4886 goto free;
4887 }
4888
4889 * result = greeting;
4890 * index = cur_token;
4891
4892 return MAILIMAP_NO_ERROR;
4893
4894 free:
4895 if (resp_cond_auth)
4896 mailimap_resp_cond_auth_free(resp_cond_auth);
4897 if (resp_cond_bye)
4898 mailimap_resp_cond_bye_free(resp_cond_bye);
4899 err:
4900 return res;
4901}
4902
4903/*
4904 header-fld-name = astring
4905*/
4906
4907static int
4908mailimap_header_fld_name_parse(mailstream * fd,
4909 MMAPString * buffer,
4910 size_t * index,
4911 char ** result,
4912 size_t progr_rate,
4913 progress_function * progr_fun)
4914{
4915 return mailimap_astring_parse(fd, buffer, index, result,
4916 progr_rate, progr_fun);
4917}
4918
4919/*
4920 header-list = "(" header-fld-name *(SP header-fld-name) ")"
4921*/
4922
4923static int
4924mailimap_header_list_parse(mailstream * fd, MMAPString * buffer,
4925 size_t * index,
4926 struct mailimap_header_list ** result,
4927 size_t progr_rate,
4928 progress_function * progr_fun)
4929{
4930 size_t cur_token;
4931 struct mailimap_header_list * header_list;
4932 clist * list;
4933 int r;
4934 int res;
4935
4936 cur_token = * index;
4937
4938 list = NULL;
4939
4940 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
4941 if (r != MAILIMAP_NO_ERROR) {
4942 res = r;
4943 goto err;
4944 }
4945
4946 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list,
4947 (mailimap_struct_parser *)
4948 mailimap_header_fld_name_parse,
4949 (mailimap_struct_destructor *)
4950 mailimap_header_fld_name_free,
4951 progr_rate, progr_fun);
4952 if (r != MAILIMAP_NO_ERROR) {
4953 res = r;
4954 goto err;
4955 }
4956
4957 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
4958 if (r != MAILIMAP_NO_ERROR) {
4959 res = r;
4960 goto free;
4961 }
4962
4963 header_list = mailimap_header_list_new(list);
4964 if (header_list == NULL) {
4965 res = MAILIMAP_ERROR_MEMORY;
4966 goto free;
4967 }
4968
4969 * result = header_list;
4970 * index = cur_token;
4971
4972 return MAILIMAP_NO_ERROR;
4973
4974 free:
4975 clist_foreach(list, (clist_func) mailimap_header_fld_name_free, NULL);
4976 clist_free(list);
4977 err:
4978 return res;
4979}
4980
4981/*
4982UNIMPLEMENTED
4983 list = "LIST" SP mailbox SP list-mailbox
4984
4985UNIMPLEMENTED
4986 list-mailbox = 1*list-char / string
4987
4988UNIMPLEMENTED
4989 list-char = ATOM-CHAR / list-wildcards / resp-specials
4990*/
4991
4992/*
4993 list-wildcards = "%" / "*"
4994*/
4995
4996static int is_list_wildcards(char ch)
4997{
4998 switch (ch) {
4999 case '%':
5000 case '*':
5001 return TRUE;
5002 }
5003 return FALSE;
5004}
5005
5006
5007/*
5008 literal = "{" number "}" CRLF *CHAR8
5009 ; Number represents the number of CHAR8s
5010*/
5011
5012static int mailimap_literal_parse(mailstream * fd, MMAPString * buffer,
5013 size_t * index, char ** result,
5014 size_t * result_len,
5015 size_t progr_rate,
5016 progress_function * progr_fun)
5017{
5018 size_t cur_token;
5019 uint32_t number;
5020 MMAPString * literal;
5021 char * literal_p;
5022 uint32_t left;
5023 int r;
5024 int res;
5025 size_t number_token;
5026
5027 cur_token = * index;
5028
5029 r = mailimap_oaccolade_parse(fd, buffer, &cur_token);
5030 if (r != MAILIMAP_NO_ERROR) {
5031 res = r;
5032 goto err;
5033 }
5034
5035 number_token = cur_token;
5036
5037 r = mailimap_number_parse(fd, buffer, &cur_token, &number);
5038 if (r != MAILIMAP_NO_ERROR) {
5039 res = r;
5040 goto err;
5041 }
5042
5043 r = mailimap_caccolade_parse(fd, buffer, &cur_token);
5044 if (r != MAILIMAP_NO_ERROR) {
5045 res = r;
5046 goto err;
5047 }
5048
5049 r = mailimap_crlf_parse(fd, buffer, &cur_token);
5050 if (r != MAILIMAP_NO_ERROR) {
5051 res = r;
5052 goto err;
5053 }
5054
5055 literal = mmap_string_sized_new(number);
5056 /*
5057 literal = g_new(char, number + 1);
5058 */
5059 if (literal == NULL) {
5060 res = MAILIMAP_ERROR_MEMORY;
5061 goto err;
5062 }
5063
5064 left = buffer->len - cur_token;
5065
5066 if (left >= number) {
5067 /*
5068 if (number > 0)
5069 strncpy(literal, buffer->str + cur_token, number);
5070 literal[number] = 0;
5071 */
5072 if (number > 0)
5073 if (mmap_string_append_len(literal, buffer->str + cur_token,
5074 number) == NULL) {
5075 res = MAILIMAP_ERROR_MEMORY;
5076 goto free_literal;
5077 }
5078 if ((progr_fun != NULL) && (progr_rate != 0))
5079 progr_fun(number, number);
5080
5081 cur_token = cur_token + number;
5082 }
5083 else {
5084 uint32_t needed;
5085 uint32_t current_prog = 0;
5086 uint32_t last_prog = 0;
5087
5088 needed = number - left;
5089 memcpy(literal->str, buffer->str + cur_token, left);
5090 literal->len += left;
5091 literal_p = literal->str + left;
5092 current_prog = left;
5093
5094 while (needed > 0) {
5095 ssize_t read_bytes;
5096
5097 read_bytes = mailstream_read(fd, literal_p, needed);
5098 if (read_bytes == -1) {
5099 res = MAILIMAP_ERROR_STREAM;
5100 goto free_literal;
5101 }
5102 literal->len += read_bytes;
5103 needed -= read_bytes;
5104 literal_p += read_bytes;
5105
5106 current_prog += read_bytes;
5107 if ((progr_fun != NULL) && (progr_rate != 0))
5108 if (current_prog - last_prog > progr_rate) {
5109 progr_fun(current_prog, number);
5110 last_prog = current_prog;
5111 }
5112 }
5113
5114 literal->str[number] = 0;
5115
5116#if 0
5117 literal->str[number] = 0;
5118 if (mmap_string_append_len(buffer, literal->str + left,
5119 literal->len - left) == NULL) {
5120 res = MAILIMAP_ERROR_STREAM;
5121 goto free_literal;
5122 }
5123#endif
5124
5125 if (mmap_string_truncate(buffer, number_token) == NULL) {
5126 res = MAILIMAP_ERROR_MEMORY;
5127 goto free_literal;
5128 }
5129
5130 if (mmap_string_append(buffer, "0}\r\n") == NULL) {
5131 res = MAILIMAP_ERROR_MEMORY;
5132 goto free_literal;
5133 }
5134
5135 cur_token = number_token + 4;
5136 }
5137 if ((progr_fun != NULL) && (progr_rate != 0))
5138 progr_fun(number, number);
5139
5140 if (mailstream_read_line_append(fd, buffer) == NULL) {
5141 res = MAILIMAP_ERROR_STREAM;
5142 goto free_literal;
5143 }
5144
5145 if (mmap_string_ref(literal) < 0) {
5146 res = MAILIMAP_ERROR_MEMORY;
5147 goto free_literal;
5148 }
5149
5150 * result = literal->str;
5151 if (result_len != NULL)
5152 * result_len = literal->len;
5153 * index = cur_token;
5154
5155 return MAILIMAP_NO_ERROR;
5156
5157 free_literal:
5158 mmap_string_free(literal);
5159 err:
5160 return res;
5161}
5162
5163/*
5164 UNIMPLEMENTED
5165 login = "LOGIN" SP userid SP password
5166
5167 UNIMPLEMENTED
5168 lsub = "LSUB" SP mailbox SP list-mailbox
5169*/
5170
5171/*
5172 mailbox = "INBOX" / astring
5173 ; INBOX is case-insensitive. All case variants of
5174 ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX
5175 ; not as an astring. An astring which consists of
5176 ; the case-insensitive sequence "I" "N" "B" "O" "X"
5177 ; is considered to be INBOX and not an astring.
5178 ; Refer to section 5.1 for further
5179 ; semantic details of mailbox names.
5180*/
5181
5182static int
5183mailimap_mailbox_parse(mailstream * fd, MMAPString * buffer,
5184 size_t * index, char ** result,
5185 size_t progr_rate,
5186 progress_function * progr_fun)
5187{
5188 size_t cur_token;
5189 char * name;
5190 int r;
5191
5192 cur_token = * index;
5193
5194 r = mailimap_astring_parse(fd, buffer, &cur_token, &name,
5195 progr_rate, progr_fun);
5196 if (r != MAILIMAP_NO_ERROR)
5197 return r;
5198
5199 * result = name;
5200 * index = cur_token;
5201
5202 return MAILIMAP_NO_ERROR;
5203}
5204
5205
5206/*
5207 mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list /
5208 "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) /
5209 "STATUS" SP mailbox SP "("
5210 [status-att SP number *(SP status-att SP number)] ")" /
5211 number SP "EXISTS" / number SP "RECENT"
5212*/
5213
5214/*
5215 "FLAGS" SP flag-list
5216*/
5217
5218static int
5219mailimap_mailbox_data_flags_parse(mailstream * fd, MMAPString * buffer,
5220 size_t * index,
5221 struct mailimap_flag_list ** result,
5222 size_t progr_rate,
5223 progress_function * progr_fun)
5224{
5225 size_t cur_token;
5226 struct mailimap_flag_list * flag_list;
5227 int r;
5228
5229 cur_token = * index;
5230
5231 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "FLAGS");
5232 if (r != MAILIMAP_NO_ERROR)
5233 return r;
5234
5235 r = mailimap_space_parse(fd, buffer, &cur_token);
5236 if (r != MAILIMAP_NO_ERROR)
5237 return r;
5238
5239 r = mailimap_flag_list_parse(fd, buffer, &cur_token, &flag_list,
5240 progr_rate, progr_fun);
5241 if (r != MAILIMAP_NO_ERROR)
5242 return r;
5243
5244 * result = flag_list;
5245 * index = cur_token;
5246
5247 return MAILIMAP_NO_ERROR;
5248}
5249
5250
5251/*
5252 "LIST" SP mailbox-list
5253*/
5254
5255static int
5256mailimap_mailbox_data_list_parse(mailstream * fd, MMAPString * buffer,
5257 size_t * index,
5258 struct mailimap_mailbox_list ** result,
5259 size_t progr_rate,
5260 progress_function * progr_fun)
5261{
5262 size_t cur_token;
5263 struct mailimap_mailbox_list * mb_list;
5264 int r;
5265 int res;
5266
5267 cur_token = * index;
5268
5269 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "LIST");
5270 if (r != MAILIMAP_NO_ERROR) {
5271 res = r;
5272 return r;
5273 }
5274
5275 r = mailimap_space_parse(fd, buffer, &cur_token);
5276 if (r != MAILIMAP_NO_ERROR) {
5277 res = r;
5278 return r;
5279 }
5280
5281 r = mailimap_mailbox_list_parse(fd, buffer, &cur_token, &mb_list,
5282 progr_rate, progr_fun);
5283 if (r != MAILIMAP_NO_ERROR) {
5284 res = r;
5285 return r;
5286 }
5287
5288 * result = mb_list;
5289 * index = cur_token;
5290
5291 return MAILIMAP_NO_ERROR;
5292}
5293
5294/*
5295 "LSUB" SP mailbox-list
5296*/
5297
5298static int
5299mailimap_mailbox_data_lsub_parse(mailstream * fd, MMAPString * buffer,
5300 size_t * index,
5301 struct mailimap_mailbox_list ** result,
5302 size_t progr_rate,
5303 progress_function * progr_fun)
5304{
5305 size_t cur_token;
5306 struct mailimap_mailbox_list * mb_list;
5307 int r;
5308
5309 cur_token = * index;
5310
5311 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "LSUB");
5312 if (r != MAILIMAP_NO_ERROR)
5313 return r;
5314
5315 r = mailimap_space_parse(fd, buffer, &cur_token);
5316 if (r != MAILIMAP_NO_ERROR)
5317 return r;
5318
5319 r = mailimap_mailbox_list_parse(fd, buffer, &cur_token, &mb_list,
5320 progr_rate, progr_fun);
5321 if (r != MAILIMAP_NO_ERROR)
5322 return r;
5323
5324 * result = mb_list;
5325 * index = cur_token;
5326
5327 return MAILIMAP_NO_ERROR;
5328}
5329
5330/*
5331 "SEARCH" *(SP nz-number)
5332*/
5333
5334
5335static int
5336mailimap_mailbox_data_search_parse(mailstream * fd, MMAPString * buffer,
5337 size_t * index,
5338 clist ** result,
5339 size_t progr_rate,
5340 progress_function * progr_fun)
5341{
5342 size_t cur_token;
5343 size_t final_token;
5344 clist * number_list;
5345 int r;
5346
5347 cur_token = * index;
5348
5349 r = mailimap_token_case_insensitive_parse(fd, buffer,
5350 &cur_token, "SEARCH");
5351 if (r != MAILIMAP_NO_ERROR)
5352 return r;
5353
5354 final_token = cur_token;
5355 number_list = NULL;
5356
5357 r = mailimap_space_parse(fd, buffer, &cur_token);
5358 if (r == MAILIMAP_NO_ERROR) {
5359 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &number_list,
5360 (mailimap_struct_parser *)
5361 mailimap_nz_number_alloc_parse,
5362 (mailimap_struct_destructor *)
5363 mailimap_number_alloc_free,
5364 progr_rate, progr_fun);
5365 if (r == MAILIMAP_NO_ERROR)
5366 final_token = cur_token;
5367 }
5368
5369 * result = number_list;
5370 * index = final_token;
5371
5372 return MAILIMAP_NO_ERROR;
5373}
5374
5375/*
5376 "STATUS" SP mailbox SP "("
5377 [status-att SP number *(SP status-att SP number)] ")"
5378*/
5379
5380/*
5381 status-att SP number
5382*/
5383
5384static int
5385mailimap_status_info_parse(mailstream * fd, MMAPString * buffer,
5386 size_t * index,
5387 struct mailimap_status_info **
5388 result,
5389 size_t progr_rate,
5390 progress_function * progr_fun)
5391{
5392 size_t cur_token;
5393 int status_att;
5394 uint32_t value;
5395 struct mailimap_status_info * info;
5396 int r;
5397
5398 cur_token = * index;
5399 value = 0;
5400
5401 r = mailimap_status_att_parse(fd, buffer, &cur_token, &status_att);
5402 if (r != MAILIMAP_NO_ERROR)
5403 return r;
5404
5405 r = mailimap_space_parse(fd, buffer, &cur_token);
5406 if (r != MAILIMAP_NO_ERROR)
5407 return r;
5408
5409 r = mailimap_number_parse(fd, buffer, &cur_token, &value);
5410 if (r != MAILIMAP_NO_ERROR)
5411 return r;
5412
5413 info = mailimap_status_info_new(status_att, value);
5414 if (info == NULL)
5415 return MAILIMAP_ERROR_MEMORY;
5416
5417 * result = info;
5418 * index = cur_token;
5419
5420 return MAILIMAP_NO_ERROR;
5421}
5422
5423/*
5424 "STATUS" SP mailbox SP "("
5425 [status-att SP number *(SP status-att SP number)] ")"
5426*/
5427
5428static int
5429mailimap_mailbox_data_status_parse(mailstream * fd, MMAPString * buffer,
5430 size_t * index, struct
5431 mailimap_mailbox_data_status ** result,
5432 size_t progr_rate,
5433 progress_function * progr_fun)
5434{
5435 size_t cur_token;
5436 char * mb;
5437 clist * status_info_list;
5438 struct mailimap_mailbox_data_status * data_status;
5439 int r;
5440 int res;
5441
5442 cur_token = * index;
5443 mb = NULL;
5444 status_info_list = NULL;
5445
5446 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "STATUS");
5447 if (r != MAILIMAP_NO_ERROR) {
5448 res = r;
5449 goto err;
5450 }
5451
5452 r = mailimap_space_parse(fd, buffer, &cur_token);
5453 if (r != MAILIMAP_NO_ERROR) {
5454 res = r;
5455 goto err;
5456 }
5457
5458 r = mailimap_mailbox_parse(fd, buffer, &cur_token, &mb,
5459 progr_rate, progr_fun);
5460 if (r != MAILIMAP_NO_ERROR) {
5461 res = r;
5462 goto err;
5463 }
5464
5465 r = mailimap_space_parse(fd, buffer, &cur_token);
5466 if (r != MAILIMAP_NO_ERROR) {
5467 res = r;
5468 goto mailbox;
5469 }
5470
5471 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
5472 if (r != MAILIMAP_NO_ERROR) {
5473 res = r;
5474 goto mailbox;
5475 }
5476
5477 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token,
5478 &status_info_list,
5479 (mailimap_struct_parser *)
5480 mailimap_status_info_parse,
5481 (mailimap_struct_destructor *)
5482 mailimap_status_info_free,
5483 progr_rate, progr_fun);
5484 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
5485 res = r;
5486 goto mailbox;
5487 }
5488
5489 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
5490 if (r != MAILIMAP_NO_ERROR) {
5491 res = r;
5492 goto status_info_list;
5493 }
5494
5495 data_status = mailimap_mailbox_data_status_new(mb, status_info_list);
5496 if (data_status == NULL) {
5497 res = MAILIMAP_ERROR_MEMORY;
5498 goto status_info_list;
5499 }
5500
5501 * result = data_status;
5502 * index = cur_token;
5503
5504 return MAILIMAP_NO_ERROR;
5505
5506 status_info_list:
5507 if (status_info_list != NULL) {
5508 clist_foreach(status_info_list, (clist_func) mailimap_status_info_free,
5509 NULL);
5510 clist_free(status_info_list);
5511 }
5512 mailbox:
5513 mailimap_mailbox_free(mb);
5514 err:
5515 return res;
5516}
5517
5518/*
5519 number SP "EXISTS"
5520*/
5521
5522static int
5523mailimap_mailbox_data_exists_parse(mailstream * fd, MMAPString * buffer,
5524 size_t * index,
5525 uint32_t * result)
5526{
5527 size_t cur_token;
5528 uint32_t number;
5529 int r;
5530
5531 cur_token = * index;
5532
5533 r = mailimap_number_parse(fd, buffer, &cur_token, &number);
5534 if (r != MAILIMAP_NO_ERROR)
5535 return r;
5536
5537 r = mailimap_space_parse(fd, buffer, &cur_token);
5538 if (r != MAILIMAP_NO_ERROR)
5539 return r;
5540
5541 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "EXISTS");
5542 if (r != MAILIMAP_NO_ERROR)
5543 return r;
5544
5545 * result = number;
5546 * index = cur_token;
5547
5548 return MAILIMAP_NO_ERROR;
5549}
5550
5551/*
5552 number SP "RECENT"
5553*/
5554
5555static int
5556mailimap_mailbox_data_recent_parse(mailstream * fd, MMAPString * buffer,
5557 size_t * index,
5558 uint32_t * result)
5559{
5560 size_t cur_token;
5561 uint32_t number;
5562 int r;
5563
5564 cur_token = * index;
5565
5566 r = mailimap_number_parse(fd, buffer, &cur_token, &number);
5567 if (r != MAILIMAP_NO_ERROR)
5568 return r;
5569
5570 r = mailimap_space_parse(fd, buffer, &cur_token);
5571 if (r != MAILIMAP_NO_ERROR)
5572 return r;
5573
5574 r = mailimap_token_case_insensitive_parse(fd, buffer,
5575 &cur_token, "RECENT");
5576 if (r != MAILIMAP_NO_ERROR)
5577 return r;
5578
5579 * result = number;
5580 * index = cur_token;
5581
5582 return MAILIMAP_NO_ERROR;
5583}
5584
5585/*
5586 mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list /
5587 "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) /
5588 "STATUS" SP mailbox SP "("
5589 [status-att SP number *(SP status-att SP number)] ")" /
5590 number SP "EXISTS" / number SP "RECENT"
5591*/
5592
5593static int
5594mailimap_mailbox_data_parse(mailstream * fd, MMAPString * buffer,
5595 size_t * index,
5596 struct mailimap_mailbox_data ** result,
5597 size_t progr_rate,
5598 progress_function * progr_fun)
5599{
5600 int type;
5601 struct mailimap_flag_list * data_flags;
5602 struct mailimap_mailbox_list * data_list;
5603 struct mailimap_mailbox_list * data_lsub;
5604 clist * data_search;
5605 struct mailimap_mailbox_data_status * data_status;
5606 uint32_t data_exists;
5607 uint32_t data_recent;
5608
5609 struct mailimap_mailbox_data * mailbox_data;
5610 size_t cur_token;
5611 int r;
5612 int res;
5613
5614 cur_token = * index;
5615
5616 data_flags = NULL;
5617 data_list = NULL;
5618 data_lsub = NULL;
5619 data_search = NULL;
5620 data_status = NULL;
5621 data_exists = 0;
5622 data_recent = 0;
5623
5624 type = MAILIMAP_MAILBOX_DATA_ERROR; /* XXX - removes a gcc warning */
5625
5626 r = mailimap_mailbox_data_flags_parse(fd, buffer, &cur_token,
5627 &data_flags,
5628 progr_rate, progr_fun);
5629 if (r == MAILIMAP_NO_ERROR)
5630 type = MAILIMAP_MAILBOX_DATA_FLAGS;
5631
5632 if (r == MAILIMAP_ERROR_PARSE) {
5633 r = mailimap_mailbox_data_list_parse(fd, buffer, &cur_token,
5634 &data_list,
5635 progr_rate, progr_fun);
5636 if (r == MAILIMAP_NO_ERROR)
5637 type = MAILIMAP_MAILBOX_DATA_LIST;
5638 }
5639
5640 if (r == MAILIMAP_ERROR_PARSE) {
5641 r = mailimap_mailbox_data_lsub_parse(fd, buffer, &cur_token,
5642 &data_lsub,
5643 progr_rate, progr_fun);
5644 if (r == MAILIMAP_NO_ERROR)
5645 type = MAILIMAP_MAILBOX_DATA_LSUB;
5646 }
5647
5648 if (r == MAILIMAP_ERROR_PARSE) {
5649 r = mailimap_mailbox_data_search_parse(fd, buffer, &cur_token,
5650 &data_search,
5651 progr_rate, progr_fun);
5652 if (r == MAILIMAP_NO_ERROR)
5653 type = MAILIMAP_MAILBOX_DATA_SEARCH;
5654 }
5655
5656 if (r == MAILIMAP_ERROR_PARSE) {
5657 r = mailimap_mailbox_data_status_parse(fd, buffer, &cur_token,
5658 &data_status,
5659 progr_rate, progr_fun);
5660 if (r == MAILIMAP_NO_ERROR)
5661 type = MAILIMAP_MAILBOX_DATA_STATUS;
5662 }
5663
5664 if (r == MAILIMAP_ERROR_PARSE) {
5665 r = mailimap_mailbox_data_exists_parse(fd, buffer, &cur_token,
5666 &data_exists);
5667 if (r == MAILIMAP_NO_ERROR)
5668 type = MAILIMAP_MAILBOX_DATA_EXISTS;
5669 }
5670
5671 if (r == MAILIMAP_ERROR_PARSE) {
5672 r = mailimap_mailbox_data_recent_parse(fd, buffer, &cur_token,
5673 &data_recent);
5674 if (r == MAILIMAP_NO_ERROR)
5675 type = MAILIMAP_MAILBOX_DATA_RECENT;
5676 }
5677
5678 if (r != MAILIMAP_NO_ERROR) {
5679 res = r;
5680 goto err;
5681 }
5682
5683 mailbox_data = mailimap_mailbox_data_new(type, data_flags, data_list,
5684 data_lsub, data_search,
5685 data_status,
5686 data_exists, data_recent);
5687
5688 if (mailbox_data == NULL) {
5689 res = MAILIMAP_ERROR_MEMORY;
5690 goto free;
5691 }
5692
5693 * result = mailbox_data;
5694 * index = cur_token;
5695
5696 return MAILIMAP_NO_ERROR;
5697
5698 free:
5699 if (data_flags != NULL)
5700 mailimap_flag_list_free(data_flags);
5701 if (data_list != NULL)
5702 mailimap_mailbox_list_free(data_list);
5703 if (data_lsub != NULL)
5704 mailimap_mailbox_list_free(data_lsub);
5705 if (data_search != NULL)
5706 mailimap_mailbox_data_search_free(data_search);
5707 if (data_status != NULL)
5708 mailimap_mailbox_data_status_free(data_status);
5709 err:
5710 return res;
5711}
5712
5713/*
5714 mailbox-list = "(" [mbx-list-flags] ")" SP
5715 (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox
5716*/
5717
5718/*
5719 DQUOTE QUOTED-CHAR DQUOTE
5720*/
5721
5722static int
5723mailimap_mailbox_list_quoted_char_parse(mailstream * fd, MMAPString * buffer,
5724 size_t * index,
5725 char * result)
5726{
5727 size_t cur_token;
5728 char ch;
5729 int r;
5730
5731 cur_token = * index;
5732
5733 r = mailimap_dquote_parse(fd, buffer, &cur_token);
5734 if (r != MAILIMAP_NO_ERROR)
5735 return r;
5736
5737 r = mailimap_quoted_char_parse(fd, buffer, &cur_token, &ch);
5738 if (r != MAILIMAP_NO_ERROR)
5739 return r;
5740
5741 r = mailimap_dquote_parse(fd, buffer, &cur_token);
5742 if (r != MAILIMAP_NO_ERROR)
5743 return r;
5744
5745 * index = cur_token;
5746 * result = ch;
5747
5748 return MAILIMAP_NO_ERROR;
5749}
5750
5751static int
5752mailimap_mailbox_list_parse(mailstream * fd, MMAPString * buffer,
5753 size_t * index,
5754 struct mailimap_mailbox_list ** result,
5755 size_t progr_rate,
5756 progress_function * progr_fun)
5757{
5758 struct mailimap_mailbox_list * mb_list;
5759 struct mailimap_mbx_list_flags * mb_flag_list;
5760 char ch;
5761 char * mb;
5762 size_t cur_token;
5763 int r;
5764 int res;
5765
5766 cur_token = * index;
5767
5768 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
5769 if (r != MAILIMAP_NO_ERROR) {
5770 res = r;
5771 goto err;
5772 }
5773
5774 mb_flag_list = NULL;
5775 ch = 0;
5776 mb = NULL;
5777
5778 r = mailimap_mbx_list_flags_parse(fd, buffer, &cur_token,
5779 &mb_flag_list, progr_rate, progr_fun);
5780 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
5781 res = r;
5782 goto err;
5783 }
5784
5785 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
5786 if (r != MAILIMAP_NO_ERROR) {
5787 res = r;
5788 goto free_list_flags;
5789 }
5790
5791 r = mailimap_space_parse(fd, buffer, &cur_token);
5792 if (r != MAILIMAP_NO_ERROR) {
5793 res = r;
5794 goto free_list_flags;
5795 }
5796
5797 r = mailimap_mailbox_list_quoted_char_parse(fd, buffer, &cur_token, &ch);
5798 if (r == MAILIMAP_ERROR_PARSE)
5799 r = mailimap_nil_parse(fd, buffer, &cur_token);
5800
5801 if (r != MAILIMAP_NO_ERROR) {
5802 res = r;
5803 goto free_list_flags;
5804 }
5805
5806 r = mailimap_space_parse(fd, buffer, &cur_token);
5807 if (r != MAILIMAP_NO_ERROR) {
5808 res = r;
5809 goto free_list_flags;
5810 }
5811
5812 r = mailimap_mailbox_parse(fd, buffer, &cur_token, &mb,
5813 progr_rate, progr_fun);
5814 if (r != MAILIMAP_NO_ERROR) {
5815 res = r;
5816 goto free_list_flags;
5817 }
5818
5819 mb_list = mailimap_mailbox_list_new(mb_flag_list, ch, mb);
5820 if (mb_list == NULL) {
5821 res = MAILIMAP_ERROR_MEMORY;
5822 goto free_mailbox;
5823 }
5824
5825 * result = mb_list;
5826 * index = cur_token;
5827
5828 return MAILIMAP_NO_ERROR;
5829
5830 free_mailbox:
5831 mailimap_mailbox_free(mb);
5832 free_list_flags:
5833 if (mb_flag_list != NULL)
5834 mailimap_mbx_list_flags_free(mb_flag_list);
5835 err:
5836 return res;
5837}
5838
5839/*
5840 mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag
5841 *(SP mbx-list-oflag) /
5842 mbx-list-oflag *(SP mbx-list-oflag)
5843*/
5844
5845static int
5846mailimap_mbx_list_flags_parse(mailstream * fd, MMAPString * buffer,
5847 size_t * index,
5848 struct mailimap_mbx_list_flags ** result,
5849 size_t progr_rate,
5850 progress_function * progr_fun)
5851{
5852 struct mailimap_mbx_list_flags * mbx_list_flag;
5853 size_t cur_token;
5854 clist * oflags;
5855 clist * oflags_2;
5856 int sflag;
5857 int type;
5858 int r;
5859 int res;
5860 size_t final_token;
5861 int try_sflag;
5862
5863 cur_token = * index;
5864 final_token = cur_token;
5865
5866 oflags = clist_new();
5867 if (oflags == NULL) {
5868 res = MAILIMAP_ERROR_MEMORY;
5869 goto err;
5870 }
5871
5872 sflag = MAILIMAP_MBX_LIST_SFLAG_ERROR;
5873 oflags_2 = NULL;
5874
5875 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token,
5876 &oflags_2,
5877 (mailimap_struct_parser *)
5878 mailimap_mbx_list_oflag_no_sflag_parse,
5879 (mailimap_struct_destructor *)
5880 mailimap_mbx_list_oflag_free,
5881 progr_rate, progr_fun);
5882 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
5883 res = r;
5884 goto free;
5885 }
5886
5887 try_sflag = 1;
5888 if (r == MAILIMAP_NO_ERROR) {
5889 clist_concat(oflags, oflags_2);
5890 clist_free(oflags_2);
5891
5892 final_token = cur_token;
5893 try_sflag = 0;
5894 r = mailimap_space_parse(fd, buffer, &cur_token);
5895 if (r == MAILIMAP_NO_ERROR)
5896 try_sflag = 1;
5897 }
5898
5899 type = MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG;
5900 if (try_sflag) {
5901 r = mailimap_mbx_list_sflag_parse(fd, buffer, &cur_token, &sflag);
5902 switch (r) {
5903 case MAILIMAP_ERROR_PARSE:
5904 type = MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG;
5905 break;
5906
5907 case MAILIMAP_NO_ERROR:
5908 type = MAILIMAP_MBX_LIST_FLAGS_SFLAG;
5909
5910 final_token = cur_token;
5911 r = mailimap_space_parse(fd, buffer, &cur_token);
5912 if (r == MAILIMAP_NO_ERROR) {
5913 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token,
5914 &oflags_2,
5915 (mailimap_struct_parser *) mailimap_mbx_list_oflag_parse,
5916 (mailimap_struct_destructor *) mailimap_mbx_list_oflag_free,
5917 progr_rate, progr_fun);
5918 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
5919 res = r;
5920 goto err;
5921 }
5922
5923 if (r == MAILIMAP_NO_ERROR) {
5924 clist_concat(oflags, oflags_2);
5925 clist_free(oflags_2);
5926
5927 final_token = cur_token;
5928 }
5929 }
5930
5931 break;
5932
5933 default:
5934 res = r;
5935 goto free;
5936 }
5937 }
5938
5939 if ((clist_count(oflags) == 0) && (type == MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG)) {
5940 res = MAILIMAP_ERROR_PARSE;
5941 goto free;
5942 }
5943
5944 cur_token = final_token;
5945 mbx_list_flag = mailimap_mbx_list_flags_new(type, oflags, sflag);
5946 if (mbx_list_flag == NULL) {
5947 res = MAILIMAP_ERROR_MEMORY;
5948 goto free;
5949 }
5950
5951 * result = mbx_list_flag;
5952 * index = cur_token;
5953
5954 return MAILIMAP_NO_ERROR;
5955
5956free:
5957 clist_foreach(oflags, (clist_func) mailimap_mbx_list_oflag_free, NULL);
5958 clist_free(oflags);
5959err:
5960 return res;
5961}
5962
5963/*
5964 mbx-list-oflag = "\Noinferiors" / flag-extension
5965 ; Other flags; multiple possible per LIST response
5966*/
5967
5968static int
5969mailimap_mbx_list_oflag_parse(mailstream * fd, MMAPString * buffer,
5970 size_t * index,
5971 struct mailimap_mbx_list_oflag ** result,
5972 size_t progr_rate,
5973 progress_function * progr_fun)
5974{
5975 int type;
5976 size_t cur_token;
5977 struct mailimap_mbx_list_oflag * oflag;
5978 char * flag_ext;
5979 int r;
5980 int res;
5981 int sflag_type;
5982
5983 cur_token = * index;
5984 flag_ext = NULL;
5985 type = MAILIMAP_MBX_LIST_OFLAG_ERROR; /* XXX - removes a gcc warning */
5986
5987 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
5988 "\\Noinferiors");
5989 if (r == MAILIMAP_NO_ERROR)
5990 type = MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS;
5991
5992 if (r == MAILIMAP_ERROR_PARSE) {
5993 r = mailimap_flag_extension_parse(fd, buffer, &cur_token,
5994 &flag_ext, progr_rate, progr_fun);
5995 if (r == MAILIMAP_NO_ERROR)
5996 type = MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT;
5997 }
5998
5999 if (r != MAILIMAP_NO_ERROR) {
6000 res = r;
6001 goto err;
6002 }
6003
6004 oflag = mailimap_mbx_list_oflag_new(type, flag_ext);
6005 if (oflag == NULL) {
6006 res = MAILIMAP_ERROR_MEMORY;
6007 goto free;
6008 }
6009
6010 * result = oflag;
6011 * index = cur_token;
6012
6013 return MAILIMAP_NO_ERROR;
6014
6015 free:
6016 if (flag_ext != NULL)
6017 mailimap_flag_extension_free(flag_ext);
6018 err:
6019 return res;
6020}
6021
6022static int
6023mailimap_mbx_list_oflag_no_sflag_parse(mailstream * fd, MMAPString * buffer,
6024 size_t * index,
6025 struct mailimap_mbx_list_oflag ** result,
6026 size_t progr_rate,
6027 progress_function * progr_fun)
6028{
6029 size_t cur_token;
6030 int sflag_type;
6031 int r;
6032
6033 cur_token = * index;
6034
6035 r = mailimap_mbx_list_sflag_parse(fd, buffer, &cur_token, &sflag_type);
6036 if (r == MAILIMAP_NO_ERROR)
6037 return MAILIMAP_ERROR_PARSE;
6038
6039 return mailimap_mbx_list_oflag_parse(fd, buffer, index, result,
6040 progr_rate, progr_fun);
6041}
6042
6043
6044/*
6045 mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked"
6046 ; Selectability flags; only one per LIST response
6047*/
6048
6049static int
6050mailimap_mbx_list_sflag_parse(mailstream * fd, MMAPString * buffer,
6051 size_t * index,
6052 int * result)
6053{
6054 int type;
6055 size_t cur_token;
6056
6057 cur_token = * index;
6058
6059 type = mailimap_mbx_list_sflag_get_token_value(fd, buffer, &cur_token);
6060 if (type == -1)
6061 return MAILIMAP_ERROR_PARSE;
6062
6063 * result = type;
6064 * index = cur_token;
6065
6066 return MAILIMAP_NO_ERROR;
6067}
6068
6069
6070/*
6071 media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" /
6072 "VIDEO") DQUOTE) / string) SP media-subtype
6073 ; Defined in [MIME-IMT]
6074*/
6075
6076/*
6077 DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" /
6078 "VIDEO") DQUOTE
6079*/
6080
6081static int
6082mailimap_media_basic_standard_parse(mailstream * fd, MMAPString * buffer,
6083 size_t * index,
6084 int * result)
6085{
6086 size_t cur_token;
6087 int type;
6088 int r;
6089
6090 cur_token = * index;
6091
6092 r = mailimap_dquote_parse(fd, buffer, &cur_token);
6093 if (r != MAILIMAP_NO_ERROR)
6094 return r;
6095
6096 type = mailimap_media_basic_get_token_value(fd, buffer, &cur_token);
6097 if (type == -1)
6098 return MAILIMAP_ERROR_PARSE;
6099
6100 r = mailimap_dquote_parse(fd, buffer, &cur_token);
6101 if (r != MAILIMAP_NO_ERROR)
6102 return FALSE;
6103
6104 * index = cur_token;
6105 * result = type;
6106
6107 return MAILIMAP_NO_ERROR;
6108}
6109
6110/*
6111 media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" /
6112 "VIDEO") DQUOTE) / string) SP media-subtype
6113 ; Defined in [MIME-IMT]
6114*/
6115
6116static int
6117mailimap_media_basic_parse(mailstream * fd, MMAPString * buffer,
6118 size_t * index,
6119 struct mailimap_media_basic ** result,
6120 size_t progr_rate,
6121 progress_function * progr_fun)
6122{
6123 size_t cur_token;
6124 int type;
6125 char * basic_type;
6126 char * subtype;
6127 struct mailimap_media_basic * media_basic;
6128 int r;
6129 int res;
6130
6131 cur_token = * index;
6132
6133 basic_type = NULL;
6134 subtype = NULL;
6135
6136 r = mailimap_media_basic_standard_parse(fd, buffer, &cur_token,
6137 &type);
6138
6139 if (r == MAILIMAP_ERROR_PARSE) {
6140 r = mailimap_string_parse(fd, buffer, &cur_token, &basic_type, NULL,
6141 progr_rate, progr_fun);
6142 if (r == MAILIMAP_NO_ERROR)
6143 type = MAILIMAP_MEDIA_BASIC_OTHER;
6144 }
6145
6146 if (r != MAILIMAP_NO_ERROR) {
6147 res = r;
6148 goto err;
6149 }
6150
6151 r = mailimap_space_parse(fd, buffer, &cur_token);
6152 if (r != MAILIMAP_NO_ERROR) {
6153 res = r;
6154 goto free_basic_type;
6155 }
6156
6157 r = mailimap_media_subtype_parse(fd, buffer, &cur_token, &subtype,
6158 progr_rate, progr_fun);
6159 if (r != MAILIMAP_NO_ERROR) {
6160 res = r;
6161 goto free_basic_type;
6162 }
6163
6164 media_basic = mailimap_media_basic_new(type, basic_type, subtype);
6165 if (media_basic == NULL) {
6166 res = MAILIMAP_ERROR_MEMORY;
6167 goto free_subtype;
6168 }
6169
6170 * result = media_basic;
6171 * index = cur_token;
6172
6173 return MAILIMAP_NO_ERROR;
6174
6175 free_subtype:
6176 mailimap_media_subtype_free(subtype);
6177 free_basic_type:
6178 if (basic_type != NULL)
6179 mailimap_string_free(basic_type);
6180 err:
6181 return res;
6182}
6183
6184
6185/*
6186 media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE
6187 ; Defined in [MIME-IMT]
6188*/
6189
6190static int
6191mailimap_media_message_parse(mailstream * fd, MMAPString * buffer,
6192 size_t * index)
6193{
6194 size_t cur_token;
6195 int r;
6196
6197 cur_token = * index;
6198
6199 r = mailimap_dquote_parse(fd, buffer, &cur_token);
6200 if (r != MAILIMAP_NO_ERROR)
6201 return r;
6202
6203 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6204 "MESSAGE");
6205 if (r != MAILIMAP_NO_ERROR)
6206 return r;
6207
6208 r = mailimap_dquote_parse(fd, buffer, &cur_token);
6209 if (r != MAILIMAP_NO_ERROR)
6210 return r;
6211
6212 r = mailimap_space_parse(fd, buffer, &cur_token);
6213 if (r != MAILIMAP_NO_ERROR)
6214 return r;
6215
6216 r = mailimap_dquote_parse(fd, buffer, &cur_token);
6217 if (r != MAILIMAP_NO_ERROR)
6218 return r;
6219
6220 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6221 "RFC822");
6222 if (r != MAILIMAP_NO_ERROR)
6223 return r;
6224
6225 r = mailimap_dquote_parse(fd, buffer, &cur_token);
6226 if (r != MAILIMAP_NO_ERROR)
6227 return r;
6228
6229 * index = cur_token;
6230
6231 return MAILIMAP_NO_ERROR;
6232}
6233
6234/*
6235 media-subtype = string
6236 ; Defined in [MIME-IMT]
6237*/
6238
6239static int
6240mailimap_media_subtype_parse(mailstream * fd, MMAPString * buffer,
6241 size_t * index,
6242 char ** result,
6243 size_t progr_rate,
6244 progress_function * progr_fun)
6245{
6246 return mailimap_string_parse(fd, buffer, index, result, NULL,
6247 progr_rate, progr_fun);
6248}
6249
6250/*
6251 media-text = DQUOTE "TEXT" DQUOTE SP media-subtype
6252 ; Defined in [MIME-IMT]
6253*/
6254
6255static int mailimap_media_text_parse(mailstream * fd, MMAPString * buffer,
6256 size_t * index,
6257 char ** result,
6258 size_t progr_rate,
6259 progress_function * progr_fun)
6260{
6261 size_t cur_token;
6262 char * media_subtype;
6263 int r;
6264
6265 cur_token = * index;
6266
6267 r = mailimap_dquote_parse(fd, buffer, &cur_token);
6268 if (r != MAILIMAP_NO_ERROR)
6269 return r;
6270
6271 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6272 "TEXT");
6273 if (r != MAILIMAP_NO_ERROR)
6274 return r;
6275
6276 r = mailimap_dquote_parse(fd, buffer, &cur_token);
6277 if (r != MAILIMAP_NO_ERROR)
6278 return r;
6279
6280 r = mailimap_space_parse(fd, buffer, &cur_token);
6281 if (r != MAILIMAP_NO_ERROR)
6282 return r;
6283
6284 r = mailimap_media_subtype_parse(fd, buffer, &cur_token, &media_subtype,
6285 progr_rate, progr_fun);
6286 if (r != MAILIMAP_NO_ERROR)
6287 return r;
6288
6289 * result = media_subtype;
6290 * index = cur_token;
6291
6292 return MAILIMAP_NO_ERROR;
6293}
6294
6295
6296/*
6297 message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att))
6298*/
6299
6300
6301static int
6302mailimap_message_data_parse(mailstream * fd, MMAPString * buffer,
6303 size_t * index,
6304 struct mailimap_message_data ** result,
6305 size_t progr_rate,
6306 progress_function * progr_fun)
6307{
6308 size_t cur_token;
6309 uint32_t number;
6310 int type;
6311 struct mailimap_msg_att * msg_att;
6312 struct mailimap_message_data * msg_data;
6313 int r;
6314 int res;
6315
6316 cur_token = * index;
6317 msg_att = NULL;
6318
6319 r = mailimap_nz_number_parse(fd, buffer, &cur_token, &number);
6320 if (r != MAILIMAP_NO_ERROR) {
6321 res = r;
6322 goto err;
6323 }
6324
6325 r = mailimap_space_parse(fd, buffer, &cur_token);
6326 if (r != MAILIMAP_NO_ERROR) {
6327 res = r;
6328 goto err;
6329 }
6330
6331 type = MAILIMAP_MESSAGE_DATA_ERROR; /* XXX - removes a gcc warning */
6332
6333 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6334 "EXPUNGE");
6335 if (r == MAILIMAP_NO_ERROR)
6336 type = MAILIMAP_MESSAGE_DATA_EXPUNGE;
6337
6338 if (r == MAILIMAP_ERROR_PARSE) {
6339 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6340 "FETCH");
6341 if (r != MAILIMAP_NO_ERROR) {
6342 res = r;
6343 goto err;
6344 }
6345
6346 r = mailimap_space_parse(fd, buffer, &cur_token);
6347 if (r != MAILIMAP_NO_ERROR) {
6348 res = r;
6349 goto err;
6350 }
6351
6352 r = mailimap_msg_att_parse(fd, buffer, &cur_token, &msg_att,
6353 progr_rate, progr_fun);
6354 if (r != MAILIMAP_NO_ERROR) {
6355 res = r;
6356 goto err;
6357 }
6358
6359 type = MAILIMAP_MESSAGE_DATA_FETCH;
6360 }
6361
6362 if (r != MAILIMAP_NO_ERROR) {
6363 res = r;
6364 goto err;
6365 }
6366
6367 msg_data = mailimap_message_data_new(number, type, msg_att);
6368 if (msg_data == NULL) {
6369 res = MAILIMAP_ERROR_MEMORY;
6370 goto free_msg_att;
6371 }
6372
6373 * result = msg_data;
6374 * index = cur_token;
6375
6376 return MAILIMAP_NO_ERROR;
6377
6378 free_msg_att:
6379 if (msg_att != NULL)
6380 mailimap_msg_att_free(msg_att);
6381 err:
6382 return res;
6383}
6384
6385/*
6386 msg-att = "(" (msg-att-dynamic / msg-att-static)
6387 *(SP (msg-att-dynamic / msg-att-static)) ")"
6388*/
6389
6390/*
6391 msg-att-dynamic / msg-att-static
6392*/
6393
6394static int
6395mailimap_msg_att_item_parse(mailstream * fd, MMAPString * buffer,
6396 size_t * index,
6397 struct mailimap_msg_att_item ** result,
6398 size_t progr_rate,
6399 progress_function * progr_fun)
6400{
6401 int type;
6402 struct mailimap_msg_att_dynamic * msg_att_dynamic;
6403 struct mailimap_msg_att_static * msg_att_static;
6404 size_t cur_token;
6405 struct mailimap_msg_att_item * item;
6406 int r;
6407 int res;
6408
6409 cur_token = * index;
6410
6411 msg_att_dynamic = NULL;
6412 msg_att_static = NULL;
6413
6414 type = MAILIMAP_MSG_ATT_ITEM_ERROR; /* XXX - removes a gcc warning */
6415
6416 r = mailimap_msg_att_dynamic_parse(fd, buffer, &cur_token,
6417 &msg_att_dynamic,
6418 progr_rate, progr_fun);
6419 if (r == MAILIMAP_NO_ERROR)
6420 type = MAILIMAP_MSG_ATT_ITEM_DYNAMIC;
6421
6422 if (r == MAILIMAP_ERROR_PARSE) {
6423 r = mailimap_msg_att_static_parse(fd, buffer, &cur_token,
6424 &msg_att_static,
6425 progr_rate, progr_fun);
6426 if (r == MAILIMAP_NO_ERROR)
6427 type = MAILIMAP_MSG_ATT_ITEM_STATIC;
6428 }
6429
6430 if (r != MAILIMAP_NO_ERROR) {
6431 res = r;
6432 goto err;
6433 }
6434
6435 item = mailimap_msg_att_item_new(type, msg_att_dynamic, msg_att_static);
6436 if (item == NULL) {
6437 res = MAILIMAP_ERROR_MEMORY;
6438 goto free;
6439 }
6440
6441 * result = item;
6442 * index = cur_token;
6443
6444 return MAILIMAP_NO_ERROR;
6445
6446 free:
6447 if (msg_att_dynamic != NULL)
6448 mailimap_msg_att_dynamic_free(msg_att_dynamic);
6449 if (msg_att_static != NULL)
6450 mailimap_msg_att_static_free(msg_att_static);
6451 err:
6452 return res;
6453}
6454
6455/*
6456 msg-att = "(" (msg-att-dynamic / msg-att-static)
6457 *(SP (msg-att-dynamic / msg-att-static)) ")"
6458*/
6459
6460static int
6461mailimap_msg_att_parse(mailstream * fd, MMAPString * buffer,
6462 size_t * index, struct mailimap_msg_att ** result,
6463 size_t progr_rate,
6464 progress_function * progr_fun)
6465{
6466 size_t cur_token;
6467 clist * list;
6468 struct mailimap_msg_att * msg_att;
6469 int r;
6470 int res;
6471
6472 cur_token = * index;
6473 list = NULL;
6474
6475 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
6476 if (r != MAILIMAP_NO_ERROR) {
6477 res = r;
6478 goto err;
6479 }
6480
6481 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list,
6482 (mailimap_struct_parser *)
6483 mailimap_msg_att_item_parse,
6484 (mailimap_struct_destructor *)
6485 mailimap_msg_att_item_free,
6486 progr_rate, progr_fun);
6487 if (r != MAILIMAP_NO_ERROR) {
6488 res = r;
6489 goto err;
6490 }
6491
6492 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
6493 if (r != MAILIMAP_NO_ERROR) {
6494 res = r;
6495 goto free;
6496 }
6497
6498 msg_att = mailimap_msg_att_new(list);
6499 if (msg_att == NULL) {
6500 res = MAILIMAP_ERROR_MEMORY;
6501 goto free;
6502 }
6503
6504 * index = cur_token;
6505 * result = msg_att;
6506
6507 return MAILIMAP_NO_ERROR;
6508
6509 free:
6510 clist_foreach(list, (clist_func) mailimap_msg_att_item_free, NULL);
6511 clist_free(list);
6512 err:
6513 return res;
6514}
6515
6516/*
6517 msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")"
6518 ; MAY change for a message
6519*/
6520
6521
6522static int
6523mailimap_msg_att_dynamic_parse(mailstream * fd, MMAPString * buffer,
6524 size_t * index,
6525 struct mailimap_msg_att_dynamic ** result,
6526 size_t progr_rate,
6527 progress_function * progr_fun)
6528{
6529 clist * list;
6530 struct mailimap_msg_att_dynamic * msg_att_dyn;
6531 size_t cur_token;
6532 int r;
6533 int res;
6534
6535 cur_token = * index;
6536
6537 list = NULL;
6538
6539 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "FLAGS");
6540 if (r != MAILIMAP_NO_ERROR) {
6541 res = r;
6542 goto err;
6543 }
6544
6545 r = mailimap_space_parse(fd, buffer, &cur_token);
6546 if (r != MAILIMAP_NO_ERROR) {
6547 res = r;
6548 goto err;
6549 }
6550
6551 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
6552 if (r != MAILIMAP_NO_ERROR) {
6553 res = r;
6554 goto err;
6555 }
6556
6557 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token,
6558 &list,
6559 (mailimap_struct_parser *)
6560 mailimap_flag_fetch_parse,
6561 (mailimap_struct_destructor *)
6562 mailimap_flag_fetch_free,
6563 progr_rate, progr_fun);
6564 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
6565 res = r;
6566 goto err;
6567 }
6568
6569 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
6570 if (r != MAILIMAP_NO_ERROR) {
6571 res = r;
6572 goto free;
6573 }
6574
6575 msg_att_dyn = mailimap_msg_att_dynamic_new(list);
6576 if (msg_att_dyn == NULL) {
6577 res = MAILIMAP_ERROR_MEMORY;
6578 goto free;
6579 }
6580
6581 * result = msg_att_dyn;
6582 * index = cur_token;
6583
6584 return MAILIMAP_NO_ERROR;
6585
6586 free:
6587 if (list != NULL) {
6588 clist_foreach(list, (clist_func) mailimap_flag_fetch_free, NULL);
6589 clist_free(list);
6590 }
6591 err:
6592 return res;
6593}
6594
6595/*
6596 msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time /
6597 "RFC822" [".HEADER" / ".TEXT"] SP nstring /
6598 "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body /
6599 "BODY" section ["<" number ">"] SP nstring /
6600 "UID" SP uniqueid
6601 ; MUST NOT change for a message
6602*/
6603
6604/*
6605 "ENVELOPE" SP envelope
6606*/
6607
6608
6609static int
6610mailimap_msg_att_envelope_parse(mailstream * fd,
6611 MMAPString * buffer,
6612 size_t * index,
6613 struct mailimap_envelope ** result,
6614 size_t progr_rate,
6615 progress_function * progr_fun)
6616{
6617 size_t cur_token;
6618 struct mailimap_envelope * env;
6619 int r;
6620
6621 cur_token = * index;
6622
6623 r = mailimap_token_case_insensitive_parse(fd, buffer,
6624 &cur_token, "ENVELOPE");
6625 if (r != MAILIMAP_NO_ERROR)
6626 return r;
6627
6628 r = mailimap_space_parse(fd, buffer, &cur_token);
6629 if (r != MAILIMAP_NO_ERROR)
6630 return r;
6631
6632 r = mailimap_envelope_parse(fd, buffer, &cur_token, &env,
6633 progr_rate, progr_fun);
6634 if (r != MAILIMAP_NO_ERROR)
6635 return r;
6636
6637 * index = cur_token;
6638 * result = env;
6639
6640 return MAILIMAP_NO_ERROR;
6641}
6642
6643
6644/*
6645 "INTERNALDATE" SP date-time
6646*/
6647
6648
6649static int
6650mailimap_msg_att_internaldate_parse(mailstream * fd, MMAPString * buffer,
6651 size_t * index,
6652 struct mailimap_date_time ** result,
6653 size_t progr_rate,
6654 progress_function * progr_fun)
6655{
6656 size_t cur_token;
6657 struct mailimap_date_time * date_time;
6658 int r;
6659
6660 cur_token = * index;
6661
6662 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6663 "INTERNALDATE");
6664 if (r != MAILIMAP_NO_ERROR)
6665 return r;
6666
6667 r = mailimap_space_parse(fd, buffer, &cur_token);
6668 if (r != MAILIMAP_NO_ERROR)
6669 return FALSE;
6670
6671 r = mailimap_date_time_parse(fd, buffer, &cur_token, &date_time,
6672 progr_rate, progr_fun);
6673 if (r != MAILIMAP_NO_ERROR)
6674 return r;
6675
6676 * result = date_time;
6677 * index = cur_token;
6678
6679 return MAILIMAP_NO_ERROR;
6680}
6681
6682/*
6683 "RFC822" SP nstring
6684*/
6685
6686static int
6687mailimap_msg_att_rfc822_parse(mailstream * fd, MMAPString * buffer,
6688 size_t * index, char ** result,
6689 size_t * result_len,
6690 size_t progr_rate,
6691 progress_function * progr_fun)
6692{
6693 size_t cur_token;
6694 char * rfc822_message;
6695 int r;
6696 size_t length;
6697
6698 cur_token = * index;
6699
6700 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6701 "RFC822");
6702 if (r != MAILIMAP_NO_ERROR)
6703 return r;
6704
6705 r = mailimap_space_parse(fd, buffer, &cur_token);
6706 if (r != MAILIMAP_NO_ERROR)
6707 return r;
6708
6709 r = mailimap_nstring_parse(fd, buffer, &cur_token, &rfc822_message, &length,
6710 progr_rate, progr_fun);
6711 if (r != MAILIMAP_NO_ERROR)
6712 return r;
6713
6714 * result = rfc822_message;
6715 if (result_len != NULL)
6716 * result_len = length;
6717 * index = cur_token;
6718
6719 return MAILIMAP_NO_ERROR;
6720}
6721
6722/*
6723 "RFC822" ".HEADER" SP nstring
6724*/
6725
6726static int
6727mailimap_msg_att_rfc822_header_parse(mailstream * fd, MMAPString * buffer,
6728 size_t * index, char ** result,
6729 size_t * result_len,
6730 size_t progr_rate,
6731 progress_function * progr_fun)
6732{
6733 size_t cur_token;
6734 char * rfc822_header;
6735 int r;
6736 size_t length;
6737
6738 cur_token = * index;
6739
6740 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6741 "RFC822");
6742 if (r != MAILIMAP_NO_ERROR)
6743 return r;
6744
6745 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6746 ".HEADER");
6747 if (r != MAILIMAP_NO_ERROR)
6748 return r;
6749
6750 r = mailimap_space_parse(fd, buffer, &cur_token);
6751 if (r != MAILIMAP_NO_ERROR)
6752 return r;
6753
6754 r = mailimap_nstring_parse(fd, buffer, &cur_token, &rfc822_header, &length,
6755 progr_rate, progr_fun);
6756 if (r != MAILIMAP_NO_ERROR)
6757 return r;
6758
6759 * result = rfc822_header;
6760 if (result_len != NULL)
6761 * result_len = length;
6762 * index = cur_token;
6763
6764 return MAILIMAP_NO_ERROR;
6765}
6766
6767/*
6768 "RFC822" ".TEXT" SP nstring
6769*/
6770
6771static int
6772mailimap_msg_att_rfc822_text_parse(mailstream * fd, MMAPString * buffer,
6773 size_t * index, char ** result,
6774 size_t * result_len,
6775 size_t progr_rate,
6776 progress_function * progr_fun)
6777{
6778 size_t cur_token;
6779 char * rfc822_text;
6780 int r;
6781 size_t length;
6782
6783 cur_token = * index;
6784
6785 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6786 "RFC822");
6787 if (r != MAILIMAP_NO_ERROR)
6788 return r;
6789
6790 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6791 ".TEXT");
6792 if (r != MAILIMAP_NO_ERROR)
6793 return r;
6794
6795 r = mailimap_space_parse(fd, buffer, &cur_token);
6796 if (r != MAILIMAP_NO_ERROR)
6797 return r;
6798
6799 r = mailimap_nstring_parse(fd, buffer, &cur_token, &rfc822_text, &length,
6800 progr_rate, progr_fun);
6801 if (r != MAILIMAP_NO_ERROR)
6802 return r;
6803
6804 * result = rfc822_text;
6805 if (result_len != NULL)
6806 * result_len = length;
6807 * index = cur_token;
6808
6809 return MAILIMAP_NO_ERROR;
6810}
6811
6812/*
6813 "RFC822.SIZE" SP number
6814*/
6815
6816static int
6817mailimap_msg_att_rfc822_size_parse(mailstream * fd, MMAPString * buffer,
6818 size_t * index, uint32_t * result)
6819{
6820 size_t cur_token;
6821 uint32_t number;
6822 int r;
6823
6824 cur_token = * index;
6825
6826 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6827 "RFC822.SIZE");
6828 if (r != MAILIMAP_NO_ERROR)
6829 return r;
6830
6831 r = mailimap_space_parse(fd, buffer, &cur_token);
6832 if (r != MAILIMAP_NO_ERROR)
6833 return r;
6834
6835 r = mailimap_number_parse(fd, buffer, &cur_token, &number);
6836 if (r != MAILIMAP_NO_ERROR)
6837 return r;
6838
6839 * result = number;
6840 * index = cur_token;
6841
6842 return MAILIMAP_NO_ERROR;
6843}
6844
6845/*
6846 "BODY" SP body
6847*/
6848
6849
6850static int
6851mailimap_msg_att_body_parse(mailstream * fd, MMAPString * buffer,
6852 size_t * index, struct mailimap_body ** result,
6853 size_t progr_rate,
6854 progress_function * progr_fun)
6855{
6856 struct mailimap_body * body;
6857 size_t cur_token;
6858 int r;
6859
6860 cur_token = * index;
6861
6862 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6863 "BODY");
6864 if (r != MAILIMAP_NO_ERROR)
6865 return r;
6866
6867 r = mailimap_space_parse(fd, buffer, &cur_token);
6868 if (r != MAILIMAP_NO_ERROR)
6869 return r;
6870
6871 r = mailimap_body_parse(fd, buffer, &cur_token, &body,
6872 progr_rate, progr_fun);
6873 if (r != MAILIMAP_NO_ERROR)
6874 return r;
6875
6876 * result = body;
6877 * index = cur_token;
6878
6879 return MAILIMAP_NO_ERROR;
6880}
6881
6882/*
6883 "BODY" "STRUCTURE" SP body
6884*/
6885
6886
6887static int
6888mailimap_msg_att_bodystructure_parse(mailstream * fd, MMAPString * buffer,
6889 size_t * index,
6890 struct mailimap_body ** result,
6891 size_t progr_rate,
6892 progress_function * progr_fun)
6893{
6894 struct mailimap_body * body;
6895 size_t cur_token;
6896 int r;
6897
6898 cur_token = * index;
6899
6900 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6901 "BODY");
6902 if (r != MAILIMAP_NO_ERROR)
6903 return r;
6904
6905 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6906 "STRUCTURE");
6907 if (r != MAILIMAP_NO_ERROR)
6908 return r;
6909
6910 r = mailimap_space_parse(fd, buffer, &cur_token);
6911 if (r != MAILIMAP_NO_ERROR)
6912 return r;
6913
6914 r = mailimap_body_parse(fd, buffer, &cur_token, &body,
6915 progr_rate, progr_fun);
6916 if (r != MAILIMAP_NO_ERROR)
6917 return r;
6918
6919 * result = body;
6920 * index = cur_token;
6921
6922 return MAILIMAP_NO_ERROR;
6923}
6924
6925/*
6926 "BODY" section ["<" number ">"] SP nstring
6927*/
6928
6929static int
6930mailimap_msg_att_body_section_parse(mailstream * fd, MMAPString * buffer,
6931 size_t * index,
6932 struct mailimap_msg_att_body_section **
6933 result,
6934 size_t progr_rate,
6935 progress_function * progr_fun)
6936{
6937 size_t cur_token;
6938 uint32_t number;
6939 struct mailimap_section * section;
6940 char * body_part;
6941 struct mailimap_msg_att_body_section * msg_att_body_section;
6942 int r;
6943 int res;
6944 size_t length;
6945
6946 cur_token = * index;
6947
6948 section = NULL;
6949 number = 0;
6950 body_part = NULL;
6951
6952 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6953 "BODY");
6954 if (r != MAILIMAP_NO_ERROR) {
6955 res = r;
6956 goto err;
6957 }
6958
6959 r = mailimap_section_parse(fd, buffer, &cur_token, &section,
6960 progr_rate, progr_fun);
6961 if (r != MAILIMAP_NO_ERROR) {
6962 res = r;
6963 goto err;
6964 }
6965
6966 r = mailimap_lower_parse(fd, buffer, &cur_token);
6967 switch (r) {
6968 case MAILIMAP_NO_ERROR:
6969 r = mailimap_number_parse(fd, buffer, &cur_token, &number);
6970 if (r != MAILIMAP_NO_ERROR) {
6971 res = r;
6972 goto free_section;
6973 }
6974
6975 r = mailimap_greater_parse(fd, buffer, &cur_token);
6976 if (r != MAILIMAP_NO_ERROR) {
6977 res = r;
6978 goto free_section;
6979 }
6980 break;
6981
6982 case MAILIMAP_ERROR_PARSE:
6983 break;
6984
6985 default:
6986 return r;
6987 }
6988
6989 r = mailimap_space_parse(fd, buffer, &cur_token);
6990 if (r != MAILIMAP_NO_ERROR) {
6991 res = r;
6992 goto free_section;
6993 }
6994
6995 r = mailimap_nstring_parse(fd, buffer, &cur_token, &body_part, &length,
6996 progr_rate, progr_fun);
6997 if (r != MAILIMAP_NO_ERROR) {
6998 res = r;
6999 goto free_section;
7000 }
7001
7002 msg_att_body_section =
7003 mailimap_msg_att_body_section_new(section, number, body_part, length);
7004 if (msg_att_body_section == NULL) {
7005 res = MAILIMAP_ERROR_MEMORY;
7006 goto free_string;
7007 }
7008
7009 * result = msg_att_body_section;
7010 * index = cur_token;
7011
7012 return MAILIMAP_NO_ERROR;
7013
7014 free_string:
7015 mailimap_nstring_free(body_part);
7016 free_section:
7017 if (section != NULL)
7018 mailimap_section_free(section);
7019 err:
7020 return res;
7021}
7022
7023/*
7024 "UID" SP uniqueid
7025*/
7026
7027static int
7028mailimap_msg_att_uid_parse(mailstream * fd, MMAPString * buffer,
7029 size_t * index,
7030 uint32_t * result)
7031{
7032 size_t cur_token;
7033 uint32_t uid;
7034 int r;
7035
7036 cur_token = * index;
7037
7038 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "UID");
7039 if (r != MAILIMAP_NO_ERROR)
7040 return r;
7041
7042 r = mailimap_space_parse(fd, buffer, &cur_token);
7043 if (r != MAILIMAP_NO_ERROR)
7044 return r;
7045
7046 r = mailimap_uniqueid_parse(fd, buffer, &cur_token, &uid);
7047 if (r != MAILIMAP_NO_ERROR)
7048 return r;
7049
7050 * index = cur_token;
7051 * result = uid;
7052
7053 return MAILIMAP_NO_ERROR;
7054}
7055
7056/*
7057 msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time /
7058 "RFC822" [".HEADER" / ".TEXT"] SP nstring /
7059 "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body /
7060 "BODY" section ["<" number ">"] SP nstring /
7061 "UID" SP uniqueid
7062 ; MUST NOT change for a message
7063*/
7064
7065static int
7066mailimap_msg_att_static_parse(mailstream * fd, MMAPString * buffer,
7067 size_t * index,
7068 struct mailimap_msg_att_static ** result,
7069 size_t progr_rate,
7070 progress_function * progr_fun)
7071{
7072 size_t cur_token;
7073 struct mailimap_envelope * env;
7074 struct mailimap_date_time * internal_date;
7075 char * rfc822;
7076 char * rfc822_header;
7077 char * rfc822_text;
7078 uint32_t rfc822_size;
7079 struct mailimap_body * bodystructure;
7080 struct mailimap_body * body;
7081 struct mailimap_msg_att_body_section * body_section;
7082 uint32_t uid;
7083 struct mailimap_msg_att_static * msg_att_static;
7084 int type;
7085 int r;
7086 int res;
7087 size_t length;
7088
7089 cur_token = * index;
7090
7091 env = NULL;
7092 internal_date = NULL;
7093 rfc822 = NULL;
7094 rfc822_header = NULL;
7095 rfc822_text = NULL;
7096 rfc822_size = 0;
7097 length = 0;
7098 bodystructure = NULL;
7099 body = NULL;
7100 body_section = NULL;
7101 uid = 0;
7102
7103 type = MAILIMAP_MSG_ATT_ERROR; /* XXX - removes a gcc warning */
7104
7105 r = mailimap_msg_att_envelope_parse(fd, buffer, &cur_token, &env,
7106 progr_rate, progr_fun);
7107 if (r == MAILIMAP_NO_ERROR)
7108 type = MAILIMAP_MSG_ATT_ENVELOPE;
7109
7110 if (r == MAILIMAP_ERROR_PARSE) {
7111 r = mailimap_msg_att_internaldate_parse(fd, buffer, &cur_token,
7112 &internal_date,
7113 progr_rate, progr_fun);
7114 if (r == MAILIMAP_NO_ERROR)
7115 type = MAILIMAP_MSG_ATT_INTERNALDATE;
7116 }
7117
7118 if (r == MAILIMAP_ERROR_PARSE) {
7119 r = mailimap_msg_att_rfc822_parse(fd, buffer, &cur_token,
7120 &rfc822, &length,
7121 progr_rate, progr_fun);
7122 if (r == MAILIMAP_NO_ERROR)
7123 type = MAILIMAP_MSG_ATT_RFC822;
7124 }
7125
7126 if (r == MAILIMAP_ERROR_PARSE) {
7127 r = mailimap_msg_att_rfc822_header_parse(fd, buffer, &cur_token,
7128 &rfc822_header, &length,
7129 progr_rate, progr_fun);
7130 type = MAILIMAP_MSG_ATT_RFC822_HEADER;
7131 }
7132
7133 if (r == MAILIMAP_ERROR_PARSE) {
7134 r = mailimap_msg_att_rfc822_text_parse(fd, buffer, &cur_token,
7135 &rfc822_text, &length,
7136 progr_rate, progr_fun);
7137 if (r == MAILIMAP_NO_ERROR)
7138 type = MAILIMAP_MSG_ATT_RFC822_TEXT;
7139 }
7140
7141 if (r == MAILIMAP_ERROR_PARSE) {
7142 r = mailimap_msg_att_rfc822_size_parse(fd, buffer, &cur_token,
7143 &rfc822_size);
7144 if (r == MAILIMAP_NO_ERROR)
7145 type = MAILIMAP_MSG_ATT_RFC822_SIZE;
7146 }
7147
7148 if (r == MAILIMAP_ERROR_PARSE) {
7149 r = mailimap_msg_att_body_parse(fd, buffer, &cur_token,
7150 &body, progr_rate, progr_fun);
7151 if (r == MAILIMAP_NO_ERROR)
7152 type = MAILIMAP_MSG_ATT_BODY;
7153 }
7154
7155 if (r == MAILIMAP_ERROR_PARSE) {
7156 r = mailimap_msg_att_bodystructure_parse(fd, buffer, &cur_token,
7157 &bodystructure,
7158 progr_rate, progr_fun);
7159 if (r == MAILIMAP_NO_ERROR)
7160 type = MAILIMAP_MSG_ATT_BODYSTRUCTURE;
7161 }
7162
7163 if (r == MAILIMAP_ERROR_PARSE) {
7164 r = mailimap_msg_att_body_section_parse(fd, buffer, &cur_token,
7165 &body_section,
7166 progr_rate, progr_fun);
7167 if (r == MAILIMAP_NO_ERROR)
7168 type = MAILIMAP_MSG_ATT_BODY_SECTION;
7169 }
7170
7171 if (r == MAILIMAP_ERROR_PARSE) {
7172 r = mailimap_msg_att_uid_parse(fd, buffer, &cur_token,
7173 &uid);
7174 if (r == MAILIMAP_NO_ERROR)
7175 type = MAILIMAP_MSG_ATT_UID;
7176 }
7177
7178 if (r != MAILIMAP_NO_ERROR) {
7179 res = r;
7180 goto err;
7181 }
7182
7183 msg_att_static = mailimap_msg_att_static_new(type, env, internal_date,
7184 rfc822, rfc822_header,
7185 rfc822_text, length,
7186 rfc822_size, bodystructure,
7187 body, body_section, uid);
7188 if (msg_att_static == NULL) {
7189 res = MAILIMAP_ERROR_MEMORY;
7190 goto free;
7191 }
7192
7193 * result = msg_att_static;
7194 * index = cur_token;
7195
7196 return MAILIMAP_NO_ERROR;
7197
7198 free:
7199 if (env)
7200 mailimap_msg_att_envelope_free(env);
7201 if (internal_date)
7202 mailimap_msg_att_internaldate_free(internal_date);
7203 if (rfc822)
7204 mailimap_msg_att_rfc822_free(rfc822);
7205 if (rfc822_header)
7206 mailimap_msg_att_rfc822_header_free(rfc822_header);
7207 if (rfc822_text)
7208 mailimap_msg_att_rfc822_text_free(rfc822_text);
7209 if (bodystructure)
7210 mailimap_msg_att_bodystructure_free(bodystructure);
7211 if (body)
7212 mailimap_msg_att_body_free(body);
7213 if (body_section)
7214 mailimap_msg_att_body_section_free(body_section);
7215 err:
7216 return res;
7217}
7218
7219
7220/*
7221 nil = "NIL"
7222*/
7223
7224static int mailimap_nil_parse(mailstream * fd, MMAPString * buffer,
7225 size_t * index)
7226{
7227 return mailimap_token_case_insensitive_parse(fd, buffer, index, "NIL");
7228}
7229
7230/*
7231 nstring = string / nil
7232*/
7233
7234
7235static int mailimap_nstring_parse(mailstream * fd, MMAPString * buffer,
7236 size_t * index, char ** result,
7237 size_t * result_len,
7238 size_t progr_rate,
7239 progress_function * progr_fun)
7240{
7241 int r;
7242
7243 r = mailimap_string_parse(fd, buffer, index, result, result_len,
7244 progr_rate, progr_fun);
7245 switch (r) {
7246 case MAILIMAP_NO_ERROR:
7247 return MAILIMAP_NO_ERROR;
7248
7249 case MAILIMAP_ERROR_PARSE:
7250 r = mailimap_nil_parse(fd, buffer, index);
7251 if (r != MAILIMAP_NO_ERROR) {
7252 return r;
7253 }
7254
7255 * result = NULL;
7256 if (result_len != NULL)
7257 * result_len = 0;
7258 return MAILIMAP_NO_ERROR;
7259
7260 default:
7261 return r;
7262 }
7263}
7264
7265/*
7266 number = 1*DIGIT
7267 ; Unsigned 32-bit integer
7268 ; (0 <= n < 4,294,967,296)
7269*/
7270
7271static int
7272mailimap_number_parse(mailstream * fd, MMAPString * buffer,
7273 size_t * index, uint32_t * result)
7274{
7275 size_t cur_token;
7276 int digit;
7277 uint32_t number;
7278 int parsed;
7279 int r;
7280
7281 cur_token = * index;
7282 parsed = FALSE;
7283
7284#ifdef UNSTRICT_SYNTAX
7285 mailimap_space_parse(fd, buffer, &cur_token);
7286#endif
7287
7288 number = 0;
7289 while (1) {
7290 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit);
7291 if (r == MAILIMAP_ERROR_PARSE)
7292 break;
7293 else if (r == MAILIMAP_NO_ERROR) {
7294 number *= 10;
7295 number += digit;
7296 parsed = TRUE;
7297 }
7298 else
7299 return r;
7300 }
7301
7302 if (!parsed)
7303 return MAILIMAP_ERROR_PARSE;
7304
7305 * result = number;
7306 * index = cur_token;
7307
7308 return MAILIMAP_NO_ERROR;
7309}
7310
7311/*
7312 nz-number = digit-nz *DIGIT
7313 ; Non-zero unsigned 32-bit integer
7314 ; (0 < n < 4,294,967,296)
7315*/
7316
7317static int
7318mailimap_nz_number_parse(mailstream * fd, MMAPString * buffer,
7319 size_t * index, uint32_t * result)
7320{
7321#ifdef UNSTRICT_SYNTAX
7322 size_t cur_token;
7323 uint32_t number;
7324 int r;
7325
7326 cur_token = * index;
7327
7328 r = mailimap_number_parse(fd, buffer, &cur_token, &number);
7329 if (r != MAILIMAP_NO_ERROR)
7330 return r;
7331
7332 if (number == 0)
7333 return MAILIMAP_ERROR_PARSE;
7334
7335#else
7336 size_t cur_token;
7337 int digit;
7338 uint32_t number;
7339 int r;
7340
7341 cur_token = * index;
7342
7343 r = mailimap_digit_nz_parse(fd, buffer, &cur_token, &digit);
7344 if (r != MAILIMAP_NO_ERROR)
7345 return r;
7346
7347 number = digit;
7348
7349 while (1) {
7350 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit);
7351 if (r == MAILIMAP_ERROR_PARSE)
7352 break;
7353 else if (r == MAILIMAP_NO_ERROR) {
7354 number *= 10;
7355 number += (guint32) digit;
7356 }
7357 else
7358 return r;
7359 }
7360#endif
7361
7362 * result = number;
7363 * index = cur_token;
7364
7365 return MAILIMAP_NO_ERROR;
7366}
7367
7368/*
7369 password = astring
7370*/
7371
7372/*
7373 quoted = DQUOTE *QUOTED-CHAR DQUOTE
7374*/
7375
7376static int
7377mailimap_quoted_parse(mailstream * fd, MMAPString * buffer,
7378 size_t * index, char ** result,
7379 size_t progr_rate,
7380 progress_function * progr_fun)
7381{
7382 char ch;
7383 size_t cur_token;
7384 MMAPString * gstr_quoted;
7385 int r;
7386 int res;
7387
7388 cur_token = * index;
7389
7390#ifdef UNSTRICT_SYNTAX
7391 r = mailimap_space_parse(fd, buffer, &cur_token);
7392 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE))
7393 return r;
7394#endif
7395
7396 r = mailimap_dquote_parse(fd, buffer, &cur_token);
7397 if (r != MAILIMAP_NO_ERROR) {
7398 res = r;
7399 goto err;
7400 }
7401
7402 gstr_quoted = mmap_string_new("");
7403 if (gstr_quoted == NULL) {
7404 res = MAILIMAP_ERROR_MEMORY;
7405 goto err;
7406 }
7407
7408 while (1) {
7409 r = mailimap_quoted_char_parse(fd, buffer, &cur_token, &ch);
7410 if (r == MAILIMAP_ERROR_PARSE)
7411 break;
7412 else if (r == MAILIMAP_NO_ERROR) {
7413 if (mmap_string_append_c(gstr_quoted, ch) == NULL) {
7414 res = MAILIMAP_ERROR_MEMORY;
7415 goto free;
7416 }
7417 }
7418 else {
7419 res = r;
7420 goto free;
7421 }
7422 }
7423
7424 r = mailimap_dquote_parse(fd, buffer, &cur_token);
7425 if (r != MAILIMAP_NO_ERROR) {
7426 res = r;
7427 goto free;
7428 }
7429
7430 if (mmap_string_ref(gstr_quoted) < 0) {
7431 res = MAILIMAP_ERROR_MEMORY;
7432 goto free;
7433 }
7434
7435 * index = cur_token;
7436 * result = gstr_quoted->str;
7437
7438 return MAILIMAP_NO_ERROR;
7439
7440 free:
7441 mmap_string_free(gstr_quoted);
7442 err:
7443 return res;
7444}
7445
7446/*
7447 QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> /
7448 "\" quoted-specials
7449*/
7450
7451static int is_quoted_specials(char ch);
7452
7453static int
7454mailimap_quoted_char_parse(mailstream * fd, MMAPString * buffer,
7455 size_t * index, char * result)
7456{
7457 size_t cur_token;
7458 int r;
7459
7460 cur_token = * index;
7461
7462 if (!is_quoted_specials(buffer->str[cur_token])) {
7463 * result = buffer->str[cur_token];
7464 cur_token ++;
7465 * index = cur_token;
7466 return MAILIMAP_NO_ERROR;
7467 }
7468 else {
7469 char quoted_special;
7470
7471 r = mailimap_char_parse(fd, buffer, &cur_token, '\\');
7472 if (r != MAILIMAP_NO_ERROR)
7473 return r;
7474
7475 r = mailimap_quoted_specials_parse(fd, buffer, &cur_token,
7476 &quoted_special);
7477 if (r != MAILIMAP_NO_ERROR)
7478 return r;
7479
7480 * result = quoted_special;
7481 * index = cur_token;
7482
7483 return MAILIMAP_NO_ERROR;
7484 }
7485}
7486
7487/*
7488 quoted-specials = DQUOTE / "\"
7489*/
7490
7491static int is_quoted_specials(char ch)
7492{
7493 return (ch == '\"') || (ch == '\\');
7494}
7495
7496static int
7497mailimap_quoted_specials_parse(mailstream * fd, MMAPString * buffer,
7498 size_t * index, char * result)
7499{
7500 size_t cur_token;
7501
7502 cur_token = * index;
7503
7504 if (is_quoted_specials(buffer->str[cur_token])) {
7505 * result = buffer->str[cur_token];
7506 cur_token ++;
7507 * index = cur_token;
7508 return MAILIMAP_NO_ERROR;
7509 }
7510 else
7511 return MAILIMAP_ERROR_PARSE;
7512}
7513
7514/*
7515 UNIMPLEMENTED
7516 rename = "RENAME" SP mailbox SP mailbox
7517 ; Use of INBOX as a destination gives a NO error
7518*/
7519
7520/*
7521 response = *(continue-req / response-data) response-done
7522*/
7523
7524/*
7525 continue-req / response-data
7526*/
7527
7528/* static */ int
7529mailimap_cont_req_or_resp_data_parse(mailstream * fd, MMAPString * buffer,
7530 size_t * index,
7531 struct mailimap_cont_req_or_resp_data **
7532 result,
7533 size_t progr_rate,
7534 progress_function * progr_fun)
7535{
7536 size_t cur_token;
7537 struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data;
7538 struct mailimap_continue_req * cont_req;
7539 struct mailimap_response_data * resp_data;
7540 int type;
7541 int r;
7542 int res;
7543
7544 cur_token = * index;
7545
7546 cont_req = NULL;
7547 resp_data = NULL;
7548 type = MAILIMAP_RESP_ERROR; /* XXX - removes a gcc warning */
7549
7550 r = mailimap_continue_req_parse(fd, buffer, &cur_token, &cont_req,
7551 progr_rate, progr_fun);
7552 if (r == MAILIMAP_NO_ERROR)
7553 type = MAILIMAP_RESP_CONT_REQ;
7554
7555 if (r == MAILIMAP_ERROR_PARSE) {
7556 r = mailimap_response_data_parse(fd, buffer, &cur_token, &resp_data,
7557 progr_rate, progr_fun);
7558 if (r == MAILIMAP_NO_ERROR)
7559 type = MAILIMAP_RESP_RESP_DATA;
7560 }
7561
7562 if (r != MAILIMAP_NO_ERROR) {
7563 res = r;
7564 goto err;
7565 }
7566
7567 /*
7568 multi-lines response
7569 read another response line because after that token,
7570 there must have something (continue-req, response-data or response-done)
7571 */
7572
7573 if (!mailstream_read_line_append(fd, buffer)) {
7574 res = MAILIMAP_ERROR_STREAM;
7575 goto free;
7576 }
7577
7578 cont_req_or_resp_data =
7579 mailimap_cont_req_or_resp_data_new(type, cont_req, resp_data);
7580 if (cont_req_or_resp_data == NULL) {
7581 res = MAILIMAP_ERROR_MEMORY;
7582 goto free;
7583 }
7584
7585 * result = cont_req_or_resp_data;
7586 * index = cur_token;
7587
7588 return MAILIMAP_NO_ERROR;
7589
7590 free:
7591 if (cont_req != NULL)
7592 mailimap_continue_req_free(cont_req);
7593 if (resp_data != NULL)
7594 mailimap_response_data_free(resp_data);
7595 err:
7596 return res;
7597}
7598
7599/*
7600 response = *(continue-req / response-data) response-done
7601*/
7602
7603int
7604mailimap_response_parse(mailstream * fd, MMAPString * buffer,
7605 size_t * index, struct mailimap_response ** result,
7606 size_t progr_rate,
7607 progress_function * progr_fun)
7608{
7609 size_t cur_token;
7610 clist * cont_req_or_resp_data_list;
7611 struct mailimap_response * resp;
7612 struct mailimap_response_done * resp_done;
7613 int r;
7614 int res;
7615
7616 cur_token = * index;
7617 cont_req_or_resp_data_list = NULL;
7618 resp_done = NULL;
7619
7620 r = mailimap_struct_multiple_parse(fd, buffer,
7621 &cur_token, &cont_req_or_resp_data_list,
7622 (mailimap_struct_parser *)
7623 mailimap_cont_req_or_resp_data_parse,
7624 (mailimap_struct_destructor *)
7625 mailimap_cont_req_or_resp_data_free,
7626 progr_rate, progr_fun);
7627
7628 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE))
7629 return r;
7630
7631 r = mailimap_response_done_parse(fd, buffer, &cur_token, &resp_done,
7632 progr_rate, progr_fun);
7633 if (r != MAILIMAP_NO_ERROR) {
7634 res = r;
7635 goto free_list;
7636 }
7637
7638 resp = mailimap_response_new(cont_req_or_resp_data_list, resp_done);
7639 if (resp == NULL) {
7640 res = MAILIMAP_ERROR_MEMORY;
7641 goto free_resp_done;
7642 }
7643
7644 * result = resp;
7645 * index = cur_token;
7646
7647 return MAILIMAP_NO_ERROR;
7648
7649 free_resp_done:
7650 mailimap_response_done_free(resp_done);
7651 free_list:
7652 if (cont_req_or_resp_data_list != NULL) {
7653 clist_foreach(cont_req_or_resp_data_list,
7654 (clist_func) mailimap_cont_req_or_resp_data_free, NULL);
7655 clist_free(cont_req_or_resp_data_list);
7656 }
7657 return res;
7658}
7659
7660/*
7661 response-data = "*" SP (resp-cond-state / resp-cond-bye /
7662 mailbox-data / message-data / capability-data) CRLF
7663*/
7664
7665static int
7666mailimap_response_data_parse(mailstream * fd, MMAPString * buffer,
7667 size_t * index,
7668 struct mailimap_response_data ** result,
7669 size_t progr_rate,
7670 progress_function * progr_fun)
7671{
7672 struct mailimap_response_data * resp_data;
7673 size_t cur_token;
7674 int type;
7675 struct mailimap_resp_cond_state * cond_state;
7676 struct mailimap_resp_cond_bye * cond_bye;
7677 struct mailimap_mailbox_data * mb_data;
7678 struct mailimap_message_data * msg_data;
7679 struct mailimap_capability_data * cap_data;
7680 int r;
7681 int res;
7682
7683 cond_state = NULL;
7684 cond_bye = NULL;
7685 mb_data = NULL;
7686 msg_data = NULL;
7687 cap_data = NULL;
7688
7689 cur_token = * index;
7690
7691 r = mailimap_star_parse(fd, buffer, &cur_token);
7692 if (r != MAILIMAP_NO_ERROR) {
7693 res = r;
7694 goto err;
7695 }
7696
7697 r = mailimap_space_parse(fd, buffer, &cur_token);
7698 if (r != MAILIMAP_NO_ERROR) {
7699 res = r;
7700 goto err;
7701 }
7702
7703 type = MAILIMAP_RESP_DATA_TYPE_ERROR; /* XXX - removes a gcc warning */
7704
7705 r = mailimap_resp_cond_state_parse(fd, buffer, &cur_token, &cond_state,
7706 progr_rate, progr_fun);
7707 if (r == MAILIMAP_NO_ERROR)
7708 type = MAILIMAP_RESP_DATA_TYPE_COND_STATE;
7709
7710 if (r == MAILIMAP_ERROR_PARSE) {
7711 r = mailimap_resp_cond_bye_parse(fd, buffer, &cur_token, &cond_bye,
7712 progr_rate, progr_fun);
7713 if (r == MAILIMAP_NO_ERROR)
7714 type = MAILIMAP_RESP_DATA_TYPE_COND_BYE;
7715 }
7716
7717 if (r == MAILIMAP_ERROR_PARSE) {
7718 r = mailimap_mailbox_data_parse(fd, buffer, &cur_token, &mb_data,
7719 progr_rate, progr_fun);
7720 if (r == MAILIMAP_NO_ERROR)
7721 type = MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA;
7722 }
7723
7724 if (r == MAILIMAP_ERROR_PARSE) {
7725 r = mailimap_message_data_parse(fd, buffer, &cur_token, &msg_data,
7726 progr_rate, progr_fun);
7727 if (r == MAILIMAP_NO_ERROR)
7728 type = MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA;
7729 }
7730
7731 if (r == MAILIMAP_ERROR_PARSE) {
7732 r = mailimap_capability_data_parse(fd, buffer, &cur_token, &cap_data,
7733 progr_rate, progr_fun);
7734 if (r == MAILIMAP_NO_ERROR)
7735 type = MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA;
7736 }
7737
7738 if (r != MAILIMAP_NO_ERROR) {
7739 res = r;
7740 goto err;
7741 }
7742
7743 r = mailimap_crlf_parse(fd, buffer, &cur_token);
7744 if (r != MAILIMAP_NO_ERROR) {
7745 res = r;
7746 goto free;
7747 }
7748
7749 resp_data = mailimap_response_data_new(type, cond_state,
7750 cond_bye, mb_data,
7751 msg_data, cap_data);
7752 if (resp_data == NULL) {
7753 res = MAILIMAP_ERROR_MEMORY;
7754 goto free;
7755 }
7756
7757 * result = resp_data;
7758 * index = cur_token;
7759
7760 return MAILIMAP_NO_ERROR;
7761
7762 free:
7763 if (cond_state)
7764 mailimap_resp_cond_state_free(cond_state);
7765 if (cond_bye)
7766 mailimap_resp_cond_bye_free(cond_bye);
7767 if (mb_data)
7768 mailimap_mailbox_data_free(mb_data);
7769 if (msg_data)
7770 mailimap_message_data_free(msg_data);
7771 if (cap_data)
7772 mailimap_capability_data_free(cap_data);
7773 err:
7774 return res;
7775}
7776
7777/*
7778 response-done = response-tagged / response-fatal
7779*/
7780
7781static int
7782mailimap_response_done_parse(mailstream * fd, MMAPString * buffer,
7783 size_t * index,
7784 struct mailimap_response_done ** result,
7785 size_t progr_rate,
7786 progress_function * progr_fun)
7787{
7788 int type;
7789 struct mailimap_response_done * resp_done;
7790 size_t cur_token;
7791 struct mailimap_response_tagged * tagged;
7792 struct mailimap_response_fatal * fatal;
7793 int r;
7794 int res;
7795
7796 cur_token = * index;
7797
7798 tagged = NULL;
7799 fatal = NULL;
7800
7801 type = MAILIMAP_RESP_DONE_TYPE_ERROR; /* removes a gcc warning */
7802
7803 r = mailimap_response_tagged_parse(fd, buffer, &cur_token, &tagged,
7804 progr_rate, progr_fun);
7805 if (r == MAILIMAP_NO_ERROR)
7806 type = MAILIMAP_RESP_DONE_TYPE_TAGGED;
7807
7808 if (r == MAILIMAP_ERROR_PARSE) {
7809 r = mailimap_response_fatal_parse(fd, buffer, &cur_token, &fatal,
7810 progr_rate, progr_fun);
7811 if (r == MAILIMAP_NO_ERROR)
7812 type = MAILIMAP_RESP_DONE_TYPE_FATAL;
7813 }
7814
7815 if (r != MAILIMAP_NO_ERROR) {
7816 res = r;
7817 goto err;
7818 }
7819
7820 resp_done = mailimap_response_done_new(type, tagged, fatal);
7821 if (resp_done == NULL) {
7822 res = MAILIMAP_ERROR_MEMORY;
7823 goto free;
7824 }
7825
7826 * result = resp_done;
7827 * index = cur_token;
7828
7829 return MAILIMAP_NO_ERROR;
7830
7831 free:
7832 if (tagged == NULL)
7833 mailimap_response_tagged_free(tagged);
7834 if (fatal == NULL)
7835 mailimap_response_fatal_free(fatal);
7836 err:
7837 return res;
7838}
7839
7840/*
7841 response-fatal = "*" SP resp-cond-bye CRLF
7842 ; Server closes connection immediately
7843*/
7844
7845static int
7846mailimap_response_fatal_parse(mailstream * fd, MMAPString * buffer,
7847 size_t * index,
7848 struct mailimap_response_fatal ** result,
7849 size_t progr_rate,
7850 progress_function * progr_fun)
7851{
7852 struct mailimap_resp_cond_bye * cond_bye;
7853 struct mailimap_response_fatal * fatal;
7854 size_t cur_token;
7855 int res;
7856 int r;
7857
7858 cur_token = * index;
7859
7860 r = mailimap_star_parse(fd, buffer, &cur_token);
7861 if (r != MAILIMAP_NO_ERROR) {
7862 res = r;
7863 goto err;
7864 }
7865
7866 r = mailimap_space_parse(fd, buffer, &cur_token);
7867 if (r != MAILIMAP_NO_ERROR) {
7868 res = r;
7869 goto err;
7870 }
7871
7872 r = mailimap_resp_cond_bye_parse(fd, buffer, &cur_token, &cond_bye,
7873 progr_rate, progr_fun);
7874 if (r != MAILIMAP_NO_ERROR) {
7875 res = r;
7876 goto err;
7877 }
7878
7879 r = mailimap_crlf_parse(fd, buffer, &cur_token);
7880 if (r != MAILIMAP_NO_ERROR) {
7881 res = r;
7882 goto free;
7883 }
7884
7885 fatal = mailimap_response_fatal_new(cond_bye);
7886 if (fatal == NULL) {
7887 res = MAILIMAP_ERROR_MEMORY;
7888 goto free;
7889 }
7890
7891 * result = fatal;
7892 * index = cur_token;
7893
7894 return MAILIMAP_NO_ERROR;
7895
7896 free:
7897 mailimap_resp_cond_bye_free(cond_bye);
7898 err:
7899 return res;
7900}
7901
7902/*
7903 response-tagged = tag SP resp-cond-state CRLF
7904*/
7905
7906static int
7907mailimap_response_tagged_parse(mailstream * fd, MMAPString * buffer,
7908 size_t * index,
7909 struct mailimap_response_tagged ** result,
7910 size_t progr_rate,
7911 progress_function * progr_fun)
7912{
7913 size_t cur_token;
7914 char * tag;
7915 struct mailimap_resp_cond_state * cond_state;
7916 struct mailimap_response_tagged * resp_tagged;
7917 int r;
7918 int res;
7919
7920 cur_token = * index;
7921 cond_state = NULL;
7922
7923 r = mailimap_tag_parse(fd, buffer, &cur_token, &tag,
7924 progr_rate, progr_fun);
7925 if (r != MAILIMAP_NO_ERROR) {
7926 res = r;
7927 goto err;
7928 }
7929
7930 r = mailimap_space_parse(fd, buffer, &cur_token);
7931 if (r != MAILIMAP_NO_ERROR) {
7932 res = r;
7933 goto free_tag;
7934 }
7935
7936 r = mailimap_resp_cond_state_parse(fd, buffer, &cur_token, &cond_state,
7937 progr_rate, progr_fun);
7938 if (r != MAILIMAP_NO_ERROR) {
7939 res = r;
7940 goto free_tag;
7941 }
7942
7943 resp_tagged = mailimap_response_tagged_new(tag, cond_state);
7944 if (resp_tagged == NULL) {
7945 res = MAILIMAP_ERROR_MEMORY;
7946 goto free_cond_state;
7947 }
7948
7949 * result = resp_tagged;
7950 * index = cur_token;
7951
7952 return MAILIMAP_NO_ERROR;
7953
7954 free_cond_state:
7955 mailimap_resp_cond_state_free(cond_state);
7956 free_tag:
7957 mailimap_tag_free(tag);
7958 err:
7959 return res;
7960}
7961
7962/*
7963 resp-cond-auth = ("OK" / "PREAUTH") SP resp-text
7964 ; Authentication condition
7965*/
7966
7967static int
7968mailimap_resp_cond_auth_parse(mailstream * fd, MMAPString * buffer,
7969 size_t * index,
7970 struct mailimap_resp_cond_auth ** result,
7971 size_t progr_rate,
7972 progress_function * progr_fun)
7973{
7974 struct mailimap_resp_cond_auth * cond_auth;
7975 size_t cur_token;
7976 struct mailimap_resp_text * text;
7977 int type;
7978 int r;
7979 int res;
7980
7981 cur_token = * index;
7982 text = NULL;
7983
7984 type = MAILIMAP_RESP_COND_AUTH_ERROR; /* XXX - removes a gcc warning */
7985
7986 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "OK");
7987 if (r == MAILIMAP_NO_ERROR)
7988 type = MAILIMAP_RESP_COND_AUTH_OK;
7989
7990 if (r == MAILIMAP_ERROR_PARSE) {
7991 r = mailimap_token_case_insensitive_parse(fd, buffer,
7992 &cur_token, "PREAUTH");
7993 if (r == MAILIMAP_NO_ERROR)
7994 type = MAILIMAP_RESP_COND_AUTH_PREAUTH;
7995 }
7996
7997 if (r != MAILIMAP_NO_ERROR) {
7998 res = r;
7999 goto err;
8000 }
8001
8002 r = mailimap_space_parse(fd, buffer, &cur_token);
8003 if (r != MAILIMAP_NO_ERROR) {
8004 res = r;
8005 goto err;
8006 }
8007
8008 r = mailimap_resp_text_parse(fd, buffer, &cur_token, &text,
8009 progr_rate, progr_fun);
8010 if (r != MAILIMAP_NO_ERROR) {
8011 res = r;
8012 goto err;
8013 }
8014
8015 cond_auth = mailimap_resp_cond_auth_new(type, text);
8016 if (cond_auth == NULL) {
8017 res = MAILIMAP_ERROR_MEMORY;
8018 goto free;
8019 }
8020
8021 * result = cond_auth;
8022 * index = cur_token;
8023
8024 return MAILIMAP_NO_ERROR;
8025
8026 free:
8027 mailimap_resp_text_free(text);
8028 err:
8029 return res;
8030}
8031
8032/*
8033 resp-cond-bye = "BYE" SP resp-text
8034*/
8035
8036static int
8037mailimap_resp_cond_bye_parse(mailstream * fd, MMAPString * buffer,
8038 size_t * index,
8039 struct mailimap_resp_cond_bye ** result,
8040 size_t progr_rate,
8041 progress_function * progr_fun)
8042{
8043 size_t cur_token;
8044 struct mailimap_resp_cond_bye * cond_bye;
8045 struct mailimap_resp_text * text;
8046 int r;
8047 int res;
8048
8049 cur_token = * index;
8050
8051 r = mailimap_token_case_insensitive_parse(fd, buffer,
8052 &cur_token, "BYE");
8053 if (r != MAILIMAP_NO_ERROR) {
8054 res = r;
8055 goto err;
8056 }
8057
8058 r = mailimap_space_parse(fd, buffer, &cur_token);
8059 if (r != MAILIMAP_NO_ERROR) {
8060 res = r;
8061 goto err;
8062 }
8063
8064 r = mailimap_resp_text_parse(fd, buffer, &cur_token, &text,
8065 progr_rate, progr_fun);
8066 if (r != MAILIMAP_NO_ERROR) {
8067 res = r;
8068 goto err;
8069 }
8070
8071 cond_bye = mailimap_resp_cond_bye_new(text);
8072 if (cond_bye == NULL) {
8073 res = MAILIMAP_ERROR_MEMORY;
8074 goto free;
8075 }
8076
8077 * index = cur_token;
8078 * result = cond_bye;
8079
8080 return MAILIMAP_NO_ERROR;
8081
8082 free:
8083 mailimap_resp_text_free(text);
8084 err:
8085 return res;
8086}
8087
8088/*
8089 resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text
8090 ; Status condition
8091*/
8092
8093static int
8094mailimap_resp_cond_state_parse(mailstream * fd, MMAPString * buffer,
8095 size_t * index,
8096 struct mailimap_resp_cond_state ** result,
8097 size_t progr_rate,
8098 progress_function * progr_fun)
8099{
8100 struct mailimap_resp_cond_state * cond_state;
8101 size_t cur_token;
8102 struct mailimap_resp_text * text;
8103 int type;
8104 int r;
8105 int res;
8106
8107 cur_token = * index;
8108 text = NULL;
8109
8110 type = mailimap_resp_cond_state_get_token_value(fd, buffer, &cur_token);
8111 if (type == -1) {
8112 res = MAILIMAP_ERROR_PARSE;
8113 goto err;
8114 }
8115
8116 r = mailimap_space_parse(fd, buffer, &cur_token);
8117 if (r != MAILIMAP_NO_ERROR) {
8118 res = r;
8119 goto err;
8120 }
8121
8122 r = mailimap_resp_text_parse(fd, buffer, &cur_token, &text,
8123 progr_rate, progr_fun);
8124 if (r != MAILIMAP_NO_ERROR) {
8125 res = r;
8126 goto err;
8127 }
8128
8129 cond_state = mailimap_resp_cond_state_new(type, text);
8130 if (cond_state == NULL) {
8131 res = MAILIMAP_ERROR_MEMORY;
8132 goto free;
8133 }
8134
8135 * result = cond_state;
8136 * index = cur_token;
8137
8138 return MAILIMAP_NO_ERROR;
8139
8140 free:
8141 mailimap_resp_text_free(text);
8142 err:
8143 return res;
8144}
8145
8146
8147/*
8148 resp-specials = "]"
8149*/
8150
8151static int is_resp_specials(char ch)
8152{
8153 switch (ch) {
8154 case ']':
8155 return TRUE;
8156 };
8157 return FALSE;
8158}
8159
8160/*
8161 resp-text = ["[" resp-text-code "]" SP] text
8162*/
8163
8164/* "[" resp-text-code "]" */
8165
8166static int
8167mailimap_resp_text_resp_text_code_parse(mailstream * fd, MMAPString * buffer,
8168 size_t * index,
8169 struct mailimap_resp_text_code **
8170 result,
8171 size_t progr_rate,
8172 progress_function * progr_fun)
8173{
8174 struct mailimap_resp_text_code * text_code;
8175 size_t cur_token;
8176 int r;
8177 int res;
8178
8179 cur_token = * index;
8180
8181 r = mailimap_obracket_parse(fd, buffer, &cur_token);
8182 if (r != MAILIMAP_NO_ERROR) {
8183 res = r;
8184 goto err;
8185 }
8186
8187 r = mailimap_resp_text_code_parse(fd, buffer, &cur_token, &text_code,
8188 progr_rate, progr_fun);
8189 if (r != MAILIMAP_NO_ERROR) {
8190 res = r;
8191 goto err;
8192 }
8193
8194 r = mailimap_cbracket_parse(fd, buffer, &cur_token);
8195 if (r != MAILIMAP_NO_ERROR) {
8196 res = r;
8197 goto free;
8198 }
8199
8200 r = mailimap_space_parse(fd, buffer, &cur_token);
8201 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
8202 res = r;
8203 goto free;
8204 }
8205
8206 * result = text_code;
8207 * index = cur_token;
8208
8209 return MAILIMAP_NO_ERROR;
8210
8211 free:
8212 mailimap_resp_text_code_free(text_code);
8213 err:
8214 return res;
8215}
8216
8217/*
8218 resp-text = ["[" resp-text-code "]" SP] text
8219*/
8220
8221static int
8222mailimap_resp_text_parse(mailstream * fd, MMAPString * buffer,
8223 size_t * index,
8224 struct mailimap_resp_text ** result,
8225 size_t progr_rate,
8226 progress_function * progr_fun)
8227{
8228 size_t cur_token;
8229 struct mailimap_resp_text_code * text_code;
8230 struct mailimap_resp_text * resp_text;
8231 char * text;
8232 int r;
8233 int res;
8234
8235 cur_token = * index;
8236 text = NULL;
8237 text_code = NULL;
8238
8239 r = mailimap_resp_text_resp_text_code_parse(fd, buffer, &cur_token,
8240 &text_code,
8241 progr_rate, progr_fun);
8242 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE))
8243 return r;
8244
8245 r = mailimap_text_parse(fd, buffer, &cur_token, &text,
8246 progr_rate, progr_fun);
8247 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
8248 res = r;
8249 goto free_resp_text_code;
8250 }
8251
8252 resp_text = mailimap_resp_text_new(text_code, text);
8253 if (resp_text == NULL) {
8254 res = MAILIMAP_ERROR_MEMORY;
8255 goto free_text;
8256 }
8257
8258 * result = resp_text;
8259 * index = cur_token;
8260
8261 return MAILIMAP_NO_ERROR;
8262
8263 free_resp_text_code:
8264 if (text_code != NULL)
8265 mailimap_resp_text_code_free(text_code);
8266 free_text:
8267 mailimap_text_free(text);
8268 return res;
8269}
8270
8271/*
8272 resp-text-code = "ALERT" /
8273 "BADCHARSET" [SP "(" astring *(SP astring) ")" ] /
8274 capability-data / "PARSE" /
8275 "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" /
8276 "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
8277 "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number /
8278 "UNSEEN" SP nz-number /
8279 atom [SP 1*<any TEXT-CHAR except "]">]
8280*/
8281
8282/*
8283 ALERT / PARSE / READ-ONLY / READ-WRITE / TRYCREATE
8284*/
8285
8286static int
8287mailimap_resp_text_code_1_parse(mailstream * fd, MMAPString * buffer,
8288 size_t * index,
8289 int * result)
8290{
8291 int id;
8292 size_t cur_token;
8293
8294 cur_token = * index;
8295
8296 id = mailimap_resp_text_code_1_get_token_value(fd, buffer, &cur_token);
8297
8298 if (id == -1)
8299 return MAILIMAP_ERROR_PARSE;
8300
8301 * result = id;
8302 * index = cur_token;
8303
8304 return MAILIMAP_NO_ERROR;
8305}
8306
8307
8308/*
8309 "BADCHARSET" [SP "(" astring *(SP astring) ")" ]
8310*/
8311
8312/*
8313 SP "(" astring *(SP astring) ")"
8314*/
8315
8316static int
8317mailimap_resp_text_code_badcharset_1_parse(mailstream * fd,
8318 MMAPString * buffer,
8319 size_t * index,
8320 clist ** result,
8321 size_t progr_rate,
8322 progress_function * progr_fun)
8323{
8324 size_t cur_token;
8325 clist * charset;
8326 int r;
8327 int res;
8328
8329 cur_token = * index;
8330
8331 r = mailimap_space_parse(fd, buffer, &cur_token);
8332 if (r != MAILIMAP_NO_ERROR) {
8333 res = r;
8334 goto err;
8335 }
8336
8337 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
8338 if (r != MAILIMAP_NO_ERROR) {
8339 res = r;
8340 goto err;
8341 }
8342
8343 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &charset,
8344 (mailimap_struct_parser *)
8345 mailimap_astring_parse,
8346 (mailimap_struct_destructor *)
8347 mailimap_astring_free,
8348 progr_rate, progr_fun);
8349 if (r != MAILIMAP_NO_ERROR) {
8350 res = r;
8351 goto err;
8352 }
8353
8354 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
8355 if (r != MAILIMAP_NO_ERROR) {
8356 res = r;
8357 goto charset;
8358 }
8359
8360 * index = cur_token;
8361 * result = charset;
8362
8363 return MAILIMAP_NO_ERROR;
8364
8365 charset:
8366 clist_foreach(charset, (clist_func) mailimap_string_free, NULL);
8367 clist_free(charset);
8368 err:
8369 return res;
8370}
8371
8372/*
8373 "BADCHARSET" [SP "(" astring *(SP astring) ")" ]
8374*/
8375
8376static int
8377mailimap_resp_text_code_badcharset_parse(mailstream * fd, MMAPString * buffer,
8378 size_t * index,
8379 clist ** result,
8380 size_t progr_rate,
8381 progress_function * progr_fun)
8382{
8383 size_t cur_token;
8384 clist * charset;
8385 int r;
8386
8387 cur_token = * index;
8388
8389 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
8390 "BADCHARSET");
8391 if (r != MAILIMAP_NO_ERROR)
8392 return r;
8393
8394 charset = NULL;
8395
8396 r = mailimap_resp_text_code_badcharset_1_parse(fd, buffer, &cur_token,
8397 &charset,
8398 progr_rate, progr_fun);
8399 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE))
8400 return r;
8401
8402 * result = charset;
8403 * index = cur_token;
8404
8405 return MAILIMAP_NO_ERROR;
8406}
8407
8408/*
8409 "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")"
8410*/
8411
8412static int
8413mailimap_resp_text_code_permanentflags_parse(mailstream * fd,
8414 MMAPString * buffer,
8415 size_t * index,
8416 clist ** result,
8417 size_t progr_rate,
8418 progress_function * progr_fun)
8419{
8420 size_t cur_token;
8421 clist * flaglist;
8422 int r;
8423 int res;
8424
8425 cur_token = * index;
8426
8427 flaglist = NULL;
8428
8429 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
8430 "PERMANENTFLAGS");
8431 if (r != MAILIMAP_NO_ERROR) {
8432 res = r;
8433 goto err;
8434 }
8435
8436 r = mailimap_space_parse(fd, buffer, &cur_token);
8437 if (r != MAILIMAP_NO_ERROR) {
8438 res = r;
8439 goto err;
8440 }
8441
8442 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
8443 if (r != MAILIMAP_NO_ERROR) {
8444 res = r;
8445 goto err;
8446 }
8447
8448 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &flaglist,
8449 (mailimap_struct_parser *)
8450 mailimap_flag_perm_parse,
8451 (mailimap_struct_destructor *)
8452 mailimap_flag_perm_free,
8453 progr_rate, progr_fun);
8454 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
8455 res = r;
8456 goto err;
8457 }
8458
8459 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
8460 if (r != MAILIMAP_NO_ERROR) {
8461 res = r;
8462 goto free;
8463 }
8464
8465 * index = cur_token;
8466 * result = flaglist;
8467
8468 return MAILIMAP_NO_ERROR;
8469
8470 free:
8471 clist_foreach(flaglist, (clist_func) mailimap_flag_perm_free, NULL);
8472 clist_free(flaglist);
8473 err:
8474 return res;
8475}
8476
8477
8478/*
8479 "UIDNEXT" SP nz-number /
8480 "UIDVALIDITY" SP nz-number /
8481 "UNSEEN" SP nz-number
8482*/
8483
8484static int
8485mailimap_resp_text_code_number_parse(mailstream * fd, MMAPString * buffer,
8486 size_t * index,
8487 struct mailimap_resp_text_code ** result,
8488 size_t progr_rate,
8489 progress_function * progr_fun)
8490{
8491 size_t cur_token;
8492 int type;
8493 uint32_t number;
8494 struct mailimap_resp_text_code * resp_text_code;
8495 int r;
8496
8497 cur_token = * index;
8498
8499 resp_text_code = NULL;
8500
8501 type = mailimap_resp_text_code_2_get_token_value(fd, buffer, &cur_token);
8502 if (type == -1)
8503 return MAILIMAP_ERROR_PARSE;
8504
8505 r = mailimap_space_parse(fd, buffer, &cur_token);
8506 if (r != MAILIMAP_NO_ERROR)
8507 return r;
8508
8509 r = mailimap_nz_number_parse(fd, buffer, &cur_token, &number);
8510 if (r != MAILIMAP_NO_ERROR)
8511 return r;
8512
8513 switch (type) {
8514 case MAILIMAP_RESP_TEXT_CODE_UIDNEXT:
8515 resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL,
8516 number, 0, 0, NULL , NULL);
8517 break;
8518 case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY:
8519 resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL,
8520 0, number, 0, NULL , NULL);
8521 break;
8522 case MAILIMAP_RESP_TEXT_CODE_UNSEEN:
8523 resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL,
8524 0, 0, number, NULL , NULL);
8525 break;
8526 }
8527
8528 if (resp_text_code == NULL)
8529 return MAILIMAP_ERROR_MEMORY;
8530
8531 * result = resp_text_code;
8532 * index = cur_token;
8533
8534 return MAILIMAP_NO_ERROR;
8535}
8536
8537/*
8538 atom [SP 1*<any TEXT-CHAR except "]">]
8539*/
8540
8541static int is_text_char(char ch);
8542
8543/*
8544 any TEXT-CHAR except "]"
8545*/
8546
8547static int is_text_char_1(char ch)
8548{
8549 if (ch == ']')
8550 return FALSE;
8551 return is_text_char(ch);
8552}
8553
8554/*
8555 1*<any TEXT-CHAR except "]"
8556*/
8557
8558static int
8559mailimap_resp_text_code_other_2_parse(mailstream * fd, MMAPString * buffer,
8560 size_t * index, char ** result,
8561 size_t progr_rate,
8562 progress_function * progr_fun)
8563{
8564 return mailimap_custom_string_parse(fd, buffer, index, result,
8565 is_text_char_1);
8566}
8567
8568/*
8569 SP 1*<any TEXT-CHAR except "]">
8570*/
8571
8572static int
8573mailimap_resp_text_code_other_1_parse(mailstream * fd, MMAPString * buffer,
8574 size_t * index,
8575 char ** result,
8576 size_t progr_rate,
8577 progress_function * progr_fun)
8578{
8579 size_t cur_token;
8580 char * value;
8581 int r;
8582
8583 cur_token = * index;
8584
8585 r = mailimap_space_parse(fd, buffer, &cur_token);
8586 if (r != MAILIMAP_NO_ERROR)
8587 return r;
8588
8589 r = mailimap_resp_text_code_other_2_parse(fd, buffer, &cur_token,
8590 &value,
8591 progr_rate, progr_fun);
8592 if (r != MAILIMAP_NO_ERROR)
8593 return r;
8594
8595 * result = value;
8596 * index = cur_token;
8597
8598 return MAILIMAP_NO_ERROR;
8599}
8600
8601/*
8602 atom [SP 1*<any TEXT-CHAR except "]">]
8603*/
8604
8605static int
8606mailimap_resp_text_code_other_parse(mailstream * fd, MMAPString * buffer,
8607 size_t * index,
8608 struct mailimap_resp_text_code ** result,
8609 size_t progr_rate,
8610 progress_function * progr_fun)
8611{
8612 size_t cur_token;
8613 char * atom;
8614 char * value;
8615 struct mailimap_resp_text_code * resp_text_code;
8616 int r;
8617 int res;
8618
8619 cur_token = * index;
8620 atom = NULL;
8621 value = NULL;
8622
8623 r = mailimap_atom_parse(fd, buffer, &cur_token, &atom,
8624 progr_rate, progr_fun);
8625 if (r != MAILIMAP_NO_ERROR) {
8626 res = r;
8627 goto err;
8628 }
8629
8630 r = mailimap_resp_text_code_other_1_parse(fd, buffer, &cur_token,
8631 &value, progr_rate, progr_fun);
8632 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
8633 res = r;
8634 goto err;
8635 }
8636
8637 resp_text_code = mailimap_resp_text_code_new(MAILIMAP_RESP_TEXT_CODE_OTHER,
8638 NULL, NULL, NULL,
8639 0, 0, 0, atom, value);
8640 if (resp_text_code == NULL) {
8641 res = MAILIMAP_ERROR_MEMORY;
8642 goto free_value;
8643 }
8644
8645 * result = resp_text_code;
8646 * index = cur_token;
8647
8648 return MAILIMAP_NO_ERROR;
8649
8650 free_value:
8651 if (value != NULL)
8652 free(value);
8653 mailimap_atom_free(atom);
8654 err:
8655 return res;
8656}
8657
8658
8659
8660/*
8661 resp-text-code = "ALERT" /
8662 "BADCHARSET" [SP "(" astring *(SP astring) ")" ] /
8663 capability-data / "PARSE" /
8664 "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" /
8665 "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
8666 "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number /
8667 "UNSEEN" SP nz-number /
8668 atom [SP 1*<any TEXT-CHAR except "]">]
8669*/
8670
8671static int
8672mailimap_resp_text_code_parse(mailstream * fd, MMAPString * buffer,
8673 size_t * index,
8674 struct mailimap_resp_text_code ** result,
8675 size_t progr_rate,
8676 progress_function * progr_fun)
8677{
8678 size_t cur_token;
8679 struct mailimap_resp_text_code * resp_text_code;
8680 clist * badcharset;
8681 clist * permanentflags;
8682 struct mailimap_capability_data * cap_data;
8683 int type;
8684 int r;
8685 int res;
8686
8687 cur_token = * index;
8688
8689 resp_text_code = NULL;
8690 badcharset = NULL;
8691 cap_data = NULL;
8692 permanentflags = NULL;
8693
8694 r = mailimap_resp_text_code_1_parse(fd, buffer, &cur_token, &type);
8695 if (r == MAILIMAP_NO_ERROR) {
8696 /* do nothing */
8697 }
8698
8699 if (r == MAILIMAP_ERROR_PARSE) {
8700
8701 r = mailimap_resp_text_code_badcharset_parse(fd, buffer, &cur_token,
8702 &badcharset,
8703 progr_rate, progr_fun);
8704 if (r == MAILIMAP_NO_ERROR)
8705 type = MAILIMAP_RESP_TEXT_CODE_BADCHARSET;
8706 }
8707
8708 if (r == MAILIMAP_ERROR_PARSE) {
8709
8710 r = mailimap_capability_data_parse(fd, buffer, &cur_token,
8711 &cap_data,
8712 progr_rate, progr_fun);
8713 if (r == MAILIMAP_NO_ERROR)
8714 type = MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA;
8715 }
8716
8717 if (r == MAILIMAP_ERROR_PARSE) {
8718 r = mailimap_resp_text_code_permanentflags_parse(fd, buffer, &cur_token,
8719 &permanentflags,
8720 progr_rate,
8721 progr_fun);
8722 if (r == MAILIMAP_NO_ERROR)
8723 type = MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS;
8724 }
8725
8726 if (r == MAILIMAP_ERROR_PARSE) {
8727 r = mailimap_resp_text_code_number_parse(fd, buffer, &cur_token,
8728 &resp_text_code,
8729 progr_rate, progr_fun);
8730 }
8731
8732 if (r == MAILIMAP_ERROR_PARSE) {
8733 r = mailimap_resp_text_code_other_parse(fd, buffer, &cur_token,
8734 &resp_text_code,
8735 progr_rate, progr_fun);
8736 }
8737
8738 if (r != MAILIMAP_NO_ERROR) {
8739 res = r;
8740 goto err;
8741 }
8742
8743 if (resp_text_code == NULL) {
8744 resp_text_code = mailimap_resp_text_code_new(type,
8745 badcharset, cap_data,
8746 permanentflags,
8747 0, 0, 0, NULL, NULL);
8748 if (resp_text_code == NULL) {
8749 res = MAILIMAP_ERROR_MEMORY;
8750 goto free;
8751 }
8752 }
8753
8754 * result = resp_text_code;
8755 * index = cur_token;
8756
8757 return MAILIMAP_NO_ERROR;
8758
8759free:
8760 if (permanentflags) {
8761 clist_foreach(permanentflags,
8762 (clist_func) mailimap_flag_perm_free, NULL);
8763 clist_free(permanentflags);
8764 }
8765 if (cap_data)
8766 mailimap_capability_data_free(cap_data);
8767 if (badcharset) {
8768 clist_foreach(badcharset, (clist_func) mailimap_astring_free, NULL);
8769 clist_free(badcharset);
8770 }
8771err:
8772 return res;
8773}
8774
8775/*
8776 UNIMPLEMENTED
8777 search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key)
8778 ; CHARSET argument to MUST be registered with IANA
8779*/
8780
8781/*
8782 UNIMPLEMENTED
8783 search-key = "ALL" / "ANSWERED" / "BCC" SP astring /
8784 "BEFORE" SP date / "BODY" SP astring /
8785 "CC" SP astring / "DELETED" / "FLAGGED" /
8786 "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" /
8787 "OLD" / "ON" SP date / "RECENT" / "SEEN" /
8788 "SINCE" SP date / "SUBJECT" SP astring /
8789 "TEXT" SP astring / "TO" SP astring /
8790 "UNANSWERED" / "UNDELETED" / "UNFLAGGED" /
8791 "UNKEYWORD" SP flag-keyword / "UNSEEN" /
8792 ; Above this line were in [IMAP2]
8793 "DRAFT" / "HEADER" SP header-fld-name SP astring /
8794 "LARGER" SP number / "NOT" SP search-key /
8795 "OR" SP search-key SP search-key /
8796 "SENTBEFORE" SP date / "SENTON" SP date /
8797 "SENTSINCE" SP date / "SMALLER" SP number /
8798 "UID" SP set / "UNDRAFT" / set /
8799 "(" search-key *(SP search-key) ")"
8800*/
8801
8802/*
8803 section = "[" [section-spec] "]"
8804*/
8805
8806static int
8807mailimap_section_parse(mailstream * fd, MMAPString * buffer,
8808 size_t * index,
8809 struct mailimap_section ** result,
8810 size_t progr_rate,
8811 progress_function * progr_fun)
8812{
8813 struct mailimap_section_spec * section_spec;
8814 size_t cur_token;
8815 struct mailimap_section * section;
8816 int r;
8817 int res;
8818
8819 cur_token = * index;
8820
8821 section_spec = NULL;
8822
8823 r = mailimap_obracket_parse(fd, buffer, &cur_token);
8824 if (r != MAILIMAP_NO_ERROR) {
8825 res = r;
8826 goto err;
8827 }
8828
8829 r = mailimap_section_spec_parse(fd, buffer, &cur_token, &section_spec,
8830 progr_rate, progr_fun);
8831 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
8832 res = r;
8833 goto err;
8834 }
8835
8836 r = mailimap_cbracket_parse(fd, buffer, &cur_token);
8837 if (r != MAILIMAP_NO_ERROR) {
8838 res = r;
8839 goto err;
8840 }
8841
8842 if (section_spec == NULL)
8843 section = NULL;
8844 else {
8845 section = mailimap_section_new(section_spec);
8846 if (section == NULL) {
8847 res = MAILIMAP_ERROR_MEMORY;
8848 goto free;
8849 }
8850 }
8851
8852 * result = section;
8853 * index = cur_token;
8854
8855 return MAILIMAP_NO_ERROR;
8856
8857 free:
8858 mailimap_section_spec_free(section_spec);
8859 err:
8860 return res;
8861}
8862
8863/*
8864 section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list /
8865 "TEXT"
8866 ; top-level or MESSAGE/RFC822 part
8867*/
8868
8869static int
8870mailimap_section_msgtext_parse(mailstream * fd, MMAPString * buffer,
8871 size_t * index,
8872 struct mailimap_section_msgtext ** result,
8873 size_t progr_rate,
8874 progress_function * progr_fun)
8875{
8876 size_t cur_token;
8877 int type;
8878 struct mailimap_header_list * header_list;
8879 struct mailimap_section_msgtext * msgtext;
8880 int r;
8881 int res;
8882
8883 cur_token = * index;
8884
8885 header_list = NULL;
8886
8887 type = mailimap_section_msgtext_get_token_value(fd, buffer, &cur_token);
8888 if (type == -1) {
8889 res = MAILIMAP_ERROR_PARSE;
8890 goto err;
8891 }
8892
8893 if (type == MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS) {
8894 r = mailimap_header_list_parse(fd, buffer, &cur_token, &header_list,
8895 progr_rate, progr_fun);
8896 if (r != MAILIMAP_NO_ERROR) {
8897 res = r;
8898 goto err;
8899 }
8900 }
8901 else if (type == MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT) {
8902 r = mailimap_header_list_parse(fd, buffer, &cur_token, &header_list,
8903 progr_rate, progr_fun);
8904 if (r != MAILIMAP_NO_ERROR) {
8905 res = r;
8906 goto err;
8907 }
8908 }
8909
8910 msgtext = mailimap_section_msgtext_new(type, header_list);
8911 if (msgtext == NULL) {
8912 res = MAILIMAP_ERROR_MEMORY;
8913 goto free_header_list;
8914 }
8915
8916 * result = msgtext;
8917 * index = cur_token;
8918
8919 return MAILIMAP_NO_ERROR;
8920
8921 free_header_list:
8922 if (header_list)
8923 mailimap_header_list_free(header_list);
8924 err:
8925 return res;
8926}
8927
8928/*
8929 section-part = nz-number *("." nz-number)
8930 ; body part nesting
8931*/
8932
8933static int
8934mailimap_section_part_parse(mailstream * fd, MMAPString * buffer,
8935 size_t * index,
8936 struct mailimap_section_part ** result,
8937 size_t progr_rate,
8938 progress_function * progr_fun)
8939{
8940 struct mailimap_section_part * section_part;
8941 size_t cur_token;
8942 clist * section_id;
8943 int r;
8944 int res;
8945
8946 cur_token = * index;
8947 section_id = NULL;
8948
8949 r = mailimap_struct_list_parse(fd, buffer, &cur_token, &section_id, '.',
8950 (mailimap_struct_parser *)
8951 mailimap_nz_number_alloc_parse,
8952 (mailimap_struct_destructor *)
8953 mailimap_number_alloc_free,
8954 progr_rate, progr_fun);
8955 if (r != MAILIMAP_NO_ERROR) {
8956 res = r;
8957 goto err;
8958 }
8959
8960 section_part = mailimap_section_part_new(section_id);
8961 if (section_part == NULL) {
8962 res = MAILIMAP_ERROR_MEMORY;
8963 goto free_section_id;
8964 }
8965
8966 * result = section_part;
8967 * index = cur_token;
8968
8969 return MAILIMAP_NO_ERROR;
8970
8971 free_section_id:
8972 clist_foreach(section_id, (clist_func) mailimap_number_alloc_free, NULL);
8973 clist_free(section_id);
8974 err:
8975 return res;
8976}
8977
8978/*
8979 section-spec = section-msgtext / (section-part ["." section-text])
8980*/
8981
8982static int
8983mailimap_section_spec_parse(mailstream * fd, MMAPString * buffer,
8984 size_t * index,
8985 struct mailimap_section_spec ** result,
8986 size_t progr_rate,
8987 progress_function * progr_fun)
8988{
8989 int type;
8990 struct mailimap_section_msgtext * section_msgtext;
8991 struct mailimap_section_part * section_part;
8992 struct mailimap_section_text * section_text;
8993 struct mailimap_section_spec * section_spec;
8994 size_t cur_token;
8995 int r;
8996 int res;
8997 size_t final_token;
8998
8999 cur_token = * index;
9000
9001 section_msgtext = NULL;
9002 section_part = NULL;
9003 section_text = NULL;
9004
9005 r = mailimap_section_msgtext_parse(fd, buffer, &cur_token,
9006 &section_msgtext,
9007 progr_rate, progr_fun);
9008 switch (r) {
9009 case MAILIMAP_NO_ERROR:
9010 type = MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT;
9011 break;
9012
9013 case MAILIMAP_ERROR_PARSE:
9014
9015 r = mailimap_section_part_parse(fd, buffer, &cur_token,
9016 &section_part,
9017 progr_rate, progr_fun);
9018 if (r != MAILIMAP_NO_ERROR) {
9019 res = r;
9020 goto err;
9021 }
9022
9023 final_token = cur_token;
9024
9025 type = MAILIMAP_SECTION_SPEC_SECTION_PART;
9026
9027 r = mailimap_dot_parse(fd, buffer, &cur_token);
9028 if (r == MAILIMAP_NO_ERROR) {
9029 r = mailimap_section_text_parse(fd, buffer, &cur_token, &section_text,
9030 progr_rate, progr_fun);
9031 if (r == MAILIMAP_NO_ERROR) {
9032 final_token = cur_token;
9033 }
9034 else if (r != MAILIMAP_ERROR_PARSE) {
9035 res = r;
9036 goto err;
9037 }
9038 }
9039 else if (r != MAILIMAP_ERROR_PARSE) {
9040 res = r;
9041 goto err;
9042 }
9043
9044 cur_token = final_token;
9045 break;
9046
9047 default:
9048 res = r;
9049 goto err;
9050 }
9051
9052 section_spec = mailimap_section_spec_new(type, section_msgtext,
9053 section_part, section_text);
9054 if (section_spec == NULL) {
9055 res = MAILIMAP_ERROR_MEMORY;
9056 goto free;
9057 }
9058
9059 * result = section_spec;
9060 * index = cur_token;
9061
9062 return MAILIMAP_NO_ERROR;
9063
9064 free:
9065 if (section_msgtext)
9066 mailimap_section_msgtext_free(section_msgtext);
9067 if (section_part)
9068 mailimap_section_part_free(section_part);
9069 if (section_text)
9070 mailimap_section_text_free(section_text);
9071 err:
9072 return res;
9073}
9074
9075/*
9076 section-text = section-msgtext / "MIME"
9077 ; text other than actual body part (headers, etc.)
9078*/
9079
9080static int
9081mailimap_section_text_parse(mailstream * fd, MMAPString * buffer,
9082 size_t * index,
9083 struct mailimap_section_text ** result,
9084 size_t progr_rate,
9085 progress_function * progr_fun)
9086{
9087 struct mailimap_section_msgtext * section_msgtext;
9088 size_t cur_token;
9089 struct mailimap_section_text * section_text;
9090 int type;
9091 int r;
9092 int res;
9093
9094 cur_token = * index;
9095
9096 section_msgtext = NULL;
9097
9098 type = MAILIMAP_SECTION_TEXT_ERROR; /* XXX - removes a gcc warning */
9099
9100 r = mailimap_section_msgtext_parse(fd, buffer, &cur_token, &section_msgtext,
9101 progr_rate, progr_fun);
9102 if (r == MAILIMAP_NO_ERROR)
9103 type = MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT;
9104
9105 if (r == MAILIMAP_ERROR_PARSE) {
9106 r= mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "MIME");
9107
9108 if (r == MAILIMAP_NO_ERROR)
9109 type = MAILIMAP_SECTION_TEXT_MIME;
9110 }
9111
9112 if (r != MAILIMAP_NO_ERROR) {
9113 res = r;
9114 goto err;
9115 }
9116
9117 section_text = mailimap_section_text_new(type, section_msgtext);
9118 if (section_text == NULL) {
9119 res = MAILIMAP_ERROR_MEMORY;
9120 goto free;
9121 }
9122
9123 * result = section_text;
9124 * index = cur_token;
9125
9126 return MAILIMAP_NO_ERROR;
9127
9128 free:
9129 if (section_msgtext)
9130 mailimap_section_msgtext_free(section_msgtext);
9131 err:
9132 return res;
9133}
9134
9135/*
9136 UNIMPLEMENTED
9137 select = "SELECT" SP mailbox
9138*/
9139
9140/*
9141 UNIMPLEMENTED
9142 sequence-num = nz-number / "*"
9143 ; * is the largest number in use. For message
9144 ; sequence numbers, it is the number of messages
9145 ; in the mailbox. For unique identifiers, it is
9146 ; the unique identifier of the last message in
9147 ; the mailbox.
9148*/
9149
9150/*
9151 UNIMPLEMENTED
9152 set = sequence-num / (sequence-num ":" sequence-num) /
9153 (set "," set)
9154 ; Identifies a set of messages. For message
9155 ; sequence numbers, these are consecutive
9156 ; numbers from 1 to the number of messages in
9157 ; the mailbox
9158 ; Comma delimits individual numbers, colon
9159 ; delimits between two numbers inclusive.
9160 ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13,
9161 ; 14,15 for a mailbox with 15 messages.
9162*/
9163
9164/*
9165 UNIMPLEMENTED
9166 status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")"
9167*/
9168
9169/*
9170 status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" /
9171 "UNSEEN"
9172*/
9173
9174static int mailimap_status_att_parse(mailstream * fd, MMAPString * buffer,
9175 size_t * index, int * result)
9176{
9177 int type;
9178 size_t cur_token;
9179
9180 cur_token = * index;
9181
9182 type = mailimap_status_att_get_token_value(fd, buffer, &cur_token);
9183
9184 if (type == -1)
9185 return MAILIMAP_ERROR_PARSE;
9186
9187 * result = type;
9188 * index = cur_token;
9189
9190 return MAILIMAP_NO_ERROR;
9191}
9192
9193
9194/*
9195 UNIMPLEMENTED
9196 store = "STORE" SP set SP store-att-flags
9197*/
9198
9199/*
9200 UNIMPLEMENTED
9201 store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP
9202 (flag-list / (flag *(SP flag)))
9203*/
9204
9205/*
9206 string = quoted / literal
9207*/
9208
9209static int
9210mailimap_string_parse(mailstream * fd, MMAPString * buffer,
9211 size_t * index, char ** result,
9212 size_t * result_len,
9213 size_t progr_rate,
9214 progress_function * progr_fun)
9215{
9216 size_t cur_token;
9217 char * string;
9218 int r;
9219 size_t len;
9220
9221 cur_token = * index;
9222
9223 r = mailimap_quoted_parse(fd, buffer, &cur_token, &string,
9224 progr_rate, progr_fun);
9225 if (r == MAILIMAP_NO_ERROR)
9226 len = strlen(string);
9227 else if (r == MAILIMAP_ERROR_PARSE) {
9228 r = mailimap_literal_parse(fd, buffer, &cur_token, &string, &len,
9229 progr_rate, progr_fun);
9230 }
9231
9232 if (r != MAILIMAP_NO_ERROR)
9233 return r;
9234
9235 * result = string;
9236 if (result_len != NULL)
9237 * result_len = len;
9238 * index = cur_token;
9239
9240 return MAILIMAP_NO_ERROR;
9241}
9242
9243
9244/*
9245 UNIMPLEMENTED
9246 subscribe = "SUBSCRIBE" SP mailbox
9247*/
9248
9249/*
9250 tag = 1*<any ASTRING-CHAR except "+">
9251*/
9252
9253/*
9254 any ASTRING-CHAR except "+"
9255*/
9256
9257static int is_tag_char(char ch)
9258{
9259 if (ch == '+')
9260 return FALSE;
9261 return is_astring_char(ch);
9262}
9263
9264/*
9265 tag = 1*<any ASTRING-CHAR except "+">
9266*/
9267
9268static int mailimap_tag_parse(mailstream * fd, MMAPString * buffer,
9269 size_t * index, char ** result,
9270 size_t progr_rate,
9271 progress_function * progr_fun)
9272{
9273 size_t cur_token;
9274 char * tag;
9275 int r;
9276
9277 cur_token = * index;
9278
9279 r = mailimap_custom_string_parse(fd, buffer, &cur_token, &tag,
9280 is_tag_char);
9281 if (r != MAILIMAP_NO_ERROR)
9282 return r;
9283
9284 * index = cur_token;
9285 * result = tag;
9286
9287 return MAILIMAP_NO_ERROR;
9288}
9289
9290/*
9291 text = 1*TEXT-CHAR
9292*/
9293
9294static int mailimap_text_parse(mailstream * fd, MMAPString * buffer,
9295 size_t * index, char ** result,
9296 size_t progr_rate,
9297 progress_function * progr_fun)
9298{
9299 return mailimap_custom_string_parse(fd, buffer, index, result,
9300 is_text_char);
9301}
9302
9303
9304/*
9305 TEXT-CHAR = <any CHAR except CR and LF>
9306*/
9307
9308static int is_text_char(char ch)
9309{
9310 if ((ch == '\r') || (ch == '\n'))
9311 return FALSE;
9312
9313 return is_char(ch);
9314}
9315
9316/*
9317 time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
9318 ; Hours minutes seconds
9319*/
9320
9321/*
9322 2DIGIT
9323*/
9324
9325static int mailimap_2digit_parse(mailstream * fd, MMAPString * buffer,
9326 size_t * index, int * result)
9327{
9328#ifndef UNSTRICT_SYNTAX
9329 int digit;
9330 int two_digit;
9331 size_t cur_token;
9332 int r;
9333
9334 cur_token = * index;
9335
9336 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit);
9337 if (r != MAILIMAP_NO_ERROR)
9338 return r;
9339
9340 two_digit = digit;
9341
9342 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit);
9343 if (r != MAILIMAP_NO_ERROR)
9344 return r;
9345
9346 two_digit = two_digit * 10 + digit;
9347
9348 * result = two_digit;
9349 * index = cur_token;
9350
9351 return MAILIMAP_NO_ERROR;
9352#else
9353 uint32_t number;
9354 size_t cur_token;
9355 int r;
9356
9357 cur_token = * index;
9358
9359 r = mailimap_number_parse(fd, buffer, &cur_token, &number);
9360 if (r != MAILIMAP_NO_ERROR)
9361 return r;
9362
9363 * index = cur_token;
9364 * result = number;
9365
9366 return MAILIMAP_NO_ERROR;
9367#endif
9368}
9369
9370/*
9371 time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
9372 ; Hours minutes seconds
9373*/
9374
9375static int mailimap_time_parse(mailstream * fd, MMAPString * buffer,
9376 size_t * index,
9377 int * phour, int * pmin, int * psec)
9378{
9379 size_t cur_token;
9380 int hour;
9381 int min;
9382 int sec;
9383 int r;
9384
9385 cur_token = * index;
9386
9387 r = mailimap_2digit_parse(fd, buffer, &cur_token, &hour);
9388 if (r != MAILIMAP_NO_ERROR)
9389 return r;
9390
9391 r = mailimap_colon_parse(fd, buffer, &cur_token);
9392 if (r != MAILIMAP_NO_ERROR)
9393 return r;
9394
9395 r = mailimap_2digit_parse(fd, buffer, &cur_token, &min);
9396 if (r != MAILIMAP_NO_ERROR)
9397 return r;
9398
9399 r = mailimap_colon_parse(fd, buffer, &cur_token);
9400 if (r != MAILIMAP_NO_ERROR)
9401 return r;
9402
9403 r = mailimap_2digit_parse(fd, buffer, &cur_token, &sec);
9404 if (r != MAILIMAP_NO_ERROR)
9405 return r;
9406
9407 * phour = hour;
9408 * pmin = min;
9409 * psec = sec;
9410 * index = cur_token;
9411
9412 return MAILIMAP_NO_ERROR;
9413}
9414
9415/*
9416 UNIMPLEMENTED
9417 uid = "UID" SP (copy / fetch / search / store)
9418 ; Unique identifiers used instead of message
9419 ; sequence numbers
9420*/
9421
9422/*
9423 uniqueid = nz-number
9424 ; Strictly ascending
9425*/
9426
9427static int mailimap_uniqueid_parse(mailstream * fd, MMAPString * buffer,
9428 size_t * index, uint32_t * result)
9429{
9430 return mailimap_nz_number_parse(fd, buffer, index, result);
9431}
9432
9433/*
9434 UNIMPLEMENTED
9435 unsubscribe = "UNSUBSCRIBE" SP mailbox
9436*/
9437
9438/*
9439 UNIMPLEMENTED
9440 userid = astring
9441*/
9442
9443/*
9444 UNIMPLEMENTED
9445 x-command = "X" atom <experimental command arguments>
9446*/
9447
9448/*
9449 zone = ("+" / "-") 4DIGIT
9450 ; Signed four-digit value of hhmm representing
9451 ; hours and minutes east of Greenwich (that is,
9452 ; the amount that the given time differs from
9453 ; Universal Time). Subtracting the timezone
9454 ; from the given time will give the UT form.
9455 ; The Universal Time zone is "+0000".
9456*/
9457
9458static int mailimap_zone_parse(mailstream * fd, MMAPString * buffer,
9459 size_t * index, int * result)
9460{
9461 size_t cur_token;
9462 uint32_t zone;
9463#ifndef UNSTRICT_SYNTAX
9464 int i;
9465 int digit;
9466#endif
9467 int sign;
9468 int r;
9469
9470 cur_token = * index;
9471
9472 sign = 1;
9473 r = mailimap_plus_parse(fd, buffer, &cur_token);
9474 if (r == MAILIMAP_NO_ERROR)
9475 sign = 1;
9476
9477 if (r == MAILIMAP_ERROR_PARSE) {
9478 r = mailimap_minus_parse(fd, buffer, &cur_token);
9479 if (r == MAILIMAP_NO_ERROR)
9480 sign = -1;
9481 }
9482
9483 if (r != MAILIMAP_NO_ERROR)
9484 return r;
9485
9486#ifdef UNSTRICT_SYNTAX
9487 r = mailimap_number_parse(fd, buffer, &cur_token, &zone);
9488 if (r != MAILIMAP_NO_ERROR)
9489 return r;
9490#else
9491 zone = 0;
9492 for(i = 0 ; i < 4 ; i ++) {
9493 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit);
9494 if (r != MAILIMAP_NO_ERROR)
9495 return r;
9496 zone = zone * 10 + digit;
9497 }
9498#endif
9499
9500 zone *= sign;
9501
9502 * result = zone;
9503 * index = cur_token;
9504
9505 return MAILIMAP_NO_ERROR;
9506}