]> git.llucax.com Git - software/mutt-debian.git/blobdiff - mh.c
Move Mutt with NNTP support to mutt-nntp package
[software/mutt-debian.git] / mh.c
diff --git a/mh.c b/mh.c
index e020d0b9b7b0ca082c9afce4c70efc0ad673b6f3..21f516bb2c8ca8361f2ae75d8f9df24b98ce3eb2 100644 (file)
--- a/mh.c
+++ b/mh.c
@@ -1,6 +1,6 @@
 /*
 /*
- * Copyright (C) 1996-2002 Michael R. Elkins <me@mutt.org>
- * Copyright (C) 1999-2002 Thomas Roessler <roessler@does-not-exist.org>
+ * Copyright (C) 1996-2002,2007,2009 Michael R. Elkins <me@mutt.org>
+ * Copyright (C) 1999-2005 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
  * 
  *     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
@@ -30,9 +30,7 @@
 #include "mailbox.h"
 #include "mx.h"
 #include "copy.h"
 #include "mailbox.h"
 #include "mx.h"
 #include "copy.h"
-#include "buffy.h"
 #include "sort.h"
 #include "sort.h"
-#include "account.h"
 #if USE_HCACHE
 #include "hcache.h"
 #endif
 #if USE_HCACHE
 #include "hcache.h"
 #endif
@@ -142,20 +140,25 @@ static short mhs_unset (struct mh_sequences *mhs, int i, short f)
 
 #endif
 
 
 #endif
 
-static void mh_read_token (char *t, int *first, int *last)
+static int mh_read_token (char *t, int *first, int *last)
 {
   char *p;
   if ((p = strchr (t, '-')))
   {
     *p++ = '\0';
 {
   char *p;
   if ((p = strchr (t, '-')))
   {
     *p++ = '\0';
-    *first = atoi (t);
-    *last = atoi (p);
+    if (mutt_atoi (t, first) < 0 || mutt_atoi (p, last) < 0)
+      return -1;
   }
   else
   }
   else
-    *first = *last = atoi (t);
+  {
+    if (mutt_atoi (t, first) < 0)
+      return -1;
+    *last = *first;
+  }
+  return 0;
 }
 
 }
 
-static void mh_read_sequences (struct mh_sequences *mhs, const char *path)
+static int mh_read_sequences (struct mh_sequences *mhs, const char *path)
 {
   FILE *fp;
   int line = 1;
 {
   FILE *fp;
   int line = 1;
@@ -164,15 +167,15 @@ static void mh_read_sequences (struct mh_sequences *mhs, const char *path)
   size_t sz = 0;
 
   short f;
   size_t sz = 0;
 
   short f;
-  int first, last;
+  int first, last, rc = 0;
 
   char pathname[_POSIX_PATH_MAX];
   snprintf (pathname, sizeof (pathname), "%s/.mh_sequences", path);
 
   if (!(fp = fopen (pathname, "r")))
 
   char pathname[_POSIX_PATH_MAX];
   snprintf (pathname, sizeof (pathname), "%s/.mh_sequences", path);
 
   if (!(fp = fopen (pathname, "r")))
-    return;
+    return 0; /* yes, ask callers to silently ignore the error */
 
 
-  while ((buff = mutt_read_line (buff, &sz, fp, &line)))
+  while ((buff = mutt_read_line (buff, &sz, fp, &line, 0)))
   {
     if (!(t = strtok (buff, " \t:")))
       continue;
   {
     if (!(t = strtok (buff, " \t:")))
       continue;
@@ -188,14 +191,23 @@ static void mh_read_sequences (struct mh_sequences *mhs, const char *path)
 
     while ((t = strtok (NULL, " \t:")))
     {
 
     while ((t = strtok (NULL, " \t:")))
     {
-      mh_read_token (t, &first, &last);
+      if (mh_read_token (t, &first, &last) < 0)
+      {
+       mhs_free_sequences (mhs);
+       rc = -1;
+       goto out;
+      }
       for (; first <= last; first++)
        mhs_set (mhs, first, f);
     }
   }
 
       for (; first <= last; first++)
        mhs_set (mhs, first, f);
     }
   }
 
