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