1
/***************************************************************************
3
* Project ___| | | | _ \| |
5
* | (__| |_| | _ <| |___
6
* \___|\___/|_| \_\_____|
8
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
10
* This software is licensed as described in the file COPYING, which
11
* you should have received as part of this distribution. The terms
12
* are also available at http://curl.haxx.se/docs/copyright.html.
14
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
15
* copies of the Software, and permit persons to whom the Software is
16
* furnished to do so, under the terms of the COPYING file.
18
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
* KIND, either express or implied.
21
* RFC3501 IMAPv4 protocol
22
* RFC5092 IMAP URL Scheme
24
***************************************************************************/
28
#ifndef CURL_DISABLE_IMAP
39
#ifdef HAVE_SYS_SOCKET_H
40
#include <sys/socket.h>
42
#ifdef HAVE_NETINET_IN_H
43
#include <netinet/in.h>
45
#ifdef HAVE_ARPA_INET_H
46
#include <arpa/inet.h>
49
#include <sys/utsname.h>
59
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
61
#define in_addr_t unsigned long
64
#include <curl/curl.h>
67
#include "easyif.h" /* for Curl_convert_... prototypes */
74
#include "http.h" /* for HTTP proxy tunnel stuff */
78
#include "strtoofft.h"
87
#include "strtoofft.h"
89
#define _MPRINTF_REPLACE /* use our functions only */
90
#include <curl/mprintf.h>
92
#include "curl_memory.h"
93
/* The last #include file should be: */
96
/* Local API functions */
97
static CURLcode imap_parse_url_path(struct connectdata *conn);
98
static CURLcode imap_regular_transfer(struct connectdata *conn, bool *done);
99
static CURLcode imap_do(struct connectdata *conn, bool *done);
100
static CURLcode imap_done(struct connectdata *conn,
101
CURLcode, bool premature);
102
static CURLcode imap_connect(struct connectdata *conn, bool *done);
103
static CURLcode imap_disconnect(struct connectdata *conn);
104
static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done);
105
static int imap_getsock(struct connectdata *conn,
106
curl_socket_t *socks,
108
static CURLcode imap_doing(struct connectdata *conn,
110
static CURLcode imap_setup_connection(struct connectdata * conn);
113
* IMAP protocol handler.
116
const struct Curl_handler Curl_handler_imap = {
118
imap_setup_connection, /* setup_connection */
120
imap_done, /* done */
121
ZERO_NULL, /* do_more */
122
imap_connect, /* connect_it */
123
imap_multi_statemach, /* connecting */
124
imap_doing, /* doing */
125
imap_getsock, /* proto_getsock */
126
imap_getsock, /* doing_getsock */
127
ZERO_NULL, /* perform_getsock */
128
imap_disconnect, /* disconnect */
129
PORT_IMAP, /* defport */
130
PROT_IMAP /* protocol */
136
* IMAPS protocol handler.
139
const struct Curl_handler Curl_handler_imaps = {
140
"IMAPS", /* scheme */
141
imap_setup_connection, /* setup_connection */
143
imap_done, /* done */
144
ZERO_NULL, /* do_more */
145
imap_connect, /* connect_it */
146
imap_multi_statemach, /* connecting */
147
imap_doing, /* doing */
148
imap_getsock, /* proto_getsock */
149
imap_getsock, /* doing_getsock */
150
ZERO_NULL, /* perform_getsock */
151
imap_disconnect, /* disconnect */
152
PORT_IMAPS, /* defport */
153
PROT_IMAP | PROT_IMAPS | PROT_SSL /* protocol */
157
#ifndef CURL_DISABLE_HTTP
159
* HTTP-proxyed IMAP protocol handler.
162
static const struct Curl_handler Curl_handler_imap_proxy = {
164
ZERO_NULL, /* setup_connection */
165
Curl_http, /* do_it */
166
Curl_http_done, /* done */
167
ZERO_NULL, /* do_more */
168
ZERO_NULL, /* connect_it */
169
ZERO_NULL, /* connecting */
170
ZERO_NULL, /* doing */
171
ZERO_NULL, /* proto_getsock */
172
ZERO_NULL, /* doing_getsock */
173
ZERO_NULL, /* perform_getsock */
174
ZERO_NULL, /* disconnect */
175
PORT_IMAP, /* defport */
176
PROT_HTTP /* protocol */
182
* HTTP-proxyed IMAPS protocol handler.
185
static const struct Curl_handler Curl_handler_imaps_proxy = {
186
"IMAPS", /* scheme */
187
ZERO_NULL, /* setup_connection */
188
Curl_http, /* do_it */
189
Curl_http_done, /* done */
190
ZERO_NULL, /* do_more */
191
ZERO_NULL, /* connect_it */
192
ZERO_NULL, /* connecting */
193
ZERO_NULL, /* doing */
194
ZERO_NULL, /* proto_getsock */
195
ZERO_NULL, /* doing_getsock */
196
ZERO_NULL, /* perform_getsock */
197
ZERO_NULL, /* disconnect */
198
PORT_IMAPS, /* defport */
199
PROT_HTTP /* protocol */
204
/***********************************************************************
208
* Sends the formated string as an IMAP command to a server
210
* NOTE: we build the command in a fixed-length buffer, which sets length
211
* restrictions on the command!
213
* Designed to never block.
215
static CURLcode imapsendf(struct connectdata *conn,
216
const char *idstr, /* id to wait for at the
217
completion of this command */
218
const char *fmt, ...)
221
struct imap_conn *imapc = &conn->proto.imapc;
225
imapc->idstr = idstr; /* this is the thing */
227
res = Curl_pp_vsendf(&imapc->pp, fmt, ap);
234
static const char *getcmdid(struct connectdata *conn)
236
static const char * const ids[]= {
243
struct imap_conn *imapc = &conn->proto.imapc;
245
/* get the next id, but wrap at end of table */
246
imapc->cmdid = (int)((imapc->cmdid+1) % (sizeof(ids)/sizeof(ids[0])));
248
return ids[imapc->cmdid];
251
/* For the IMAP "protocol connect" and "doing" phases only */
252
static int imap_getsock(struct connectdata *conn,
253
curl_socket_t *socks,
256
return Curl_pp_getsock(&conn->proto.imapc.pp, socks, numsocks);
259
/* fucntion that checks for an imap status code at the start of the
261
static int imap_endofresp(struct pingpong *pp, int *resp)
263
char *line = pp->linestart_resp;
264
size_t len = pp->nread_resp;
265
struct imap_conn *imapc = &pp->conn->proto.imapc;
266
const char *id = imapc->idstr;
267
size_t id_len = strlen(id);
269
if(len >= id_len + 3) {
270
if(!memcmp(id, line, id_len) && (line[id_len] == ' ') ) {
271
/* end of response */
272
*resp = line[id_len+1]; /* O, N or B */
275
else if((imapc->state == IMAP_FETCH) &&
276
!memcmp("* ", line, 2) ) {
277
/* FETCH response we're interested in */
282
return FALSE; /* nothing for us */
285
/* This is the ONLY way to change IMAP state! */
286
static void state(struct connectdata *conn,
289
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
290
/* for debug purposes */
291
static const char * const names[]={
302
struct imap_conn *imapc = &conn->proto.imapc;
303
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
304
if(imapc->state != newstate)
305
infof(conn->data, "IMAP %p state change from %s to %s\n",
306
imapc, names[imapc->state], names[newstate]);
308
imapc->state = newstate;
311
static CURLcode imap_state_login(struct connectdata *conn)
314
struct FTP *imap = conn->data->state.proto.imap;
317
str = getcmdid(conn);
319
/* send USER and password */
320
result = imapsendf(conn, str, "%s LOGIN %s %s", str,
321
imap->user?imap->user:"",
322
imap->passwd?imap->passwd:"");
326
state(conn, IMAP_LOGIN);
331
/* for STARTTLS responses */
332
static CURLcode imap_state_starttls_resp(struct connectdata *conn,
336
CURLcode result = CURLE_OK;
337
struct SessionHandle *data = conn->data;
338
(void)instate; /* no use for this yet */
340
if(imapcode != 'O') {
341
failf(data, "STARTTLS denied. %c", imapcode);
342
result = CURLE_LOGIN_DENIED;
345
/* Curl_ssl_connect is BLOCKING */
346
result = Curl_ssl_connect(conn, FIRSTSOCKET);
347
if(CURLE_OK == result) {
348
conn->protocol |= PROT_IMAPS;
349
result = imap_state_login(conn);
352
state(conn, IMAP_STOP);
356
/* for LOGIN responses */
357
static CURLcode imap_state_login_resp(struct connectdata *conn,
361
CURLcode result = CURLE_OK;
362
struct SessionHandle *data = conn->data;
363
(void)instate; /* no use for this yet */
365
if(imapcode != 'O') {
366
failf(data, "Access denied. %c", imapcode);
367
result = CURLE_LOGIN_DENIED;
370
state(conn, IMAP_STOP);
374
/* for the (first line of) FETCH BODY[TEXT] response */
375
static CURLcode imap_state_fetch_resp(struct connectdata *conn,
379
CURLcode result = CURLE_OK;
380
struct SessionHandle *data = conn->data;
381
struct imap_conn *imapc = &conn->proto.imapc;
382
struct FTP *imap = data->state.proto.imap;
383
struct pingpong *pp = &imapc->pp;
384
const char *ptr = data->state.buffer;
385
(void)instate; /* no use for this yet */
387
if('*' != imapcode) {
388
Curl_pgrsSetDownloadSize(data, 0);
389
state(conn, IMAP_STOP);
393
/* Something like this comes "* 1 FETCH (BODY[TEXT] {2021}\r" */
394
while(*ptr && (*ptr != '{'))
398
curl_off_t filesize = curlx_strtoofft(ptr+1, NULL, 10);
400
Curl_pgrsSetDownloadSize(data, filesize);
402
infof(data, "Found %" FORMAT_OFF_TU " bytes to download\n", filesize);
405
/* At this point there is a bunch of data in the header "cache" that is
406
actually body content, send it as body and then skip it. Do note
407
that there may even be additional "headers" after the body. */
408
size_t chunk = pp->cache_size;
410
if(chunk > (size_t)filesize)
411
/* the conversion from curl_off_t to size_t is always fine here */
412
chunk = (size_t)filesize;
414
result = Curl_client_write(conn, CLIENTWRITE_BODY, pp->cache, chunk);
420
/* we've now used parts of or the entire cache */
421
if(pp->cache_size > chunk) {
422
/* part of, move the trailing data to the start and reduce the size */
423
memmove(pp->cache, pp->cache+chunk,
424
pp->cache_size - chunk);
425
pp->cache_size -= chunk;
428
/* cache is drained */
435
infof(data, "Filesize left: %" FORMAT_OFF_T "\n", filesize);
438
/* the entire data is already transfered! */
439
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
442
Curl_setup_transfer(conn, FIRSTSOCKET, filesize, FALSE,
443
imap->bytecountp, -1, NULL); /* no upload here */
445
data->req.maxdownload = filesize;
448
/* We don't know how to parse this line */
449
result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: fix this code */
451
state(conn, IMAP_STOP);
455
/* start the DO phase */
456
static CURLcode imap_select(struct connectdata *conn)
458
CURLcode result = CURLE_OK;
459
struct imap_conn *imapc = &conn->proto.imapc;
462
str = getcmdid(conn);
464
result = imapsendf(conn, str, "%s SELECT %s", str,
465
imapc->mailbox?imapc->mailbox:"");
469
state(conn, IMAP_SELECT);
473
static CURLcode imap_fetch(struct connectdata *conn)
475
CURLcode result = CURLE_OK;
478
str = getcmdid(conn);
480
/* TODO: make this select the correct mail
481
* Use "1 body[text]" to get the full mail body of mail 1
483
result = imapsendf(conn, str, "%s FETCH 1 BODY[TEXT]", str);
488
* When issued, the server will respond with a single line similar to
489
* '* 1 FETCH (BODY[TEXT] {2021}'
491
* Identifying the fetch and how many bytes of contents we can expect. We
492
* must extract that number before continuing to "download as usual".
495
state(conn, IMAP_FETCH);
499
/* for SELECT responses */
500
static CURLcode imap_state_select_resp(struct connectdata *conn,
504
CURLcode result = CURLE_OK;
505
struct SessionHandle *data = conn->data;
506
(void)instate; /* no use for this yet */
508
if(imapcode != 'O') {
509
failf(data, "Select failed");
510
result = CURLE_LOGIN_DENIED;
513
result = imap_fetch(conn);
517
static CURLcode imap_statemach_act(struct connectdata *conn)
520
curl_socket_t sock = conn->sock[FIRSTSOCKET];
521
struct SessionHandle *data=conn->data;
523
struct imap_conn *imapc = &conn->proto.imapc;
524
struct pingpong *pp = &imapc->pp;
528
return Curl_pp_flushsend(pp);
530
/* we read a piece of response */
531
result = Curl_pp_readresp(sock, pp, &imapcode, &nread);
536
/* we have now received a full IMAP server response */
537
switch(imapc->state) {
538
case IMAP_SERVERGREET:
539
if(imapcode != 'O') {
540
failf(data, "Got unexpected imap-server response");
541
return CURLE_FTP_WEIRD_SERVER_REPLY;
544
if(data->set.ftp_ssl && !conn->ssl[FIRSTSOCKET].use) {
545
/* We don't have a SSL/TLS connection yet, but SSL is requested. Switch
546
to TLS connection now */
549
str = getcmdid(conn);
550
result = imapsendf(conn, str, "%s STARTTLS", str);
551
state(conn, IMAP_STARTTLS);
554
result = imap_state_login(conn);
560
result = imap_state_login_resp(conn, imapcode, imapc->state);
564
result = imap_state_starttls_resp(conn, imapcode, imapc->state);
568
result = imap_state_fetch_resp(conn, imapcode, imapc->state);
572
result = imap_state_select_resp(conn, imapcode, imapc->state);
576
/* fallthrough, just stop! */
579
state(conn, IMAP_STOP);
586
/* called repeatedly until done from multi.c */
587
static CURLcode imap_multi_statemach(struct connectdata *conn,
590
struct imap_conn *imapc = &conn->proto.imapc;
591
CURLcode result = Curl_pp_multi_statemach(&imapc->pp);
593
*done = (bool)(imapc->state == IMAP_STOP);
598
static CURLcode imap_easy_statemach(struct connectdata *conn)
600
struct imap_conn *imapc = &conn->proto.imapc;
601
struct pingpong *pp = &imapc->pp;
602
CURLcode result = CURLE_OK;
604
while(imapc->state != IMAP_STOP) {
605
result = Curl_pp_easy_statemach(pp);
614
* Allocate and initialize the struct IMAP for the current SessionHandle. If
617
static CURLcode imap_init(struct connectdata *conn)
619
struct SessionHandle *data = conn->data;
620
struct FTP *imap = data->state.proto.imap;
622
imap = data->state.proto.imap = calloc(sizeof(struct FTP), 1);
624
return CURLE_OUT_OF_MEMORY;
627
/* get some initial data into the imap struct */
628
imap->bytecountp = &data->req.bytecount;
630
/* No need to duplicate user+password, the connectdata struct won't change
631
during a session, but we re-init them here since on subsequent inits
632
since the conn struct may have changed or been replaced.
634
imap->user = conn->user;
635
imap->passwd = conn->passwd;
641
* imap_connect() should do everything that is to be considered a part of
642
* the connection phase.
644
* The variable 'done' points to will be TRUE if the protocol-layer connect
645
* phase is done when this function returns, or FALSE is not. When called as
646
* a part of the easy interface, it will always be TRUE.
648
static CURLcode imap_connect(struct connectdata *conn,
649
bool *done) /* see description above */
652
struct imap_conn *imapc = &conn->proto.imapc;
653
struct SessionHandle *data=conn->data;
654
struct pingpong *pp = &imapc->pp;
656
*done = FALSE; /* default to not done yet */
658
/* If there already is a protocol-specific struct allocated for this
659
sessionhandle, deal with it */
660
Curl_reset_reqproto(conn);
662
result = imap_init(conn);
663
if(CURLE_OK != result)
666
/* We always support persistant connections on imap */
667
conn->bits.close = FALSE;
669
pp->response_time = RESP_TIMEOUT; /* set default response time-out */
670
pp->statemach_act = imap_statemach_act;
671
pp->endofresp = imap_endofresp;
674
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_PROXY)
675
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
676
/* for IMAP over HTTP proxy */
677
struct HTTP http_proxy;
678
struct FTP *imap_save;
681
/* We want "seamless" IMAP operations through HTTP proxy tunnel */
683
/* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member
684
* conn->proto.http; we want IMAP through HTTP and we have to change the
685
* member temporarily for connecting to the HTTP proxy. After
686
* Curl_proxyCONNECT we have to set back the member to the original struct
689
imap_save = data->state.proto.imap;
690
memset(&http_proxy, 0, sizeof(http_proxy));
691
data->state.proto.http = &http_proxy;
693
result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
694
conn->host.name, conn->remote_port);
696
data->state.proto.imap = imap_save;
698
if(CURLE_OK != result)
701
#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_PROXY */
703
if(conn->protocol & PROT_IMAPS) {
705
/* IMAPS is simply imap with SSL for the control channel */
706
/* now, perform the SSL initialization for this socket */
707
result = Curl_ssl_connect(conn, FIRSTSOCKET);
712
Curl_pp_init(pp); /* init generic pingpong data */
714
/* When we connect, we start in the state where we await the server greeting
716
state(conn, IMAP_SERVERGREET);
717
imapc->idstr = "*"; /* we start off waiting for a '*' response */
719
if(data->state.used_interface == Curl_if_multi)
720
result = imap_multi_statemach(conn, done);
722
result = imap_easy_statemach(conn);
730
/***********************************************************************
734
* The DONE function. This does what needs to be done after a single DO has
737
* Input argument is already checked for validity.
739
static CURLcode imap_done(struct connectdata *conn, CURLcode status,
742
struct SessionHandle *data = conn->data;
743
struct FTP *imap = data->state.proto.imap;
744
CURLcode result=CURLE_OK;
748
/* When the easy handle is removed from the multi while libcurl is still
749
* trying to resolve the host name, it seems that the imap struct is not
750
* yet initialized, but the removal action calls Curl_done() which calls
751
* this function. So we simply return success if no imap pointer is set.
756
conn->bits.close = TRUE; /* marked for closure */
757
result = status; /* use the already set error code */
760
/* clear these for next connection */
761
imap->transfer = FTPTRANSFER_BODY;
766
/***********************************************************************
770
* This is the actual DO function for IMAP. Get a file/directory according to
771
* the options previously setup.
775
CURLcode imap_perform(struct connectdata *conn,
776
bool *connected, /* connect status after PASV / PORT */
779
/* this is IMAP and no proxy */
780
CURLcode result=CURLE_OK;
782
DEBUGF(infof(conn->data, "DO phase starts\n"));
784
if(conn->data->set.opt_no_body) {
785
/* requested no body means no transfer... */
786
struct FTP *imap = conn->data->state.proto.imap;
787
imap->transfer = FTPTRANSFER_INFO;
790
*dophase_done = FALSE; /* not done yet */
792
/* start the first command in the DO phase */
793
result = imap_select(conn);
797
/* run the state-machine */
798
if(conn->data->state.used_interface == Curl_if_multi)
799
result = imap_multi_statemach(conn, dophase_done);
801
result = imap_easy_statemach(conn);
802
*dophase_done = TRUE; /* with the easy interface we are done here */
804
*connected = conn->bits.tcpconnect;
807
DEBUGF(infof(conn->data, "DO phase is complete\n"));
812
/***********************************************************************
816
* This function is registered as 'curl_do' function. It decodes the path
817
* parts etc as a wrapper to the actual DO function (imap_perform).
819
* The input argument is already checked for validity.
821
static CURLcode imap_do(struct connectdata *conn, bool *done)
823
CURLcode retcode = CURLE_OK;
825
*done = FALSE; /* default to false */
828
Since connections can be re-used between SessionHandles, this might be a
829
connection already existing but on a fresh SessionHandle struct so we must
830
make sure we have a good 'struct IMAP' to play with. For new connections,
831
the struct IMAP is allocated and setup in the imap_connect() function.
833
Curl_reset_reqproto(conn);
834
retcode = imap_init(conn);
838
retcode = imap_parse_url_path(conn);
842
retcode = imap_regular_transfer(conn, done);
847
/***********************************************************************
851
* This should be called before calling sclose(). We should then wait for the
852
* response from the server before returning. The calling code should then try
853
* to close the connection.
856
static CURLcode imap_logout(struct connectdata *conn)
858
CURLcode result = CURLE_OK;
861
str = getcmdid(conn);
863
result = imapsendf(conn, str, "%s LOGOUT", str, NULL);
866
state(conn, IMAP_LOGOUT);
868
result = imap_easy_statemach(conn);
873
/***********************************************************************
877
* Disconnect from an IMAP server. Cleanup protocol-specific per-connection
878
* resources. BLOCKING.
880
static CURLcode imap_disconnect(struct connectdata *conn)
882
struct imap_conn *imapc= &conn->proto.imapc;
884
/* The IMAP session may or may not have been allocated/setup at this
887
(void)imap_logout(conn); /* ignore errors on the LOGOUT */
889
Curl_pp_disconnect(&imapc->pp);
891
Curl_safefree(imapc->mailbox);
896
/***********************************************************************
898
* imap_parse_url_path()
900
* Parse the URL path into separate path components.
903
static CURLcode imap_parse_url_path(struct connectdata *conn)
905
/* the imap struct is already inited in imap_connect() */
906
struct imap_conn *imapc = &conn->proto.imapc;
907
struct SessionHandle *data = conn->data;
908
const char *path = data->state.path;
914
/* url decode the path and use this mailbox */
915
imapc->mailbox = curl_easy_unescape(data, path, 0, &len);
917
return CURLE_OUT_OF_MEMORY;
922
/* call this when the DO phase has completed */
923
static CURLcode imap_dophase_done(struct connectdata *conn,
926
struct FTP *imap = conn->data->state.proto.imap;
929
if(imap->transfer != FTPTRANSFER_BODY)
930
/* no data to transfer */
931
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
936
/* called from multi.c while DOing */
937
static CURLcode imap_doing(struct connectdata *conn,
941
result = imap_multi_statemach(conn, dophase_done);
944
result = imap_dophase_done(conn, FALSE /* not connected */);
946
DEBUGF(infof(conn->data, "DO phase is complete\n"));
951
/***********************************************************************
953
* imap_regular_transfer()
955
* The input argument is already checked for validity.
957
* Performs all commands done before a regular transfer between a local and a
962
CURLcode imap_regular_transfer(struct connectdata *conn,
965
CURLcode result=CURLE_OK;
966
bool connected=FALSE;
967
struct SessionHandle *data = conn->data;
968
data->req.size = -1; /* make sure this is unknown at this point */
970
Curl_pgrsSetUploadCounter(data, 0);
971
Curl_pgrsSetDownloadCounter(data, 0);
972
Curl_pgrsSetUploadSize(data, 0);
973
Curl_pgrsSetDownloadSize(data, 0);
975
result = imap_perform(conn,
976
&connected, /* have we connected after PASV/PORT */
977
dophase_done); /* all commands in the DO-phase done? */
979
if(CURLE_OK == result) {
982
/* the DO phase has not completed yet */
985
result = imap_dophase_done(conn, connected);
993
static CURLcode imap_setup_connection(struct connectdata * conn)
995
struct SessionHandle *data = conn->data;
997
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
998
/* Unless we have asked to tunnel imap operations through the proxy, we
999
switch and use HTTP operations only */
1000
#ifndef CURL_DISABLE_HTTP
1001
if(conn->handler == &Curl_handler_imap)
1002
conn->handler = &Curl_handler_imap_proxy;
1005
conn->handler = &Curl_handler_imaps_proxy;
1007
failf(data, "IMAPS not supported!");
1008
return CURLE_UNSUPPORTED_PROTOCOL;
1012
* We explicitly mark this connection as persistent here as we're doing
1013
* IMAP over HTTP and thus we accidentally avoid setting this value
1016
conn->bits.close = FALSE;
1018
failf(data, "IMAP over http proxy requires HTTP support built-in!");
1019
return CURLE_UNSUPPORTED_PROTOCOL;
1023
data->state.path++; /* don't include the initial slash */
1028
#endif /* CURL_DISABLE_IMAP */