summaryrefslogtreecommitdiffstats
path: root/imap
diff options
context:
space:
mode:
authorThomas Roessler <roessler@does-not-exist.org>2001-02-12 10:27:10 +0000
committerThomas Roessler <roessler@does-not-exist.org>2001-02-12 10:27:10 +0000
commita632b853e8703cc0ad16c95d8411c5bc6252874a (patch)
tree1d7e0d423c562146ba035af31188c6f16e656955 /imap
parentdf825439c00aa31bbbab2d54a5c25b02cd82d4e2 (diff)
Brendan Cully's SASL patch.
Diffstat (limited to 'imap')
-rw-r--r--imap/auth_login.c5
-rw-r--r--imap/auth_sasl.c50
-rw-r--r--imap/browse.c13
-rw-r--r--imap/command.c93
-rw-r--r--imap/imap.c118
-rw-r--r--imap/imap_private.h36
-rw-r--r--imap/message.c34
-rw-r--r--imap/util.c79
8 files changed, 226 insertions, 202 deletions
diff --git a/imap/auth_login.c b/imap/auth_login.c
index fff5baa6..212d7fde 100644
--- a/imap/auth_login.c
+++ b/imap/auth_login.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999-2000 Brendan Cully <brendan@kublai.com>
+ * Copyright (C) 1999-2001 Brendan Cully <brendan@kublai.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -60,9 +60,6 @@ imap_auth_res_t imap_auth_login (IMAP_DATA* idata)
if (!rc)
return IMAP_AUTH_SUCCESS;
- else if (rc == -1)
- dprint (1, (debugfile, "imap_auth_login: Error logging in.\n"));
-
mutt_error _("Login failed.");
sleep (2);
return IMAP_AUTH_FAILURE;
diff --git a/imap/auth_sasl.c b/imap/auth_sasl.c
index 55885e2c..75d0659c 100644
--- a/imap/auth_sasl.c
+++ b/imap/auth_sasl.c
@@ -23,9 +23,6 @@
#include "imap_private.h"
#include "auth.h"
-#include <netinet/in.h>
-#include <netdb.h>
-
#include <sasl.h>
#include <saslutil.h>
@@ -44,42 +41,13 @@ imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata)
if (mutt_sasl_start () != SASL_OK)
return IMAP_AUTH_FAILURE;
- /* TODO: set fourth option to SASL_SECURITY_LAYER once we have a wrapper
- * (ie more than auth code) for SASL. */
- rc = sasl_client_new ("imap", idata->conn->account.host,
- mutt_sasl_get_callbacks (&idata->conn->account), SASL_SECURITY_LAYER,
- &saslconn);
-
- if (rc != SASL_OK)
+ if (mutt_sasl_client_new (idata->conn, &saslconn) < 0)
{
- dprint (1, (debugfile, "imap_auth_sasl: Error allocating SASL connection.\n"));
+ dprint (1, (debugfile,
+ "imap_auth_sasl: Error allocating SASL connection.\n"));
return IMAP_AUTH_FAILURE;
}
- /*** set sasl IP properties, necessary for use with krb4 ***/
- {
- struct sockaddr_in local, remote;
- int r, size;
-
- size = sizeof(local);
- r = getsockname(idata->conn->fd, &local, &size);
- if (r!=0) return IMAP_AUTH_FAILURE;
-
- size = sizeof(remote);
- r = getpeername(idata->conn->fd, &remote, &size);
- if (r!=0) return IMAP_AUTH_FAILURE;
-
-#ifdef SASL_IP_LOCAL
- r = sasl_setprop(saslconn, SASL_IP_LOCAL, &local);
- if (r!=0) return IMAP_AUTH_FAILURE;
-#endif
-
-#ifdef SASL_IP_REMOTE
- r = sasl_setprop(saslconn, SASL_IP_REMOTE, &remote);
- if (r!=0) return IMAP_AUTH_FAILURE;
-#endif
- }
-
/* hack for SASL ANONYMOUS support:
* 1. Fetch username. If it's "" or "anonymous" then
* 2. attempt sasl_client_start with only "AUTH=ANONYMOUS" capability
@@ -128,13 +96,13 @@ imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata)
irc = imap_cmd_step (idata);
while (irc == IMAP_CMD_CONTINUE);
- if (irc == IMAP_CMD_FAIL || irc == IMAP_CMD_NO)
+ if (irc == IMAP_CMD_BAD || irc == IMAP_CMD_NO)
goto bail;
if (irc == IMAP_CMD_RESPOND)
{
- if (sasl_decode64 (idata->buf+2, strlen (idata->buf+2), buf, &len) !=
- SASL_OK)
+ if (sasl_decode64 (idata->cmd.buf+2, strlen (idata->cmd.buf+2), buf,
+ &len) != SASL_OK)
{
dprint (1, (debugfile, "imap_auth_sasl: error base64-decoding server response.\n"));
goto bail;
@@ -163,7 +131,7 @@ imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata)
/* sasl_client_st(art|ep) allocate pc with malloc, expect me to
* free it */
- safe_free (&pc);
+ FREE (&pc);
}
if (olen || rc == SASL_CONTINUE)
@@ -179,14 +147,14 @@ imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata)
}
}
- while (irc != IMAP_CMD_DONE)
+ while (irc != IMAP_CMD_OK)
if ((irc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
break;
if (rc != SASL_OK)
goto bail;
- if (imap_code (idata->buf))
+ if (imap_code (idata->cmd.buf))
{
mutt_sasl_setup_conn (idata->conn, saslconn);
return IMAP_AUTH_SUCCESS;
diff --git a/imap/browse.c b/imap/browse.c
index cf7c4bc5..7a31f63d 100644
--- a/imap/browse.c
+++ b/imap/browse.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1996-9 Brandon Long <blong@fiction.net>
- * Copyright (C) 1999-2000 Brendan Cully <brendan@kublai.com>
+ * Copyright (C) 1999-2001 Brendan Cully <brendan@kublai.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -124,7 +124,7 @@ int imap_browse (char* path, struct browser_state* state)
}
}
}
- while (mutt_strncmp (idata->buf, idata->seq, SEQLEN));
+ while (mutt_strncmp (idata->cmd.buf, idata->cmd.seq, SEQLEN));
}
/* if we're descending a folder, mark it as current in browser_state */
@@ -222,7 +222,6 @@ int imap_browse (char* path, struct browser_state* state)
}
}
- mutt_clear_error ();
FREE (&mx.mbox);
return 0;
@@ -316,7 +315,7 @@ static int browse_add_list_result (IMAP_DATA* idata, const char* cmd,
isparent);
}
}
- while ((mutt_strncmp (idata->buf, idata->seq, SEQLEN) != 0));
+ while ((mutt_strncmp (idata->cmd.buf, idata->cmd.seq, SEQLEN) != 0));
FREE (&mx.mbox);
return 0;
@@ -412,7 +411,7 @@ static int browse_get_namespace (IMAP_DATA* idata, char* nsbuf, int nsblen,
if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
break;
- s = imap_next_word (idata->buf);
+ s = imap_next_word (idata->cmd.buf);
if (mutt_strncasecmp ("NAMESPACE", s, 9) == 0)
{
/* There are three sections to the response, User, Other, Shared,
@@ -485,7 +484,7 @@ static int browse_get_namespace (IMAP_DATA* idata, char* nsbuf, int nsblen,
}
while (rc == IMAP_CMD_CONTINUE);
- if (rc != IMAP_CMD_DONE)
+ if (rc != IMAP_CMD_OK)
return -1;
return 0;
@@ -524,7 +523,7 @@ static int browse_verify_namespace (IMAP_DATA* idata,
return -1;
nsi->listable |= (name != NULL);
}
- while ((mutt_strncmp (idata->buf, idata->seq, SEQLEN) != 0));
+ while ((mutt_strncmp (idata->cmd.buf, idata->cmd.seq, SEQLEN) != 0));
}
return 0;
diff --git a/imap/command.c b/imap/command.c
index f26af035..b3c3029a 100644
--- a/imap/command.c
+++ b/imap/command.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
* Copyright (C) 1996-9 Brandon Long <blong@fiction.net>
- * Copyright (C) 1999-2000 Brendan Cully <brendan@kublai.com>
+ * Copyright (C) 1999-2001 Brendan Cully <brendan@kublai.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -35,7 +35,7 @@
static void cmd_finish (IMAP_DATA* idata);
static void cmd_handle_fatal (IMAP_DATA* idata);
static int cmd_handle_untagged (IMAP_DATA* idata);
-static void cmd_make_sequence (char* buf, size_t buflen);
+static void cmd_make_sequence (IMAP_DATA* idata);
static void cmd_parse_capabilities (IMAP_DATA* idata, char* s);
static void cmd_parse_expunge (IMAP_DATA* idata, char* s);
static void cmd_parse_myrights (IMAP_DATA* idata, char* s);
@@ -62,25 +62,25 @@ int imap_cmd_start (IMAP_DATA* idata, const char* cmd)
{
char* out;
int outlen;
- int rc = 0;
+ int rc;
if (idata->status == IMAP_FATAL)
{
cmd_handle_fatal (idata);
- return IMAP_CMD_FAIL;
+ return IMAP_CMD_BAD;
}
- cmd_make_sequence (idata->seq, sizeof (idata->seq));
+ cmd_make_sequence (idata);
/* seq, space, cmd, \r\n\0 */
- outlen = strlen (idata->seq) + strlen (cmd) + 4;
+ outlen = strlen (idata->cmd.seq) + strlen (cmd) + 4;
out = (char*) safe_malloc (outlen);
- snprintf (out, outlen, "%s %s\r\n", idata->seq, cmd);
+ snprintf (out, outlen, "%s %s\r\n", idata->cmd.seq, cmd);
rc = mutt_socket_write (idata->conn, out);
FREE (&out);
- return (rc < 0) ? IMAP_CMD_FAIL : 0;
+ return (rc < 0) ? IMAP_CMD_BAD : 0;
}
/* imap_cmd_step: Reads server responses from an IMAP command, detects
@@ -89,33 +89,35 @@ int imap_cmd_start (IMAP_DATA* idata, const char* cmd)
* large!). */
int imap_cmd_step (IMAP_DATA* idata)
{
+ IMAP_COMMAND* cmd = &idata->cmd;
unsigned int len = 0;
int c;
if (idata->status == IMAP_FATAL)
{
cmd_handle_fatal (idata);
- return IMAP_CMD_FAIL;
+ return IMAP_CMD_BAD;
}
/* read into buffer, expanding buffer as necessary until we have a full
* line */
do
{
- if (len == idata->blen)
+ if (len == cmd->blen)
{
- safe_realloc ((void**) &idata->buf, idata->blen + IMAP_CMD_BUFSIZE);
- idata->blen = idata->blen + IMAP_CMD_BUFSIZE;
- dprint (3, (debugfile, "imap_cmd_step: grew buffer to %u bytes\n", idata->blen));
+ safe_realloc ((void**) &cmd->buf, cmd->blen + IMAP_CMD_BUFSIZE);
+ cmd->blen = cmd->blen + IMAP_CMD_BUFSIZE;
+ dprint (3, (debugfile, "imap_cmd_step: grew buffer to %u bytes\n",
+ cmd->blen));
}
- if ((c = mutt_socket_readln (idata->buf + len, idata->blen - len,
+ if ((c = mutt_socket_readln (cmd->buf + len, cmd->blen - len,
idata->conn)) < 0)
{
dprint (1, (debugfile, "imap_cmd_step: Error while reading server response, closing connection.\n"));
mutt_socket_close (idata->conn);
idata->status = IMAP_FATAL;
- return IMAP_CMD_FAIL;
+ return IMAP_CMD_BAD;
}
len += c;
@@ -123,30 +125,32 @@ int imap_cmd_step (IMAP_DATA* idata)
/* if we've read all the way to the end of the buffer, we haven't read a
* full line (mutt_socket_readln strips the \r, so we always have at least
* one character free when we've read a full line) */
- while (len == idata->blen);
+ while (len == cmd->blen);
- /* don't let one large string make idata->buf hog memory forever */
- if ((idata->blen > IMAP_CMD_BUFSIZE) && (len <= IMAP_CMD_BUFSIZE))
+ /* don't let one large string make cmd->buf hog memory forever */
+ if ((cmd->blen > IMAP_CMD_BUFSIZE) && (len <= IMAP_CMD_BUFSIZE))
{
- safe_realloc ((void**) &idata->buf, IMAP_CMD_BUFSIZE);
- idata->blen = IMAP_CMD_BUFSIZE;
- dprint (3, (debugfile, "imap_cmd_step: shrank buffer to %u bytes\n", idata->blen));
+ safe_realloc ((void**) &cmd->buf, IMAP_CMD_BUFSIZE);
+ cmd->blen = IMAP_CMD_BUFSIZE;
+ dprint (3, (debugfile, "imap_cmd_step: shrank buffer to %u bytes\n", cmd->blen));
}
/* handle untagged messages. The caller still gets its shot afterwards. */
- if (!strncmp (idata->buf, "* ", 2) &&
+ if (!strncmp (cmd->buf, "* ", 2) &&
cmd_handle_untagged (idata))
- return IMAP_CMD_FAIL;
+ return IMAP_CMD_BAD;
/* server demands a continuation response from us */
- if (!strncmp (idata->buf, "+ ", 2))
+ if (!strncmp (cmd->buf, "+ ", 2))
+ {
return IMAP_CMD_RESPOND;
+ }
/* tagged completion code */
- if (!mutt_strncmp (idata->buf, idata->seq, SEQLEN))
+ if (!mutt_strncmp (cmd->buf, cmd->seq, SEQLEN))
{
cmd_finish (idata);
- return imap_code (idata->buf) ? IMAP_CMD_DONE : IMAP_CMD_NO;
+ return imap_code (cmd->buf) ? IMAP_CMD_OK : IMAP_CMD_NO;
}
return IMAP_CMD_CONTINUE;
@@ -181,11 +185,11 @@ int imap_exec (IMAP_DATA* idata, const char* cmd, int flags)
}
/* create sequence for command */
- cmd_make_sequence (idata->seq, sizeof (idata->seq));
+ cmd_make_sequence (idata);
/* seq, space, cmd, \r\n\0 */
- outlen = strlen (idata->seq) + strlen (cmd) + 4;
+ outlen = strlen (idata->cmd.seq) + strlen (cmd) + 4;
out = (char*) safe_malloc (outlen);
- snprintf (out, outlen, "%s %s\r\n", idata->seq, cmd);
+ snprintf (out, outlen, "%s %s\r\n", idata->cmd.seq, cmd);
rc = mutt_socket_write_d (idata->conn, out,
flags & IMAP_CMD_PASS ? IMAP_LOG_PASS : IMAP_LOG_CMD);
@@ -201,15 +205,15 @@ int imap_exec (IMAP_DATA* idata, const char* cmd, int flags)
if (rc == IMAP_CMD_NO && (flags & IMAP_CMD_FAIL_OK))
return -2;
- if (rc != IMAP_CMD_DONE)
+ if (rc != IMAP_CMD_OK)
{
char *pc;
if (flags & IMAP_CMD_FAIL_OK)
return -2;
- dprint (1, (debugfile, "imap_exec: command failed: %s\n", idata->buf));
- pc = idata->buf;
+ dprint (1, (debugfile, "imap_exec: command failed: %s\n", idata->cmd.buf));
+ pc = idata->cmd.buf;
pc = imap_next_word (pc);
mutt_error ("%s", pc);
sleep (2);
@@ -220,16 +224,23 @@ int imap_exec (IMAP_DATA* idata, const char* cmd, int flags)
return 0;
}
+/* imap_cmd_running: Returns whether an IMAP command is in progress. */
+int imap_cmd_running (IMAP_DATA* idata)
+{
+ if (idata->cmd.state == IMAP_CMD_CONTINUE ||
+ idata->cmd.state == IMAP_CMD_RESPOND)
+ return 1;
+
+ return 0;
+}
+
/* cmd_finish: When the caller has finished reading command responses,
* it must call this routine to perform cleanup (eg fetch new mail if
* detected, do expunge). Called automatically by imap_cmd_step */
static void cmd_finish (IMAP_DATA* idata)
{
if (!(idata->state == IMAP_SELECTED) || idata->ctx->closing)
- {
- mutt_clear_error ();
return;
- }
if ((idata->reopen & IMAP_REOPEN_ALLOW) &&
(idata->reopen & (IMAP_EXPUNGE_PENDING|IMAP_NEWMAIL_PENDING)))
@@ -275,7 +286,7 @@ static int cmd_handle_untagged (IMAP_DATA* idata)
char* pn;
int count;
- s = imap_next_word (idata->buf);
+ s = imap_next_word (idata->cmd.buf);
if ((idata->state == IMAP_SELECTED) && isdigit (*s))
{
@@ -360,14 +371,12 @@ static int cmd_handle_untagged (IMAP_DATA* idata)
}
/* cmd_make_sequence: make a tag suitable for starting an IMAP command */
-static void cmd_make_sequence (char* buf, size_t buflen)
+static void cmd_make_sequence (IMAP_DATA* idata)
{
- static int sequence = 0;
-
- snprintf (buf, buflen, "a%04d", sequence++);
+ snprintf (idata->cmd.seq, sizeof (idata->cmd.seq), "a%04d", idata->seqno++);
- if (sequence > 9999)
- sequence = 0;
+ if (idata->seqno > 9999)
+ idata->seqno = 0;
}
/* cmd_parse_capabilities: set capability bits according to CAPABILITY
diff --git a/imap/imap.c b/imap/imap.c
index 4945952f..ba96e782 100644
--- a/imap/imap.c
+++ b/imap/imap.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
* Copyright (C) 1996-9 Brandon Long <blong@fiction.net>
- * Copyright (C) 1999-2000 Brendan Cully <brendan@kublai.com>
+ * Copyright (C) 1999-2001 Brendan Cully <brendan@kublai.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -97,54 +97,6 @@ void imap_logout_all (void)
}
}
-/* imap_parse_date: date is of the form: DD-MMM-YYYY HH:MM:SS +ZZzz */
-time_t imap_parse_date (char *s)
-{
- struct tm t;
- time_t tz;
-
- t.tm_mday = (s[0] == ' '? s[1] - '0' : (s[0] - '0') * 10 + (s[1] - '0'));
- s += 2;
- if (*s != '-')
- return 0;
- s++;
- t.tm_mon = mutt_check_month (s);
- s += 3;
- if (*s != '-')
- return 0;
- s++;
- t.tm_year = (s[0] - '0') * 1000 + (s[1] - '0') * 100 + (s[2] - '0') * 10 + (s[3] - '0') - 1900;
- s += 4;
- if (*s != ' ')
- return 0;
- s++;
-
- /* time */
- t.tm_hour = (s[0] - '0') * 10 + (s[1] - '0');
- s += 2;
- if (*s != ':')
- return 0;
- s++;
- t.tm_min = (s[0] - '0') * 10 + (s[1] - '0');
- s += 2;
- if (*s != ':')
- return 0;
- s++;
- t.tm_sec = (s[0] - '0') * 10 + (s[1] - '0');
- s += 2;
- if (*s != ' ')
- return 0;
- s++;
-
- /* timezone */
- tz = ((s[1] - '0') * 10 + (s[2] - '0')) * 3600 +
- ((s[3] - '0') * 10 + (s[4] - '0')) * 60;
- if (s[0] == '+')
- tz = -tz;
-
- return (mutt_mktime (&t, 0) + tz);
-}
-
/* imap_read_literal: read bytes bytes from server into file. Not explicitly
* buffered, relies on FILE buffering. NOTE: strips \r from \r\n.
* Apparently even literals use \r\n-terminated strings ?! */
@@ -240,7 +192,7 @@ static int imap_get_delim (IMAP_DATA *idata)
if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
break;
- s = imap_next_word (idata->buf);
+ s = imap_next_word (idata->cmd.buf);
if (mutt_strncasecmp ("LIST", s, 4) == 0)
{
s = imap_next_word (s);
@@ -253,7 +205,7 @@ static int imap_get_delim (IMAP_DATA *idata)
}
while (rc == IMAP_CMD_CONTINUE);
- if (rc != IMAP_CMD_DONE)
+ if (rc != IMAP_CMD_OK)
{
dprint (1, (debugfile, "imap_get_delim: failed.\n"));
return -1;
@@ -285,7 +237,7 @@ static int imap_check_capabilities (IMAP_DATA* idata)
{
if (imap_exec (idata, "CAPABILITY", 0) != 0)
{
- imap_error ("imap_check_capabilities", idata->buf);
+ imap_error ("imap_check_capabilities", idata->cmd.buf);
return -1;
}
@@ -329,29 +281,29 @@ IMAP_DATA* imap_conn_find (const ACCOUNT* account, int flags)
/* don't open a new connection if one isn't wanted */
if (flags & M_IMAP_CONN_NONEW)
if (!idata || idata->state == IMAP_DISCONNECTED)
- {
- mutt_socket_free (conn);
-
- return NULL;
- }
+ goto err_conn;
if (!idata)
{
/* The current connection is a new connection */
- idata = safe_calloc (1, sizeof (IMAP_DATA));
+ if (! (idata = imap_new_idata ()))
+ goto err_conn;
+
conn->data = idata;
idata->conn = conn;
}
if (idata->state == IMAP_DISCONNECTED)
if (imap_open_connection (idata) != 0)
- {
- FREE (&idata);
- mutt_socket_free (conn);
-
- return NULL;
- }
+ goto err_idata;
return idata;
+
+ err_idata:
+ imap_free_idata (&idata);
+ err_conn:
+ mutt_socket_free (conn);
+
+ return NULL;
}
int imap_open_connection (IMAP_DATA* idata)
@@ -359,19 +311,23 @@ int imap_open_connection (IMAP_DATA* idata)
char buf[LONG_STRING];
if (mutt_socket_open (idata->conn) < 0)
+ {
+ mutt_error (_("Connection to %s failed."), idata->conn->account.host);
+ sleep (1);
return -1;
+ }
idata->state = IMAP_CONNECTED;
if (imap_cmd_step (idata) != IMAP_CMD_CONTINUE)
goto bail;
- if (mutt_strncmp ("* OK", idata->buf, 4) == 0)
+ if (mutt_strncmp ("* OK", idata->cmd.buf, 4) == 0)
{
if (imap_check_capabilities (idata) || imap_authenticate (idata))
goto bail;
}
- else if (mutt_strncmp ("* PREAUTH", idata->buf, 9) == 0)
+ else if (mutt_strncmp ("* PREAUTH", idata->cmd.buf, 9) == 0)
{
if (imap_check_capabilities (idata) != 0)
goto bail;
@@ -510,7 +466,7 @@ int imap_open_mailbox (CONTEXT* ctx)
if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
break;
- pc = idata->buf + 2;
+ pc = idata->cmd.buf + 2;
pc = imap_next_word (pc);
if (!mutt_strncasecmp ("EXISTS", pc, 6))
{
@@ -521,7 +477,7 @@ int imap_open_mailbox (CONTEXT* ctx)
idata->newMailCount = 0;
}
- pc = idata->buf + 2;
+ pc = idata->cmd.buf + 2;
/* Obtain list of available flags here, may be overridden by a
* PERMANENTFLAGS tag in the OK response */
@@ -552,18 +508,18 @@ int imap_open_mailbox (CONTEXT* ctx)
if (rc == IMAP_CMD_NO)
{
char *s;
- s = imap_next_word (idata->buf); /* skip seq */
+ s = imap_next_word (idata->cmd.buf); /* skip seq */
s = imap_next_word (s); /* Skip response */
mutt_error ("%s", s);
sleep (2);
goto fail;
}
- if (rc != IMAP_CMD_DONE)
+ if (rc != IMAP_CMD_OK)
goto fail;
/* check for READ-ONLY notification */
- if (!strncmp (imap_get_qualifier (idata->buf), "[READ-ONLY]", 11))
+ if (!strncmp (imap_get_qualifier (idata->cmd.buf), "[READ-ONLY]", 11))
{
dprint (2, (debugfile, "Mailbox is read-only.\n"));
ctx->readonly = 1;
@@ -934,7 +890,7 @@ int imap_sync_mailbox (CONTEXT* ctx, int expunge, int* index_hint)
(err_continue != M_YES))
{
err_continue = imap_continue ("imap_sync_mailbox: STORE failed",
- idata->buf);
+ idata->cmd.buf);
if (err_continue != M_YES)
return -1;
}
@@ -951,7 +907,7 @@ int imap_sync_mailbox (CONTEXT* ctx, int expunge, int* index_hint)
mutt_message _("Expunging messages from server...");
if (imap_exec (idata, "EXPUNGE", 0) != 0)
{
- imap_error ("imap_sync_mailbox: EXPUNGE failed", idata->buf);
+ imap_error ("imap_sync_mailbox: EXPUNGE failed", idata->cmd.buf);
return -1;
}
}
@@ -975,7 +931,7 @@ void imap_close_mailbox (CONTEXT* ctx)
(ctx == idata->ctx))
{
if (!(idata->noclose) && imap_exec (idata, "CLOSE", 0))
- imap_error ("CLOSE failed", idata->buf);
+ imap_error ("CLOSE failed", idata->cmd.buf);
idata->reopen &= IMAP_REOPEN_ALLOW;
idata->state = IMAP_AUTHENTICATED;
@@ -1020,7 +976,7 @@ int imap_check_mailbox (CONTEXT *ctx, int *index_hint)
if (imap_exec (idata, "NOOP", 0) != 0)
{
- imap_error ("imap_check_mailbox", idata->buf);
+ imap_error ("imap_check_mailbox", idata->cmd.buf);
return -1;
}
}
@@ -1103,7 +1059,7 @@ int imap_mailbox_check (char* path, int new)
if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
break;
- s = imap_next_word (idata->buf);
+ s = imap_next_word (idata->cmd.buf);
if (mutt_strncasecmp ("STATUS", s, 6) == 0)
{
s = imap_next_word (s);
@@ -1148,12 +1104,12 @@ int imap_parse_list_response(IMAP_DATA* idata, char **name, int *noselect,
*name = NULL;
rc = imap_cmd_step (idata);
- if (rc == IMAP_CMD_DONE)
+ if (rc == IMAP_CMD_OK)
return 0;
if (rc != IMAP_CMD_CONTINUE)
return -1;
- s = imap_next_word (idata->buf);
+ s = imap_next_word (idata->cmd.buf);
if ((mutt_strncasecmp ("LIST", s, 4) == 0) ||
(mutt_strncasecmp ("LSUB", s, 4) == 0))
{
@@ -1193,11 +1149,11 @@ int imap_parse_list_response(IMAP_DATA* idata, char **name, int *noselect,
s = imap_next_word (s); /* name */
if (s && *s == '{') /* Literal */
{
- if (imap_get_literal_count(idata->buf, &bytes) < 0)
+ if (imap_get_literal_count(idata->cmd.buf, &bytes) < 0)
return -1;
if (imap_cmd_step (idata) != IMAP_CMD_CONTINUE)
return -1;
- *name = idata->buf;
+ *name = idata->cmd.buf;
}
else
*name = s;
@@ -1324,7 +1280,7 @@ int imap_complete(char* dest, size_t dlen, char* path) {
completions++;
}
}
- while (mutt_strncmp(idata->seq, idata->buf, SEQLEN));
+ while (mutt_strncmp(idata->cmd.seq, idata->cmd.buf, SEQLEN));
if (completions)
{
diff --git a/imap/imap_private.h b/imap/imap_private.h
index 84d045da..78f6e62f 100644
--- a/imap/imap_private.h
+++ b/imap/imap_private.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1996-9 Brandon Long <blong@fiction.net>
- * Copyright (C) 1999-2000 Brendan Cully <brendan@kublai.com>
+ * Copyright (C) 1999-2001 Brendan Cully <brendan@kublai.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,11 +32,16 @@
#define IMAP_LOG_LTRL 4
#define IMAP_LOG_PASS 5
-/* IMAP command responses */
-#define IMAP_CMD_DONE (0)
-#define IMAP_CMD_FAIL (-1)
+/* IMAP command responses. Used in IMAP_COMMAND.state too */
+/* <tag> OK ... */
+#define IMAP_CMD_OK (0)
+/* <tag> BAD ... */
+#define IMAP_CMD_BAD (-1)
+/* <tag> NO ... */
#define IMAP_CMD_NO (-2)
+/* * ... */
#define IMAP_CMD_CONTINUE (1)
+/* + */
#define IMAP_CMD_RESPOND (2)
/* number of entries in the hash table */
@@ -132,17 +137,21 @@ typedef struct
int noinferiors;
} IMAP_NAMESPACE_INFO;
+/* IMAP command structure */
+typedef struct
+{
+ char seq[SEQLEN+1];
+ char* buf;
+ unsigned int blen;
+ int state;
+} IMAP_COMMAND;
+
typedef struct
{
/* This data is specific to a CONNECTION to an IMAP server */
CONNECTION *conn;
unsigned char state;
unsigned char status;
- unsigned char capabilities[(CAPMAX + 7)/8];
- char seq[SEQLEN+1];
- /* command input buffer */
- char* buf;
- unsigned int blen;
/* let me explain capstr: SASL needs the capability string (not bits).
* we have 3 options:
* 1. rerun CAPABILITY inside SASL function.
@@ -152,6 +161,10 @@ typedef struct
* tracking all possible capabilities. bah. (1) I don't like because
* it's just no fun to get the same information twice */
char* capstr;
+ unsigned char capabilities[(CAPMAX + 7)/8];
+ unsigned int seqno;
+ /* who knows, one day we may run multiple commands in parallel */
+ IMAP_COMMAND cmd;
/* The following data is all specific to the currently SELECTED mbox */
char delim;
@@ -167,6 +180,7 @@ typedef struct
/* all folder flags - system flags AND keywords */
LIST *flags;
} IMAP_DATA;
+/* I wish that were called IMAP_CONTEXT :( */
/* -- macros -- */
#define CTX_DATA ((IMAP_DATA *) ctx->data)
@@ -178,7 +192,6 @@ int imap_make_msg_set (IMAP_DATA* idata, char* buf, size_t buflen, int flag,
int changed);
int imap_open_connection (IMAP_DATA* idata);
IMAP_DATA* imap_conn_find (const ACCOUNT* account, int flags);
-time_t imap_parse_date (char* s);
int imap_parse_list_response(IMAP_DATA* idata, char** name, int* noselect,
int* noinferiors, char* delim);
int imap_read_literal (FILE* fp, IMAP_DATA* idata, long bytes);
@@ -202,11 +215,14 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend);
/* util.c */
int imap_continue (const char* msg, const char* resp);
void imap_error (const char* where, const char* msg);
+IMAP_DATA* imap_new_idata (void);
+void imap_free_idata (IMAP_DATA** idata);
char* imap_fix_path (IMAP_DATA* idata, char* mailbox, char* path,
size_t plen);
int imap_get_literal_count (const char* buf, long* bytes);
char* imap_get_qualifier (char* buf);
char* imap_next_word (char* s);
+time_t imap_parse_date (char* s);
void imap_qualify_path (char *dest, size_t len, IMAP_MBOX *mx, char* path);
void imap_quote_string (char* dest, size_t slen, const char* src);
void imap_unquote_string (char* s);
diff --git a/imap/message.c b/imap/message.c
index 9946778c..adaf142b 100644
--- a/imap/message.c
+++ b/imap/message.c
@@ -127,7 +127,7 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend)
if (rc != IMAP_CMD_CONTINUE)
break;
- if ((mfhrc = msg_fetch_header (idata->ctx, &h, idata->buf, fp)) == -1)
+ if ((mfhrc = msg_fetch_header (idata->ctx, &h, idata->cmd.buf, fp)) == -1)
continue;
else if (mfhrc < 0)
break;
@@ -164,10 +164,10 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend)
mx_update_context (ctx); /* increments ->msgcount */
}
- while ((rc != IMAP_CMD_DONE) && ((mfhrc == -1) ||
+ while ((rc != IMAP_CMD_OK) && ((mfhrc == -1) ||
((msgno + 1) >= fetchlast)));
- if ((mfhrc < -1) || ((rc != IMAP_CMD_CONTINUE) && (rc != IMAP_CMD_DONE)))
+ if ((mfhrc < -1) || ((rc != IMAP_CMD_CONTINUE) && (rc != IMAP_CMD_OK)))
{
imap_free_header_data ((void**) &h.data);
fclose (fp);
@@ -257,7 +257,7 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
break;
- pc = idata->buf;
+ pc = idata->cmd.buf;
pc = imap_next_word (pc);
pc = imap_next_word (pc);
@@ -289,7 +289,7 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
/* pick up trailing line */
if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
goto bail;
- pc = idata->buf;
+ pc = idata->cmd.buf;
fetched = 1;
}
@@ -348,10 +348,10 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
}
while (rc == IMAP_CMD_CONTINUE);
- if (rc != IMAP_CMD_DONE)
+ if (rc != IMAP_CMD_OK)
goto bail;
- if (!fetched || !imap_code (idata->buf))
+ if (!fetched || !imap_code (idata->cmd.buf))
goto bail;
/* Update the header information. Previously, we only downloaded a
@@ -453,9 +453,10 @@ int imap_append_message (CONTEXT *ctx, MESSAGE *msg)
{
char *pc;
- dprint (1, (debugfile, "imap_append_message(): command failed: %s\n", idata->buf));
+ dprint (1, (debugfile, "imap_append_message(): command failed: %s\n",
+ idata->cmd.buf));
- pc = idata->buf + SEQLEN;
+ pc = idata->cmd.buf + SEQLEN;
SKIPWS (pc);
pc = imap_next_word (pc);
mutt_error ("%s", pc);
@@ -487,12 +488,13 @@ int imap_append_message (CONTEXT *ctx, MESSAGE *msg)
rc = imap_cmd_step (idata);
while (rc == IMAP_CMD_CONTINUE);
- if (!imap_code (idata->buf))
+ if (!imap_code (idata->cmd.buf))
{
char *pc;
- dprint (1, (debugfile, "imap_append_message(): command failed: %s\n", idata->buf));
- pc = idata->buf + SEQLEN;
+ dprint (1, (debugfile, "imap_append_message(): command failed: %s\n",
+ idata->cmd.buf));
+ pc = idata->cmd.buf + SEQLEN;
SKIPWS (pc);
pc = imap_next_word (pc);
mutt_error ("%s", pc);
@@ -568,9 +570,9 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete)
if (rc == -2)
{
/* bail out if command failed for reasons other than nonexistent target */
- if (strncmp (imap_get_qualifier (idata->buf), "[TRYCREATE]", 11))
+ if (strncmp (imap_get_qualifier (idata->cmd.buf), "[TRYCREATE]", 11))
{
- imap_error ("imap_copy_messages", idata->buf);
+ imap_error ("imap_copy_messages", idata->cmd.buf);
goto fail;
}
dprint (2, (debugfile, "imap_copy_messages: server suggests TRYCREATE\n"));
@@ -588,7 +590,7 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete)
}
if (rc != 0)
{
- imap_error ("imap_copy_messages", idata->buf);
+ imap_error ("imap_copy_messages", idata->cmd.buf);
goto fail;
}
@@ -699,7 +701,7 @@ static int msg_fetch_header (CONTEXT* ctx, IMAP_HEADER* h, char* buf, FILE* fp)
if (imap_cmd_step (idata) != IMAP_CMD_CONTINUE)
return -2;
- if (msg_parse_fetch (h, idata->buf) == -1)
+ if (msg_parse_fetch (h, idata->cmd.buf) == -1)
return rc;
rc = 0; /* success */
diff --git a/imap/util.c b/imap/util.c
index 778d39b2..c0cfa1d7 100644
--- a/imap/util.c
+++ b/imap/util.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
* Copyright (C) 1996-9 Brandon Long <blong@fiction.net>
- * Copyright (C) 1999-2000 Brendan Cully <brendan@kublai.com>
+ * Copyright (C) 1999-2001 Brendan Cully <brendan@kublai.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -50,6 +50,35 @@ void imap_error (const char *where, const char *msg)
sleep (2);
}
+/* imap_new_idata: Allocate and initialise a new IMAP_DATA structure.
+ * Returns NULL on failure (no mem) */
+IMAP_DATA* imap_new_idata (void) {
+ IMAP_DATA* idata;
+
+ idata = safe_calloc (1, sizeof (IMAP_DATA));
+ if (!idata)
+ return NULL;
+
+ idata->conn = NULL;
+ idata->state = IMAP_DISCONNECTED;
+ idata->seqno = 0;
+
+ idata->cmd.buf = NULL;
+ idata->cmd.blen = 0;
+ idata->cmd.state = IMAP_CMD_OK;
+
+ return idata;
+}
+
+/* imap_free_idata: Release and clear storage in an IMAP_DATA structure. */
+void imap_free_idata (IMAP_DATA** idata) {
+ if (!idata)
+ return;
+
+ FREE (&((*idata)->cmd.buf));
+ FREE (idata);
+}
+
/*
* Fix up the imap path. This is necessary because the rest of mutt
* assumes a hierarchy delimiter of '/', which is not necessarily true
@@ -127,6 +156,54 @@ char *imap_next_word (char *s)
return s;
}
+/* imap_parse_date: date is of the form: DD-MMM-YYYY HH:MM:SS +ZZzz */
+time_t imap_parse_date (char *s)
+{
+ struct tm t;
+ time_t tz;
+
+ t.tm_mday = (s[0] == ' '? s[1] - '0' : (s[0] - '0') * 10 + (s[1] - '0'));
+ s += 2;
+ if (*s != '-')
+ return 0;
+ s++;
+ t.tm_mon = mutt_check_month (s);
+ s += 3;
+ if (*s != '-')
+ return 0;
+ s++;
+ t.tm_year = (s[0] - '0') * 1000 + (s[1] - '0') * 100 + (s[2] - '0') * 10 + (s[3] - '0') - 1900;
+ s += 4;
+ if (*s != ' ')
+ return 0;
+ s++;
+
+ /* time */
+ t.tm_hour = (s[0] - '0') * 10 + (s[1] - '0');
+ s += 2;
+ if (*s != ':')
+ return 0;
+ s++;
+ t.tm_min = (s[0] - '0') * 10 + (s[1] - '0');
+ s += 2;
+ if (*s != ':')
+ return 0;
+ s++;
+ t.tm_sec = (s[0] - '0') * 10 + (s[1] - '0');
+ s += 2;
+ if (*s != ' ')
+ return 0;
+ s++;
+
+ /* timezone */
+ tz = ((s[1] - '0') * 10 + (s[2] - '0