Rocco Rutte:
[apps/madmutt.git] / mh.c
diff --git a/mh.c b/mh.c
index cbc7b8b..c9f3d47 100644 (file)
--- a/mh.c
+++ b/mh.c
@@ -1,20 +1,11 @@
 /*
+ * Copyright notice from original mutt:
  * Copyright (C) 1996-2002 Michael R. Elkins <me@mutt.org>
  * Copyright (C) 1999-2002 Thomas Roessler <roessler@does-not-exist.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., 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.
  */
 
 /*
 #endif
 
 #include "mutt.h"
-#include "mailbox.h"
 #include "mx.h"
+#include "mh.h"
+#include "mbox.h"
 #include "copy.h"
 #include "buffy.h"
 #include "sort.h"
 
+#include "lib/mem.h"
+#include "lib/intl.h"
+#include "lib/str.h"
+
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <dirent.h>
 #include <string.h>
 #include <utime.h>
 
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
 struct maildir {
   HEADER *h;
   char *canon_fname;
   unsigned header_parsed:1;
+#ifdef USE_INODESORT
   ino_t inode;
+#endif /* USE_INODESORT */
   struct maildir *next;
 };
 
@@ -149,11 +151,11 @@ static void mh_read_sequences (struct mh_sequences *mhs, const char *path)
     if (!(t = strtok (buff, " \t:")))
       continue;
 
-    if (!mutt_strcmp (t, MhUnseen))
+    if (!safe_strcmp (t, MhUnseen))
       f = MH_SEQ_UNSEEN;
-    else if (!mutt_strcmp (t, MhFlagged))
+    else if (!safe_strcmp (t, MhFlagged))
       f = MH_SEQ_FLAGGED;
-    else if (!mutt_strcmp (t, MhReplied))
+    else if (!safe_strcmp (t, MhReplied))
       f = MH_SEQ_REPLIED;
     else                        /* unknown sequence */
       continue;
