changeset: 6880:2c1d79d3edd5 user: TAKAHASHI Tamotsu <tta...@lapis.plala.or.jp> date: Wed Sep 07 20:00:04 2016 -0700 link: http://dev.mutt.org/hg/mutt/rev/2c1d79d3edd5
Fix openssl 1.1 compilation issues. (closes #3870) With these changes, Mutt will no longer compile for versions less than 0.9.6. changeset: 6881:10c4761cea89 user: Kevin McCarthy <ke...@8t8.us> date: Sat Nov 19 19:35:07 2016 -0800 link: http://dev.mutt.org/hg/mutt/rev/10c4761cea89 More openssl1.1 fixes: remove uses of X509->name in debugging. (closes #3870) X509->name was a shortcut for the longer name = X509_NAME_oneline (X509_get_subject_name (cert), buf, sizeof (buf)); invocation. Change the debugging to print the cert name and chain names in the ssl_check_certificate() loop instead. changeset: 6882:a0a970530a8b user: Vincent Lefevre <vinc...@vinc17.net> date: Sat Nov 26 00:57:42 2016 +0100 link: http://dev.mutt.org/hg/mutt/rev/a0a970530a8b Fix build failure with GPGME 1.8: do not steal the gpgme_ prefix. changeset: 6883:a17189b58284 user: Kevin McCarthy <ke...@8t8.us> date: Sun Dec 04 15:41:33 2016 -0800 link: http://dev.mutt.org/hg/mutt/rev/a17189b58284 merge stable diffs (truncated from 9681 to 950 lines): diff -r c6704c7f8e23 -r a17189b58284 INSTALL --- a/INSTALL Sun Oct 23 14:46:37 2016 -0700 +++ b/INSTALL Sun Dec 04 15:41:33 2016 -0800 @@ -29,7 +29,7 @@ - If you are building from Mercurial, or if you are changing parts of mutt, particularly the build system, do read doc/devel-notes.txt. -- An ANSI C compiler (such as GCC) is required. +- A C99 compiler (such as GCC) is required. - You must also have a SysV compatible curses library, or you must install either diff -r c6704c7f8e23 -r a17189b58284 Makefile.am --- a/Makefile.am Sun Oct 23 14:46:37 2016 -0700 +++ b/Makefile.am Sun Dec 04 15:41:33 2016 -0800 @@ -5,12 +5,16 @@ AUTOMAKE_OPTIONS = 1.6 foreign EXTRA_PROGRAMS = mutt_dotlock pgpring pgpewrap mutt_md5 +if BUILD_DOC +DOC_SUBDIR = doc +endif + if BUILD_IMAP IMAP_SUBDIR = imap IMAP_INCLUDES = -I$(top_srcdir)/imap endif -SUBDIRS = m4 po intl doc contrib $(IMAP_SUBDIR) +SUBDIRS = m4 po intl $(DOC_SUBDIR) contrib $(IMAP_SUBDIR) bin_SCRIPTS = muttbug flea $(SMIMEAUX_TARGET) @@ -50,7 +54,7 @@ AM_CPPFLAGS=-I. -I$(top_srcdir) $(IMAP_INCLUDES) $(GPGME_CFLAGS) -Iintl -EXTRA_mutt_SOURCES = account.c bcache.c crypt-gpgme.c crypt-mod-pgp-classic.c \ +EXTRA_mutt_SOURCES = account.c bcache.c compress.c crypt-gpgme.c crypt-mod-pgp-classic.c \ crypt-mod-pgp-gpgme.c crypt-mod-smime-classic.c \ crypt-mod-smime-gpgme.c dotlock.c gnupgparse.c hcache.c md5.c \ mutt_idna.c mutt_sasl.c mutt_socket.c mutt_ssl.c mutt_ssl_gnutls.c \ @@ -61,7 +65,7 @@ EXTRA_DIST = COPYRIGHT GPL OPS OPS.PGP OPS.CRYPT OPS.SMIME TODO UPDATING \ configure account.h \ - attach.h buffy.h charset.h copy.h crypthash.h dotlock.h functions.h gen_defs \ + attach.h buffy.h charset.h compress.h copy.h crypthash.h dotlock.h functions.h gen_defs \ globals.h hash.h history.h init.h keymap.h mutt_crypt.h \ mailbox.h mapping.h md5.h mime.h mutt.h mutt_curses.h mutt_menu.h \ mutt_regex.h mutt_sasl.h mutt_socket.h mutt_ssl.h mutt_tunnel.h \ diff -r c6704c7f8e23 -r a17189b58284 OPS --- a/OPS Sun Oct 23 14:46:37 2016 -0700 +++ b/OPS Sun Dec 04 15:41:33 2016 -0800 @@ -36,6 +36,7 @@ OP_COMPOSE_NEW_MIME "compose new attachment using mailcap entry" OP_COMPOSE_TOGGLE_RECODE "toggle recoding of this attachment" OP_COMPOSE_POSTPONE_MESSAGE "save this message to send later" +OP_COMPOSE_RENAME_ATTACHMENT "send attachment with a different name" OP_COMPOSE_RENAME_FILE "rename/move an attached file" OP_COMPOSE_SEND_MESSAGE "send the message" OP_COMPOSE_TOGGLE_DISPOSITION "toggle disposition between inline/attachment" @@ -124,11 +125,13 @@ OP_MAIN_PREV_UNREAD "jump to the previous unread message" OP_MAIN_READ_THREAD "mark the current thread as read" OP_MAIN_READ_SUBTHREAD "mark the current subthread as read" +OP_MAIN_ROOT_MESSAGE "jump to root message in thread" OP_MAIN_SET_FLAG "set a status flag on a message" OP_MAIN_SYNC_FOLDER "save changes to mailbox" OP_MAIN_TAG_PATTERN "tag messages matching a pattern" OP_MAIN_UNDELETE_PATTERN "undelete messages matching a pattern" OP_MAIN_UNTAG_PATTERN "untag messages matching a pattern" +OP_MARK_MSG "create a hotkey macro for the current message" OP_MIDDLE_PAGE "move to the middle of the page" OP_NEXT_ENTRY "move to the next entry" OP_NEXT_LINE "scroll down one line" diff -r c6704c7f8e23 -r a17189b58284 attach.c --- a/attach.c Sun Oct 23 14:46:37 2016 -0700 +++ b/attach.c Sun Dec 04 15:41:33 2016 -0800 @@ -620,6 +620,8 @@ STATE s; memset (&s, 0, sizeof (STATE)); + /* perform charset conversion on text attachments when piping */ + s.flags = MUTT_CHARCONV; if (outfile && *outfile) thepid = mutt_create_filter_fd (path, &s.fpout, NULL, NULL, -1, out, -1); diff -r c6704c7f8e23 -r a17189b58284 browser.c --- a/browser.c Sun Oct 23 14:46:37 2016 -0700 +++ b/browser.c Sun Dec 04 15:41:33 2016 -0800 @@ -176,11 +176,12 @@ tnow = time (NULL); t_fmt = tnow - folder->ff->mtime < 31536000 ? "%b %d %H:%M" : "%b %d %Y"; } - if (do_locales) - setlocale(LC_TIME, NONULL (Locale)); /* use environment if $locale is not set */ - else - setlocale(LC_TIME, "C"); - strftime (date, sizeof (date), t_fmt, localtime (&folder->ff->mtime)); + + if (!do_locales) + setlocale (LC_TIME, "C"); + strftime (date, sizeof (date), t_fmt, localtime (&folder->ff->mtime)); + if (!do_locales) + setlocale (LC_TIME, ""); mutt_format_s (dest, destlen, fmt, date); } diff -r c6704c7f8e23 -r a17189b58284 compose.c --- a/compose.c Sun Oct 23 14:46:37 2016 -0700 +++ b/compose.c Sun Dec 04 15:41:33 2016 -0800 @@ -1019,7 +1019,32 @@ /* No send2hook since this doesn't change the message. */ break; - + + case OP_COMPOSE_RENAME_ATTACHMENT: + { + char *src; + int ret; + + CHECK_COUNT; + if (idx[menu->current]->content->d_filename) + src = idx[menu->current]->content->d_filename; + else + src = idx[menu->current]->content->filename; + strfcpy (fname, mutt_basename (NONULL (src)), sizeof (fname)); + ret = mutt_get_field (_("Send attachment with name: "), + fname, sizeof (fname), MUTT_FILE); + if (ret == 0) + { + /* + * As opposed to RENAME_FILE, we don't check fname[0] because it's + * valid to set an empty string here, to erase what was set + */ + mutt_str_replace (&idx[menu->current]->content->d_filename, fname); + menu->redraw = REDRAW_CURRENT; + } + } + break; + case OP_COMPOSE_RENAME_FILE: CHECK_COUNT; strfcpy (fname, idx[menu->current]->content->filename, sizeof (fname)); diff -r c6704c7f8e23 -r a17189b58284 compress.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/compress.c Sun Dec 04 15:41:33 2016 -0800 @@ -0,0 +1,961 @@ +/* Copyright (C) 1997 Alain Penders <al...@finale-dev.com> + * Copyright (C) 2016 Richard Russon <r...@flatcap.org> + * + * 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. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "mutt.h" +#include "mailbox.h" +#include "mutt_curses.h" +#include "mx.h" +#include "compress.h" + +/* Notes: + * Any references to compressed files also apply to encrypted files. + * ctx->path == plaintext file + * ctx->realpath == compressed file + */ + +/** + * struct COMPRESS_INFO - Private data for compress + * + * This object gets attached to the mailbox's CONTEXT. + */ +typedef struct +{ + const char *append; /* append-hook command */ + const char *close; /* close-hook command */ + const char *open; /* open-hook command */ + off_t size; /* size of the compressed file */ + struct mx_ops *child_ops; /* callbacks of de-compressed file */ + int locked; /* if realpath is locked */ + FILE *lockfp; /* fp used for locking */ +} COMPRESS_INFO; + + +/** + * lock_realpath - Try to lock the ctx->realpath + * @ctx: Mailbox to lock + * @excl: Lock exclusively? + * + * Try to (exclusively) lock the mailbox. If we succeed, then we mark the + * mailbox as locked. If we fail, but we didn't want exclusive rights, then + * the mailbox will be marked readonly. + * + * Returns: + * 1: Success (locked or readonly) + * 0: Error (can't lock the file) + */ +static int +lock_realpath (CONTEXT *ctx, int excl) +{ + if (!ctx) + return 0; + + COMPRESS_INFO *ci = ctx->compress_info; + if (!ci) + return 0; + + if (ci->locked) + return 1; + + if (excl) + ci->lockfp = fopen (ctx->realpath, "a"); + else + ci->lockfp = fopen (ctx->realpath, "r"); + if (!ci->lockfp) + { + mutt_perror (ctx->realpath); + return 0; + } + + int r = mx_lock_file (ctx->realpath, fileno (ci->lockfp), excl, 1, 1); + + if (r == 0) + ci->locked = 1; + else if (excl == 0) + { + safe_fclose (&ci->lockfp); + ctx->readonly = 1; + return 1; + } + + return (r == 0); +} + +/** + * unlock_realpath - Unlock the ctx->realpath + * @ctx: Mailbox to unlock + * + * Unlock a mailbox previously locked by lock_mailbox(). + */ +static void +unlock_realpath (CONTEXT *ctx) +{ + if (!ctx) + return; + + COMPRESS_INFO *ci = ctx->compress_info; + if (!ci) + return; + + if (!ci->locked) + return; + + mx_unlock_file (ctx->realpath, fileno (ci->lockfp), 1); + + ci->locked = 0; + safe_fclose (&ci->lockfp); +} + +/** + * setup_paths - Set the mailbox paths + * @ctx: Mailbox to modify + * + * Save the compressed filename in ctx->realpath. + * Create a temporary filename and put its name in ctx->path. + * The temporary file is created to prevent symlink attacks. + * + * Returns: + * 0: Success + * -1: Error + */ +static int +setup_paths (CONTEXT *ctx) +{ + if (!ctx) + return -1; + + char tmppath[_POSIX_PATH_MAX]; + FILE *tmpfp; + + /* Setup the right paths */ + FREE(&ctx->realpath); + ctx->realpath = ctx->path; + + /* We will uncompress to /tmp */ + mutt_mktemp (tmppath, sizeof (tmppath)); + ctx->path = safe_strdup (tmppath); + + if ((tmpfp = safe_fopen (ctx->path, "w")) == NULL) + return -1; + + safe_fclose (&tmpfp); + return 0; +} + +/** + * get_size - Get the size of a file + * @path: File to measure + * + * Returns: + * number: Size in bytes + * 0: On error + */ +static int +get_size (const char *path) +{ + if (!path) + return 0; + + struct stat sb; + if (stat (path, &sb) != 0) + return 0; + + return sb.st_size; +} + +/** + * store_size - Save the size of the compressed file + * @ctx: Mailbox + * + * Save the compressed file size in the compress_info struct. + */ +static void +store_size (const CONTEXT *ctx) +{ + if (!ctx) + return; + + COMPRESS_INFO *ci = ctx->compress_info; + if (!ci) + return; + + ci->size = get_size (ctx->realpath); +} + +/** + * find_hook - Find a hook to match a path + * @type: Type of hook, e.g. MUTT_CLOSEHOOK + * @path: Filename to test + * + * Each hook has a type and a pattern. + * Find a command that matches the type and path supplied. e.g. + * + * User config: + * open-hook '\.gz$' "gzip -cd '%f' > '%t'" + * + * Call: + * find_hook (MUTT_OPENHOOK, "myfile.gz"); + * + * Returns: + * string: Matching hook command + * NULL: No matches + */ +static const char * +find_hook (int type, const char *path) +{ + if (!path) + return NULL; + + const char *c = mutt_find_hook (type, path); + if (!c || !*c) + return NULL; + + return c; +} + +/** + * set_compress_info - Find the compress hooks for a mailbox + * @ctx: Mailbox to examine + * + * When a mailbox is opened, we check if there are any matching hooks. + * + * Returns: + * COMPRESS_INFO: Hook info for the mailbox's path + * NULL: On error + */ +static COMPRESS_INFO * +set_compress_info (CONTEXT *ctx) +{ + if (!ctx || !ctx->path) + return NULL; + + if (ctx->compress_info) + return ctx->compress_info; + + /* Open is compulsory */ + const char *o = find_hook (MUTT_OPENHOOK, ctx->path); + if (!o) + return NULL; + + const char *c = find_hook (MUTT_CLOSEHOOK, ctx->path); + const char *a = find_hook (MUTT_APPENDHOOK, ctx->path); + + COMPRESS_INFO *ci = safe_calloc (1, sizeof (COMPRESS_INFO)); + ctx->compress_info = ci; + + ci->open = safe_strdup (o); + ci->close = safe_strdup (c); + ci->append = safe_strdup (a); + + return ci; +} + +/** + * mutt_free_compress_info - Frees the compress info members and structure. + * @ctx: Mailbox to free compress_info for. + */ +void +mutt_free_compress_info (CONTEXT *ctx) +{ + COMPRESS_INFO *ci; + + if (!ctx || !ctx->compress_info) + return; + + ci = ctx->compress_info; + FREE (&ci->open); + FREE (&ci->close); + FREE (&ci->append); + + unlock_realpath (ctx); + + FREE (&ctx->compress_info); +} + +/** + * escape_path - Escapes single quotes in a path for a command string. + * @src - the path to escape. + * + * Returns: a pointer to the escaped string. + */ +static char * +escape_path (char *src) +{ + static char dest[HUGE_STRING]; + char *destp = dest; + int destsize = 0; + + if (!src) + return NULL; + + while (*src && (destsize < sizeof(dest) - 1)) + { + if (*src != '\'') + { + *destp++ = *src++; + destsize++; + } + else + { + /* convert ' into '\'' */ + if (destsize + 4 < sizeof(dest)) + { + *destp++ = *src++; + *destp++ = '\\'; + *destp++ = '\''; + *destp++ = '\''; + destsize += 4; + } + else + break; + } + } + *destp = '\0'; + + return dest; +} + +/** + * cb_format_str - Expand the filenames in the command string + * @dest: Buffer in which to save string + * @destlen: Buffer length + * @col: Starting column, UNUSED + * @cols: Number of screen columns, UNUSED + * @op: printf-like operator, e.g. 't' + * @src: printf-like format string + * @fmt: Field formatting string, UNUSED + * @ifstring: If condition is met, display this string, UNUSED + * @elsestring: Otherwise, display this string, UNUSED + * @data: Pointer to the mailbox CONTEXT + * @flags: Format flags, UNUSED + * + * cb_format_str is a callback function for mutt_FormatString. It understands + * two operators. '%f' : 'from' filename, '%t' : 'to' filename. + * + * Returns: src (unchanged) + */ +static const char * +cb_format_str (char *dest, size_t destlen, size_t col, int cols, char op, const char *src, + const char *fmt, const char *ifstring, const char *elsestring, + unsigned long data, format_flag flags) +{ + if (!dest || (data == 0)) + return src; + + CONTEXT *ctx = (CONTEXT *) data; + + switch (op) + { + case 'f': + /* Compressed file */ + snprintf (dest, destlen, "%s", NONULL (escape_path (ctx->realpath))); + break; + case 't': + /* Plaintext, temporary file */ + snprintf (dest, destlen, "%s", NONULL (escape_path (ctx->path))); + break; + } + return src; +} + +/** + * expand_command_str - Expand placeholders in command string + * @ctx: Mailbox for paths + * @buf: Buffer to store the command + * @buflen: Size of the buffer + * + * This function takes a hook command and expands the filename placeholders + * within it. The function calls mutt_FormatString() to do the replacement + * which calls our callback function cb_format_str(). e.g. + * + * Template command: + * gzip -cd '%f' > '%t' + * + * Result: + * gzip -dc '~/mail/abc.gz' > '/tmp/xyz' + */ +static void +expand_command_str (const CONTEXT *ctx, const char *cmd, char *buf, int buflen) +{ + if (!ctx || !cmd || !buf) + return; + + mutt_FormatString (buf, buflen, 0, buflen, cmd, cb_format_str, (unsigned long) ctx, 0); +} + +/** + * execute_command - Run a system command + * @ctx: Mailbox to work with + * @command: Command string to execute + * @progress: Message to show the user + * + * Run the supplied command, taking care of all the Mutt requirements, + * such as locking files and blocking signals. + * + * Returns: + * 1: Success + * 0: Failure + */ +static int +execute_command (CONTEXT *ctx, const char *command, const char *progress) +{ + int rc = 1; + char sys_cmd[HUGE_STRING]; + + if (!ctx || !command || !progress) + return 0; + + if (!ctx->quiet) + mutt_message (progress, ctx->realpath); + + mutt_block_signals(); + endwin(); + fflush (stdout); + + expand_command_str (ctx, command, sys_cmd, sizeof (sys_cmd)); + + if (mutt_system (sys_cmd) != 0) + { + rc = 0; + mutt_any_key_to_continue (NULL); + mutt_error (_("Error running \"%s\"!"), sys_cmd); + } + + mutt_unblock_signals(); + + return rc; +} + +/** + * open_mailbox - Open a compressed mailbox + * @ctx: Mailbox to open + * + * Set up a compressed mailbox to be read. + * Decompress the mailbox and set up the paths and hooks needed. + * Then determine the type of the mailbox so we can delegate the handling of + * messages. + */ +static int +open_mailbox (CONTEXT *ctx) +{ + if (!ctx || (ctx->magic != MUTT_COMPRESSED)) + return -1; + + COMPRESS_INFO *ci = set_compress_info (ctx); + if (!ci) + return -1; + + /* If there's no close-hook, or the file isn't writable */ + if (!ci->close || (access (ctx->path, W_OK) != 0)) + ctx->readonly = 1; + + if (setup_paths (ctx) != 0) + goto or_fail; + store_size (ctx); + + if (!lock_realpath (ctx, 0)) + { + mutt_error (_("Unable to lock mailbox!")); + goto or_fail; + } + + int rc = execute_command (ctx, ci->open, _("Decompressing %s")); + if (rc == 0) + goto or_fail; + + unlock_realpath (ctx); + + ctx->magic = mx_get_magic (ctx->path); + if (ctx->magic == 0) + { + mutt_error (_("Can't identify the contents of the compressed file")); + goto or_fail; + } + + ci->child_ops = mx_get_ops (ctx->magic); + if (!ci->child_ops) + { + mutt_error (_("Can't find mailbox ops for mailbox type %d"), ctx->magic); + goto or_fail; + } + + return ci->child_ops->open (ctx); + +or_fail: + /* remove the partial uncompressed file */ + remove (ctx->path); + mutt_free_compress_info (ctx); + return -1; +} + +/** + * open_append_mailbox - Open a compressed mailbox for appending + * @ctx: Mailbox to open + * @flags: e.g. Does the file already exist? + * + * To append to a compressed mailbox we need an append-hook (or both open- and + * close-hooks). + * + * Returns: + * 0: Success + * -1: Failure + */ +static int +open_append_mailbox (CONTEXT *ctx, int flags) +{ + if (!ctx) + return -1; + + /* If this succeeds, we know there's an open-hook */ + COMPRESS_INFO *ci = set_compress_info (ctx); + if (!ci) + return -1; + + /* To append we need an append-hook or a close-hook */ + if (!ci->append && !ci->close) + { + mutt_error (_("Cannot append without an append-hook or close-hook : %s"), ctx->path); + goto oa_fail1; + } + + if (setup_paths (ctx) != 0) + goto oa_fail2; + + /* Lock the realpath for the duration of the append. + * It will be unlocked in the close */ + if (!lock_realpath (ctx, 1)) + { + mutt_error (_("Unable to lock mailbox!")); + goto oa_fail2; + } + + /* Open the existing mailbox, unless we are appending */ + if (!ci->append && (get_size (ctx->realpath) > 0)) + { + int rc = execute_command (ctx, ci->open, _("Decompressing %s")); + if (rc == 0) + { + mutt_error (_("Compress command failed: %s"), ci->open); + goto oa_fail2; + } + ctx->magic = mx_get_magic (ctx->path); + } + else + ctx->magic = DefaultMagic; + + /* We can only deal with mbox and mmdf mailboxes */ + if ((ctx->magic != MUTT_MBOX) && (ctx->magic != MUTT_MMDF)) + { + mutt_error (_("Unsupported mailbox type for appending.")); + goto oa_fail2; + } + + ci->child_ops = mx_get_ops (ctx->magic); + if (!ci->child_ops) + { + mutt_error (_("Can't find mailbox ops for mailbox type %d"), ctx->magic); + goto oa_fail2; + } + + if (ci->child_ops->open_append (ctx, flags) != 0) + goto oa_fail2; + + return 0; + +oa_fail2: + /* remove the partial uncompressed file */ + remove (ctx->path); +oa_fail1: + /* Free the compress_info to prevent close from trying to recompress */ + mutt_free_compress_info (ctx); + + return -1; +} + +/** + * close_mailbox - Close a compressed mailbox + * @ctx: Mailbox to close + * + * If the mailbox has been changed then re-compress the tmp file. + * Then delete the tmp file. + * + * Returns: + * 0: Success + * -1: Failure + */ +static int +close_mailbox (CONTEXT *ctx) +{ + if (!ctx) + return -1; + + COMPRESS_INFO *ci = ctx->compress_info; + if (!ci) + return -1; + + struct mx_ops *ops = ci->child_ops; + if (!ops) + return -1; + + ops->close (ctx); + + /* sync has already been called, so we only need to delete some files */ + if (!ctx->append) + { + /* If the file was removed, remove the compressed folder too */ + if ((access (ctx->path, F_OK) != 0) && !option (OPTSAVEEMPTY)) + { + remove (ctx->realpath); + } + else + { + remove (ctx->path); + } + + return 0; + } + + const char *append; + const char *msg; + + /* The file exists and we can append */ + if ((access (ctx->realpath, F_OK) == 0) && ci->append) + { + append = ci->append; + msg = _("Compressed-appending to %s..."); + } + else + { + append = ci->close; + msg = _("Compressing %s..."); + } + + int rc = execute_command (ctx, append, msg); + if (rc == 0) + { + mutt_any_key_to_continue (NULL); + mutt_error (_("Error. Preserving temporary file: %s"), ctx->path); + } + else + remove (ctx->path); + + unlock_realpath (ctx); + + return 0; +} + +/** + * check_mailbox - Check for changes in the compressed file + * @ctx: Mailbox + * + * If the compressed file changes in size but the mailbox hasn't been changed + * in Mutt, then we can close and reopen the mailbox. + * + * If the mailbox has been changed in Mutt, warn the user. + * + * The return codes are picked to match mx_check_mailbox(). + * + * Returns: + * 0: Mailbox OK + * MUTT_REOPENED: The mailbox was closed and reopened + * -1: Mailbox bad + */ +static int +check_mailbox (CONTEXT *ctx, int *index_hint) +{ + if (!ctx) + return -1; + + COMPRESS_INFO *ci = ctx->compress_info; + if (!ci) + return -1; + + struct mx_ops *ops = ci->child_ops; + if (!ops) + return -1; + + int size = get_size (ctx->realpath); + if (size == ci->size) + return 0; + + if (!lock_realpath (ctx, 0)) + { + mutt_error (_("Unable to lock mailbox!")); + return -1; + } + + int rc = execute_command (ctx, ci->open, _("Decompressing %s")); + store_size (ctx); + unlock_realpath (ctx); + if (rc == 0) + return -1; + + return ops->check (ctx, index_hint); +} + + +/** + * open_message - Delegated to mbox handler + */ +static int +open_message (CONTEXT *ctx, MESSAGE *msg, int msgno) +{ + if (!ctx) + return -1; + + COMPRESS_INFO *ci = ctx->compress_info; + if (!ci) + return -1; + + struct mx_ops *ops = ci->child_ops; + if (!ops) + return -1; + + /* Delegate */ + return ops->open_msg (ctx, msg, msgno); +} + +/** + * close_message - Delegated to mbox handler + */ +static int +close_message (CONTEXT *ctx, MESSAGE *msg) +{ + if (!ctx) + return -1; + + COMPRESS_INFO *ci = ctx->compress_info; + if (!ci) + return -1; + + struct mx_ops *ops = ci->child_ops; + if (!ops) + return -1; + + /* Delegate */ + return ops->close_msg (ctx, msg); +} + +/** + * commit_message - Delegated to mbox handler + */ +static int +commit_message (CONTEXT *ctx, MESSAGE *msg) +{ + if (!ctx) + return -1; + + COMPRESS_INFO *ci = ctx->compress_info; + if (!ci) + return -1; + + struct mx_ops *ops = ci->child_ops; + if (!ops) + return -1; + + /* Delegate */ + return ops->commit_msg (ctx, msg); +} + +/** + * open_new_message - Delegated to mbox handler + */ +static int +open_new_message (MESSAGE *msg, CONTEXT *ctx, HEADER *hdr) +{ + if (!ctx) + return -1; + + COMPRESS_INFO *ci = ctx->compress_info; + if (!ci) + return -1; + + struct mx_ops *ops = ci->child_ops; + if (!ops) + return -1; + + /* Delegate */