From 585a2cf18f58c3b0080fabcb680192c6963e1653 Mon Sep 17 00:00:00 2001 From: Thomas Roessler Date: Thu, 6 Jul 2000 06:36:45 +0000 Subject: [PATCH] More IMAP fixes from Brendan Cully. --- imap/browse.c | 2 +- imap/command.c | 5 ++- imap/imap.c | 27 ++++++------ imap/imap_private.h | 1 + imap/imap_socket.h | 11 +++-- imap/message.c | 21 ++++----- imap/socket.c | 101 +++++++++++++++++++++++--------------------- imap/util.c | 20 +++++++++ 8 files changed, 109 insertions(+), 79 deletions(-) diff --git a/imap/browse.c b/imap/browse.c index 4ac57f14..5e6c85b6 100644 --- a/imap/browse.c +++ b/imap/browse.c @@ -66,7 +66,7 @@ int imap_init_browse (char *path, struct browser_state *state) strfcpy (list_cmd, option (OPTIMAPLSUB) ? "LSUB" : "LIST", sizeof (list_cmd)); - conn = mutt_socket_select_connection (&mx, 0); + conn = mutt_socket_find (&mx, 0); idata = CONN_DATA; if (!idata || (idata->state == IMAP_DISCONNECTED)) diff --git a/imap/command.c b/imap/command.c index cfa7deba..28c6bee9 100644 --- a/imap/command.c +++ b/imap/command.c @@ -257,9 +257,10 @@ int imap_handle_untagged (IMAP_DATA *idata, char *s) idata->status = IMAP_BYE; if (idata->state == IMAP_SELECTED) mx_fastclose_mailbox (idata->selected_ctx); - mutt_socket_close_connection (idata->conn); + mutt_socket_close (idata->conn); idata->state = IMAP_DISCONNECTED; - return (-1); + + return -1; } else if (option (OPTIMAPSERVERNOISE) && (mutt_strncasecmp ("NO", s, 2) == 0)) { diff --git a/imap/imap.c b/imap/imap.c index c796c2d5..67a8ebbc 100644 --- a/imap/imap.c +++ b/imap/imap.c @@ -421,15 +421,16 @@ int imap_open_connection (IMAP_DATA *idata, CONNECTION *conn) { char buf[LONG_STRING]; - if (mutt_socket_open_connection (conn) < 0) + if (mutt_socket_open (conn) < 0) return -1; idata->state = IMAP_CONNECTED; if (mutt_socket_read_line_d (buf, sizeof (buf), conn) < 0) { - mutt_socket_close_connection (conn); + mutt_socket_close (conn); idata->state = IMAP_DISCONNECTED; + return -1; } @@ -438,7 +439,7 @@ int imap_open_connection (IMAP_DATA *idata, CONNECTION *conn) if (imap_check_capabilities(idata) != 0 || imap_authenticate (idata, conn) != 0) { - mutt_socket_close_connection (conn); + mutt_socket_close (conn); idata->state = IMAP_DISCONNECTED; return -1; } @@ -447,7 +448,7 @@ int imap_open_connection (IMAP_DATA *idata, CONNECTION *conn) { if (imap_check_capabilities(idata) != 0) { - mutt_socket_close_connection (conn); + mutt_socket_close (conn); idata->state = IMAP_DISCONNECTED; return -1; } @@ -455,7 +456,7 @@ int imap_open_connection (IMAP_DATA *idata, CONNECTION *conn) else { imap_error ("imap_open_connection()", buf); - mutt_socket_close_connection (conn); + mutt_socket_close (conn); idata->state = IMAP_DISCONNECTED; return -1; } @@ -540,7 +541,7 @@ int imap_open_mailbox (CONTEXT *ctx) return -1; } - conn = mutt_socket_select_connection (&mx, 0); + conn = mutt_socket_find (&mx, 0); idata = CONN_DATA; if (!idata || (idata->state != IMAP_AUTHENTICATED)) @@ -551,7 +552,7 @@ int imap_open_mailbox (CONTEXT *ctx) /* We need to create a new connection, the current one isn't useful */ idata = safe_calloc (1, sizeof (IMAP_DATA)); - conn = mutt_socket_select_connection (&mx, 1); + conn = mutt_socket_find (&mx, 1); conn->data = idata; idata->conn = conn; } @@ -721,7 +722,7 @@ int imap_select_mailbox (CONTEXT* ctx, const char* path) return -1; /* and that it's on the same server as the current folder */ - conn = mutt_socket_select_connection (&mx, 0); + conn = mutt_socket_find (&mx, 0); if (!CTX_DATA || !CONN_DATA || (CTX_DATA->conn != CONN_DATA->conn)) { dprint(2, (debugfile, @@ -755,7 +756,7 @@ int imap_open_mailbox_append (CONTEXT *ctx) ctx->magic = M_IMAP; - conn = mutt_socket_select_connection (&mx, 0); + conn = mutt_socket_find (&mx, 0); idata = CONN_DATA; if (!idata || (idata->state == IMAP_DISCONNECTED)) @@ -838,7 +839,7 @@ int imap_close_connection (CONTEXT *ctx) while (mutt_strncmp (seq, buf, SEQLEN) != 0); mutt_clear_error (); } - mutt_socket_close_connection (CTX_DATA->conn); + mutt_socket_close (CTX_DATA->conn); CTX_DATA->state = IMAP_DISCONNECTED; CTX_DATA->conn->data = NULL; return 0; @@ -1197,7 +1198,7 @@ int imap_mailbox_check (char *path, int new) if (imap_parse_path (path, &mx)) return -1; - conn = mutt_socket_select_connection (&mx, 0); + conn = mutt_socket_find (&mx, 0); idata = CONN_DATA; if (!idata || (idata->state == IMAP_DISCONNECTED)) @@ -1377,7 +1378,7 @@ int imap_subscribe (char *path, int subscribe) if (imap_parse_path (path, &mx)) return (-1); - conn = mutt_socket_select_connection (&mx, 0); + conn = mutt_socket_find (&mx, 0); idata = CONN_DATA; if (!idata || (idata->state == IMAP_DISCONNECTED)) @@ -1433,7 +1434,7 @@ int imap_complete(char* dest, size_t dlen, char* path) { return -1; } - conn = mutt_socket_select_connection (&mx, 0); + conn = mutt_socket_find (&mx, 0); idata = CONN_DATA; /* don't open a new socket just for completion */ diff --git a/imap/imap_private.h b/imap/imap_private.h index 2572efe1..ae5847da 100644 --- a/imap/imap_private.h +++ b/imap/imap_private.h @@ -187,6 +187,7 @@ void imap_free_header_data (void** data); int imap_read_headers (CONTEXT* ctx, int msgbegin, int msgend); /* util.c */ +int imap_account_match (const IMAP_MBOX* m1, const IMAP_MBOX* m2); int imap_continue (const char* msg, const char* resp); void imap_error (const char* where, const char* msg); char* imap_fix_path (IMAP_DATA* idata, char* mailbox, char* path, diff --git a/imap/imap_socket.h b/imap/imap_socket.h index 8a164928..d868fd6e 100644 --- a/imap/imap_socket.h +++ b/imap/imap_socket.h @@ -36,16 +36,19 @@ typedef struct _connection int (*write) (struct _connection *conn, const char *buf); int (*open) (struct _connection *conn); int (*close) (struct _connection *conn); -} CONNECTION; + /* status bits */ + int up : 1; +} CONNECTION; +int mutt_socket_open (CONNECTION* conn); +int mutt_socket_close (CONNECTION* conn); int mutt_socket_readchar (CONNECTION *conn, char *c); int mutt_socket_read_line (char *buf, size_t buflen, CONNECTION *conn); int mutt_socket_read_line_d (char *buf, size_t buflen, CONNECTION *conn); int mutt_socket_write (CONNECTION *conn, const char *buf); -CONNECTION *mutt_socket_select_connection (const IMAP_MBOX *mx, int newconn); -int mutt_socket_open_connection (CONNECTION *conn); -int mutt_socket_close_connection (CONNECTION *conn); + +CONNECTION* mutt_socket_find (const IMAP_MBOX* mx, int newconn); int raw_socket_read (CONNECTION *conn); int raw_socket_write (CONNECTION *conn, const char *buf); diff --git a/imap/message.c b/imap/message.c index 8bf9c91e..197edba2 100644 --- a/imap/message.c +++ b/imap/message.c @@ -56,7 +56,6 @@ int imap_read_headers (CONTEXT *ctx, int msgbegin, int msgend) IMAP_HEADER *h, *h0; const char *want_headers = "DATE FROM SUBJECT TO CC MESSAGE-ID REFERENCES CONTENT-TYPE IN-REPLY-TO REPLY-TO LINES X-LABEL"; int using_body_peek = 0; - int c; fetchlast = 0; @@ -164,6 +163,13 @@ int imap_read_headers (CONTEXT *ctx, int msgbegin, int msgend) return -1; } imap_read_bytes (fp, CTX_DATA->conn, bytes); + /* make sure headers are followed by ONE blank line (separator + * for mutt_read_rfc822_header) */ + do + fseek (fp, -2, SEEK_CUR); + while (fgetc (fp) == '\n'); + fputs ("\n\n", fp); + /* we may have other fields of the FETCH _after_ the literal * (eg Domino puts FLAGS here). Nothing wrong with that, either. * This all has to go - we should accept literals and nonliterals @@ -257,15 +263,6 @@ int imap_read_headers (CONTEXT *ctx, int msgbegin, int msgend) h = h->next; /* hdata is freed later */ safe_free ((void **) &h0); - - /* - * skip over additional \n characters - Courier IMAP seems to - * put them here. - */ - - while ((c = fgetc (fp)) == '\n') - ; - ungetc (c, fp); } fclose(fp); @@ -597,8 +594,8 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete) return -1; } - /* check that the save-to folder is on the same server */ - if (mutt_socket_select_connection (&mx, 0) != CTX_DATA->conn) + /* check that the save-to folder is in the same account */ + if (!imap_account_match (&(CTX_DATA->conn->mx), &mx)) { dprint (3, (debugfile, "imap_copy_message: %s not same server as %s\n", dest, ctx->path)); diff --git a/imap/socket.c b/imap/socket.c index d621f923..adf7b3e5 100644 --- a/imap/socket.c +++ b/imap/socket.c @@ -1,5 +1,7 @@ /* * Copyright (C) 1998 Michael R. Elkins + * Copyright (C) 1999-2000 Brendan Cully + * Copyright (C) 1999-2000 Tommi Komulainen * * 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 @@ -34,18 +36,29 @@ #include /* support for multiple socket connections */ - static CONNECTION *Connections = NULL; +/* forward declarations */ +static int socket_connect (CONNECTION* conn, struct sockaddr_in sin, + int verbose); +static CONNECTION* socket_new_conn (); /* Wrappers */ -int mutt_socket_open_connection (CONNECTION *conn) +int mutt_socket_open (CONNECTION* conn) { - return conn->open (conn); + int rc; + + rc = conn->open (conn); + if (!rc) + conn->up = 1; + + return rc; } -int mutt_socket_close_connection (CONNECTION *conn) +int mutt_socket_close (CONNECTION* conn) { + conn->up = 0; + return conn->close (conn); } @@ -55,8 +68,6 @@ int mutt_socket_write (CONNECTION *conn, const char *buf) return conn->write (conn, buf); } - - /* simple read buffering to speed things up. */ int mutt_socket_readchar (CONNECTION *conn, char *c) { @@ -99,28 +110,9 @@ int mutt_socket_read_line_d (char *buf, size_t buflen, CONNECTION *conn) return r; } -/* imap_account_match: compare account info (host/port/user) */ -static int imap_account_match (const IMAP_MBOX *m1, const IMAP_MBOX *m2) +CONNECTION* mutt_socket_find (const IMAP_MBOX* mx, int newconn) { - const char *user = ImapUser ? ImapUser : NONULL (Username); - - if (mutt_strcasecmp (m1->host, m2->host)) - return 0; - if (m1->port != m2->port) - return 0; - - if (m1->flags & m2->flags & M_IMAP_USER) - return (!strcmp (m1->user, m2->user)); - if (m1->flags & M_IMAP_USER) - return (!strcmp (m1->user, user)); - if (m2->flags & M_IMAP_USER) - return (!strcmp (m2->user, user)); - return 1; -} - -CONNECTION *mutt_socket_select_connection (const IMAP_MBOX *mx, int newconn) -{ - CONNECTION *conn; + CONNECTION* conn; if (! newconn) { @@ -132,11 +124,11 @@ CONNECTION *mutt_socket_select_connection (const IMAP_MBOX *mx, int newconn) conn = conn->next; } } - conn = (CONNECTION *) safe_calloc (1, sizeof (CONNECTION)); - conn->fd = -1; + + conn = socket_new_conn (); memcpy (&conn->mx, mx, sizeof (conn->mx)); conn->mx.mbox = 0; - conn->preconnect = safe_strdup (ImapPreconnect); + conn->next = Connections; Connections = conn; @@ -161,16 +153,15 @@ CONNECTION *mutt_socket_select_connection (const IMAP_MBOX *mx, int newconn) * make sure we've got all the context we need. */ void imap_logout_all (void) { - CONNECTION* conn, *tmp; - char buf[LONG_STRING]; + CONNECTION* conn; + char buf[SHORT_STRING]; char seq[SEQLEN+1]; conn = Connections; while (conn) { - /* what's up here? the last connection doesn't seem to be used */ - if (conn->fd >= 0) + if (conn->up) { snprintf (buf, sizeof (buf), _("Closing connection to %s..."), conn->mx.host); @@ -188,31 +179,33 @@ void imap_logout_all (void) } while (mutt_strncmp (buf, seq, SEQLEN) != 0); mutt_clear_error (); + + mutt_socket_close (conn); } - tmp = conn; - conn = conn->next; + Connections = conn->next; - mutt_socket_close_connection (tmp); - - if (tmp->data) { + if (conn->data) { dprint (2, (debugfile, "imap_logout_all: Connection still has valid CONTEXT?!\n")); } - free (tmp); + free (conn); + + conn = Connections; } } - -static int try_socket_and_connect (CONNECTION *conn, struct sockaddr_in sin, - int verbose) +/* socket_connect: attempt to bind a socket and connect to it */ +static int socket_connect (CONNECTION* conn, struct sockaddr_in sin, + int verbose) { if ((conn->fd = socket (AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0) { if (verbose) mutt_perror ("socket"); - return (-1); + + return -1; } if (connect (conn->fd, (struct sockaddr *) &sin, sizeof (sin)) < 0) @@ -223,12 +216,25 @@ static int try_socket_and_connect (CONNECTION *conn, struct sockaddr_in sin, mutt_perror ("connect"); sleep (1); } - return (-1); + + return -1; } return 0; } +/* socket_new_conn: allocate and initialise a new connection. */ +static CONNECTION* socket_new_conn () +{ + CONNECTION* conn; + + conn = (CONNECTION *) safe_calloc (1, sizeof (CONNECTION)); + conn->preconnect = safe_strdup (ImapPreconnect); + conn->fd = -1; + + return conn; +} + int raw_socket_close (CONNECTION *conn) { int ret = close (conn->fd); @@ -272,7 +278,7 @@ int raw_socket_open (CONNECTION *conn) if (do_preconnect && first_try_without_preconnect) { verbose = FALSE; - if (try_socket_and_connect (conn, sin, verbose) == 0) + if (socket_connect (conn, sin, verbose) == 0) return 0; } @@ -294,5 +300,6 @@ int raw_socket_open (CONNECTION *conn) } verbose = TRUE; - return try_socket_and_connect (conn, sin, verbose); + + return socket_connect (conn, sin, verbose); } diff --git a/imap/util.c b/imap/util.c index 6e959fc4..e36d91d2 100644 --- a/imap/util.c +++ b/imap/util.c @@ -34,6 +34,26 @@ #include +/* imap_account_match: compare account info (host/port/user) */ +int imap_account_match (const IMAP_MBOX* m1, const IMAP_MBOX* m2) +{ + const char* user = ImapUser ? ImapUser : NONULL (Username); + + if (mutt_strcasecmp (m1->host, m2->host)) + return 0; + if (m1->port != m2->port) + return 0; + + if (m1->flags & m2->flags & M_IMAP_USER) + return (!strcmp (m1->user, m2->user)); + if (m1->flags & M_IMAP_USER) + return (!strcmp (m1->user, user)); + if (m2->flags & M_IMAP_USER) + return (!strcmp (m2->user, user)); + + return 1; +} + /* imap_continue: display a message and ask the user if she wants to * go on. */ int imap_continue (const char* msg, const char* resp) -- 2.40.0