@@ -296,11 +298,11 @@ void mh_update_sequences (CONTEXT * ctx)
   /* first, copy unknown sequences */
   if ((ofp = fopen (sequences, "r"))) {
     while ((buff = mutt_read_line (buff, &s, ofp, &l))) {
-      if (!mutt_strncmp (buff, seq_unseen, mutt_strlen (seq_unseen)))
+      if (!safe_strncmp (buff, seq_unseen, safe_strlen (seq_unseen)))
         continue;
-      if (!mutt_strncmp (buff, seq_flagged, mutt_strlen (seq_flagged)))
+      if (!safe_strncmp (buff, seq_flagged, safe_strlen (seq_flagged)))
         continue;
-      if (!mutt_strncmp (buff, seq_replied, mutt_strlen (seq_replied)))
+      if (!safe_strncmp (buff, seq_replied, safe_strlen (seq_replied)))
         continue;
 
       fprintf (nfp, "%s\n", buff);
@@ -387,17 +389,17 @@ static void mh_sequences_add_one (CONTEXT * ctx, int n, short unseen,
   snprintf (sequences, sizeof (sequences), "%s/.mh_sequences", ctx->path);
   if ((ofp = fopen (sequences, "r"))) {
     while ((buff = mutt_read_line (buff, &sz, ofp, &line))) {
-      if (unseen && !strncmp (buff, seq_unseen, mutt_strlen (seq_unseen))) {
+      if (unseen && !strncmp (buff, seq_unseen, safe_strlen (seq_unseen))) {
         fprintf (nfp, "%s %d\n", buff, n);
         unseen_done = 1;
       }
       else if (flagged
-               && !strncmp (buff, seq_flagged, mutt_strlen (seq_flagged))) {
+               && !strncmp (buff, seq_flagged, safe_strlen (seq_flagged))) {
         fprintf (nfp, "%s %d\n", buff, n);
         flagged_done = 1;
       }
       else if (replied
-               && !strncmp (buff, seq_replied, mutt_strlen (seq_replied))) {
+               && !strncmp (buff, seq_replied, safe_strlen (seq_replied))) {
         fprintf (nfp, "%s %d\n", buff, n);
         replied_done = 1;
       }
@@ -480,10 +482,10 @@ static void maildir_parse_flags (HEADER * h, const char *path)
   h->read = 0;
   h->replied = 0;
 
-  if ((p = strrchr (path, ':')) != NULL && mutt_strncmp (p + 1, "2,", 2) == 0) {
+  if ((p = strrchr (path, ':')) != NULL && safe_strncmp (p + 1, "2,", 2) == 0) {
     p += 3;
 
-    mutt_str_replace (&h->maildir_flags, p);
+    str_replace (&h->maildir_flags, p);
     q = h->maildir_flags;
 
     while (*p) {
@@ -637,7 +639,9 @@ static int maildir_parse_entry (CONTEXT * ctx, struct maildir ***last,
     entry = safe_calloc (sizeof (struct maildir), 1);
     entry->h = h;
     entry->header_parsed = (ctx->magic == M_MH);
+#ifdef USE_INODESORT
     entry->inode = inode;
+#endif /* USE_INODESORT */
     **last = entry;
     *last = &entry->next;
 
@@ -673,7 +677,7 @@ static int maildir_parse_dir (CONTEXT * ctx, struct maildir ***last,
 
   if (subdir) {
     snprintf (buf, sizeof (buf), "%s/%s", ctx->path, subdir);
-    is_old = (mutt_strcmp ("cur", subdir) == 0);
+    is_old = (safe_strcmp ("cur", subdir) == 0);
   }
   else
     strfcpy (buf, ctx->path, sizeof (buf));
@@ -747,6 +751,7 @@ static int maildir_move_to_context (CONTEXT * ctx, struct maildir **md)
   return r;
 }
 
+#ifdef USE_INODESORT
 /*
  * Merge two maildir lists according to the inode numbers.
  */
@@ -823,13 +828,14 @@ static struct maildir *maildir_sort_inode (struct maildir *list)
   right = maildir_sort_inode (right);
   return maildir_merge_inode (left, right);
 }
+#endif /* USE_INODESORT */
 
 #if USE_HCACHE
 static size_t maildir_hcache_keylen (const char *fn)
 {
   const char *p = strchr (fn, ':');
 
-  return p ? (size_t) (p - fn) : mutt_strlen (fn);
+  return p ? (size_t) (p - fn) : safe_strlen (fn);
 }
 #endif
 
@@ -906,7 +912,7 @@ void maildir_delayed_parsing (CONTEXT * ctx, struct maildir *md)
  *     subdir [IN]     NULL for MH mailboxes, otherwise the subdir of the
  *                     maildir mailbox to read from
  */
-int mh_read_dir (CONTEXT * ctx, const char *subdir)
+static int _mh_read_dir (CONTEXT * ctx, const char *subdir)
 {
   struct maildir *md;
   struct mh_sequences mhs;
@@ -930,7 +936,9 @@ int mh_read_dir (CONTEXT * ctx, const char *subdir)
     mhs_free_sequences (&mhs);
   }
 
+#ifdef USE_INODESORT
   md = maildir_sort_inode (md);
+#endif /* USE_INODESORT */
 
   if (ctx->magic == M_MAILDIR)
     maildir_delayed_parsing (ctx, md);
@@ -939,13 +947,17 @@ int mh_read_dir (CONTEXT * ctx, const char *subdir)
   return 0;
 }
 
+int mh_read_dir (CONTEXT* ctx) {
+  return (_mh_read_dir (ctx, NULL));
+}
+
 /* read a maildir style mailbox */
 int maildir_read_dir (CONTEXT * ctx)
 {
   /* maildir looks sort of like MH, except that there are two subdirectories
    * of the main folder path from which to read messages
    */
-  if (mh_read_dir (ctx, "new") == -1 || mh_read_dir (ctx, "cur") == -1)
+  if (_mh_read_dir (ctx, "new") == -1 || _mh_read_dir (ctx, "cur") == -1)
     return (-1);
 
   return 0;
@@ -989,7 +1001,7 @@ static void maildir_flags (char *dest, size_t destlen, HEADER * hdr)
               hdr->read ? "S" : "", hdr->deleted ? "T" : "",
               NONULL (hdr->maildir_flags));
     if (hdr->maildir_flags)
-      qsort (tmp, strlen (tmp), 1, ch_compar);
+      qsort (tmp, safe_strlen (tmp), 1, ch_compar);
     snprintf (dest, destlen, ":2,%s", tmp);
   }
 }
@@ -1115,7 +1127,7 @@ int maildir_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr)
 
     if (safe_rename (msg->path, full) == 0) {
       if (hdr)
-        mutt_str_replace (&hdr->path, path);
+        str_replace (&hdr->path, path);
       FREE (&msg->path);
 
       /*
@@ -1201,7 +1213,7 @@ static int _mh_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr,
     snprintf (path, sizeof (path), "%s/%s", ctx->path, tmp);
     if (safe_rename (msg->path, path) == 0) {
       if (hdr)
-        mutt_str_replace (&hdr->path, tmp);
+        str_replace (&hdr->path, tmp);
       FREE (&msg->path);
       break;
     }
@@ -1282,7 +1294,7 @@ static int mh_rewrite_message (CONTEXT * ctx, int msgno)
     if (ctx->magic == M_MH && rc == 0) {
       snprintf (newpath, _POSIX_PATH_MAX, "%s/%s", ctx->path, h->path);
       if ((rc = safe_rename (newpath, oldpath)) == 0)
-        mutt_str_replace (&h->path, partpath);
+        str_replace (&h->path, partpath);
     }
   }
   else
@@ -1349,7 +1361,7 @@ static int maildir_sync_message (CONTEXT * ctx, int msgno)
     snprintf (fullpath, sizeof (fullpath), "%s/%s", ctx->path, partpath);
     snprintf (oldpath, sizeof (oldpath), "%s/%s", ctx->path, h->path);
 
-    if (mutt_strcmp (fullpath, oldpath) == 0) {
+    if (safe_strcmp (fullpath, oldpath) == 0) {
       /* message hasn't really changed */
       return 0;
     }
@@ -1361,7 +1373,7 @@ static int maildir_sync_message (CONTEXT * ctx, int msgno)
       mutt_perror ("rename");
       return (-1);
     }
-    mutt_str_replace (&h->path, partpath);
+    str_replace (&h->path, partpath);
   }
   return (0);
 }
@@ -1617,8 +1629,8 @@ int maildir_check_mailbox (CONTEXT * ctx, int *index_hint)
       /* check to see if the message has moved to a different
        * subdirectory.  If so, update the associated filename.
        */
-      if (mutt_strcmp (ctx->hdrs[i]->path, p->h->path))
-        mutt_str_replace (&ctx->hdrs[i]->path, p->h->path);
+      if (safe_strcmp (ctx->hdrs[i]->path, p->h->path))
+        str_replace (&ctx->hdrs[i]->path, p->h->path);
 
       /* if the user hasn't modified the flags on this message, update
        * the flags we just detected.
@@ -1802,7 +1814,7 @@ FILE *_maildir_open_find_message (const char *folder, const char *unique,
   while ((de = readdir (dp))) {
     maildir_canon_filename (tunique, de->d_name, sizeof (tunique));
 
-    if (!mutt_strcmp (tunique, unique)) {
+    if (!safe_strcmp (tunique, unique)) {
       snprintf (fname, sizeof (fname), "%s/%s/%s", folder, subfolder,
                 de->d_name);
       fp = fopen (fname, "r");  /* __FOPEN_CHECKED__ */
@@ -1914,3 +1926,83 @@ int mh_check_empty (const char *path)
 
   return r;
 }
+
+int mh_is_magic (const char* path) {
+  struct stat st;
+  char tmp[_POSIX_PATH_MAX];
+
+  if (stat (path, &st) == -1)
+    return (-1);
+
+  if (S_ISDIR (st.st_mode)) {
+    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);
+  }
+  return (-1);
+}
+
+int maildir_is_magic (const char* path) {
+  struct stat st;
+  char tmp[_POSIX_PATH_MAX];
+
+  if (stat (path, &st) == -1)
+    return (-1);
+  if (S_ISDIR (st.st_mode)) {
+    snprintf (tmp, sizeof (tmp), "%s/cur", path);
+    if (stat (tmp, &st) == 0 && S_ISDIR (st.st_mode))
+      return (M_MAILDIR);
+  }
+  return (-1);
+}
+
+/* routines common to maildir and mh */
+static mx_t* reg_mx (void) {
+  mx_t* fmt = safe_calloc (1, sizeof (mx_t));
+  fmt->local = 1;
+  fmt->mx_access = access;
+  return (fmt);
+}
+
+mx_t* mh_reg_mx (void) {
+  mx_t* fmt = reg_mx ();
+  fmt->type = M_MH;
+  fmt->mx_check_empty = mh_check_empty;
+  fmt->mx_is_magic = mh_is_magic;
+  fmt->mx_open_mailbox = mh_read_dir;
+  return (fmt);
+}
+
+mx_t* maildir_reg_mx (void) {
+  mx_t* fmt = reg_mx ();
+  fmt->type = M_MAILDIR;
+  fmt->mx_check_empty = maildir_check_empty;
+  fmt->mx_is_magic = maildir_is_magic;
+  fmt->mx_open_mailbox = maildir_read_dir;
+  return (fmt);
+}