summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am10
-rw-r--r--OPS.MIX7
-rw-r--r--acconfig.h3
-rw-r--r--compose.c61
-rw-r--r--configure.in12
-rw-r--r--functions.h17
-rw-r--r--globals.h5
-rw-r--r--headers.c42
-rw-r--r--init.h7
-rw-r--r--keymap.c16
-rw-r--r--keymap.h11
-rw-r--r--lib.c3
-rw-r--r--mutt.h8
-rw-r--r--postpone.c29
-rw-r--r--protos.h15
-rw-r--r--remailer.c683
-rw-r--r--remailer.h62
-rw-r--r--send.c13
-rw-r--r--sendlib.c33
19 files changed, 973 insertions, 64 deletions
diff --git a/Makefile.am b/Makefile.am
index fc340a9b..05488977 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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
index 00000000..49883332
--- /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"
diff --git a/acconfig.h b/acconfig.h
index 59b7633f..9c5f5074 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -137,3 +137,6 @@
/* Use the included regex.c? */
#undef USE_GNU_REGEX
+
+/* Where's mixmaster located? */
+#undef MIXMASTER
diff --git a/compose.c b/compose.c
index ea0f5b20..1aacf759 100644
--- a/compose.c
+++ b/compose.c
@@ -26,6 +26,10 @@
#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
}
}
diff --git a/configure.in b/configure.in
index 73f522ef..08bbc867 100644
--- a/configure.in
+++ b/configure.in
@@ -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)
diff --git a/functions.h b/functions.h
index e2f3e4a8..e8162819 100644
--- a/functions.h
+++ b/functions.h
@@ -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 */
diff --git a/globals.h b/globals.h
index 5ce9deed..18f108ec 100644
--- 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;
diff --git a/headers.c b/headers.c
index f1a569d2..a45d2d3f 100644
--- a/headers.c
+++ b/headers.c
@@ -18,50 +18,10 @@
#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 9edc74cd..0513e52d 100644
--- 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 },
diff --git a/keymap.c b/keymap.c
index 943ce54f..9281cb54 100644
--- 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;
diff --git a/keymap.h b/keymap.h
index 7ec44a5c..c361e29a 100644
--- 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 4488f268..4653e977 100644
--- 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 2b78e262..d9f35149 100644
--- a/mutt.h
+++ b/mutt.h
@@ -48,6 +48,10 @@
# 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"
diff --git a/postpone.c b/postpone.c
index bc172c2b..74cda268 100644
--- a/postpone.c
+++ b/postpone.c
@@ -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
{
diff --git a/protos.h b/protos.h
index 5c8ce635..96142c26 100644
--- 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
index 00000000..f216b9ae
--- /dev/null
+++ b/remailer.c
@@ -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);
+