1 /*
2 * MAINTMSG.C
3 *
4 * Written on 30-Jul-90 by jim nutt. Changes on 10-Jul-94 by John Dennis.
5 * Released to the public domain.
6 *
7 * Handles message maintenance.
8 */
9
10 #define TEXTLEN 256
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <time.h>
16 #include "addr.h"
17 #include "nedit.h"
18 #include "msged.h"
19 #include "memextra.h"
20 #include "keys.h"
21 #include "strextra.h"
22 #include "readmail.h"
23 #include "areas.h"
24 #include "makemsgn.h"
25 #include "template.h"
26 #include "winsys.h"
27 #include "menu.h"
28 #include "nshow.h"
29 #include "maintmsg.h"
30 #include "group.h"
31
32 static char *formenu[] =
33 {
34 "Move Message",
35 "Copy Message",
36 "Redirect Message",
37 "Forward Message",
38 NULL
39 };
40
41 /*
42 * Deletes the current message.
43 */
44
deletemsg(void)45 void deletemsg(void)
46 {
47 unsigned long n = CurArea.current;
48 msg *from;
49 msg *to;
50 int i;
51
52 if (message == NULL)
53 {
54 message = readmsg(CurArea.current);
55 if (message == NULL)
56 {
57 return;
58 }
59 }
60 if (!confirm("Erase Message?"))
61 {
62 /* patch up reply links */
63 return;
64 }
65
66 for (i = 0; i < 10; i++)
67 {
68 if (message->replies[i] != 0)
69 {
70 from = MsgReadHeader(message->replies[i], RD_HEADER);
71 if (from)
72 {
73 from->replyto = 0;
74 MsgWriteHeader(from, WR_HEADER);
75 dispose(from);
76 }
77 }
78 }
79
80 to = MsgReadHeader(message->replyto, RD_HEADER);
81 if (to)
82 {
83 for (i = 0; i < 10; i++)
84 {
85 if (to->replies[i] == n)
86 {
87 to->replies[i] = 0;
88 }
89 }
90 MsgWriteHeader(to, WR_HEADER);
91 dispose(to);
92 }
93
94 MsgDelete(message->msgnum); /* we re-scan the area to be safe */
95 MsgAreaClose();
96 message = KillMsg(message);
97 CurArea.messages = MsgAreaOpen(&CurArea);
98 CurArea.current = min(max(1, n), CurArea.messages);
99 }
100
101 /*
102 * Forwards the current message.
103 */
104
forward_msg(int to_area)105 int forward_msg(int to_area)
106 {
107 msg *m;
108 msg *oldm;
109 int fr_area = SW->grouparea;
110 time_t now = time(NULL);
111
112 if (to_area == -1)
113 {
114 to_area = selectarea("Forward To Area", fr_area);
115 }
116
117 if (msgederr)
118 {
119 return -1;
120 }
121
122 if (message == NULL)
123 {
124 message = readmsg(CurArea.current);
125 if (message == NULL)
126 {
127 return -1;
128 }
129 }
130
131 /*
132 * Save the current message and make the global pointer equal
133 * to null (forcing a re-read).
134 */
135
136 oldm = duplicatemsg(message);
137 m = message;
138 message = NULL;
139
140 set_area(to_area);
141
142 if (!CurArea.status)
143 {
144 dispose(oldm);
145 dispose(m);
146 set_area(fr_area);
147 return -1;
148 }
149
150 if ((m->reply && group_getareano(fr_area) != to_area) || CurArea.netmail)
151 {
152 release(m->reply);
153 }
154
155 release(m->msgid);
156 release(m->isfrom);
157 release(m->isto);
158 release(m->from.domain);
159 release(m->to.domain);
160 m->to.zone = m->to.net = m->to.node = m->to.point = 0; m->to.notfound = 0;
161 m->to.fidonet = 0; m->to.internet = 0; m->to.bangpath = 0;
162
163 m->from = CurArea.addr;
164
165 if (CurArea.addr.domain)
166 {
167 m->from.domain = xstrdup(CurArea.addr.domain);
168 }
169
170 clear_attributes(&m->attrib);
171 memset(m->replies, 0, sizeof(m->replies));
172
173 CurArea.new = 1;
174 m->isfrom = xstrdup(ST->username);
175 m->new = 1;
176 m->msgnum = MsgnToUid(CurArea.messages) + 1;
177 m->attrib.local = 1;
178 m->attrib.sent = 0;
179 m->timestamp = now;
180 m->scanned = 0;
181 m->replyto = 0;
182 m->attrib.priv = CurArea.priv;
183 m->invkludges = 1;
184
185 if (EditHeader(m) == Key_Esc && confirm("Cancel?"))
186 {
187 set_area(fr_area);
188 }
189 else
190 {
191 MakeTemplateMsg(m, oldm, group_getareano(fr_area), MT_FOR);
192 save(m);
193 set_area(fr_area);
194 }
195 dispose(oldm);
196 dispose(m);
197 return to_area;
198 }
199
200 /*
201 * Redirects the current message.
202 */
203
redirect_msg(int to_area)204 int redirect_msg(int to_area)
205 {
206 msg *m;
207 msg *oldm;
208 int fr_area = SW->grouparea;
209
210 if (to_area == -1)
211 {
212 to_area = selectarea("Redirect To Area", fr_area);
213 }
214
215 if (msgederr)
216 {
217 return -1;
218 }
219
220 if (message != NULL)
221 {
222 dispose(message);
223 }
224
225 read_verbatim = 1;
226 message = readmsg(CurArea.current);
227 if (message == NULL)
228 {
229 return -1;
230 }
231
232 oldm = duplicatemsg(message);
233 m = message;
234 message = NULL;
235 set_area(to_area);
236
237 if (!CurArea.status)
238 {
239 dispose(oldm);
240 dispose(m);
241 set_area(fr_area);
242 return -1;
243 }
244
245 memset(m->replies, 0, sizeof(m->replies));
246
247 if ((m->reply && group_getareano(fr_area) != to_area) || CurArea.netmail)
248 {
249 release(m->reply);
250 }
251
252 release(m->msgid);
253 release(m->isto);
254 clear_attributes(&m->attrib);
255
256 CurArea.new = 1;
257 m->new = 1;
258 m->attrib.local = 1;
259 m->attrib.sent = 0;
260 m->msgnum = MsgnToUid(CurArea.messages) + 1;
261 m->scanned = 0;
262 m->replyto = 0;
263 m->attrib.priv = CurArea.priv;
264 m->rawcopy = 1;
265
266 if (EditHeader(m) == Key_Esc && confirm("Cancel?"))
267 {
268 set_area(fr_area);
269 }
270 else
271 {
272 MakeTemplateMsg(m, oldm, group_getareano(fr_area), MT_RED);
273 save(m);
274 set_area(fr_area);
275 }
276 dispose(oldm);
277 dispose(m);
278 return to_area;
279 }
280
281 /*
282 * Copies the current message.
283 */
284
copy_msg(int to_area)285 int copy_msg(int to_area)
286 {
287 msg *m;
288 int fr_area = SW->grouparea;
289
290 if (to_area == -1)
291 {
292 to_area = selectarea("Copy To Area", fr_area);
293 }
294
295 if (msgederr)
296 {
297 return -1;
298 }
299
300 if (message != NULL)
301 {
302 dispose(message);
303 }
304
305 read_verbatim = 1;
306 message = readmsg(CurArea.current);
307
308 if (message == NULL)
309 {
310 return -1;
311 }
312
313 m = message;
314 message = NULL;
315
316 set_area(to_area);
317 if (!CurArea.status)
318 {
319 dispose(m);
320 set_area(fr_area);
321 return -1;
322 }
323 clear_attributes(&m->attrib);
324 CurArea.new = 1;
325 release(m->from.domain);
326 m->from = CurArea.addr;
327 if (CurArea.addr.domain != NULL)
328 {
329 m->from.domain = xstrdup(CurArea.addr.domain);
330 }
331 m->msgnum = MsgnToUid(CurArea.messages) + 1;
332 m->new = 1;
333 m->attrib.sent = 0;
334 m->attrib.local = 1;
335 m->scanned = 0;
336 m->attrib.priv = CurArea.priv;
337 m->rawcopy = 1;
338
339 memset(m->replies, 0, sizeof(m->replies));
340 m->replyto = 0;
341
342 writemsg(m);
343 set_area(fr_area);
344 dispose(m);
345 return to_area;
346 }
347
348
349 /*
350 * create bitmask for area type of current area based on
351 * the area type variables
352 *
353 * returns:
354 * - bitmask containing the flags from the area type variables
355 * bit 0: local
356 * bit 1: netmail
357 * bit 2: echomail
358 * bit 3: uucp
359 * bit 4: news
360 */
361
get_areatype(void)362 unsigned int get_areatype(void)
363 {
364 unsigned int bitmask;
365
366 bitmask = CurArea.news;
367 bitmask <<= 1;
368 bitmask |= CurArea.uucp;
369 bitmask <<= 1;
370 bitmask |= CurArea.echomail;
371 bitmask <<= 1;
372 bitmask |= CurArea.netmail;
373 bitmask <<= 1;
374 bitmask |= CurArea.local;
375
376 return bitmask;
377 }
378
379
380 /*
381 * Moves the current message.
382 */
383
move_msg(int to_area)384 int move_msg(int to_area)
385 {
386 msg *m;
387 int fr_area = SW->grouparea;
388 int status;
389 unsigned int sent_flag; /* flag for sent attribute */
390 unsigned int src_type, dest_type; /* area types */
391
392 if (to_area == -1)
393 {
394 to_area = selectarea("Move To Area", fr_area);
395 }
396
397 if (msgederr)
398 {
399 return -1;
400 }
401
402 if (message != NULL)
403 {
404 dispose(message);
405 message = NULL;
406 }
407
408 read_verbatim = 1;
409 message = readmsg(CurArea.current);
410
411 if (message == NULL)
412 {
413 return -1;
414 }
415
416 m = message; /* save the msg so we can write it */
417 message = NULL;
418
419 src_type = get_areatype(); /* areatype of source area */
420
421 set_area(to_area);
422 if (!CurArea.status)
423 {
424 set_area(fr_area);
425 dispose(m);
426 return -1;
427 }
428
429 dest_type = get_areatype(); /* areatype of destination area */
430
431 /* reset attributes when area types differ */
432 if (src_type != dest_type)
433 {
434 sent_flag = m->attrib.sent; /* save sent attribute */
435 clear_attributes(&m->attrib); /* reset all attributes */
436 m->attrib.sent = sent_flag; /* restore sent attribute */
437 }
438
439 CurArea.new = 1;
440 release(m->from.domain);
441 m->from = CurArea.addr;
442 if (CurArea.addr.domain != NULL)
443 {
444 m->from.domain = xstrdup(CurArea.addr.domain);
445 }
446 m->msgnum = MsgnToUid(CurArea.messages) + 1;
447 m->new = 1;
448 m->attrib.local = 1;
449 m->scanned = 0;
450 m->attrib.priv = CurArea.priv;
451 m->rawcopy = 1;
452
453 memset(m->replies, 0, sizeof(m->replies));
454 m->replyto = 0;
455
456 status = writemsg(m);
457 dispose(m);
458 set_area(fr_area);
459
460 if (status == TRUE)
461 {
462 int confirm_temp;
463 confirm_temp = SW->confirmations;
464 SW->confirmations = 0;
465 deletemsg();
466 SW->confirmations = confirm_temp;
467 }
468 return to_area;
469 }
470
471 /*
472 * Allows forwarding, redirecting, moving and copying of messages.
473 */
474
movemsg(void)475 void movemsg(void)
476 {
477 int rc;
478 int oldgroup;
479
480 rc = DoMenu((maxx / 2) - 8, (maxy / 2) - 1, (maxx / 2) + 8,
481 (maxy / 2) + 2, formenu, 0, SELBOX_MOVEMSG, "");
482
483 oldgroup = SW->group;
484 group_set_group(0); /* allow move to every defined area */
485
486 switch (rc)
487 {
488 case 0: /* Move */
489 move_msg(-1); /* to_area = -1 will present a menu that */
490 break; /* lets the user select an area */
491
492 case 1: /* Copy */
493 copy_msg(-1);
494 break;
495
496 case 2: /* Redirect */
497 redirect_msg(-1);
498 break;
499
500 case 3: /* Forward */
501 forward_msg(-1);
502 break;
503
504 case -1: /* Escape */
505 return;
506 }
507
508 group_set_group(oldgroup);
509
510 ShowNewArea();
511 }
512