X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=mx.c;h=fde597c67fec215ea0fbbcd11de5680e8c09efda;hp=974ce3c22e8385a98fc08755d1b4e21c563c801f;hb=98cf5779d8184a74541be1bc61d15c5f35efd310;hpb=420f3633557ed75a0de989eb065af6e09eed29ba diff --git a/mx.c b/mx.c index 974ce3c..fde597c 100644 --- a/mx.c +++ b/mx.c @@ -1,72 +1,56 @@ /* + * Copyright notice from original mutt: * Copyright (C) 1996-2002 Michael R. Elkins * Copyright (C) 1999-2000 Thomas Roessler - * - * 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - */ + * + * This file is part of mutt-ng, see http://www.muttng.org/. + * It's licensed under the GNU General Public License, + * please see the file GPL in the top level source directory. + */ + +#include + +#include + +#include +#include +#include #include "mutt.h" +#include "buffy.h" #include "mx.h" -#include "rfc2047.h" +#include "mbox.h" +#include "mh.h" #include "sort.h" -#include "mailbox.h" +#include "thread.h" #include "copy.h" #include "keymap.h" -#include "url.h" - -#ifdef USE_COMPRESSED #include "compress.h" -#endif -#ifdef USE_IMAP -#include "imap.h" -#endif +#include +#include -#ifdef USE_POP -#include "pop.h" -#endif +#include +#include #ifdef USE_NNTP -#include "nntp.h" -#endif - -#ifdef BUFFY_SIZE -#include "buffy.h" +#include "nntp/nntp.h" +#include "nntp/mx_nntp.h" #endif #ifdef USE_DOTLOCK #include "dotlock.h" #endif -#include "mutt_crypt.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef BUFFY_SIZE -#include -#endif +#include +#include "lib/list.h" -#define mutt_is_spool(s) (mutt_strcmp (Spoolfile, s) == 0) +static list2_t* MailboxFormats = NULL; +#define MX_COMMAND(idx,cmd) ((mx_t*) MailboxFormats->data[idx])->cmd +#define MX_IDX(idx) (idx >= 0 && idx < MailboxFormats->length) + +#define mutt_is_spool(s) (m_strcmp(Spoolfile, s) == 0) #ifdef USE_DOTLOCK /* parameters: @@ -74,85 +58,98 @@ * retry - should retry if unable to lock? */ -#ifdef DL_STANDALONE - -static int invoke_dotlock (const char *path, int dummy, int flags, int retry) +static int invoke_dotlock (const char *path, int flags, int retry) { char cmd[LONG_STRING + _POSIX_PATH_MAX]; char f[SHORT_STRING + _POSIX_PATH_MAX]; char r[SHORT_STRING]; - + if (flags & DL_FL_RETRY) snprintf (r, sizeof (r), "-r %d ", retry ? MAXLOCKATTEMPT : 0); - + mutt_quote_filename (f, sizeof (f), path); - + snprintf (cmd, sizeof (cmd), - "%s %s%s%s%s%s%s%s", - NONULL (MuttDotlock), - flags & DL_FL_TRY ? "-t " : "", - flags & DL_FL_UNLOCK ? "-u " : "", - flags & DL_FL_USEPRIV ? "-p " : "", - flags & DL_FL_FORCE ? "-f " : "", - flags & DL_FL_UNLINK ? "-d " : "", - flags & DL_FL_RETRY ? r : "", - f); - + "%s %s%s%s%s%s%s%s", + NONULL (MuttDotlock), + flags & DL_FL_TRY ? "-t " : "", + flags & DL_FL_UNLOCK ? "-u " : "", + flags & DL_FL_USEPRIV ? "-p " : "", + flags & DL_FL_FORCE ? "-f " : "", + flags & DL_FL_UNLINK ? "-d " : "", + flags & DL_FL_RETRY ? r : "", f); + return mutt_system (cmd); } -#else - -#define invoke_dotlock dotlock_invoke - -#endif - -static int dotlock_file (const char *path, int fd, int retry) +static int dotlock_file (const char *path, int retry) { int r; int flags = DL_FL_USEPRIV | DL_FL_RETRY; - if (retry) retry = 1; + if (retry) + retry = 1; retry_lock: - if ((r = invoke_dotlock(path, fd, flags, retry)) == DL_EX_EXIST) - { - if (!option (OPTNOCURSES)) - { + if ((r = invoke_dotlock (path, flags, retry)) == DL_EX_EXIST) { + if (!option (OPTNOCURSES)) { char msg[LONG_STRING]; - - snprintf(msg, sizeof(msg), _("Lock count exceeded, remove lock for %s?"), - path); - if(retry && mutt_yesorno(msg, M_YES) == M_YES) - { - flags |= DL_FL_FORCE; - retry--; - mutt_clear_error (); - goto retry_lock; + + snprintf (msg, sizeof (msg), + _("Lock count exceeded, remove lock for %s?"), path); + if (retry && mutt_yesorno (msg, M_YES) == M_YES) { + flags |= DL_FL_FORCE; + retry--; + mutt_clear_error (); + goto retry_lock; } - } - else - { - mutt_error ( _("Can't dotlock %s.\n"), path); + } + else { + mutt_error (_("Can't dotlock %s.\n"), path); } } return (r == DL_EX_OK ? 0 : -1); } -static int undotlock_file (const char *path, int fd) +static int undotlock_file (const char *path) { - return (invoke_dotlock(path, fd, DL_FL_USEPRIV | DL_FL_UNLOCK, 0) == DL_EX_OK ? - 0 : -1); + return (invoke_dotlock (path, DL_FL_USEPRIV | DL_FL_UNLOCK, 0) == + DL_EX_OK ? 0 : -1); } #endif /* USE_DOTLOCK */ +/* looks up index of type for path in MailboxFormats */ +static int mx_get_idx (const char* path) { + int i = 0, t = 0; + struct stat st; + + /* first, test all non-local folders to avoid stat() call */ + for (i = 0; i < MailboxFormats->length; i++) { + if (!MX_COMMAND(i,local)) + t = MX_COMMAND(i,mx_is_magic)(path, NULL); + if (t >= 1) + return (t-1); + } + if (stat (path, &st) == 0) { + /* if stat() succeeded, keep testing until success and + * pass stat() info so that we only need to do it once */ + for (i = 0; i < MailboxFormats->length; i++) { + if (MX_COMMAND(i,local)) + t = MX_COMMAND(i,mx_is_magic)(path, &st); + if (t >= 1) + return (t-1); + } + } + return (-1); +} + /* Args: * excl if excl != 0, request an exclusive lock * dot if dot != 0, try to dotlock the file - * timeout should retry locking? + * time_out should retry locking? */ -int mx_lock_file (const char *path, int fd, int excl, int dot, int timeout) +int mx_lock_file (const char *path, int fd, int excl, int dot, int time_out) { #if defined (USE_FCNTL) || defined (USE_FLOCK) int count; @@ -163,35 +160,35 @@ int mx_lock_file (const char *path, int fd, int excl, int dot, int timeout) #ifdef USE_FCNTL struct flock lck; - - memset (&lck, 0, sizeof (struct flock)); + + p_clear(&lck, 1); lck.l_type = excl ? F_WRLCK : F_RDLCK; lck.l_whence = SEEK_SET; count = 0; attempt = 0; - while (fcntl (fd, F_SETLK, &lck) == -1) - { + prev_sb.st_size = 0; + while (fcntl (fd, F_SETLK, &lck) == -1) { struct stat sb; - dprint(1,(debugfile, "mx_lock_file(): fcntl errno %d.\n", errno)); - if (errno != EAGAIN && errno != EACCES) - { + + if (errno != EAGAIN && errno != EACCES) { mutt_perror ("fcntl"); return (-1); } if (fstat (fd, &sb) != 0) - sb.st_size = 0; - + sb.st_size = 0; + if (count == 0) prev_sb = sb; /* only unlock file if it is unchanged */ - if (prev_sb.st_size == sb.st_size && ++count >= (timeout?MAXLOCKATTEMPT:0)) - { - if (timeout) - mutt_error _("Timeout exceeded while attempting fcntl lock!"); + if (prev_sb.st_size == sb.st_size + && ++count >= (time_out ? MAXLOCKATTEMPT : 0)) { + if (time_out) + mutt_error _("Timeout exceeded while attempting fcntl lock!"); + return (-1); } @@ -205,27 +202,27 @@ int mx_lock_file (const char *path, int fd, int excl, int dot, int timeout) #ifdef USE_FLOCK count = 0; attempt = 0; - while (flock (fd, (excl ? LOCK_EX : LOCK_SH) | LOCK_NB) == -1) - { + while (flock (fd, (excl ? LOCK_EX : LOCK_SH) | LOCK_NB) == -1) { struct stat sb; - if (errno != EWOULDBLOCK) - { + + if (errno != EWOULDBLOCK) { mutt_perror ("flock"); r = -1; break; } - if (fstat(fd,&sb) != 0 ) - sb.st_size=0; - + if (fstat (fd, &sb) != 0) + sb.st_size = 0; + if (count == 0) - prev_sb=sb; + prev_sb = sb; /* only unlock file if it is unchanged */ - if (prev_sb.st_size == sb.st_size && ++count >= (timeout?MAXLOCKATTEMPT:0)) - { - if (timeout) - mutt_error _("Timeout exceeded while attempting flock lock!"); + if (prev_sb.st_size == sb.st_size + && ++count >= (time_out ? MAXLOCKATTEMPT : 0)) { + if (time_out) + mutt_error _("Timeout exceeded while attempting flock lock!"); + r = -1; break; } @@ -239,11 +236,10 @@ int mx_lock_file (const char *path, int fd, int excl, int dot, int timeout) #ifdef USE_DOTLOCK if (r == 0 && dot) - r = dotlock_file (path, fd, timeout); + r = dotlock_file (path, time_out); #endif /* USE_DOTLOCK */ - if (r == -1) - { + if (r == -1) { /* release any other locks obtained in this routine */ #ifdef USE_FCNTL @@ -264,9 +260,9 @@ int mx_lock_file (const char *path, int fd, int excl, int dot, int timeout) int mx_unlock_file (const char *path, int fd, int dot) { #ifdef USE_FCNTL - struct flock unlockit = { F_UNLCK, 0, 0, 0 }; + struct flock unlockit; - memset (&unlockit, 0, sizeof (struct flock)); + p_clear(&unlockit, 1); unlockit.l_type = F_UNLCK; unlockit.l_whence = SEEK_SET; fcntl (fd, F_SETLK, &unlockit); @@ -278,15 +274,16 @@ int mx_unlock_file (const char *path, int fd, int dot) #ifdef USE_DOTLOCK if (dot) - undotlock_file (path, fd); + undotlock_file (path); #endif - + return 0; } -void mx_unlink_empty (const char *path) +static void mx_unlink_empty (const char *path) { int fd; + #ifndef USE_DOTLOCK struct stat sb; #endif @@ -294,14 +291,13 @@ void mx_unlink_empty (const char *path) if ((fd = open (path, O_RDWR)) == -1) return; - if (mx_lock_file (path, fd, 1, 0, 1) == -1) - { + if (mx_lock_file (path, fd, 1, 0, 1) == -1) { close (fd); return; } #ifdef USE_DOTLOCK - invoke_dotlock (path, fd, DL_FL_UNLINK, 1); + invoke_dotlock (path, DL_FL_UNLINK, 1); #else if (fstat (fd, &sb) == 0 && sb.st_size == 0) unlink (path); @@ -311,180 +307,21 @@ void mx_unlink_empty (const char *path) close (fd); } -/* try to figure out what type of mailbox ``path'' is - * - * return values: - * M_* mailbox type - * 0 not a mailbox - * -1 error - */ - -#ifdef USE_IMAP - -int mx_is_imap(const char *p) -{ - url_scheme_t scheme; - - if (!p) - return 0; - - if (*p == '{') - return 1; - - scheme = url_check_scheme (p); - if (scheme == U_IMAP || scheme == U_IMAPS) - return 1; - - return 0; -} - -#endif - -#ifdef USE_POP -int mx_is_pop (const char *p) -{ - url_scheme_t scheme; - - if (!p) - return 0; - - scheme = url_check_scheme (p); - if (scheme == U_POP || scheme == U_POPS) - return 1; - - return 0; -} -#endif - -#ifdef USE_NNTP -int mx_is_nntp (const char *p) -{ - url_scheme_t scheme; - - if (!p) - return 0; - - scheme = url_check_scheme (p); - if (scheme == U_NNTP || scheme == U_NNTPS) - return 1; - - return 0; -} -#endif - -int mx_get_magic (const char *path) -{ - struct stat st; - int magic = 0; - char tmp[_POSIX_PATH_MAX]; - FILE *f; - -#ifdef USE_IMAP - if(mx_is_imap(path)) - return M_IMAP; -#endif /* USE_IMAP */ - -#ifdef USE_POP - if (mx_is_pop (path)) - return M_POP; -#endif /* USE_POP */ - -#ifdef USE_NNTP - if (mx_is_nntp (path)) - return M_NNTP; -#endif /* USE_NNTP */ - - if (stat (path, &st) == -1) - { - dprint (1, (debugfile, "mx_get_magic(): unable to stat %s: %s (errno %d).\n", - path, strerror (errno), errno)); - return (-1); - } - - if (S_ISDIR (st.st_mode)) - { - /* check for maildir-style mailbox */ - - snprintf (tmp, sizeof (tmp), "%s/cur", path); - if (stat (tmp, &st) == 0 && S_ISDIR (st.st_mode)) - return (M_MAILDIR); - - /* check for mh-style mailbox */ - - snprintf (tmp, sizeof (tmp), "%s/.mh_sequences", path); - if (access (tmp, F_OK) == 0) - return (M_MH); - - snprintf (tmp, sizeof (tmp), "%s/.xmhcache", path); - if (access (tmp, F_OK) == 0) - return (M_MH); - - snprintf (tmp, sizeof (tmp), "%s/.mew_cache", path); - if (access (tmp, F_OK) == 0) - return (M_MH); - - snprintf (tmp, sizeof (tmp), "%s/.mew-cache", path); - if (access (tmp, F_OK) == 0) - return (M_MH); - - snprintf (tmp, sizeof (tmp), "%s/.sylpheed_cache", path); - if (access (tmp, F_OK) == 0) - return (M_MH); - - /* - * ok, this isn't an mh folder, but mh mode can be used to read - * Usenet news from the spool. ;-) - */ - - snprintf (tmp, sizeof (tmp), "%s/.overview", path); - if (access (tmp, F_OK) == 0) - return (M_MH); - - } - else if (st.st_size == 0) - { - /* hard to tell what zero-length files are, so assume the default magic */ - if (DefaultMagic == M_MBOX || DefaultMagic == M_MMDF) - return (DefaultMagic); - else - return (M_MBOX); - } - else if ((f = fopen (path, "r")) != NULL) - { -#ifndef BUFFY_SIZE - struct utimbuf times; -#endif +/* try to figure out what type of mailbox ``path'' is */ +int mx_get_magic (const char *path) { + int i = 0; - fgets (tmp, sizeof (tmp), f); - if (mutt_strncmp ("From ", tmp, 5) == 0) - magic = M_MBOX; - else if (mutt_strcmp (MMDF_SEP, tmp) == 0) - magic = M_MMDF; - safe_fclose (&f); -#ifndef BUFFY_SIZE - /* need to restore the times here, the file was not really accessed, - * only the type was accessed. This is important, because detection - * of "new mail" depends on those times set correctly. - */ - times.actime = st.st_atime; - times.modtime = st.st_mtime; - utime (path, ×); -#endif - } - else - { - dprint (1, (debugfile, "mx_get_magic(): unable to open file %s for reading.\n", - path)); - mutt_perror (path); + if (m_strlen(path) == 0) return (-1); - } - -#ifdef USE_COMPRESSED - if (magic == 0 && mutt_can_read_compressed (path)) - return M_COMPRESSED; -#endif + if ((i = mx_get_idx (path)) >= 0) + return (MX_COMMAND(i,type)); + return (-1); +} - return (magic); +int mx_is_local (int m) { + if (!MX_IDX(m)) + return (0); + return (MX_COMMAND(m,local)); } /* @@ -509,141 +346,120 @@ int mx_set_magic (const char *s) /* mx_access: Wrapper for access, checks permissions on a given mailbox. * We may be interested in using ACL-style flags at some point, currently * we use the normal access() flags. */ -int mx_access (const char* path, int flags) +int mx_access (const char *path, int flags) { -#ifdef USE_IMAP - if (mx_is_imap (path)) - return imap_access (path, flags); -#endif + int i = 0; - return access (path, flags); + if ((i = mx_get_idx (path)) >= 0 && MX_COMMAND(i,mx_access)) + return (MX_COMMAND(i,mx_access)(path,flags)); + return (0); } -static int mx_open_mailbox_append (CONTEXT *ctx, int flags) +static int mx_open_mailbox_append (CONTEXT * ctx, int flags) { struct stat sb; -#ifdef USE_COMPRESSED /* special case for appending to compressed folders - * even if we can not open them for reading */ if (mutt_can_append_compressed (ctx->path)) mutt_open_append_compressed (ctx); -#endif ctx->append = 1; -#ifdef USE_IMAP - - if(mx_is_imap(ctx->path)) + if (mx_get_magic (ctx->path) == M_IMAP) return imap_open_mailbox_append (ctx); -#endif - - if(stat(ctx->path, &sb) == 0) - { + if (stat (ctx->path, &sb) == 0) { ctx->magic = mx_get_magic (ctx->path); - - switch (ctx->magic) - { - case 0: - mutt_error (_("%s is not a mailbox."), ctx->path); - /* fall through */ - case -1: - return (-1); + + switch (ctx->magic) { + case 0: + mutt_error (_("%s is not a mailbox."), ctx->path); + /* fall through */ + case -1: + return (-1); } } - else if (errno == ENOENT) - { + else if (errno == ENOENT) { ctx->magic = DefaultMagic; - if (ctx->magic == M_MH || ctx->magic == M_MAILDIR) - { + if (ctx->magic == M_MH || ctx->magic == M_MAILDIR) { char tmp[_POSIX_PATH_MAX]; - if (mkdir (ctx->path, S_IRWXU)) - { - mutt_perror (ctx->path); - return (-1); + if (mkdir (ctx->path, S_IRWXU)) { + mutt_perror (ctx->path); + return (-1); } - if (ctx->magic == M_MAILDIR) - { - snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path); - if (mkdir (tmp, S_IRWXU)) - { - mutt_perror (tmp); - rmdir (ctx->path); - return (-1); - } - - snprintf (tmp, sizeof (tmp), "%s/new", ctx->path); - if (mkdir (tmp, S_IRWXU)) - { - mutt_perror (tmp); - snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path); - rmdir (tmp); - rmdir (ctx->path); - return (-1); - } - snprintf (tmp, sizeof (tmp), "%s/tmp", ctx->path); - if (mkdir (tmp, S_IRWXU)) - { - mutt_perror (tmp); - snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path); - rmdir (tmp); - snprintf (tmp, sizeof (tmp), "%s/new", ctx->path); - rmdir (tmp); - rmdir (ctx->path); - return (-1); - } + if (ctx->magic == M_MAILDIR) { + snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path); + if (mkdir (tmp, S_IRWXU)) { + mutt_perror (tmp); + rmdir (ctx->path); + return (-1); + } + + snprintf (tmp, sizeof (tmp), "%s/new", ctx->path); + if (mkdir (tmp, S_IRWXU)) { + mutt_perror (tmp); + snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path); + rmdir (tmp); + rmdir (ctx->path); + return (-1); + } + snprintf (tmp, sizeof (tmp), "%s/tmp", ctx->path); + if (mkdir (tmp, S_IRWXU)) { + mutt_perror (tmp); + snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path); + rmdir (tmp); + snprintf (tmp, sizeof (tmp), "%s/new", ctx->path); + rmdir (tmp); + rmdir (ctx->path); + return (-1); + } } - else - { - int i; - - snprintf (tmp, sizeof (tmp), "%s/.mh_sequences", ctx->path); - if ((i = creat (tmp, S_IRWXU)) == -1) - { - mutt_perror (tmp); - rmdir (ctx->path); - return (-1); - } - close (i); + else { + int i; + + snprintf (tmp, sizeof (tmp), "%s/.mh_sequences", ctx->path); + if ((i = creat (tmp, S_IRWXU)) == -1) { + mutt_perror (tmp); + rmdir (ctx->path); + return (-1); + } + close (i); } } } - else - { + else { mutt_perror (ctx->path); return (-1); } - switch (ctx->magic) - { - case M_MBOX: - case M_MMDF: - if ((ctx->fp = safe_fopen (ctx->path, flags & M_NEWFOLDER ? "w" : "a")) == NULL || - mbox_lock_mailbox (ctx, 1, 1) != 0) - { - if (!ctx->fp) - mutt_perror (ctx->path); - else - { - mutt_error (_("Couldn't lock %s\n"), ctx->path); - safe_fclose (&ctx->fp); - } - return (-1); + switch (ctx->magic) { + case M_MBOX: + case M_MMDF: + if ((ctx->fp = + safe_fopen (ctx->path, flags & M_NEWFOLDER ? "w" : "a")) == NULL + || mbox_lock_mailbox (ctx, 1, 1) != 0) { + if (!ctx->fp) + mutt_perror (ctx->path); + else { + mutt_error (_("Couldn't lock %s\n"), ctx->path); + safe_fclose (&ctx->fp); } - fseek (ctx->fp, 0, 2); - break; + return (-1); + } + fseeko (ctx->fp, 0, 2); + break; - case M_MH: - case M_MAILDIR: - /* nothing to do */ - break; + case M_MH: + case M_MAILDIR: + /* nothing to do */ + break; - default: - return (-1); + default: + return (-1); } return 0; @@ -659,57 +475,55 @@ static int mx_open_mailbox_append (CONTEXT *ctx, int flags) * M_QUIET only print error messages * ctx if non-null, context struct to use */ -CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx) +CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT * pctx) { CONTEXT *ctx = pctx; int rc; if (!ctx) - ctx = safe_malloc (sizeof (CONTEXT)); - memset (ctx, 0, sizeof (CONTEXT)); - ctx->path = safe_strdup (path); + ctx = p_new(CONTEXT, 1); + p_clear(ctx, 1); + ctx->path = m_strdup(path); ctx->msgnotreadyet = -1; ctx->collapsed = 0; - + if (flags & M_QUIET) ctx->quiet = 1; if (flags & M_READONLY) ctx->readonly = 1; + if (flags & M_COUNT) + ctx->counting = 1; - if (flags & (M_APPEND|M_NEWFOLDER)) - { - if (mx_open_mailbox_append (ctx, flags) != 0) - { + if (flags & (M_APPEND | M_NEWFOLDER)) { + if (mx_open_mailbox_append (ctx, flags) != 0) { mx_fastclose_mailbox (ctx); if (!pctx) - FREE (&ctx); + p_delete(&ctx); return NULL; } return ctx; } - ctx->magic = mx_get_magic (path); - -#ifdef USE_COMPRESSED + if (!MX_IDX(ctx->magic-1)) + ctx->magic = mx_get_magic (path); + if (ctx->magic == M_COMPRESSED) mutt_open_read_compressed (ctx); -#endif - if(ctx->magic == 0) + if (ctx->magic == 0) mutt_error (_("%s is not a mailbox."), path); - if(ctx->magic == -1) - mutt_perror(path); - - if(ctx->magic <= 0) - { + if (ctx->magic == -1) + mutt_perror (path); + + if (ctx->magic <= 0) { mx_fastclose_mailbox (ctx); if (!pctx) - FREE (&ctx); + p_delete(&ctx); return (NULL); } - + /* if the user has a `push' command in their .muttrc, or in a folder-hook, * it will cause the progress messages not to be displayed because * mutt_refresh() will think we are in the middle of a macro. so set a @@ -720,50 +534,12 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx) if (!ctx->quiet) mutt_message (_("Reading %s..."), ctx->path); - switch (ctx->magic) - { - case M_MH: - rc = mh_read_dir (ctx, NULL); - break; + rc = MX_COMMAND(ctx->magic-1,mx_open_mailbox)(ctx); - case M_MAILDIR: - rc = maildir_read_dir (ctx); - break; - - case M_MMDF: - case M_MBOX: - rc = mbox_open_mailbox (ctx); - break; - -#ifdef USE_IMAP - case M_IMAP: - rc = imap_open_mailbox (ctx); - break; -#endif /* USE_IMAP */ - -#ifdef USE_POP - case M_POP: - rc = pop_open_mailbox (ctx); - break; -#endif /* USE_POP */ - -#ifdef USE_NNTP - case M_NNTP: - rc = nntp_open_mailbox (ctx); - break; -#endif /* USE_NNTP */ - - default: - rc = -1; - break; - } - - if (rc == 0) - { - if ((flags & M_NOSORT) == 0) - { + if (rc == 0) { + if ((flags & M_NOSORT) == 0) { /* avoid unnecessary work since the mailbox is completely unthreaded - to begin with */ + to begin with */ unset_option (OPTSORTSUBTHREADS); unset_option (OPTNEEDRESCORE); mutt_sort_headers (ctx, 1); @@ -771,11 +547,10 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx) if (!ctx->quiet) mutt_clear_error (); } - else - { + else { mx_fastclose_mailbox (ctx); if (!pctx) - FREE (&ctx); + p_delete(&ctx); } unset_option (OPTFORCEREFRESH); @@ -783,160 +558,102 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx) } /* free up memory associated with the mailbox context */ -void mx_fastclose_mailbox (CONTEXT *ctx) +void mx_fastclose_mailbox (CONTEXT * ctx) { int i; - if(!ctx) + if (!ctx) return; - -#ifdef USE_IMAP - if (ctx->magic == M_IMAP) - imap_close_mailbox (ctx); -#endif /* USE_IMAP */ -#ifdef USE_POP - if (ctx->magic == M_POP) - pop_close_mailbox (ctx); -#endif /* USE_POP */ -#ifdef USE_NNTP - if (ctx->magic == M_NNTP) - nntp_fastclose_mailbox (ctx); -#endif /* USE_NNTP */ + + if (MX_IDX(ctx->magic-1) && MX_COMMAND(ctx->magic-1,mx_fastclose_mailbox)) + MX_COMMAND(ctx->magic-1,mx_fastclose_mailbox(ctx)); if (ctx->subj_hash) hash_destroy (&ctx->subj_hash, NULL); if (ctx->id_hash) hash_destroy (&ctx->id_hash, NULL); mutt_clear_threads (ctx); for (i = 0; i < ctx->msgcount; i++) - mutt_free_header (&ctx->hdrs[i]); - FREE (&ctx->hdrs); - FREE (&ctx->v2r); -#ifdef USE_COMPRESSED + header_delete(&ctx->hdrs[i]); + p_delete(&ctx->hdrs); + p_delete(&ctx->v2r); + if (ctx->compressinfo) mutt_fast_close_compressed (ctx); -#endif - FREE (&ctx->path); - FREE (&ctx->pattern); - if (ctx->limit_pattern) + + p_delete(&ctx->path); + p_delete(&ctx->pattern); + if (ctx->limit_pattern) mutt_pattern_free (&ctx->limit_pattern); safe_fclose (&ctx->fp); - memset (ctx, 0, sizeof (CONTEXT)); + p_clear(ctx, 1); } /* save changes to disk */ -static int sync_mailbox (CONTEXT *ctx, int *index_hint) +static int sync_mailbox (CONTEXT * ctx, int *index_hint) { -#ifdef BUFFY_SIZE - BUFFY *tmp = NULL; -#endif int rc = -1; if (!ctx->quiet) mutt_message (_("Writing %s..."), ctx->path); - switch (ctx->magic) - { - case M_MBOX: - case M_MMDF: - rc = mbox_sync_mailbox (ctx, index_hint); -#ifdef BUFFY_SIZE - tmp = mutt_find_mailbox (ctx->path); -#endif - break; - - case M_MH: - case M_MAILDIR: - rc = mh_sync_mailbox (ctx, index_hint); - break; - -#ifdef USE_IMAP - case M_IMAP: - /* extra argument means EXPUNGE */ - rc = imap_sync_mailbox (ctx, 1, index_hint); - break; -#endif /* USE_IMAP */ - -#ifdef USE_POP - case M_POP: - rc = pop_sync_mailbox (ctx, index_hint); - break; -#endif /* USE_POP */ + if (MX_IDX(ctx->magic-1)) + /* the 1 is only of interest for IMAP and means EXPUNGE */ + rc = MX_COMMAND(ctx->magic-1,mx_sync_mailbox(ctx,1,index_hint)); -#ifdef USE_NNTP - case M_NNTP: - rc = nntp_sync_mailbox (ctx); - break; -#endif /* USE_NNTP */ - } - -#if 0 - if (!ctx->quiet && !ctx->shutup && rc == -1) - mutt_error ( _("Could not synchronize mailbox %s!"), ctx->path); -#endif - -#ifdef BUFFY_SIZE - if (tmp && tmp->new == 0) - mutt_update_mailbox (tmp); -#endif - -#ifdef USE_COMPRESSED if (rc == 0 && ctx->compressinfo) return mutt_sync_compressed (ctx); -#endif return rc; } /* move deleted mails to the trash folder */ -static int trash_append (CONTEXT *ctx) +static int trash_append (CONTEXT * ctx) { - CONTEXT *ctx_trash; - int i = 0; - struct stat st, stc; + CONTEXT *ctx_trash; + int i = 0; + struct stat st, stc; - if (!TrashPath || !ctx->deleted || - (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH))) - return 0; + if (!TrashPath || !ctx->deleted || + (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH))) + return 0; - for (;i < ctx->msgcount && (!ctx->hdrs[i]->deleted || - ctx->hdrs[i]->appended); i++); - if (i == ctx->msgcount) - return 0; /* nothing to be done */ + for (; i < ctx->msgcount && (!ctx->hdrs[i]->deleted || + ctx->hdrs[i]->appended); i++); + if (i == ctx->msgcount) + return 0; /* nothing to be done */ - if (mutt_save_confirm (TrashPath, &st) != 0) - { - mutt_error _("message(s) not deleted"); - return -1; - } + if (mutt_save_confirm (TrashPath, &st) != 0) { + mutt_error _("message(s) not deleted"); - if (lstat (ctx->path, &stc) == 0 && stc.st_ino == st.st_ino - && stc.st_dev == st.st_dev && stc.st_rdev == st.st_rdev) - return 0; /* we are in the trash folder: simple sync */ + return -1; + } - if ((ctx_trash = mx_open_mailbox (TrashPath, M_APPEND, NULL)) != NULL) - { - for (i = 0 ; i < ctx->msgcount ; i++) - if (ctx->hdrs[i]->deleted && !ctx->hdrs[i]->appended - && !ctx->hdrs[i]->purged - && mutt_append_message (ctx_trash, ctx, ctx->hdrs[i], 0, 0) == -1) - { - mx_close_mailbox (ctx_trash, NULL); - return -1; - } - - mx_close_mailbox (ctx_trash, NULL); - } - else - { - mutt_error _("Can't open trash folder"); - return -1; - } + if (lstat (ctx->path, &stc) == 0 && stc.st_ino == st.st_ino + && stc.st_dev == st.st_dev && stc.st_rdev == st.st_rdev) + return 0; /* we are in the trash folder: simple sync */ - return 0; + if ((ctx_trash = mx_open_mailbox (TrashPath, M_APPEND, NULL)) != NULL) { + for (i = 0; i < ctx->msgcount; i++) + if (ctx->hdrs[i]->deleted && !ctx->hdrs[i]->appended + && !ctx->hdrs[i]->purged + && mutt_append_message (ctx_trash, ctx, ctx->hdrs[i], 0, 0) == -1) { + mx_close_mailbox (ctx_trash, NULL); + return -1; + } + + mx_close_mailbox (ctx_trash, NULL); + } + else { + mutt_error _("Can't open trash folder"); + + return -1; + } + + return 0; } /* save changes and close mailbox */ -int mx_close_mailbox (CONTEXT *ctx, int *index_hint) +static int _mx_close_mailbox (CONTEXT * ctx, int *index_hint) { int i, move_messages = 0, purge = 1, read_msgs = 0; int check; @@ -945,13 +662,13 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint) char mbox[_POSIX_PATH_MAX]; char buf[SHORT_STRING]; - if (!ctx) return 0; + if (!ctx) + return 0; ctx->closing = 1; #ifdef USE_NNTP - if (ctx->magic == M_NNTP) - { + if (ctx->magic == M_NNTP) { int ret; ret = nntp_close_mailbox (ctx); @@ -959,15 +676,13 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint) return ret; } #endif - if (ctx->readonly || ctx->dontwrite) - { + if (ctx->readonly || ctx->dontwrite) { /* mailbox is readonly or we don't want to write */ mx_fastclose_mailbox (ctx); return 0; } - if (ctx->append) - { + if (ctx->append) { /* mailbox was opened in write-mode */ if (ctx->magic == M_MBOX || ctx->magic == M_MMDF) mbox_close_mailbox (ctx); @@ -976,36 +691,30 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint) return 0; } - for (i = 0; i < ctx->msgcount; i++) - { - if (!ctx->hdrs[i]->deleted && ctx->hdrs[i]->read + for (i = 0; i < ctx->msgcount; i++) { + if (!ctx->hdrs[i]->deleted && ctx->hdrs[i]->read && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED))) read_msgs++; } - if (read_msgs && quadoption (OPT_MOVE) != M_NO) - { + if (read_msgs && quadoption (OPT_MOVE) != M_NO) { char *p; - if ((p = mutt_find_hook (M_MBOXHOOK, ctx->path))) - { + if ((p = mutt_find_hook (M_MBOXHOOK, ctx->path))) { isSpool = 1; - strfcpy (mbox, p, sizeof (mbox)); + m_strcpy(mbox, sizeof(mbox), p); } - else - { - strfcpy (mbox, NONULL(Inbox), sizeof (mbox)); + else { + m_strcpy(mbox, sizeof(mbox), NONULL(Inbox)); isSpool = mutt_is_spool (ctx->path) && !mutt_is_spool (mbox); } mutt_expand_path (mbox, sizeof (mbox)); - if (isSpool) - { + if (isSpool) { snprintf (buf, sizeof (buf), _("Move read messages to %s?"), mbox); - if ((move_messages = query_quadoption (OPT_MOVE, buf)) == -1) - { - ctx->closing = 0; - return (-1); + if ((move_messages = query_quadoption (OPT_MOVE, buf)) == -1) { + ctx->closing = 0; + return (-1); } } } @@ -1014,165 +723,148 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint) * There is no point in asking whether or not to purge if we are * just marking messages as "trash". */ - if (ctx->deleted && !(ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH))) - { + if (ctx->deleted && !(ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH))) { snprintf (buf, sizeof (buf), ctx->deleted == 1 - ? _("Purge %d deleted message?") : _("Purge %d deleted messages?"), - ctx->deleted); - if ((purge = query_quadoption (OPT_DELETE, buf)) < 0) - { + ? _("Purge %d deleted message?") : + _("Purge %d deleted messages?"), ctx->deleted); + if ((purge = query_quadoption (OPT_DELETE, buf)) < 0) { ctx->closing = 0; return (-1); } } -#ifdef USE_IMAP /* IMAP servers manage the OLD flag themselves */ if (ctx->magic != M_IMAP) -#endif - if (option (OPTMARKOLD)) - { - for (i = 0; i < ctx->msgcount; i++) - { - if (!ctx->hdrs[i]->deleted && !ctx->hdrs[i]->old) - mutt_set_flag (ctx, ctx->hdrs[i], M_OLD, 1); + if (option (OPTMARKOLD)) { + for (i = 0; i < ctx->msgcount; i++) { + if (!ctx->hdrs[i]->deleted && !ctx->hdrs[i]->old) + mutt_set_flag (ctx, ctx->hdrs[i], M_OLD, 1); + } } - } - if (move_messages) - { + if (move_messages) { mutt_message (_("Moving read messages to %s..."), mbox); -#ifdef USE_IMAP /* try to use server-side copy first */ i = 1; - - if (ctx->magic == M_IMAP && mx_is_imap (mbox)) - { + + if (ctx->magic == M_IMAP && imap_is_magic (mbox, NULL) == M_IMAP) { /* tag messages for moving, and clear old tags, if any */ for (i = 0; i < ctx->msgcount; i++) - if (ctx->hdrs[i]->read && !ctx->hdrs[i]->deleted - && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED))) - ctx->hdrs[i]->tagged = 1; - else - ctx->hdrs[i]->tagged = 0; - + if (ctx->hdrs[i]->read && !ctx->hdrs[i]->deleted + && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED))) + ctx->hdrs[i]->tagged = 1; + else + ctx->hdrs[i]->tagged = 0; + i = imap_copy_messages (ctx, NULL, mbox, 1); } - - if (i == 0) /* success */ + + if (i == 0) /* success */ mutt_clear_error (); - else if (i == -1) /* horrible error, bail */ - { - ctx->closing=0; + else if (i == -1) { /* horrible error, bail */ + ctx->closing = 0; return -1; } - else /* use regular append-copy mode */ -#endif + else /* use regular append-copy mode */ { - if (mx_open_mailbox (mbox, M_APPEND, &f) == NULL) - { - ctx->closing = 0; - return -1; + if (mx_open_mailbox (mbox, M_APPEND, &f) == NULL) { + ctx->closing = 0; + return -1; } - for (i = 0; i < ctx->msgcount; i++) - { - if (ctx->hdrs[i]->read && !ctx->hdrs[i]->deleted - && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED))) - { - if (mutt_append_message (&f, ctx, ctx->hdrs[i], 0, CH_UPDATE_LEN) == 0) - { - mutt_set_flag (ctx, ctx->hdrs[i], M_DELETE, 1); - mutt_set_flag (ctx, ctx->hdrs[i], M_APPENDED, 1); - } - else - { - mx_close_mailbox (&f, NULL); - ctx->closing = 0; - return -1; - } - } + for (i = 0; i < ctx->msgcount; i++) { + if (ctx->hdrs[i]->read && !ctx->hdrs[i]->deleted + && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED))) { + if (mutt_append_message (&f, ctx, ctx->hdrs[i], 0, CH_UPDATE_LEN) == + 0) { + mutt_set_flag (ctx, ctx->hdrs[i], M_DELETE, 1); + mutt_set_flag (ctx, ctx->hdrs[i], M_APPENDED, 1); + } + else { + mx_close_mailbox (&f, NULL); + ctx->closing = 0; + return -1; + } + } } - + mx_close_mailbox (&f, NULL); } - + } - else if (!ctx->changed && ctx->deleted == 0) - { + else if (!ctx->changed && ctx->deleted == 0) { mutt_message _("Mailbox is unchanged."); + mx_fastclose_mailbox (ctx); return 0; } - + /* copy mails to the trash before expunging */ if (purge && ctx->deleted) - if (trash_append (ctx) != 0) - { + if (trash_append (ctx) != 0) { ctx->closing = 0; return -1; } -#ifdef USE_IMAP /* allow IMAP to preserve the deleted flag across sessions */ - if (ctx->magic == M_IMAP) - { - if ((check = imap_sync_mailbox (ctx, purge, index_hint)) != 0) - { + if (ctx->magic == M_IMAP) { + if ((check = imap_sync_mailbox (ctx, purge, index_hint)) != 0) { ctx->closing = 0; return check; } } else -#endif { - if (!purge) - { + if (!purge) { for (i = 0; i < ctx->msgcount; i++) ctx->hdrs[i]->deleted = 0; ctx->deleted = 0; } - if (ctx->changed || ctx->deleted) - { - if ((check = sync_mailbox (ctx, index_hint)) != 0) - { - ctx->closing = 0; - return check; + if (ctx->changed || ctx->deleted) { + if ((check = sync_mailbox (ctx, index_hint)) != 0) { + ctx->closing = 0; + return check; } } } if (move_messages) - mutt_message (_("%d kept, %d moved, %d deleted."), - ctx->msgcount - ctx->deleted, read_msgs, ctx->deleted); + mutt_message (_("%d kept, %d moved, %d deleted."), + ctx->msgcount - ctx->deleted, read_msgs, ctx->deleted); else mutt_message (_("%d kept, %d deleted."), - ctx->msgcount - ctx->deleted, ctx->deleted); + ctx->msgcount - ctx->deleted, ctx->deleted); if (ctx->msgcount == ctx->deleted && (ctx->magic == M_MMDF || ctx->magic == M_MBOX) && - !mutt_is_spool(ctx->path) && !option (OPTSAVEEMPTY)) + !mutt_is_spool (ctx->path) && !option (OPTSAVEEMPTY)) mx_unlink_empty (ctx->path); -#ifdef USE_COMPRESSED if (ctx->compressinfo && mutt_slow_close_compressed (ctx)) return (-1); -#endif mx_fastclose_mailbox (ctx); return 0; } +int mx_close_mailbox (CONTEXT * ctx, int *index_hint) { + int ret = 0; + if (!ctx) + return (0); + ret = _mx_close_mailbox (ctx, index_hint); + sidebar_set_buffystats (ctx); + return (ret); +} /* update a Context structure's internal tables. */ -void mx_update_tables(CONTEXT *ctx, int committing) +void mx_update_tables (CONTEXT * ctx, int committing) { int i, j; - + /* update memory to reflect the new state of the mailbox */ ctx->vcount = 0; ctx->vsize = 0; @@ -1183,66 +875,67 @@ void mx_update_tables(CONTEXT *ctx, int committing) ctx->changed = 0; ctx->flagged = 0; #define this_body ctx->hdrs[j]->content - for (i = 0, j = 0; i < ctx->msgcount; i++) - { - if ((committing && (!ctx->hdrs[i]->deleted || - (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH)))) || - (!committing && ctx->hdrs[i]->active)) - { - if (i != j) - { - ctx->hdrs[j] = ctx->hdrs[i]; - ctx->hdrs[i] = NULL; + for (i = 0, j = 0; i < ctx->msgcount; i++) { + if ((committing && (!ctx->hdrs[i]->deleted || + (ctx->magic == M_MAILDIR + && option (OPTMAILDIRTRASH)))) || (!committing + && ctx->hdrs[i]-> + active)) { + if (i != j) { + ctx->hdrs[j] = ctx->hdrs[i]; + ctx->hdrs[i] = NULL; } ctx->hdrs[j]->msgno = j; - if (ctx->hdrs[j]->virtual != -1) - { - ctx->v2r[ctx->vcount] = j; - ctx->hdrs[j]->virtual = ctx->vcount++; - ctx->vsize += this_body->length + this_body->offset - - this_body->hdr_offset; + if (ctx->hdrs[j]->virtual != -1) { + ctx->v2r[ctx->vcount] = j; + ctx->hdrs[j]->virtual = ctx->vcount++; + ctx->vsize += this_body->length + this_body->offset - + this_body->hdr_offset; } if (committing) - ctx->hdrs[j]->changed = 0; + ctx->hdrs[j]->changed = 0; else if (ctx->hdrs[j]->changed) - ctx->changed++; - - if (!committing || (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH))) - { - if (ctx->hdrs[j]->deleted) - ctx->deleted++; + ctx->changed++; + + if (!committing + || (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH))) { + if (ctx->hdrs[j]->deleted) + ctx->deleted++; } if (ctx->hdrs[j]->tagged) - ctx->tagged++; + ctx->tagged++; if (ctx->hdrs[j]->flagged) - ctx->flagged++; - if (!ctx->hdrs[j]->read) - { - ctx->unread++; - if (!ctx->hdrs[j]->old) - ctx->new++; - } + ctx->flagged++; + if (!ctx->hdrs[j]->read) { + ctx->unread++; + if (!ctx->hdrs[j]->old) + ctx->new++; + } j++; } - else - { + else { if (ctx->magic == M_MH || ctx->magic == M_MAILDIR) - ctx->size -= (ctx->hdrs[i]->content->length + - ctx->hdrs[i]->content->offset - - ctx->hdrs[i]->content->hdr_offset); + ctx->size -= (ctx->hdrs[i]->content->length + + ctx->hdrs[i]->content->offset - + ctx->hdrs[i]->content->hdr_offset); /* remove message from the hash tables */ if (ctx->subj_hash && ctx->hdrs[i]->env->real_subj) - hash_delete (ctx->subj_hash, ctx->hdrs[i]->env->real_subj, ctx->hdrs[i], NULL); + hash_delete (ctx->subj_hash, ctx->hdrs[i]->env->real_subj, + ctx->hdrs[i], NULL); if (ctx->id_hash && ctx->hdrs[i]->env->message_id) - hash_delete (ctx->id_hash, ctx->hdrs[i]->env->message_id, ctx->hdrs[i], NULL); - mutt_free_header (&ctx->hdrs[i]); + hash_delete (ctx->id_hash, ctx->hdrs[i]->env->message_id, + ctx->hdrs[i], NULL); + header_delete(&ctx->hdrs[i]); } } #undef this_body ctx->msgcount = j; + + /* update sidebar count */ + sidebar_set_buffystats (ctx); } @@ -1252,61 +945,57 @@ void mx_update_tables(CONTEXT *ctx, int committing) * 0 success * -1 error */ -int mx_sync_mailbox (CONTEXT *ctx, int *index_hint) +static int _mx_sync_mailbox (CONTEXT * ctx, int *index_hint) { int rc, i; int purge = 1; int msgcount, deleted; - if (ctx->dontwrite) - { + if (ctx->dontwrite) { char buf[STRING], tmp[STRING]; - if (km_expand_key (buf, sizeof(buf), + + if (km_expand_key (buf, sizeof (buf), km_find_func (MENU_MAIN, OP_TOGGLE_WRITE))) - snprintf (tmp, sizeof(tmp), _(" Press '%s' to toggle write"), buf); + snprintf (tmp, sizeof (tmp), _(" Press '%s' to toggle write"), buf); else - strfcpy (tmp, _("Use 'toggle-write' to re-enable write!"), sizeof(tmp)); + m_strcpy(tmp, sizeof(tmp), _("Use 'toggle-write' to re-enable write!")); mutt_error (_("Mailbox is marked unwritable. %s"), tmp); return -1; } - else if (ctx->readonly) - { + else if (ctx->readonly) { mutt_error _("Mailbox is read-only."); + return -1; } - if (!ctx->changed && !ctx->deleted) - { + if (!ctx->changed && !ctx->deleted) { mutt_message _("Mailbox is unchanged."); + return (0); } - if (ctx->deleted) - { + if (ctx->deleted) { char buf[SHORT_STRING]; snprintf (buf, sizeof (buf), ctx->deleted == 1 - ? _("Purge %d deleted message?") : _("Purge %d deleted messages?"), - ctx->deleted); + ? _("Purge %d deleted message?") : + _("Purge %d deleted messages?"), ctx->deleted); if ((purge = query_quadoption (OPT_DELETE, buf)) < 0) return (-1); - else if (purge == M_NO) - { + else if (purge == M_NO) { if (!ctx->changed) - return 0; /* nothing to do! */ -#ifdef USE_IMAP + return 0; /* nothing to do! */ /* let IMAP servers hold on to D flags */ if (ctx->magic != M_IMAP) -#endif { - for (i = 0 ; i < ctx->msgcount ; i++) + for (i = 0; i < ctx->msgcount; i++) ctx->hdrs[i]->deleted = 0; ctx->deleted = 0; } } else if (ctx->last_tag && ctx->last_tag->deleted) - ctx->last_tag = NULL; /* reset last tagged msg now useless */ + ctx->last_tag = NULL; /* reset last tagged msg now useless */ } /* really only for IMAP - imap_sync_mailbox results in a call to @@ -1314,34 +1003,27 @@ int mx_sync_mailbox (CONTEXT *ctx, int *index_hint) msgcount = ctx->msgcount; deleted = ctx->deleted; - if (purge && ctx->deleted) - { + if (purge && ctx->deleted) { if (trash_append (ctx) == -1) return -1; - } + } -#ifdef USE_IMAP if (ctx->magic == M_IMAP) rc = imap_sync_mailbox (ctx, purge, index_hint); else -#endif rc = sync_mailbox (ctx, index_hint); - if (rc == 0) - { -#ifdef USE_IMAP + if (rc == 0) { if (ctx->magic == M_IMAP && !purge) - mutt_message _("Mailbox checkpointed."); + mutt_message (_("Mailbox checkpointed.")); + else -#endif - mutt_message (_("%d kept, %d deleted."), msgcount - deleted, - deleted); + mutt_message (_("%d kept, %d deleted."), msgcount - deleted, deleted); mutt_sleep (0); - + if (ctx->msgcount == ctx->deleted && - (ctx->magic == M_MBOX || ctx->magic == M_MMDF) && - !mutt_is_spool (ctx->path) && !option (OPTSAVEEMPTY)) - { + (ctx->magic == M_MBOX || ctx->magic == M_MMDF) && + !mutt_is_spool (ctx->path) && !option (OPTSAVEEMPTY)) { unlink (ctx->path); mx_fastclose_mailbox (ctx); return 0; @@ -1354,15 +1036,12 @@ int mx_sync_mailbox (CONTEXT *ctx, int *index_hint) * MH and maildir are safe. mbox-style seems to need re-sorting, * at least with the new threading code. */ - if (purge || (ctx->magic != M_MAILDIR && ctx->magic != M_MH)) - { -#ifdef USE_IMAP + if (purge || (ctx->magic != M_MAILDIR && ctx->magic != M_MH)) { /* IMAP does this automatically after handling EXPUNGE */ if (ctx->magic != M_IMAP) -#endif { - mx_update_tables (ctx, 1); - mutt_sort_headers (ctx, 1); /* rethread from scratch */ + mx_update_tables (ctx, 1); + mutt_sort_headers (ctx, 1); /* rethread from scratch */ } } } @@ -1370,359 +1049,198 @@ int mx_sync_mailbox (CONTEXT *ctx, int *index_hint) return (rc); } - -/* {maildir,mh}_open_new_message are in mh.c. */ - -int mbox_open_new_message (MESSAGE *msg, CONTEXT *dest, HEADER *hdr) -{ - msg->fp = dest->fp; - return 0; +int mx_sync_mailbox (CONTEXT* ctx, int* index_hint) { + int ret = _mx_sync_mailbox (ctx, index_hint); + sidebar_set_buffystats (ctx); + return (ret); } -#ifdef USE_IMAP -int imap_open_new_message (MESSAGE *msg, CONTEXT *dest, HEADER *hdr) -{ - char tmp[_POSIX_PATH_MAX]; - - mutt_mktemp(tmp); - if ((msg->fp = safe_fopen (tmp, "w")) == NULL) - return (-1); - msg->path = safe_strdup(tmp); - return 0; -} -#endif - /* args: * dest destintation mailbox * hdr message being copied (required for maildir support, because * the filename depends on the message flags) */ -MESSAGE *mx_open_new_message (CONTEXT *dest, HEADER *hdr, int flags) +MESSAGE *mx_open_new_message (CONTEXT * dest, HEADER * hdr, int flags) { MESSAGE *msg; - int (*func) (MESSAGE *, CONTEXT *, HEADER *); - ADDRESS *p = NULL; + address_t *p = NULL; - switch (dest->magic) - { - case M_MMDF: - case M_MBOX: - func = mbox_open_new_message; - break; - case M_MAILDIR: - func = maildir_open_new_message; - break; - case M_MH: - func = mh_open_new_message; - break; -#ifdef USE_IMAP - case M_IMAP: - func = imap_open_new_message; - break; -#endif - default: - dprint (1, (debugfile, "mx_open_new_message(): function unimplemented for mailbox type %d.\n", - dest->magic)); - return (NULL); + if (!MX_IDX(dest->magic-1)) { + return (NULL); } - msg = safe_calloc (1, sizeof (MESSAGE)); + msg = p_new(MESSAGE, 1); msg->magic = dest->magic; msg->write = 1; - if (hdr) - { + if (hdr) { msg->flags.flagged = hdr->flagged; msg->flags.replied = hdr->replied; - msg->flags.read = hdr->read; + msg->flags.read = hdr->read; msg->received = hdr->received; } - if(msg->received == 0) - time(&msg->received); - - if (func (msg, dest, hdr) == 0) - { + if (msg->received == 0) + time (&msg->received); + + if (MX_COMMAND(dest->magic-1,mx_open_new_message)(msg, dest, hdr) == 0) { if (dest->magic == M_MMDF) fputs (MMDF_SEP, msg->fp); - if ((msg->magic == M_MBOX || msg->magic == M_MMDF) && - flags & M_ADD_FROM) - { - if (hdr) - { - if (hdr->env->return_path) - p = hdr->env->return_path; - else if (hdr->env->sender) - p = hdr->env->sender; - else - p = hdr->env->from; + if ((msg->magic == M_MBOX || msg->magic == M_MMDF) && flags & M_ADD_FROM) { + if (hdr) { + if (hdr->env->return_path) + p = hdr->env->return_path; + else if (hdr->env->sender) + p = hdr->env->sender; + else + p = hdr->env->from; } - fprintf (msg->fp, "From %s %s", p ? p->mailbox : NONULL(Username), ctime (&msg->received)); + fprintf (msg->fp, "From %s %s", p ? p->mailbox : NONULL (Username), + ctime (&msg->received)); } } else - FREE (&msg); + p_delete(&msg); return msg; } /* check for new mail */ -int mx_check_mailbox (CONTEXT *ctx, int *index_hint, int lock) -{ - int rc; - -#ifdef USE_COMPRESSED +int mx_check_mailbox (CONTEXT * ctx, int *index_hint, int lock) { if (ctx->compressinfo) return mutt_check_mailbox_compressed (ctx); -#endif - - if (ctx) - { - if (ctx->locked) lock = 0; - switch (ctx->magic) - { - case M_MBOX: - case M_MMDF: - - if (lock) - { - mutt_block_signals (); - if (mbox_lock_mailbox (ctx, 0, 0) == -1) - { - mutt_unblock_signals (); - return M_LOCKED; - } - } - - rc = mbox_check_mailbox (ctx, index_hint); - - if (lock) - { - mutt_unblock_signals (); - mbox_unlock_mailbox (ctx); - } - - return rc; - - - case M_MH: - return (mh_check_mailbox (ctx, index_hint)); - case M_MAILDIR: - return (maildir_check_mailbox (ctx, index_hint)); - -#ifdef USE_IMAP - case M_IMAP: - return (imap_check_mailbox (ctx, index_hint, 0)); -#endif /* USE_IMAP */ - -#ifdef USE_POP - case M_POP: - return (pop_check_mailbox (ctx, index_hint)); -#endif /* USE_POP */ - -#ifdef USE_NNTP - case M_NNTP: - return (nntp_check_mailbox (ctx)); -#endif /* USE_NNTP */ - } + if (ctx) { + if (ctx->locked) + lock = 0; + if (MX_IDX(ctx->magic-1) && MX_COMMAND(ctx->magic-1,mx_check_mailbox)) + return (MX_COMMAND(ctx->magic-1,mx_check_mailbox)(ctx, index_hint, lock)); } - dprint (1, (debugfile, "mx_check_mailbox: null or invalid context.\n")); return (-1); } /* return a stream pointer for a message */ -MESSAGE *mx_open_message (CONTEXT *ctx, int msgno) +MESSAGE *mx_open_message (CONTEXT * ctx, int msgno) { MESSAGE *msg; - - msg = safe_calloc (1, sizeof (MESSAGE)); - switch (msg->magic = ctx->magic) - { - case M_MBOX: - case M_MMDF: - msg->fp = ctx->fp; - break; - case M_MH: - case M_MAILDIR: + msg = p_new(MESSAGE, 1); + switch (msg->magic = ctx->magic) { + case M_MBOX: + case M_MMDF: + msg->fp = ctx->fp; + break; + + case M_MH: + case M_MAILDIR: { HEADER *cur = ctx->hdrs[msgno]; char path[_POSIX_PATH_MAX]; - + snprintf (path, sizeof (path), "%s/%s", ctx->path, cur->path); - + if ((msg->fp = fopen (path, "r")) == NULL && errno == ENOENT && - ctx->magic == M_MAILDIR) - msg->fp = maildir_open_find_message (ctx->path, cur->path); - - if (msg->fp == NULL) - { - mutt_perror (path); - dprint (1, (debugfile, "mx_open_message: fopen: %s: %s (errno %d).\n", - path, strerror (errno), errno)); - FREE (&msg); + ctx->magic == M_MAILDIR) + msg->fp = maildir_open_find_message (ctx->path, cur->path); + + if (msg->fp == NULL) { + mutt_perror (path); + p_delete(&msg); } } break; - -#ifdef USE_IMAP - case M_IMAP: + + case M_IMAP: { if (imap_fetch_message (msg, ctx, msgno) != 0) - FREE (&msg); + p_delete(&msg); break; } -#endif /* USE_IMAP */ -#ifdef USE_POP - case M_POP: + case M_POP: { if (pop_fetch_message (msg, ctx, msgno) != 0) - FREE (&msg); + p_delete(&msg); break; } -#endif /* USE_POP */ #ifdef USE_NNTP - case M_NNTP: + case M_NNTP: { if (nntp_fetch_message (msg, ctx, msgno) != 0) - FREE (&msg); + p_delete(&msg); break; } #endif /* USE_NNTP */ - default: - dprint (1, (debugfile, "mx_open_message(): function not implemented for mailbox type %d.\n", ctx->magic)); - FREE (&msg); - break; + default: + p_delete(&msg); + break; } return (msg); } /* commit a message to a folder */ -int mx_commit_message (MESSAGE *msg, CONTEXT *ctx) -{ - int r = 0; - - if (!(msg->write && ctx->append)) - { - dprint (1, (debugfile, "mx_commit_message(): msg->write = %d, ctx->append = %d\n", - msg->write, ctx->append)); +int mx_commit_message (MESSAGE * msg, CONTEXT * ctx) { + if (!(msg->write && ctx->append)) { return -1; } - - switch (msg->magic) - { - case M_MMDF: - { - if (fputs (MMDF_SEP, msg->fp) == EOF) - r = -1; - break; - } - - case M_MBOX: - { - if (fputc ('\n', msg->fp) == EOF) - r = -1; - break; - } - -#ifdef USE_IMAP - case M_IMAP: - { - if ((r = safe_fclose (&msg->fp)) == 0) - r = imap_append_message (ctx, msg); - break; - } -#endif - - case M_MAILDIR: - { - r = maildir_commit_message (ctx, msg, NULL); - break; - } - - case M_MH: - { - r = mh_commit_message (ctx, msg, NULL); - break; - } - } - - if (r == 0 && (ctx->magic == M_MBOX || ctx->magic == M_MMDF) - && (fflush (msg->fp) == EOF || fsync (fileno (msg->fp)) == -1)) - { - mutt_perror _("Can't write message"); - r = -1; - } - - return r; + if (!ctx || !MX_IDX(ctx->magic-1) || !MX_COMMAND(ctx->magic-1,mx_commit_message)) + return (-1); + return (MX_COMMAND(ctx->magic-1,mx_commit_message) (msg, ctx)); } /* close a pointer to a message */ -int mx_close_message (MESSAGE **msg) +int mx_close_message (MESSAGE ** msg) { int r = 0; if ((*msg)->magic == M_MH || (*msg)->magic == M_MAILDIR -#ifdef USE_IMAP || (*msg)->magic == M_IMAP -#endif -#ifdef USE_POP || (*msg)->magic == M_POP -#endif #ifdef USE_NNTP || (*msg)->magic == M_NNTP #endif - ) - { + ) { r = safe_fclose (&(*msg)->fp); } else (*msg)->fp = NULL; - if ((*msg)->path) - { - dprint (1, (debugfile, "mx_close_message (): unlinking %s\n", - (*msg)->path)); + if ((*msg)->path) { unlink ((*msg)->path); - FREE (&(*msg)->path); + p_delete(&(*msg)->path); } - FREE (msg); + p_delete(msg); return (r); } -void mx_alloc_memory (CONTEXT *ctx) +void mx_alloc_memory (CONTEXT * ctx) { int i; size_t s = MAX (sizeof (HEADER *), sizeof (int)); - - if ((ctx->hdrmax + 25) * s < ctx->hdrmax * s) - { + + if ((ctx->hdrmax + 25) * s < ctx->hdrmax * s) { mutt_error _("Integer overflow -- can't allocate memory."); + sleep (1); mutt_exit (1); } - - if (ctx->hdrs) - { - safe_realloc (&ctx->hdrs, sizeof (HEADER *) * (ctx->hdrmax += 25)); - safe_realloc (&ctx->v2r, sizeof (int) * ctx->hdrmax); + + if (ctx->hdrs) { + p_realloc(&ctx->hdrs, ctx->hdrmax += 25); + p_realloc(&ctx->v2r, ctx->hdrmax); } - else - { - ctx->hdrs = safe_calloc ((ctx->hdrmax += 25), sizeof (HEADER *)); - ctx->v2r = safe_calloc (ctx->hdrmax, sizeof (int)); + else { + ctx->hdrs = p_new(HEADER *, (ctx->hdrmax += 25)); + ctx->v2r = p_new(int, ctx->hdrmax); } - for (i = ctx->msgcount ; i < ctx->hdrmax ; i++) - { + for (i = ctx->msgcount; i < ctx->hdrmax; i++) { ctx->hdrs[i] = NULL; ctx->v2r[i] = -1; } @@ -1731,23 +1249,18 @@ void mx_alloc_memory (CONTEXT *ctx) /* this routine is called to update the counts in the context structure for * the last message header parsed. */ -void mx_update_context (CONTEXT *ctx, int new_messages) +void mx_update_context (CONTEXT * ctx, int new_messages) { HEADER *h; int msgno; - for (msgno = ctx->msgcount - new_messages; msgno < ctx->msgcount; msgno++) - { + for (msgno = ctx->msgcount - new_messages; msgno < ctx->msgcount; msgno++) { h = ctx->hdrs[msgno]; - if (WithCrypto) - { - /* NOTE: this _must_ be done before the check for mailcap! */ - h->security = crypt_query (h->content); - } + /* NOTE: this _must_ be done before the check for mailcap! */ + h->security = crypt_query (h->content); - if (!ctx->pattern) - { + if (!ctx->pattern) { ctx->v2r[ctx->vcount] = msgno; h->virtual = ctx->vcount++; } @@ -1755,32 +1268,32 @@ void mx_update_context (CONTEXT *ctx, int new_messages) h->virtual = -1; h->msgno = msgno; - if (h->env->supersedes) - { + if (h->env->supersedes) { HEADER *h2; - if (!ctx->id_hash) - ctx->id_hash = mutt_make_id_hash (ctx); + if (!ctx->id_hash) + ctx->id_hash = mutt_make_id_hash (ctx); h2 = hash_find (ctx->id_hash, h->env->supersedes); - /* FREE (&h->env->supersedes); should I ? */ - if (h2) - { - h2->superseded = 1; - if (option (OPTSCORE)) - mutt_score_message (ctx, h2, 1); + /* p_delete(&h->env->supersedes); should I ? */ + if (h2) { + h2->superseded = 1; + if (!ctx->counting && option (OPTSCORE)) + mutt_score_message (ctx, h2, 1); } } /* add this message to the hash tables */ if (ctx->id_hash && h->env->message_id) hash_insert (ctx->id_hash, h->env->message_id, h, 0); - if (ctx->subj_hash && h->env->real_subj) - hash_insert (ctx->subj_hash, h->env->real_subj, h, 1); + if (!ctx->counting) { + if (ctx->subj_hash && h->env->real_subj) + hash_insert (ctx->subj_hash, h->env->real_subj, h, 1); - if (option (OPTSCORE)) - mutt_score_message (ctx, h, 0); + if (option (OPTSCORE)) + mutt_score_message (ctx, h, 0); + } if (h->changed) ctx->changed = 1; @@ -1788,13 +1301,14 @@ void mx_update_context (CONTEXT *ctx, int new_messages) ctx->flagged++; if (h->deleted) ctx->deleted++; - if (!h->read) - { + if (!h->read) { ctx->unread++; if (!h->old) - ctx->new++; + ctx->new++; } } + /* update sidebar count */ + sidebar_set_buffystats (ctx); } /* @@ -1805,18 +1319,91 @@ void mx_update_context (CONTEXT *ctx, int new_messages) */ int mx_check_empty (const char *path) { - switch (mx_get_magic (path)) - { - case M_MBOX: - case M_MMDF: - return mbox_check_empty (path); - case M_MH: - return mh_check_empty (path); - case M_MAILDIR: - return maildir_check_empty (path); - default: - errno = EINVAL; - return -1; + int i = 0; + if ((i = mx_get_idx (path)) >= 0 && MX_COMMAND(i,mx_check_empty)) + return (MX_COMMAND(i,mx_check_empty)(path)); + errno = EINVAL; + return (-1); +} + +int mx_acl_check (CONTEXT* ctx, int flag) { + if (!ctx || !MX_IDX(ctx->magic-1)) + return (0); + /* if no acl_check defined for module, assume permission is granted */ + if (!MX_COMMAND(ctx->magic-1,mx_acl_check)) + return (1); + return (MX_COMMAND(ctx->magic-1,mx_acl_check)(ctx,flag)); +} + +void mx_init (void) { + list_push_back (&MailboxFormats, (void*) mbox_reg_mx ()); + list_push_back (&MailboxFormats, (void*) mmdf_reg_mx ()); + list_push_back (&MailboxFormats, (void*) mh_reg_mx ()); + list_push_back (&MailboxFormats, (void*) maildir_reg_mx ()); + list_push_back (&MailboxFormats, (void*) imap_reg_mx ()); + list_push_back (&MailboxFormats, (void*) pop_reg_mx ()); +#ifdef USE_NNTP + list_push_back (&MailboxFormats, (void*) nntp_reg_mx ()); +#endif + list_push_back (&MailboxFormats, (void*) compress_reg_mx ()); +} + +int mx_rebuild_cache (void) { +#ifndef USE_HCACHE + mutt_error (_("Support for header caching was not build in.")); + return (1); +#else + int i = 0, magic = 0; + CONTEXT* ctx = NULL; + BUFFY* b = NULL; + + if (list_empty(Incoming)) { + mutt_error (_("No mailboxes defined.")); + return (1); + } + + for (i = 0; i < Incoming->length; i++) { + b = (BUFFY*) Incoming->data[i]; + magic = mx_get_magic (b->path); + if (magic != M_MAILDIR && magic != M_MH && magic != M_IMAP) + continue; + sidebar_set_current (b->path); + sidebar_draw (); + if ((ctx = mx_open_mailbox (b->path, + M_READONLY | M_NOSORT | M_COUNT, + NULL)) != NULL) + mx_close_mailbox (ctx, 0); } - /* not reached */ + mutt_clear_error (); + + if (Context && Context->path) + sidebar_set_current (Context->path); + sidebar_draw (); + + return (0); +#endif +} + +void mutt_parse_mime_message (CONTEXT * ctx, HEADER * cur) +{ + MESSAGE *msg; + int flags = 0; + + do { + if (cur->content->type != TYPEMESSAGE + && cur->content->type != TYPEMULTIPART) + break; /* nothing to do */ + + if (cur->content->parts) + break; /* The message was parsed earlier. */ + + if ((msg = mx_open_message (ctx, cur->msgno))) { + mutt_parse_part (msg->fp, cur->content); + + cur->security = crypt_query (cur->content); + + mx_close_message (&msg); + } + } while (0); + mutt_count_body_parts (cur, flags | M_PARTS_RECOUNT); }