Browse Source

more sophisticated CAPABILITY handling. also, don't issue the command if

the initial response already had it in the status code.
0.9
Oswald Buddenhagen 21 years ago
parent
commit
a52fd7dde0
  1. 83
      src/imap.c
  2. 17
      src/isync.h

83
src/imap.c

@ -42,6 +42,10 @@
# include <openssl/err.h>
#endif
#define as(ar) (sizeof(ar)/sizeof(ar[0]))
#define CAP(cap) (imap->caps & (1 << (cap)))
static int Tag;
const char *Flags[] = {
@ -395,14 +399,44 @@ parse_fetch (imap_t *imap, char *cmd)
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_response_code (imap_t * imap, char *s)
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
parse_response_code (imap_t * imap, char *s)
{
char *arg, *p;
if (*s != '[')
return; /* no response code */
s++;
if (!(p = strchr (s, ']')))
{
fprintf (stderr, "IMAP error: malformed response code\n");
return;
}
*p++ = 0;
arg = next_arg (&s);
@ -411,12 +445,17 @@ parse_response_code (imap_t * imap, char *s)
arg = next_arg (&s);
imap->uidvalidity = atol (arg);
}
else if (!strcmp ("CAPABILITY", arg))
{
parse_capability (imap, s);
}
else if (!strcmp ("ALERT", arg))
{
/* RFC2060 says that these messages MUST be displayed
* 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))
{
while ((arg = next_arg (&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
}
parse_capability (imap, cmd);
}
else if (!strcmp ("LIST", arg))
{
@ -736,8 +761,8 @@ imap_connect (config_t * cfg)
fprintf (stderr, "IMAP error: unknown greeting response\n");
goto bail;
}
/* let's see what this puppy can do... */
if (imap_exec (imap, "CAPABILITY"))
parse_response_code (imap, rsp);
if (!imap->caps && imap_exec (imap, "CAPABILITY"))
goto bail;
if (!preauth)
@ -749,7 +774,7 @@ imap_connect (config_t * cfg)
if (cfg->use_sslv2 || cfg->use_sslv3 || cfg->use_tlsv1)
{
/* always try to select SSL support if available */
if (imap->have_starttls)
if (CAP(STARTTLS))
{
if (imap_exec (imap, "STARTTLS"))
goto bail;
@ -757,14 +782,6 @@ imap_connect (config_t * cfg)
goto bail;
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"))
goto bail;
}
@ -817,7 +834,7 @@ imap_connect (config_t * cfg)
}
#if HAVE_LIBSSL
if (imap->have_cram)
if (CAP(CRAM))
{
info ("Authenticating with CRAM-MD5\n");
imap->cram = 1;
@ -832,7 +849,7 @@ imap_connect (config_t * cfg)
else
#endif
{
if (imap->have_nologin)
if (CAP(NOLOGIN))
{
fprintf (stderr, "Skipping %s, server forbids LOGIN\n", cfg->path);
goto bail;
@ -850,7 +867,7 @@ imap_connect (config_t * cfg)
} /* !preauth */
/* 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"))
goto bail;
@ -1204,7 +1221,7 @@ imap_append_message (imap_t * imap, int fd, message_t * msg)
}
extra = 0, i = 0;
if (!imap->have_uidplus)
if (!CAP(UIDPLUS))
{
nloop:
start = i;
@ -1266,7 +1283,7 @@ imap_append_message (imap_t * imap, int fd, message_t * msg)
}
i = 0;
if (!imap->have_uidplus)
if (!CAP(UIDPLUS))
{
n1loop:
start = i;

17
src/isync.h

@ -153,17 +153,24 @@ typedef struct
list_t *ns_personal;
list_t *ns_other;
list_t *ns_shared;
unsigned int have_nologin:1;
unsigned int have_uidplus:1;
unsigned int have_namespace:1;
unsigned int caps;
#if HAVE_LIBSSL
unsigned int have_cram:1;
unsigned int have_starttls:1;
unsigned int cram:1;
#endif
}
imap_t;
/* Keep in sync with cap_list */
enum CAPABILITY {
NOLOGIN,
UIDPLUS,
NAMESPACE,
#if HAVE_LIBSSL
CRAM,
STARTTLS,
#endif
};
/* flags for sync_mailbox */
#define SYNC_DELETE (1<<0) /* delete local that don't exist on server */
#define SYNC_EXPUNGE (1<<1) /* don't fetch deleted messages */

Loading…
Cancel
Save