X-Git-Url: https://git.llucax.com/software/mutt-debian.git/blobdiff_plain/14c29200cb58d3c4a0830265f2433849781858d0..939639fcf1dad1b8f3a85d641f41d11c49281f3c:/imap/util.c diff --git a/imap/util.c b/imap/util.c index 785d8f3..b38268e 100644 --- a/imap/util.c +++ b/imap/util.c @@ -1,22 +1,22 @@ /* * Copyright (C) 1996-8 Michael R. Elkins * Copyright (C) 1996-9 Brandon Long - * Copyright (C) 1999-2005 Brendan Cully - * + * Copyright (C) 1999-2009 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 * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ + */ /* general IMAP utility functions */ @@ -26,7 +26,6 @@ #include "mx.h" /* for M_IMAP */ #include "url.h" #include "imap_private.h" -#include "mutt_ssl.h" #ifdef USE_HCACHE #include "message.h" #include "hcache.h" @@ -55,14 +54,18 @@ int imap_expand_path (char* path, size_t len) { IMAP_MBOX mx; + IMAP_DATA* idata; ciss_url_t url; + char fixedpath[LONG_STRING]; int rc; if (imap_parse_path (path, &mx) < 0) return -1; + idata = imap_conn_find (&mx.account, M_IMAP_CONN_NONEW); mutt_account_tourl (&mx.account, &url); - url.path = mx.mbox; + imap_fix_path (idata, mx.mbox, fixedpath, sizeof (fixedpath)); + url.path = fixedpath; rc = url_ciss_tostring (&url, path, len, U_DECODE_PASSWD); FREE (&mx.mbox); @@ -126,6 +129,8 @@ HEADER* imap_hcache_get (IMAP_DATA* idata, unsigned int uid) { if (*uv == idata->uid_validity) h = mutt_hcache_restore ((unsigned char*)uv, NULL); + else + dprint (3, (debugfile, "hcache uidvalidity mismatch: %u", *uv)); FREE (&uv); } @@ -189,7 +194,7 @@ int imap_parse_path (const char* path, IMAP_MBOX* mx) } /* Defaults */ - mx->account.flags = 0; + memset(&mx->account, 0, sizeof(mx->account)); mx->account.port = ImapPort; mx->account.type = M_ACCT_TYPE_IMAP; @@ -223,7 +228,7 @@ int imap_parse_path (const char* path, IMAP_MBOX* mx) else /* walk past closing '}' */ mx->mbox = safe_strdup (c+1); - + if ((c = strrchr (tmp, '@'))) { *c = '\0'; @@ -231,14 +236,14 @@ int imap_parse_path (const char* path, IMAP_MBOX* mx) strfcpy (tmp, c+1, sizeof (tmp)); mx->account.flags |= M_ACCT_USER; } - + if ((n = sscanf (tmp, "%127[^:/]%127s", mx->account.host, tmp)) < 1) { dprint (1, (debugfile, "imap_parse_path: NULL host in %s\n", path)); FREE (&mx->mbox); return -1; } - + if (n > 1) { if (sscanf (tmp, ":%hu%127s", &(mx->account.port), tmp) >= 1) mx->account.flags |= M_ACCT_PORT; @@ -265,10 +270,28 @@ int imap_parse_path (const char* path, IMAP_MBOX* mx) /* silly helper for mailbox name string comparisons, because of INBOX */ int imap_mxcmp (const char* mx1, const char* mx2) { + char* b1; + char* b2; + int rc; + + if (!mx1 || !*mx1) + mx1 = "INBOX"; + if (!mx2 || !*mx2) + mx2 = "INBOX"; if (!ascii_strcasecmp (mx1, "INBOX") && !ascii_strcasecmp (mx2, "INBOX")) return 0; - - return mutt_strcmp (mx1, mx2); + + b1 = safe_malloc (strlen (mx1) + 1); + b2 = safe_malloc (strlen (mx2) + 1); + + imap_fix_path (NULL, mx1, b1, strlen (mx1) + 1); + imap_fix_path (NULL, mx2, b2, strlen (mx2) + 1); + + rc = mutt_strcmp (b1, b2); + FREE (&b1); + FREE (&b2); + + return rc; } /* imap_pretty_mailbox: called by mutt_pretty_mailbox to make IMAP paths @@ -295,7 +318,7 @@ void imap_pretty_mailbox (char* path) { if (! hlen) home_match = 1; - else + else if (ImapDelimChars) for (delim = ImapDelimChars; *delim != '\0'; delim++) if (target.mbox[hlen] == *delim) home_match = 1; @@ -354,6 +377,13 @@ IMAP_DATA* imap_new_idata (void) if (!(idata->cmdbuf = mutt_buffer_init (NULL))) FREE (&idata); + idata->cmdslots = ImapPipelineDepth + 2; + if (!(idata->cmds = safe_calloc(idata->cmdslots, sizeof(*idata->cmds)))) + { + mutt_buffer_free(&idata->cmdbuf); + FREE (&idata); + } + return idata; } @@ -369,6 +399,7 @@ void imap_free_idata (IMAP_DATA** idata) mutt_buffer_free(&(*idata)->cmdbuf); FREE (&(*idata)->buf); mutt_bcache_close (&(*idata)->bcache); + FREE (&(*idata)->cmds); FREE (idata); /* __FREE_CHECKED__ */ } @@ -380,31 +411,40 @@ void imap_free_idata (IMAP_DATA** idata) * are not required to do this. * Moreover, IMAP servers may dislike the path ending with the delimiter. */ -char *imap_fix_path (IMAP_DATA *idata, char *mailbox, char *path, +char *imap_fix_path (IMAP_DATA *idata, const char *mailbox, char *path, size_t plen) { - int x = 0; + int i = 0; + char delim = '\0'; + + if (idata) + delim = idata->delim; - while (mailbox && *mailbox && (x < (plen - 1))) + while (mailbox && *mailbox && i < plen - 1) { - if ((*mailbox == '/') || (*mailbox == idata->delim)) + if ((ImapDelimChars && strchr(ImapDelimChars, *mailbox)) + || (delim && *mailbox == delim)) { - while ((*mailbox == '/') || (*mailbox == idata->delim)) mailbox++; - path[x] = idata->delim; + /* use connection delimiter if known. Otherwise use user delimiter */ + if (!idata) + delim = *mailbox; + + while (*mailbox + && ((ImapDelimChars && strchr(ImapDelimChars, *mailbox)) + || (delim && *mailbox == delim))) + mailbox++; + path[i] = delim; } else { - path[x] = *mailbox; + path[i] = *mailbox; mailbox++; } - x++; + i++; } - if (x && path[--x] != idata->delim) - x++; - path[x] = '\0'; - - if (!path[0]) - strfcpy (path, "INBOX", plen); + if (i && path[--i] != delim) + i++; + path[i] = '\0'; return path; } @@ -498,7 +538,7 @@ 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')); + t.tm_mday = (s[0] == ' '? s[1] - '0' : (s[0] - '0') * 10 + (s[1] - '0')); s += 2; if (*s != '-') return 0; @@ -540,6 +580,21 @@ time_t imap_parse_date (char *s) return (mutt_mktime (&t, 0) + tz); } +/* format date in IMAP style: DD-MMM-YYYY HH:MM:SS +ZZzz. + * Caller should provide a buffer of IMAP_DATELEN bytes */ +void imap_make_date (char *buf, time_t timestamp) +{ + struct tm* tm = localtime (×tamp); + time_t tz = mutt_local_tz (timestamp); + + tz /= 60; + + snprintf (buf, IMAP_DATELEN, "%02d-%s-%d %02d:%02d:%02d %+03d%02d", + tm->tm_mday, Months[tm->tm_mon], tm->tm_year + 1900, + tm->tm_hour, tm->tm_min, tm->tm_sec, + (int) tz / 60, (int) abs (tz) % 60); +} + /* imap_qualify_path: make an absolute IMAP folder target, given IMAP_MBOX * and relative path. */ void imap_qualify_path (char *dest, size_t len, IMAP_MBOX *mx, char* path) @@ -566,7 +621,7 @@ void imap_quote_string (char *dest, size_t dlen, const char *src) *pt++ = '"'; /* save room for trailing quote-char */ dlen -= 2; - + for (; *s && dlen; s++) { if (strchr (quote, *s)) @@ -646,7 +701,7 @@ void imap_unmunge_mbox_name (char *s) imap_utf7_decode (&buf); strncpy (s, buf, strlen (s)); } - + FREE (&buf); } @@ -672,10 +727,10 @@ int imap_wordcasecmp(const char *a, const char *b) return ascii_strcasecmp(a, tmp); } -/* +/* * Imap keepalive: poll the current folder to keep the * connection alive. - * + * */ static RETSIGTYPE alrm_handler (int sig) @@ -694,6 +749,8 @@ void imap_keepalive (void) { if (conn->account.type == M_ACCT_TYPE_IMAP) { + int need_free = 0; + idata = (IMAP_DATA*) conn->data; if (idata->state >= IMAP_AUTHENTICATED @@ -705,9 +762,17 @@ void imap_keepalive (void) { ctx = safe_calloc (1, sizeof (CONTEXT)); ctx->data = idata; + /* imap_close_mailbox will set ctx->iadata->ctx to NULL, so we can't + * rely on the value of iadata->ctx to determine if this placeholder + * context needs to be freed. + */ + need_free = 1; } + /* if the imap connection closes during this call, ctx may be invalid + * after this point, and thus should not be read. + */ imap_check_mailbox (ctx, NULL, 1); - if (!idata->ctx) + if (need_free) FREE (&ctx); } } @@ -724,7 +789,7 @@ int imap_wait_keepalive (pid_t pid) int rc; short imap_passive = option (OPTIMAPPASSIVE); - + set_option (OPTIMAPPASSIVE); set_option (OPTKEEPQUIET); @@ -749,7 +814,7 @@ int imap_wait_keepalive (pid_t pid) } alarm (0); /* cancel a possibly pending alarm */ - + sigaction (SIGALRM, &oldalrm, NULL); sigprocmask (SIG_SETMASK, &oldmask, NULL); @@ -773,3 +838,13 @@ void imap_disallow_reopen (CONTEXT *ctx) if (ctx && ctx->magic == M_IMAP && CTX_DATA->ctx == ctx) CTX_DATA->reopen &= ~IMAP_REOPEN_ALLOW; } + +int imap_account_match (const ACCOUNT* a1, const ACCOUNT* a2) +{ + IMAP_DATA* a1_idata = imap_conn_find (a1, M_IMAP_CONN_NONEW); + IMAP_DATA* a2_idata = imap_conn_find (a2, M_IMAP_CONN_NONEW); + const ACCOUNT* a1_canon = a1_idata == NULL ? a1 : &a1_idata->conn->account; + const ACCOUNT* a2_canon = a2_idata == NULL ? a2 : &a2_idata->conn->account; + + return mutt_account_match (a1_canon, a2_canon); +}