]> granicus.if.org Git - neomutt/commitdiff
A first take at adding a mixmaster front-end to mutt. Don't worry,
authorThomas Roessler <roessler@does-not-exist.org>
Wed, 13 Jan 1999 01:53:03 +0000 (01:53 +0000)
committerThomas Roessler <roessler@does-not-exist.org>
Wed, 13 Jan 1999 01:53:03 +0000 (01:53 +0000)
it's optional. ;-)

19 files changed:
Makefile.am
OPS.MIX [new file with mode: 0644]
acconfig.h
compose.c
configure.in
functions.h
globals.h
headers.c
init.h
keymap.c
keymap.h
lib.c
mutt.h
postpone.c
protos.h
remailer.c [new file with mode: 0644]
remailer.h [new file with mode: 0644]
send.c
sendlib.c

index fc340a9bc1aa201be0ce4d1440cad357b2e455d5..054889779f5ff1bafb0440bee317c05d24e35656 100644 (file)
@@ -24,10 +24,12 @@ INCLUDES=-I. -I$(includedir)
 
 non_us_sources = pgp.c pgpinvoke.c pgpkey.c pgppubring.c sha1dgst.c \
        gnupgparse.c sha.h sha_locl.h \
-       doc/language.txt doc/language50.txt OPS.PGP doc/PGP-Notes
+       doc/language.txt doc/language50.txt OPS.PGP doc/PGP-Notes \
+       OPS.MIX remailer.c remailer.h
 
 EXTRA_mutt_SOURCES = pgp.c pgpinvoke.c pgpkey.c pgppubring.c sha1dgst.c \
        gnupgparse.c resize.c dotlock.c pop.c imap.c socket.c
+       remailer.c remailer.h
 
 EXTRA_DIST = COPYRIGHT GPL OPS OPS.PGP TODO configure acconfig.h attach.h \
        buffy.h charset.h config.h copy.h dotlock.h functions.h gen_defs \
@@ -35,7 +37,7 @@ EXTRA_DIST = COPYRIGHT GPL OPS OPS.PGP TODO configure acconfig.h attach.h \
        mailbox.h mapping.h mime.h mutt.h mutt_curses.h mutt_menu.h  \
        mutt_regex.h mutt_socket.h mx.h pager.h parse.h pgp.h protos.h  \
        reldate.h rfc1524.h rfc2047.h rfc822.h sha.h sha_locl.h \
-       sort.h mime.types VERSION prepare _regex.h
+       sort.h mime.types VERSION prepare _regex.h OPS.MIX
 
 BUILT_SOURCES = mutt_dotlock.c keymap_defs.h
 
@@ -54,7 +56,7 @@ LDADD = @LIBOBJS@ @INTLLIBS@
 
 SUBDIRS = doc intl m4 po contrib
 
-OPS=$(srcdir)/OPS $(srcdir)/OPS.PGP
+OPS=@OPS@
 
 keymap_defs.h: $(OPS) $(srcdir)/gen_defs
        $(srcdir)/gen_defs $(OPS) > keymap_defs.h
@@ -108,7 +110,7 @@ us-distdir: distdir dist-hook
 
 us-dist: us-distdir
        for file in $(distdir)-us/*.c $(distdir)-us/*.h ; do \
-               $(srcdir)/reap.pl _PGPPATH < $$file > $$file.n && rm $$file && mv $$file.n $$file ; \
+               $(srcdir)/reap.pl _PGPPATH < $$file | $(srcdir)/reap.pl MIXMASTER > $$file.n && rm $$file && mv $$file.n $$file ; \
        done
        for file in $(non_us_sources) ; do \
                echo "/* This file is only available in the international mutt version */" \
diff --git a/OPS.MIX b/OPS.MIX
new file mode 100644 (file)
index 0000000..4988333
--- /dev/null
+++ b/OPS.MIX
@@ -0,0 +1,7 @@
+OP_MIX_USE "Accept the chain constructed"
+OP_MIX_APPEND "Append a remailer to the chain"
+OP_MIX_INSERT "Insert a remailer into the chain"
+OP_MIX_DELETE "Delete a remailer from the chain"
+OP_MIX_CHAIN_PREV "Select the previous element of the chain"
+OP_MIX_CHAIN_NEXT "Select the next element of the chain"
+OP_COMPOSE_MIX "send the message through a mixmaster remailer chain"
index 59b7633fb08939cca698d1bef75ca7833fa17fd6..9c5f50749ba73817d8a3201e880be4443451131e 100644 (file)
 
 /* Use the included regex.c? */
 #undef USE_GNU_REGEX
+
+/* Where's mixmaster located? */
+#undef MIXMASTER
index ea0f5b20709ba9057985eb0f108034a1c7176193..1aacf75948768f4da780568c80f35d4521fe435f 100644 (file)
--- a/compose.c
+++ b/compose.c
 #include "mailbox.h"
 #include "sort.h"
 
+#ifdef MIXMASTER
+#include "remailer.h"
+#endif
+
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
@@ -46,13 +50,15 @@ enum
   HDR_REPLYTO,
   HDR_FCC,
 
+#ifdef MIXMASTER
+  HDR_MIX,
+#endif
 
 #ifdef _PGPPATH
   HDR_PGP,
   HDR_PGPSIGINFO,
 #endif
   
-  
 
   HDR_ATTACH  = (HDR_FCC + 5) /* where to start printing the attachments */
 };
@@ -214,7 +220,35 @@ static int pgp_send_menu (int bits, int *redraw)
 }
 #endif /* _PGPPATH */
 
