more sophisticated CAPABILITY handling. also, don't issue the command if
the initial response already had it in the status code.
This commit is contained in:
parent
3e392b6aa2
commit
a52fd7dde0
83
src/imap.c
83
src/imap.c
|
@ -42,6 +42,10 @@
|
||||||
# include <openssl/err.h>
|
# include <openssl/err.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define as(ar) (sizeof(ar)/sizeof(ar[0]))
|
||||||
|
|
||||||
|
#define CAP(cap) (imap->caps & (1 << (cap)))
|
||||||
|
|
||||||
static int Tag;
|
static int Tag;
|
||||||
|
|
||||||
const char *Flags[] = {
|
const char *Flags[] = {
|
||||||
|
@ -395,14 +399,44 @@ parse_fetch (imap_t *imap, char *cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Keep this in sync with enum CAPABILITY */
|
||||||
|
const char *cap_list[] = {
|
||||||
|
"LOGINDISABLED",
|
||||||
|
"UIDPLUS",
|
||||||
|
"NAMESPACE",
|
||||||
|
#if HAVE_LIBSSL
|
||||||
|
"AUTH=CRAM-MD5",
|
||||||
|
"STARTTLS",
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_capability (imap_t *imap, char *cmd)
|
||||||
|
{
|
||||||
|
char *arg;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
imap->caps = 0x80000000;
|
||||||
|
while ((arg = next_arg (&cmd)))
|
||||||
|
for (i = 0; i < as(cap_list); i++)
|
||||||
|
if (!strcmp (cap_list[i], arg))
|
||||||
|
imap->caps |= 1 << i;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parse_response_code (imap_t * imap, char *s)
|
parse_response_code (imap_t * imap, char *s)
|
||||||
{
|
{
|
||||||
char *arg;
|
char *arg, *p;
|
||||||
|
|
||||||
if (*s != '[')
|
if (*s != '[')
|
||||||
return; /* no response code */
|
return; /* no response code */
|
||||||
s++;
|
s++;
|
||||||
|
if (!(p = strchr (s, ']')))
|
||||||
|
{
|
||||||
|
fprintf (stderr, "IMAP error: malformed response code\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*p++ = 0;
|
||||||
|
|
||||||
arg = next_arg (&s);
|
arg = next_arg (&s);
|
||||||
|
|
||||||
|
@ -411,12 +445,17 @@ parse_response_code (imap_t * imap, char *s)
|
||||||
arg = next_arg (&s);
|
arg = next_arg (&s);
|
||||||
imap->uidvalidity = atol (arg);
|
imap->uidvalidity = atol (arg);
|
||||||
}
|
}
|
||||||
|
else if (!strcmp ("CAPABILITY", arg))
|
||||||
|
{
|
||||||
|
parse_capability (imap, s);
|
||||||
|
}
|
||||||
else if (!strcmp ("ALERT", arg))
|
else if (!strcmp ("ALERT", arg))
|
||||||
{
|
{
|
||||||
/* RFC2060 says that these messages MUST be displayed
|
/* RFC2060 says that these messages MUST be displayed
|
||||||
* to the user
|
* to the user
|
||||||
*/
|
*/
|
||||||
fprintf (stderr, "*** IMAP ALERT *** %s\n", s);
|
for (; isspace ((unsigned char)*p); p++);
|
||||||
|
fprintf (stderr, "*** IMAP ALERT *** %s\n", p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,21 +516,7 @@ imap_exec (imap_t * imap, const char *fmt, ...)
|
||||||
}
|
}
|
||||||
else if (!strcmp ("CAPABILITY", arg))
|
else if (!strcmp ("CAPABILITY", arg))
|
||||||
{
|
{
|
||||||
while ((arg = next_arg (&cmd)))
|
parse_capability (imap, cmd);
|
||||||
{
|
|
||||||
if (!strcmp ("UIDPLUS", arg))
|
|
||||||
imap->have_uidplus = 1;
|
|
||||||
else if (!strcmp ("NAMESPACE", arg))
|
|
||||||
imap->have_namespace = 1;
|
|
||||||
else if (!strcmp ("LOGINDISABLED", arg))
|
|
||||||
imap->have_nologin = 1;
|
|
||||||
#if HAVE_LIBSSL
|
|
||||||
else if (!strcmp ("STARTTLS", arg))
|
|
||||||
imap->have_starttls = 1;
|
|
||||||
else if (!strcmp ("AUTH=CRAM-MD5", arg))
|
|
||||||
imap->have_cram = 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (!strcmp ("LIST", arg))
|
else if (!strcmp ("LIST", arg))
|
||||||
{
|
{
|
||||||
|
@ -736,8 +761,8 @@ imap_connect (config_t * cfg)
|
||||||
fprintf (stderr, "IMAP error: unknown greeting response\n");
|
fprintf (stderr, "IMAP error: unknown greeting response\n");
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
/* let's see what this puppy can do... */
|
parse_response_code (imap, rsp);
|
||||||
if (imap_exec (imap, "CAPABILITY"))
|
if (!imap->caps && imap_exec (imap, "CAPABILITY"))
|
||||||
goto bail;
|
goto bail;
|
||||||
|
|
||||||
if (!preauth)
|
if (!preauth)
|
||||||
|
@ -749,7 +774,7 @@ imap_connect (config_t * cfg)
|
||||||
if (cfg->use_sslv2 || cfg->use_sslv3 || cfg->use_tlsv1)
|
if (cfg->use_sslv2 || cfg->use_sslv3 || cfg->use_tlsv1)
|
||||||
{
|
{
|
||||||
/* always try to select SSL support if available */
|
/* always try to select SSL support if available */
|
||||||
if (imap->have_starttls)
|
if (CAP(STARTTLS))
|
||||||
{
|
{
|
||||||
if (imap_exec (imap, "STARTTLS"))
|
if (imap_exec (imap, "STARTTLS"))
|
||||||
goto bail;
|
goto bail;
|
||||||
|
@ -757,14 +782,6 @@ imap_connect (config_t * cfg)
|
||||||
goto bail;
|
goto bail;
|
||||||
use_ssl = 1;
|
use_ssl = 1;
|
||||||
|
|
||||||
/* to conform to RFC2595 we need to forget all information
|
|
||||||
* retrieved from CAPABILITY invocations before STARTTLS.
|
|
||||||
*/
|
|
||||||
imap->have_uidplus = 0;
|
|
||||||
imap->have_namespace = 0;
|
|
||||||
imap->have_cram = 0;
|
|
||||||
imap->have_nologin = 0;
|
|
||||||
/* imap->have_starttls = 0; */
|
|
||||||
if (imap_exec (imap, "CAPABILITY"))
|
if (imap_exec (imap, "CAPABILITY"))
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
@ -817,7 +834,7 @@ imap_connect (config_t * cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_LIBSSL
|
#if HAVE_LIBSSL
|
||||||
if (imap->have_cram)
|
if (CAP(CRAM))
|
||||||
{
|
{
|
||||||
info ("Authenticating with CRAM-MD5\n");
|
info ("Authenticating with CRAM-MD5\n");
|
||||||
imap->cram = 1;
|
imap->cram = 1;
|
||||||
|
@ -832,7 +849,7 @@ imap_connect (config_t * cfg)
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (imap->have_nologin)
|
if (CAP(NOLOGIN))
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Skipping %s, server forbids LOGIN\n", cfg->path);
|
fprintf (stderr, "Skipping %s, server forbids LOGIN\n", cfg->path);
|
||||||
goto bail;
|
goto bail;
|
||||||
|
@ -850,7 +867,7 @@ imap_connect (config_t * cfg)
|
||||||
} /* !preauth */
|
} /* !preauth */
|
||||||
|
|
||||||
/* get NAMESPACE info */
|
/* get NAMESPACE info */
|
||||||
if (!global.folder && cfg->use_namespace && imap->have_namespace)
|
if (!global.folder && cfg->use_namespace && CAP(NAMESPACE))
|
||||||
{
|
{
|
||||||
if (imap_exec (imap, "NAMESPACE"))
|
if (imap_exec (imap, "NAMESPACE"))
|
||||||
goto bail;
|
goto bail;
|
||||||
|
@ -1204,7 +1221,7 @@ imap_append_message (imap_t * imap, int fd, message_t * msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
extra = 0, i = 0;
|
extra = 0, i = 0;
|
||||||
if (!imap->have_uidplus)
|
if (!CAP(UIDPLUS))
|
||||||
{
|
{
|
||||||
nloop:
|
nloop:
|
||||||
start = i;
|
start = i;
|
||||||
|
@ -1266,7 +1283,7 @@ imap_append_message (imap_t * imap, int fd, message_t * msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
if (!imap->have_uidplus)
|
if (!CAP(UIDPLUS))
|
||||||
{
|
{
|
||||||
n1loop:
|
n1loop:
|
||||||
start = i;
|
start = i;
|
||||||
|
|
17
src/isync.h
17
src/isync.h
|
@ -153,17 +153,24 @@ typedef struct
|
||||||
list_t *ns_personal;
|
list_t *ns_personal;
|
||||||
list_t *ns_other;
|
list_t *ns_other;
|
||||||
list_t *ns_shared;
|
list_t *ns_shared;
|
||||||
unsigned int have_nologin:1;
|
unsigned int caps;
|
||||||
unsigned int have_uidplus:1;
|
|
||||||
unsigned int have_namespace:1;
|
|
||||||
#if HAVE_LIBSSL
|
#if HAVE_LIBSSL
|
||||||
unsigned int have_cram:1;
|
|
||||||
unsigned int have_starttls:1;
|
|
||||||
unsigned int cram:1;
|
unsigned int cram:1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
imap_t;
|
imap_t;
|
||||||
|
|
||||||
|
/* Keep in sync with cap_list */
|
||||||
|
enum CAPABILITY {
|
||||||
|
NOLOGIN,
|
||||||
|
UIDPLUS,
|
||||||
|
NAMESPACE,
|
||||||
|
#if HAVE_LIBSSL
|
||||||
|
CRAM,
|
||||||
|
STARTTLS,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
/* flags for sync_mailbox */
|
/* flags for sync_mailbox */
|
||||||
#define SYNC_DELETE (1<<0) /* delete local that don't exist on server */
|
#define SYNC_DELETE (1<<0) /* delete local that don't exist on server */
|
||||||
#define SYNC_EXPUNGE (1<<1) /* don't fetch deleted messages */
|
#define SYNC_EXPUNGE (1<<1) /* don't fetch deleted messages */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user