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