From a07d9f79f6a533ec83d64dda1c824e3a81c2d493 Mon Sep 17 00:00:00 2001 From: Thomas Roessler Date: Mon, 15 Jun 1998 15:19:45 +0000 Subject: Brandon's IMAP patch. --- imap.c | 498 ++++++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 371 insertions(+), 127 deletions(-) (limited to 'imap.c') diff --git a/imap.c b/imap.c index 619482c7..872e019b 100644 --- a/imap.c +++ b/imap.c @@ -30,6 +30,7 @@ #include #include #include +#include /* Minimal support for IMAP 4rev1 */ @@ -45,9 +46,21 @@ 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; @@ -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); -- cgit v1.2.3