tmenusend.c - mixmaster - mixmaster 3.0 patched for libressl
  HTML git clone git://parazyd.org/mixmaster.git
   DIR Log
   DIR Files
   DIR Refs
   DIR README
       ---
       tmenusend.c (12957B)
       ---
            1 /* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
            2 
            3    Mixmaster may be redistributed and modified under certain conditions.
            4    This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
            5    ANY KIND, either express or implied. See the file COPYRIGHT for
            6    details.
            7 
            8    Menu-based user interface -- send message
            9    $Id: menusend.c 934 2006-06-24 13:40:39Z rabbi $ */
           10 
           11 
           12 #include "menu.h"
           13 #include "mix3.h"
           14 #include <string.h>
           15 #include <ctype.h>
           16 #include <stdlib.h>
           17 #ifdef POSIX
           18 #include <unistd.h>
           19 #else /* end of POSIX */
           20 #include <io.h>
           21 #endif /* else if not POSIX */
           22 
           23 void send_message(int type, char *nym, BUFFER *in)
           24 {
           25   char dest[LINELEN] = "", subject[LINELEN] = "";
           26   char chain[CHAINMAX], thisnym[LINELEN], path[PATHMAX];
           27   BUFFER *chainlist, *msg, *txt, *tmp, *field, *content, *cc, *cite;
           28   int numcopies;
           29   int hdr = 0;                        /* txt buffer contains header lines */
           30   FILE *f;
           31   int n, err;
           32 
           33 #ifdef USE_PGP
           34   int sign = 0, encrypt = 0, key = 0;
           35 
           36 #endif /* USE_PGP */
           37 #ifdef USE_NCURSES
           38   char reliability[9];
           39   int c;
           40   char line[LINELEN];
           41 
           42 #endif /* USE_NCURSES */
           43   msg = buf_new();
           44   tmp = buf_new();
           45   txt = buf_new();
           46   field = buf_new();
           47   content = buf_new();
           48   chainlist = buf_new();
           49   cc = buf_new();
           50   cite = buf_new();
           51   strncpy(chain, CHAIN, CHAINMAX);
           52   numcopies = NUMCOPIES;
           53 
           54   mix_status("");
           55   strncpy(thisnym, nym, sizeof(thisnym));
           56 
           57   if (in != NULL)
           58     buf_set(txt, in);
           59 
           60   if (bufileft(txt, "From "))
           61     buf_getline(txt, field);        /* ignore envelope From */
           62 
           63   if (type == 'p' || type == 'm') {
           64 #ifndef USE_NCURSES
           65     mix_status("Invalid option to -f");
           66     mix_exit();
           67     exit(1);
           68 #else /* end of not USE_NCURSES */
           69     clear();
           70     echo();
           71     if (in != NULL)
           72       mvprintw(1, 0, "%s forwarding message...", thisnym);
           73     if (type == 'p')
           74       mvprintw(3, 0, "Newsgroups: ");
           75     else
           76       mvprintw(3, 0, "Send message to: ");
           77     refresh();
           78     wgetnstr(stdscr, dest, LINELEN);
           79     if (dest[0] == '\0') {
           80       noecho();
           81       cl(3, 0);
           82       goto quit;
           83     }
           84     if (txt->length == 0) {
           85       mvprintw(4, 0, "Subject: ");
           86       refresh();
           87       wgetnstr(stdscr, subject, LINELEN);
           88     } else {
           89       strcpy(subject, "Forwarded message");
           90       while (buf_getheader(txt, field, content) == 0) {
           91         if (bufieq(field, "subject")) {
           92           strncpy(subject, content->data, sizeof(subject));
           93           strcatn(subject, " (fwd)", sizeof(subject));
           94         }
           95         if (bufieq(field, "from") || bufieq(field, "subject") ||
           96             bufieq(field, "date"))
           97           buf_appendheader(tmp, field, content);
           98       }
           99       buf_nl(tmp);
          100       buf_rest(tmp, txt);
          101       buf_move(txt, tmp);
          102     }
          103     noecho();
          104 #endif /* else if USE_NCURSES */
          105   } else {
          106     strcpy(subject, "Re: your mail");
          107     while (buf_getheader(txt, field, content) == 0) {
          108       if (bufieq(field, "subject")) {
          109         if (bufileft(content, "Re:"))
          110           subject[0] = '\0';
          111         else
          112           strcpy(subject, "Re: ");
          113         strcatn(subject, content->data, sizeof(subject));
          114       }
          115       if (bufieq(field, "from"))
          116         buf_set(cite, content);
          117       if (type == 'p' || type == 'f') {
          118         if (dest[0] == '\0' && bufieq(field, "newsgroups"))
          119           strncpy(dest, content->data, sizeof(dest));
          120         if (bufieq(field, "followup-to") && !bufieq(content, "poster"))
          121           strncpy(dest, content->data, sizeof(dest));
          122         if (bufieq(field, "message-id"))
          123           buf_appendf(tmp, "References: %b\n", content);
          124       } else {
          125         if (dest[0] == '\0' && bufieq(field, "from"))
          126           strncpy(dest, content->data, sizeof(dest));
          127         if (bufieq(field, "reply-to"))
          128           strncpy(dest, content->data, sizeof(dest));
          129         if (type == 'g' && (bufieq(field, "to") || bufieq(field, "cc"))) {
          130           if (cc->length)
          131             buf_appends(cc, ", ");
          132           buf_cat(cc, content);
          133         }
          134         if (bufieq(field, "message-id"))
          135           buf_appendf(tmp, "In-Reply-To: %b\n", content);
          136       }
          137     }
          138     if (cc->length)
          139       buf_appendf(tmp, "Cc: %b\n", cc);
          140     if (tmp->length > 0)
          141       hdr = 1;
          142     if (hdr)
          143       buf_nl(tmp);
          144 
          145     if ((type == 'f' || type == 'g') && cite->length) {
          146       buf_appendf(tmp, "%b wrote:\n\n", cite);
          147     }
          148     if (type == 'r')
          149       buf_appends(tmp, "You wrote:\n\n");
          150 
          151     while (buf_getline(txt, content) != -1)
          152       buf_appendf(tmp, "> %b\n", content);
          153     buf_set(txt, tmp);
          154     if (dest[0] == '\0') {
          155 #ifdef USE_NCURSES
          156       beep();
          157       mix_status("No recipient address found.");
          158 #endif /* USE_NCURSES */
          159       goto quit;
          160     }
          161     goto edit;
          162   }
          163 
          164 #ifdef USE_NCURSES
          165 redraw:
          166   clear();
          167 
          168   for (;;) {
          169     standout();
          170     mvprintw(0, 0, "Mixmaster %s - ", VERSION);
          171     printw(type == 'p' || type == 'f' ? "posting to Usenet" : "sending mail");
          172     standend();
          173     mix_status(NULL);
          174     cl(2, 0);
          175 #ifdef NYMSUPPORT
          176     printw("n)ym: %s", thisnym);
          177 #endif /* NYMSUPPORT */
          178     if (!strleft(thisnym, NONANON)) {
          179       chain_reliability(chain, 0, reliability);   /* chaintype 0=mix */
          180       cl(4, 0);
          181       printw("c)hain: %-35s (reliability: %s)", chain, reliability);
          182       cl(5, 0);
          183       printw("r)edundancy: %3d copies ", numcopies);
          184     }
          185     cl(7, 0);
          186     printw("d)estination: %s", dest);
          187     cl(8, 0);
          188     printw("s)ubject: %s", subject);
          189 #ifdef USE_PGP
          190     if (type != 'p' && type != 'f') {
          191       cl(10, 0);
          192       printw("pgp encry)ption: ");
          193       if (encrypt)
          194         printw("yes");
          195       else
          196         printw("no");
          197     }
          198     if (!streq(thisnym, ANON)) {
          199       cl(11, 0);
          200       printw("p)gp signature: ");
          201       if (sign)
          202         printw("yes");
          203       else
          204         printw("no");
          205       cl(12, 0);
          206       if (key == 0)
          207         printw("attach pgp k)ey: no");
          208     }
          209 #endif /* USE_PGP */
          210 
          211     if (txt->length == 0)
          212       mvprintw(LINES - 3, 18,
          213                "e)dit message           f)ile      q)uit w/o sending");
          214     else
          215       mvprintw(LINES - 3, 0,
          216                "m)ail message      e)dit message         f)ile          q)uit w/o sending");
          217     move(LINES - 1, COLS - 1);
          218     refresh();
          219     c = getch();
          220     if (c != ERR) {
          221       mix_status("");
          222       if (c == '\r' || c == '\n') {        /* default action is edit or mail */
          223         if (txt->length == 0)
          224           c = 'e';
          225         else
          226           c = 'm';
          227       }
          228       switch (c) {
          229 #ifdef NYMSUPPORT
          230       case 'n':
          231         menu_nym(thisnym);
          232         goto redraw;
          233 #endif /* NYMSUPPORT */
          234       case '\014':
          235         goto redraw;
          236       case 'd':
          237         echo();
          238         cl(LINES - 3, 20);
          239         cl(7, 14);
          240         wgetnstr(stdscr, dest, LINELEN);
          241         noecho();
          242         break;
          243       case 's':
          244         echo();
          245         cl(LINES - 3, 20);
          246         cl(8, 10);
          247         wgetnstr(stdscr, subject, LINELEN);
          248         noecho();
          249         break;
          250       case 'c':
          251         menu_chain(chain, 0, (type == 'p' || type == 'f')
          252                    && streq(thisnym, ANON));
          253         goto redraw;
          254       case 'r':
          255         echo();
          256         cl(LINES - 5, 20);
          257         cl(5, 13);
          258         wgetnstr(stdscr, line, LINELEN);
          259         numcopies = strtol(line, NULL, 10);
          260         if (numcopies < 1 || numcopies > 10)
          261           numcopies = 1;
          262         noecho();
          263         break;
          264       case 'f':
          265         cl(LINES - 3, 0);
          266         askfilename(path);
          267         cl(LINES - 3, 0);
          268         if (txt->length) {
          269           buf_sets(tmp, path);
          270           buf_clear(msg);
          271           if (!hdr)
          272             buf_nl(msg);
          273           buf_cat(msg, txt);
          274           if (attachfile(msg, tmp) == -1)
          275             beep();
          276           else {
          277             buf_move(txt, msg);
          278             hdr = 1;
          279           }
          280         } else {
          281           if ((f = fopen(path, "r")) != NULL) {
          282             buf_clear(txt);
          283             buf_read(txt, f);
          284             fclose(f);
          285           } else
          286             beep();
          287         }
          288         break;
          289       case 'e':
          290 #endif /* USE_NCURSES */
          291         {
          292           int linecount;
          293 
          294         edit:
          295           linecount = 1;
          296           sprintf(path, "%s%cx%02x%02x%02x%02x.txt", POOLDIR, DIRSEP,
          297                   rnd_byte(), rnd_byte(), rnd_byte(), rnd_byte());
          298           f = fopen(path, "w");
          299           if (f == NULL) {
          300 #ifdef USE_NCURSES
          301             beep();
          302 #endif /* USE_NCURSES */
          303           } else {
          304             if (type == 'f' || type == 'p')
          305               fprintf(f, "Newsgroups: %s\n", dest);
          306             if (type == 'r' || type == 'g' || type == 'm')
          307               fprintf(f, "To: %s\n", dest);
          308             fprintf(f, "Subject: %s\n", subject);
          309             linecount += 2;
          310             if (hdr)
          311               while (buf_getline(txt, NULL) == 0) linecount++;
          312             else
          313               fprintf(f, "\n");
          314             linecount++;
          315             if (txt->length == 0)
          316               fprintf(f, "\n");
          317 
          318             buf_write(txt, f);
          319             fclose(f);
          320           }
          321 
          322           menu_spawn_editor(path, linecount);
          323 
          324           f = fopen(path, "r");
          325           if (f == NULL) {
          326 #ifdef USE_NCURSES
          327             clear();
          328             beep();
          329             continue;
          330 #else /* end of USE_NCURSES */
          331             goto quit;
          332 #endif /* else if not USE_NCURSES */
          333           }
          334           buf_reset(txt);
          335           hdr = 0;
          336 
          337           buf_reset(tmp);
          338           buf_read(tmp, f);
          339           while (buf_getheader(tmp, field, content) == 0) {
          340             if (bufieq(field, "subject"))
          341               strncpy(subject, content->data,
          342                       sizeof(subject));
          343             else if ((type == 'p' || type == 'f') &&
          344                      bufieq(field, "newsgroups"))
          345               strncpy(dest, content->data, sizeof(dest));
          346             else if (bufieq(field, "to"))
          347               strncpy(dest, content->data, sizeof(dest));
          348             else {
          349               buf_appendheader(txt, field, content);
          350               hdr = 1;
          351             }
          352           }
          353           if (hdr)
          354             buf_nl(txt);
          355           buf_rest(txt, tmp);
          356 
          357           fclose(f);
          358           unlink(path);
          359           strcatn(path, "~", PATHMAX);
          360           unlink(path);
          361 #ifndef USE_NCURSES
          362           {
          363             char line[4];
          364 
          365             fprintf(stderr, "Send message [y/n]? ");
          366             scanf("%3s", line);
          367             if (!strleft(line, "y"))
          368               goto quit;
          369           }
          370 #else /* end of not USE_NCURSES */
          371           goto redraw;
          372         }
          373         break;
          374       case 'm':
          375         if (txt->length == 0)
          376           beep();
          377         else if (dest[0] == '\0') {
          378           mix_status("No destination given.");
          379           goto redraw;
          380         } else {
          381           mix_status("Creating message...");
          382 #endif /* else if USE_NCURSES */
          383           buf_reset(msg);
          384 
          385           if (type == 'p' || type == 'f')
          386             buf_appends(msg, "Newsgroups: ");
          387           else
          388             buf_appends(msg, "To: ");
          389           buf_appends(msg, dest);
          390           buf_nl(msg);
          391           buf_appends(msg, "Subject: ");
          392           if (subject[0] == '\0')
          393             buf_appends(msg, "(no subject)");
          394           else
          395             buf_appends(msg, subject);
          396           buf_nl(msg);
          397           if (!hdr)
          398             buf_nl(msg);
          399           buf_cat(msg, txt);
          400 #ifdef USE_PGP
          401           {
          402             BUFFER *p;
          403 
          404             p = buf_new();
          405             if (streq(thisnym, ANON))
          406               sign = 0;
          407             if (sign || (key && !strileft(thisnym, NONANON)))
          408               user_pass(p);
          409 
          410             if (encrypt || sign) {
          411               if (pgp_mailenc((encrypt ? PGP_ENCRYPT : 0)
          412                               | (sign ? PGP_SIGN : 0) | PGP_TEXT
          413                               | (strleft(thisnym, NONANON) ? 0 : PGP_REMAIL),
          414                               msg, strleft(thisnym, NONANON) ?
          415                               ADDRESS : thisnym, p, PGPPUBRING,
          416                               strleft(thisnym, NONANON) ?
          417                               PGPSECRING : NYMSECRING) == -1) {
          418                 mix_genericerror();
          419 #ifdef USE_NCURSES
          420                 beep();
          421                 goto redraw;
          422 #endif /* USE_NCURSES */
          423               }
          424             }
          425             buf_free(p);
          426           }
          427 #endif /* USE_PGP */
          428 
          429           if (strleft(thisnym, NONANON)) {
          430             FILE *f = NULL;
          431 
          432             if (type == 'p' || type == 'f') {
          433               if (strchr(NEWS, '@')) {
          434                 /*  NOT_IMPLEMENTED; */
          435               } else
          436                 f = openpipe(NEWS);
          437             } else {
          438               if (NAME[0]) {
          439                 buf_sets(tmp, NAME);
          440                 buf_appends(tmp, " <");
          441                 buf_appends(tmp, ADDRESS);
          442                 buf_appends(tmp, ">");
          443               } else
          444                 buf_sets(tmp, ADDRESS);
          445               mail_encode(msg, 0);
          446               if (sendmail(msg, tmp->data, NULL) != 0) {
          447 #ifdef USE_NCURSES
          448                 clear();
          449 #endif /* USE_NCURSES */
          450                 mix_status("Error sending message.");
          451 #ifdef USE_NCURSES
          452                 goto redraw;
          453 #else /* end of USE_NCURSES */
          454                 goto quit;
          455 #endif /* else if not USE_NCURSES */
          456               }
          457             }
          458 #ifdef USE_NCURSES
          459             clear();
          460 #endif /* USE_NCURSES */
          461             mix_status("Message sent non-anonymously.");
          462             goto quit;
          463           } else {
          464 #ifdef USE_PGP
          465 #ifdef NYMSUPPORT
          466             if (!streq(thisnym, ANON)) {
          467               if (nym_encrypt(msg, thisnym, (type == 'p' || type == 'f') ?
          468                               MSG_POST : MSG_MAIL) == 0)
          469                 type = 'm';
          470             }
          471 #endif /* NYMSUPPORT */
          472 #endif /* USE_PGP */
          473             err = mix_encrypt((type == 'p' || type == 'f') ?
          474                               MSG_POST : MSG_MAIL,
          475                               msg, chain, numcopies, chainlist);
          476             if (err == 0) {
          477 #ifdef USE_NCURSES
          478               clear();
          479 #endif /* USE_NCURSES */
          480               for (n = 0; buf_getline(chainlist, tmp) == 0; n++) ;
          481               if (n > 1)
          482                 mix_status("Done. (%d packets)", n);
          483               else
          484                 mix_status("Chain: %s", chainlist->data);
          485               goto quit;
          486             } else {
          487 #ifdef USE_NCURSES
          488               beep();
          489 #endif /* USE_NCURSES */
          490               if (chainlist->length)
          491                 mix_status("%s", chainlist->data);
          492               else
          493                 mix_genericerror();
          494             }
          495           }
          496         }
          497 #ifdef USE_NCURSES
          498         break;
          499       case 'q':
          500       case 'Q':
          501         clear();
          502         goto quit;
          503 #ifdef USE_PGP
          504       case 'p':
          505         if (!streq(thisnym, ANON))
          506           sign = !sign;
          507         break;
          508       case 'y':
          509         encrypt = !encrypt;
          510         break;
          511       case 'k':
          512         if (!streq(thisnym, ANON)) {
          513           BUFFER *p, *keytxt, *uid;
          514 
          515           key = 1;
          516           p = buf_new();
          517           keytxt = buf_new();
          518           uid = buf_new();
          519 
          520           buf_appendf(uid, "<%s>", strleft(thisnym, NONANON) ? ADDRESS :
          521                       thisnym);
          522           user_pass(p);
          523           pgp_pubkeycert(uid, strleft(thisnym, NONANON) ?
          524                          PGPSECRING : NYMSECRING, p, keytxt, PGP_ARMOR_NYMKEY);
          525 
          526           buf_clear(msg);
          527           if (!hdr)
          528             buf_nl(msg);
          529           buf_cat(msg, txt);
          530           buf_sets(p, "application/pgp-keys");
          531           mime_attach(msg, keytxt, p);
          532           hdr = 1;
          533           buf_move(txt, msg);
          534 
          535           buf_free(p);
          536           buf_free(keytxt);
          537           buf_free(uid);
          538         }
          539         break;
          540 #endif /* USE_PGP */
          541       default:
          542         beep();
          543       }
          544     }
          545   }
          546 #endif /* USE_NCURSES */
          547 quit:
          548   buf_free(cc);
          549   buf_free(cite);
          550   buf_free(msg);
          551   buf_free(txt);
          552   buf_free(field);
          553   buf_free(content);
          554   buf_free(chainlist);
          555   buf_free(tmp);
          556 }