/* Support for IMAP4rev1, with the occasional nod to IMAP 4. */
#include <lib-lib/lib-lib.h>
+#include <lib-mx/mx.h>
#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 <lib-sys/mutt_ssl.h>
-#endif
#include "buffy.h"
/* imap forward declarations */
/* 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;
return -1;
}
-#if 1
if (r == 1 && c != '\n')
fputc ('\r', fp);
}
else
r = 0;
-#endif
+
fputc (c, fp);
if (bar && !(pos % 1024))
mutt_progress_bar (bar, pos);
* 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] == '\"')
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;
}
CONNECTION *conn;
IMAP_DATA *idata;
ACCOUNT *creds;
- int new = 0;
if (!(conn = mutt_conn_find (NULL, account)))
return NULL;
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;
+ } 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;
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 ((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
- {
+ if (mutt_ssl_starttls (idata->conn)) {
mutt_error (_("Could not negotiate TLS connection"));
mutt_sleep (1);
goto err_close_conn;
- }
- else {
+ } else {
/* RFC 2595 demands we recheck CAPABILITY after TLS completes. */
if (imap_exec (idata, "CAPABILITY", 0))
goto bail;
}
}
- 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;
return s;
}
-int imap_open_mailbox (CONTEXT * ctx)
+static int imap_open_mailbox (CONTEXT * ctx)
{
CONNECTION *conn;
IMAP_DATA *idata;
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 (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);
/* 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)) {
ctx->readonly = 1;
}
if (!(idata = imap_conn_find (&(mx.account), 0))) {
p_delete(&mx.mbox);
- return (-1);
+ return -1;
}
conn = idata->conn;
if (imap_create_mailbox (idata, mailbox) < 0)
return -1;
- return (0);
+ return 0;
}
/* imap_logout: Gracefully log out of server. */
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);
-}
-
-/*
-int imap_close_connection (CONTEXT *ctx)
-{
- 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_free_idata(&idata);
}
-*/
/* imap_set_flag: append str to flags if we currently have permission
* according to aclbit */
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;
}
/* 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;
}
}
/* 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;
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
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;
}
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;
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) {
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);
- mutt_parse_rc_line (mbox, &token, &err);
- p_delete(&token.data);
+ buffy_do_mailboxes(path, subscribe);
}
if (subscribe)
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);
/* 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);
completions++;
}
}
- while (m_strncmp(idata->cmd.seq, idata->cmd.buf, SEQLEN));
+ while (m_strncmp(idata->cmd.seq, idata->cmd.buf.data, SEQLEN));
if (completions) {
/* reformat output */
IMAP_DATA *imap_data;
if (!ctx)
- return (-1);
+ return -1;
imap_data = (IMAP_DATA *) ctx->data;
mx_open_mailbox (ctx->path, 0, ctx);
return 0;
}
+
+static 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,
+};