Rocco Rutte:
[apps/madmutt.git] / muttlib.c
index 234efd2..c52c58b 100644 (file)
--- a/muttlib.c
+++ b/muttlib.c
@@ -214,19 +214,25 @@ void mutt_free_parameter (PARAMETER ** p)
   *p = 0;
 }
 
-LIST *mutt_add_list (LIST * head, const char *data)
-{
+LIST *mutt_add_list (LIST * head, const char *data) {
+  size_t len = mutt_strlen (data);
+  return (mutt_add_list_n (head, data, len ? len + 1 : 0));
+}
+
+LIST *mutt_add_list_n (LIST *head, const void *data, size_t len) {
   LIST *tmp;
 
   for (tmp = head; tmp && tmp->next; tmp = tmp->next);
+
   if (tmp) {
     tmp->next = safe_malloc (sizeof (LIST));
     tmp = tmp->next;
-  }
-  else
+  } else
     head = tmp = safe_malloc (sizeof (LIST));
 
-  tmp->data = safe_strdup (data);
+  tmp->data = safe_malloc (len);
+  if (len)
+    memcpy (tmp->data, data, len);
   tmp->next = NULL;
   return head;
 }
@@ -637,6 +643,50 @@ void mutt_free_envelope (ENVELOPE ** p)
   FREE (p);
 }
 
+/* move all the headers from extra not present in base into base */
+void mutt_merge_envelopes(ENVELOPE* base, ENVELOPE** extra)
+{
+  /* copies each existing element if necessary, and sets the element
+  * to NULL in the source so that mutt_free_envelope doesn't leave us
+  * with dangling pointers. */
+#define MOVE_ELEM(h) if (!base->h) { base->h = (*extra)->h; (*extra)->h = NULL; }
+  MOVE_ELEM(return_path);
+  MOVE_ELEM(from);
+  MOVE_ELEM(to);
+  MOVE_ELEM(cc);
+  MOVE_ELEM(bcc);
+  MOVE_ELEM(sender);
+  MOVE_ELEM(reply_to);
+  MOVE_ELEM(mail_followup_to);
+  MOVE_ELEM(list_post);
+  MOVE_ELEM(message_id);
+  MOVE_ELEM(supersedes);
+  MOVE_ELEM(date);
+  MOVE_ELEM(x_label);
+  if (!base->refs_changed) {
+    MOVE_ELEM(references);
+  }
+  if (!base->irt_changed) {
+    MOVE_ELEM(in_reply_to);
+  }
+  /* real_subj is subordinate to subject */
+  if (!base->subject) {
+    base->subject = (*extra)->subject;
+    base->real_subj = (*extra)->real_subj;
+    (*extra)->subject = NULL;
+    (*extra)->real_subj = NULL;
+  }
+  /* spam and user headers should never be hashed, and the new envelope may
+   * have better values. Use new versions regardless. */
+  mutt_buffer_free (&base->spam);
+  mutt_free_list (&base->userhdrs);
+  MOVE_ELEM(spam);
+  MOVE_ELEM(userhdrs);
+#undef MOVE_ELEM
+  
+  mutt_free_envelope(extra);
+}
+
 void _mutt_mktemp (char *s, const char *src, int line)
 {
 
@@ -1181,16 +1231,10 @@ int mutt_save_confirm (const char *s, struct stat *st)
   }
 #endif
 