+#ifdef MIXMASTER
+
+static void redraw_mix_line (LIST *chain)
+{
+  int c;
+
+  mvaddstr (HDR_MIX, 0,     "     Mix: ");
+
+  if (!chain)
+  {
+    addstr ("no");
+    clrtoeol ();
+    return;
+  }
+  
+  for (c = 12; chain; chain = chain->next)
+  {
+    if (c + mutt_strlen ((char *) chain->data) + 2 >= COLS)
+      break;
+
+    
+    addstr (NONULL((char *) chain->data));
+    if (chain->next)
+      addstr (", ");
 
+    c += mutt_strlen ((char *) chain->data) + 2;
+  }
+}
+#endif
 
 static int
 check_attachments(ATTACHPTR **idx, short idxlen)
@@ -276,9 +310,17 @@ static void draw_envelope (HEADER *msg, char *fcc)
   redraw_pgp_lines (msg->pgp);
 #endif /* _PGPPATH */
 
+#ifdef MIXMASTER
+  redraw_mix_line (msg->chain);
+#endif
 
+  SETCOLOR (MT_COLOR_STATUS);
+  mvaddstr (HDR_ATTACH - 1, 0, _("-- Attachments"));
+  BKGDSET (MT_COLOR_STATUS);
+  clrtoeol ();
 
-  mvaddstr (HDR_ATTACH - 1, 0, _("===== Attachments ====="));
+  BKGDSET (MT_COLOR_NORMAL);
+  SETCOLOR (MT_COLOR_NORMAL);
 }
 
 static int edit_address_list (int line, ADDRESS **addr)
@@ -779,6 +821,12 @@ int mutt_compose_menu (HEADER *msg,   /* structure for new message */
          menu->redraw = REDRAW_FULL;
          break;
        }
