summaryrefslogtreecommitdiffstats
path: root/imap.c
diff options
context:
space:
mode:
authorThomas Roessler <roessler@does-not-exist.org>1998-06-15 15:19:45 +0000
committerThomas Roessler <roessler@does-not-exist.org>1998-06-15 15:19:45 +0000
commita07d9f79f6a533ec83d64dda1c824e3a81c2d493 (patch)
tree0b024e76c4f235e5f917ca179731c1515b615fc7 /imap.c
parent90bea32a9b22777b4b32e787661aa532c7d77fc2 (diff)
Brandon's IMAP patch.
Diffstat (limited to 'imap.c')
-rw-r--r--imap.c498
1 files changed, 371 insertions, 127 deletions
diff --git a/imap.c b/imap.c
index 619482c7..872e019b 100644
--- a/imap.c
+++ b/imap.c
@@ -30,6 +30,7 @@
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/stat.h>
/* Minimal support for IMAP 4rev1 */
@@ -45,11 +46,23 @@ enum
IMAP_FATAL = 1,
IMAP_NEW_MAIL,
IMAP_EXPUNGE,
- IMAP_BYE
+ IMAP_BYE,
+ IMAP_OK_FAIL,
+ IMAP_OPEN_NEW
};
typedef struct
{
+ char *server;
+ int uses;
+ int fd;
+ char inbuf[LONG_STRING];
+ int bufpos;
+ int available;
+} CONNECTION;
+
+typedef struct
+{
int index;
char *path;
} IMAP_CACHE;
@@ -59,36 +72,40 @@ typedef struct
short status;
unsigned short sequence;
unsigned short newMailCount;
+ char *mailbox;
short xxx;
IMAP_CACHE cache[IMAP_CACHE_LEN];
+ CONNECTION *conn;
} IMAP_DATA;
+#define CTX_DATA ((IMAP_DATA *) ctx->data)
+
+static CONNECTION *Connections = NULL;
+static int NumConnections = 0;
+
/* simple read buffering to speed things up. */
-static int imap_readchar (int fd, char *c)
+static int imap_readchar (CONNECTION *conn, char *c)
{
- static char inbuf[LONG_STRING];
- static int bufpos=0, available=0;
-
- if (bufpos>=available)
- {
- available = read (fd, inbuf, sizeof(inbuf));
- bufpos = 0;
- if (available <= 0)
- return available; /* returns 0 for EOF or -1 for other error */
- }
- *c = inbuf[bufpos];
- bufpos++;
+ if (conn->bufpos >= conn->available)
+ {
+ conn->available = read (conn->fd, conn->inbuf, sizeof(LONG_STRING));
+ conn->bufpos = 0;
+ if (conn->available <= 0)
+ return conn->available; /* returns 0 for EOF or -1 for other error */
+ }
+ *c = conn->inbuf[conn->bufpos];
+ conn->bufpos++;
return 1;
}
-static int imap_read_line (char *buf, size_t buflen, int fd)
+static int imap_read_line (char *buf, size_t buflen, CONNECTION *conn)
{
char ch;
int i;
for (i = 0; i < buflen; i++)
{
- if (imap_readchar (fd, &ch) != 1)
+ if (imap_readchar (conn, &ch) != 1)
return (-1);
if (ch == '\n')
break;
@@ -98,22 +115,22 @@ static int imap_read_line (char *buf, size_t buflen, int fd)
return (i + 1);
}
-static int imap_read_line_d (char *buf, size_t buflen, int fd)
+static int imap_read_line_d (char *buf, size_t buflen, CONNECTION *conn)
{
- int r = imap_read_line (buf, buflen, fd);
+ int r = imap_read_line (buf, buflen, conn);
dprint (1,(debugfile,"imap_read_line_d():%s\n", buf));
return r;
}
static void imap_make_sequence (char *buf, size_t buflen, CONTEXT *ctx)
{
- snprintf (buf, buflen, "a%04d", ((IMAP_DATA *) ctx->data)->sequence++);
+ snprintf (buf, buflen, "a%04d", CTX_DATA->sequence++);
}
-static int imap_write (int fd, const char *buf)
+static int imap_write (CONNECTION *conn, const char *buf)
{
dprint (1,(debugfile,"imap_write():%s", buf));
- return (write (fd, buf, strlen (buf)));
+ return (write (conn->fd, buf, strlen (buf)));
}
static void imap_error (const char *where, const char *msg)
@@ -121,13 +138,43 @@ static void imap_error (const char *where, const char *msg)
dprint (1, (debugfile, "imap_error(): unexpected response in %s: %s\n", where, msg));
}
+static CONNECTION *imap_select_connection (char *host, int flags)
+{
+ int x;
+
+ if (flags != IMAP_OPEN_NEW)
+ {
+ for (x = 0; x < NumConnections; x++)
+ {
+ if (!strcmp (host, Connections[x].server))
+ return &Connections[x];
+ }
+ }
+ if (NumConnections == 0)
+ {
+ NumConnections = 1;
+ Connections = (CONNECTION *) safe_malloc (sizeof (CONNECTION));
+ }
+ else
+ {
+ NumConnections++;
+ safe_realloc ((void *)Connections, sizeof (CONNECTION) * NumConnections);
+ }
+ Connections[NumConnections - 1].bufpos = 0;
+ Connections[NumConnections - 1].available = 0;
+ Connections[NumConnections - 1].uses = 0;
+ Connections[NumConnections - 1].server = safe_strdup (host);
+
+ return &Connections[NumConnections - 1];
+}
+
/* date is of the form: DD-MMM-YYYY HH:MM:SS +ZZzz */
static time_t imap_parse_date (char *s)
{
struct tm t;
time_t tz;
- t.tm_mday = (s[0] - '0') * 10 + (s[1] - '0');
+ t.tm_mday = (s[0] == ' '? s[1] - '0' : (s[0] - '0') * 10 + (s[1] - '0'));
s += 2;
if (*s != '-')
return 0;
@@ -200,6 +247,7 @@ static int imap_parse_fetch (HEADER *h, char *s)
/* we're about to get a new set of headers, so clear the old ones. */
h->deleted=0; h->flagged=0;
h->replied=0; h->read=0;
+ h->changed=0;
s++;
state = 1;
}
@@ -230,7 +278,7 @@ static int imap_parse_fetch (HEADER *h, char *s)
while (isdigit (*s))
*ptmp++ = *s++;
*ptmp = 0;
- h->content->length = atoi (tmp);
+ h->content->length += atoi (tmp);
}
else if (*s == ')')
s++; /* end of request */
@@ -278,7 +326,7 @@ static int imap_parse_fetch (HEADER *h, char *s)
return 0;
}
-static int imap_read_bytes (FILE *fp, int fd, long bytes)
+static int imap_read_bytes (FILE *fp, CONNECTION *conn, long bytes)
{
long pos;
long len;
@@ -286,7 +334,7 @@ static int imap_read_bytes (FILE *fp, int fd, long bytes)
for (pos = 0; pos < bytes; )
{
- len = imap_read_line (buf, sizeof (buf), fd);
+ len = imap_read_line (buf, sizeof (buf), conn);
if (len < 0)
return (-1);
pos += len;
@@ -331,29 +379,28 @@ static int imap_handle_untagged (CONTEXT *ctx, char *s)
/* new mail arrived */
count = atoi (pn);
- if (((IMAP_DATA *) ctx->data)->status != IMAP_EXPUNGE) {
- if (count <= ctx->msgcount)
- {
- /* something is wrong because the server reported fewer messages
- * than we previously saw
- */
- mutt_error ("Fatal error. Message count is out of sync!");
- ((IMAP_DATA *) ctx->data)->status = IMAP_FATAL;
- mx_fastclose_mailbox (ctx);
- return (-1);
- }
- else
- {
- ((IMAP_DATA *) ctx->data)->status = IMAP_NEW_MAIL;
- ((IMAP_DATA *) ctx->data)->newMailCount = count;
- }
- }
+ if ( (CTX_DATA->status != IMAP_EXPUNGE) &&
+ count <= ctx->msgcount)
+ {
+ /* something is wrong because the server reported fewer messages
+ * than we previously saw
+ */
+ mutt_error ("Fatal error. Message count is out of sync!");
+ CTX_DATA->status = IMAP_FATAL;
+ mx_fastclose_mailbox (ctx);
+ return (-1);
+ }
+ else
+ {
+ CTX_DATA->status = IMAP_NEW_MAIL;
+ CTX_DATA->newMailCount = count;
+ }
}
else if (strncasecmp ("EXPUNGE", s, 7) == 0)
{
/* a message was removed; reindex remaining messages */
/* (which amounts to decrementing indices of messages */
- /* with an index greater than the deleted one. */
+ /* with an index greater than the deleted one.) */
ind = atoi (pn) - 1;
for (n = 0; n < ctx->msgcount; n++)
if (ctx->hdrs[n]->index > ind)
@@ -366,7 +413,7 @@ static int imap_handle_untagged (CONTEXT *ctx, char *s)
s += 3;
SKIPWS (s);
mutt_error (s);
- ((IMAP_DATA *) ctx->data)->status = IMAP_BYE;
+ CTX_DATA->status = IMAP_BYE;
mx_fastclose_mailbox (ctx);
return (-1);
}
@@ -387,7 +434,7 @@ static int imap_read_header (CONTEXT *ctx, int msgno)
char seq[8];
char *pc;
char *pn;
- long bytes;
+ long bytes = 0;
ctx->hdrs[ctx->msgcount]->index = ctx->msgcount;
@@ -399,11 +446,11 @@ static int imap_read_header (CONTEXT *ctx, int msgno)
imap_make_sequence (seq, sizeof (seq), ctx);
snprintf (buf, sizeof (buf), "%s FETCH %d RFC822.HEADER\r\n", seq, msgno + 1);
- imap_write (ctx->fd, buf);
+ imap_write (CTX_DATA->conn, buf);
do
{
- if (imap_read_line (buf, sizeof (buf), ctx->fd) < 0)
+ if (imap_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0)
{
return (-1);
}
@@ -427,7 +474,7 @@ static int imap_read_header (CONTEXT *ctx, int msgno)
*pc = 0;
bytes = atoi (pn);
- imap_read_bytes (fp, ctx->fd, bytes);
+ imap_read_bytes (fp, CTX_DATA->conn, bytes);
}
else if (imap_handle_untagged (ctx, buf) != 0)
return (-1);
@@ -438,16 +485,19 @@ static int imap_read_header (CONTEXT *ctx, int msgno)
rewind (fp);
ctx->hdrs[msgno]->env = mutt_read_rfc822_header (fp, ctx->hdrs[msgno]);
+/* subtract the header length; the total message size will be added to this */
+ ctx->hdrs[msgno]->content->length = -bytes;
+
fclose (fp);
unlink (tempfile);
/* get the status of this message */
imap_make_sequence (seq, sizeof (seq), ctx);
snprintf (buf, sizeof (buf), "%s FETCH %d FAST\r\n", seq, msgno + 1);
- imap_write (ctx->fd, buf);
+ imap_write (CTX_DATA->conn, buf);
do
{
- if (imap_read_line_d (buf, sizeof (buf), ctx->fd) < 0)
+ if (imap_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0)
break;
if (buf[0] == '*')
{
@@ -475,15 +525,15 @@ static int imap_read_header (CONTEXT *ctx, int msgno)
}
static int imap_exec (char *buf, size_t buflen,
- CONTEXT *ctx, const char *seq, const char *cmd)
+ CONTEXT *ctx, const char *seq, const char *cmd, int flags)
{
int count;
- imap_write (ctx->fd, cmd);
+ imap_write (CTX_DATA->conn, cmd);
do
{
- if (imap_read_line_d (buf, buflen, ctx->fd) < 0)
+ if (imap_read_line_d (buf, buflen, CTX_DATA->conn) < 0)
return (-1);
if (buf[0] == '*' && imap_handle_untagged (ctx, buf) != 0)
@@ -491,16 +541,16 @@ static int imap_exec (char *buf, size_t buflen,
}
while (strncmp (buf, seq, SEQLEN) != 0);
- if (((IMAP_DATA *) ctx->data)->status == IMAP_NEW_MAIL)
+ if (CTX_DATA->status == IMAP_NEW_MAIL)
{
/* read new mail messages */
dprint (1, (debugfile, "imap_exec(): new mail detected\n"));
mutt_message ("Fetching headers for new mail...");
- ((IMAP_DATA *) ctx->data)->status = 0;
+ CTX_DATA->status = 0;
- count = ((IMAP_DATA *) ctx->data)->newMailCount;
+ count = CTX_DATA->newMailCount;
while (count > ctx->hdrmax)
mx_alloc_memory (ctx);
@@ -513,12 +563,12 @@ static int imap_exec (char *buf, size_t buflen,
/* check to make sure that new mail hasn't arrived in the middle of
* checking for new mail (sigh)
*/
- if (((IMAP_DATA *) ctx->data)->status == IMAP_NEW_MAIL)
+ if (CTX_DATA->status == IMAP_NEW_MAIL)
{
- count = ((IMAP_DATA *) ctx->data)->newMailCount;
+ count = CTX_DATA->newMailCount;
while (count > ctx->hdrmax)
mx_alloc_memory (ctx);
- ((IMAP_DATA *) ctx->data)->status = 0;
+ CTX_DATA->status = 0;
}
}
@@ -529,6 +579,8 @@ static int imap_exec (char *buf, size_t buflen,
{
char *pc;
+ if (flags == IMAP_OK_FAIL)
+ return (-1);
dprint (1, (debugfile, "imap_exec(): command failed: %s\n", buf));
pc = buf + SEQLEN;
SKIPWS (pc);
@@ -541,31 +593,14 @@ static int imap_exec (char *buf, size_t buflen,
return 0;
}
-int imap_open_mailbox (CONTEXT *ctx)
+static int imap_open_connection (CONTEXT *ctx, CONNECTION *conn)
{
struct sockaddr_in sin;
struct hostent *he;
char buf[LONG_STRING];
- char bufout[LONG_STRING];
- char host[SHORT_STRING];
char user[SHORT_STRING];
char pass[SHORT_STRING];
- char mailbox[_POSIX_PATH_MAX];
char seq[16];
- int count = 0;
- int n;
- char *pc;
-
- if (ctx->path[0] != '{')
- return (-1);
- for(n = 0, pc = ctx->path + 1; *pc && *pc != '}' && n < sizeof(host) - 1;
- n++, pc++)
- host[n++] = *pc++;
- if(*pc != '}')
- return -1;
- host[n] = 0;
- pc++;
- strfcpy (mailbox, pc, sizeof (mailbox));
if (!ImapUser)
{
@@ -583,7 +618,7 @@ int imap_open_mailbox (CONTEXT *ctx)
if (!ImapPass)
{
pass[0]=0;
- snprintf (buf, sizeof (buf), "Password for %s@%s: ", user, host);
+ snprintf (buf, sizeof (buf), "Password for %s@%s: ", user, conn->server);
if (mutt_get_field (buf, pass, sizeof (pass), M_PASS) != 0 ||
!pass[0])
{
@@ -596,53 +631,48 @@ int imap_open_mailbox (CONTEXT *ctx)
memset (&sin, 0, sizeof (sin));
sin.sin_port = htons (IMAP_PORT);
sin.sin_family = AF_INET;
- if ((he = gethostbyname (host)) == NULL)
+ if ((he = gethostbyname (conn->server)) == NULL)
{
- mutt_perror (host);
+ mutt_perror (conn->server);
return (-1);
}
memcpy (&sin.sin_addr, he->h_addr_list[0], he->h_length);
- if ((ctx->fd = socket (AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0)
+ if ((conn->fd = socket (AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0)
{
mutt_perror ("socket");
return (-1);
}
- mutt_message ("Connecting to %s...", host);
+ mutt_message ("Connecting to %s...", conn->server);
- if (connect (ctx->fd, (struct sockaddr *) &sin, sizeof (sin)) < 0)
+ if (connect (conn->fd, (struct sockaddr *) &sin, sizeof (sin)) < 0)
{
mutt_perror ("connect");
- close (ctx->fd);
+ close (conn->fd);
}
- if (imap_read_line_d (buf, sizeof (buf), ctx->fd) < 0)
+ if (imap_read_line_d (buf, sizeof (buf), conn) < 0)
{
- close (ctx->fd);
+ close (conn->fd);
return (-1);
}
if (strncmp ("* OK", buf, 4) != 0)
{
- imap_error ("imap_open_mailbox()", buf);
- close (ctx->fd);
+ imap_error ("imap_open_connection()", buf);
+ close (conn->fd);
return (-1);
}
- /* create IMAP-specific state struct */
- ctx->data = safe_malloc (sizeof (IMAP_DATA));
- memset (ctx->data, 0, sizeof (IMAP_DATA));
-
mutt_message ("Logging in...");
- imap_make_sequence (seq, sizeof (seq), ctx);
+ /* sequence numbers are currently context dependent, so just make one
+ * up for this first access to the server */
+ strcpy (seq, "l0000");
snprintf (buf, sizeof (buf), "%s LOGIN %s %s\r\n", seq, user, pass);
- if (imap_exec (buf, sizeof (buf), ctx, seq, buf) != 0)
+ if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0)
{
- /* Most likely an invalid login; clear username and password for re-entry. */
- FREE (&ImapUser);
- FREE (&ImapPass);
- imap_error ("imap_open_mailbox()", buf);
+ imap_error ("imap_open_connection()", buf);
return (-1);
}
/* If they have a successful login, we may as well cache the user/password. */
@@ -651,14 +681,54 @@ int imap_open_mailbox (CONTEXT *ctx)
if (!ImapPass)
ImapPass = safe_strdup (pass);
- mutt_message ("Selecting %s...", mailbox);
+ return 0;
+}
+
+int imap_open_mailbox (CONTEXT *ctx)
+{
+ CONNECTION *conn;
+ char buf[LONG_STRING];
+ char bufout[LONG_STRING];
+ char host[SHORT_STRING];
+ char seq[16];
+ int count = 0;
+ int n;
+ char *pc;
+
+ /* create IMAP-specific state struct */
+ ctx->data = safe_malloc (sizeof (IMAP_DATA));
+ memset (ctx->data, 0, sizeof (IMAP_DATA));
+
+ pc = ctx->path;
+ if (*pc != '{')
+ return (-1);
+ pc++;
+ n = 0;
+ while (*pc && *pc != '}')
+ host[n++] = *pc++;
+ host[n] = 0;
+ if (!*pc)
+ return (-1);
+ pc++;
+
+ CTX_DATA->mailbox = safe_strdup (pc);
+
+ conn = imap_select_connection (host, IMAP_OPEN_NEW);
+ CTX_DATA->conn = conn;
+
+ if (conn->uses == 0)
+ if (imap_open_connection (ctx, conn))
+ return (-1);
+ conn->uses++;
+
+ mutt_message ("Selecting %s...", CTX_DATA->mailbox);
imap_make_sequence (seq, sizeof (seq), ctx);
- snprintf (bufout, sizeof (bufout), "%s SELECT %s\r\n", seq, mailbox);
- imap_write (ctx->fd, bufout);
+ snprintf (bufout, sizeof (bufout), "%s SELECT %s\r\n", seq, CTX_DATA->mailbox);
+ imap_write (CTX_DATA->conn, bufout);
do
{
- if (imap_read_line_d (buf, sizeof (buf), ctx->fd) < 0)
+ if (imap_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0)
break;
if (buf[0] == '*')
@@ -704,18 +774,89 @@ int imap_open_mailbox (CONTEXT *ctx)
mx_update_context (ctx); /* increments ->msgcount */
/* in case we get new mail while fetching the headers */
- if (((IMAP_DATA *) ctx->data)->status == IMAP_NEW_MAIL)
+ if (CTX_DATA->status == IMAP_NEW_MAIL)
{
- count = ((IMAP_DATA *) ctx->data)->newMailCount;
+ count = CTX_DATA->newMailCount;
while (count > ctx->hdrmax)
mx_alloc_memory (ctx);
- ((IMAP_DATA *) ctx->data)->status = 0;
+ CTX_DATA->status = 0;
}
}
return 0;
}
+static int imap_create_mailbox (CONTEXT *ctx)
+{
+ char seq[8];
+ char buf[LONG_STRING];
+
+ imap_make_sequence (seq, sizeof (seq), ctx);
+ snprintf (buf, sizeof (buf), "%s CREATE %s\r\n", seq, CTX_DATA->mailbox);
+
+ if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0)
+ {
+ imap_error ("imap_sync_mailbox()", buf);
+ return (-1);
+ }
+ return 0;
+}
+
+int imap_open_mailbox_append (CONTEXT *ctx)
+{
+ CONNECTION *conn;
+ char host[SHORT_STRING];
+ char buf[LONG_STRING];
+ char seq[16];
+ int n;
+ char *pc;
+
+ /* create IMAP-specific state struct */
+ ctx->data = safe_malloc (sizeof (IMAP_DATA));
+ memset (ctx->data, 0, sizeof (IMAP_DATA));
+
+ pc = ctx->path;
+ if (*pc != '{')
+ return (-1);
+ pc++;
+ n = 0;
+ while (*pc && *pc != '}')
+ host[n++] = *pc++;
+ host[n] = 0;
+ if (!*pc)
+ return (-1);
+ pc++;
+
+ CTX_DATA->mailbox = pc;
+
+ conn = imap_select_connection (host, 0);
+ CTX_DATA->conn = conn;
+
+ if (conn->uses == 0)
+ if (imap_open_connection (ctx, conn))
+ return (-1);
+ conn->uses++;
+
+ /* check mailbox existance */
+
+ imap_make_sequence (seq, sizeof (seq), ctx);
+ snprintf (buf, sizeof (buf), "%s STATUS %s (UIDVALIDITY)\r\n", seq,
+ CTX_DATA->mailbox);
+
+ if (imap_exec (buf, sizeof (buf), ctx, seq, buf, IMAP_OK_FAIL) != 0)
+ {
+ if (option (OPTCONFIRMCREATE))
+ {
+ snprintf (buf, sizeof (buf), "Create %s?", CTX_DATA->mailbox);
+ if (mutt_yesorno (buf, 1) < 1)
+ return (-1);
+ if (imap_create_mailbox (ctx) < 0)
+ return (-1);
+ }
+ }
+ return 0;
+}
+
int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
{
char seq[8];
@@ -727,7 +868,7 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
IMAP_CACHE *cache;
/* see if we already have the message in our cache */
- cache = &((IMAP_DATA *) ctx->data)->cache[ctx->hdrs[msgno]->index % IMAP_CACHE_LEN];
+ cache = &CTX_DATA->cache[ctx->hdrs[msgno]->index % IMAP_CACHE_LEN];
if (cache->path)
{
@@ -763,10 +904,10 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
imap_make_sequence (seq, sizeof (seq), ctx);
snprintf (buf, sizeof (buf), "%s FETCH %d RFC822\r\n", seq,
ctx->hdrs[msgno]->index + 1);
- imap_write (ctx->fd, buf);
+ imap_write (CTX_DATA->conn, buf);
do
{
- if (imap_read_line (buf, sizeof (buf), ctx->fd) < 0)
+ if (imap_read_line (buf, sizeof (buf), CTX_DATA->conn) < 0)
{
return (-1);
}
@@ -789,7 +930,7 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
pc++;
*pc = 0;
bytes = atoi (pn);
- imap_read_bytes (msg->fp, ctx->fd, bytes);
+ imap_read_bytes (msg->fp, CTX_DATA->conn, bytes);
}
else if (imap_handle_untagged (ctx, buf) != 0)
return (-1);
@@ -806,27 +947,119 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
return 0;
}
+int imap_append_message (CONTEXT *ctx, MESSAGE *msg)
+{
+ FILE *fp;
+ struct stat s;
+ char seq[8];
+ char buf[LONG_STRING];
+
+ if (stat (msg->path, &s) == -1)
+ {
+ mutt_perror (msg->path);
+ return (-1);
+ }
+
+ if ((fp = safe_fopen (msg->path, "r")) == NULL)
+ {
+ mutt_perror (msg->path);
+ return (-1);
+ }
+
+ mutt_message ("Sending APPEND command ...");
+ imap_make_sequence (seq, sizeof (seq), ctx);
+ snprintf (buf, sizeof (buf), "%s APPEND %s {%d}\r\n", seq,
+ CTX_DATA->mailbox, s.st_size);
+
+ imap_write (CTX_DATA->conn, buf);
+
+ do
+ {
+ if (imap_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0)
+ {
+ fclose (fp);
+ return (-1);
+ }
+
+ if (buf[0] == '*' && imap_handle_untagged (ctx, buf) != 0)
+ {
+ return (-1);
+ fclose (fp);
+ }
+ }
+ while ((strncmp (buf, seq, SEQLEN) != 0) && (buf[0] != '+'));
+
+ if (buf[0] != '+')
+ {
+ char *pc;
+
+ dprint (1, (debugfile, "imap_append_message(): command failed: %s\n", buf));
+
+ pc = buf + SEQLEN;
+ SKIPWS (pc);
+ pc = imap_next_word (pc);
+ mutt_error (pc);
+ sleep (1);
+ fclose (fp);
+ return (-1);
+ }
+
+ mutt_message ("Uploading message ...");
+ while (fgets (buf, sizeof (buf), fp) != NULL)
+ {
+ imap_write (CTX_DATA->conn, buf);
+ }
+ imap_write (CTX_DATA->conn, "\r\n");
+ fclose (fp);
+
+ do
+ {
+ if (imap_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0)
+ return (-1);
+
+ if (buf[0] == '*' && imap_handle_untagged (ctx, buf) != 0)
+ return (-1);
+ }
+ while (strncmp (buf, seq, SEQLEN) != 0);
+
+ if (!imap_code (buf))
+ {
+ char *pc;
+
+ dprint (1, (debugfile, "imap_append_message(): command failed: %s\n", buf));
+ pc = buf + SEQLEN;
+ SKIPWS (pc);
+ pc = imap_next_word (pc);
+ mutt_error (pc);
+ sleep (1);
+ return (-1);
+ }
+
+ return 0;
+}
+
int imap_close_connection (CONTEXT *ctx)
{
char buf[LONG_STRING];
char seq[8];
/* if the server didn't shut down on us, close the connection gracefully */
- if (((IMAP_DATA *) ctx->data)->status != IMAP_BYE)
+ if (CTX_DATA->status != IMAP_BYE)
{
mutt_message ("Closing connection to IMAP server...");
imap_make_sequence (seq, sizeof (seq), ctx);
snprintf (buf, sizeof (buf), "%s LOGOUT\r\n", seq);
- imap_write (ctx->fd, buf);
+ imap_write (CTX_DATA->conn, buf);
do
{
- if (imap_read_line_d (buf, sizeof (buf), ctx->fd) < 0)
+ if (imap_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0)
break;
}
while (strncmp (seq, buf, SEQLEN) != 0);
mutt_clear_error ();
}
- close (ctx->fd);
+ close (CTX_DATA->conn->fd);
+ CTX_DATA->conn->uses--;
return 0;
}
@@ -840,11 +1073,11 @@ int imap_sync_mailbox (CONTEXT *ctx)
/* save status changes */
for (n = 0; n < ctx->msgcount; n++)
{
- snprintf (tmp, sizeof (tmp), "Saving message status flags... [%d/%d]", n+1,
- ctx->msgcount);
- mutt_message (tmp);
if (ctx->hdrs[n]->deleted || ctx->hdrs[n]->changed)
{
+ snprintf (tmp, sizeof (tmp), "Saving message status flags... [%d/%d]", n+1,
+ ctx->msgcount);
+ mutt_message (tmp);
*tmp = 0;
if (ctx->hdrs[n]->read)
strcat (tmp, "\\Seen ");
@@ -860,7 +1093,7 @@ int imap_sync_mailbox (CONTEXT *ctx)
imap_make_sequence (seq, sizeof (seq), ctx);
snprintf (buf, sizeof (buf), "%s STORE %d FLAGS.SILENT (%s)\r\n", seq,
ctx->hdrs[n]->index + 1, tmp);
- if (imap_exec (buf, sizeof (buf), ctx, seq, buf) != 0)
+ if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0)
{
imap_error ("imap_sync_mailbox()", buf);
return (-1);
@@ -869,17 +1102,25 @@ int imap_sync_mailbox (CONTEXT *ctx)
}
mutt_message ("Expunging messages from server...");
- ((IMAP_DATA *) ctx->data)->status = IMAP_EXPUNGE;
+ CTX_DATA->status = IMAP_EXPUNGE;
imap_make_sequence (seq, sizeof (seq), ctx);
snprintf (buf, sizeof (buf), "%s EXPUNGE\r\n", seq);
- if (imap_exec (buf, sizeof (buf), ctx, seq, buf) != 0)
+ if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0)
{
imap_error ("imap_sync_mailbox()", buf);
return (-1);
}
- ((IMAP_DATA *) ctx->data)->status = 0;
- /* WARNING: Messages need to be reindexed at this point after the expunge, or */
- /* mutt will become -very- confused unless it's quitting. */
+ CTX_DATA->status = 0;
+
+ for (n = 0; n < IMAP_CACHE_LEN; n++)
+ {
+ if (CTX_DATA->cache[n].path)
+ {
+ unlink (CTX_DATA->cache[n].path);
+ safe_free ((void **) &CTX_DATA->cache[n].path);
+ }
+ }
+
return 0;
}
@@ -887,13 +1128,16 @@ void imap_fastclose_mailbox (CONTEXT *ctx)
{
int i;
+ /* Check to see if the mailbox is actually open */
+ if (!ctx->data)
+ return;
imap_close_connection (ctx);
for (i = 0; i < IMAP_CACHE_LEN; i++)
{
- if (((IMAP_DATA *) ctx->data)->cache[i].path)
+ if (CTX_DATA->cache[i].path)
{
- unlink (((IMAP_DATA *) ctx->data)->cache[i].path);
- safe_free ((void **) &((IMAP_DATA *) ctx->data)->cache[i].path);
+ unlink (CTX_DATA->cache[i].path);
+ safe_free ((void **) &CTX_DATA->cache[i].path);
}
}
safe_free ((void **) &ctx->data);
@@ -909,7 +1153,7 @@ int imap_close_mailbox (CONTEXT *ctx)
mutt_message ("Closing mailbox...");
imap_make_sequence (seq, sizeof (seq), ctx);
snprintf (buf, sizeof (buf), "%s CLOSE\r\n", seq);
- if (imap_exec (buf, sizeof (buf), ctx, seq, buf) != 0)
+ if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0)
{
imap_error ("imap_close_mailbox()", buf);
return (-1);
@@ -934,7 +1178,7 @@ int imap_check_mailbox (CONTEXT *ctx, int *index_hint)
imap_make_sequence (seq, sizeof (seq), ctx);
snprintf (buf, sizeof (buf), "%s NOOP\r\n", seq);
- if (imap_exec (buf, sizeof (buf), ctx, seq, buf) != 0)
+ if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0)
{
imap_error ("imap_check_mailbox()", buf);
return (-1);