organize module
[apps/madmutt.git] / lib-mx / compress.c
index 52978ac..ec4db2b 100644 (file)
@@ -12,7 +12,7 @@
 #include <lib-sys/mutt_signal.h>
 #include <lib-sys/unix.h>
 
-#include <lib-ui/curses.h>
+#include <lib-ui/lib-ui.h>
 
 #include "mutt.h"
 
@@ -38,36 +38,50 @@ static int mbox_lock_compressed (CONTEXT * ctx, FILE * fp, int excl, int retry)
 {
   int r;
 
-  if ((r = mx_lock_file (ctx->realpath, fileno (fp), excl, 1, retry)) == 0)
+  if ((r = mx_lock_file (ctx->realpath, fileno (fp), excl, retry)) == 0)
     ctx->locked = 1;
   else if (retry && !excl) {
     ctx->readonly = 1;
     return 0;
   }
 
-  return (r);
+  return r;
 }
 
 static void mbox_unlock_compressed (CONTEXT * ctx, FILE * fp)
 {
   if (ctx->locked) {
     fflush (fp);
-
-    mx_unlock_file (ctx->realpath, fileno (fp), 1);
+    mx_unlock_file(ctx->realpath, fileno(fp));
     ctx->locked = 0;
   }
 }
 
 static int is_new (const char *path)
 {
-  return (access (path, W_OK) != 0 && errno == ENOENT) ? 1 : 0;
+  return access (path, W_OK) && errno == ENOENT;
 }
 
 static const char *find_compress_hook (int type, const char *path)
 {
-  const char *c = mutt_find_hook (type, path);
-
-  return (!c || !*c) ? NULL : c;
+  int len = strlen(path);
+  if (len > 3 && !strcmp(path + len - 3, ".gz")) {
+      switch (type) {
+        case M_OPENHOOK:   return "gzip -cd %f > %t";
+        case M_CLOSEHOOK:  return "gzip -cd %t > %f";
+        case M_APPENDHOOK: return "gzip -cd %t >> %f";
+        default: return NULL;
+      }
+  }
+  if (len > 4 && !strcmp(path + len - 4, ".bz2")) {
+      switch (type) {
+        case M_OPENHOOK:   return "bzip2 -cd %f > %t";
+        case M_CLOSEHOOK:  return "bzip2 -cd %t > %f";
+        case M_APPENDHOOK: return "bzip2 -cd %t >> %f";
+        default: return NULL;
+      }
+  }
+  return NULL;
 }
 
 int mutt_can_read_compressed (const char *path)
@@ -88,7 +102,7 @@ int mutt_can_append_compressed (const char *path)
   int magic;
 
   if (is_new (path))
-    return (find_compress_hook (M_CLOSEHOOK, path) ? 1 : 0);
+    return find_compress_hook (M_CLOSEHOOK, path) ? 1 : 0;
 
   magic = mx_get_magic (path);
 
@@ -113,38 +127,26 @@ static compress_info *set_compress_info (CONTEXT * ctx)
   return (ctx->cinfo = ci);
 }
 
-static void set_path (CONTEXT * ctx)
-{
-  char tmppath[_POSIX_PATH_MAX];
-
-  /* Setup the right paths */
-  ctx->realpath = ctx->path;
-
-  /* Uncompress to /tmp */
-  mutt_mktemp (tmppath);
-  ctx->path = p_dupstr(tmppath, m_strlen(tmppath));
-}
-
 static int get_size (const char *path)
 {
   struct stat sb;
 
   if (stat (path, &sb) != 0)
     return 0;
-  return (sb.st_size);
+  return sb.st_size;
 }
 