+  rc = 0;
+
+out:
   FREE (&buff);
   safe_fclose (&fp);
   FREE (&buff);
   safe_fclose (&fp);
+  return rc;
 }
 
 static inline mode_t mh_umask (CONTEXT* ctx)
 }
 
 static inline mode_t mh_umask (CONTEXT* ctx)
@@ -221,7 +233,8 @@ int mh_buffy (const char *path)
   struct mh_sequences mhs;
   memset (&mhs, 0, sizeof (mhs));
 
   struct mh_sequences mhs;
   memset (&mhs, 0, sizeof (mhs));
 
-  mh_read_sequences (&mhs, path);
+  if (mh_read_sequences (&mhs, path) < 0)
+    return 0;
   for (i = 0; !r && i <= mhs.max; i++)
     if (mhs_check (&mhs, i) & MH_SEQ_UNSEEN)
       r = 1;
   for (i = 0; !r && i <= mhs.max; i++)
     if (mhs_check (&mhs, i) & MH_SEQ_UNSEEN)
       r = 1;
@@ -312,7 +325,7 @@ static void mhs_write_one_sequence (FILE * fp, struct mh_sequences *mhs,
 
 /* XXX - we don't currently remove deleted messages from sequences we don't know.  Should we? */
 
 
 /* XXX - we don't currently remove deleted messages from sequences we don't know.  Should we? */
 
-void mh_update_sequences (CONTEXT * ctx)
+static void mh_update_sequences (CONTEXT * ctx)
 {
   FILE *ofp, *nfp;
 
 {
   FILE *ofp, *nfp;
 
@@ -352,7 +365,7 @@ void mh_update_sequences (CONTEXT * ctx)
   /* first, copy unknown sequences */
   if ((ofp = fopen (sequences, "r")))
   {
   /* first, copy unknown sequences */
   if ((ofp = fopen (sequences, "r")))
   {
-    while ((buff = mutt_read_line (buff, &s, ofp, &l)))
+    while ((buff = mutt_read_line (buff, &s, ofp, &l, 0)))
     {
       if (!mutt_strncmp (buff, seq_unseen, mutt_strlen (seq_unseen)))
        continue;
     {
       if (!mutt_strncmp (buff, seq_unseen, mutt_strlen (seq_unseen)))
        continue;
@@ -377,7 +390,8 @@ void mh_update_sequences (CONTEXT * ctx)
     else
       p = ctx->hdrs[l]->path;
 
     else
       p = ctx->hdrs[l]->path;
 
-    i = atoi (p);
+    if (mutt_atoi (p, &i) < 0)
+      continue;
 
     if (!ctx->hdrs[l]->read)
     {
 
     if (!ctx->hdrs[l]->read)
     {
@@ -450,7 +464,7 @@ 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")))
   {
   snprintf (sequences, sizeof (sequences), "%s/.mh_sequences", ctx->path);
   if ((ofp = fopen (sequences, "r")))
   {
-    while ((buff = mutt_read_line (buff, &sz, ofp, &line)))
+    while ((buff = mutt_read_line (buff, &sz, ofp, &line, 0)))
     {
       if (unseen && !strncmp (buff, seq_unseen, mutt_strlen (seq_unseen)))
       {
     {
       if (unseen && !strncmp (buff, seq_unseen, mutt_strlen (seq_unseen)))
       {
@@ -505,7 +519,8 @@ static void mh_update_maildir (struct maildir *md, struct mh_sequences *mhs)
     else
       p = md->h->path;
 
     else
       p = md->h->path;
 
-    i = atoi (p);
+    if (mutt_atoi (p, &i) < 0)
+      continue;
     f = mhs_check (mhs, i);
 
     md->h->read = (f & MH_SEQ_UNSEEN) ? 0 : 1;
     f = mhs_check (mhs, i);
 
     md->h->read = (f & MH_SEQ_UNSEEN) ? 0 : 1;
@@ -639,13 +654,13 @@ static HEADER *maildir_parse_message (int magic, const char *fname,
     h->env = mutt_read_rfc822_header (f, h, 0, 0);
 
     fstat (fileno (f), &st);
     h->env = mutt_read_rfc822_header (f, h, 0, 0);
 
     fstat (fileno (f), &st);
-    fclose (f);
+    safe_fclose (&f);
 
     if (!h->received)
       h->received = h->date_sent;
 
 
     if (!h->received)
       h->received = h->date_sent;
 
-    if (h->content->length <= 0)
-      h->content->length = st.st_size - h->content->offset;
+    /* always update the length since we have fresh information available. */
+    h->content->length = st.st_size - h->content->offset;
 
     h->index = -1;
 
 
     h->index = -1;
 
@@ -978,7 +993,7 @@ static struct maildir *skip_duplicates (struct maildir *p, struct maildir **last
 /* 
  * This function does the second parsing pass
  */
 /* 
  * This function does the second parsing pass
  */
-void maildir_delayed_parsing (CONTEXT * ctx, struct maildir **md,
+static void maildir_delayed_parsing (CONTEXT * ctx, struct maildir **md,
                              progress_t *progress)
 { 
   struct maildir *p, *last = NULL;
                              progress_t *progress)
 { 
   struct maildir *p, *last = NULL;
@@ -1029,13 +1044,14 @@ void maildir_delayed_parsing (CONTEXT * ctx, struct maildir **md,
     if (!ctx->quiet && progress)
       mutt_progress_update (progress, count, -1);
 
     if (!ctx->quiet && progress)
       mutt_progress_update (progress, count, -1);
 
+    DO_SORT();
+
     snprintf (fn, sizeof (fn), "%s/%s", ctx->path, p->h->path);
 
 #if USE_HCACHE
     if (option(OPTHCACHEVERIFY))
     {
     snprintf (fn, sizeof (fn), "%s/%s", ctx->path, p->h->path);
 
 #if USE_HCACHE
     if (option(OPTHCACHEVERIFY))
     {
-      DO_SORT();
-      ret = stat(fn, &lastchanged);
+       ret = stat(fn, &lastchanged);
     }
     else
     {
     }
     else
     {
@@ -1059,7 +1075,6 @@ void maildir_delayed_parsing (CONTEXT * ctx, struct maildir **md,
     {
 #endif /* USE_HCACHE */
 
     {
 #endif /* USE_HCACHE */
 
-    DO_SORT();
     if (maildir_parse_message (ctx->magic, fn, p->h->old, p->h))
     {
       p->header_parsed = 1;
     if (maildir_parse_message (ctx->magic, fn, p->h->old, p->h))
     {
       p->header_parsed = 1;
@@ -1141,7 +1156,8 @@ int mh_read_dir (CONTEXT * ctx, const char *subdir)
 
   if (ctx->magic == M_MH)
   {
 
   if (ctx->magic == M_MH)
   {
-    mh_read_sequences (&mhs, ctx->path);
+    if (mh_read_sequences (&mhs, ctx->path) < 0)
+      return -1;
     mh_update_maildir (md, &mhs);
     mhs_free_sequences (&mhs);
   }
     mh_update_maildir (md, &mhs);
     mhs_free_sequences (&mhs);
   }
@@ -1150,7 +1166,7 @@ int mh_read_dir (CONTEXT * ctx, const char *subdir)
 
   if (!data->mh_umask)
     data->mh_umask = mh_umask (ctx);
 
   if (!data->mh_umask)
     data->mh_umask = mh_umask (ctx);
-  
+
   return 0;
 }
 
   return 0;
 }
 
@@ -1175,7 +1191,7 @@ int mh_open_new_message (MESSAGE * msg, CONTEXT * dest, HEADER * hdr)
   return mh_mkstemp (dest, &msg->fp, &msg->path);
 }
 
   return mh_mkstemp (dest, &msg->fp, &msg->path);
 }
 
-int ch_compar (const void *a, const void *b)
+static int ch_compar (const void *a, const void *b)
 {
   return (int)( *((const char *) a) - *((const char *) b));
 }
 {
   return (int)( *((const char *) a) - *((const char *) b));
 }
@@ -1244,8 +1260,8 @@ int maildir_open_new_message (MESSAGE * msg, CONTEXT * dest, HEADER * hdr)
   omask = umask (mh_umask (dest));
   FOREVER
   {
   omask = umask (mh_umask (dest));
   FOREVER
   {
-    snprintf (path, _POSIX_PATH_MAX, "%s/tmp/%s.%ld.%u_%d.%s%s",
-             dest->path, subdir, time (NULL), (unsigned int)getpid (),
+    snprintf (path, _POSIX_PATH_MAX, "%s/tmp/%s.%lld.%u_%d.%s%s",
+             dest->path, subdir, (long long)time (NULL), (unsigned int)getpid (),
              Counter++, NONULL (Hostname), suffix);
 
     dprint (2, (debugfile, "maildir_open_new_message (): Trying %s.\n",
              Counter++, NONULL (Hostname), suffix);
 
     dprint (2, (debugfile, "maildir_open_new_message (): Trying %s.\n",
@@ -1311,8 +1327,11 @@ int maildir_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr)
   char full[_POSIX_PATH_MAX];
   char *s;
 
   char full[_POSIX_PATH_MAX];
   char *s;
 
-  if (safe_fclose (&msg->fp) != 0)
+  if (safe_fsync_close (&msg->fp))
+  {
+    mutt_perror (_("Could not flush message to disk"));
     return -1;
     return -1;
+  }
 
   /* extract the subdir */
   s = strrchr (msg->path, '/') + 1;
 
   /* extract the subdir */
   s = strrchr (msg->path, '/') + 1;
@@ -1327,8 +1346,8 @@ int maildir_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr)
   /* construct a new file name. */
   FOREVER
   {
   /* construct a new file name. */
   FOREVER
   {
-    snprintf (path, _POSIX_PATH_MAX, "%s/%ld.%u_%d.%s%s", subdir,
-             time (NULL), (unsigned int)getpid (), Counter++, 
+    snprintf (path, _POSIX_PATH_MAX, "%s/%lld.%u_%d.%s%s", subdir,
+             (long long)time (NULL), (unsigned int)getpid (), Counter++,
              NONULL (Hostname), suffix);
     snprintf (full, _POSIX_PATH_MAX, "%s/%s", ctx->path, path);
 
              NONULL (Hostname), suffix);
     snprintf (full, _POSIX_PATH_MAX, "%s/%s", ctx->path, path);
 
@@ -1386,8 +1405,11 @@ static int _mh_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr,
   char path[_POSIX_PATH_MAX];
   char tmp[16];
 
   char path[_POSIX_PATH_MAX];
   char tmp[16];
 
-  if (safe_fclose (&msg->fp) != 0)
+  if (safe_fsync_close (&msg->fp))
+  {
+    mutt_perror (_("Could not flush message to disk"));
     return -1;
     return -1;
+  }
 
   if ((dirp = opendir (ctx->path)) == NULL)
   {
 
   if ((dirp = opendir (ctx->path)) == NULL)
   {
@@ -1686,6 +1708,18 @@ int mh_sync_mailbox (CONTEXT * ctx, int *index_hint)
          goto err;
       }
     }
          goto err;
       }
     }
+
+#if USE_HCACHE
+    if (ctx->hdrs[i]->changed)
+    {
+      if (ctx->magic == M_MAILDIR)
+       mutt_hcache_store (hc, ctx->hdrs[i]->path + 3, ctx->hdrs[i],
+                          0, &maildir_hcache_keylen);
+      else if (ctx->magic == M_MH)
+       mutt_hcache_store (hc, ctx->hdrs[i]->path, ctx->hdrs[i], 0, strlen);
+    }
+#endif
+
   }
 
 #if USE_HCACHE
   }
 
 #if USE_HCACHE
@@ -1866,7 +1900,7 @@ int maildir_check_mailbox (CONTEXT * ctx, int *index_hint)
    * of each message we scanned.  This is used in the loop over the
    * existing messages below to do some correlation.
    */
    * of each message we scanned.  This is used in the loop over the
    * existing messages below to do some correlation.
    */
-  fnames = hash_create (1031);
+  fnames = hash_create (1031, 0);
 
   for (p = md; p; p = p->next)
   {
 
   for (p = md; p; p = p->next)
   {
@@ -1976,7 +2010,7 @@ int mh_check_mailbox (CONTEXT * ctx, int *index_hint)
   
   /* create .mh_sequences when there isn't one. */
   snprintf (buf, sizeof (buf), "%s/.mh_sequences", ctx->path);
   
   /* create .mh_sequences when there isn't one. */
   snprintf (buf, sizeof (buf), "%s/.mh_sequences", ctx->path);
-  if ((i = stat (buf, &st_cur) == -1) && errno == ENOENT)
+  if ((i = stat (buf, &st_cur)) == -1 && errno == ENOENT)
   {
     char *tmp;
     FILE *fp = NULL;
   {
     char *tmp;
     FILE *fp = NULL;
@@ -2010,12 +2044,13 @@ int mh_check_mailbox (CONTEXT * ctx, int *index_hint)
   maildir_parse_dir (ctx, &last, NULL, NULL, NULL);
   maildir_delayed_parsing (ctx, &md, NULL);
 
   maildir_parse_dir (ctx, &last, NULL, NULL, NULL);
   maildir_delayed_parsing (ctx, &md, NULL);
 
-  mh_read_sequences (&mhs, ctx->path);
+  if (mh_read_sequences (&mhs, ctx->path) < 0)
+    return -1;
   mh_update_maildir (md, &mhs);
   mhs_free_sequences (&mhs);
 
   /* check for modifications and adjust flags */
   mh_update_maildir (md, &mhs);
   mhs_free_sequences (&mhs);
 
   /* check for modifications and adjust flags */
-  fnames = hash_create (1031);
+  fnames = hash_create (1031, 0);
 
   for (p = md; p; p = p->next)
     hash_insert (fnames, p->h->path, p, 0);
 
   for (p = md; p; p = p->next)
     hash_insert (fnames, p->h->path, p, 0);
@@ -2061,7 +2096,7 @@ int mh_check_mailbox (CONTEXT * ctx, int *index_hint)
  * then again, it's called rarely.
  */
 
  * then again, it's called rarely.
  */
 
-FILE *_maildir_open_find_message (const char *folder, const char *unique,
+static FILE *_maildir_open_find_message (const char *folder, const char *unique,
                                  const char *subfolder)
 {
   char dir[_POSIX_PATH_MAX];
                                  const char *subfolder)
 {
   char dir[_POSIX_PATH_MAX];
@@ -2209,3 +2244,50 @@ int mh_check_empty (const char *path)
   
   return r;
 }
   
   return r;
 }
+
+int mx_is_maildir (const char *path)
+{
+  char tmp[_POSIX_PATH_MAX];
+  struct stat st;
+
+  snprintf (tmp, sizeof (tmp), "%s/cur", path);
+  if (stat (tmp, &st) == 0 && S_ISDIR (st.st_mode))
+    return 1;
+  return 0;
+}
+
+int mx_is_mh (const char *path)
+{
+  char tmp[_POSIX_PATH_MAX];
+
+  snprintf (tmp, sizeof (tmp), "%s/.mh_sequences", path);
+  if (access (tmp, F_OK) == 0)
+    return 1;
+
+  snprintf (tmp, sizeof (tmp), "%s/.xmhcache", path);
+  if (access (tmp, F_OK) == 0)
+    return 1;
+
+  snprintf (tmp, sizeof (tmp), "%s/.mew_cache", path);
+  if (access (tmp, F_OK) == 0)
+    return 1;
+
+  snprintf (tmp, sizeof (tmp), "%s/.mew-cache", path);
+  if (access (tmp, F_OK) == 0)
+    return 1;
+
+  snprintf (tmp, sizeof (tmp), "%s/.sylpheed_cache", path);
+  if (access (tmp, F_OK) == 0)
+    return 1;
+
+  /*
+   * 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 1;
+
+  return 0;
+}