Rocco Rutte:
[apps/madmutt.git] / mx.c
diff --git a/mx.c b/mx.c
index d4c0bcc..fc2a908 100644 (file)
--- a/mx.c
+++ b/mx.c
 #endif
 
 #include "mutt.h"
+#include "ascii.h"
 #include "mx.h"
 #include "mbox.h"
 #include "mh.h"
 #include "rfc2047.h"
 #include "sort.h"
+#include "thread.h"
 #include "copy.h"
 #include "keymap.h"
 #include "url.h"
+#include "sidebar.h"
 
 #ifdef USE_COMPRESSED
 #include "compress.h"
@@ -55,6 +58,7 @@
 #include "lib/intl.h"
 #include "lib/str.h"
 #include "lib/list.h"
+#include "lib/debug.h"
 
 #include <dirent.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#ifndef BUFFY_SIZE
 #include <utime.h>
-#endif
 
 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)  (safe_strcmp (Spoolfile, s) == 0)
+#define mutt_is_spool(s)  (str_cmp (Spoolfile, s) == 0)
 
 #ifdef USE_DOTLOCK
 /* parameters: 
@@ -152,11 +155,24 @@ static int undotlock_file (const char *path, int fd)
 /* 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++) {
-    t = MX_COMMAND(i,mx_is_magic)(path);
+    if (!MX_COMMAND(i,local))
+      t = MX_COMMAND(i,mx_is_magic)(path, NULL);
     if (t >= 1)
-      return (t-1);     /* use type as index for array */
+      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);
 }
@@ -188,7 +204,7 @@ int mx_lock_file (const char *path, int fd, int excl, int dot, int timeout)
   while (fcntl (fd, F_SETLK, &lck) == -1) {
     struct stat sb;
 
-    dprint (1, (debugfile, "mx_lock_file(): fcntl errno %d.\n", errno));
+    debug_print (1, ("fcntl errno %d.\n", errno));
     if (errno != EAGAIN && errno != EACCES) {
       mutt_perror ("fcntl");
       return (-1);
@@ -328,13 +344,19 @@ void mx_unlink_empty (const char *path)
 int mx_get_magic (const char *path) {
   int i = 0;
 
-  if (safe_strlen (path) == 0)
+  if (str_len (path) == 0)
     return (-1);
   if ((i = mx_get_idx (path)) >= 0)
     return (MX_COMMAND(i,type));
   return (-1);
 }
 
+int mx_is_local (int m) {
+  if (!MX_IDX(m))
+    return (0);
+  return (MX_COMMAND(m,local));
+}
+
 /*
  * set DefaultMagic to the given value
  */
@@ -498,9 +520,9 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT * pctx)
   int rc;
 
   if (!ctx)
-    ctx = safe_malloc (sizeof (CONTEXT));
+    ctx = mem_malloc (sizeof (CONTEXT));
   memset (ctx, 0, sizeof (CONTEXT));
-  ctx->path = safe_strdup (path);
+  ctx->path = str_dup (path);
 
   ctx->msgnotreadyet = -1;
   ctx->collapsed = 0;
@@ -509,18 +531,21 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT * pctx)
     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) {
       mx_fastclose_mailbox (ctx);
       if (!pctx)
-        FREE (&ctx);
+        mem_free (&ctx);
       return NULL;
     }
     return ctx;
   }
 
-  ctx->magic = mx_get_magic (path);
+  if (!MX_IDX(ctx->magic-1))
+    ctx->magic = mx_get_magic (path);
 
 #ifdef USE_COMPRESSED
   if (ctx->magic == M_COMPRESSED)
@@ -536,7 +561,7 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT * pctx)
   if (ctx->magic <= 0) {
     mx_fastclose_mailbox (ctx);
     if (!pctx)
-      FREE (&ctx);
+      mem_free (&ctx);
     return (NULL);
   }
 
@@ -566,7 +591,7 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT * pctx)
   else {
     mx_fastclose_mailbox (ctx);
     if (!pctx)
-      FREE (&ctx);
+      mem_free (&ctx);
   }
 
   unset_option (OPTFORCEREFRESH);
@@ -581,18 +606,8 @@ void mx_fastclose_mailbox (CONTEXT * 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)
@@ -600,14 +615,14 @@ void mx_fastclose_mailbox (CONTEXT * ctx)
   mutt_clear_threads (ctx);
   for (i = 0; i < ctx->msgcount; i++)
     mutt_free_header (&ctx->hdrs[i]);
-  FREE (&ctx->hdrs);
-  FREE (&ctx->v2r);
+  mem_free (&ctx->hdrs);
+  mem_free (&ctx->v2r);
 #ifdef USE_COMPRESSED
   if (ctx->compressinfo)
     mutt_fast_close_compressed (ctx);
 #endif
