From: Thomas Roessler Date: Thu, 9 Dec 1999 11:17:04 +0000 (+0000) Subject: Tommi Komulainen's multiple IMAP usernames patch. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f9a796c9da896d519db16bed4b9426ff9785cea8;p=neomutt Tommi Komulainen's multiple IMAP usernames patch. --- diff --git a/browser.c b/browser.c index 0973ebaee..0f4f04ce1 100644 --- a/browser.c +++ b/browser.c @@ -808,16 +808,15 @@ void _mutt_select_file (char *f, size_t flen, int buffy, else { char msg[LONG_STRING]; - char* mbox; + IMAP_MBOX mx; int nentry = menu->current; - imap_parse_path (state.entry[nentry].name, NULL, 0, NULL, - NULL, &mbox); + imap_parse_path (state.entry[nentry].name, &mx); snprintf (msg, sizeof (msg), _("Really delete mailbox \"%s\"?"), - mbox); + mx.mbox); if (mutt_yesorno (msg, M_NO) == M_YES) { - if (!imap_delete_mailbox (Context, mbox)) + if (!imap_delete_mailbox (Context, mx.mbox)) { /* free the mailbox from the browser */ safe_free ((void **) &((state.entry)[nentry].name)); diff --git a/doc/manual.sgml.head b/doc/manual.sgml.head index 66278a8b8..ead39e7ff 100644 --- a/doc/manual.sgml.head +++ b/doc/manual.sgml.head @@ -1959,11 +1959,14 @@ server, you should use {imapserver}path/to/folder where You can select an alternative port by specifying it with the server, ie: {imapserver[:port]/ssl}path/to/folder as your +use {[username@]imapserver[:port]/ssl}path/to/folder as your folder path. Note that not all servers use / as the hierarchy separator. Mutt should diff --git a/imap/README b/imap/README index b45706ad5..d12712bcd 100644 --- a/imap/README +++ b/imap/README @@ -26,3 +26,4 @@ New features vs. the stable distribution: * Preserve message keywords * Preserve deleted messages if you don't choose to expunge them * Delete mailboxes (from the browser) +* Multiple IMAP usernames diff --git a/imap/auth.c b/imap/auth.c index 6f85acc20..73ac9fb09 100644 --- a/imap/auth.c +++ b/imap/auth.c @@ -121,7 +121,7 @@ static int imap_auth_gss (IMAP_DATA* idata, const char* user) dprint (2, (debugfile, "Attempting GSS login...\n")); /* get an IMAP service ticket for the server */ - snprintf (buf1, sizeof (buf1), "imap@%s", idata->conn->server); + snprintf (buf1, sizeof (buf1), "imap@%s", idata->conn->mx.host); request_buf.value = buf1; request_buf.length = strlen (buf1) + 1; maj_stat = gss_import_name (&min_stat, &request_buf, gss_nt_service_name, @@ -477,17 +477,22 @@ int imap_authenticate (IMAP_DATA *idata, CONNECTION *conn) while (r != 0) { - if (!ImapUser) + if (! (conn->mx.flags & M_IMAP_USER)) { - strfcpy (user, NONULL(Username), sizeof (user)); - if (mutt_get_field (_("IMAP Username: "), user, sizeof (user), 0) != 0) + if (!ImapUser) { - user[0] = 0; - return (-1); + strfcpy (user, NONULL(Username), sizeof (user)); + if (mutt_get_field (_("IMAP Username: "), user, sizeof (user), 0) != 0) + { + user[0] = 0; + return (-1); + } } + else + strfcpy (user, ImapUser, sizeof (user)); } else - strfcpy (user, ImapUser, sizeof (user)); + strfcpy (user, conn->mx.user, sizeof (user)); if (!user[0]) { @@ -519,16 +524,21 @@ int imap_authenticate (IMAP_DATA *idata, CONNECTION *conn) /* attempt CRAM-MD5 if available */ if (mutt_bit_isset (idata->capabilities, ACRAM_MD5)) { - if (!ImapCRAMKey) + if (!(conn->mx.flags & M_IMAP_CRAM)) { - ckey[0] = '\0'; - snprintf (buf, sizeof (buf), _("CRAM key for %s@%s: "), user, - conn->server); - if (mutt_get_field (buf, ckey, sizeof (ckey), M_PASS) != 0) - return -1; + if (!ImapCRAMKey) + { + ckey[0] = '\0'; + snprintf (buf, sizeof (buf), _("CRAM key for %s@%s: "), user, + conn->mx.host); + if (mutt_get_field (buf, ckey, sizeof (ckey), M_PASS) != 0) + return -1; + } + else + strfcpy (ckey, ImapCRAMKey, sizeof (ckey)); } else - strfcpy (ckey, ImapCRAMKey, sizeof (ckey)); + strfcpy (ckey, conn->mx.pass, sizeof (ckey)); if (*ckey) { @@ -536,9 +546,16 @@ int imap_authenticate (IMAP_DATA *idata, CONNECTION *conn) { mutt_error _("CRAM-MD5 authentication failed."); sleep (1); + if (!(conn->mx.flags & M_IMAP_CRAM)) + FREE (&ImapCRAMKey); + conn->mx.flags &= ~M_IMAP_CRAM; } else + { + strfcpy (conn->mx.pass, ckey, sizeof (conn->mx.pass)); + conn->mx.flags |= M_IMAP_CRAM; return 0; + } } else { @@ -549,18 +566,23 @@ int imap_authenticate (IMAP_DATA *idata, CONNECTION *conn) else dprint (2, (debugfile, "CRAM-MD5 authentication is not available\n")); - if (!ImapPass) + if (! (conn->mx.flags & M_IMAP_PASS)) { - pass[0]=0; - snprintf (buf, sizeof (buf), _("Password for %s@%s: "), user, conn->server); - if (mutt_get_field (buf, pass, sizeof (pass), M_PASS) != 0 || - !pass[0]) + if (!ImapPass) { - return (-1); + pass[0]=0; + snprintf (buf, sizeof (buf), _("Password for %s@%s: "), user, conn->mx.host); + if (mutt_get_field (buf, pass, sizeof (pass), M_PASS) != 0 || + !pass[0]) + { + return (-1); + } } + else + strfcpy (pass, ImapPass, sizeof (pass)); } else - strfcpy (pass, ImapPass, sizeof (pass)); + strfcpy (pass, conn->mx.pass, sizeof (pass)); imap_quote_string (q_user, sizeof (q_user), user); imap_quote_string (q_pass, sizeof (q_pass), pass); @@ -580,17 +602,22 @@ int imap_authenticate (IMAP_DATA *idata, CONNECTION *conn) mutt_error _("Login failed."); sleep (1); - FREE (&ImapUser); - FREE (&ImapPass); + if (!(conn->mx.flags & M_IMAP_USER)) + FREE (&ImapUser); + if (!(conn->mx.flags & M_IMAP_PASS)) + FREE (&ImapPass); + conn->mx.flags &= ~M_IMAP_PASS; } else { /* If they have a successful login, we may as well cache the * user/password. */ - if (!ImapUser) - ImapUser = safe_strdup (user); - if (!ImapPass) - ImapPass = safe_strdup (pass); + if (!(conn->mx.flags & M_IMAP_USER)) + strfcpy (conn->mx.user, user, sizeof (conn->mx.user)); + if (!(conn->mx.flags & M_IMAP_PASS)) + strfcpy (conn->mx.pass, pass, sizeof (conn->mx.pass)); + + conn->mx.flags |= (M_IMAP_USER | M_IMAP_PASS); } } return 0; diff --git a/imap/browse.c b/imap/browse.c index 5769ec33e..adb354f75 100644 --- a/imap/browse.c +++ b/imap/browse.c @@ -43,11 +43,8 @@ int imap_init_browse (char *path, struct browser_state *state) char buf[LONG_STRING]; char nsbuf[LONG_STRING]; char mbox[LONG_STRING]; - char host[SHORT_STRING]; - int port; char list_cmd[5]; char seq[16]; - char *ipath = NULL; IMAP_NAMESPACE_INFO nsi[16]; int home_namespace = 0; int n; @@ -59,8 +56,9 @@ int imap_init_browse (char *path, struct browser_state *state) short showparents = 0; int noselect; int noinferiors; + IMAP_MBOX mx; - if (imap_parse_path (path, host, sizeof (host), &port, NULL, &ipath)) + if (imap_parse_path (path, &mx)) { mutt_error ("%s is an invalid IMAP path", path); return -1; @@ -68,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 (host, port, 0); + conn = mutt_socket_select_connection (&mx, 0); idata = CONN_DATA; if (!idata || (idata->state == IMAP_DISCONNECTED)) @@ -84,11 +82,11 @@ int imap_init_browse (char *path, struct browser_state *state) return (-1); } - if (ipath[0] == '\0') + if (mx.mbox[0] == '\0') { home_namespace = 1; mbox[0] = 0; /* Do not replace "" with "INBOX" here */ - ipath = ImapHomeNamespace; + mx.mbox = ImapHomeNamespace; nns = 0; if (mutt_bit_isset(idata->capabilities,NAMESPACE)) { @@ -98,13 +96,13 @@ int imap_init_browse (char *path, struct browser_state *state) if (verify_namespace (conn, nsi, nns) != 0) return (-1); } - if (!ipath) /* Any explicitly set imap_home_namespace wins */ + if (!mx.mbox) /* Any explicitly set imap_home_namespace wins */ { for (i = 0; i < nns; i++) if (nsi[i].listable && (nsi[i].type == IMAP_NS_PERSONAL || nsi[i].type == IMAP_NS_SHARED)) { - ipath = nsi->prefix; + mx.mbox = nsi->prefix; nsi->home_namespace = 1; break; } @@ -113,9 +111,9 @@ int imap_init_browse (char *path, struct browser_state *state) mutt_message _("Contacted server, getting folder list..."); - if (ipath && ipath[0] != '\0') + if (mx.mbox && mx.mbox[0] != '\0') { - imap_fix_path (idata, ipath, mbox, sizeof (mbox)); + imap_fix_path (idata, mx.mbox, mbox, sizeof (mbox)); n = mutt_strlen (mbox); dprint (3, (debugfile, "imap_init_browse: mbox: %s\n", mbox)); @@ -153,7 +151,7 @@ int imap_init_browse (char *path, struct browser_state *state) if (mbox[n-1] == idata->delim) { showparents = 1; - imap_qualify_path (buf, sizeof (buf), host, port, mbox, NULL); + imap_qualify_path (buf, sizeof (buf), &mx, mbox, NULL); state->folder = safe_strdup (buf); n--; } @@ -182,7 +180,7 @@ int imap_init_browse (char *path, struct browser_state *state) mbox[n++] = ctmp; ctmp = mbox[n]; mbox[n] = '\0'; - imap_qualify_path (buf, sizeof (buf), host, port, mbox, NULL); + imap_qualify_path (buf, sizeof (buf), &mx, mbox, NULL); state->folder = safe_strdup (buf); } mbox[n] = ctmp; @@ -197,7 +195,7 @@ int imap_init_browse (char *path, struct browser_state *state) imap_add_folder (idata->delim, relpath, 1, 0, state, 1); if (!state->folder) { - imap_qualify_path (buf, sizeof (buf), host, port, relpath, NULL); + imap_qualify_path (buf, sizeof (buf), &mx, relpath, NULL); state->folder = safe_strdup (buf); } } @@ -206,7 +204,7 @@ int imap_init_browse (char *path, struct browser_state *state) /* no namespace, no folder: set folder to host only */ if (!state->folder) { - imap_qualify_path (buf, sizeof (buf), host, port, NULL, NULL); + imap_qualify_path (buf, sizeof (buf), &mx, NULL, NULL); state->folder = safe_strdup (buf); } @@ -248,14 +246,12 @@ static int add_list_result (CONNECTION *conn, const char *seq, const char *cmd, { IMAP_DATA *idata = CONN_DATA; char buf[LONG_STRING]; - char host[SHORT_STRING]; - int port; - char *curfolder; char *name; int noselect; int noinferiors; + IMAP_MBOX mx; - if (imap_parse_path (state->folder, host, sizeof (host), &port, NULL, &curfolder)) + if (imap_parse_path (state->folder, &mx)) { dprint (2, (debugfile, "add_list_result: current folder %s makes no sense\n", state->folder)); @@ -277,7 +273,7 @@ static int add_list_result (CONNECTION *conn, const char *seq, const char *cmd, if (isparent) noselect = 1; /* prune current folder from output */ - if (isparent || strncmp (name, curfolder, strlen (name))) + if (isparent || strncmp (name, mx.mbox, strlen (name))) imap_add_folder (idata->delim, name, noselect, noinferiors, state, isparent); } @@ -294,12 +290,10 @@ static void imap_add_folder (char delim, char *folder, int noselect, { char tmp[LONG_STRING]; char relpath[LONG_STRING]; - char host[SHORT_STRING]; - int port; - char *curfolder; int flen = strlen (folder); + IMAP_MBOX mx; - if (imap_parse_path (state->folder, host, sizeof (host), &port, NULL, &curfolder)) + if (imap_parse_path (state->folder, &mx)) return; imap_unquote_string (folder); @@ -320,8 +314,8 @@ static void imap_add_folder (char delim, char *folder, int noselect, if (isparent) strfcpy (relpath, "../", sizeof (relpath)); /* strip current folder from target, to render a relative path */ - else if (!strncmp (curfolder, folder, strlen (curfolder))) - strfcpy (relpath, folder + strlen (curfolder), sizeof (relpath)); + else if (!strncmp (mx.mbox, folder, strlen (mx.mbox))) + strfcpy (relpath, folder + strlen (mx.mbox), sizeof (relpath)); else strfcpy (relpath, folder, sizeof (relpath)); @@ -333,7 +327,7 @@ static void imap_add_folder (char delim, char *folder, int noselect, if (!noselect) { - imap_qualify_path (tmp, sizeof (tmp), host, port, folder, NULL); + imap_qualify_path (tmp, sizeof (tmp), &mx, folder, NULL); (state->entry)[state->entrylen].name = safe_strdup (tmp); (state->entry)[state->entrylen].desc = safe_strdup (relpath); @@ -349,7 +343,7 @@ static void imap_add_folder (char delim, char *folder, int noselect, trailing_delim[1] = '\0'; trailing_delim[0] = (flen && folder[flen - 1] != delim) ? delim : '\0'; - imap_qualify_path (tmp, sizeof (tmp), host, port, folder, trailing_delim); + imap_qualify_path (tmp, sizeof (tmp), &mx, folder, trailing_delim); (state->entry)[state->entrylen].name = safe_strdup (tmp); if (!isparent && (strlen (relpath) < sizeof (relpath) - 2)) diff --git a/imap/imap.c b/imap/imap.c index 959d32f00..6830fbee3 100644 --- a/imap/imap.c +++ b/imap/imap.c @@ -537,21 +537,18 @@ int imap_open_mailbox (CONTEXT *ctx) IMAP_DATA *idata; char buf[LONG_STRING]; char bufout[LONG_STRING]; - char host[SHORT_STRING]; char seq[16]; - char *pc = NULL; int count = 0; int n; - int port; - int socktype; - - if (imap_parse_path (ctx->path, host, sizeof (host), &port, &socktype, &pc)) + IMAP_MBOX mx; + + if (imap_parse_path (ctx->path, &mx)) { mutt_error ("%s is an invalid IMAP path", ctx->path); return -1; } - conn = mutt_socket_select_connection (host, port, 0); + conn = mutt_socket_select_connection (&mx, 0); idata = CONN_DATA; if (!idata || (idata->state != IMAP_AUTHENTICATED)) @@ -562,7 +559,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 (host, port, socktype); + conn = mutt_socket_select_connection (&mx, 1); conn->data = idata; idata->conn = conn; } @@ -572,10 +569,10 @@ int imap_open_mailbox (CONTEXT *ctx) ctx->data = (void *) idata; /* Clean up path and replace the one in the ctx */ - imap_fix_path (idata, pc, buf, sizeof (buf)); + imap_fix_path (idata, mx.mbox, buf, sizeof (buf)); FREE(&(idata->selected_mailbox)); idata->selected_mailbox = safe_strdup (buf); - imap_qualify_path (buf, sizeof (buf), host, port, idata->selected_mailbox, + imap_qualify_path (buf, sizeof (buf), &mx, idata->selected_mailbox, NULL); FREE (&(ctx->path)); @@ -597,6 +594,8 @@ int imap_open_mailbox (CONTEXT *ctx) do { + char *pc; + if (mutt_socket_read_line_d (buf, sizeof (buf), conn) < 0) break; @@ -712,18 +711,16 @@ int imap_select_mailbox (CONTEXT* ctx, const char* path) { IMAP_DATA* idata; CONNECTION* conn; - char host[SHORT_STRING]; - int port; char curpath[LONG_STRING]; - char* mbox = NULL; + IMAP_MBOX mx; strfcpy (curpath, path, sizeof (curpath)); /* check that the target folder makes sense */ - if (imap_parse_path (curpath, host, sizeof (host), &port, NULL, &mbox)) + if (imap_parse_path (curpath, &mx)) return -1; /* and that it's on the same server as the current folder */ - conn = mutt_socket_select_connection (host, port, 0); + conn = mutt_socket_select_connection (&mx, 0); if (!CTX_DATA || !CONN_DATA || (CTX_DATA->conn != CONN_DATA->conn)) { dprint(2, (debugfile, @@ -747,20 +744,17 @@ int imap_open_mailbox_append (CONTEXT *ctx) { CONNECTION *conn; IMAP_DATA *idata; - char host[SHORT_STRING]; char buf[LONG_STRING], mbox[LONG_STRING]; char mailbox[LONG_STRING]; - char *pc; int r; - int port; - int socktype; + IMAP_MBOX mx; - if (imap_parse_path (ctx->path, host, sizeof (host), &port, &socktype, &pc)) + if (imap_parse_path (ctx->path, &mx)) return (-1); ctx->magic = M_IMAP; - conn = mutt_socket_select_connection (host, port, 0); + conn = mutt_socket_select_connection (&mx, 0); idata = CONN_DATA; if (!idata || (idata->state == IMAP_DISCONNECTED)) @@ -779,7 +773,7 @@ int imap_open_mailbox_append (CONTEXT *ctx) /* check mailbox existance */ - imap_fix_path (idata, pc, mailbox, sizeof (mailbox)); + imap_fix_path (idata, mx.mbox, mailbox, sizeof (mailbox)); imap_quote_string (mbox, sizeof (mbox), mailbox); @@ -1167,20 +1161,18 @@ int imap_mailbox_check (char *path, int new) { CONNECTION *conn; IMAP_DATA *idata; - char host[SHORT_STRING]; char buf[LONG_STRING]; char mbox[LONG_STRING]; char mbox_unquoted[LONG_STRING]; char seq[8]; char *s; - char *pc; int msgcount = 0; - int port; - - if (imap_parse_path (path, host, sizeof (host), &port, NULL, &pc)) + IMAP_MBOX mx; + + if (imap_parse_path (path, &mx)) return -1; - conn = mutt_socket_select_connection (host, port, 0); + conn = mutt_socket_select_connection (&mx, 0); idata = CONN_DATA; if (!idata || (idata->state == IMAP_DISCONNECTED)) @@ -1200,10 +1192,10 @@ int imap_mailbox_check (char *path, int new) return -1; } - imap_fix_path (idata, pc, buf, sizeof (buf)); + imap_fix_path (idata, mx.mbox, buf, sizeof (buf)); /* Update the path, if it fits */ - if (strlen (buf) < strlen (pc)) - strcpy (pc, buf); + if (strlen (buf) < strlen (mx.mbox)) + strcpy (mx.mbox, buf); imap_make_sequence (seq, sizeof (seq)); imap_quote_string (mbox, sizeof(mbox), buf); @@ -1358,14 +1350,12 @@ int imap_subscribe (char *path, int subscribe) IMAP_DATA *idata; char buf[LONG_STRING]; char mbox[LONG_STRING]; - char host[SHORT_STRING]; - char *ipath = NULL; - int port; + IMAP_MBOX mx; - if (imap_parse_path (path, host, sizeof (host), &port, NULL, &ipath)) + if (imap_parse_path (path, &mx)) return (-1); - conn = mutt_socket_select_connection (host, port, 0); + conn = mutt_socket_select_connection (&mx, 0); idata = CONN_DATA; if (!idata || (idata->state == IMAP_DISCONNECTED)) @@ -1381,7 +1371,7 @@ int imap_subscribe (char *path, int subscribe) return -1; } - imap_fix_path (idata, ipath, buf, sizeof (buf)); + imap_fix_path (idata, mx.mbox, buf, sizeof (buf)); if (subscribe) mutt_message (_("Subscribing to %s..."), buf); else @@ -1402,12 +1392,9 @@ int imap_subscribe (char *path, int subscribe) int imap_complete(char* dest, size_t dlen, char* path) { CONNECTION* conn; IMAP_DATA* idata; - char host[SHORT_STRING]; - int port; char list[LONG_STRING]; char buf[LONG_STRING]; char seq[16]; - char* mbox = NULL; char* list_word = NULL; int noselect, noinferiors; char delim; @@ -1415,15 +1402,16 @@ int imap_complete(char* dest, size_t dlen, char* path) { int clen, matchlen = 0; int completions = 0; int pos = 0; + IMAP_MBOX mx; /* verify passed in path is an IMAP path */ - if (imap_parse_path (path, host, sizeof(host), &port, NULL, &mbox)) + if (imap_parse_path (path, &mx)) { dprint(2, (debugfile, "imap_complete: bad path %s\n", path)); return -1; } - conn = mutt_socket_select_connection (host, port, 0); + conn = mutt_socket_select_connection (&mx, 0); idata = CONN_DATA; /* don't open a new socket just for completion */ @@ -1436,8 +1424,8 @@ int imap_complete(char* dest, size_t dlen, char* path) { /* reformat path for IMAP list, and append wildcard */ /* don't use INBOX in place of "" */ - if (mbox[0]) - imap_fix_path (idata, mbox, list, sizeof(list)); + if (mx.mbox[0]) + imap_fix_path (idata, mx.mbox, list, sizeof(list)); else list[0] = '\0'; @@ -1448,7 +1436,7 @@ int imap_complete(char* dest, size_t dlen, char* path) { mutt_socket_write (conn, buf); /* and see what the results are */ - strfcpy (completion, mbox, sizeof(completion)); + strfcpy (completion, mx.mbox, sizeof(completion)); do { if (imap_parse_list_response(conn, buf, sizeof(buf), &list_word, @@ -1492,7 +1480,7 @@ int imap_complete(char* dest, size_t dlen, char* path) { if (completions) { /* reformat output */ - imap_qualify_path (dest, dlen, host, port, completion, NULL); + imap_qualify_path (dest, dlen, &mx, completion, NULL); mutt_pretty_mailbox (dest); return 0; diff --git a/imap/imap.h b/imap/imap.h index 6f86a1ebc..a88479f22 100644 --- a/imap/imap.h +++ b/imap/imap.h @@ -22,6 +22,19 @@ #include "browser.h" #include "mailbox.h" +typedef struct +{ + char user[32]; + char pass[32]; + char host[128]; + int port; + char type[16]; + int socktype; + char *mbox; + int flags; +} IMAP_MBOX; + + /* imap.c */ int imap_check_mailbox (CONTEXT *ctx, int *index_hint); int imap_create_mailbox (CONTEXT* idata, char* mailbox); @@ -47,9 +60,8 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete); int imap_fetch_message (MESSAGE* msg, CONTEXT* ctx, int msgno); /* util.c */ -int imap_parse_path (char* path, char* host, size_t hlen, int* port, - int *socktype, char** mbox); -void imap_qualify_path (char* dest, size_t len, const char* host, int port, +int imap_parse_path (const char* path, IMAP_MBOX *mx); +void imap_qualify_path (char* dest, size_t len, const IMAP_MBOX *mx, const char* path, const char* name); int imap_wait_keepalive (pid_t pid); diff --git a/imap/imap_private.h b/imap/imap_private.h index b61e9d08d..a116a0b04 100644 --- a/imap/imap_private.h +++ b/imap/imap_private.h @@ -32,6 +32,12 @@ #define SEQLEN 5 +#define M_IMAP_USER (1<<0) +#define M_IMAP_PORT (1<<1) +#define M_IMAP_TYPE (1<<2) +#define M_IMAP_PASS (1<<3) +#define M_IMAP_CRAM (1<<4) + enum { IMAP_FATAL = 1, diff --git a/imap/imap_socket.h b/imap/imap_socket.h index 3fd9d24eb..ad112b406 100644 --- a/imap/imap_socket.h +++ b/imap/imap_socket.h @@ -22,9 +22,8 @@ typedef struct _connection { - char *server; + IMAP_MBOX mx; char *preconnect; /* Actually specific to server, not connection */ - int port; int uses; int fd; char inbuf[LONG_STRING]; @@ -45,7 +44,7 @@ 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 (char *host, int port, int flags); +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); diff --git a/imap/imap_ssl.c b/imap/imap_ssl.c index 09c354735..b4e6db272 100644 --- a/imap/imap_ssl.c +++ b/imap/imap_ssl.c @@ -24,6 +24,7 @@ #include #include "mutt.h" +#include "imap.h" #include "imap_socket.h" #include "mutt_menu.h" #include "mutt_curses.h" diff --git a/imap/message.c b/imap/message.c index 0a89ad3aa..f959187b4 100644 --- a/imap/message.c +++ b/imap/message.c @@ -396,19 +396,17 @@ int imap_append_message (CONTEXT *ctx, MESSAGE *msg) { FILE *fp; char buf[LONG_STRING]; - char host[SHORT_STRING]; char mbox[LONG_STRING]; char mailbox[LONG_STRING]; char seq[16]; - char *pc; - int port; size_t len; int c, last; + IMAP_MBOX mx; - if (imap_parse_path (ctx->path, host, sizeof (host), &port, NULL, &pc)) + if (imap_parse_path (ctx->path, &mx)) return (-1); - imap_fix_path (CTX_DATA, pc, mailbox, sizeof (mailbox)); + imap_fix_path (CTX_DATA, mx.mbox, mailbox, sizeof (mailbox)); if ((fp = fopen (msg->path, "r")) == NULL) { @@ -521,27 +519,25 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete) char buf[HUGE_STRING]; char cmd[LONG_STRING]; char mbox[LONG_STRING]; - char host[SHORT_STRING]; - int port; - char* pc; int rc; int n; + IMAP_MBOX mx; - if (imap_parse_path (dest, host, sizeof (host), &port, NULL, &pc)) + if (imap_parse_path (dest, &mx)) { dprint (1, (debugfile, "imap_copy_message: bad destination %s\n", dest)); return -1; } /* check that the save-to folder is on the same server */ - if (mutt_socket_select_connection (host, port, 0) != CTX_DATA->conn) + if (mutt_socket_select_connection (&mx, 0) != CTX_DATA->conn) { dprint (3, (debugfile, "imap_copy_message: %s not same server as %s\n", dest, ctx->path)); return 1; } - imap_fix_path (CTX_DATA, pc, cmd, sizeof (cmd)); + imap_fix_path (CTX_DATA, mx.mbox, cmd, sizeof (cmd)); /* Null HEADER* means copy tagged messages */ if (!h) diff --git a/imap/socket.c b/imap/socket.c index cf921a122..e0783f9ba 100644 --- a/imap/socket.c +++ b/imap/socket.c @@ -18,7 +18,9 @@ #include "mutt.h" #include "globals.h" +#include "imap.h" #include "imap_socket.h" +#include "imap_private.h" #ifdef USE_SSL #include "imap_ssl.h" #endif @@ -97,20 +99,29 @@ int mutt_socket_read_line_d (char *buf, size_t buflen, CONNECTION *conn) return r; } -CONNECTION *mutt_socket_select_connection (char *host, int port, int flags) +static int imap_user_match (const IMAP_MBOX *m1, const IMAP_MBOX *m2) +{ + const char *user = ImapUser ? ImapUser : NONULL (Username); + + 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; -#ifdef USE_SSL - if (flags != M_NEW_SOCKET && flags != M_NEW_SSL_SOCKET) -#else - if (flags != M_NEW_SOCKET) -#endif + if (! newconn) { conn = Connections; while (conn) { - if (!mutt_strcmp (host, conn->server) && (port == conn->port)) + if (!mutt_strcmp (mx->host, conn->mx.host) && (mx->port == conn->mx.port) && imap_user_match (mx, &conn->mx)) return conn; conn = conn->next; } @@ -119,14 +130,14 @@ CONNECTION *mutt_socket_select_connection (char *host, int port, int flags) conn->bufpos = 0; conn->available = 0; conn->uses = 0; - conn->server = safe_strdup (host); + memcpy (&conn->mx, mx, sizeof (conn->mx)); + conn->mx.mbox = 0; conn->preconnect = safe_strdup (ImapPreconnect); - conn->port = port; conn->next = Connections; Connections = conn; #ifdef USE_SSL - if (flags == M_NEW_SSL_SOCKET) + if (mx->socktype == M_NEW_SSL_SOCKET) { conn->read = ssl_socket_read; conn->write = ssl_socket_write; @@ -195,16 +206,16 @@ int raw_socket_open (CONNECTION *conn) int first_try_without_preconnect = TRUE; memset (&sin, 0, sizeof (sin)); - sin.sin_port = htons (conn->port); + sin.sin_port = htons (conn->mx.port); sin.sin_family = AF_INET; - if ((he = gethostbyname (conn->server)) == NULL) + if ((he = gethostbyname (conn->mx.host)) == NULL) { - mutt_perror (conn->server); + mutt_perror (conn->mx.host); return (-1); } memcpy (&sin.sin_addr, he->h_addr_list[0], he->h_length); - mutt_message (_("Connecting to %s..."), conn->server); + mutt_message (_("Connecting to %s..."), conn->mx.host); if (do_preconnect && first_try_without_preconnect) { @@ -217,7 +228,7 @@ int raw_socket_open (CONNECTION *conn) { int ret; - dprint (1,(debugfile,"Preconnect to server %s:\n", conn->server)); + dprint (1,(debugfile,"Preconnect to server %s:\n", conn->mx.host)); dprint (1,(debugfile,"\t%s\n", conn->preconnect)); /* Execute preconnect command */ ret = mutt_system (conn->preconnect) < 0; diff --git a/imap/util.c b/imap/util.c index 81aef5f2a..720c7cf37 100644 --- a/imap/util.c +++ b/imap/util.c @@ -126,98 +126,96 @@ char *imap_next_word (char *s) /* imap_parse_path: given an IMAP mailbox name, return host, port * and a path IMAP servers will recognise. */ -int imap_parse_path (char* path, char* host, size_t hlen, int* port, - int *socktype, char** mbox) +int imap_parse_path (const char *path, IMAP_MBOX *mx) { + char tmp[128]; + char *c; int n; - char *pc; - char *pt; - - /* set default port */ - if (port) - *port = 0; - if (socktype) - *socktype = M_NEW_SOCKET; - pc = path; - if (*pc != '{') - return -1; - pc++; - /* skip over the entire host, but copy in only what we have room for */ - for (n = 0; *pc && *pc != '}' && *pc != ':' && *pc != '/'; pc++) - if (n+1 < hlen) - host[n++] = *pc; - if (hlen) - host[n] = 0; - - /* catch NULL hosts, unless we're deliberately not parsing them */ - if (hlen && !*host) + + mx->type[0] = '\0'; + if (sscanf (path, "{%128[^}]}", tmp) != 1) { - dprint (1, (debugfile, "imap_parse_path: NULL host in %s\n", path)); return -1; } - if (!*pc) - return -1; - if (*pc == ':') + mx->mbox = strchr (path, '}') + 1; + + /* Defaults */ + mx->flags = 0; + mx->port = IMAP_PORT; + mx->socktype = M_NEW_SOCKET; + + if ((c = strrchr (tmp, '@'))) { - char c; - pc++; - pt = pc; - while (*pc && *pc != '}' && *pc != '/') pc++; - if (!*pc) - return -1; - c = *pc; - *pc = '\0'; - if (port) - *port = atoi (pt); - if (port && !*port) - { - dprint (1, (debugfile, "imap_parse_path: bad port in %s\n", path)); - return -1; - } - *pc = c; + *c = '\0'; + strfcpy (mx->user, tmp, sizeof (mx->user)); + strfcpy (tmp, c+1, sizeof (tmp)); + mx->flags |= M_IMAP_USER; } - if (*pc == '/') + + if ((n = sscanf (tmp, "%128[^:/]%128s", mx->host, tmp)) < 1) { - pc++; - pt = pc; - while (*pc && *pc != '}') pc++; - if (!*pc) - return (-1); - *pc = '\0'; -#ifdef USE_SSL - if (!strcmp (pt, "ssl")) + dprint (1, (debugfile, "imap_parse_path: NULL host in %s\n", path)); + return -1; + } + + if (n > 1) { + if (sscanf (tmp, ":%d%128s", &mx->port, tmp) >= 1) + mx->flags |= M_IMAP_PORT; + if (sscanf (tmp, "/%s", mx->type) == 1) { - if (socktype) - *socktype = M_NEW_SSL_SOCKET; - if (port && !*port) - *port = IMAP_SSL_PORT; - } else +#ifdef USE_SSL + if (!strcmp (mx->type, "ssl")) + { + if (! (mx->flags & M_IMAP_PORT)) + mx->port = IMAP_SSL_PORT; + mx->socktype = M_NEW_SSL_SOCKET; + mx->flags |= M_IMAP_TYPE; + } + else #endif - return (-1); - *pc = '}'; + { + dprint (1, (debugfile, "imap_parse_path: Unknown connection type in %s\n", path)); + return (-1); + } + } } - pc++; - - if (port && !*port) - *port = IMAP_PORT; - *mbox = pc; return 0; } + /* imap_qualify_path: make an absolute IMAP folder target, given host, port * and relative path. Use this and maybe it will be easy to convert to * IMAP URLs */ -void imap_qualify_path (char* dest, size_t len, const char* host, int port, +void imap_qualify_path (char *dest, size_t len, const IMAP_MBOX *mx, const char* path, const char* name) { - if (port == IMAP_PORT) - snprintf (dest, len, "{%s}%s%s", host, NONULL (path), NONULL (name)); - else - snprintf (dest, len, "{%s:%d}%s%s", host, port, NONULL (path), - NONULL (name)); + char tmp[128]; + + strcpy (dest, "{"); + if ((mx->flags & M_IMAP_USER) && (!ImapUser || strcmp (mx->user, ImapUser))) + { + snprintf (tmp, sizeof (tmp), "%s@", mx->user); + strncat (dest, tmp, len); + } + strncat (dest, mx->host, len); + if (mx->flags & M_IMAP_PORT) + { + snprintf (tmp, sizeof (tmp), ":%d", mx->port); + strncat (dest, tmp, len); + } +#ifdef USE_SSL + if (mx->flags & M_IMAP_TYPE) + { + snprintf (tmp, sizeof (tmp), "/%s", mx->type); + strncat (dest, tmp, len); + } +#endif + snprintf (tmp, sizeof (tmp), "}%s%s", NONULL (path), NONULL (name)); + strncat (dest, tmp, len); } + /* imap_quote_string: quote string according to IMAP rules: * surround string with quotes, escape " and \ with \ */ void imap_quote_string (char *dest, size_t slen, const char *src) diff --git a/init.c b/init.c index 6986e39d1..55e97f365 100644 --- a/init.c +++ b/init.c @@ -30,6 +30,7 @@ #ifdef USE_SSL +#include "imap.h" #include "imap_socket.h" #include "imap_ssl.h" #endif