+
+      
+#ifdef MIXMASTER
+        if (mix_check_message (msg) != 0)
+         break;
+#endif
       
        if (!fccSet && *fcc)
        {
@@ -987,7 +1035,7 @@ int mutt_compose_menu (HEADER *msg,   /* structure for new message */
        /* fall through to postpone! */
 
       case OP_COMPOSE_POSTPONE_MESSAGE:
-      
+
         if(check_attachments(idx, idxlen) != 0)
         {
          menu->redraw = REDRAW_FULL;
@@ -1050,7 +1098,12 @@ int mutt_compose_menu (HEADER *msg,   /* structure for new message */
 
 #endif /* _PGPPATH */
 
-
+#ifdef MIXMASTER
+      case OP_COMPOSE_MIX:
+      
+       mix_make_chain (&msg->chain, &menu->redraw);
+        break;
+#endif
 
     }
   }
index 73f522efcc7ab368658cb21905f3cbd759d34c64..08bbc8675f2506b1b631bd8bfabb6bea6f1a51b5 100644 (file)
@@ -80,6 +80,18 @@ else
                MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS pgp.o pgpinvoke.o pgpkey.o pgppubring.o sha1dgst.o gnupgparse.o"
                OPS="$OPS \$(srcdir)/OPS.PGP"
        fi
+       
+       AC_ARG_WITH(mixmaster, [  --with-mixmaster[=PATH]       include Mixmaster support],
+               [if test -x "$withval" ; then
+                       MIXMASTER="$withval"
+                else
+                       MIXMASTER="mixmaster"
+                fi
+                OPS="$OPS \$(srcdir)/OPS.MIX"
+                MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS remailer.o"
+                AC_DEFINE_UNQUOTED(MIXMASTER, "$MIXMASTER")
+                ])
+               
 fi
 AC_SUBST(OPS)
 
index e2f3e4a88f12705949ca28cc14ea386f1023fdae..e8162819da46ae87b376fb2127bbd4f6237b0114 100644 (file)
@@ -296,6 +296,10 @@ struct binding_t OpCompose[] = {
   { "pgp-menu",                OP_COMPOSE_PGP_MENU,            "p"     },
 #endif
 
+#ifdef MIXMASTER
+  { "mix",             OP_COMPOSE_MIX,                 "M" },
+#endif
+  
   { NULL,              0,                              NULL }
 };
 
@@ -356,3 +360,16 @@ struct binding_t OpPgp[] = {
   { NULL,              0,                              NULL }
 };
 #endif /* _PGPPATH */
+
+
+#ifdef MIXMASTER
+struct binding_t OpMix[] = {
+  { "accept",          OP_MIX_USE,     M_ENTER_S },
+  { "append",          OP_MIX_APPEND,  "a"       },
+  { "insert",          OP_MIX_INSERT,  "i"       },
+  { "delete",          OP_MIX_DELETE,  "d"       },
+  { "chain-prev",      OP_MIX_CHAIN_PREV, "<left>" },
+  { "chain-next",      OP_MIX_CHAIN_NEXT, "<right>" },
+  { NULL,              0,              NULL }
+};
+#endif /* MIXMASTER */
index 5ce9deed569f2864097a0de79da47f77a4689188..18f108ec7fd16445d4a7b1df98de84c8094be80d 100644 (file)
--- a/globals.h
+++ b/globals.h
@@ -52,6 +52,11 @@ WHERE char *Locale;
 WHERE char *MailcapPath;
 WHERE char *Maildir;
 WHERE char *MsgFmt;
+
+#ifdef MIXMASTER
+WHERE char *Mixmaster;
+#endif
+
 WHERE char *Muttrc INITVAL (NULL);
 WHERE char *Outbox;
 WHERE char *Pager;
index f1a569d2764f30b1b7b2d7bfaf46bf7bbaca179b..a45d2d3f95d1eac7bec29dd481e74b0cebea2430 100644 (file)
--- a/headers.c
+++ b/headers.c
 
 #include "mutt.h"
 
-
-
 #ifdef _PGPPATH
 #include "pgp.h"
 #endif
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 #include <sys/stat.h>
 #include <string.h>
 #include <ctype.h>
@@ -90,7 +50,7 @@ void mutt_edit_headers (const char *editor,
     return;
   }
 
-  mutt_write_rfc822_header (ofp, msg->env, NULL, 1);
+  mutt_write_rfc822_header (ofp, msg->env, NULL, 1, 0);
   fputc ('\n', ofp);   /* tie off the header. */
 
   /* now copy the body of the message. */
diff --git a/init.h b/init.h
index 9edc74cd577e3cbdb03d8f5e17e20fdad9a7539a..0513e52da09cfb630d6d11937c87924b2890b125 100644 (file)
--- a/init.h
+++ b/init.h
@@ -150,6 +150,13 @@ struct option_t MuttVars[] = {
   { "mime_forward",    DT_QUAD, R_NONE, OPT_MIMEFWD, M_NO },
   { "mime_forward_decode", DT_BOOL, R_NONE, OPTMIMEFORWDECODE, 0 },
   { "mime_fwd",                DT_SYN,  R_NONE, UL "mime_forward", 0 },
+
+
+#ifdef MIXMASTER
+  { "mixmaster",       DT_PATH, R_NONE, UL &Mixmaster, UL MIXMASTER },
+#endif
+
+
   { "move",            DT_QUAD, R_NONE, OPT_MOVE, M_ASKNO },
   { "message_format",  DT_STR,  R_NONE, UL &MsgFmt, UL "%s" },
   { "msg_format",      DT_SYN,  R_NONE, UL "message_format", 0 },
index 943ce54f41c161d08c5c7f568f0b698aee86ca60..9281cb54707cb4902b6d276921ff6b0cb2addd1d 100644 (file)
--- a/keymap.c
+++ b/keymap.c
@@ -39,12 +39,14 @@ struct mapping_t Menus[] = {
  { "pager",    MENU_PAGER },
  { "postpone", MENU_POST },
 
-  
 
 #ifdef _PGPPATH
  { "pgp",      MENU_PGP },
 #endif  
   
+#ifdef MIXMASTER
+  { "mix",     MENU_MIX },
+#endif
   
 
  { "query",    MENU_QUERY },
@@ -533,7 +535,13 @@ void km_init (void)
   create_bindings (OpPgp, MENU_PGP);
 #endif
 
-
+#ifdef MIXMASTER
+  create_bindings (OpMix, MENU_MIX);
+  
+  km_bindkey ("<space>", MENU_MIX, OP_GENERIC_SELECT_ENTRY);
+  km_bindkey ("h", MENU_MIX, OP_MIX_CHAIN_PREV);
+  km_bindkey ("l", MENU_MIX, OP_MIX_CHAIN_NEXT);
+#endif
   
   /* bindings for the line editor */
   create_bindings (OpEditor, MENU_EDITOR);
@@ -728,6 +736,10 @@ struct binding_t *km_get_table (int menu)
 #endif
 
 
+#ifdef MIXMASTER
+    case MENU_MIX:
+      return OpMix;
+#endif
 
   }
   return NULL;
index 7ec44a5c9b081d7d0ffd25ca7a467711a0aa3fa8..c361e29a0e4909610f1d4d1ed356f51f2ffd1dcf 100644 (file)
--- a/keymap.h
+++ b/keymap.h
@@ -58,16 +58,19 @@ enum
   MENU_MAIN,
   MENU_PAGER,
   MENU_POST,
+  MENU_QUERY,
 
+  
 #ifdef _PGPPATH
   MENU_PGP,
 #endif
 
+#ifdef MIXMASTER
+  MENU_MIX,
+#endif
 
 
 
-
-  MENU_QUERY,
   MENU_MAX
 };
 
@@ -102,6 +105,10 @@ extern struct binding_t OpQuery[];
 extern struct binding_t OpPgp[];
 #endif /* _PGPPATH */
 
+#ifdef MIXMASTER
+extern struct binding_t OpMix[];
+#endif
+
 #include "keymap_defs.h"
 
 #endif /* KEYMAP_H */
diff --git a/lib.c b/lib.c
index 4488f268cff826ff7958c57301d5e07761e9336b..4653e97727b77ead46f4972fba8413309109ebee 100644 (file)
--- a/lib.c
+++ b/lib.c
@@ -155,6 +155,9 @@ void mutt_free_header (HEADER **h)
   mutt_free_body (&(*h)->content);
   safe_free ((void **) &(*h)->tree);
   safe_free ((void **) &(*h)->path);
+#ifdef MIXMASTER
+  mutt_free_list (&(*h)->chain);
+#endif
   safe_free ((void **) h);
 }
 
diff --git a/mutt.h b/mutt.h
index 2b78e2625faaf804594f028357653882b78e1677..d9f3514944a737611cf7a205d7a17f31f97d9d65 100644 (file)
--- a/mutt.h
+++ b/mutt.h
 # define N_(a) a
 #endif
 
+#ifdef MIXMASTER
+# include "remailer.h"
+#endif
+
 #ifdef SUBVERSION
 # define MUTT_VERSION (VERSION SUBVERSION)
 #else  
@@ -575,6 +579,10 @@ typedef struct header
   struct header *last_sort; /* last message in subthread, for secondary SORT_LAST */
   char *tree;            /* character string to print thread tree */
 
+#ifdef MIXMASTER
+  LIST *chain;
+#endif
+  
 } HEADER;
 
 #include "mutt_regex.h"