-  if (stat (s, st) != -1) {
-    if (magic == -1) {
-      mutt_error (_("%s is not a mailbox!"), s);
-      return 1;
-    }
-
+  if (magic > 0 && !mx_access (s, W_OK)) {
     if (option (OPTCONFIRMAPPEND) &&
-        (!TrashPath || (mutt_strcmp (s, TrashPath) != 0)))
+        (!TrashPath || (mutt_strcmp (s, TrashPath) != 0))) {
       /* if we're appending to the trash, there's no point in asking */
-    {
       snprintf (tmp, sizeof (tmp), _("Append messages to %s?"), s);
       if ((rc = mutt_yesorno (tmp, M_YES)) == M_NO)
         ret = 1;
@@ -1198,6 +1242,13 @@ int mutt_save_confirm (const char *s, struct stat *st)
         ret = -1;
     }
   }
+
+  if (stat (s, st) != -1) {
+    if (magic == -1) {
+      mutt_error (_("%s is not a mailbox!"), s);
+      return 1;
+    }
+  }
   else {
 #ifdef USE_IMAP
     if (magic != M_IMAP)
@@ -1490,3 +1541,111 @@ int mutt_match_spam_list (const char *s, SPAM_LIST * l, char *text, int x)
 
   return 0;
 }
+
+int mutt_cmp_header (const HEADER * h1, const HEADER * h2) {
+  if (h1 && h2) {
+    if (h1->received != h2->received ||
+        h1->date_sent != h2->date_sent ||
+        h1->content->length != h2->content->length ||
+        h1->lines != h2->lines ||
+        h1->zhours != h2->zhours ||
+        h1->zminutes != h2->zminutes ||
+        h1->zoccident != h2->zoccident ||
+        h1->mime != h2->mime ||
+        !mutt_cmp_env (h1->env, h2->env) ||
+        !mutt_cmp_body (h1->content, h2->content))
+      return (0);
+    else
+      return (1);
+  }
+  else {
+    if (h1 == NULL && h2 == NULL)
+      return (1);
+    else
+      return (0);
+  }
+}
+
+/* return 1 if address lists are strictly identical */
+int mutt_cmp_addr (const ADDRESS * a, const ADDRESS * b)
+{
+  while (a && b) {
+    if (mutt_strcmp (a->mailbox, b->mailbox) ||
+        mutt_strcmp (a->personal, b->personal))
+      return (0);
+
+    a = a->next;
+    b = b->next;
+  }
+  if (a || b)
+    return (0);
+
+  return (1);
+}
+
+int mutt_cmp_list (const LIST * a, const LIST * b)
+{
+  while (a && b) {
+    if (mutt_strcmp (a->data, b->data))
+      return (0);
+
+    a = a->next;
+    b = b->next;
+  }
+  if (a || b)
+    return (0);
+
+  return (1);
+}
+
+int mutt_cmp_env (const ENVELOPE * e1, const ENVELOPE * e2)
+{
+  if (e1 && e2) {
+    if (mutt_strcmp (e1->message_id, e2->message_id) ||
+        mutt_strcmp (e1->subject, e2->subject) ||
+        !mutt_cmp_list (e1->references, e2->references) ||
+        !mutt_cmp_addr (e1->from, e2->from) ||
+        !mutt_cmp_addr (e1->sender, e2->sender) ||
+        !mutt_cmp_addr (e1->reply_to, e2->reply_to) ||
+        !mutt_cmp_addr (e1->to, e2->to) ||
+        !mutt_cmp_addr (e1->cc, e2->cc) ||
+        !mutt_cmp_addr (e1->return_path, e2->return_path))
+      return (0);
+    else
+      return (1);
+  }
+  else {
+    if (e1 == NULL && e2 == NULL)
+      return (1);
+    else
+      return (0);
+  }
+}
+
+int mutt_cmp_param (const PARAMETER * p1, const PARAMETER * p2)
+{
+  while (p1 && p2) {
+    if (mutt_strcmp (p1->attribute, p2->attribute) ||
+        mutt_strcmp (p1->value, p2->value))
+      return (0);
+
+    p1 = p1->next;
+    p2 = p2->next;
+  }
+  if (p1 || p2)
+    return (0);
+
+  return (1);
+}
+
+int mutt_cmp_body (const BODY * b1, const BODY * b2)
+{
+  if (b1->type != b2->type ||
+      b1->encoding != b2->encoding ||
+      mutt_strcmp (b1->subtype, b2->subtype) ||
+      mutt_strcmp (b1->description, b2->description) ||
+      !mutt_cmp_param (b1->parameter, b2->parameter) ||
+      b1->length != b2->length)
+    return (0);
+  return (1);
+}