X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=imap%2Fimap.c;h=ea2eb80fd6d10c8a076879126e81057fd3cf7852;hp=f7b30f4f4f2532dae34cf75afd2d51d4187fdd44;hb=8297f3a57ccff9c0663551658cdd5d3bf166249d;hpb=5b0581b41f115cd0442037a97db313ef5b5b8822 diff --git a/imap/imap.c b/imap/imap.c index f7b30f4..ea2eb80 100644 --- a/imap/imap.c +++ b/imap/imap.c @@ -11,37 +11,17 @@ /* Support for IMAP4rev1, with the occasional nod to IMAP 4. */ -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include -#include -#include +#include +#include #include "mutt.h" -#include "mx.h" #include "globals.h" +#include "pattern.h" #include "sort.h" -#include "browser.h" #include "message.h" #include "imap_private.h" -#if defined(USE_SSL) || defined(USE_GNUTLS) -# include -#endif #include "buffy.h" -#include - -#include -#include -#include -#include -#include -#include - /* imap forward declarations */ static int imap_get_delim (IMAP_DATA * idata); static char *imap_get_flags (string_list_t ** hflags, char *s); @@ -53,7 +33,7 @@ static void imap_set_flag (IMAP_DATA * idata, int aclbit, int flag, /* imap_access: Check permissions on an IMAP mailbox. * TODO: ACL checks. Right now we assume if it exists we can * mess with it. */ -int imap_access (const char *path, int flags __attribute__ ((unused))) +static int imap_access (const char *path, int flags __attribute__ ((unused))) { IMAP_DATA *idata; IMAP_MBOX mx; @@ -74,7 +54,7 @@ int imap_access (const char *path, int flags __attribute__ ((unused))) imap_fix_path (idata, mx.mbox, mailbox, sizeof (mailbox)); /* we may already be in the folder we're checking */ - if (!ascii_strcmp(idata->mailbox, mx.mbox)) { + if (!m_strcmp(idata->mailbox, mx.mbox)) { p_delete(&mx.mbox); return 0; } @@ -87,12 +67,10 @@ int imap_access (const char *path, int flags __attribute__ ((unused))) else if (mutt_bit_isset (idata->capabilities, STATUS)) snprintf (buf, sizeof (buf), "STATUS %s (UID-VALIDITY)", mbox); else { - debug_print (2, ("STATUS not supported?\n")); return -1; } if (imap_exec (idata, buf, IMAP_CMD_FAIL_OK) < 0) { - debug_print (1, ("Can't check STATUS of %s\n", mbox)); return -1; } @@ -190,17 +168,13 @@ int imap_read_literal (FILE * fp, IMAP_DATA * idata, long bytes, progress_t* bar int r = 0; - debug_print (2, ("reading %ld bytes\n", bytes)); - for (pos = 0; pos < bytes; pos++) { if (mutt_socket_readchar (idata->conn, &c) != 1) { - debug_print (1, ("error during read, %ld bytes read\n", pos)); idata->status = IMAP_FATAL; return -1; } -#if 1 if (r == 1 && c != '\n') fputc ('\r', fp); @@ -210,14 +184,10 @@ int imap_read_literal (FILE * fp, IMAP_DATA * idata, long bytes, progress_t* bar } else r = 0; -#endif + fputc (c, fp); if (bar && !(pos % 1024)) mutt_progress_bar (bar, pos); -#ifdef DEBUG - if (DebugFile && DebugLevel >= IMAP_LOG_LTRL) - fputc (c, DebugFile); -#endif } return 0; @@ -235,8 +205,6 @@ void imap_expunge_mailbox (IMAP_DATA * idata) h = idata->ctx->hdrs[i]; if (h->index == -1) { - debug_print (2, ("Expunging message UID %d.\n", HEADER_DATA (h)->uid)); - h->active = 0; /* free cached body from disk, if neccessary */ @@ -266,14 +234,14 @@ static int imap_get_delim (IMAP_DATA * idata) * than getting the delim wrong */ idata->delim = '/'; - imap_cmd_start (idata, "string_list_t \"\" \"\""); + imap_cmd_start (idata, "LIST \"\" \"\""); do { if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE) break; - s = imap_next_word (idata->cmd.buf); - if (ascii_strncasecmp ("string_list_t", s, 4) == 0) { + s = imap_next_word (idata->cmd.buf.data); + if (ascii_strncasecmp ("LIST", s, 4) == 0) { s = imap_next_word (s); s = imap_next_word (s); if (s && s[0] == '\"' && s[1] && s[2] == '\"') @@ -285,13 +253,6 @@ static int imap_get_delim (IMAP_DATA * idata) } while (rc == IMAP_CMD_CONTINUE); - if (rc != IMAP_CMD_OK) { - debug_print (1, ("failed.\n")); - return -1; - } - - debug_print (2, ("Delimiter: %c\n", idata->delim)); - return -1; } @@ -314,7 +275,7 @@ static int imap_check_acl (IMAP_DATA * idata) static int imap_check_capabilities (IMAP_DATA * idata) { if (imap_exec (idata, "CAPABILITY", 0) != 0) { - imap_error ("imap_check_capabilities", idata->cmd.buf); + imap_error ("imap_check_capabilities", idata->cmd.buf.data); return -1; } @@ -337,7 +298,6 @@ IMAP_DATA *imap_conn_find (const ACCOUNT * account, int flags) CONNECTION *conn; IMAP_DATA *idata; ACCOUNT *creds; - int new = 0; if (!(conn = mutt_conn_find (NULL, account))) return NULL; @@ -367,35 +327,31 @@ IMAP_DATA *imap_conn_find (const ACCOUNT * account, int flags) if (!idata) { /* The current connection is a new connection */ - if (!(idata = imap_new_idata ())) { - mutt_socket_free (conn); - return NULL; - } - - conn->data = idata; + idata = imap_new_idata(); + conn->data = idata; idata->conn = conn; - new = 1; } if (idata->state == IMAP_DISCONNECTED) imap_open_connection (idata); if (idata->state == IMAP_CONNECTED) { - if (!imap_authenticate (idata)) { + if (!imap_authenticate(idata)) { idata->state = IMAP_AUTHENTICATED; - if (idata->conn->ssf) - debug_print (2, ("Communication encrypted at %d bits\n", idata->conn->ssf)); + } else { + mutt_socket_close(idata->conn); + idata->state = IMAP_DISCONNECTED; + idata->conn->account.has_pass = 0; } - else - mutt_account_unsetpass (&idata->conn->account); p_delete(&idata->capstr); } - if (new && idata->state == IMAP_AUTHENTICATED) { + if (idata->isnew && idata->state == IMAP_AUTHENTICATED) { imap_get_delim (idata); if (option (OPTIMAPCHECKSUBSCRIBED)) { mutt_message _("Checking mailbox subscriptions"); imap_exec (idata, "LSUB \"\" \"*\"", 0); } + idata->isnew = 0; } return idata; @@ -416,28 +372,22 @@ int imap_open_connection (IMAP_DATA * idata) return -1; } - if (ascii_strncasecmp ("* OK", idata->cmd.buf, 4) == 0) { + if (ascii_strncasecmp ("* OK", idata->cmd.buf.data, 4) == 0) { /* TODO: Parse new tagged CAPABILITY data (* OK [CAPABILITY...]) */ if (imap_check_capabilities (idata)) goto bail; -#if defined(USE_SSL) || defined(USE_GNUTLS) /* Attempt STARTTLS if available and desired. */ - if (!idata->conn->ssf && (option(OPTSSLFORCETLS) || + if (!idata->conn->ssf && (mod_ssl.force_tls || mutt_bit_isset (idata->capabilities, STARTTLS))) { int rc; - if (option (OPTSSLFORCETLS)) + if (mod_ssl.force_tls) rc = M_YES; - else if ((rc = query_quadoption (OPT_SSLSTARTTLS, - _("Secure connection with TLS?"))) == -1) - goto err_close_conn; - if (rc == M_YES) { + else if (mod_ssl.starttls) { if ((rc = imap_exec (idata, "STARTTLS", IMAP_CMD_FAIL_OK)) == -1) goto bail; if (rc != -2) { -#if defined (USE_SSL) || defined (USE_GNUTLS) if (mutt_ssl_starttls (idata->conn)) -#endif { mutt_error (_("Could not negotiate TLS connection")); mutt_sleep (1); @@ -452,14 +402,13 @@ int imap_open_connection (IMAP_DATA * idata) } } - if (option(OPTSSLFORCETLS) && ! idata->conn->ssf) { + if (mod_ssl.force_tls && ! idata->conn->ssf) { mutt_error _("Encrypted connection unavailable"); mutt_sleep (1); goto err_close_conn; } -#endif } - else if (ascii_strncasecmp ("* PREAUTH", idata->cmd.buf, 9) == 0) { + else if (ascii_strncasecmp ("* PREAUTH", idata->cmd.buf.data, 9) == 0) { idata->state = IMAP_AUTHENTICATED; if (imap_check_capabilities (idata) != 0) goto bail; @@ -490,12 +439,10 @@ static char *imap_get_flags (string_list_t ** hflags, char *s) /* sanity-check string */ if (ascii_strncasecmp ("FLAGS", s, 5) != 0) { - debug_print (1, ("not a FLAGS response: %s\n", s)); return NULL; } s = vskipspaces(s + 5); if (*s != '(') { - debug_print (1, ("bogus FLAGS response: %s\n", s)); return NULL; } @@ -517,7 +464,6 @@ static char *imap_get_flags (string_list_t ** hflags, char *s) /* note bad flags response */ if (*s != ')') { - debug_print (1, ("Unterminated FLAGS response: %s\n", s)); string_list_wipe(hflags); return NULL; @@ -528,7 +474,7 @@ static char *imap_get_flags (string_list_t ** hflags, char *s) return s; } -int imap_open_mailbox (CONTEXT * ctx) +static int imap_open_mailbox (CONTEXT * ctx) { CONNECTION *conn; IMAP_DATA *idata; @@ -585,21 +531,19 @@ int imap_open_mailbox (CONTEXT * ctx) if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE) break; - pc = idata->cmd.buf + 2; + pc = idata->cmd.buf.data + 2; /* Obtain list of available flags here, may be overridden by a * PERMANENTFLAGS tag in the OK response */ if (ascii_strncasecmp ("FLAGS", pc, 5) == 0) { /* don't override PERMANENTFLAGS */ if (!idata->flags) { - debug_print (2, ("Getting mailbox FLAGS\n")); if ((pc = imap_get_flags (&(idata->flags), pc)) == NULL) goto fail; } } /* PERMANENTFLAGS are massaged to look like FLAGS, then override FLAGS */ else if (ascii_strncasecmp ("OK [PERMANENTFLAGS", pc, 18) == 0) { - debug_print (2, ("Getting mailbox PERMANENTFLAGS\n")); /* safe to call on NULL */ string_list_wipe(&(idata->flags)); /* skip "OK [PERMANENT" so syntax is the same as FLAGS */ @@ -610,7 +554,6 @@ int imap_open_mailbox (CONTEXT * ctx) #ifdef USE_HCACHE /* save UIDVALIDITY for the header cache */ else if (ascii_strncasecmp ("OK [UIDVALIDITY", pc, 14) == 0) { - debug_print (2, ("Getting mailbox UIDVALIDITY\n")); pc += 3; pc = imap_next_word (pc); @@ -630,7 +573,7 @@ int imap_open_mailbox (CONTEXT * ctx) if (rc == IMAP_CMD_NO) { char *s; - s = imap_next_word (idata->cmd.buf); /* skip seq */ + s = imap_next_word (idata->cmd.buf.data); /* skip seq */ s = imap_next_word (s); /* Skip response */ mutt_error ("%s", s); mutt_sleep (2); @@ -642,31 +585,11 @@ int imap_open_mailbox (CONTEXT * ctx) /* check for READ-ONLY notification */ if (!ascii_strncasecmp - (imap_get_qualifier (idata->cmd.buf), "[READ-ONLY]", 11) + (imap_get_qualifier (idata->cmd.buf.data), "[READ-ONLY]", 11) && !mutt_bit_isset (idata->capabilities, ACL)) { - debug_print (2, ("Mailbox is read-only.\n")); ctx->readonly = 1; } -#ifdef DEBUG - /* dump the mailbox flags we've found */ - if (DebugLevel > 2) { - if (!idata->flags) - debug_print (3, ("No folder flags found\n")); - else { - string_list_t *t = idata->flags; - - debug_print (3, ("Mailbox flags:\n")); - - t = t->next; - while (t) { - debug_print (3, ("[%s]\n", t->data)); - t = t->next; - } - } - } -#endif - if (mutt_bit_isset (idata->capabilities, ACL)) { if (imap_check_acl (idata)) goto fail; @@ -699,7 +622,6 @@ int imap_open_mailbox (CONTEXT * ctx) goto fail; } - debug_print (2, ("msgcount is %d\n", ctx->msgcount)); p_delete(&mx.mbox); return 0; @@ -727,7 +649,7 @@ int imap_open_mailbox_append (CONTEXT * ctx) if (!(idata = imap_conn_find (&(mx.account), 0))) { p_delete(&mx.mbox); - return (-1); + return -1; } conn = idata->conn; @@ -749,7 +671,7 @@ int imap_open_mailbox_append (CONTEXT * ctx) if (imap_create_mailbox (idata, mailbox) < 0) return -1; - return (0); + return 0; } /* imap_logout: Gracefully log out of server. */ @@ -760,27 +682,9 @@ void imap_logout (IMAP_DATA * idata) idata->status = IMAP_BYE; imap_cmd_start (idata, "LOGOUT"); while (imap_cmd_step (idata) == IMAP_CMD_CONTINUE); - p_delete(&idata->cmd.buf); - p_delete(&idata); + imap_free_idata(&idata); } -/* -int imap_close_connection (CONTEXT *ctx) -{ - debug_print (1, (debugfile, "imap_close_connection(): closing connection\n")); - if (CTX_DATA->status != IMAP_BYE) - { - mutt_message _("Closing connection to IMAP server..."); - imap_logout (CTX_DATA); - mutt_clear_error (); - } - mutt_socket_close (CTX_DATA->conn); - CTX_DATA->state = IMAP_DISCONNECTED; - CTX_DATA->conn->data = NULL; - return 0; -} -*/ - /* imap_set_flag: append str to flags if we currently have permission * according to aclbit */ static void imap_set_flag(IMAP_DATA *idata, int aclbit, int flag, @@ -933,7 +837,7 @@ int imap_sync_message (IMAP_DATA *idata, HEADER *hdr, BUFFER *cmd, err_continue && (*err_continue != M_YES)) { *err_continue = imap_continue ("imap_sync_message: STORE failed", - idata->cmd.buf); + idata->cmd.buf.data); if (*err_continue != M_YES) return -1; } @@ -963,7 +867,6 @@ int imap_sync_mailbox (CONTEXT * ctx, int expunge, int *index_hint) idata = (IMAP_DATA *) ctx->data; if (idata->state != IMAP_SELECTED) { - debug_print (2, ("no mailbox selected\n")); return -1; } @@ -1011,14 +914,11 @@ int imap_sync_mailbox (CONTEXT * ctx, int expunge, int *index_hint) * This works better if we're expunging, of course. */ if ((ctx->hdrs[n]->env && (ctx->hdrs[n]->env->refs_changed || ctx->hdrs[n]->env->irt_changed)) || ctx->hdrs[n]->attach_del) { - debug_print (3, ("Attachments to be deleted, falling back to _mutt_save_message\n")); if (!appendctx) appendctx = mx_open_mailbox (ctx->path, M_APPEND | M_QUIET, NULL); - if (!appendctx) { - debug_print (1, ("Error opening mailbox in append mode\n")); - } - else + if (appendctx) { _mutt_save_message (ctx->hdrs[n], appendctx, 1, 0, 0); + } } if (imap_sync_message (idata, ctx->hdrs[n], &cmd, &err_continue) < 0) { @@ -1037,7 +937,7 @@ int imap_sync_mailbox (CONTEXT * ctx, int expunge, int *index_hint) /* Set expunge bit so we don't get spurious reopened messages */ idata->reopen |= IMAP_EXPUNGE_EXPECTED; if (imap_exec (idata, "EXPUNGE", 0) != 0) { - imap_error (_("imap_sync_mailbox: EXPUNGE failed"), idata->cmd.buf); + imap_error (_("imap_sync_mailbox: EXPUNGE failed"), idata->cmd.buf.data); rc = imap_reconnect (ctx); goto out; } @@ -1061,7 +961,7 @@ out: } /* imap_close_mailbox: clean up IMAP data in CONTEXT */ -void imap_close_mailbox (CONTEXT * ctx) +static void imap_close_mailbox (CONTEXT * ctx) { IMAP_DATA *idata; int i; @@ -1201,7 +1101,7 @@ int imap_mailbox_check (char *path, int new) if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE) break; - s = imap_next_word (idata->cmd.buf); + s = imap_next_word (idata->cmd.buf.data); if (ascii_strncasecmp ("STATUS", s, 6) == 0) { s = imap_next_word (s); /* The mailbox name may or may not be quoted here. We could try to @@ -1214,12 +1114,9 @@ int imap_mailbox_check (char *path, int new) if (isdigit ((unsigned char) *s)) { if (*s != '0') { msgcount = atoi (s); - debug_print (2, ("%d new messages in %s\n", msgcount, path)); } } } - else - debug_print (1, ("STATUS response doesn't match requested mailbox.\n")); } } while (rc == IMAP_CMD_CONTINUE); @@ -1378,8 +1275,8 @@ int imap_parse_list_response (IMAP_DATA * idata, char **name, int *noselect, if (rc != IMAP_CMD_CONTINUE) return -1; - s = imap_next_word (idata->cmd.buf); - if ((ascii_strncasecmp ("string_list_t", s, 4) == 0) || + s = imap_next_word (idata->cmd.buf.data); + if ((ascii_strncasecmp ("LIST", s, 4) == 0) || (ascii_strncasecmp ("LSUB", s, 4) == 0)) { *noselect = 0; *noinferiors = 0; @@ -1419,11 +1316,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->cmd.buf, &bytes) < 0) + if (imap_get_literal_count (idata->cmd.buf.data, &bytes) < 0) return -1; if (imap_cmd_step (idata) != IMAP_CMD_CONTINUE) return -1; - *name = idata->cmd.buf; + *name = idata->cmd.buf.data; } else *name = s; @@ -1438,8 +1335,6 @@ int imap_subscribe (char *path, int subscribe) IMAP_DATA *idata; char buf[LONG_STRING]; char mbox[LONG_STRING]; - char errstr[STRING]; - BUFFER err, token; IMAP_MBOX mx; if (mx_get_magic (path) != M_IMAP || imap_parse_path (path, &mx) < 0) { @@ -1455,14 +1350,7 @@ int imap_subscribe (char *path, int subscribe) imap_fix_path (idata, mx.mbox, buf, sizeof (buf)); if (option (OPTIMAPCHECKSUBSCRIBED)) { - p_clear(&token, 1); - err.data = errstr; - err.dsize = sizeof (errstr); - snprintf (mbox, sizeof (mbox), "%smailboxes \"%s\"", - subscribe ? "" : "un", path); - if (mutt_parse_rc_line (mbox, &token, &err)) - debug_print (1, ("Error adding subscribed mailbox: %s\n", errstr)); - p_delete(&token.data); + buffy_do_mailboxes(path, subscribe); } if (subscribe) @@ -1507,10 +1395,10 @@ static int imap_complete_hosts (char *dest, ssize_t len) { int i = 0; matchlen = m_strlen(dest); - if (list_empty (Incoming)) - return (-1); - for (i = 0; i < Incoming->length; i++) { - mailbox = (BUFFY*) Incoming->data[i]; + if (!Incoming.len) + return -1; + for (i = 0; i < Incoming.len; i++) { + mailbox = Incoming.arr[i]; if (!m_strncmp(dest, mailbox->path, matchlen)) { if (rc) { m_strcpy(dest, len, mailbox->path); @@ -1582,7 +1470,7 @@ int imap_complete (char *dest, size_t dlen, char *path) { /* fire off command */ snprintf (buf, sizeof (buf), "%s \"\" \"%s%%\"", - option (OPTIMAPLSUB) ? "LSUB" : "string_list_t", list); + option (OPTIMAPLSUB) ? "LSUB" : "LIST", list); imap_cmd_start (idata, buf); @@ -1616,7 +1504,7 @@ int imap_complete (char *dest, size_t dlen, char *path) { completions++; } } - while (ascii_strncmp (idata->cmd.seq, idata->cmd.buf, SEQLEN)); + while (m_strncmp(idata->cmd.seq, idata->cmd.buf.data, SEQLEN)); if (completions) { /* reformat output */ @@ -1636,7 +1524,7 @@ int imap_reconnect (CONTEXT * ctx) IMAP_DATA *imap_data; if (!ctx) - return (-1); + return -1; imap_data = (IMAP_DATA *) ctx->data; @@ -1653,3 +1541,64 @@ int imap_reconnect (CONTEXT * ctx) mx_open_mailbox (ctx->path, 0, ctx); return 0; } + +int imap_is_magic (const char* path, struct stat* st __attribute__ ((unused))) { + url_scheme_t s; + if (!path || !*path) + return -1; + s = url_check_scheme (NONULL (path)); + return (s == U_IMAP || s == U_IMAPS) ? M_IMAP : -1; +} + +static int acl_check_imap (CONTEXT* ctx, int bit) { + return (!mutt_bit_isset (((IMAP_DATA*) ctx->data)->capabilities, ACL) || + mutt_bit_isset (((IMAP_DATA*) ctx->data)->rights, bit)); +} + +static int imap_open_new_message (MESSAGE * msg, + CONTEXT * dest __attribute__ ((unused)), + HEADER * hdr __attribute__ ((unused))) +{ + char tmp[_POSIX_PATH_MAX]; + + msg->fp = m_tempfile(tmp, sizeof(tmp), NONULL(mod_core.tmpdir), NULL); + if (!msg->fp) { + mutt_perror(tmp); + return -1; + } + + msg->path = m_strdup(tmp); + return 0; +} + +/* this ugly kludge is required since the last int to + * imap_check_mailbox() doesn't mean 'lock' but 'force'... */ +static int _imap_check_mailbox (CONTEXT* ctx, + int* index_hint, + int lock __attribute__ ((unused))) { + return imap_check_mailbox (ctx, index_hint, 0); +} + +static int imap_commit_message (MESSAGE* msg, CONTEXT* ctx) { + int r = 0; + + if ((r = m_fclose(&msg->fp)) == 0) + r = imap_append_message (ctx, msg); + return r; +} + +mx_t const imap_mx = { + M_IMAP, + 0, + imap_is_magic, + NULL, + imap_access, + imap_open_mailbox, + imap_open_new_message, + imap_fetch_message, + acl_check_imap, + _imap_check_mailbox, + imap_close_mailbox, + imap_sync_mailbox, + imap_commit_message, +};