From 526d86334066515821e3ce6cf8211fe1858d3ce0 Mon Sep 17 00:00:00 2001 From: Thomas Roessler Date: Wed, 13 Jan 1999 01:53:03 +0000 Subject: [PATCH] A first take at adding a mixmaster front-end to mutt. Don't worry, it's optional. ;-) --- Makefile.am | 10 +- OPS.MIX | 7 + acconfig.h | 3 + compose.c | 61 ++++- configure.in | 12 + functions.h | 17 ++ globals.h | 5 + headers.c | 42 +--- init.h | 7 + keymap.c | 16 +- keymap.h | 11 +- lib.c | 3 + mutt.h | 8 + postpone.c | 29 ++- protos.h | 15 +- remailer.c | 683 +++++++++++++++++++++++++++++++++++++++++++++++++++ remailer.h | 62 +++++ send.c | 13 +- sendlib.c | 33 ++- 19 files changed, 973 insertions(+), 64 deletions(-) create mode 100644 OPS.MIX create mode 100644 remailer.c create mode 100644 remailer.h diff --git a/Makefile.am b/Makefile.am index fc340a9bc..054889779 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 000000000..498833320 --- /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 59b7633fb..9c5f50749 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 ea0f5b207..1aacf7594 100644 --- a/compose.c +++ b/compose.c @@ -26,6 +26,10 @@ #include "mailbox.h" #include "sort.h" +#ifdef MIXMASTER +#include "remailer.h" +#endif + #include #include #include @@ -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 73f522efc..08bbc8675 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 e2f3e4a88..e8162819d 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, "" }, + { "chain-next", OP_MIX_CHAIN_NEXT, "" }, + { NULL, 0, NULL } +}; +#endif /* MIXMASTER */ diff --git a/globals.h b/globals.h index 5ce9deed5..18f108ec7 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 f1a569d27..a45d2d3f9 100644 --- a/headers.c +++ b/headers.c @@ -18,50 +18,10 @@ #include "mutt.h" - - #ifdef _PGPPATH #include "pgp.h" #endif - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #include #include #include @@ -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 9edc74cd5..0513e52da 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 943ce54f4..9281cb547 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 ("", 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 7ec44a5c9..c361e29a0 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 4488f268c..4653e9772 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 2b78e2625..d9f351494 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 bc172c2bb..74cda2683 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 5c8ce6359..96142c26e 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 000000000..f216b9ae1 --- /dev/null +++ b/remailer.c @@ -0,0 +1,683 @@ +/* + * Copyright (C) 1999 Thomas Roessler + * + * 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 +#include +#include + +#include +#include +#include + +#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 (""); + 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, "")) + { + 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 */ + + 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 index 000000000..57050ec91 --- /dev/null +++ b/remailer.h @@ -0,0 +1,62 @@ +#ifndef _REMAILER_H +#define _REMAILER_H + +/* + * Copyright (C) 1999 Thomas Roessler + * + * 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 c29d71d0c..c9fded204 100644 --- 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); diff --git a/sendlib.c b/sendlib.c index 38c6cd909..69dd96734 100644 --- 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, 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) { -- 2.40.0