-static const char *compresshook_format_str (char *dest, ssize_t destlen,
-                                            char op, const char *src,
-                                            const char *fmt,
-                                            const char *ifstring __attribute__ ((unused)),
-                                            const char *elsestring __attribute__ ((unused)),
-                                            unsigned long data,
-                                            format_flag flags __attribute__ ((unused)))
+static const char *
+compresshook_format_str(char *dest, ssize_t destlen,
+                        char op, const char *src, const char *fmt,
+                        const char *ifstr __attribute__ ((unused)),
+                        const char *elstr __attribute__ ((unused)),
+                        anytype data,
+                        format_flag flags __attribute__ ((unused)))
 {
   char tmp[STRING];
 
-  CONTEXT *ctx = (CONTEXT *) data;
+  CONTEXT *ctx = data.ptr;
 
   switch (op) {
   case 'f':
@@ -156,7 +158,7 @@ static const char *compresshook_format_str (char *dest, ssize_t destlen,
     snprintf (dest, destlen, tmp, ctx->path);
     break;
   }
-  return (src);
+  return src;
 }
 
 /* check that the command has both %f and %t
@@ -167,13 +169,11 @@ int mutt_test_compress_command (const char *cmd)
   return (strstr (cmd, "%f") && strstr (cmd, "%t")) ? 0 : -1;
 }
 
-static char *get_compression_cmd (const char *cmd, const CONTEXT * ctx)
+static char *get_compression_cmd(const char *cmd, const CONTEXT *ctx)
 {
-  char expanded[_POSIX_PATH_MAX];
-
-  mutt_FormatString (expanded, sizeof (expanded), cmd,
-                     compresshook_format_str, (unsigned long) ctx, 0);
-  return m_strdup(expanded);
+    char buf[_POSIX_PATH_MAX];
+    m_strformat(buf, sizeof(buf), 0, cmd, compresshook_format_str, (void*)ctx, 0);
+    return m_strdup(buf);
 }
 
 int mutt_check_mailbox_compressed (CONTEXT * ctx)
@@ -183,28 +183,43 @@ int mutt_check_mailbox_compressed (CONTEXT * ctx)
     p_delete(&ctx->realpath);
     mutt_error _("Mailbox was corrupted!");
 
-    return (-1);
+    return -1;
   }
-  return (0);
+  return 0;
 }
 
-int mutt_open_read_compressed (CONTEXT * ctx)
+int mutt_open_read_compressed(CONTEXT * ctx)
 {
   char *cmd;
   FILE *fp;
   int rc;
+  char tmppath[_POSIX_PATH_MAX];
+  int tmpfd;
 
   compress_info *ci = set_compress_info (ctx);
 
   if (!ci->open) {
     ctx->magic = 0;
     p_delete(&ctx->cinfo);
-    return (-1);
+    return -1;
   }
   if (!ci->close || access (ctx->path, W_OK) != 0)
     ctx->readonly = 1;
 
-  set_path (ctx);
+  /* Setup the right paths */
+  ctx->realpath = ctx->path;
+
+  /* Uncompress to /tmp */
+  tmpfd = m_tempfd(tmppath, sizeof(tmppath), NONULL(mod_core.tmpdir), NULL);
+  /* If we cannot open tempfile, that means the file already exists (!?)
+   * or we are following a symlink, which is bad and insecure.
+   */
+  if(tmpfd < 0) {
+      return -1;
+  }
+  close(tmpfd);
+
+  ctx->path = p_dupstr(tmppath, m_strlen(tmppath));
   ctx->cinfo->size = get_size(ctx->realpath);
 
   if (!ctx->quiet)
@@ -212,12 +227,12 @@ int mutt_open_read_compressed (CONTEXT * ctx)
 
   cmd = get_compression_cmd (ci->open, ctx);
   if (cmd == NULL)
-    return (-1);
+    return -1;
 
   if ((fp = fopen (ctx->realpath, "r")) == NULL) {
     mutt_perror (ctx->realpath);
     p_delete(&cmd);
-    return (-1);
+    return -1;
   }
   mutt_block_signals ();
   if (mbox_lock_compressed (ctx, fp, 0, 1) == -1) {
@@ -226,7 +241,7 @@ int mutt_open_read_compressed (CONTEXT * ctx)
     mutt_error _("Unable to lock mailbox!");
 
     p_delete(&cmd);
-    return (-1);
+    return -1;
   }
 
   endwin ();
@@ -246,14 +261,14 @@ int mutt_open_read_compressed (CONTEXT * ctx)
   }
   p_delete(&cmd);
   if (rc)
-    return (-1);
+    return -1;
 
   if (mutt_check_mailbox_compressed (ctx))
-    return (-1);
+    return -1;
 
   ctx->magic = mx_get_magic (ctx->path);
 
-  return (0);
+  return 0;
 }
 
 static void restore_path (CONTEXT * ctx)
@@ -265,7 +280,7 @@ static void restore_path (CONTEXT * ctx)
 /* remove the temporary mailbox */
 static void remove_file (CONTEXT * ctx)
 {
-  if (ctx->magic == M_MBOX || ctx->magic == M_MMDF)
+  if (ctx->magic == M_MBOX)
     remove (ctx->path);
 }
 