-  FREE (&ctx->path);
-  FREE (&ctx->pattern);
+  mem_free (&ctx->path);
+  mem_free (&ctx->pattern);
   if (ctx->limit_pattern)
     mutt_pattern_free (&ctx->limit_pattern);
   safe_fclose (&ctx->fp);
@@ -617,57 +632,14 @@ void mx_fastclose_mailbox (CONTEXT * ctx)
 /* save changes to disk */
 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 */
-
-#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
+  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_COMPRESSED
   if (rc == 0 && ctx->compressinfo)
@@ -822,7 +794,7 @@ int mx_close_mailbox (CONTEXT * ctx, int *index_hint)
     /* try to use server-side copy first */
     i = 1;
 
-    if (ctx->magic == M_IMAP && mx_get_magic (mbox) == M_IMAP) {
+    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
@@ -1004,6 +976,9 @@ void mx_update_tables (CONTEXT * ctx, int committing)
   }
 #undef this_body
   ctx->msgcount = j;
+
+  /* update sidebar count */
+  sidebar_set_buffystats (ctx);
 }
 
 
@@ -1104,6 +1079,9 @@ int mx_sync_mailbox (CONTEXT * ctx, int *index_hint)
       return 0;
     }
 
+    /* update sidebar counts */
+    sidebar_set_buffystats (ctx);
+
     /* if we haven't deleted any messages, we don't need to resort */
     /* ... except for certain folder formats which need "unsorted" 
      * sort order in order to synchronize folders.
@@ -1126,19 +1104,6 @@ int mx_sync_mailbox (CONTEXT * ctx, int *index_hint)
   return (rc);
 }
 
-#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
@@ -1147,34 +1112,14 @@ int imap_open_new_message (MESSAGE * msg, CONTEXT * dest, HEADER * hdr)
 MESSAGE *mx_open_new_message (CONTEXT * dest, HEADER * hdr, int flags)
 {
   MESSAGE *msg;
-  int (*func) (MESSAGE *, CONTEXT *, HEADER *);
   ADDRESS *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));
+  if (!MX_IDX(dest->magic-1)) {
+    debug_print (1, ("function unimplemented for mailbox type %d.\n", dest->magic));
     return (NULL);
   }
 
-  msg = safe_calloc (1, sizeof (MESSAGE));
+  msg = mem_calloc (1, sizeof (MESSAGE));
   msg->magic = dest->magic;
   msg->write = 1;
 
@@ -1188,7 +1133,7 @@ MESSAGE *mx_open_new_message (CONTEXT * dest, HEADER * hdr, int flags)
   if (msg->received == 0)
     time (&msg->received);
 
-  if (func (msg, dest, hdr) == 0) {
+  if (MX_COMMAND(dest->magic-1,mx_open_new_message)(msg, dest, hdr) == 0) {
     if (dest->magic == M_MMDF)
       fputs (MMDF_SEP, msg->fp);
 
@@ -1207,16 +1152,13 @@ MESSAGE *mx_open_new_message (CONTEXT * dest, HEADER * hdr, int flags)
     }
   }
   else
-    FREE (&msg);
+    mem_free (&msg);
 
   return msg;
 }
 
 /* check for new mail */
-int mx_check_mailbox (CONTEXT * ctx, int *index_hint, int lock)
-{
-  int rc;
-
+int mx_check_mailbox (CONTEXT * ctx, int *index_hint, int lock) {
 #ifdef USE_COMPRESSED
   if (ctx->compressinfo)
     return mutt_check_mailbox_compressed (ctx);
@@ -1225,53 +1167,13 @@ int mx_check_mailbox (CONTEXT * ctx, int *index_hint, int lock)
   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 (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"));
+  debug_print (1, ("null or invalid context.\n"));
   return (-1);
+
 }
 
 /* return a stream pointer for a message */
@@ -1279,7 +1181,7 @@ MESSAGE *mx_open_message (CONTEXT * ctx, int msgno)
 {
   MESSAGE *msg;
 
-  msg = safe_calloc (1, sizeof (MESSAGE));
+  msg = mem_calloc (1, sizeof (MESSAGE));
   switch (msg->magic = ctx->magic) {
   case M_MBOX:
   case M_MMDF:
@@ -1300,9 +1202,8 @@ MESSAGE *mx_open_message (CONTEXT * ctx, int msgno)
 
       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);
+        debug_print (1, ("fopen: %s: %s (errno %d).\n", path, strerror (errno), errno));
+        mem_free (&msg);
       }
     }
     break;
@@ -1311,7 +1212,7 @@ MESSAGE *mx_open_message (CONTEXT * ctx, int msgno)
   case M_IMAP:
     {
       if (imap_fetch_message (msg, ctx, msgno) != 0)
-        FREE (&msg);
+        mem_free (&msg);
       break;
     }
 #endif /* USE_IMAP */
@@ -1320,7 +1221,7 @@ MESSAGE *mx_open_message (CONTEXT * ctx, int msgno)
   case M_POP:
     {
       if (pop_fetch_message (msg, ctx, msgno) != 0)
-        FREE (&msg);
+        mem_free (&msg);
       break;
     }
 #endif /* USE_POP */
@@ -1329,17 +1230,14 @@ MESSAGE *mx_open_message (CONTEXT * ctx, int msgno)
   case M_NNTP:
     {
       if (nntp_fetch_message (msg, ctx, msgno) != 0)
-        FREE (&msg);
+        mem_free (&msg);
       break;
     }
 #endif /* USE_NNTP */
 
   default:
-    dprint (1,
-            (debugfile,
-             "mx_open_message(): function not implemented for mailbox type %d.\n",
-             ctx->magic));
-    FREE (&msg);
+    debug_print (1, ("function not implemented for mailbox type %d.\n", ctx->magic));
+    mem_free (&msg);
     break;
   }
   return (msg);
