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 }