@@ -273,27 +288,31 @@ int mutt_open_append_compressed (CONTEXT * ctx)
 {
   FILE *fh;
   compress_info *ci = set_compress_info (ctx);
+  char tmppath[_POSIX_PATH_MAX];
 
   if (!get_append_command (ctx->path, ctx)) {
     if (ci->open && ci->close)
-      return (mutt_open_read_compressed (ctx));
+      return mutt_open_read_compressed(ctx);
 
     ctx->magic = 0;
     p_delete(&ctx->cinfo);
-    return (-1);
+    return -1;
   }
 
-  set_path (ctx);
+  /* Setup the right paths */
+  ctx->realpath = ctx->path;
 
-  ctx->magic = DefaultMagic;
+  /* Uncompress to /tmp */
+  fh = m_tempfile(tmppath, sizeof(tmppath), NONULL(mod_core.tmpdir), NULL);
+  m_fclose(&fh);
 
-  if (!is_new (ctx->realpath))
-    if (ctx->magic == M_MBOX || ctx->magic == M_MMDF)
-      if ((fh = safe_fopen (ctx->path, "w")))
-        m_fclose(&fh);
-  /* No error checking - the parent function will catch it */
+  ctx->path = p_dupstr(tmppath, m_strlen(tmppath));
+  ctx->magic = M_MBOX;
+  if (is_new (ctx->realpath) || ctx->magic != M_MBOX)
+      unlink(tmppath);
 
-  return (0);
+  /* No error checking - the parent function will catch it */
+  return 0;
 }
 
 /* close a compressed mailbox */
@@ -303,11 +322,7 @@ void mutt_fast_close_compressed (CONTEXT * ctx)
     m_fclose(&ctx->fp);
 
     /* if the folder was removed, remove the gzipped folder too */
-    if (access (ctx->path, F_OK) != 0 && !option (OPTSAVEEMPTY))
-      remove (ctx->realpath);
-    else
-      remove_file (ctx);
-
+    remove_file (ctx);
     restore_path (ctx);
     p_delete(&ctx->cinfo);
   }
@@ -325,12 +340,12 @@ int mutt_sync_compressed (CONTEXT * ctx)
 
   cmd = get_compression_cmd (ctx->cinfo->close, ctx);
   if (cmd == NULL)
-    return (-1);
+    return -1;
 
   if ((fp = fopen (ctx->realpath, "a")) == NULL) {
     mutt_perror (ctx->realpath);
     p_delete(&cmd);
-    return (-1);
+    return -1;
   }
   mutt_block_signals ();
   if (mbox_lock_compressed (ctx, fp, 1, 1) == -1) {
@@ -341,7 +356,7 @@ int mutt_sync_compressed (CONTEXT * ctx)
     ctx->cinfo->size = get_size(ctx->realpath);
 
     p_delete(&cmd);
-    return (-1);
+    return -1;
   }
 
   endwin ();
@@ -364,7 +379,7 @@ int mutt_sync_compressed (CONTEXT * ctx)
 
   ctx->cinfo->size = get_size(ctx->realpath);
 
-  return (rc);
+  return rc;
 }
 
 int mutt_slow_close_compressed (CONTEXT * ctx)
@@ -379,7 +394,7 @@ int mutt_slow_close_compressed (CONTEXT * ctx)
       /* if we can not or should not append, we only have to remove the
          compressed info, because sync was already called */
     mutt_fast_close_compressed (ctx);
-    return (0);
+    return 0;
   }
 
   m_fclose(&ctx->fp);
@@ -393,12 +408,12 @@ int mutt_slow_close_compressed (CONTEXT * ctx)
 
   cmd = get_compression_cmd (append, ctx);
   if (cmd == NULL)
-    return (-1);
+    return -1;
 
   if ((fp = fopen (ctx->realpath, "a")) == NULL) {
     mutt_perror (ctx->realpath);
     p_delete(&cmd);
-    return (-1);
+    return -1;
   }
   mutt_block_signals ();
   if (mbox_lock_compressed (ctx, fp, 1, 1) == -1) {
@@ -407,7 +422,7 @@ int mutt_slow_close_compressed (CONTEXT * ctx)
     mutt_error _("Unable to lock mailbox!");
 
     p_delete(&cmd);
-    return (-1);
+    return -1;
   }
 
   endwin ();
@@ -428,7 +443,7 @@ int mutt_slow_close_compressed (CONTEXT * ctx)
     mbox_unlock_compressed (ctx, fp);
     mutt_unblock_signals ();
     m_fclose(&fp);
-    return (-1);
+    return -1;
   }
 
   mbox_unlock_compressed (ctx, fp);
@@ -439,7 +454,7 @@ int mutt_slow_close_compressed (CONTEXT * ctx)
   p_delete(&cmd);
   p_delete(&ctx->cinfo);
 
-  return (0);
+  return 0;
 }
 
 mx_t const compress_mx = {
@@ -455,4 +470,5 @@ mx_t const compress_mx = {
     NULL,
     NULL,
     NULL,
+    NULL,
 };