index bc172c2bb08ad72e5007d032d4d8d6cb778e27b1..74cda2683bec51eaf17f55e0a0ef1d6c0940dfbd 100644 (file)
@@ -273,7 +273,10 @@ int mutt_get_postponed (CONTEXT *ctx, HEADER *hdr, HEADER **cur, char *fcc, size
 
 
 #ifdef _PGPPATH
-    else if (mutt_strncmp ("Pgp:", tmp->data, 4) == 0)
+    else if (mutt_strncmp ("Pgp:", tmp->data, 4) == 0 /* this is generated
+                                                      * by old mutt versions
+                                                      */
+            || mutt_strncmp ("X-Mutt-PGP:", tmp->data, 11) == 0)
     {
       hdr->pgp = mutt_parse_pgp_hdr (tmp->data+4, 1);
        
@@ -289,7 +292,29 @@ int mutt_get_postponed (CONTEXT *ctx, HEADER *hdr, HEADER **cur, char *fcc, size
     }
 #endif /* _PGPPATH */
 
-
+#ifdef MIXMASTER
+    else if (mutt_strncmp ("X-Mutt-Mix:", tmp->data, 11) == 0)
+    {
+      char *t;
+      mutt_free_list (&hdr->chain);
+      
+      t = strtok (tmp->data + 11, " \t\n");
+      while (t)
+      {
+       hdr->chain = mutt_add_list (hdr->chain, t);
+       t = strtok (NULL, " \t\n");
+      }
+      
+      next = tmp->next;
+      if (last) 
+       last->next = tmp->next;
+      else
+       hdr->env->userhdrs = tmp->next;
+      tmp->next = NULL;
+      mutt_free_list (&tmp);
+      tmp = next;
+    }
+#endif
 
     else
     {
index 5c8ce63597efd11d83a591839fca9c0a0f09edbe..96142c26e63e3dbd28fdb80d7a7b6045bf5ec42e 100644 (file)
--- a/protos.h
+++ b/protos.h
@@ -277,7 +277,7 @@ int mutt_which_case (const char *);
 int mutt_write_fcc (const char *path, HEADER *hdr, const char *msgid, int, char *);
 int mutt_write_mime_body (BODY *, FILE *);
 int mutt_write_mime_header (BODY *, FILE *);
-int mutt_write_rfc822_header (FILE *, ENVELOPE *, BODY *, int);
+int mutt_write_rfc822_header (FILE *, ENVELOPE *, BODY *, int, int);
 int mutt_yesorno (const char *, int);
 void mutt_set_header_color(CONTEXT *, HEADER *);
 int mutt_save_confirm (const char  *, struct stat *);
@@ -432,3 +432,16 @@ int ioctl (int, int, ...);
 /* unsorted */
 void ci_bounce_message (HEADER *, int *);
 void ci_send_message (int, HEADER *, char *, CONTEXT *, HEADER *);
+
+
+
+#ifdef MIXMASTER
+/* mixmaster support - must go here so we get the
+ * type definitions in the right order.
+ */
+
+
+int mix_send_message (LIST *, const char *);
+int mix_check_message (HEADER *msg);
+void mix_make_chain (LIST **, int *);
+#endif
diff --git a/remailer.c b/remailer.c
new file mode 100644 (file)
index 0000000..f216b9a
--- /dev/null
@@ -0,0 +1,683 @@
+/*
+ * Copyright (C) 1999   Thomas Roessler <roessler@guug.de>
+ * 
+ *     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., 675 Mass Ave, Cambridge, MA
+ *     02139, USA.
+ */ 
+
+/*
+ * Mixmaster support for Mutt
+ */
+
+#include "mutt.h"
+#include "mutt_curses.h"
+#include "mutt_menu.h"
+#include "mapping.h"
+
+#include "remailer.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <fcntl.h>
+
+#ifdef MIXMASTER
+
+struct coord
+{
+  short r, c;
+};
+
+static REMAILER **mix_type2_list (size_t *l);
+static REMAILER *mix_new_remailer (void);
+static const char *mix_format_caps (REMAILER *r);
+static int mix_get_caps (const char *capstr);
+static void mix_add_entry (REMAILER ***, REMAILER *, size_t *, size_t *);
+static int mix_chain_add (MIXCHAIN *chain, const char *s, REMAILER **type2_list);
+static void mix_entry (char *b, size_t blen, MUTTMENU *menu, int num);
+static void mix_free_remailer (REMAILER **r);
+static void mix_free_type2_list (REMAILER ***ttlp);
+static void mix_redraw_ce (REMAILER **type2_list, struct coord *coords, MIXCHAIN *chain, int i, short selected);
+static void mix_redraw_chain (REMAILER **type2_list, struct coord *coords, MIXCHAIN *chain, int cur);
+static void mix_redraw_head (MIXCHAIN *);
+static void mix_screen_coordinates (REMAILER **type2_list, struct coord **, MIXCHAIN *, int);
+
+static int mix_get_caps (const char *capstr)
+{
+  int caps = 0;
+
+  while (*capstr)
+  {
+    switch (*capstr)
+    {
+      case 'C':
+       caps |= MIX_CAP_COMPRESS;
+        break;
+      
+      case 'M':
+        caps |= MIX_CAP_MIDDLEMAN;
+        break;
+      
+      case 'N':
+      {
+       switch (*++capstr)
+       {
+         case 'm':
+           caps |= MIX_CAP_NEWSMAIL;
+           break;
+         
+         case 'p':
+           caps |= MIX_CAP_NEWSPOST;
+           break;
+         
+       }
+      }
+    }
+    
+    if (*capstr) capstr++;
+  }
+  
+  return caps;
+}
+
+static void mix_add_entry (REMAILER ***type2_list, REMAILER *entry,
+                          size_t *slots, size_t *used)
+{
+  if (*used == *slots)
+  {
+    *slots += 5;
+    safe_realloc ((void **) type2_list, sizeof (REMAILER *) * (*slots));
+  }
+  
+  (*type2_list)[(*used)++] = entry;
+}
+
+static REMAILER *mix_new_remailer (void)
+{
+  return safe_calloc (1, sizeof (REMAILER));
+}
+
+static void mix_free_remailer (REMAILER **r)
+{
+  safe_free ((void **) &(*r)->shortname);
+  safe_free ((void **) &(*r)->addr);
+  safe_free ((void **) &(*r)->ver);
+  
+  safe_free ((void **) r);
+}
+
+/* parse the type2.list as given by mixmaster -T */
+
+static REMAILER **mix_type2_list (size_t *l)
+{
+  FILE *fp;
+  pid_t mm_pid;
+  int devnull;
+
+  char cmd[HUGE_STRING + _POSIX_PATH_MAX];
+  char line[HUGE_STRING];
+  char *t;
+  
+  REMAILER **type2_list = NULL, *p;
+  size_t slots = 0, used = 0;
+
+  if (!l)
+    return NULL;
+  
+  if ((devnull = open ("/dev/null", O_RDWR)) == -1)
+    return NULL;
+  
+  snprintf (cmd, sizeof (cmd), "%s -T", Mixmaster);
+  
+  if ((mm_pid = mutt_create_filter_fd (cmd, NULL, &fp, NULL, devnull, -1, devnull)) == -1)
+  {
+    close (devnull);
+    return NULL;
+  }
+
+  /* first, generate the "random" remailer */
+  
+  p = mix_new_remailer ();
+  p->shortname = safe_strdup ("<random>");
+  mix_add_entry (&type2_list, p, &slots, &used);
+  
+  while (fgets (line, sizeof (line), fp))
+  {
+    p = mix_new_remailer ();
+    
+    if (!(t = strtok (line, " \t\n")))
+      goto problem;
+    
+    p->shortname = safe_strdup (t);
+    
+    if (!(t = strtok (NULL, " \t\n")))
+      goto problem;
+
+    p->addr = safe_strdup (t);
+    
+    if (!(t = strtok (NULL, " \t\n")))
+      goto problem;
+
+    if (!(t = strtok (NULL, " \t\n")))
+      goto problem;
+
+    p->ver = safe_strdup (t);
+    
+    if (!(t = strtok (NULL, " \t\n")))
+      goto problem;
+
+    p->caps = mix_get_caps (t);
+    
+    mix_add_entry (&type2_list, p, &slots, &used);
+    continue;
+    
+    problem:
+    mix_free_remailer (&p);
+  }
+  
+  *l = used;
+
+  mix_add_entry (&type2_list, NULL, &slots, &used);
+  mutt_wait_filter (mm_pid);
+
+  close (devnull);
+  
+  return type2_list;
+}
+
+static void mix_free_type2_list (REMAILER ***ttlp)
+{
+  int i;
+  REMAILER **type2_list = *ttlp;
+  
+  for (i = 0; type2_list[i]; i++)
+    mix_free_remailer (&type2_list[i]);
+  
+  safe_free ((void **) type2_list);
+}
+
+
+#define MIX_HOFFSET 2
+#define MIX_VOFFSET (LINES - 6)
+#define MIX_MAXROW  (LINES - 3)
+
+
+static void mix_screen_coordinates (REMAILER **type2_list,
+                                   struct coord **coordsp,
+                                   MIXCHAIN *chain,
+                                   int i)
+{
+  short c, r, oc;
+  struct coord *coords;
+
+  if (!chain->cl)
+    return;
+  
+  safe_realloc ((void **) coordsp, sizeof (struct coord) * chain->cl);
+  
+  coords = *coordsp;
+  
+  if (i)
+  {
+    c = coords[i-1].c + strlen (type2_list[chain->ch[i-1]]->shortname) + 2;
+    r = coords[i-1].r;
+  }
+  else
+  {
+    r = MIX_VOFFSET;
+    c = MIX_HOFFSET;
+  }
+    
+  
+  for (; i < chain->cl; i++)
+  {
+    oc = c;
+    c += strlen (type2_list[chain->ch[i]]->shortname) + 2;
+
+    if (c  >= COLS)
+    {
+      oc = c = MIX_HOFFSET;
+      r++;
+    }
+    
+    coords[i].c = oc;
+    coords[i].r = r;
+    
+  }
+  
+}
+
+static void mix_redraw_ce (REMAILER **type2_list,
+                          struct coord *coords,
+                          MIXCHAIN *chain,
+                          int i,
+                          short selected)
+{
+  if (!coords || !chain)
+    return;
+  
+  if (coords[i].r < MIX_MAXROW)
+  {
+    
+    if (selected)
+      SETCOLOR (MT_COLOR_INDICATOR);
+    else
+      SETCOLOR (MT_COLOR_NORMAL);
+    
+    mvaddstr (coords[i].r, coords[i].c, type2_list[chain->ch[i]]->shortname);
+    SETCOLOR (MT_COLOR_NORMAL);
+
+    if (i + 1 < chain->cl)
+      addstr (", ");
+  }
+}
+
+static void mix_redraw_chain (REMAILER **type2_list,
+                             struct coord *coords,
+                             MIXCHAIN *chain,
+                             int cur)
+{
+  int i;
+  
+  SETCOLOR (MT_COLOR_NORMAL);
+  BKGDSET (MT_COLOR_NORMAL);
+  
+  for (i = MIX_VOFFSET; i < MIX_MAXROW; i++)
+  {
+    move (i, 0);
+    clrtoeol ();
+  }
+
+  for (i = 0; i < chain->cl; i++)
+    mix_redraw_ce (type2_list, coords, chain, i, i == cur);
+}
+
+static void mix_redraw_head (MIXCHAIN *chain)
+{
+  SETCOLOR (MT_COLOR_STATUS);
+  mvprintw (MIX_VOFFSET - 1, 0, "-- Remailer chain [Length: %d]", chain ? chain->cl : 0);
+  
+  BKGDSET (MT_COLOR_STATUS);
+  clrtoeol ();
+  
+  BKGDSET (MT_COLOR_NORMAL);
+  SETCOLOR (MT_COLOR_NORMAL);
+}
+
+static const char *mix_format_caps (REMAILER *r)
+{
+  static char capbuff[10];
+  char *t = capbuff;
+  
+  if (r->caps & MIX_CAP_COMPRESS)
+    *t++ = 'C';
+  else
+    *t++ = ' ';
+  
+  if (r->caps & MIX_CAP_MIDDLEMAN)
+    *t++ = 'M';
+  else
+    *t++ = ' ';
+  
+  if (r->caps & MIX_CAP_NEWSPOST)
+  {
+    *t++ = 'N';
+    *t++ = 'p';
+  }
+  else
+  {
+    *t++ = ' ';
+    *t++ = ' ';
+  }
+   
+  if (r->caps & MIX_CAP_NEWSMAIL)
+  {
+    *t++ = 'N';
+    *t++ = 'm';
+  }
+  else
+  {
+    *t++ = ' ';
+    *t++ = ' ';
+  }
+  
+  *t = '\0';
+  
+  return capbuff;
+}
+  
+  
+static void mix_entry (char *b, size_t blen, MUTTMENU *menu, int num)
+{
+  REMAILER **type2_list = (REMAILER **) menu->data;
+  snprintf (b, blen, "%4d %s    %-16s %s",
+           num + 1, mix_format_caps (type2_list[num]),
+           NONULL (type2_list[num]->shortname),
+           NONULL (type2_list[num]->addr));
+}
+
+static int mix_chain_add (MIXCHAIN *chain, const char *s, 
+                         REMAILER **type2_list)
+{
+  int i;
+  
+  if (chain->cl >= MAXMIXES)
+    return -1;
+  
+  if (!mutt_strcmp (s, "0") || !mutt_strcasecmp (s, "<random>"))
+  {
+    chain->ch[chain->cl++] = 0;
+    return 0;
+  }
+
+  for (i = 0; type2_list[i]; i++)
+  {
+    if (!mutt_strcasecmp (s, type2_list[i]->shortname))
+    {
+      chain->ch[chain->cl++] = i;
+      return 0;
+    }
+  }
+  
+  /* replace unknown remailers by <random> */
+  
+  if (!type2_list[i])
+    chain->ch[chain->cl++] = 0;
+
+  return 0;
+}
+
+static struct mapping_t RemailerHelp[] = 
+{
+  { N_("Append"), OP_MIX_APPEND },
+  { N_("Insert"), OP_MIX_INSERT },
+  { N_("Delete"), OP_MIX_DELETE },
+  { N_("Abort"),  OP_EXIT       },
+  { N_("OK"),     OP_MIX_USE    },
+  { NULL }
+};
+  
+
+void mix_make_chain (LIST **chainp, int *redraw)
+{
+  LIST *p;
+  MIXCHAIN *chain;
+  int c_cur = 0, c_old = 0;
+  int m_len;
+  short c_redraw = 1;
+  
+  REMAILER **type2_list = NULL;
+  size_t ttll = 0;
+  
+  struct coord *coords = NULL;
+  
+  MUTTMENU *menu;
+  char helpstr[SHORT_STRING];
+  short loop = 1;
+  int op;
+  
+  int i, j;
+  char *t;
+
+  if (!(type2_list = mix_type2_list (&ttll)))
+  {
+    mutt_error _("Can't get mixmaster's type2.list!");
+    return;
+  }
+
+  *redraw = REDRAW_FULL;
+  
+  chain = safe_calloc (sizeof (MIXCHAIN), 1);
+  for (p = *chainp; p; p = p->next)
+    mix_chain_add (chain, (char *) p->data, type2_list);
+
+  mutt_free_list (chainp);
+  
+  /* safety check */
+  for (i = 0; i < chain->cl; i++)
+  {
+    if (chain->ch[i] >= ttll)
+      chain->ch[i] = 0;
+  }
+  
+  mix_screen_coordinates (type2_list, &coords, chain, 0);
+  
+  menu = mutt_new_menu ();
+  menu->menu = MENU_MIX;
+  menu->max = ttll;
+  menu->make_entry = mix_entry;
+  menu->tag = NULL;
+  menu->title = _("Select a remailer chain.");
+  menu->data = type2_list;
+  menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MIX, RemailerHelp);
+
+  m_len = menu->pagelen = MIX_VOFFSET - menu->offset - 1;
+  
+  while (loop) 
+  {
+    if (menu->pagelen != m_len)
+    {
+      menu->pagelen = m_len;
+      menu->redraw = REDRAW_FULL;
+    }
+    
+    if (c_redraw)
+    {
+      mix_redraw_head (chain);
+      mix_redraw_chain (type2_list, coords, chain, c_cur);
+      c_redraw = 0;
+    }
+    else if (c_cur != c_old)
+    {
+      mix_redraw_ce (type2_list, coords, chain, c_old, 0);
+      mix_redraw_ce (type2_list, coords, chain, c_cur, 1);
+    }
+    
+    c_old = c_cur;
+    
+    switch ((op = mutt_menuLoop (menu)))
+    {
+      case OP_REDRAW:
+      {
+       menu_redraw_status (menu);
+       mix_redraw_head (chain);
+       mix_screen_coordinates (type2_list, &coords, chain, 0);
+       mix_redraw_chain (type2_list, coords, chain, c_cur);
+       menu->pagelen = m_len = MIX_VOFFSET - menu->offset - 1;
+       break;
+      }
+      
+      case OP_EXIT:
+      {
+       chain->cl = 0;
+       loop = 0;
+       break;
+      }
+
+      case OP_MIX_USE:
+      {
+       if (chain->cl && chain->ch[chain->cl - 1] && 
+           (type2_list[chain->ch[chain->cl-1]]->caps & MIX_CAP_MIDDLEMAN))
+       {
+         char buff[SHORT_STRING];
+         
+         snprintf (buff, sizeof (buff), _("Error: %s can't be used as the final remailer of a chain."),
+                   type2_list[chain->ch[chain->cl - 1]]->shortname);
+         mutt_error (buff);
+       }
+       else
+       {
+         loop = 0;
+       }
+       break;
+      }
+
+      case OP_GENERIC_SELECT_ENTRY:
+      case OP_MIX_APPEND:
+      {
+       if (chain->cl < MAXMIXES)
+       {
+         c_cur = chain->cl++;
+         chain->ch[c_cur] = menu->current;
+         mix_screen_coordinates (type2_list, &coords, chain, c_cur);
+         c_redraw = 1;
+       }
+       else
+       {
+         char buff[SHORT_STRING];
+         snprintf (buff, sizeof (buff), _("Mixmaster chains are limited to %d elements."),
+                   MAXMIXES);
+         mutt_error (buff);
+       }
+       break;
+      }
+      
+      case OP_MIX_INSERT:
+      {
+       if (chain->cl < MAXMIXES)
+       {
+         chain->cl++;
+         for (i = chain->cl - 1; i > c_cur; i--)
+           chain->ch[i] = chain->ch[i-1];
+         
+         chain->ch[c_cur] = menu->current;
+         mix_screen_coordinates (type2_list, &coords, chain, c_cur);
+         c_redraw = 1;
+       }
+       else
+       {
+         char buff[SHORT_STRING];
+         snprintf (buff, sizeof (buff), _("Mixmaster chains are limited to %d elements."),
+                   MAXMIXES);
+         mutt_error (buff);
+       }
+       
+       break;
+      }
+      
+      case OP_MIX_DELETE:
+      {
+       if (chain->cl)
+       {
+         chain->cl--;
+         
+         for (i = c_cur; i < chain->cl; i++)
+           chain->ch[i] = chain->ch[i+1];
+
+         if (c_cur == chain->cl && c_cur)
+           c_cur--;
+         
+         mix_screen_coordinates (type2_list, &coords, chain, c_cur);
+         c_redraw = 1;
+       }
+       else
+       {
+         mutt_error _("The remailer chain is already empty.");
+       }
+       break;
+      }
+      
+      case OP_MIX_CHAIN_PREV:
+      {
+       if (c_cur) 
+         c_cur--;
+       else
+         mutt_error _("You already have the first chain element selected.");
+       
+       break;
+      }
+      
+      case OP_MIX_CHAIN_NEXT:
+      {
+       if (chain->cl && c_cur < chain->cl - 1)
+         c_cur++;
+       else
+         mutt_error _("You already have the last chain element selected.");
+       
+       break;
+      }
+    }
+  }
+  
+  mutt_menuDestroy (&menu);
+
+  /* construct the remailer list */
+  
+  if (chain->cl)
+  {
+    for (i = 0; i < chain->cl; i++)
+    {
+      if ((j = chain->ch[i]))
+       t = type2_list[j]->shortname;
+      else
+       t = "0";
+      
+      *chainp = mutt_add_list (*chainp, t);
+    }
+  }
+  
+  mix_free_type2_list (&type2_list);
+  safe_free ((void **) &coords);
+  safe_free ((void **) &chain);
+}
+
+int mix_check_message (HEADER *msg)
+{
+  if (msg->env->cc || msg->env->bcc)
+  {
+    mutt_error _("Mixmaster doesn't accept Cc or Bcc headers.");
+    return -1;
+  }
+  
+  return 0;
+}
+
+int mix_send_message (LIST *chain, const char *tempfile)
+{
+  char cmd[HUGE_STRING];
+  char tmp[HUGE_STRING];
+  int i;
+
+  snprintf (cmd, sizeof (cmd), "cat %s | %s -m -l", tempfile, Mixmaster);
+  for (; chain; chain = chain->next)
+  {
+    strfcpy (tmp, cmd, sizeof (tmp));
+    snprintf (cmd, sizeof (cmd), "%s %s", tmp, (char *) chain->data);
+  }
+  
+  if (!option (OPTNOCURSES))
+    endwin ();
+  
+  if ((i = mutt_system (cmd)))
+  {
+    fprintf (stderr, _("Error sending message, child exited %d.\n"), i);
+    if (!option (OPTNOCURSES))
+    {
+      mutt_any_key_to_continue (NULL);
+      mutt_error _("Error sending message.");
+    }
+  }
+
+  unlink (tempfile);
+  return i;
+}
+  
+
+#endif
diff --git a/remailer.h b/remailer.h
new file mode 100644 (file)
index 0000000..57050ec
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef _REMAILER_H
+#define _REMAILER_H
+
+/*
+ * Copyright (C) 1999   Thomas Roessler <roessler@guug.de>
+ * 
+ *     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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */ 
+
+/*
+ * Mixmaster support for Mutt
+ */
+
+#include "config.h"
+
+#ifdef MIXMASTER
+
+#define MIX_CAP_COMPRESS  (1 << 0)
+#define MIX_CAP_MIDDLEMAN (1 << 1)
+#define MIX_CAP_NEWSPOST  (1 << 2)
+#define MIX_CAP_NEWSMAIL  (1 << 3)
+
+/* Mixmaster's maximum chain length.  Don't change this. */
+
+#define MAXMIXES 20
+
+struct type2
+{
+  char *shortname;
+  char *addr;
+  char *ver;
+  int caps;
+};
+
+typedef struct type2 REMAILER;
+
+
+struct mixchain
+{
+  size_t cl;
+  int ch[MAXMIXES];
+};
+
+typedef struct mixchain MIXCHAIN;
+
+/* function prototypes are in protos.h */
+
+#endif /* MIXMASTER */
+
+#endif /* _REMAILER_H */
diff --git a/send.c b/send.c
index c29d71d0c711901aee6fe84cbf55b919eddb1824..c9fded20424e2146144fe1883b7c540d8ad68a25 100644 (file)
--- a/send.c
+++ b/send.c
@@ -799,7 +799,13 @@ static int send_message (HEADER *msg)
   if ((tempfp = safe_fopen (tempfile, "w")) == NULL)
     return (-1);
 
-  mutt_write_rfc822_header (tempfp, msg->env, msg->content, 0);
+#ifdef MIXMASTER
+  mutt_write_rfc822_header (tempfp, msg->env, msg->content, 0, msg->chain ? 1 : 0);
+#endif
+#ifndef MIXMASTER
+  mutt_write_rfc822_header (tempfp, msg->env, msg->content, 0, 0);
+#endif
+  
   fputc ('\n', tempfp); /* tie off the header. */
 
   if ((mutt_write_mime_body (msg->content, tempfp) == -1))
@@ -816,6 +822,11 @@ static int send_message (HEADER *msg)
     return (-1);
   }
 
+#ifdef MIXMASTER
+  if (msg->chain)
+    return mix_send_message (msg->chain, tempfile);
+#endif
+
   i = mutt_invoke_sendmail (msg->env->to, msg->env->cc, msg->env->bcc,
                       tempfile, (msg->content->encoding == ENC8BIT));
   return (i ? -1 : 0);
index 38c6cd90979990db74566fc4a6fc06fdc295a819..69dd9673488931bba59b3be0dd576f7450440f20 100644 (file)
--- a/sendlib.c
+++ b/sendlib.c
@@ -1224,14 +1224,18 @@ static void write_references (LIST *r, FILE *f)
  * mode == 1  => "lite" mode (used for edit_hdrs)
  * mode == 0  => normal mode.  write full header + MIME headers
  * mode == -1 => write just the envelope info (used for postponing messages)
+ * 
+ * privacy != 0 => will omit any headers which may identify the user.
+ * 
  */
 
-int mutt_write_rfc822_header (FILE *fp, ENVELOPE *env, BODY *attach, int mode)
+int mutt_write_rfc822_header (FILE *fp, ENVELOPE *env, BODY *attach, 
+                             int mode, int privacy)
 {
   char buffer[LONG_STRING];
   LIST *tmp = env->userhdrs;
 
-  if (option(OPTUSEHEADERDATE))
+  if (option(OPTUSEHEADERDATE) && !privacy)
   {
     if(env->date)
       fprintf(fp, "Date: %s\n", env->date);
@@ -1246,7 +1250,7 @@ int mutt_write_rfc822_header (FILE *fp, ENVELOPE *env, BODY *attach, int mode)
   /* OPTUSEFROM is not consulted here so that we can still write a From:
    * field if the user sets it with the `my_hdr' command
    */
-  if (env->from)
+  if (env->from && !privacy)
   {
     buffer[0] = 0;
     rfc822_write_address (buffer, sizeof (buffer), env->from);
@@ -1286,7 +1290,7 @@ int mutt_write_rfc822_header (FILE *fp, ENVELOPE *env, BODY *attach, int mode)
     fputs ("Subject: \n", fp);
 
   /* save message id if the user has set it */
-  if (env->message_id)
+  if (env->message_id && !privacy)
     fprintf (fp, "Message-ID: %s\n", env->message_id);
 
   if (env->reply_to)
@@ -1318,7 +1322,7 @@ int mutt_write_rfc822_header (FILE *fp, ENVELOPE *env, BODY *attach, int mode)
   }
 
 #ifndef NO_XMAILER
-  if (mode == 0)
+  if (mode == 0 && !privacy)
   {
     /* Add a vanity header */
     fprintf (fp, "X-Mailer: Mutt %s\n", MUTT_VERSION);
@@ -1899,7 +1903,7 @@ int mutt_write_fcc (const char *path, HEADER *hdr, const char *msgid, int post,
   /* post == 1 => postpone message. Set mode = -1 in mutt_write_rfc822_header()
    * post == 0 => Normal mode. Set mode = 0 in mutt_write_rfc822_header() 
    * */
-  mutt_write_rfc822_header (msg->fp, hdr->env, hdr->content, post ? -post : 0);
+  mutt_write_rfc822_header (msg->fp, hdr->env, hdr->content, post ? -post : 0, 0);
 
   /* (postponment) if this was a reply of some sort, <msgid> contians the
    * Message-ID: of message replied to.  Save it using a special X-Mutt-
@@ -1923,7 +1927,7 @@ int mutt_write_fcc (const char *path, HEADER *hdr, const char *msgid, int post,
   /* (postponment) if the mail is to be signed or encrypted, save this info */
   if (post && (hdr->pgp & (PGPENCRYPT | PGPSIGN)))
   {
-    fputs ("Pgp: ", msg->fp);
+    fputs ("X-Mutt-PGP: ", msg->fp);
     if (hdr->pgp & PGPENCRYPT) 
       fputc ('E', msg->fp);
     if (hdr->pgp & PGPSIGN)
@@ -1938,7 +1942,22 @@ int mutt_write_fcc (const char *path, HEADER *hdr, const char *msgid, int post,
   }
 #endif /* _PGPPATH */
 
+#ifdef MIXMASTER
+  /* (postponement) if the mail is to be sent through a mixmaster 
+   * chain, save that information
+   */
+  
+  if (post && hdr->chain && hdr->chain)
+  {
+    LIST *p;
 
+    fputs ("X-Mutt-Mix:", msg->fp);
+    for (p = hdr->chain; p; p = p->next)
+      fprintf (msg->fp, " %s", (char *) p->data);
+    
+    fputc ('\n', msg->fp);
+  }
+#endif    
 
   if (tempfp)
   {