@@ -1347,63 +1245,14 @@ MESSAGE *mx_open_message (CONTEXT * ctx, int msgno)
 
 /* commit a message to a folder */
 
-int mx_commit_message (MESSAGE * msg, CONTEXT * ctx)
-{
-  int r = 0;
-
+int mx_commit_message (MESSAGE * msg, CONTEXT * ctx) {
   if (!(msg->write && ctx->append)) {
-    dprint (1,
-            (debugfile,
-             "mx_commit_message(): msg->write = %d, ctx->append = %d\n",
-             msg->write, ctx->append));
+    debug_print (1, ("msg->write = %d, ctx->append = %d\n", 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 */
@@ -1428,13 +1277,12 @@ int mx_close_message (MESSAGE ** msg)
     (*msg)->fp = NULL;
 
   if ((*msg)->path) {
-    dprint (1, (debugfile, "mx_close_message (): unlinking %s\n",
-                (*msg)->path));
+    debug_print (1, ("unlinking %s\n", (*msg)->path));
     unlink ((*msg)->path);
-    FREE (&(*msg)->path);
+    mem_free (&(*msg)->path);
   }
 
-  FREE (msg);
+  mem_free (msg);
   return (r);
 }
 
@@ -1451,12 +1299,12 @@ void mx_alloc_memory (CONTEXT * ctx)
   }
 
   if (ctx->hdrs) {
-    safe_realloc (&ctx->hdrs, sizeof (HEADER *) * (ctx->hdrmax += 25));
-    safe_realloc (&ctx->v2r, sizeof (int) * ctx->hdrmax);
+    mem_realloc (&ctx->hdrs, sizeof (HEADER *) * (ctx->hdrmax += 25));
+    mem_realloc (&ctx->v2r, sizeof (int) * ctx->hdrmax);
   }
   else {
-    ctx->hdrs = safe_calloc ((ctx->hdrmax += 25), sizeof (HEADER *));
-    ctx->v2r = safe_calloc (ctx->hdrmax, sizeof (int));
+    ctx->hdrs = mem_calloc ((ctx->hdrmax += 25), sizeof (HEADER *));
+    ctx->v2r = mem_calloc (ctx->hdrmax, sizeof (int));
   }
   for (i = ctx->msgcount; i < ctx->hdrmax; i++) {
     ctx->hdrs[i] = NULL;
@@ -1496,10 +1344,10 @@ void mx_update_context (CONTEXT * ctx, int new_messages)
 
       h2 = hash_find (ctx->id_hash, h->env->supersedes);
 
-      /* FREE (&h->env->supersedes); should I ? */
+      /* mem_free (&h->env->supersedes); should I ? */
       if (h2) {
         h2->superseded = 1;
-        if (option (OPTSCORE))
+        if (!ctx->counting && option (OPTSCORE))
           mutt_score_message (ctx, h2, 1);
       }
     }
@@ -1507,11 +1355,13 @@ void mx_update_context (CONTEXT * ctx, int new_messages)
     /* 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;
@@ -1525,6 +1375,8 @@ void mx_update_context (CONTEXT * ctx, int new_messages)
         ctx->new++;
     }
   }
+  /* update sidebar count */
+  sidebar_set_buffystats (ctx);
 }
 
 /*
@@ -1543,7 +1395,7 @@ int mx_check_empty (const char *path)
 }
 
 int mx_acl_check (CONTEXT* ctx, int flag) {
-  if (!ctx || ctx->magic <= 0 || ctx->magic >= MailboxFormats->length)
+  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))
@@ -1578,6 +1430,7 @@ void mx_init (void) {
     if (MX_COMMAND(i,type) < 1)         EXITWITHERR("type");
     if (!MX_COMMAND(i,mx_is_magic))     EXITWITHERR("mx_is_magic");
     if (!MX_COMMAND(i,mx_open_mailbox)) EXITWITHERR("mx_open_mailbox");
+/*    if (!MX_COMMAND(i,mx_sync_mailbox)) EXITWITHERR("mx_sync_mailbox");*/
   }
 #undef EXITWITHERR
 #endif /* DEBUG */