From a632b853e8703cc0ad16c95d8411c5bc6252874a Mon Sep 17 00:00:00 2001 From: Thomas Roessler Date: Mon, 12 Feb 2001 10:27:10 +0000 Subject: Brendan Cully's SASL patch. --- imap/auth_login.c | 5 +-- imap/auth_sasl.c | 50 ++++------------------ imap/browse.c | 13 +++--- imap/command.c | 93 ++++++++++++++++++++++------------------- imap/imap.c | 118 ++++++++++++++++------------------------------------ imap/imap_private.h | 36 +++++++++++----- imap/message.c | 34 ++++++++------- imap/util.c | 79 ++++++++++++++++++++++++++++++++++- 8 files changed, 226 insertions(+), 202 deletions(-) (limited to 'imap') 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 + * Copyright (C) 1999-2001 Brendan Cully * * 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 -#include - #include #include @@ -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 - * Copyright (C) 1999-2000 Brendan Cully + * Copyright (C) 1999-2001 Brendan Cully * * 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 * Copyright (C) 1996-9 Brandon Long - * Copyright (C) 1999-2000 Brendan Cully + * Copyright (C) 1999-2001 Brendan Cully * * 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 * Copyright (C) 1996-9 Brandon Long - * Copyright (C) 1999-2000 Brendan Cully + * Copyright (C) 1999-2001 Brendan Cully * * 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 - * Copyright (C) 1999-2000 Brendan Cully + * Copyright (C) 1999-2001 Brendan Cully * * 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 */ +/* OK ... */ +#define IMAP_CMD_OK (0) +/* BAD ... */ +#define IMAP_CMD_BAD (-1) +/* 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 * Copyright (C) 1996-9 Brandon Long - * Copyright (C) 1999-2000 Brendan Cully + * Copyright (C) 1999-2001 Brendan Cully * * 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')) * 3600 + + ((s[3] - '0') * 10 + (s[4] - '0')) * 60; + if (s[0] == '+') + tz = -tz; + + return (mutt_mktime (&t, 0) + tz); +} + /* imap_parse_path: given an IMAP mailbox name, return host, port * and a path IMAP servers will recognise. * mx.mbox is malloc'd, caller must free it */ -- cgit v1.2.3