1 /*****************************************************************************
2  * HPT --- FTN NetMail/EchoMail Tosser
3  *****************************************************************************
4  * Copyright (C) 1997-1999
5  *
6  * Matthias Tichy
7  *
8  * Fido:     2:2433/1245 2:2433/1247 2:2432/605.14
9  * Internet: mtt@tichy.de
10  *
11  * Grimmestr. 12         Buchholzer Weg 4
12  * 33098 Paderborn       40472 Duesseldorf
13  * Germany               Germany
14  *
15  * Copyright (c) 1999-2001
16  * Max Levenkov, sackett@mail.ru
17  *
18  * This file is part of HPT.
19  *
20  * HPT is free software; you can redistribute it and/or modify it
21  * under the terms of the GNU General Public License as published by the
22  * Free Software Foundation; either version 2, or (at your option) any
23  * later version.
24  *
25  * HPT is distributed in the hope that it will be useful, but
26  * WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
28  * General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with HPT; see the file COPYING.  If not, write to the Free
32  * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
33  *****************************************************************************
34  * $Id$
35  */
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include <errno.h>
40 
41 #include <huskylib/compiler.h>
42 #include <huskylib/huskylib.h>
43 #include <huskylib/cvtdate.h>
44 
45 #include <smapi/msgapi.h>
46 
47 #include <fidoconf/fidoconf.h>
48 #include <fidoconf/common.h>
49 #include <huskylib/xstr.h>
50 #include <fidoconf/afixcmd.h>
51 #include <huskylib/log.h>
52 #include <huskylib/recode.h>
53 
54 #include <areafix/areafix.h>
55 
56 #include <pkt.h>
57 #include <scan.h>
58 #include <seenby.h>
59 #include <global.h>
60 #include <version.h>
61 #include <toss.h>
62 #include <hpt.h>
63 #include <dupe.h>
64 
65 #ifdef DO_PERL
66 #include <hptperl.h>
67 #endif
68 
makeMsg(HMSG hmsg,XMSG xmsg,s_message * msg,s_area * echo,int action)69 void makeMsg(HMSG hmsg, XMSG xmsg, s_message *msg, s_area *echo, int action)
70 {
71    /*  action == 0 - scan area */
72    /*  action == 1 - rescan area */
73    /*  action == 2 - rescan badarea */
74     char   *kludgeLines = NULL, *seenByPath = NULL;
75    UCHAR  *msgtid = NULL;
76    UCHAR  *ctrlBuff = NULL;
77    UINT32 ctrlLen;
78    UCHAR  tid[]= "TID";
79 
80    memset(msg, '\0', sizeof(s_message));
81 
82    msg->origAddr.zone  = xmsg.orig.zone;
83    msg->origAddr.net   = xmsg.orig.net;
84    msg->origAddr.node  = xmsg.orig.node;
85    msg->origAddr.point = xmsg.orig.point;
86 
87    msg->destAddr.zone  = xmsg.dest.zone;
88    msg->destAddr.net   = xmsg.dest.net;
89    msg->destAddr.node  = xmsg.dest.node;
90    msg->destAddr.point = xmsg.dest.point;
91 
92    msg->attributes = xmsg.attr & ~MSGLOCAL; /*  msg should not have MSGLOCAL bit set */
93    sc_time((union stamp_combo *) &(xmsg.date_written), (char *)msg->datetime);
94 
95    xstrcat(&msg->toUserName, (char*)xmsg.to);
96    xstrcat(&msg->fromUserName, (char*)xmsg.from);
97    xstrcat(&msg->subjectLine, (char*)xmsg.subj);
98 
99    /*  make msgtext */
100 
101    /*  convert kludgeLines */
102    ctrlLen = MsgGetCtrlLen(hmsg);
103    ctrlBuff = (UCHAR *) safe_malloc(ctrlLen+1);
104    MsgReadMsg(hmsg, NULL, 0, 0, NULL, ctrlLen, ctrlBuff);
105    /* MsgReadMsg does not do zero termination! */
106    ctrlBuff[ctrlLen] = '\0';
107    if (action == 0 && config->disableTID == 0)
108    {
109        while ((msgtid = GetCtrlToken(ctrlBuff, tid)) != NULL)
110            MsgRemoveToken(ctrlBuff, tid);
111        xstrscat((char **)&ctrlBuff, "\001TID: ", versionStr, NULLP);
112    }
113    /*  add '\r' after each kludge */
114    kludgeLines = (char *) CvtCtrlToKludge(ctrlBuff);
115 
116    nfree(ctrlBuff);
117 
118    if (action == 0)
119 	   xstrcat(&seenByPath, "SEEN-BY: "); /*  9 bytes */
120 
121    /*  create text */
122    msg->textLength = MsgGetTextLen(hmsg); /*  with trailing \0 */
123    msg->text=NULL;
124    if (action!=2) {
125 	xscatprintf(&(msg->text),"AREA:%s\r",echo->areaName);
126 	strUpper(msg->text+5);
127    }
128    xstrcat(&(msg->text), kludgeLines);
129    nfree(kludgeLines);
130    ctrlLen = strlen(msg->text);
131    xstralloc(&(msg->text), ctrlLen + msg->textLength);
132    MsgReadMsg(hmsg, NULL, (dword) 0, (dword) msg->textLength,
133               (byte *)(msg->text+ctrlLen), (dword) 0, (byte *)NULL);
134    msg->text[msg->textLength + ctrlLen]='\0';
135    msg->textLength += ctrlLen-1;
136    /*  if origin has no ending \r add it */
137    if (msg->text[msg->textLength-1] != '\r') {
138 	   xstrcat(&(msg->text), "\r");
139 	   msg->textLength++;
140    }
141    if (action == 0) {
142 	   xstrcat(&(msg->text), seenByPath);
143 	   msg->textLength += 9; /*  strlen(seenByPath) */
144    }
145 
146    /*  recoding from internal to transport charSet */
147    if (config->outtab != NULL && action != 2) {
148       recodeToTransportCharset((char*)msg->fromUserName);
149       recodeToTransportCharset((char*)msg->toUserName);
150       recodeToTransportCharset((char*)msg->subjectLine);
151       recodeToTransportCharset((char*)msg->text);
152    } else msg->recode |= (REC_HDR|REC_TXT);
153 
154    nfree(seenByPath);
155 }
156 
packEMMsg(HMSG hmsg,XMSG * xmsg,s_area * echo)157 void packEMMsg(HMSG hmsg, XMSG *xmsg, s_area *echo)
158 {
159    s_message    msg;
160    s_message* messCC;
161 
162    makeMsg(hmsg, *xmsg, &msg, echo, 0);
163 
164    /*  msg is dupe -- return */
165    if (dupeDetection(echo, msg)!=1) return;
166 
167 #ifdef DO_PERL
168    if (perlscanmsg(echo->areaName, &msg))
169    {   freeMsgBuffers(&msg);
170        return;
171    }
172 #endif
173 
174    messCC = MessForCC(&msg); /* make copy of original message*/
175 
176    /*  export msg to downlinks */
177    forwardMsgToLinks(echo, &msg, *echo->useAka);
178 
179    /*  process carbon copy */
180    if (config->carbonOut) carbonCopy(messCC, xmsg, echo);
181 
182    /*  mark msg as sent and scanned */
183    xmsg->attr |= MSGSENT;
184    xmsg->attr |= MSGSCANNED;
185    if (0!=MsgWriteMsg(hmsg, 0, xmsg, NULL, 0, 0, 0, NULL))
186        w_log(LL_ERR, "Could not update msg in area %s! Check the wholeness of messagebase, please.", echo->areaName);
187 
188    freeMsgBuffers(&msg);
189    freeMsgBuffers(messCC);
190    nfree(messCC);
191    statScan.exported++;
192    echo->scn++;
193 }
194 
scanEMArea(s_area * echo)195 void scanEMArea(s_area *echo)
196 {
197    HAREA area;
198    HMSG  hmsg;
199    XMSG  xmsg;
200    dword highestMsg, i;
201 
202    if (echo->scn) return;
203 
204    area = MsgOpenArea((UCHAR *) echo->fileName, MSGAREA_NORMAL, (word)(echo->msgbType | MSGTYPE_ECHO));
205    if (area != NULL) {
206        statScan.areas++;
207        echo->scn++;
208        w_log(LL_START, "Scanning area: %s", echo->areaName);
209 
210        i = (noHighWaters) ? 0 : MsgGetHighWater(area);
211        highestMsg = MsgGetNumMsg(area);
212 
213        while (i < highestMsg) {
214 	   hmsg = MsgOpenMsg(area, MOPEN_RW, ++i);
215 	   if (hmsg == NULL) continue;      /*  msg# does not exist */
216 	   statScan.msgs++;
217 	   MsgReadMsg(hmsg, &xmsg, 0, 0, NULL, 0, NULL);
218 	   if (((xmsg.attr & MSGSENT) != MSGSENT) &&
219            ((xmsg.attr & MSGLOCKED) != MSGLOCKED) &&
220 	       ((xmsg.attr & MSGLOCAL) == MSGLOCAL)) {
221 	       packEMMsg(hmsg, &xmsg, echo);
222 	   }
223 
224 	   MsgCloseMsg(hmsg);
225 
226 	   /*  kill msg */
227 	   if ((xmsg.attr & MSGKILL) == MSGKILL) {
228 	       MsgKillMsg(area, i);
229 	       i--;
230 	   }
231 
232        }
233        if (i < highestMsg)
234            MsgSetHighWater(area, i);
235 
236        closeOpenedPkt();
237        MsgCloseArea(area);
238 
239    } else {
240        w_log(LL_START, "Could not open %s", echo->fileName);
241    } /* endif */
242 }
243 
244 /* rescan functions taken from areafix.c */
245 
repackEMMsg(HMSG hmsg,XMSG xmsg,s_area * echo,s_arealink * arealink)246 int repackEMMsg(HMSG hmsg, XMSG xmsg, s_area *echo, s_arealink *arealink)
247 {
248    s_message    msg;
249    UINT32       j=0;
250    s_seenBy     *seenBys = NULL, *path = NULL;
251    UINT         seenByCount = 0, pathCount = 0;
252    s_arealink   **links;
253    char         *tempbefore, *addrstr, *tempafter;
254 
255    links = (s_arealink **) scalloc(2, sizeof(s_arealink*));
256    if (links==NULL) exit_hpt("out of memory",1);
257    links[0] = arealink;
258 
259    makeMsg(hmsg, xmsg, &msg, echo, 1);
260 
261    /* translating name of the area to uppercase */
262    while (msg.text[j] != '\r') {msg.text[j]=(char)toupper(msg.text[j]);j++;}
263 
264    if (strncmp(msg.text+j+1,"NOECHO",6)==0) {
265        freeMsgBuffers(&msg);
266        nfree(links);
267        return 0;
268    }
269 
270    if (!config->disableKludgeRescanned)
271    {
272        /* d_sergienko: Following FSC-0057 ... */
273        tempbefore = (char *) scalloc(j+1, 1);
274        tempbefore = (char *)strncpy(tempbefore, msg.text, j);
275        tempafter = (char *)sstrdup(msg.text+j+1);
276        nfree(msg.text);
277        xstrscat((char **) &msg.text, tempbefore, "\r\001RESCANNED ",
278          (addrstr=aka2str5d(*arealink->link->ourAka)), "\r", tempafter, NULLP);
279        nfree(tempbefore);
280        nfree(tempafter);
281        nfree(addrstr);
282    }
283 
284    createSeenByArrayFromMsg(echo, &msg, &seenBys, &seenByCount);
285    createPathArrayFromMsg(&msg, &path, &pathCount);
286 
287    forwardToLinks(&msg, echo, links, &seenBys, &seenByCount, &path, &pathCount);
288 
289    freeMsgBuffers(&msg);
290    nfree(links);
291    nfree(seenBys);
292    nfree(path);
293 
294    return 1;
295 }
296 
rescanEMArea(s_area * echo,s_arealink * arealink,long rescanCount,long rescanAfter)297 int rescanEMArea(s_area *echo, s_arealink *arealink, long rescanCount, long rescanAfter)
298 {
299    HAREA area;
300    HMSG  hmsg;
301    XMSG  xmsg;
302 /*   dword highestMsg; */
303    dword i;
304    dword *pool;              /* pool of messages to rescan */
305    int   n_pool = 0, s_pool; /* actual and allocated pool size */
306    unsigned int rc=0;
307 
308    area = MsgOpenArea((UCHAR *) echo->fileName, MSGAREA_NORMAL,
309                       (word)(echo->msgbType | MSGTYPE_ECHO));
310    if (area != NULL) {
311 #if 0 /* val: change in algorithm */
312        /*       i = highWaterMark = MsgGetHighWater(area); */
313        i = 0;
314        highestMsg    = MsgGetHighMsg(area);
315 
316        /*  if rescanCount == -1 all mails should be rescanned */
317        if ((rescanCount == -1) || (rescanCount > (long)highestMsg))
318 	   rescanCount = highestMsg;
319 
320        while (i <= highestMsg) {
321 	   if (i > highestMsg - rescanCount) { /*  honour rescanCount paramater */
322 	       hmsg = MsgOpenMsg(area, MOPEN_RW, i);
323 	       if (hmsg != NULL) {     /*  msg# does not exist */
324 		   MsgReadMsg(hmsg, &xmsg, 0, 0, NULL, 0, NULL);
325 		   rc += repackEMMsg(hmsg, xmsg, echo, arealink);
326 		   MsgCloseMsg(hmsg);
327 	       }
328 	   }
329 	   i++;
330        }
331 
332        MsgSetHighWater(area, i);
333 #else /* val: change in algorithm */
334        i = MsgGetHighMsg(area);
335 	   if (i > 0)
336 	   {
337 		   MsgSetHighWater(area, i);
338 	   }
339        if (rescanCount <= 0) rescanCount = i;
340        s_pool = rescanCount > 1024 ? 1024 : rescanCount;
341        pool = safe_malloc(s_pool * sizeof(*pool));
342        while (i > 0 && rescanCount > 0) {
343 	       hmsg = MsgOpenMsg(area, MOPEN_RW, i--);
344 	       if (hmsg != NULL) {     /*  msg# does not exist */
345              MsgReadMsg(hmsg, &xmsg, 0, 0, NULL, 0, NULL);
346              if (rescanAfter) {
347                struct tm stm;
348                DosDate_to_TmDate((SCOMBO*)(&xmsg.date_written), &stm);
349                if (mktime(&stm) + gettz() < rescanAfter) {
350                  MsgCloseMsg(hmsg);
351                  continue;
352                }
353              }
354              /* add its number to pool of to-rescan messages */
355              if (n_pool >= s_pool) {
356                s_pool *= 2;
357                pool = safe_realloc(pool, s_pool * sizeof(*pool));
358              }
359              pool[n_pool++] = i + 1;
360              rescanCount--;        /* keep track of left to rescan messages */
361              MsgCloseMsg(hmsg);
362 	       }
363        }
364        for (i = n_pool; i > 0; ) {
365 	       hmsg = MsgOpenMsg(area, MOPEN_RW, pool[--i]);
366 	       if (hmsg != NULL) {     /*  msg# does not exist */
367              MsgReadMsg(hmsg, &xmsg, 0, 0, NULL, 0, NULL);
368              rc += repackEMMsg(hmsg, xmsg, echo, arealink);
369              MsgCloseMsg(hmsg);
370 	       }
371        }
372        nfree(pool);
373 #endif /* val: change in algorithm */
374        MsgCloseArea(area);
375        closeOpenedPkt();
376 
377    } else w_log(LL_ERR, "Could not open %s: %s", echo->fileName, strerror(errno));
378 
379    return rc;
380 }
381