summaryrefslogtreecommitdiffabout
path: root/libetpan/src/low-level/imap/mailimap.c
Unidiff
Diffstat (limited to 'libetpan/src/low-level/imap/mailimap.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/low-level/imap/mailimap.c2164
1 files changed, 2164 insertions, 0 deletions
diff --git a/libetpan/src/low-level/imap/mailimap.c b/libetpan/src/low-level/imap/mailimap.c
new file mode 100644
index 0000000..ef38413
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap.c
@@ -0,0 +1,2164 @@
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 "mailimap.h"
37#include "mailimap_parser.h"
38#include "mailimap_sender.h"
39#include "mail.h"
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44
45#ifdef DEBUG
46#include "mailimap_print.h"
47#endif
48
49/*
50 RFC 2060 : IMAP4rev1
51 draft-crispin-imapv-15
52 RFC 2222 : Simple Authentication and Security Layer
53
542061 IMAP4 Compatibility with IMAP2bis. M. Crispin. December 1996.
55 (Format: TXT=5867 bytes) (Obsoletes RFC1730) (Status: INFORMATIONAL)
56
572062 Internet Message Access Protocol - Obsolete Syntax. M. Crispin.
58 December 1996. (Format: TXT=14222 bytes) (Status: INFORMATIONAL)
59
602086 IMAP4 ACL extension. J. Myers. January 1997. (Format: TXT=13925
61 bytes) (Status: PROPOSED STANDARD)
62
632087 IMAP4 QUOTA extension. J. Myers. January 1997. (Format: TXT=8542
64 bytes) (Status: PROPOSED STANDARD)
65
662088 IMAP4 non-synchronizing literals. J. Myers. January 1997.
67 (Format: TXT=4052 bytes) (Status: PROPOSED STANDARD)
68
692177 IMAP4 IDLE command. B. Leiba. June 1997. (Format: TXT=6770 bytes)
70 (Status: PROPOSED STANDARD)
71
722180 IMAP4 Multi-Accessed Mailbox Practice. M. Gahrns. July 1997.
73 (Format: TXT=24750 bytes) (Status: INFORMATIONAL)
74
752192 IMAP URL Scheme. C. Newman. September 1997. (Format: TXT=31426
76 bytes) (Status: PROPOSED STANDARD)
77
782193 IMAP4 Mailbox Referrals. M. Gahrns. September 1997. (Format:
79 TXT=16248 bytes) (Status: PROPOSED STANDARD)
80
812195 IMAP/POP AUTHorize Extension for Simple Challenge/Response. J.
82 Klensin, R. Catoe, P. Krumviede. September 1997. (Format: TXT=10468
83 bytes) (Obsoletes RFC2095) (Status: PROPOSED STANDARD)
84
852221 IMAP4 Login Referrals. M. Gahrns. October 1997. (Format: TXT=9251
86 bytes) (Status: PROPOSED STANDARD)
87
882342 IMAP4 Namespace. M. Gahrns, C. Newman. May 1998. (Format:
89 TXT=19489 bytes) (Status: PROPOSED STANDARD)
90
912359 IMAP4 UIDPLUS extension. J. Myers. June 1998. (Format: TXT=10862
92 bytes) (Status: PROPOSED STANDARD)
93
942595 Using TLS with IMAP, POP3 and ACAP. C. Newman. June 1999.
95 (Format: TXT=32440 bytes) (Status: PROPOSED STANDARD)
96
972683 IMAP4 Implementation Recommendations. B. Leiba. September 1999.
98 (Format: TXT=56300 bytes) (Status: INFORMATIONAL)
99
1002971 IMAP4 ID extension. T. Showalter. October 2000. (Format:
101 TXT=14670 bytes) (Status: PROPOSED STANDARD)
102
103http://www.ietf.org/ids.by.wg/imapext.html
104*/
105
106static char * read_line(mailimap * session);
107
108static int send_current_tag(mailimap * session);
109
110static int parse_response(mailimap * session,
111 struct mailimap_response ** result);
112
113static int parse_greeting(mailimap * session,
114 struct mailimap_greeting ** result);
115
116
117/* struct mailimap_response_info * */
118
119static void resp_text_store(mailimap * session,
120 struct mailimap_resp_text *
121 resp_text)
122{
123 struct mailimap_resp_text_code * resp_text_code;
124
125 resp_text_code = resp_text->rsp_code;
126
127 if (resp_text_code != NULL) {
128 switch (resp_text_code->rc_type) {
129 case MAILIMAP_RESP_TEXT_CODE_ALERT:
130 if (session->imap_response_info)
131 if (session->imap_response_info->rsp_alert != NULL)
132 free(session->imap_response_info->rsp_alert);
133 session->imap_response_info->rsp_alert = strdup(resp_text->rsp_text);
134 break;
135
136 case MAILIMAP_RESP_TEXT_CODE_BADCHARSET:
137 if (session->imap_response_info) {
138 if (session->imap_response_info->rsp_badcharset != NULL) {
139 clist_foreach(resp_text_code->rc_data.rc_badcharset,
140 (clist_func) mailimap_astring_free, NULL);
141 clist_free(resp_text_code->rc_data.rc_badcharset);
142 }
143 session->imap_response_info->rsp_badcharset =
144 resp_text_code->rc_data.rc_badcharset;
145 resp_text_code->rc_data.rc_badcharset = NULL;
146 }
147 break;
148
149 case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA:
150 if (session->imap_connection_info) {
151 if (session->imap_connection_info->imap_capability != NULL)
152 mailimap_capability_data_free(session->imap_connection_info->imap_capability);
153 session->imap_connection_info->imap_capability =
154 resp_text_code->rc_data.rc_cap_data;
155 /* detach before free */
156 resp_text_code->rc_data.rc_cap_data = NULL;
157 }
158 break;
159
160 case MAILIMAP_RESP_TEXT_CODE_PARSE:
161 if (session->imap_response_info) {
162 if (session->imap_response_info->rsp_parse != NULL)
163 free(session->imap_response_info->rsp_parse);
164 session->imap_response_info->rsp_parse = strdup(resp_text->rsp_text);
165 }
166 break;
167
168 case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS:
169 if (session->imap_selection_info) {
170 if (session->imap_selection_info->sel_perm_flags != NULL) {
171 clist_foreach(session->imap_selection_info->sel_perm_flags,
172 (clist_func) mailimap_flag_perm_free, NULL);
173 clist_free(session->imap_selection_info->sel_perm_flags);
174 }
175 session->imap_selection_info->sel_perm_flags =
176 resp_text_code->rc_data.rc_perm_flags;
177 /* detach before free */
178 resp_text_code->rc_data.rc_perm_flags = NULL;
179 }
180 break;
181
182 case MAILIMAP_RESP_TEXT_CODE_READ_ONLY:
183 if (session->imap_selection_info)
184 session->imap_selection_info->sel_perm = MAILIMAP_MAILBOX_READONLY;
185 break;
186
187 case MAILIMAP_RESP_TEXT_CODE_READ_WRITE:
188 if (session->imap_selection_info)
189 session->imap_selection_info->sel_perm = MAILIMAP_MAILBOX_READWRITE;
190 break;
191
192 case MAILIMAP_RESP_TEXT_CODE_TRY_CREATE:
193 if (session->imap_response_info)
194 session->imap_response_info->rsp_trycreate = TRUE;
195 break;
196
197 case MAILIMAP_RESP_TEXT_CODE_UIDNEXT:
198 if (session->imap_selection_info)
199 session->imap_selection_info->sel_uidnext =
200 resp_text_code->rc_data.rc_uidnext;
201 break;
202
203 case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY:
204 if (session->imap_selection_info)
205 session->imap_selection_info->sel_uidvalidity =
206 resp_text_code->rc_data.rc_uidvalidity;
207 break;
208
209 case MAILIMAP_RESP_TEXT_CODE_UNSEEN:
210 if (session->imap_selection_info)
211 session->imap_selection_info->sel_first_unseen =
212 resp_text_code->rc_data.rc_first_unseen;
213 break;
214 }
215 }
216}
217
218static void resp_cond_state_store(mailimap * session,
219 struct mailimap_resp_cond_state * resp_cond_state)
220{
221 resp_text_store(session, resp_cond_state->rsp_text);
222}
223
224static void mailbox_data_store(mailimap * session,
225 struct mailimap_mailbox_data * mb_data)
226{
227 int r;
228
229 switch (mb_data->mbd_type) {
230 case MAILIMAP_MAILBOX_DATA_FLAGS:
231 if (session->imap_selection_info) {
232 if (session->imap_selection_info->sel_flags != NULL)
233 mailimap_flag_list_free(session->imap_selection_info->sel_flags);
234 session->imap_selection_info->sel_flags = mb_data->mbd_data.mbd_flags;
235 mb_data->mbd_data.mbd_flags = NULL;
236 }
237 break;
238
239 case MAILIMAP_MAILBOX_DATA_LIST:
240 if (session->imap_response_info) {
241 r = clist_append(session->imap_response_info->rsp_mailbox_list,
242 mb_data->mbd_data.mbd_list);
243 if (r == 0)
244 mb_data->mbd_data.mbd_list = NULL;
245 else {
246 /* TODO must handle error case */
247 }
248 }
249 break;
250
251 case MAILIMAP_MAILBOX_DATA_LSUB:
252 if (session->imap_response_info) {
253 r = clist_append(session->imap_response_info->rsp_mailbox_lsub,
254 mb_data->mbd_data.mbd_lsub);
255 if (r == 0)
256 mb_data->mbd_data.mbd_lsub = NULL;
257 else {
258 /* TODO must handle error case */
259 }
260 }
261 break;
262
263 case MAILIMAP_MAILBOX_DATA_SEARCH:
264 if (session->imap_response_info) {
265 if (session->imap_response_info->rsp_search_result != NULL) {
266 if (mb_data->mbd_data.mbd_search != NULL) {
267 clist_concat(session->imap_response_info->rsp_search_result,
268 mb_data->mbd_data.mbd_search);
269 clist_free(mb_data->mbd_data.mbd_search);
270 mb_data->mbd_data.mbd_search = NULL;
271 }
272 }
273 else {
274 if (mb_data->mbd_data.mbd_search != NULL) {
275 session->imap_response_info->rsp_search_result =
276 mb_data->mbd_data.mbd_search;
277 mb_data->mbd_data.mbd_search = NULL;
278 }
279 }
280 }
281 break;
282
283 case MAILIMAP_MAILBOX_DATA_STATUS:
284 if (session->imap_response_info) {
285 if (session->imap_response_info->rsp_status != NULL)
286 mailimap_mailbox_data_status_free(session->imap_response_info->rsp_status);
287 session->imap_response_info->rsp_status = mb_data->mbd_data.mbd_status;
288#if 0
289 if (session->imap_selection_info != NULL) {
290 clistiter * cur;
291
292 for(cur = clist_begin(mb_data->status->status_info_list)
293 ; cur != NULL ; cur = clist_next(cur)) {
294 struct mailimap_status_info * info;
295
296 info = clist_content(cur);
297 switch (info->att) {
298 case MAILIMAP_STATUS_ATT_MESSAGES:
299 session->imap_selection_info->exists = info->value;
300 break;
301 case MAILIMAP_STATUS_ATT_RECENT:
302 session->imap_selection_info->recent = info->value;
303 break;
304 case MAILIMAP_STATUS_ATT_UIDNEXT:
305 session->imap_selection_info->uidnext = info->value;
306 break;
307 case MAILIMAP_STATUS_ATT_UIDVALIDITY:
308 session->imap_selection_info->uidvalidity = info->value;
309 break;
310 case MAILIMAP_STATUS_ATT_UNSEEN:
311 session->imap_selection_info->unseen = info->value;
312 break;
313 }
314 }
315 }
316#endif
317#if 0
318 mailimap_mailbox_data_status_free(mb_data->status);
319#endif
320 mb_data->mbd_data.mbd_status = NULL;
321 }
322 break;
323
324 case MAILIMAP_MAILBOX_DATA_EXISTS:
325 if (session->imap_selection_info)
326 session->imap_selection_info->sel_exists = mb_data->mbd_data.mbd_exists;
327 break;
328
329 case MAILIMAP_MAILBOX_DATA_RECENT:
330 if (session->imap_selection_info)
331 session->imap_selection_info->sel_recent =
332 mb_data->mbd_data.mbd_recent;
333 break;
334 }
335}
336
337static void
338message_data_store(mailimap * session,
339 struct mailimap_message_data * msg_data)
340{
341 uint32_t * expunged;
342 int r;
343
344 switch (msg_data->mdt_type) {
345 case MAILIMAP_MESSAGE_DATA_EXPUNGE:
346 if (session->imap_response_info) {
347 expunged = mailimap_number_alloc_new(msg_data->mdt_number);
348 if (expunged != NULL) {
349 r = clist_append(session->imap_response_info->rsp_expunged, expunged);
350 if (r == 0) {
351 /* do nothing */
352 }
353 else {
354 /* TODO : must handle error case */
355 mailimap_number_alloc_free(expunged);
356 }
357 if (session->imap_selection_info != NULL)
358 session->imap_selection_info->sel_exists --;
359 }
360 }
361 break;
362
363 case MAILIMAP_MESSAGE_DATA_FETCH:
364 r = clist_append(session->imap_response_info->rsp_fetch_list,
365 msg_data->mdt_msg_att);
366 if (r == 0) {
367 msg_data->mdt_msg_att->att_number = msg_data->mdt_number;
368 msg_data->mdt_msg_att = NULL;
369 }
370 else {
371 /* TODO : must handle error case */
372 }
373 break;
374 }
375}
376
377static void
378cont_req_or_resp_data_store(mailimap * session,
379 struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data)
380{
381 if (cont_req_or_resp_data->rsp_type == MAILIMAP_RESP_RESP_DATA) {
382 struct mailimap_response_data * resp_data;
383
384 resp_data = cont_req_or_resp_data->rsp_data.rsp_resp_data;
385
386 switch (resp_data->rsp_type) {
387 case MAILIMAP_RESP_DATA_TYPE_COND_STATE:
388 resp_cond_state_store(session, resp_data->rsp_data.rsp_cond_state);
389 break;
390 case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA:
391 mailbox_data_store(session, resp_data->rsp_data.rsp_mailbox_data);
392 break;
393 case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA:
394 message_data_store(session, resp_data->rsp_data.rsp_message_data);
395 break;
396 case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA:
397 if (session->imap_connection_info) {
398 if (session->imap_connection_info->imap_capability != NULL)
399 mailimap_capability_data_free(session->imap_connection_info->imap_capability);
400 session->imap_connection_info->imap_capability = resp_data->rsp_data.rsp_capability_data;
401 resp_data->rsp_data.rsp_capability_data = NULL;
402 }
403 break;
404 }
405 }
406}
407
408static void response_tagged_store(mailimap * session,
409 struct mailimap_response_tagged * tagged)
410{
411 resp_cond_state_store(session, tagged->rsp_cond_state);
412}
413
414static void resp_cond_bye_store(mailimap * session,
415 struct mailimap_resp_cond_bye * resp_cond_bye)
416{
417 resp_text_store(session, resp_cond_bye->rsp_text);
418}
419
420static void response_fatal_store(mailimap * session,
421 struct mailimap_response_fatal * fatal)
422{
423 resp_cond_bye_store(session, fatal->rsp_bye);
424}
425
426static void response_done_store(mailimap * session,
427 struct mailimap_response_done * resp_done)
428{
429 switch(resp_done->rsp_type) {
430 case MAILIMAP_RESP_DONE_TYPE_TAGGED:
431 response_tagged_store(session, resp_done->rsp_data.rsp_tagged);
432 break;
433 case MAILIMAP_RESP_DONE_TYPE_FATAL:
434 response_fatal_store(session, resp_done->rsp_data.rsp_fatal);
435 break;
436 }
437}
438
439static void
440response_store(mailimap * session,
441 struct mailimap_response * response)
442{
443 clistiter * cur;
444
445 if (session->imap_response_info) {
446 mailimap_response_info_free(session->imap_response_info);
447 session->imap_response_info = NULL;
448 }
449
450 session->imap_response_info = mailimap_response_info_new();
451 if (session->imap_response_info == NULL) {
452 /* ignored error */
453 return;
454 }
455
456 if (response->rsp_cont_req_or_resp_data_list != NULL) {
457 for(cur = clist_begin(response->rsp_cont_req_or_resp_data_list) ;
458 cur != NULL ; cur = clist_next(cur)) {
459 struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data;
460
461 cont_req_or_resp_data = clist_content(cur);
462
463 cont_req_or_resp_data_store(session, cont_req_or_resp_data);
464 }
465 }
466
467 response_done_store(session, response->rsp_resp_done);
468}
469
470static void resp_cond_auth_store(mailimap * session,
471 struct mailimap_resp_cond_auth * cond_auth)
472{
473 resp_text_store(session, cond_auth->rsp_text);
474}
475
476static void greeting_store(mailimap * session,
477 struct mailimap_greeting * greeting)
478{
479 switch (greeting->gr_type) {
480 case MAILIMAP_GREETING_RESP_COND_AUTH:
481 resp_cond_auth_store(session, greeting->gr_data.gr_auth);
482 break;
483
484 case MAILIMAP_GREETING_RESP_COND_BYE:
485 resp_cond_bye_store(session, greeting->gr_data.gr_bye);
486 break;
487 }
488}
489
490int mailimap_connect(mailimap * session, mailstream * s)
491{
492 struct mailimap_greeting * greeting;
493 int r;
494 int auth_type;
495 struct mailimap_connection_info * connection_info;
496
497 if (session->imap_state != MAILIMAP_STATE_DISCONNECTED)
498 return MAILIMAP_ERROR_BAD_STATE;
499
500 session->imap_stream = s;
501
502 if (session->imap_connection_info)
503 mailimap_connection_info_free(session->imap_connection_info);
504 connection_info = mailimap_connection_info_new();
505 if (connection_info != NULL)
506 session->imap_connection_info = connection_info;
507
508 if (read_line(session) == NULL) {
509 return MAILIMAP_ERROR_STREAM;
510 }
511
512 r = parse_greeting(session, &greeting);
513 if (r != MAILIMAP_NO_ERROR) {
514 return r;
515 }
516
517 auth_type = greeting->gr_data.gr_auth->rsp_type;
518
519 mailimap_greeting_free(greeting);
520
521 switch (auth_type) {
522 case MAILIMAP_RESP_COND_AUTH_PREAUTH:
523 session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
524 return MAILIMAP_NO_ERROR_AUTHENTICATED;
525 default:
526 session->imap_state = MAILIMAP_STATE_NON_AUTHENTICATED;
527 return MAILIMAP_NO_ERROR_NON_AUTHENTICATED;
528 }
529}
530
531
532
533
534
535
536
537
538/* ********************************************************************** */
539
540
541
542int mailimap_append(mailimap * session, const char * mailbox,
543 struct mailimap_flag_list * flag_list,
544 struct mailimap_date_time * date_time,
545 const char * literal, size_t literal_size)
546{
547 struct mailimap_response * response;
548 int r;
549 int error_code;
550 struct mailimap_continue_req * cont_req;
551 size_t index;
552 size_t fixed_literal_size;
553
554 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
555 (session->imap_state != MAILIMAP_STATE_SELECTED))
556 return MAILIMAP_ERROR_BAD_STATE;
557
558 r = send_current_tag(session);
559 if (r != MAILIMAP_NO_ERROR)
560 return r;
561
562 fixed_literal_size = mailstream_get_data_crlf_size(literal, literal_size);
563
564 r = mailimap_append_send(session->imap_stream, mailbox, flag_list, date_time,
565 fixed_literal_size);
566 if (r != MAILIMAP_NO_ERROR)
567 return r;
568
569 if (mailstream_flush(session->imap_stream) == -1)
570 return MAILIMAP_ERROR_STREAM;
571
572 if (read_line(session) == NULL)
573 return MAILIMAP_ERROR_STREAM;
574
575 index = 0;
576
577 r = mailimap_continue_req_parse(session->imap_stream,
578 session->imap_stream_buffer,
579 &index, &cont_req,
580 session->imap_progr_rate, session->imap_progr_fun);
581 if (r == MAILIMAP_NO_ERROR)
582 mailimap_continue_req_free(cont_req);
583
584 if (r == MAILIMAP_ERROR_PARSE) {
585 r = parse_response(session, &response);
586 if (r != MAILIMAP_NO_ERROR)
587 return r;
588 mailimap_response_free(response);
589
590 return MAILIMAP_ERROR_APPEND;
591 }
592
593 r = mailimap_literal_data_send(session->imap_stream, literal, literal_size,
594 session->imap_progr_rate, session->imap_progr_fun);
595 if (r != MAILIMAP_NO_ERROR)
596 return r;
597
598 r = mailimap_crlf_send(session->imap_stream);
599 if (r != MAILIMAP_NO_ERROR)
600 return r;
601
602 if (mailstream_flush(session->imap_stream) == -1)
603 return MAILIMAP_ERROR_STREAM;
604
605 if (read_line(session) == NULL)
606 return MAILIMAP_ERROR_STREAM;
607
608 r = parse_response(session, &response);
609 if (r != MAILIMAP_NO_ERROR)
610 return r;
611
612 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
613
614 mailimap_response_free(response);
615
616 switch (error_code) {
617 case MAILIMAP_RESP_COND_STATE_OK:
618 return MAILIMAP_NO_ERROR;
619
620 default:
621 return MAILIMAP_ERROR_APPEND;
622 }
623}
624
625/*
626gboolean mailimap_authenticate(mailimap * session,
627 gchar * auth_type)
628{
629}
630
631gboolean mailimap_authenticate_resp_send(mailimap * session,
632 gchar * base64)
633{
634}
635*/
636
637int mailimap_noop(mailimap * session)
638{
639 struct mailimap_response * response;
640 int r;
641 int error_code;
642
643 r = send_current_tag(session);
644 if (r != MAILIMAP_NO_ERROR)
645 return r;
646
647 r = mailimap_noop_send(session->imap_stream);
648 if (r != MAILIMAP_NO_ERROR)
649 return r;
650
651 r = mailimap_crlf_send(session->imap_stream);
652 if (r != MAILIMAP_NO_ERROR)
653 return r;
654
655 if (mailstream_flush(session->imap_stream) == -1)
656 return MAILIMAP_ERROR_STREAM;
657
658 if (read_line(session) == NULL)
659 return MAILIMAP_ERROR_STREAM;
660
661 r = parse_response(session, &response);
662 if (r != MAILIMAP_NO_ERROR)
663 return r;
664
665 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
666
667 mailimap_response_free(response);
668
669 switch (error_code) {
670 case MAILIMAP_RESP_COND_STATE_OK:
671 return MAILIMAP_NO_ERROR;
672
673 default:
674 return MAILIMAP_ERROR_NOOP;
675 }
676}
677
678int mailimap_logout(mailimap * session)
679{
680 struct mailimap_response * response;
681 int r;
682 int error_code;
683 int res;
684
685 r = send_current_tag(session);
686 if (r != MAILIMAP_NO_ERROR) {
687 res = r;
688 goto close;
689 }
690
691 r = mailimap_logout_send(session->imap_stream);
692 if (r != MAILIMAP_NO_ERROR) {
693 res = r;
694 goto close;
695 }
696
697 r = mailimap_crlf_send(session->imap_stream);
698 if (r != MAILIMAP_NO_ERROR) {
699 res = r;
700 goto close;
701 }
702
703 if (mailstream_flush(session->imap_stream) == -1) {
704 res = MAILIMAP_ERROR_STREAM;
705 goto close;
706 }
707
708 if (read_line(session) == NULL) {
709 res = MAILIMAP_ERROR_STREAM;
710 goto close;
711 }
712
713 r = parse_response(session, &response);
714 if (r != MAILIMAP_NO_ERROR) {
715 res = r;
716 goto close;
717 }
718
719 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
720
721 mailimap_response_free(response);
722
723 switch (error_code) {
724 case MAILIMAP_RESP_COND_STATE_OK:
725 if (session->imap_connection_info) {
726 mailimap_connection_info_free(session->imap_connection_info);
727 session->imap_connection_info = NULL;
728 }
729 res = MAILIMAP_NO_ERROR;
730 goto close;
731
732 default:
733 res = MAILIMAP_ERROR_LOGOUT;
734 goto close;
735 }
736
737 close:
738 mailstream_close(session->imap_stream);
739 session->imap_stream = NULL;
740 session->imap_state = MAILIMAP_STATE_DISCONNECTED;
741 return res;
742}
743
744/* send the results back to the caller */
745/* duplicate the result */
746
747static struct mailimap_capability *
748mailimap_capability_dup(struct mailimap_capability * orig_cap)
749{
750 struct mailimap_capability * cap;
751 char * auth_type;
752 char * name;
753
754 name = NULL;
755 auth_type = NULL;
756 switch (orig_cap->cap_type) {
757 case MAILIMAP_CAPABILITY_NAME:
758 name = strdup(orig_cap->cap_data.cap_name);
759 if (name == NULL)
760 goto err;
761 break;
762 case MAILIMAP_CAPABILITY_AUTH_TYPE:
763 auth_type = strdup(orig_cap->cap_data.cap_auth_type);
764 if (auth_type == NULL)
765 goto err;
766 break;
767 }
768
769 cap = mailimap_capability_new(orig_cap->cap_type, auth_type, name);
770 if (cap == NULL)
771 goto free;
772
773 return cap;
774
775 free:
776 if (name != NULL)
777 free(name);
778 if (auth_type != NULL)
779 free(auth_type);
780 err:
781 return NULL;
782}
783
784static struct mailimap_capability_data *
785mailimap_capability_data_dup(struct mailimap_capability_data * orig_cap_data)
786{
787 struct mailimap_capability_data * cap_data;
788 struct mailimap_capability * cap_dup;
789 clist * list;
790 clistiter * cur;
791 int r;
792
793 list = clist_new();
794 if (list == NULL)
795 goto err;
796
797 for(cur = clist_begin(orig_cap_data->cap_list) ;
798 cur != NULL ; cur = clist_next(cur)) {
799 struct mailimap_capability * cap;
800
801 cap = clist_content(cur);
802
803 cap_dup = mailimap_capability_dup(cap);
804 if (cap_dup == NULL)
805 goto list;
806
807 r = clist_append(list, cap_dup);
808 if (r < 0) {
809 mailimap_capability_free(cap_dup);
810 goto list;
811 }
812 }
813
814 cap_data = mailimap_capability_data_new(list);
815 if (cap_data == NULL)
816 goto list;
817
818 return cap_data;
819
820list:
821 clist_foreach(list, (clist_func) mailimap_capability_free, NULL);
822 clist_free(list);
823err:
824 return NULL;
825}
826
827int mailimap_capability(mailimap * session,
828 struct mailimap_capability_data ** result)
829{
830 struct mailimap_response * response;
831 int r;
832 int error_code;
833 struct mailimap_capability_data * cap_data;
834
835 r = send_current_tag(session);
836 if (r != MAILIMAP_NO_ERROR)
837 return r;
838
839 r = mailimap_capability_send(session->imap_stream);
840 if (r != MAILIMAP_NO_ERROR)
841 return r;
842
843 r = mailimap_crlf_send(session->imap_stream);
844 if (r != MAILIMAP_NO_ERROR)
845 return r;
846
847 if (mailstream_flush(session->imap_stream) == -1)
848 return MAILIMAP_ERROR_STREAM;
849
850 if (read_line(session) == NULL)
851 return MAILIMAP_ERROR_STREAM;
852
853 r = parse_response(session, &response);
854 if (r != MAILIMAP_NO_ERROR)
855 return r;
856
857 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
858
859 mailimap_response_free(response);
860
861 switch (error_code) {
862 case MAILIMAP_RESP_COND_STATE_OK:
863 cap_data =
864 mailimap_capability_data_dup(session->imap_connection_info->imap_capability);
865 if (cap_data == NULL)
866 return MAILIMAP_ERROR_MEMORY;
867
868 * result = cap_data;
869
870 return MAILIMAP_NO_ERROR;
871
872 default:
873 return MAILIMAP_ERROR_CAPABILITY;
874 }
875}
876
877int mailimap_check(mailimap * session)
878{
879 struct mailimap_response * response;
880 int r;
881 int error_code;
882
883 if (session->imap_state != MAILIMAP_STATE_SELECTED)
884 return MAILIMAP_ERROR_BAD_STATE;
885
886 r = send_current_tag(session);
887 if (r != MAILIMAP_NO_ERROR)
888 return r;
889
890 r = mailimap_check_send(session->imap_stream);
891 if (r != MAILIMAP_NO_ERROR)
892 return r;
893
894 r = mailimap_crlf_send(session->imap_stream);
895 if (r != MAILIMAP_NO_ERROR)
896 return r;
897
898 if (mailstream_flush(session->imap_stream) == -1)
899 return MAILIMAP_ERROR_STREAM;
900
901 if (read_line(session) == NULL)
902 return MAILIMAP_ERROR_STREAM;
903
904 r = parse_response(session, &response);
905 if (r != MAILIMAP_NO_ERROR)
906 return r;
907
908 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
909
910 mailimap_response_free(response);
911
912 switch (error_code) {
913 case MAILIMAP_RESP_COND_STATE_OK:
914 return MAILIMAP_NO_ERROR;
915
916 default:
917 return MAILIMAP_ERROR_CHECK;
918 }
919}
920
921int mailimap_close(mailimap * session)
922{
923 struct mailimap_response * response;
924 int r;
925 int error_code;
926
927 if (session->imap_state != MAILIMAP_STATE_SELECTED)
928 return MAILIMAP_ERROR_BAD_STATE;
929
930 r = send_current_tag(session);
931 if (r != MAILIMAP_NO_ERROR)
932 return r;
933
934 r = mailimap_close_send(session->imap_stream);
935 if (r != MAILIMAP_NO_ERROR)
936 return r;
937
938 r = mailimap_crlf_send(session->imap_stream);
939 if (r != MAILIMAP_NO_ERROR)
940 return r;
941
942 if (mailstream_flush(session->imap_stream) == -1)
943 return MAILIMAP_ERROR_STREAM;
944
945 if (read_line(session) == NULL)
946 return MAILIMAP_ERROR_STREAM;
947
948 r = parse_response(session, &response);
949 if (r != MAILIMAP_NO_ERROR)
950 return r;
951
952 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
953
954 mailimap_response_free(response);
955
956 switch (error_code) {
957 case MAILIMAP_RESP_COND_STATE_OK:
958 /* leave selected state */
959 mailimap_selection_info_free(session->imap_selection_info);
960 session->imap_selection_info = NULL;
961
962 session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
963 return MAILIMAP_NO_ERROR;
964
965 default:
966 return MAILIMAP_ERROR_CLOSE;
967 }
968}
969
970int mailimap_expunge(mailimap * session)
971{
972 struct mailimap_response * response;
973 int r;
974 int error_code;
975
976 if (session->imap_state != MAILIMAP_STATE_SELECTED)
977 return MAILIMAP_ERROR_BAD_STATE;
978
979 r = send_current_tag(session);
980 if (r != MAILIMAP_NO_ERROR)
981 return r;
982
983 r = mailimap_expunge_send(session->imap_stream);
984 if (r != MAILIMAP_NO_ERROR)
985 return r;
986
987 r = mailimap_crlf_send(session->imap_stream);
988 if (r != MAILIMAP_NO_ERROR)
989 return r;
990
991 if (mailstream_flush(session->imap_stream) == -1)
992 return MAILIMAP_ERROR_STREAM;
993
994 if (read_line(session) == NULL)
995 return MAILIMAP_ERROR_STREAM;
996
997 r = parse_response(session, &response);
998 if (r != MAILIMAP_NO_ERROR)
999 return r;
1000
1001 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1002
1003 mailimap_response_free(response);
1004
1005 switch (error_code) {
1006 case MAILIMAP_RESP_COND_STATE_OK:
1007 return MAILIMAP_NO_ERROR;
1008
1009 default:
1010 return MAILIMAP_ERROR_EXPUNGE;
1011 }
1012}
1013
1014int mailimap_copy(mailimap * session, struct mailimap_set * set,
1015 const char * mb)
1016{
1017 struct mailimap_response * response;
1018 int r;
1019 int error_code;
1020
1021 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1022 return MAILIMAP_ERROR_BAD_STATE;
1023
1024 r = send_current_tag(session);
1025 if (r != MAILIMAP_NO_ERROR)
1026 return r;
1027
1028 r = mailimap_copy_send(session->imap_stream, set, mb);
1029 if (r != MAILIMAP_NO_ERROR)
1030 return r;
1031
1032 r = mailimap_crlf_send(session->imap_stream);
1033 if (r != MAILIMAP_NO_ERROR)
1034 return r;
1035
1036 if (mailstream_flush(session->imap_stream) == -1)
1037 return MAILIMAP_ERROR_STREAM;
1038
1039 if (read_line(session) == NULL)
1040 return MAILIMAP_ERROR_STREAM;
1041
1042 r = parse_response(session, &response);
1043 if (r != MAILIMAP_NO_ERROR)
1044 return r;
1045
1046 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1047
1048 mailimap_response_free(response);
1049
1050 switch (error_code) {
1051 case MAILIMAP_RESP_COND_STATE_OK:
1052 return MAILIMAP_NO_ERROR;
1053
1054 default:
1055 return MAILIMAP_ERROR_COPY;
1056 }
1057}
1058
1059int mailimap_uid_copy(mailimap * session, struct mailimap_set * set,
1060 const char * mb)
1061{
1062 struct mailimap_response * response;
1063 int r;
1064 int error_code;
1065
1066 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1067 return MAILIMAP_ERROR_BAD_STATE;
1068
1069 r = send_current_tag(session);
1070 if (r != MAILIMAP_NO_ERROR)
1071 return r;
1072
1073 r = mailimap_uid_copy_send(session->imap_stream, set, mb);
1074 if (r != MAILIMAP_NO_ERROR)
1075 return r;
1076
1077 r = mailimap_crlf_send(session->imap_stream);
1078 if (r != MAILIMAP_NO_ERROR)
1079 return r;
1080
1081 if (mailstream_flush(session->imap_stream) == -1)
1082 return MAILIMAP_ERROR_STREAM;
1083
1084 if (read_line(session) == NULL)
1085 return MAILIMAP_ERROR_STREAM;
1086
1087 r = parse_response(session, &response);
1088 if (r != MAILIMAP_NO_ERROR)
1089 return r;
1090
1091 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1092
1093 mailimap_response_free(response);
1094
1095 switch (error_code) {
1096 case MAILIMAP_RESP_COND_STATE_OK:
1097 return MAILIMAP_NO_ERROR;
1098
1099 default:
1100 return MAILIMAP_ERROR_UID_COPY;
1101 }
1102}
1103
1104int mailimap_create(mailimap * session, const char * mb)
1105{
1106 struct mailimap_response * response;
1107 int r;
1108 int error_code;
1109
1110 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1111 (session->imap_state != MAILIMAP_STATE_SELECTED))
1112 return MAILIMAP_ERROR_BAD_STATE;
1113
1114 r = send_current_tag(session);
1115 if (r != MAILIMAP_NO_ERROR)
1116 return r;
1117
1118 r = mailimap_create_send(session->imap_stream, mb);
1119 if (r != MAILIMAP_NO_ERROR)
1120 return r;
1121
1122 r = mailimap_crlf_send(session->imap_stream);
1123 if (r != MAILIMAP_NO_ERROR)
1124 return r;
1125
1126 if (mailstream_flush(session->imap_stream) == -1)
1127 return MAILIMAP_ERROR_STREAM;
1128
1129 if (read_line(session) == NULL)
1130 return MAILIMAP_ERROR_STREAM;
1131
1132 r = parse_response(session, &response);
1133 if (r != MAILIMAP_NO_ERROR)
1134 return r;
1135
1136 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1137
1138 mailimap_response_free(response);
1139
1140 switch (error_code) {
1141 case MAILIMAP_RESP_COND_STATE_OK:
1142 return MAILIMAP_NO_ERROR;
1143
1144 default:
1145 return MAILIMAP_ERROR_CREATE;
1146 }
1147}
1148
1149
1150int mailimap_delete(mailimap * session, const char * mb)
1151{
1152 struct mailimap_response * response;
1153 int r;
1154 int error_code;
1155
1156 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1157 (session->imap_state != MAILIMAP_STATE_SELECTED))
1158 return MAILIMAP_ERROR_BAD_STATE;
1159
1160 r = send_current_tag(session);
1161 if (r != MAILIMAP_NO_ERROR)
1162 return r;
1163
1164 r = mailimap_delete_send(session->imap_stream, mb);
1165 if (r != MAILIMAP_NO_ERROR)
1166 return r;
1167
1168 r = mailimap_crlf_send(session->imap_stream);
1169 if (r != MAILIMAP_NO_ERROR)
1170 return r;
1171
1172 if (mailstream_flush(session->imap_stream) == -1)
1173 return MAILIMAP_ERROR_STREAM;
1174
1175 if (read_line(session) == NULL)
1176 return MAILIMAP_ERROR_STREAM;
1177
1178 r = parse_response(session, &response);
1179 if (r != MAILIMAP_NO_ERROR)
1180 return r;
1181
1182 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1183
1184 mailimap_response_free(response);
1185
1186 switch (error_code) {
1187 case MAILIMAP_RESP_COND_STATE_OK:
1188 return MAILIMAP_NO_ERROR;
1189
1190 default:
1191 return MAILIMAP_ERROR_DELETE;
1192 }
1193}
1194
1195int mailimap_examine(mailimap * session, const char * mb)
1196{
1197 struct mailimap_response * response;
1198 int r;
1199 int error_code;
1200
1201 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1202 (session->imap_state != MAILIMAP_STATE_SELECTED))
1203 return MAILIMAP_ERROR_BAD_STATE;
1204
1205 r = send_current_tag(session);
1206 if (r != MAILIMAP_NO_ERROR)
1207 return r;
1208
1209 r = mailimap_examine_send(session->imap_stream, mb);
1210 if (r != MAILIMAP_NO_ERROR)
1211 return r;
1212
1213 r = mailimap_crlf_send(session->imap_stream);
1214 if (r != MAILIMAP_NO_ERROR)
1215 return r;
1216
1217 if (mailstream_flush(session->imap_stream) == -1)
1218 return MAILIMAP_ERROR_STREAM;
1219
1220 if (read_line(session) == NULL)
1221 return MAILIMAP_ERROR_STREAM;
1222
1223 if (session->imap_selection_info != NULL)
1224 mailimap_selection_info_free(session->imap_selection_info);
1225 session->imap_selection_info = mailimap_selection_info_new();
1226
1227 r = parse_response(session, &response);
1228 if (r != MAILIMAP_NO_ERROR)
1229 return r;
1230
1231 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1232
1233 mailimap_response_free(response);
1234
1235 switch (error_code) {
1236 case MAILIMAP_RESP_COND_STATE_OK:
1237 session->imap_state = MAILIMAP_STATE_SELECTED;
1238 return MAILIMAP_NO_ERROR;
1239
1240 default:
1241 mailimap_selection_info_free(session->imap_selection_info);
1242 session->imap_selection_info = NULL;
1243 session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
1244 return MAILIMAP_ERROR_EXAMINE;
1245 }
1246}
1247
1248int
1249mailimap_fetch(mailimap * session, struct mailimap_set * set,
1250 struct mailimap_fetch_type * fetch_type, clist ** result)
1251{
1252 struct mailimap_response * response;
1253 int r;
1254 int error_code;
1255
1256 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1257 return MAILIMAP_ERROR_BAD_STATE;
1258
1259 r = send_current_tag(session);
1260 if (r != MAILIMAP_NO_ERROR)
1261 return r;
1262
1263 r = mailimap_fetch_send(session->imap_stream, set, fetch_type);
1264 if (r != MAILIMAP_NO_ERROR)
1265 return r;
1266
1267 r = mailimap_crlf_send(session->imap_stream);
1268 if (r != MAILIMAP_NO_ERROR)
1269 return r;
1270
1271 if (mailstream_flush(session->imap_stream) == -1)
1272 return MAILIMAP_ERROR_STREAM;
1273
1274 if (read_line(session) == NULL)
1275 return MAILIMAP_ERROR_STREAM;
1276
1277 r = parse_response(session, &response);
1278 if (r != MAILIMAP_NO_ERROR)
1279 return r;
1280
1281 * result = session->imap_response_info->rsp_fetch_list;
1282 session->imap_response_info->rsp_fetch_list = NULL;
1283
1284 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1285
1286 mailimap_response_free(response);
1287
1288 switch (error_code) {
1289 case MAILIMAP_RESP_COND_STATE_OK:
1290 return MAILIMAP_NO_ERROR;
1291
1292 default:
1293 return MAILIMAP_ERROR_FETCH;
1294 }
1295}
1296
1297void mailimap_fetch_list_free(clist * fetch_list)
1298{
1299 clist_foreach(fetch_list, (clist_func) mailimap_msg_att_free, NULL);
1300 clist_free(fetch_list);
1301}
1302
1303int
1304mailimap_uid_fetch(mailimap * session,
1305 struct mailimap_set * set,
1306 struct mailimap_fetch_type * fetch_type, clist ** result)
1307{
1308 struct mailimap_response * response;
1309 int r;
1310 int error_code;
1311
1312 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1313 return MAILIMAP_ERROR_BAD_STATE;
1314
1315 r = send_current_tag(session);
1316 if (r != MAILIMAP_NO_ERROR)
1317 return r;
1318
1319 r = mailimap_uid_fetch_send(session->imap_stream, set, fetch_type);
1320 if (r != MAILIMAP_NO_ERROR)
1321 return r;
1322
1323 r = mailimap_crlf_send(session->imap_stream);
1324 if (r != MAILIMAP_NO_ERROR)
1325 return r;
1326
1327 if (mailstream_flush(session->imap_stream) == -1)
1328 return MAILIMAP_ERROR_STREAM;
1329
1330 if (read_line(session) == NULL)
1331 return MAILIMAP_ERROR_STREAM;
1332
1333 r = parse_response(session, &response);
1334
1335 if (r != MAILIMAP_NO_ERROR)
1336 return r;
1337
1338 * result = session->imap_response_info->rsp_fetch_list;
1339 session->imap_response_info->rsp_fetch_list = NULL;
1340
1341 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1342
1343 mailimap_response_free(response);
1344
1345 switch (error_code) {
1346 case MAILIMAP_RESP_COND_STATE_OK:
1347 return MAILIMAP_NO_ERROR;
1348
1349 default:
1350 return MAILIMAP_ERROR_UID_FETCH;
1351 }
1352}
1353
1354int mailimap_list(mailimap * session, const char * mb,
1355 const char * list_mb, clist ** result)
1356{
1357 struct mailimap_response * response;
1358 int r;
1359 int error_code;
1360
1361 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1362 (session->imap_state != MAILIMAP_STATE_SELECTED))
1363 return MAILIMAP_ERROR_BAD_STATE;
1364
1365 r = send_current_tag(session);
1366 if (r != MAILIMAP_NO_ERROR)
1367 return r;
1368
1369 r = mailimap_list_send(session->imap_stream, mb, list_mb);
1370 if (r != MAILIMAP_NO_ERROR)
1371 return r;
1372
1373 r = mailimap_crlf_send(session->imap_stream);
1374 if (r != MAILIMAP_NO_ERROR)
1375 return r;
1376
1377 if (mailstream_flush(session->imap_stream) == -1)
1378 return MAILIMAP_ERROR_STREAM;
1379
1380 if (read_line(session) == NULL)
1381 return MAILIMAP_ERROR_STREAM;
1382
1383 r = parse_response(session, &response);
1384 if (r != MAILIMAP_NO_ERROR)
1385 return r;
1386
1387 * result = session->imap_response_info->rsp_mailbox_list;
1388 session->imap_response_info->rsp_mailbox_list = NULL;
1389
1390 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1391
1392 mailimap_response_free(response);
1393
1394 switch (error_code) {
1395 case MAILIMAP_RESP_COND_STATE_OK:
1396 return MAILIMAP_NO_ERROR;
1397
1398 default:
1399 return MAILIMAP_ERROR_LIST;
1400 }
1401}
1402
1403int mailimap_login(mailimap * session,
1404 const char * userid, const char * password)
1405{
1406 struct mailimap_response * response;
1407 int r;
1408 int error_code;
1409
1410 if (session->imap_state != MAILIMAP_STATE_NON_AUTHENTICATED)
1411 return MAILIMAP_ERROR_BAD_STATE;
1412
1413 r = send_current_tag(session);
1414 if (r != MAILIMAP_NO_ERROR)
1415 return r;
1416
1417 r = mailimap_login_send(session->imap_stream, userid, password);
1418 if (r != MAILIMAP_NO_ERROR)
1419 return r;
1420
1421 r = mailimap_crlf_send(session->imap_stream);
1422 if (r != MAILIMAP_NO_ERROR)
1423 return r;
1424
1425 if (mailstream_flush(session->imap_stream) == -1)
1426 return MAILIMAP_ERROR_STREAM;
1427
1428 if (read_line(session) == NULL)
1429 return MAILIMAP_ERROR_STREAM;
1430
1431 r = parse_response(session, &response);
1432 if (r != MAILIMAP_NO_ERROR)
1433 return r;
1434
1435 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1436
1437 mailimap_response_free(response);
1438
1439 switch (error_code) {
1440 case MAILIMAP_RESP_COND_STATE_OK:
1441 session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
1442 return MAILIMAP_NO_ERROR;
1443
1444 default:
1445 return MAILIMAP_ERROR_LOGIN;
1446 }
1447}
1448
1449int mailimap_lsub(mailimap * session, const char * mb,
1450 const char * list_mb, clist ** result)
1451{
1452 struct mailimap_response * response;
1453 int r;
1454 int error_code;
1455
1456 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1457 (session->imap_state != MAILIMAP_STATE_SELECTED))
1458 return MAILIMAP_ERROR_BAD_STATE;
1459
1460 r = send_current_tag(session);
1461 if (r != MAILIMAP_NO_ERROR)
1462 return r;
1463
1464 r = mailimap_lsub_send(session->imap_stream, mb, list_mb);
1465 if (r != MAILIMAP_NO_ERROR)
1466 return r;
1467
1468 r = mailimap_crlf_send(session->imap_stream);
1469 if (r != MAILIMAP_NO_ERROR)
1470 return r;
1471
1472 if (mailstream_flush(session->imap_stream) == -1)
1473 return MAILIMAP_ERROR_STREAM;
1474
1475 if (read_line(session) == NULL)
1476 return MAILIMAP_ERROR_STREAM;
1477
1478 r = parse_response(session, &response);
1479 if (r != MAILIMAP_NO_ERROR)
1480 return r;
1481
1482 * result = session->imap_response_info->rsp_mailbox_lsub;
1483 session->imap_response_info->rsp_mailbox_lsub = NULL;
1484
1485 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1486
1487 mailimap_response_free(response);
1488
1489 switch (error_code) {
1490 case MAILIMAP_RESP_COND_STATE_OK:
1491 return MAILIMAP_NO_ERROR;
1492
1493 default:
1494 return MAILIMAP_ERROR_LSUB;
1495 }
1496}
1497
1498void mailimap_list_result_free(clist * list)
1499{
1500 clist_foreach(list, (clist_func) mailimap_mailbox_list_free, NULL);
1501 clist_free(list);
1502}
1503
1504int mailimap_rename(mailimap * session,
1505 const char * mb, const char * new_name)
1506{
1507 struct mailimap_response * response;
1508 int r;
1509 int error_code;
1510
1511 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1512 (session->imap_state != MAILIMAP_STATE_SELECTED))
1513 return MAILIMAP_ERROR_BAD_STATE;
1514
1515 r = send_current_tag(session);
1516 if (r != MAILIMAP_NO_ERROR)
1517 return r;
1518
1519 r = mailimap_rename_send(session->imap_stream, mb, new_name);
1520 if (r != MAILIMAP_NO_ERROR)
1521 return r;
1522
1523 if (!mailimap_crlf_send(session->imap_stream))
1524 if (r != MAILIMAP_NO_ERROR)
1525 return r;
1526
1527 if (mailstream_flush(session->imap_stream) == -1)
1528 return MAILIMAP_ERROR_STREAM;
1529
1530 if (read_line(session) == NULL)
1531 return MAILIMAP_ERROR_STREAM;
1532
1533 r = parse_response(session, &response);
1534 if (r != MAILIMAP_NO_ERROR)
1535 return r;
1536
1537 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1538
1539 mailimap_response_free(response);
1540
1541 switch (error_code) {
1542 case MAILIMAP_RESP_COND_STATE_OK:
1543 return MAILIMAP_NO_ERROR;
1544
1545 default:
1546 return MAILIMAP_ERROR_RENAME;
1547 }
1548}
1549
1550int
1551mailimap_search(mailimap * session, const char * charset,
1552 struct mailimap_search_key * key, clist ** result)
1553{
1554 struct mailimap_response * response;
1555 int r;
1556 int error_code;
1557
1558 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1559 return MAILIMAP_ERROR_BAD_STATE;
1560
1561 r = send_current_tag(session);
1562 if (r != MAILIMAP_NO_ERROR)
1563 return r;
1564
1565 r = mailimap_search_send(session->imap_stream, charset, key);
1566 if (r != MAILIMAP_NO_ERROR)
1567 return r;
1568
1569 r = mailimap_crlf_send(session->imap_stream);
1570 if (r != MAILIMAP_NO_ERROR)
1571 return r;
1572
1573 if (mailstream_flush(session->imap_stream) == -1)
1574 return MAILIMAP_ERROR_STREAM;
1575
1576 if (read_line(session) == NULL)
1577 return MAILIMAP_ERROR_STREAM;
1578
1579 r = parse_response(session, &response);
1580 if (r != MAILIMAP_NO_ERROR)
1581 return r;
1582
1583 * result = session->imap_response_info->rsp_search_result;
1584 session->imap_response_info->rsp_search_result = NULL;
1585
1586 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1587
1588 mailimap_response_free(response);
1589
1590 switch (error_code) {
1591 case MAILIMAP_RESP_COND_STATE_OK:
1592 return MAILIMAP_NO_ERROR;
1593
1594 default:
1595 return MAILIMAP_ERROR_SEARCH;
1596 }
1597}
1598
1599int
1600mailimap_uid_search(mailimap * session, const char * charset,
1601 struct mailimap_search_key * key, clist ** result)
1602{
1603 struct mailimap_response * response;
1604 int r;
1605 int error_code;
1606
1607 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1608 return MAILIMAP_ERROR_BAD_STATE;
1609
1610 r = send_current_tag(session);
1611 if (r != MAILIMAP_NO_ERROR)
1612 return r;
1613
1614 r = mailimap_uid_search_send(session->imap_stream, charset, key);
1615 if (r != MAILIMAP_NO_ERROR)
1616 return r;
1617
1618 r = mailimap_crlf_send(session->imap_stream);
1619 if (r != MAILIMAP_NO_ERROR)
1620 return r;
1621
1622 if (mailstream_flush(session->imap_stream) == -1)
1623 return MAILIMAP_ERROR_STREAM;
1624
1625 if (read_line(session) == NULL)
1626 return MAILIMAP_ERROR_STREAM;
1627
1628 r = parse_response(session, &response);
1629 if (r != MAILIMAP_NO_ERROR)
1630 return r;
1631
1632 * result = session->imap_response_info->rsp_search_result;
1633 session->imap_response_info->rsp_search_result = NULL;
1634
1635 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1636
1637 mailimap_response_free(response);
1638
1639 switch (error_code) {
1640 case MAILIMAP_RESP_COND_STATE_OK:
1641 return MAILIMAP_NO_ERROR;
1642
1643 default:
1644 return MAILIMAP_ERROR_UID_SEARCH;
1645 }
1646}
1647
1648void mailimap_search_result_free(clist * search_result)
1649{
1650 clist_foreach(search_result, (clist_func) free, NULL);
1651 clist_free(search_result);
1652}
1653
1654int
1655mailimap_select(mailimap * session, const char * mb)
1656{
1657 struct mailimap_response * response;
1658 int r;
1659 int error_code;
1660
1661 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1662 (session->imap_state != MAILIMAP_STATE_SELECTED))
1663 return MAILIMAP_ERROR_BAD_STATE;
1664
1665 r = send_current_tag(session);
1666 if (r != MAILIMAP_NO_ERROR)
1667 return r;
1668
1669 r = mailimap_select_send(session->imap_stream, mb);
1670 if (r != MAILIMAP_NO_ERROR)
1671 return r;
1672
1673 r = mailimap_crlf_send(session->imap_stream);
1674 if (r != MAILIMAP_NO_ERROR)
1675 return r;
1676
1677 if (mailstream_flush(session->imap_stream) == -1)
1678 return MAILIMAP_ERROR_STREAM;
1679
1680 if (read_line(session) == NULL)
1681 return MAILIMAP_ERROR_STREAM;
1682
1683 if (session->imap_selection_info != NULL)
1684 mailimap_selection_info_free(session->imap_selection_info);
1685 session->imap_selection_info = mailimap_selection_info_new();
1686
1687 r = parse_response(session, &response);
1688 if (r != MAILIMAP_NO_ERROR)
1689 return r;
1690
1691 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1692
1693 mailimap_response_free(response);
1694
1695 switch (error_code) {
1696 case MAILIMAP_RESP_COND_STATE_OK:
1697 session->imap_state = MAILIMAP_STATE_SELECTED;
1698 return MAILIMAP_NO_ERROR;
1699
1700 default:
1701 mailimap_selection_info_free(session->imap_selection_info);
1702 session->imap_selection_info = NULL;
1703 session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
1704 return MAILIMAP_ERROR_SELECT;
1705 }
1706}
1707
1708int
1709mailimap_status(mailimap * session, const char * mb,
1710 struct mailimap_status_att_list * status_att_list,
1711 struct mailimap_mailbox_data_status ** result)
1712{
1713 struct mailimap_response * response;
1714 int r;
1715 int error_code;
1716
1717 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1718 (session->imap_state != MAILIMAP_STATE_SELECTED))
1719 return MAILIMAP_ERROR_BAD_STATE;
1720
1721 r = send_current_tag(session);
1722 if (r != MAILIMAP_NO_ERROR)
1723 return r;
1724
1725 r = mailimap_status_send(session->imap_stream, mb, status_att_list);
1726 if (r != MAILIMAP_NO_ERROR)
1727 return r;
1728
1729 r = mailimap_crlf_send(session->imap_stream);
1730 if (r != MAILIMAP_NO_ERROR)
1731 return r;
1732
1733 if (mailstream_flush(session->imap_stream) == -1)
1734 return MAILIMAP_ERROR_STREAM;
1735
1736 if (read_line(session) == NULL)
1737 return MAILIMAP_ERROR_STREAM;
1738
1739 r = parse_response(session, &response);
1740 if (r != MAILIMAP_NO_ERROR)
1741 return r;
1742
1743 * result = session->imap_response_info->rsp_status;
1744 session->imap_response_info->rsp_status = NULL;
1745
1746 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1747
1748 mailimap_response_free(response);
1749
1750 switch (error_code) {
1751 case MAILIMAP_RESP_COND_STATE_OK:
1752 return MAILIMAP_NO_ERROR;
1753
1754 default:
1755 return MAILIMAP_ERROR_STATUS;
1756 }
1757}
1758
1759
1760int
1761mailimap_store(mailimap * session,
1762 struct mailimap_set * set,
1763 struct mailimap_store_att_flags * store_att_flags)
1764{
1765 struct mailimap_response * response;
1766 int r;
1767 int error_code;
1768
1769 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1770 return MAILIMAP_ERROR_BAD_STATE;
1771
1772 r = send_current_tag(session);
1773 if (r != MAILIMAP_NO_ERROR)
1774 return r;
1775
1776 r = mailimap_store_send(session->imap_stream, set, store_att_flags);
1777 if (r != MAILIMAP_NO_ERROR)
1778 return r;
1779
1780 r = mailimap_crlf_send(session->imap_stream);
1781 if (r != MAILIMAP_NO_ERROR)
1782 return r;
1783
1784 if (mailstream_flush(session->imap_stream) == -1)
1785 return MAILIMAP_ERROR_STREAM;
1786
1787 if (read_line(session) == NULL)
1788 return MAILIMAP_ERROR_STREAM;
1789
1790 r = parse_response(session, &response);
1791 if (r != MAILIMAP_NO_ERROR)
1792 return r;
1793
1794 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1795
1796 mailimap_response_free(response);
1797
1798 switch (error_code) {
1799 case MAILIMAP_RESP_COND_STATE_OK:
1800 return MAILIMAP_NO_ERROR;
1801
1802 default:
1803 return MAILIMAP_ERROR_STORE;
1804 }
1805}
1806
1807int
1808mailimap_uid_store(mailimap * session,
1809 struct mailimap_set * set,
1810 struct mailimap_store_att_flags * store_att_flags)
1811{
1812 struct mailimap_response * response;
1813 int r;
1814 int error_code;
1815
1816 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1817 return MAILIMAP_ERROR_BAD_STATE;
1818
1819 r = send_current_tag(session);
1820 if (r != MAILIMAP_NO_ERROR)
1821 return r;
1822
1823 r = mailimap_uid_store_send(session->imap_stream, set, store_att_flags);
1824 if (r != MAILIMAP_NO_ERROR)
1825 return r;
1826
1827 r = mailimap_crlf_send(session->imap_stream);
1828 if (r != MAILIMAP_NO_ERROR)
1829 return r;
1830
1831 if (mailstream_flush(session->imap_stream) == -1)
1832 return MAILIMAP_ERROR_STREAM;
1833
1834 if (read_line(session) == NULL)
1835 return MAILIMAP_ERROR_STREAM;
1836
1837 r = parse_response(session, &response);
1838 if (r != MAILIMAP_NO_ERROR)
1839 return r;
1840
1841 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1842
1843 mailimap_response_free(response);
1844
1845 switch (error_code) {
1846 case MAILIMAP_RESP_COND_STATE_OK:
1847 return MAILIMAP_NO_ERROR;
1848
1849 default:
1850 return MAILIMAP_ERROR_UID_STORE;
1851 }
1852}
1853
1854int mailimap_subscribe(mailimap * session, const char * mb)
1855{
1856 struct mailimap_response * response;
1857 int r;
1858 int error_code;
1859
1860 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1861 (session->imap_state != MAILIMAP_STATE_SELECTED))
1862 return MAILIMAP_ERROR_BAD_STATE;
1863
1864 r = send_current_tag(session);
1865 if (r != MAILIMAP_NO_ERROR)
1866 return r;
1867
1868 r = mailimap_subscribe_send(session->imap_stream, mb);
1869 if (r != MAILIMAP_NO_ERROR)
1870 return r;
1871
1872 r = mailimap_crlf_send(session->imap_stream);
1873 if (r != MAILIMAP_NO_ERROR)
1874 return r;
1875
1876 if (mailstream_flush(session->imap_stream) == -1)
1877 return MAILIMAP_ERROR_STREAM;
1878
1879 if (read_line(session) == NULL)
1880 return MAILIMAP_ERROR_STREAM;
1881
1882 r = parse_response(session, &response);
1883 if (r != MAILIMAP_NO_ERROR)
1884 return r;
1885
1886 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1887
1888 mailimap_response_free(response);
1889
1890 switch (error_code) {
1891 case MAILIMAP_RESP_COND_STATE_OK:
1892 return MAILIMAP_NO_ERROR;
1893
1894 default:
1895 return MAILIMAP_ERROR_SUBSCRIBE;
1896 }
1897}
1898
1899int mailimap_unsubscribe(mailimap * session, const char * mb)
1900{
1901 struct mailimap_response * response;
1902 int r;
1903 int error_code;
1904
1905 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1906 (session->imap_state != MAILIMAP_STATE_SELECTED))
1907 return MAILIMAP_ERROR_BAD_STATE;
1908
1909 r = send_current_tag(session);
1910 if (r != MAILIMAP_NO_ERROR)
1911 return r;
1912
1913 r = mailimap_unsubscribe_send(session->imap_stream, mb);
1914 if (r != MAILIMAP_NO_ERROR)
1915 return r;
1916
1917 r = mailimap_crlf_send(session->imap_stream);
1918 if (r != MAILIMAP_NO_ERROR)
1919 return r;
1920
1921 if (mailstream_flush(session->imap_stream) == -1)
1922 return MAILIMAP_ERROR_STREAM;
1923
1924 if (read_line(session) == NULL)
1925 return MAILIMAP_ERROR_STREAM;
1926
1927 r = parse_response(session, &response);
1928 if (r != MAILIMAP_NO_ERROR)
1929 return r;
1930
1931 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1932
1933 mailimap_response_free(response);
1934
1935 switch (error_code) {
1936 case MAILIMAP_RESP_COND_STATE_OK:
1937 return MAILIMAP_NO_ERROR;
1938
1939 default:
1940 return MAILIMAP_ERROR_UNSUBSCRIBE;
1941 }
1942}
1943
1944
1945int mailimap_starttls(mailimap * session)
1946{
1947 struct mailimap_response * response;
1948 int r;
1949 int error_code;
1950
1951 r = send_current_tag(session);
1952 if (r != MAILIMAP_NO_ERROR)
1953 return r;
1954
1955 r = mailimap_starttls_send(session->imap_stream);
1956 if (r != MAILIMAP_NO_ERROR)
1957 return r;
1958
1959 r = mailimap_crlf_send(session->imap_stream);
1960 if (r != MAILIMAP_NO_ERROR)
1961 return r;
1962
1963 if (mailstream_flush(session->imap_stream) == -1)
1964 return MAILIMAP_ERROR_STREAM;
1965
1966 if (read_line(session) == NULL)
1967 return MAILIMAP_ERROR_STREAM;
1968
1969 r = parse_response(session, &response);
1970 if (r != MAILIMAP_NO_ERROR)
1971 return r;
1972
1973 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1974
1975 mailimap_response_free(response);
1976
1977 switch (error_code) {
1978 case MAILIMAP_RESP_COND_STATE_OK:
1979 return MAILIMAP_NO_ERROR;
1980
1981 default:
1982 return MAILIMAP_ERROR_STARTTLS;
1983 }
1984}
1985
1986
1987
1988static char * read_line(mailimap * session)
1989{
1990 return mailstream_read_line(session->imap_stream, session->imap_stream_buffer);
1991}
1992
1993static int send_current_tag(mailimap * session)
1994{
1995 char tag_str[15];
1996 int r;
1997
1998 session->imap_tag ++;
1999 snprintf(tag_str, 15, "%i", session->imap_tag);
2000
2001 r = mailimap_tag_send(session->imap_stream, tag_str);
2002 if (r != MAILIMAP_NO_ERROR)
2003 return r;
2004
2005 r = mailimap_space_send(session->imap_stream);
2006 if (r != MAILIMAP_NO_ERROR)
2007 return r;
2008
2009 return MAILIMAP_NO_ERROR;
2010}
2011
2012static int parse_response(mailimap * session,
2013 struct mailimap_response ** result)
2014{
2015 size_t index;
2016 struct mailimap_response * response;
2017 char tag_str[15];
2018 int r;
2019
2020 index = 0;
2021
2022 session->imap_response = NULL;
2023
2024 r = mailimap_response_parse(session->imap_stream,
2025 session->imap_stream_buffer,
2026 &index, &response,
2027 session->imap_progr_rate, session->imap_progr_fun);
2028 if (r != MAILIMAP_NO_ERROR)
2029 return r;
2030
2031#if 0
2032 mailimap_response_print(response);
2033#endif
2034
2035 response_store(session, response);
2036
2037 if (mmap_string_assign(session->imap_response_buffer,
2038 response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_text->rsp_text)
2039 == NULL)
2040 return MAILIMAP_ERROR_MEMORY;
2041
2042 session->imap_response = session->imap_response_buffer->str;
2043
2044 if (response->rsp_resp_done->rsp_type == MAILIMAP_RESP_DONE_TYPE_FATAL)
2045 return MAILIMAP_ERROR_FATAL;
2046
2047 snprintf(tag_str, 15, "%i", session->imap_tag);
2048 if (strcmp(response->rsp_resp_done->rsp_data.rsp_tagged->rsp_tag, tag_str) != 0)
2049 return MAILIMAP_ERROR_PROTOCOL;
2050
2051 if (response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type ==
2052 MAILIMAP_RESP_COND_STATE_BAD)
2053 return MAILIMAP_ERROR_PROTOCOL;
2054
2055 * result = response;
2056
2057 return MAILIMAP_NO_ERROR;
2058}
2059
2060
2061static int parse_greeting(mailimap * session,
2062 struct mailimap_greeting ** result)
2063{
2064 size_t index;
2065 struct mailimap_greeting * greeting;
2066 int r;
2067
2068 index = 0;
2069
2070 session->imap_response = NULL;
2071
2072 r = mailimap_greeting_parse(session->imap_stream,
2073 session->imap_stream_buffer,
2074 &index, &greeting, session->imap_progr_rate,
2075 session->imap_progr_fun);
2076 if (r != MAILIMAP_NO_ERROR)
2077 return r;
2078
2079#if 0
2080 mailimap_greeting_print(greeting);
2081#endif
2082
2083 greeting_store(session, greeting);
2084
2085 if (greeting->gr_type == MAILIMAP_GREETING_RESP_COND_BYE) {
2086 if (mmap_string_assign(session->imap_response_buffer,
2087 greeting->gr_data.gr_bye->rsp_text->rsp_text) == NULL)
2088 return MAILIMAP_ERROR_MEMORY;
2089
2090 session->imap_response = session->imap_response_buffer->str;
2091
2092 return MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION;
2093 }
2094
2095 if (mmap_string_assign(session->imap_response_buffer,
2096 greeting->gr_data.gr_auth->rsp_text->rsp_text) == NULL)
2097 return MAILIMAP_ERROR_MEMORY;
2098
2099 session->imap_response = session->imap_response_buffer->str;
2100
2101 * result = greeting;
2102
2103 return MAILIMAP_NO_ERROR;
2104}
2105
2106
2107mailimap * mailimap_new(size_t imap_progr_rate,
2108 progress_function * imap_progr_fun)
2109{
2110 mailimap * f;
2111
2112 f = malloc(sizeof(* f));
2113 if (f == NULL)
2114 goto err;
2115
2116 f->imap_response = NULL;
2117
2118 f->imap_stream = NULL;
2119
2120 f->imap_progr_rate = imap_progr_rate;
2121 f->imap_progr_fun = imap_progr_fun;
2122
2123 f->imap_stream_buffer = mmap_string_new("");
2124 if (f->imap_stream_buffer == NULL)
2125 goto free_f;
2126
2127 f->imap_response_buffer = mmap_string_new("");
2128 if (f->imap_response_buffer == NULL)
2129 goto free_stream_buffer;
2130
2131 f->imap_state = MAILIMAP_STATE_DISCONNECTED;
2132 f->imap_tag = 0;
2133
2134 f->imap_selection_info = NULL;
2135 f->imap_response_info = NULL;
2136 f->imap_connection_info = NULL;
2137
2138 return f;
2139
2140 free_stream_buffer:
2141 mmap_string_free(f->imap_stream_buffer);
2142 free_f:
2143 free(f);
2144 err:
2145 return NULL;
2146}
2147
2148void mailimap_free(mailimap * session)
2149{
2150 if (session->imap_stream)
2151 mailimap_logout(session);
2152
2153 mmap_string_free(session->imap_response_buffer);
2154 mmap_string_free(session->imap_stream_buffer);
2155
2156 if (session->imap_response_info)
2157 mailimap_response_info_free(session->imap_response_info);
2158 if (session->imap_selection_info)
2159 mailimap_selection_info_free(session->imap_selection_info);
2160 if (session->imap_connection_info)
2161 mailimap_connection_info_free(session->imap_connection_info);
2162
2163 free(session);
2164}