37 #ifndef CURL_DISABLE_IMAP 39 #ifdef HAVE_NETINET_IN_H 40 #include <netinet/in.h> 42 #ifdef HAVE_ARPA_INET_H 43 #include <arpa/inet.h> 46 #include <sys/utsname.h> 56 #if (defined(NETWARE) && defined(__NOVELL_LIBC__)) 58 #define in_addr_t unsigned long 101 static char *
imap_atom(
const char *
str,
bool escape_only);
108 const char *initresp);
166 #define IMAP_RESP_OK 1 167 #define IMAP_RESP_NOT_OK 2 168 #define IMAP_RESP_PREAUTH 3 192 #define imap_to_imaps(x) Curl_nop_stmt 207 const char *end = line +
len;
208 size_t cmd_len = strlen(cmd);
214 if(line < end &&
ISDIGIT(*line)) {
218 while(line < end &&
ISDIGIT(*line));
221 if(line == end || *line !=
' ')
230 (line[cmd_len] ==
' ' || line + cmd_len + 2 == end))
248 const char *
id = imapc->
resptag;
249 size_t id_len = strlen(
id);
252 if(len >= id_len + 1 && !memcmp(
id, line, id_len) && line[id_len] ==
' ') {
256 if(len >= 2 && !memcmp(line,
"OK", 2))
258 else if(len >= 7 && !memcmp(line,
"PREAUTH", 7))
267 if(len >= 2 && !memcmp(
"* ", line, 2)) {
268 switch(imapc->
state) {
278 (strcmp(imap->
custom,
"STORE") ||
280 strcmp(imap->
custom,
"SELECT") &&
281 strcmp(imap->
custom,
"EXAMINE") &&
282 strcmp(imap->
custom,
"SEARCH") &&
283 strcmp(imap->
custom,
"EXPUNGE") &&
284 strcmp(imap->
custom,
"LSUB") &&
285 strcmp(imap->
custom,
"UID") &&
286 strcmp(imap->
custom,
"NOOP")))
318 if(imap && !imap->
custom && ((len == 3 && !memcmp(
"+", line, 1)) ||
319 (len >= 2 && !memcmp(
"+ ", line, 2)))) {
320 switch(imapc->
state) {
328 failf(conn->
data,
"Unexpected continuation response");
348 char *message = NULL;
351 for(message = buffer + 2; *message ==
' ' || *message ==
'\t'; message++)
355 for(len = strlen(message); len--;)
356 if(message[len] !=
'\r' && message[len] !=
'\n' && message[len] !=
' ' &&
357 message[len] !=
'\t')
377 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) 379 static const char *
const names[]={
398 if(imapc->
state != newstate)
399 infof(conn->
data,
"IMAP %p state change from %s to %s\n",
400 (
void *)imapc, names[imapc->
state], names[newstate]);
403 imapc->
state = newstate;
502 result =
imap_sendf(conn,
"LOGIN %s %s", user ? user :
"",
503 passwd ? passwd :
"");
523 const char *initresp)
529 result =
imap_sendf(conn,
"AUTHENTICATE %s %s", mech, initresp);
533 result =
imap_sendf(conn,
"AUTHENTICATE %s", mech);
586 infof(conn->
data,
"No known authentication mechanisms supported!\n");
618 result =
imap_sendf(conn,
"LIST \"%s\" *", mailbox);
649 failf(conn->
data,
"Cannot SELECT without a mailbox.");
659 result =
imap_sendf(conn,
"SELECT %s", mailbox);
682 failf(conn->
data,
"Cannot FETCH without a UID.");
688 result =
imap_sendf(conn,
"FETCH %s BODY[%s]<%s>",
693 result =
imap_sendf(conn,
"FETCH %s BODY[%s]",
718 failf(data,
"Cannot APPEND without a mailbox.");
735 "Mime-Version: 1.0");
753 failf(data,
"Cannot APPEND with unknown input file size\n");
787 failf(conn->
data,
"Cannot SEARCH without a query string.");
831 infof(data,
"PREAUTH connection, already authenticated!\n");
834 failf(data,
"Got unexpected imap-server response");
855 if(imapcode ==
'*') {
861 (*line ==
' ' || *line ==
'\t' ||
862 *line ==
'\r' || *line ==
'\n')) {
871 for(wordlen = 0; line[wordlen] && line[wordlen] !=
' ' &&
872 line[wordlen] !=
'\t' && line[wordlen] !=
'\r' &&
873 line[wordlen] !=
'\n';)
877 if(wordlen == 8 && !memcmp(line,
"STARTTLS", 8))
881 else if(wordlen == 13 && !memcmp(line,
"LOGINDISABLED", 13))
885 else if(wordlen == 7 && !memcmp(line,
"SASL-IR", 7))
889 else if(wordlen > 5 && !memcmp(line,
"AUTH=", 5)) {
891 unsigned int mechbit;
898 if(mechbit && llen == wordlen)
915 failf(data,
"STARTTLS not supported.");
940 failf(data,
"STARTTLS denied");
975 failf(data,
"Authentication cancelled");
997 failf(data,
"Access denied. %c", imapcode);
1014 size_t len = strlen(line);
1018 if(imapcode ==
'*') {
1046 if(imapcode ==
'*') {
1048 if(sscanf(line + 2,
"OK [UIDVALIDITY %19[0123456789]]", tmp) == 1) {
1057 failf(conn->
data,
"Mailbox UIDVALIDITY has changed");
1066 else if(imap->
query)
1073 failf(data,
"Select failed");
1089 bool parsed =
FALSE;
1094 if(imapcode !=
'*') {
1102 while(*ptr && (*ptr !=
'{'))
1108 if(endptr - ptr > 1 && endptr[0] ==
'}' &&
1109 endptr[1] ==
'\r' && endptr[2] ==
'\0')
1125 if(chunk > (
size_t)size)
1137 " bytes are left for transfer\n", (
curl_off_t)chunk,
1203 if(imapcode !=
'+') {
1269 switch(imapc->
state) {
1453 connclose(conn,
"IMAP done with bad status");
1510 bool selected =
FALSE;
1519 *dophase_done =
FALSE;
1536 else if(!imap->
custom && selected && imap->
uid)
1542 else if(imap->
mailbox && !selected &&
1649 else if(*dophase_done) {
1671 bool connected =
FALSE;
1687 if(!result && *dophase_done)
1761 const char atom_specials[] =
"(){ %*]";
1764 size_t backsp_count = 0;
1765 size_t quote_count = 0;
1766 bool others_exists =
FALSE;
1768 char *newstr = NULL;
1781 else if(!escape_only) {
1782 const char *p3 = atom_specials;
1784 while(*p3 && !others_exists) {
1786 others_exists =
TRUE;
1796 if(!backsp_count && !quote_count && !others_exists)
1800 newlen = strlen(str) + backsp_count + quote_count + (escape_only ? 0 : 2);
1803 newstr = (
char *)
malloc((newlen + 1) *
sizeof(char));
1811 newstr[newlen - 1] =
'"';
1818 if(*p1 ==
'\\' || *p1 ==
'"') {
1830 newstr[newlen] =
'\0';
1846 case ':':
case '@':
case '/':
1850 case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
1851 case '7':
case '8':
case '9':
1852 case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
1853 case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
1854 case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
1855 case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
1856 case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
1857 case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
1858 case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
case 'u':
1859 case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
1860 case '-':
case '.':
case '_':
case '~':
1862 case '!':
case '$':
case '\'':
case '(':
case ')':
case '*':
1887 while(!result && ptr && *ptr) {
1891 while(*ptr && *ptr !=
'=')
1896 while(*ptr && *ptr !=
';')
1901 value, ptr - value);
1938 const char *
ptr = begin;
1946 const char *end =
ptr;
1947 if(end > begin && end[-1] ==
'/')
1959 while(*ptr ==
';') {
1966 while(*ptr && *ptr !=
'=')
1989 DEBUGF(
infof(conn->
data,
"IMAP URL parameter '%s' = '%s'\n", name, value));
1996 if(valuelen > 0 && value[valuelen - 1] ==
'/')
1997 value[valuelen - 1] =
'\0';
2003 if(valuelen > 0 && value[valuelen - 1] ==
'/')
2004 value[valuelen - 1] =
'\0';
2010 if(valuelen > 0 && value[valuelen - 1] ==
'/')
2011 value[valuelen - 1] =
'\0';
2017 if(valuelen > 0 && value[valuelen - 1] ==
'/')
2018 value[valuelen - 1] =
'\0';
2036 if(imap->
mailbox && !imap->
uid && *ptr ==
'?') {
2075 const char *params = imap->
custom;
2077 while(*params && *params !=
' ')
struct ssl_connect_data ssl[2]
static CURLcode imap_perform_append(struct connectdata *conn)
CURLcode Curl_urldecode(struct Curl_easy *data, const char *string, size_t length, char **ostring, size_t *olen, bool reject_ctrl)
CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part, struct curl_slist *headers, int take_ownership)
static CURLcode imap_setup_connection(struct connectdata *conn)
static CURLcode imap_continue_authenticate(struct connectdata *conn, const char *resp)
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size)
int curlx_sltosi(long slnum)
#define CURL_FORMAT_CURL_OFF_TU
static bool imap_matchresp(const char *line, size_t len, const char *cmd)
CURLcode Curl_pp_disconnect(struct pingpong *pp)
void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused)
static CURLcode imap_state_auth_resp(struct connectdata *conn, int imapcode, imapstate instate)
static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, int *resp)
static CURLcode imap_sendf(struct connectdata *conn, const char *fmt,...)
static const struct SASLproto saslimap
const struct Curl_handler * handler
static CURLcode imap_perform_search(struct connectdata *conn)
CURLcode Curl_pp_vsendf(struct pingpong *pp, const char *fmt, va_list args)
UNITTEST_START char * ptr
static CURLcode imap_state_starttls_resp(struct connectdata *conn, int imapcode, imapstate instate)
CURLcode Curl_pp_flushsend(struct pingpong *pp)
CURLcode Curl_mime_prepare_headers(curl_mimepart *part, const char *contenttype, const char *disposition, enum mimestrategy strategy)
curl_pp_transfer transfer
static CURLcode imap_perform_fetch(struct connectdata *conn)
static CURLcode imap_do(struct connectdata *conn, bool *done)
#define Curl_ssl_connect_nonblocking(x, y, z)
void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params)
struct curl_slist * headers
#define strcasecompare(a, b)
#define SASL_AUTH_DEFAULT
UNITTEST_START int result
static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode, imapstate instate)
CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, bool force_ir, saslprogress *progress)
static CURLcode imap_statemach_act(struct connectdata *conn)
static CURLcode imap_state_listsearch_resp(struct connectdata *conn, int imapcode, imapstate instate)
static CURLcode imap_state_servergreet_resp(struct connectdata *conn, int imapcode, imapstate instate)
CURLcode(* statemach_act)(struct connectdata *conn)
static CURLcode imap_disconnect(struct connectdata *conn, bool dead)
static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done)
size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream)
static CURLcode imap_perform_authentication(struct connectdata *conn)
static CURLcode imap_perform_starttls(struct connectdata *conn)
static CURLcode imap_perform_authenticate(struct connectdata *conn, const char *mech, const char *initresp)
void Curl_setup_transfer(struct connectdata *conn, int sockindex, curl_off_t size, bool getheader, curl_off_t *bytecountp, int writesockindex, curl_off_t *writecountp)
static bool imap_is_bchar(char ch)
curl_easy_setopt expects a curl_off_t argument for this option curl_easy_setopt expects a curl_write_callback argument for this option curl_easy_setopt expects a curl_ioctl_callback argument for this option curl_easy_setopt expects a curl_opensocket_callback argument for this option curl_easy_setopt expects a curl_debug_callback argument for this option curl_easy_setopt expects a curl_conv_callback argument for this option curl_easy_setopt expects a private data pointer as argument for this option curl_easy_setopt expects a FILE *argument for this option curl_easy_setopt expects a struct curl_httppost *argument for this option curl_easy_setopt expects a struct curl_slist *argument for this option curl_easy_getinfo expects a pointer to char *for this info curl_easy_getinfo expects a pointer to double for this info curl_easy_getinfo expects a pointer to struct curl_tlssessioninfo *for this info curl_easy_getinfo expects a pointer to curl_socket_t for this info size_t
CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt,...)
static CURLcode imap_state_login_resp(struct connectdata *conn, int imapcode, imapstate instate)
bool(* endofresp)(struct connectdata *conn, char *ptr, size_t len, int *code)
CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
CURLcode Curl_mime_rewind(curl_mimepart *part)
static CURLcode imap_perform_logout(struct connectdata *conn)
char * mailbox_uidvalidity
CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, int code, saslprogress *progress)
bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn)
unsigned int Curl_sasl_decode_mech(const char *ptr, size_t maxlen, size_t *len)
CURLofft curlx_strtoofft(const char *str, char **endp, int base, curl_off_t *num)
#define strncasecompare(a, b, c)
static CURLcode imap_connect(struct connectdata *conn, bool *done)
static CURLcode imap_perform_capability(struct connectdata *conn)
const struct Curl_handler Curl_handler_imap
void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size)
static void imap_get_message(char *buffer, char **outptr)
void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size)
CURL_TYPEOF_CURL_OFF_T curl_off_t
size_t(* curl_read_callback)(char *buffer, size_t size, size_t nitems, void *instream)
static CURLcode imap_init(struct connectdata *conn)
static CURLcode imap_state_append_final_resp(struct connectdata *conn, int imapcode, imapstate instate)
static CURLcode imap_done(struct connectdata *conn, CURLcode status, bool premature)
static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode, imapstate instate)
CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr, size_t len)
static char * imap_atom(const char *str, bool escape_only)
static CURLcode imap_perform_login(struct connectdata *conn)
#define Curl_safefree(ptr)
int Curl_pp_getsock(struct pingpong *pp, curl_socket_t *socks, int numsocks)
bool Curl_pp_moredata(struct pingpong *pp)
curl_off_t Curl_mime_size(curl_mimepart *part)
static CURLcode imap_perform_upgrade_tls(struct connectdata *conn)
static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode, imapstate instate)
static CURLcode imap_state_capability_resp(struct connectdata *conn, int imapcode, imapstate instate)
static CURLcode imap_perform_list(struct connectdata *conn)
char * Curl_checkheaders(const struct connectdata *conn, const char *thisheader)
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
void Curl_pp_init(struct pingpong *pp)
static CURLcode imap_parse_url_options(struct connectdata *conn)
struct connectdata * conn
static CURLcode imap_dophase_done(struct connectdata *conn, bool connected)
CURLcode Curl_pp_sendf(struct pingpong *pp, const char *fmt,...)
UNITTEST_START int * value
static CURLcode imap_regular_transfer(struct connectdata *conn, bool *done)
curl_read_callback fread_func
static int imap_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks)
static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done)
struct curl_slist * curlheaders
#define PROTOPT_URLOPTIONS
CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl, const char *value, size_t len)
static CURLcode imap_perform_select(struct connectdata *conn)
static CURLcode imap_parse_custom_request(struct connectdata *conn)
union connectdata::@34 proto
CURLcode Curl_pp_readresp(curl_socket_t sockfd, struct pingpong *pp, int *code, size_t *size)
static CURLcode imap_block_statemach(struct connectdata *conn)
const struct Curl_handler Curl_handler_imaps
static CURLcode imap_perform(struct connectdata *conn, bool *connected, bool *dophase_done)
static CURLcode imap_state_fetch_final_resp(struct connectdata *conn, int imapcode, imapstate instate)
#define IMAP_RESP_PREAUTH
#define PROTOPT_CLOSEACTION
static void state(struct connectdata *conn, imapstate newstate)
#define IMAP_TYPE_CLEARTEXT
static CURLcode imap_parse_url_path(struct connectdata *conn)
#define calloc(nbelem, size)
#define CURL_FORMAT_CURL_OFF_T