summaryrefslogtreecommitdiffabout
path: root/kmicromail/libetpan/imap/mailimap.c
Unidiff
Diffstat (limited to 'kmicromail/libetpan/imap/mailimap.c') (more/less context) (ignore whitespace changes)
-rw-r--r--kmicromail/libetpan/imap/mailimap.c2161
1 files changed, 2161 insertions, 0 deletions
diff --git a/kmicromail/libetpan/imap/mailimap.c b/kmicromail/libetpan/imap/mailimap.c
new file mode 100644
index 0000000..c8fbfee
--- a/dev/null
+++ b/kmicromail/libetpan/imap/mailimap.c
@@ -0,0 +1,2161 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2002 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "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
553 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
554 (session->imap_state != MAILIMAP_STATE_SELECTED))
555 return MAILIMAP_ERROR_BAD_STATE;
556
557 r = send_current_tag(session);
558 if (r != MAILIMAP_NO_ERROR)
559 return r;
560
561 r = mailimap_append_send(session->imap_stream, mailbox, flag_list, date_time,
562 literal_size);
563 if (r != MAILIMAP_NO_ERROR)
564 return r;
565
566 if (mailstream_flush(session->imap_stream) == -1)
567 return MAILIMAP_ERROR_STREAM;
568
569 if (read_line(session) == NULL)
570 return MAILIMAP_ERROR_STREAM;
571
572 index = 0;
573
574 r = mailimap_continue_req_parse(session->imap_stream,
575 session->imap_stream_buffer,
576 &index, &cont_req,
577 session->imap_progr_rate, session->imap_progr_fun);
578 if (r == MAILIMAP_NO_ERROR)
579 mailimap_continue_req_free(cont_req);
580
581 if (r == MAILIMAP_ERROR_PARSE) {
582 r = parse_response(session, &response);
583 if (r != MAILIMAP_NO_ERROR)
584 return r;
585 mailimap_response_free(response);
586
587 return MAILIMAP_ERROR_APPEND;
588 }
589
590 r = mailimap_literal_data_send(session->imap_stream, literal, literal_size,
591 session->imap_progr_rate, session->imap_progr_fun);
592 if (r != MAILIMAP_NO_ERROR)
593 return r;
594
595 r = mailimap_crlf_send(session->imap_stream);
596 if (r != MAILIMAP_NO_ERROR)
597 return r;
598
599 if (mailstream_flush(session->imap_stream) == -1)
600 return MAILIMAP_ERROR_STREAM;
601
602 if (read_line(session) == NULL)
603 return MAILIMAP_ERROR_STREAM;
604
605 r = parse_response(session, &response);
606 if (r != MAILIMAP_NO_ERROR)
607 return r;
608
609 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
610
611 mailimap_response_free(response);
612
613 switch (error_code) {
614 case MAILIMAP_RESP_COND_STATE_OK:
615 return MAILIMAP_NO_ERROR;
616
617 default:
618 return MAILIMAP_ERROR_APPEND;
619 }
620}
621
622/*
623gboolean mailimap_authenticate(mailimap * session,
624 gchar * auth_type)
625{
626}
627
628gboolean mailimap_authenticate_resp_send(mailimap * session,
629 gchar * base64)
630{
631}
632*/
633
634int mailimap_noop(mailimap * session)
635{
636 struct mailimap_response * response;
637 int r;
638 int error_code;
639
640 r = send_current_tag(session);
641 if (r != MAILIMAP_NO_ERROR)
642 return r;
643
644 r = mailimap_noop_send(session->imap_stream);
645 if (r != MAILIMAP_NO_ERROR)
646 return r;
647
648 r = mailimap_crlf_send(session->imap_stream);
649 if (r != MAILIMAP_NO_ERROR)
650 return r;
651
652 if (mailstream_flush(session->imap_stream) == -1)
653 return MAILIMAP_ERROR_STREAM;
654
655 if (read_line(session) == NULL)
656 return MAILIMAP_ERROR_STREAM;
657
658 r = parse_response(session, &response);
659 if (r != MAILIMAP_NO_ERROR)
660 return r;
661
662 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
663
664 mailimap_response_free(response);
665
666 switch (error_code) {
667 case MAILIMAP_RESP_COND_STATE_OK:
668 return MAILIMAP_NO_ERROR;
669
670 default:
671 return MAILIMAP_ERROR_NOOP;
672 }
673}
674
675int mailimap_logout(mailimap * session)
676{
677 struct mailimap_response * response;
678 int r;
679 int error_code;
680 int res;
681
682 r = send_current_tag(session);
683 if (r != MAILIMAP_NO_ERROR) {
684 res = r;
685 goto close;
686 }
687
688 r = mailimap_logout_send(session->imap_stream);
689 if (r != MAILIMAP_NO_ERROR) {
690 res = r;
691 goto close;
692 }
693
694 r = mailimap_crlf_send(session->imap_stream);
695 if (r != MAILIMAP_NO_ERROR) {
696 res = r;
697 goto close;
698 }
699
700 if (mailstream_flush(session->imap_stream) == -1) {
701 res = MAILIMAP_ERROR_STREAM;
702 goto close;
703 }
704
705 if (read_line(session) == NULL) {
706 res = MAILIMAP_ERROR_STREAM;
707 goto close;
708 }
709
710 r = parse_response(session, &response);
711 if (r != MAILIMAP_NO_ERROR) {
712 res = r;
713 goto close;
714 }
715
716 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
717
718 mailimap_response_free(response);
719
720 switch (error_code) {
721 case MAILIMAP_RESP_COND_STATE_OK:
722 if (session->imap_connection_info) {
723 mailimap_connection_info_free(session->imap_connection_info);
724 session->imap_connection_info = NULL;
725 }
726 res = MAILIMAP_NO_ERROR;
727 goto close;
728
729 default:
730 res = MAILIMAP_ERROR_LOGOUT;
731 goto close;
732 }
733
734 close:
735 mailstream_close(session->imap_stream);
736 session->imap_stream = NULL;
737 session->imap_state = MAILIMAP_STATE_DISCONNECTED;
738 return res;
739}
740
741/* send the results back to the caller */
742/* duplicate the result */
743
744static struct mailimap_capability *
745mailimap_capability_dup(struct mailimap_capability * orig_cap)
746{
747 struct mailimap_capability * cap;
748 char * auth_type;
749 char * name;
750
751 name = NULL;
752 auth_type = NULL;
753 switch (orig_cap->cap_type) {
754 case MAILIMAP_CAPABILITY_NAME:
755 name = strdup(orig_cap->cap_data.cap_name);
756 if (name == NULL)
757 goto err;
758 break;
759 case MAILIMAP_CAPABILITY_AUTH_TYPE:
760 auth_type = strdup(orig_cap->cap_data.cap_auth_type);
761 if (auth_type == NULL)
762 goto err;
763 break;
764 }
765
766 cap = mailimap_capability_new(orig_cap->cap_type, auth_type, name);
767 if (cap == NULL)
768 goto free;
769
770 return cap;
771
772 free:
773 if (name != NULL)
774 free(name);
775 if (auth_type != NULL)
776 free(auth_type);
777 err:
778 return NULL;
779}
780
781static struct mailimap_capability_data *
782mailimap_capability_data_dup(struct mailimap_capability_data * orig_cap_data)
783{
784 struct mailimap_capability_data * cap_data;
785 struct mailimap_capability * cap_dup;
786 clist * list;
787 clistiter * cur;
788 int r;
789
790 list = clist_new();
791 if (list == NULL)
792 goto err;
793
794 for(cur = clist_begin(orig_cap_data->cap_list) ;
795 cur != NULL ; cur = clist_next(cur)) {
796 struct mailimap_capability * cap;
797
798 cap = clist_content(cur);
799
800 cap_dup = mailimap_capability_dup(cap);
801 if (cap_dup == NULL)
802 goto list;
803
804 r = clist_append(list, cap_dup);
805 if (r < 0) {
806 mailimap_capability_free(cap_dup);
807 goto list;
808 }
809 }
810
811 cap_data = mailimap_capability_data_new(list);
812 if (cap_data == NULL)
813 goto list;
814
815 return cap_data;
816
817list:
818 clist_foreach(list, (clist_func) mailimap_capability_free, NULL);
819 clist_free(list);
820err:
821 return NULL;
822}
823
824int mailimap_capability(mailimap * session,
825 struct mailimap_capability_data ** result)
826{
827 struct mailimap_response * response;
828 int r;
829 int error_code;
830 struct mailimap_capability_data * cap_data;
831
832 r = send_current_tag(session);
833 if (r != MAILIMAP_NO_ERROR)
834 return r;
835
836 r = mailimap_capability_send(session->imap_stream);
837 if (r != MAILIMAP_NO_ERROR)
838 return r;
839
840 r = mailimap_crlf_send(session->imap_stream);
841 if (r != MAILIMAP_NO_ERROR)
842 return r;
843
844 if (mailstream_flush(session->imap_stream) == -1)
845 return MAILIMAP_ERROR_STREAM;
846
847 if (read_line(session) == NULL)
848 return MAILIMAP_ERROR_STREAM;
849
850 r = parse_response(session, &response);
851 if (r != MAILIMAP_NO_ERROR)
852 return r;
853
854 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
855
856 mailimap_response_free(response);
857
858 switch (error_code) {
859 case MAILIMAP_RESP_COND_STATE_OK:
860 cap_data =
861 mailimap_capability_data_dup(session->imap_connection_info->imap_capability);
862 if (cap_data == NULL)
863 return MAILIMAP_ERROR_MEMORY;
864
865 * result = cap_data;
866
867 return MAILIMAP_NO_ERROR;
868
869 default:
870 return MAILIMAP_ERROR_CAPABILITY;
871 }
872}
873
874int mailimap_check(mailimap * session)
875{
876 struct mailimap_response * response;
877 int r;
878 int error_code;
879
880 if (session->imap_state != MAILIMAP_STATE_SELECTED)
881 return MAILIMAP_ERROR_BAD_STATE;
882
883 r = send_current_tag(session);
884 if (r != MAILIMAP_NO_ERROR)
885 return r;
886
887 r = mailimap_check_send(session->imap_stream);
888 if (r != MAILIMAP_NO_ERROR)
889 return r;
890
891 r = mailimap_crlf_send(session->imap_stream);
892 if (r != MAILIMAP_NO_ERROR)
893 return r;
894
895 if (mailstream_flush(session->imap_stream) == -1)
896 return MAILIMAP_ERROR_STREAM;
897
898 if (read_line(session) == NULL)
899 return MAILIMAP_ERROR_STREAM;
900
901 r = parse_response(session, &response);
902 if (r != MAILIMAP_NO_ERROR)
903 return r;
904
905 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
906
907 mailimap_response_free(response);
908
909 switch (error_code) {
910 case MAILIMAP_RESP_COND_STATE_OK:
911 return MAILIMAP_NO_ERROR;
912
913 default:
914 return MAILIMAP_ERROR_CHECK;
915 }
916}
917
918int mailimap_close(mailimap * session)
919{
920 struct mailimap_response * response;
921 int r;
922 int error_code;
923
924 if (session->imap_state != MAILIMAP_STATE_SELECTED)
925 return MAILIMAP_ERROR_BAD_STATE;
926
927 r = send_current_tag(session);
928 if (r != MAILIMAP_NO_ERROR)
929 return r;
930
931 r = mailimap_close_send(session->imap_stream);
932 if (r != MAILIMAP_NO_ERROR)
933 return r;
934
935 r = mailimap_crlf_send(session->imap_stream);
936 if (r != MAILIMAP_NO_ERROR)
937 return r;
938
939 if (mailstream_flush(session->imap_stream) == -1)
940 return MAILIMAP_ERROR_STREAM;
941
942 if (read_line(session) == NULL)
943 return MAILIMAP_ERROR_STREAM;
944
945 r = parse_response(session, &response);
946 if (r != MAILIMAP_NO_ERROR)
947 return r;
948
949 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
950
951 mailimap_response_free(response);
952
953 switch (error_code) {
954 case MAILIMAP_RESP_COND_STATE_OK:
955 /* leave selected state */
956 mailimap_selection_info_free(session->imap_selection_info);
957 session->imap_selection_info = NULL;
958
959 session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
960 return MAILIMAP_NO_ERROR;
961
962 default:
963 return MAILIMAP_ERROR_CLOSE;
964 }
965}
966
967int mailimap_expunge(mailimap * session)
968{
969 struct mailimap_response * response;
970 int r;
971 int error_code;
972
973 if (session->imap_state != MAILIMAP_STATE_SELECTED)
974 return MAILIMAP_ERROR_BAD_STATE;
975
976 r = send_current_tag(session);
977 if (r != MAILIMAP_NO_ERROR)
978 return r;
979
980 r = mailimap_expunge_send(session->imap_stream);
981 if (r != MAILIMAP_NO_ERROR)
982 return r;
983
984 r = mailimap_crlf_send(session->imap_stream);
985 if (r != MAILIMAP_NO_ERROR)
986 return r;
987
988 if (mailstream_flush(session->imap_stream) == -1)
989 return MAILIMAP_ERROR_STREAM;
990
991 if (read_line(session) == NULL)
992 return MAILIMAP_ERROR_STREAM;
993
994 r = parse_response(session, &response);
995 if (r != MAILIMAP_NO_ERROR)
996 return r;
997
998 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
999
1000 mailimap_response_free(response);
1001
1002 switch (error_code) {
1003 case MAILIMAP_RESP_COND_STATE_OK:
1004 return MAILIMAP_NO_ERROR;
1005
1006 default:
1007 return MAILIMAP_ERROR_EXPUNGE;
1008 }
1009}
1010
1011int mailimap_copy(mailimap * session, struct mailimap_set * set,
1012 const char * mb)
1013{
1014 struct mailimap_response * response;
1015 int r;
1016 int error_code;
1017
1018 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1019 return MAILIMAP_ERROR_BAD_STATE;
1020
1021 r = send_current_tag(session);
1022 if (r != MAILIMAP_NO_ERROR)
1023 return r;
1024
1025 r = mailimap_copy_send(session->imap_stream, set, mb);
1026 if (r != MAILIMAP_NO_ERROR)
1027 return r;
1028
1029 r = mailimap_crlf_send(session->imap_stream);
1030 if (r != MAILIMAP_NO_ERROR)
1031 return r;
1032
1033 if (mailstream_flush(session->imap_stream) == -1)
1034 return MAILIMAP_ERROR_STREAM;
1035
1036 if (read_line(session) == NULL)
1037 return MAILIMAP_ERROR_STREAM;
1038
1039 r = parse_response(session, &response);
1040 if (r != MAILIMAP_NO_ERROR)
1041 return r;
1042
1043 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1044
1045 mailimap_response_free(response);
1046
1047 switch (error_code) {
1048 case MAILIMAP_RESP_COND_STATE_OK:
1049 return MAILIMAP_NO_ERROR;
1050
1051 default:
1052 return MAILIMAP_ERROR_COPY;
1053 }
1054}
1055
1056int mailimap_uid_copy(mailimap * session, struct mailimap_set * set,
1057 const char * mb)
1058{
1059 struct mailimap_response * response;
1060 int r;
1061 int error_code;
1062
1063 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1064 return MAILIMAP_ERROR_BAD_STATE;
1065
1066 r = send_current_tag(session);
1067 if (r != MAILIMAP_NO_ERROR)
1068 return r;
1069
1070 r = mailimap_uid_copy_send(session->imap_stream, set, mb);
1071 if (r != MAILIMAP_NO_ERROR)
1072 return r;
1073
1074 r = mailimap_crlf_send(session->imap_stream);
1075 if (r != MAILIMAP_NO_ERROR)
1076 return r;
1077
1078 if (mailstream_flush(session->imap_stream) == -1)
1079 return MAILIMAP_ERROR_STREAM;
1080
1081 if (read_line(session) == NULL)
1082 return MAILIMAP_ERROR_STREAM;
1083
1084 r = parse_response(session, &response);
1085 if (r != MAILIMAP_NO_ERROR)
1086 return r;
1087
1088 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1089
1090 mailimap_response_free(response);
1091
1092 switch (error_code) {
1093 case MAILIMAP_RESP_COND_STATE_OK:
1094 return MAILIMAP_NO_ERROR;
1095
1096 default:
1097 return MAILIMAP_ERROR_UID_COPY;
1098 }
1099}
1100
1101int mailimap_create(mailimap * session, const char * mb)
1102{
1103 struct mailimap_response * response;
1104 int r;
1105 int error_code;
1106
1107 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1108 (session->imap_state != MAILIMAP_STATE_SELECTED))
1109 return MAILIMAP_ERROR_BAD_STATE;
1110
1111 r = send_current_tag(session);
1112 if (r != MAILIMAP_NO_ERROR)
1113 return r;
1114
1115 r = mailimap_create_send(session->imap_stream, mb);
1116 if (r != MAILIMAP_NO_ERROR)
1117 return r;
1118
1119 r = mailimap_crlf_send(session->imap_stream);
1120 if (r != MAILIMAP_NO_ERROR)
1121 return r;
1122
1123 if (mailstream_flush(session->imap_stream) == -1)
1124 return MAILIMAP_ERROR_STREAM;
1125
1126 if (read_line(session) == NULL)
1127 return MAILIMAP_ERROR_STREAM;
1128
1129 r = parse_response(session, &response);
1130 if (r != MAILIMAP_NO_ERROR)
1131 return r;
1132
1133 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1134
1135 mailimap_response_free(response);
1136
1137 switch (error_code) {
1138 case MAILIMAP_RESP_COND_STATE_OK:
1139 return MAILIMAP_NO_ERROR;
1140
1141 default:
1142 return MAILIMAP_ERROR_CREATE;
1143 }
1144}
1145
1146
1147int mailimap_delete(mailimap * session, const char * mb)
1148{
1149 struct mailimap_response * response;
1150 int r;
1151 int error_code;
1152
1153 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1154 (session->imap_state != MAILIMAP_STATE_SELECTED))
1155 return MAILIMAP_ERROR_BAD_STATE;
1156
1157 r = send_current_tag(session);
1158 if (r != MAILIMAP_NO_ERROR)
1159 return r;
1160
1161 r = mailimap_delete_send(session->imap_stream, mb);
1162 if (r != MAILIMAP_NO_ERROR)
1163 return r;
1164
1165 r = mailimap_crlf_send(session->imap_stream);
1166 if (r != MAILIMAP_NO_ERROR)
1167 return r;
1168
1169 if (mailstream_flush(session->imap_stream) == -1)
1170 return MAILIMAP_ERROR_STREAM;
1171
1172 if (read_line(session) == NULL)
1173 return MAILIMAP_ERROR_STREAM;
1174
1175 r = parse_response(session, &response);
1176 if (r != MAILIMAP_NO_ERROR)
1177 return r;
1178
1179 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1180
1181 mailimap_response_free(response);
1182
1183 switch (error_code) {
1184 case MAILIMAP_RESP_COND_STATE_OK:
1185 return MAILIMAP_NO_ERROR;
1186
1187 default:
1188 return MAILIMAP_ERROR_DELETE;
1189 }
1190}
1191
1192int mailimap_examine(mailimap * session, const char * mb)
1193{
1194 struct mailimap_response * response;
1195 int r;
1196 int error_code;
1197
1198 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1199 (session->imap_state != MAILIMAP_STATE_SELECTED))
1200 return MAILIMAP_ERROR_BAD_STATE;
1201
1202 r = send_current_tag(session);
1203 if (r != MAILIMAP_NO_ERROR)
1204 return r;
1205
1206 r = mailimap_examine_send(session->imap_stream, mb);
1207 if (r != MAILIMAP_NO_ERROR)
1208 return r;
1209
1210 r = mailimap_crlf_send(session->imap_stream);
1211 if (r != MAILIMAP_NO_ERROR)
1212 return r;
1213
1214 if (mailstream_flush(session->imap_stream) == -1)
1215 return MAILIMAP_ERROR_STREAM;
1216
1217 if (read_line(session) == NULL)
1218 return MAILIMAP_ERROR_STREAM;
1219
1220 if (session->imap_selection_info != NULL)
1221 mailimap_selection_info_free(session->imap_selection_info);
1222 session->imap_selection_info = mailimap_selection_info_new();
1223
1224 r = parse_response(session, &response);
1225 if (r != MAILIMAP_NO_ERROR)
1226 return r;
1227
1228 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1229
1230 mailimap_response_free(response);
1231
1232 switch (error_code) {
1233 case MAILIMAP_RESP_COND_STATE_OK:
1234 session->imap_state = MAILIMAP_STATE_SELECTED;
1235 return MAILIMAP_NO_ERROR;
1236
1237 default:
1238 mailimap_selection_info_free(session->imap_selection_info);
1239 session->imap_selection_info = NULL;
1240 session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
1241 return MAILIMAP_ERROR_EXAMINE;
1242 }
1243}
1244
1245int
1246mailimap_fetch(mailimap * session, struct mailimap_set * set,
1247 struct mailimap_fetch_type * fetch_type, clist ** result)
1248{
1249 struct mailimap_response * response;
1250 int r;
1251 int error_code;
1252
1253 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1254 return MAILIMAP_ERROR_BAD_STATE;
1255
1256 r = send_current_tag(session);
1257 if (r != MAILIMAP_NO_ERROR)
1258 return r;
1259
1260 r = mailimap_fetch_send(session->imap_stream, set, fetch_type);
1261 if (r != MAILIMAP_NO_ERROR)
1262 return r;
1263
1264 r = mailimap_crlf_send(session->imap_stream);
1265 if (r != MAILIMAP_NO_ERROR)
1266 return r;
1267
1268 if (mailstream_flush(session->imap_stream) == -1)
1269 return MAILIMAP_ERROR_STREAM;
1270
1271 if (read_line(session) == NULL)
1272 return MAILIMAP_ERROR_STREAM;
1273
1274 r = parse_response(session, &response);
1275 if (r != MAILIMAP_NO_ERROR)
1276 return r;
1277
1278 * result = session->imap_response_info->rsp_fetch_list;
1279 session->imap_response_info->rsp_fetch_list = NULL;
1280
1281 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1282
1283 mailimap_response_free(response);
1284
1285 switch (error_code) {
1286 case MAILIMAP_RESP_COND_STATE_OK:
1287 return MAILIMAP_NO_ERROR;
1288
1289 default:
1290 return MAILIMAP_ERROR_FETCH;
1291 }
1292}
1293
1294void mailimap_fetch_list_free(clist * fetch_list)
1295{
1296 clist_foreach(fetch_list, (clist_func) mailimap_msg_att_free, NULL);
1297 clist_free(fetch_list);
1298}
1299
1300int
1301mailimap_uid_fetch(mailimap * session,
1302 struct mailimap_set * set,
1303 struct mailimap_fetch_type * fetch_type, clist ** result)
1304{
1305 struct mailimap_response * response;
1306 int r;
1307 int error_code;
1308
1309 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1310 return MAILIMAP_ERROR_BAD_STATE;
1311
1312 r = send_current_tag(session);
1313 if (r != MAILIMAP_NO_ERROR)
1314 return r;
1315
1316 r = mailimap_uid_fetch_send(session->imap_stream, set, fetch_type);
1317 if (r != MAILIMAP_NO_ERROR)
1318 return r;
1319
1320 r = mailimap_crlf_send(session->imap_stream);
1321 if (r != MAILIMAP_NO_ERROR)
1322 return r;
1323
1324 if (mailstream_flush(session->imap_stream) == -1)
1325 return MAILIMAP_ERROR_STREAM;
1326
1327 if (read_line(session) == NULL)
1328 return MAILIMAP_ERROR_STREAM;
1329
1330 r = parse_response(session, &response);
1331
1332 if (r != MAILIMAP_NO_ERROR)
1333 return r;
1334
1335 * result = session->imap_response_info->rsp_fetch_list;
1336 session->imap_response_info->rsp_fetch_list = NULL;
1337
1338 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1339
1340 mailimap_response_free(response);
1341
1342 switch (error_code) {
1343 case MAILIMAP_RESP_COND_STATE_OK:
1344 return MAILIMAP_NO_ERROR;
1345
1346 default:
1347 return MAILIMAP_ERROR_UID_FETCH;
1348 }
1349}
1350
1351int mailimap_list(mailimap * session, const char * mb,
1352 const char * list_mb, clist ** result)
1353{
1354 struct mailimap_response * response;
1355 int r;
1356 int error_code;
1357
1358 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1359 (session->imap_state != MAILIMAP_STATE_SELECTED))
1360 return MAILIMAP_ERROR_BAD_STATE;
1361
1362 r = send_current_tag(session);
1363 if (r != MAILIMAP_NO_ERROR)
1364 return r;
1365
1366 r = mailimap_list_send(session->imap_stream, mb, list_mb);
1367 if (r != MAILIMAP_NO_ERROR)
1368 return r;
1369
1370 r = mailimap_crlf_send(session->imap_stream);
1371 if (r != MAILIMAP_NO_ERROR)
1372 return r;
1373
1374 if (mailstream_flush(session->imap_stream) == -1)
1375 return MAILIMAP_ERROR_STREAM;
1376
1377 if (read_line(session) == NULL)
1378 return MAILIMAP_ERROR_STREAM;
1379
1380 r = parse_response(session, &response);
1381 if (r != MAILIMAP_NO_ERROR)
1382 return r;
1383
1384 * result = session->imap_response_info->rsp_mailbox_list;
1385 session->imap_response_info->rsp_mailbox_list = NULL;
1386
1387 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1388
1389 mailimap_response_free(response);
1390
1391 switch (error_code) {
1392 case MAILIMAP_RESP_COND_STATE_OK:
1393 return MAILIMAP_NO_ERROR;
1394
1395 default:
1396 return MAILIMAP_ERROR_LIST;
1397 }
1398}
1399
1400int mailimap_login(mailimap * session,
1401 const char * userid, const char * password)
1402{
1403 struct mailimap_response * response;
1404 int r;
1405 int error_code;
1406
1407 if (session->imap_state != MAILIMAP_STATE_NON_AUTHENTICATED)
1408 return MAILIMAP_ERROR_BAD_STATE;
1409
1410 r = send_current_tag(session);
1411 if (r != MAILIMAP_NO_ERROR)
1412 return r;
1413
1414 r = mailimap_login_send(session->imap_stream, userid, password);
1415 if (r != MAILIMAP_NO_ERROR)
1416 return r;
1417
1418 r = mailimap_crlf_send(session->imap_stream);
1419 if (r != MAILIMAP_NO_ERROR)
1420 return r;
1421
1422 if (mailstream_flush(session->imap_stream) == -1)
1423 return MAILIMAP_ERROR_STREAM;
1424
1425 if (read_line(session) == NULL)
1426 return MAILIMAP_ERROR_STREAM;
1427
1428 r = parse_response(session, &response);
1429 if (r != MAILIMAP_NO_ERROR)
1430 return r;
1431
1432 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1433
1434 mailimap_response_free(response);
1435
1436 switch (error_code) {
1437 case MAILIMAP_RESP_COND_STATE_OK:
1438 session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
1439 return MAILIMAP_NO_ERROR;
1440
1441 default:
1442 return MAILIMAP_ERROR_LOGIN;
1443 }
1444}
1445
1446int mailimap_lsub(mailimap * session, const char * mb,
1447 const char * list_mb, clist ** result)
1448{
1449 struct mailimap_response * response;
1450 int r;
1451 int error_code;
1452
1453 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1454 (session->imap_state != MAILIMAP_STATE_SELECTED))
1455 return MAILIMAP_ERROR_BAD_STATE;
1456
1457 r = send_current_tag(session);
1458 if (r != MAILIMAP_NO_ERROR)
1459 return r;
1460
1461 r = mailimap_lsub_send(session->imap_stream, mb, list_mb);
1462 if (r != MAILIMAP_NO_ERROR)
1463 return r;
1464
1465 r = mailimap_crlf_send(session->imap_stream);
1466 if (r != MAILIMAP_NO_ERROR)
1467 return r;
1468
1469 if (mailstream_flush(session->imap_stream) == -1)
1470 return MAILIMAP_ERROR_STREAM;
1471
1472 if (read_line(session) == NULL)
1473 return MAILIMAP_ERROR_STREAM;
1474
1475 r = parse_response(session, &response);
1476 if (r != MAILIMAP_NO_ERROR)
1477 return r;
1478
1479 * result = session->imap_response_info->rsp_mailbox_lsub;
1480 session->imap_response_info->rsp_mailbox_lsub = NULL;
1481
1482 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1483
1484 mailimap_response_free(response);
1485
1486 switch (error_code) {
1487 case MAILIMAP_RESP_COND_STATE_OK:
1488 return MAILIMAP_NO_ERROR;
1489
1490 default:
1491 return MAILIMAP_ERROR_LSUB;
1492 }
1493}
1494
1495void mailimap_list_result_free(clist * list)
1496{
1497 clist_foreach(list, (clist_func) mailimap_mailbox_list_free, NULL);
1498 clist_free(list);
1499}
1500
1501int mailimap_rename(mailimap * session,
1502 const char * mb, const char * new_name)
1503{
1504 struct mailimap_response * response;
1505 int r;
1506 int error_code;
1507
1508 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1509 (session->imap_state != MAILIMAP_STATE_SELECTED))
1510 return MAILIMAP_ERROR_BAD_STATE;
1511
1512 r = send_current_tag(session);
1513 if (r != MAILIMAP_NO_ERROR)
1514 return r;
1515
1516 r = mailimap_rename_send(session->imap_stream, mb, new_name);
1517 if (r != MAILIMAP_NO_ERROR)
1518 return r;
1519
1520 if (!mailimap_crlf_send(session->imap_stream))
1521 if (r != MAILIMAP_NO_ERROR)
1522 return r;
1523
1524 if (mailstream_flush(session->imap_stream) == -1)
1525 return MAILIMAP_ERROR_STREAM;
1526
1527 if (read_line(session) == NULL)
1528 return MAILIMAP_ERROR_STREAM;
1529
1530 r = parse_response(session, &response);
1531 if (r != MAILIMAP_NO_ERROR)
1532 return r;
1533
1534 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1535
1536 mailimap_response_free(response);
1537
1538 switch (error_code) {
1539 case MAILIMAP_RESP_COND_STATE_OK:
1540 return MAILIMAP_NO_ERROR;
1541
1542 default:
1543 return MAILIMAP_ERROR_RENAME;
1544 }
1545}
1546
1547int
1548mailimap_search(mailimap * session, const char * charset,
1549 struct mailimap_search_key * key, clist ** result)
1550{
1551 struct mailimap_response * response;
1552 int r;
1553 int error_code;
1554
1555 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1556 return MAILIMAP_ERROR_BAD_STATE;
1557
1558 r = send_current_tag(session);
1559 if (r != MAILIMAP_NO_ERROR)
1560 return r;
1561
1562 r = mailimap_search_send(session->imap_stream, charset, key);
1563 if (r != MAILIMAP_NO_ERROR)
1564 return r;
1565
1566 r = mailimap_crlf_send(session->imap_stream);
1567 if (r != MAILIMAP_NO_ERROR)
1568 return r;
1569
1570 if (mailstream_flush(session->imap_stream) == -1)
1571 return MAILIMAP_ERROR_STREAM;
1572
1573 if (read_line(session) == NULL)
1574 return MAILIMAP_ERROR_STREAM;
1575
1576 r = parse_response(session, &response);
1577 if (r != MAILIMAP_NO_ERROR)
1578 return r;
1579
1580 * result = session->imap_response_info->rsp_search_result;
1581 session->imap_response_info->rsp_search_result = NULL;
1582
1583 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1584
1585 mailimap_response_free(response);
1586
1587 switch (error_code) {
1588 case MAILIMAP_RESP_COND_STATE_OK:
1589 return MAILIMAP_NO_ERROR;
1590
1591 default:
1592 return MAILIMAP_ERROR_SEARCH;
1593 }
1594}
1595
1596int
1597mailimap_uid_search(mailimap * session, const char * charset,
1598 struct mailimap_search_key * key, clist ** result)
1599{
1600 struct mailimap_response * response;
1601 int r;
1602 int error_code;
1603
1604 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1605 return MAILIMAP_ERROR_BAD_STATE;
1606
1607 r = send_current_tag(session);
1608 if (r != MAILIMAP_NO_ERROR)
1609 return r;
1610
1611 r = mailimap_uid_search_send(session->imap_stream, charset, key);
1612 if (r != MAILIMAP_NO_ERROR)
1613 return r;
1614
1615 r = mailimap_crlf_send(session->imap_stream);
1616 if (r != MAILIMAP_NO_ERROR)
1617 return r;
1618
1619 if (mailstream_flush(session->imap_stream) == -1)
1620 return MAILIMAP_ERROR_STREAM;
1621
1622 if (read_line(session) == NULL)
1623 return MAILIMAP_ERROR_STREAM;
1624
1625 r = parse_response(session, &response);
1626 if (r != MAILIMAP_NO_ERROR)
1627 return r;
1628
1629 * result = session->imap_response_info->rsp_search_result;
1630 session->imap_response_info->rsp_search_result = NULL;
1631
1632 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1633
1634 mailimap_response_free(response);
1635
1636 switch (error_code) {
1637 case MAILIMAP_RESP_COND_STATE_OK:
1638 return MAILIMAP_NO_ERROR;
1639
1640 default:
1641 return MAILIMAP_ERROR_UID_SEARCH;
1642 }
1643}
1644
1645void mailimap_search_result_free(clist * search_result)
1646{
1647 clist_foreach(search_result, (clist_func) free, NULL);
1648 clist_free(search_result);
1649}
1650
1651int
1652mailimap_select(mailimap * session, const char * mb)
1653{
1654 struct mailimap_response * response;
1655 int r;
1656 int error_code;
1657
1658 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1659 (session->imap_state != MAILIMAP_STATE_SELECTED))
1660 return MAILIMAP_ERROR_BAD_STATE;
1661
1662 r = send_current_tag(session);
1663 if (r != MAILIMAP_NO_ERROR)
1664 return r;
1665
1666 r = mailimap_select_send(session->imap_stream, mb);
1667 if (r != MAILIMAP_NO_ERROR)
1668 return r;
1669
1670 r = mailimap_crlf_send(session->imap_stream);
1671 if (r != MAILIMAP_NO_ERROR)
1672 return r;
1673
1674 if (mailstream_flush(session->imap_stream) == -1)
1675 return MAILIMAP_ERROR_STREAM;
1676
1677 if (read_line(session) == NULL)
1678 return MAILIMAP_ERROR_STREAM;
1679
1680 if (session->imap_selection_info != NULL)
1681 mailimap_selection_info_free(session->imap_selection_info);
1682 session->imap_selection_info = mailimap_selection_info_new();
1683
1684 r = parse_response(session, &response);
1685 if (r != MAILIMAP_NO_ERROR)
1686 return r;
1687
1688 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1689
1690 mailimap_response_free(response);
1691
1692 switch (error_code) {
1693 case MAILIMAP_RESP_COND_STATE_OK:
1694 session->imap_state = MAILIMAP_STATE_SELECTED;
1695 return MAILIMAP_NO_ERROR;
1696
1697 default:
1698 mailimap_selection_info_free(session->imap_selection_info);
1699 session->imap_selection_info = NULL;
1700 session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
1701 return MAILIMAP_ERROR_SELECT;
1702 }
1703}
1704
1705int
1706mailimap_status(mailimap * session, const char * mb,
1707 struct mailimap_status_att_list * status_att_list,
1708 struct mailimap_mailbox_data_status ** result)
1709{
1710 struct mailimap_response * response;
1711 int r;
1712 int error_code;
1713
1714 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1715 (session->imap_state != MAILIMAP_STATE_SELECTED))
1716 return MAILIMAP_ERROR_BAD_STATE;
1717
1718 r = send_current_tag(session);
1719 if (r != MAILIMAP_NO_ERROR)
1720 return r;
1721
1722 r = mailimap_status_send(session->imap_stream, mb, status_att_list);
1723 if (r != MAILIMAP_NO_ERROR)
1724 return r;
1725
1726 r = mailimap_crlf_send(session->imap_stream);
1727 if (r != MAILIMAP_NO_ERROR)
1728 return r;
1729
1730 if (mailstream_flush(session->imap_stream) == -1)
1731 return MAILIMAP_ERROR_STREAM;
1732
1733 if (read_line(session) == NULL)
1734 return MAILIMAP_ERROR_STREAM;
1735
1736 r = parse_response(session, &response);
1737 if (r != MAILIMAP_NO_ERROR)
1738 return r;
1739
1740 * result = session->imap_response_info->rsp_status;
1741 session->imap_response_info->rsp_status = NULL;
1742
1743 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1744
1745 mailimap_response_free(response);
1746
1747 switch (error_code) {
1748 case MAILIMAP_RESP_COND_STATE_OK:
1749 return MAILIMAP_NO_ERROR;
1750
1751 default:
1752 return MAILIMAP_ERROR_STATUS;
1753 }
1754}
1755
1756
1757int
1758mailimap_store(mailimap * session,
1759 struct mailimap_set * set,
1760 struct mailimap_store_att_flags * store_att_flags)
1761{
1762 struct mailimap_response * response;
1763 int r;
1764 int error_code;
1765
1766 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1767 return MAILIMAP_ERROR_BAD_STATE;
1768
1769 r = send_current_tag(session);
1770 if (r != MAILIMAP_NO_ERROR)
1771 return r;
1772
1773 r = mailimap_store_send(session->imap_stream, set, store_att_flags);
1774 if (r != MAILIMAP_NO_ERROR)
1775 return r;
1776
1777 r = mailimap_crlf_send(session->imap_stream);
1778 if (r != MAILIMAP_NO_ERROR)
1779 return r;
1780
1781 if (mailstream_flush(session->imap_stream) == -1)
1782 return MAILIMAP_ERROR_STREAM;
1783
1784 if (read_line(session) == NULL)
1785 return MAILIMAP_ERROR_STREAM;
1786
1787 r = parse_response(session, &response);
1788 if (r != MAILIMAP_NO_ERROR)
1789 return r;
1790
1791 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1792
1793 mailimap_response_free(response);
1794
1795 switch (error_code) {
1796 case MAILIMAP_RESP_COND_STATE_OK:
1797 return MAILIMAP_NO_ERROR;
1798
1799 default:
1800 return MAILIMAP_ERROR_STORE;
1801 }
1802}
1803
1804int
1805mailimap_uid_store(mailimap * session,
1806 struct mailimap_set * set,
1807 struct mailimap_store_att_flags * store_att_flags)
1808{
1809 struct mailimap_response * response;
1810 int r;
1811 int error_code;
1812
1813 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1814 return MAILIMAP_ERROR_BAD_STATE;
1815
1816 r = send_current_tag(session);
1817 if (r != MAILIMAP_NO_ERROR)
1818 return r;
1819
1820 r = mailimap_uid_store_send(session->imap_stream, set, store_att_flags);
1821 if (r != MAILIMAP_NO_ERROR)
1822 return r;
1823
1824 r = mailimap_crlf_send(session->imap_stream);
1825 if (r != MAILIMAP_NO_ERROR)
1826 return r;
1827
1828 if (mailstream_flush(session->imap_stream) == -1)
1829 return MAILIMAP_ERROR_STREAM;
1830
1831 if (read_line(session) == NULL)
1832 return MAILIMAP_ERROR_STREAM;
1833
1834 r = parse_response(session, &response);
1835 if (r != MAILIMAP_NO_ERROR)
1836 return r;
1837
1838 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1839
1840 mailimap_response_free(response);
1841
1842 switch (error_code) {
1843 case MAILIMAP_RESP_COND_STATE_OK:
1844 return MAILIMAP_NO_ERROR;
1845
1846 default:
1847 return MAILIMAP_ERROR_UID_STORE;
1848 }
1849}
1850
1851int mailimap_subscribe(mailimap * session, const char * mb)
1852{
1853 struct mailimap_response * response;
1854 int r;
1855 int error_code;
1856
1857 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1858 (session->imap_state != MAILIMAP_STATE_SELECTED))
1859 return MAILIMAP_ERROR_BAD_STATE;
1860
1861 r = send_current_tag(session);
1862 if (r != MAILIMAP_NO_ERROR)
1863 return r;
1864
1865 r = mailimap_subscribe_send(session->imap_stream, mb);
1866 if (r != MAILIMAP_NO_ERROR)
1867 return r;
1868
1869 r = mailimap_crlf_send(session->imap_stream);
1870 if (r != MAILIMAP_NO_ERROR)
1871 return r;
1872
1873 if (mailstream_flush(session->imap_stream) == -1)
1874 return MAILIMAP_ERROR_STREAM;
1875
1876 if (read_line(session) == NULL)
1877 return MAILIMAP_ERROR_STREAM;
1878
1879 r = parse_response(session, &response);
1880 if (r != MAILIMAP_NO_ERROR)
1881 return r;
1882
1883 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1884
1885 mailimap_response_free(response);
1886
1887 switch (error_code) {
1888 case MAILIMAP_RESP_COND_STATE_OK:
1889 return MAILIMAP_NO_ERROR;
1890
1891 default:
1892 return MAILIMAP_ERROR_SUBSCRIBE;
1893 }
1894}
1895
1896int mailimap_unsubscribe(mailimap * session, const char * mb)
1897{
1898 struct mailimap_response * response;
1899 int r;
1900 int error_code;
1901
1902 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1903 (session->imap_state != MAILIMAP_STATE_SELECTED))
1904 return MAILIMAP_ERROR_BAD_STATE;
1905
1906 r = send_current_tag(session);
1907 if (r != MAILIMAP_NO_ERROR)
1908 return r;
1909
1910 r = mailimap_subscribe_send(session->imap_stream, mb);
1911 if (r != MAILIMAP_NO_ERROR)
1912 return r;
1913
1914 r = mailimap_crlf_send(session->imap_stream);
1915 if (r != MAILIMAP_NO_ERROR)
1916 return r;
1917
1918 if (mailstream_flush(session->imap_stream) == -1)
1919 return MAILIMAP_ERROR_STREAM;
1920
1921 if (read_line(session) == NULL)
1922 return MAILIMAP_ERROR_STREAM;
1923
1924 r = parse_response(session, &response);
1925 if (r != MAILIMAP_NO_ERROR)
1926 return r;
1927
1928 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1929
1930 mailimap_response_free(response);
1931
1932 switch (error_code) {
1933 case MAILIMAP_RESP_COND_STATE_OK:
1934 return MAILIMAP_NO_ERROR;
1935
1936 default:
1937 return MAILIMAP_ERROR_UNSUBSCRIBE;
1938 }
1939}
1940
1941
1942int mailimap_starttls(mailimap * session)
1943{
1944 struct mailimap_response * response;
1945 int r;
1946 int error_code;
1947
1948 r = send_current_tag(session);
1949 if (r != MAILIMAP_NO_ERROR)
1950 return r;
1951
1952 r = mailimap_starttls_send(session->imap_stream);
1953 if (r != MAILIMAP_NO_ERROR)
1954 return r;
1955
1956 r = mailimap_crlf_send(session->imap_stream);
1957 if (r != MAILIMAP_NO_ERROR)
1958 return r;
1959
1960 if (mailstream_flush(session->imap_stream) == -1)
1961 return MAILIMAP_ERROR_STREAM;
1962
1963 if (read_line(session) == NULL)
1964 return MAILIMAP_ERROR_STREAM;
1965
1966 r = parse_response(session, &response);
1967 if (r != MAILIMAP_NO_ERROR)
1968 return r;
1969
1970 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1971
1972 mailimap_response_free(response);
1973
1974 switch (error_code) {
1975 case MAILIMAP_RESP_COND_STATE_OK:
1976 return MAILIMAP_NO_ERROR;
1977
1978 default:
1979 return MAILIMAP_ERROR_STARTTLS;
1980 }
1981}
1982
1983
1984
1985static char * read_line(mailimap * session)
1986{
1987 return mailstream_read_line(session->imap_stream, session->imap_stream_buffer);
1988}
1989
1990static int send_current_tag(mailimap * session)
1991{
1992 char tag_str[15];
1993 int r;
1994
1995 session->imap_tag ++;
1996 snprintf(tag_str, 15, "%i", session->imap_tag);
1997
1998 r = mailimap_tag_send(session->imap_stream, tag_str);
1999 if (r != MAILIMAP_NO_ERROR)
2000 return r;
2001
2002 r = mailimap_space_send(session->imap_stream);
2003 if (r != MAILIMAP_NO_ERROR)
2004 return r;
2005
2006 return MAILIMAP_NO_ERROR;
2007}
2008
2009static int parse_response(mailimap * session,
2010 struct mailimap_response ** result)
2011{
2012 size_t index;
2013 struct mailimap_response * response;
2014 char tag_str[15];
2015 int r;
2016
2017 index = 0;
2018
2019 session->imap_response = NULL;
2020
2021 r = mailimap_response_parse(session->imap_stream,
2022 session->imap_stream_buffer,
2023 &index, &response,
2024 session->imap_progr_rate, session->imap_progr_fun);
2025 if (r != MAILIMAP_NO_ERROR)
2026 return r;
2027
2028#if 0
2029 mailimap_response_print(response);
2030#endif
2031
2032 response_store(session, response);
2033
2034 if (mmap_string_assign(session->imap_response_buffer,
2035 response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_text->rsp_text)
2036 == NULL)
2037 return MAILIMAP_ERROR_MEMORY;
2038
2039 session->imap_response = session->imap_response_buffer->str;
2040
2041 if (response->rsp_resp_done->rsp_type == MAILIMAP_RESP_DONE_TYPE_FATAL)
2042 return MAILIMAP_ERROR_FATAL;
2043
2044 snprintf(tag_str, 15, "%i", session->imap_tag);
2045 if (strcmp(response->rsp_resp_done->rsp_data.rsp_tagged->rsp_tag, tag_str) != 0)
2046 return MAILIMAP_ERROR_PROTOCOL;
2047
2048 if (response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type ==
2049 MAILIMAP_RESP_COND_STATE_BAD)
2050 return MAILIMAP_ERROR_PROTOCOL;
2051
2052 * result = response;
2053
2054 return MAILIMAP_NO_ERROR;
2055}
2056
2057
2058static int parse_greeting(mailimap * session,
2059 struct mailimap_greeting ** result)
2060{
2061 size_t index;
2062 struct mailimap_greeting * greeting;
2063 int r;
2064
2065 index = 0;
2066
2067 session->imap_response = NULL;
2068
2069 r = mailimap_greeting_parse(session->imap_stream,
2070 session->imap_stream_buffer,
2071 &index, &greeting, session->imap_progr_rate,
2072 session->imap_progr_fun);
2073 if (r != MAILIMAP_NO_ERROR)
2074 return r;
2075
2076#if 0
2077 mailimap_greeting_print(greeting);
2078#endif
2079
2080 greeting_store(session, greeting);
2081
2082 if (greeting->gr_type == MAILIMAP_GREETING_RESP_COND_BYE) {
2083 if (mmap_string_assign(session->imap_response_buffer,
2084 greeting->gr_data.gr_bye->rsp_text->rsp_text) == NULL)
2085 return MAILIMAP_ERROR_MEMORY;
2086
2087 session->imap_response = session->imap_response_buffer->str;
2088
2089 return MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION;
2090 }
2091
2092 if (mmap_string_assign(session->imap_response_buffer,
2093 greeting->gr_data.gr_auth->rsp_text->rsp_text) == NULL)
2094 return MAILIMAP_ERROR_MEMORY;
2095
2096 session->imap_response = session->imap_response_buffer->str;
2097
2098 * result = greeting;
2099
2100 return MAILIMAP_NO_ERROR;
2101}
2102
2103
2104mailimap * mailimap_new(size_t imap_progr_rate,
2105 progress_function * imap_progr_fun)
2106{
2107 mailimap * f;
2108
2109 f = malloc(sizeof(* f));
2110 if (f == NULL)
2111 goto err;
2112
2113 f->imap_response = NULL;
2114
2115 f->imap_stream = NULL;
2116
2117 f->imap_progr_rate = imap_progr_rate;
2118 f->imap_progr_fun = imap_progr_fun;
2119
2120 f->imap_stream_buffer = mmap_string_new("");
2121 if (f->imap_stream_buffer == NULL)
2122 goto free_f;
2123
2124 f->imap_response_buffer = mmap_string_new("");
2125 if (f->imap_response_buffer == NULL)
2126 goto free_stream_buffer;
2127
2128 f->imap_state = MAILIMAP_STATE_DISCONNECTED;
2129 f->imap_tag = 0;
2130
2131 f->imap_selection_info = NULL;
2132 f->imap_response_info = NULL;
2133 f->imap_connection_info = NULL;
2134
2135 return f;
2136
2137 free_stream_buffer:
2138 mmap_string_free(f->imap_stream_buffer);
2139 free_f:
2140 free(f);
2141 err:
2142 return NULL;
2143}
2144
2145void mailimap_free(mailimap * session)
2146{
2147 if (session->imap_stream)
2148 mailimap_logout(session);
2149
2150 mmap_string_free(session->imap_response_buffer);
2151 mmap_string_free(session->imap_stream_buffer);
2152
2153 if (session->imap_response_info)
2154 mailimap_response_info_free(session->imap_response_info);
2155 if (session->imap_selection_info)
2156 mailimap_selection_info_free(session->imap_selection_info);
2157 if (session->imap_connection_info)
2158 mailimap_connection_info_free(session->imap_connection_info);
2159
2160 free(session);
2161}