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-2002
16 *
17 * Max Levenkov
18 *
19 * Fido: 2:5000/117
20 * Internet: sackett@mail.ru
21 * Novosibirsk, West Siberia, Russia
22 *
23 * This file is part of HPT.
24 *
25 * HPT is free software; you can redistribute it and/or modify it
26 * under the terms of the GNU General Public License as published by the
27 * Free Software Foundation; either version 2, or (at your option) any
28 * later version.
29 *
30 * HPT is distributed in the hope that it will be useful, but
31 * WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 * General Public License for more details.
34 *
35 * You should have received a copy of the GNU General Public License
36 * along with HPT; see the file COPYING. If not, write to the Free
37 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
38 *****************************************************************************
39 * $Id$
40 */
41 #include <string.h>
42 #include <stdlib.h>
43 #include <errno.h>
44 #include <ctype.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47
48 /* compiler.h */
49 #include <huskylib/compiler.h>
50
51
52 #if (defined(__EMX__) || defined(__MINGW32__)) && defined(__NT__)
53 /* we can't include windows.h for prevent compiler errors ... */
54 /*# include <windows.h>*/
55 # define CharToOem CharToOemA
56 #endif
57
58 #ifdef HAS_UNISTD_H
59 #include <unistd.h>
60 #endif
61
62 #ifdef HAS_IO_H
63 #include <io.h>
64 #endif
65
66 #if defined(__OS2__)
67 #include <os2.h>
68 #endif
69
70 #ifdef HAS_DOS_H
71 #include <dos.h>
72 #endif
73
74 #if defined(__NT__)
75 /* we can't include windows.h for several reasons ... */
76 #define GetFileAttributes GetFileAttributesA
77 #endif
78
79 /* huskylib */
80 #include <huskylib/huskylib.h>
81 #include <huskylib/cvtdate.h>
82 #include <huskylib/dirlayer.h>
83
84 /* smapi */
85 #include <smapi/msgapi.h>
86
87 /* fidoconf */
88 #include <fidoconf/fidoconf.h>
89 #include <fidoconf/common.h>
90 #include <huskylib/dirlayer.h>
91 #include <huskylib/xstr.h>
92 #include <fidoconf/afixcmd.h>
93 #include <huskylib/temp.h>
94 #include <huskylib/recode.h>
95 #include <fidoconf/stat.h>
96 #include <areafix/areafix.h>
97 #include <areafix/query.h>
98
99 #if defined(A_HIDDEN) && !defined(_A_HIDDEN)
100 #define _A_HIDDEN A_HIDDEN
101 #endif
102
103 #ifdef USE_HPTZIP
104 # include <hptzip/hptzip.h>
105 #endif
106
107 /* hpt */
108 #include <pkt.h>
109 #include <scan.h>
110 #include <toss.h>
111 #include <global.h>
112 #include <seenby.h>
113 #include <dupe.h>
114 #include <version.h>
115 #include <scanarea.h>
116 #include <fcommon.h>
117 #include <hpt.h>
118 #ifdef DO_PERL
119 #include <hptperl.h>
120 #endif
121
122
123 #if defined(__MINGW32__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1100))
124 #define NOSLASHES
125 #endif
126
127 #ifdef DO_PERL
128 extern int perl_setattr; /* perl.c */
129 #endif
130
131
132 extern s_message **msgToSysop;
133 int save_err;
134
135 static ULONG nopenpkt, maxopenpkt;
136
137 s_statToss statToss;
138 int forwardPkt(const char *fileName, s_pktHeader *header, e_tossSecurity sec);
139 int processDir(char *directory, e_tossSecurity sec);
140 void makeMsgToSysop(char *areaName, hs_addr fromAddr, ps_addr uplinkAddr);
141 static void setmaxopen(void);
142
143 char *(BadmailReasonString[BM_MAXERROR+1]) = {
144 /* 0*/"No reason",
145 /* 1*/"System not allowed to create new area",
146 /* 2*/"Sender not allowed to post in this area (access group)",
147 /* 3*/"Sender not allowed to post in this area (access level)",
148 /* 4*/"Sender not allowed to post in this area (access import)",
149 /* 5*/"Sender not active for this area",
150 /* 6*/"Rejected by perl filter",
151 /* 7*/"MSGAPI error",
152 /* 8*/"Can't create echoarea with forbidden symbols in areatag",
153 /* 9*/"Sender not found in config file",
154 /*10*/"Can't open config file",
155 /*11*/"No downlinks for passthrough area",
156 /*12*/"Length of CONFERENCE name is more than 60 symbols",
157 /*13*/"Area killed (unsubscribed)",
158 /*14*/"New area refused by NewAreaRefuseFile",
159 /*15*/"Wrong link to autocreate from (area requested from other link)",
160 /*16*/"Area is paused (unsubscribed at uplink)",
161 /*17*/"No valid areatag is given in the message",
162 /*18*/"Can't create subdirectories for echobase",
163 /*19*/"Mail considered to be too old",
164 /*20*/"Mail considered to be too new"
165 };
166
167
get_filename(char * pathname)168 static char *get_filename(char *pathname)
169 {
170 char *ptr = NULL;
171
172 if (pathname == NULL || !(*pathname))
173 return pathname;
174
175 ptr = pathname + strlen(pathname) - 1;
176
177 while (*ptr != '/' && *ptr != '\\' && *ptr != ':' && ptr != pathname)
178 ptr--;
179
180 if (*ptr == '/' || *ptr == '\\' || *ptr == ':')
181 ptr++;
182
183 return ptr;
184 }
185
186
187 /* return value: 1 if success, 0 if fail */
putMsgInArea(s_area * echo,s_message * msg,int strip,dword forceattr)188 int putMsgInArea(s_area *echo, s_message *msg, int strip, dword forceattr)
189 {
190 char *ctrlBuff = NULL, *textStart = NULL, *textWithoutArea = NULL;
191 UINT textLength = (UINT) msg->textLength;
192 /* HAREA harea = NULL; */
193 HMSG hmsg;
194 XMSG xmsg;
195 char /**slash,*/ *p, *q, *tiny;
196 int rc = 0;
197 int recode = 1;
198
199 if (echo->msgbType==MSGTYPE_PASSTHROUGH) {
200 w_log(LL_ERR, "Can't put message to passthrough area %s!", echo->areaName);
201 return rc;
202 }
203
204 if (!msg->netMail) {
205 msg->destAddr.zone = echo->useAka->zone;
206 msg->destAddr.net = echo->useAka->net;
207 msg->destAddr.node = echo->useAka->node;
208 msg->destAddr.point = echo->useAka->point;
209 }
210 #ifdef DO_PERL
211 switch( perl_putmsg(echo, msg) ) {
212 case 0 : return 1;
213 case 2 : recode = 0;
214 default: textLength = (UINT)msg->textLength;
215 }
216 #endif
217
218 if (maxopenpkt == 0) setmaxopen();
219
220 if (echo->harea == NULL) {
221 w_log( LL_SRCLINE, "%s:%d opening %s", __FILE__, __LINE__,echo->fileName);
222 echo->harea = MsgOpenArea((UCHAR *) echo->fileName, MSGAREA_CRIFNEC,
223 (word)(echo->msgbType | (msg->netMail ? 0 : MSGTYPE_ECHO)));
224 if (echo->harea) nopenpkt+=3;
225 }
226 if (echo->harea != NULL) {
227 w_log( LL_SRCLINE, "%s:%d creating msg", __FILE__, __LINE__);
228 hmsg = MsgOpenMsg(getHAREA(echo->harea), MOPEN_CREATE, 0);
229 if (hmsg != NULL) {
230
231 /* recode from TransportCharset to internal Charset */
232 if ((config->recodeMsgBase) && (recode && config->intab != NULL)) {
233 if ((msg->recode & REC_HDR)==0) {
234 recodeToInternalCharset((char*)msg->fromUserName);
235 recodeToInternalCharset((char*)msg->toUserName);
236 recodeToInternalCharset((char*)msg->subjectLine);
237 msg->recode |= REC_HDR;
238 }
239 if ((msg->recode & REC_TXT)==0) {
240 recodeToInternalCharset((char*)msg->text);
241 msg->recode |= REC_TXT;
242 }
243 }
244
245 textWithoutArea = msg->text;
246
247 if ((strip==1) && (strncmp(msg->text, "AREA:", 5) == 0)) {
248 /* jump over AREA:xxxxx\r */
249 while (*(textWithoutArea) != '\r') textWithoutArea++;
250 textWithoutArea++;
251 textLength -= (size_t) (textWithoutArea - msg->text);
252 }
253 if (echo->killSB) {
254 tiny = strrstr(textWithoutArea, " * Origin:");
255 if (tiny == NULL) tiny = textWithoutArea;
256 if (NULL != (p = strstr(tiny, "\rSEEN-BY: "))) {
257 p[1]='\0';
258 textLength = (size_t) (p - textWithoutArea + 1);
259 }
260 } else if (echo->tinySB) {
261 tiny = strrstr(textWithoutArea, " * Origin:");
262 if (tiny == NULL) tiny = textWithoutArea;
263 if (NULL != (p = strstr(tiny, "\rSEEN-BY: "))) {
264 p++;
265 if (NULL != (q = strstr(p,"\001PATH: "))) {
266 /* memmove(p,q,strlen(q)+1); */
267 memmove(p,q,textLength-(size_t)(q-textWithoutArea)+1);
268 textLength -= (size_t) (q - p);
269 } else {
270 p[0]='\0';
271 textLength = (size_t) (p - textWithoutArea);
272 }
273 }
274 }
275 ctrlBuff = (char *) CopyToControlBuf((UCHAR *) textWithoutArea,
276 (UCHAR **)&textStart,
277 &textLength);
278 /* textStart is a pointer to the first non-kludge line */
279 xmsg = createXMSG(config,msg, NULL, forceattr,tossDir);
280 w_log( LL_SRCLINE, "%s:%d writing msg", __FILE__, __LINE__);
281 if (MsgWriteMsg(hmsg, 0, &xmsg, (byte *) textStart, (dword)
282 textLength, (dword) textLength,
283 (dword)strlen(ctrlBuff), (byte*)ctrlBuff)!=0)
284 w_log(LL_ERR, "Could not write msg in %s! Check the wholeness of messagebase, please.", echo->fileName);
285 else rc = 1; /* normal exit */
286
287 w_log( LL_SRCLINE, "%s:%d closing msg", __FILE__, __LINE__);
288 if (MsgCloseMsg(hmsg)!=0) {
289 w_log(LL_ERR, "Could not close msg in %s!", echo->fileName);
290 rc = 0;
291 }
292 nfree(ctrlBuff);
293
294 } else w_log(LL_ERR, "Could not create new msg in %s!", echo->fileName);
295 /* endif */
296 if (nopenpkt>=maxopenpkt-12) {
297 w_log( LL_SRCLINE, "%s:%d closing %s", __FILE__, __LINE__,echo->fileName);
298 MsgCloseArea(getHAREA(echo->harea));
299 echo->harea = NULL;
300 nopenpkt-=3;
301 }
302 } else w_log(LL_ERR, "Could not open/create EchoArea %s!", echo->fileName);
303 /* endif */
304 w_log( LL_SRCLINE, "%s:%d end rc=%d", __FILE__, __LINE__,rc);
305 return rc;
306 }
307
closeOpenedPkt(void)308 void closeOpenedPkt(void) {
309 unsigned int i;
310
311 for (i=0; i<config->linkCount; i++)
312 if (config->links[i]->pkt) {
313 if (closeCreatedPkt(config->links[i]->pkt))
314 w_log(LL_ERR,"can't close pkt: %s", config->links[i]->pktFile);
315 config->links[i]->pkt = NULL;
316 nopenpkt--;
317 }
318 for (i=0; i<config->echoAreaCount; i++)
319 if (getHAREA(config->echoAreas[i].harea)) {
320 w_log( LL_SRCLINE, "%s:%d closing %s", __FILE__, __LINE__,config->echoAreas[i].fileName);
321 MsgCloseArea(getHAREA(config->echoAreas[i].harea));
322 config->echoAreas[i].harea = NULL;
323 nopenpkt-=3;
324 }
325 for (i=0; i<config->netMailAreaCount; i++)
326 if (getHAREA(config->netMailAreas[i].harea)) {
327 w_log( LL_SRCLINE, "%s:%d closing %s", __FILE__, __LINE__,config->netMailAreas[i].fileName);
328 MsgCloseArea(getHAREA(config->netMailAreas[i].harea));
329 config->netMailAreas[i].harea = NULL;
330 nopenpkt-=3;
331 }
332 for (i=0; i<config->localAreaCount; i++)
333 {
334 if (getHAREA(config->localAreas[i].harea)) {
335 w_log( LL_SRCLINE, "%s:%d closing %s", __FILE__, __LINE__,config->localAreas[i].fileName);
336 MsgCloseArea(getHAREA(config->localAreas[i].harea));
337 config->localAreas[i].harea = NULL;
338 nopenpkt-=3;
339 }
340 }
341 if (getHAREA(config->badArea.harea)) {
342 w_log( LL_SRCLINE, "%s:%d closing %s", __FILE__, __LINE__,config->badArea.fileName);
343 MsgCloseArea(getHAREA(config->badArea.harea));
344 config->badArea.harea = NULL;
345 nopenpkt-=3;
346 }
347 if (getHAREA(config->dupeArea.harea)) {
348 w_log( LL_SRCLINE, "%s:%d closing %s", __FILE__, __LINE__,config->dupeArea.fileName);
349 MsgCloseArea(getHAREA(config->dupeArea.harea));
350 config->dupeArea.harea = NULL;
351 nopenpkt-=3;
352 }
353 }
354
forwardToLinks(s_message * msg,s_area * echo,s_arealink ** newLinks,s_seenBy ** seenBys,UINT * seenByCount,s_seenBy ** path,UINT * pathCount)355 void forwardToLinks(s_message *msg, s_area *echo, s_arealink **newLinks,
356 s_seenBy **seenBys, UINT *seenByCount,
357 s_seenBy **path, UINT *pathCount) {
358 unsigned int i, rc=0;
359 ULONG len;
360 FILE *f=NULL;
361 s_pktHeader header;
362 char *start = NULL, *text = NULL, *seenByText = NULL, *pathText = NULL;
363 char *debug=NULL;
364
365 if (newLinks[0] == NULL) return;
366
367 if (echo->debug) {
368 xstrscat(&debug, config->logFileDir,
369 (echo->DOSFile) ? "common" : echo->areaName,
370 ".dbg", NULLP);
371
372 if (config->areasFileNameCase == eLower)
373 debug = strLower(debug);
374 else
375 debug = strUpper(debug);
376
377 if ((f=fopen(debug,"a"))==NULL) {
378 w_log(LL_ERR,"can't open file: %s",debug);
379 }else w_log(LL_FILE,"toss.c:forwardToLinks(): opened %s (\"a\" mode)",debug);
380 nfree(debug);
381 }
382
383 if (echo->sbstripCount > 0) /* strip SEEN-BYs */
384 {
385 stripSeenByArray(seenBys, seenByCount, echo->sbstrip, echo->sbstripCount);
386 }
387
388 for (i=0; i<config->addToSeenCount; i++) {
389 (*seenByCount)++;
390 (*seenBys) = (s_seenBy*) safe_realloc(*seenBys,sizeof(s_seenBy)*(*seenByCount));
391 (*seenBys)[*seenByCount-1].net = (UINT16) config->addToSeen[i].net;
392 (*seenBys)[*seenByCount-1].node = (UINT16) config->addToSeen[i].node;
393 }
394 for (i=0; i<echo->sbaddCount; i++) {
395 (*seenByCount)++;
396 (*seenBys) = (s_seenBy*) safe_realloc(*seenBys,sizeof(s_seenBy)*(*seenByCount));
397 (*seenBys)[*seenByCount-1].net = (UINT16) echo->sbadd[i].net;
398 (*seenBys)[*seenByCount-1].node = (UINT16) echo->sbadd[i].node;
399 }
400
401 /* add our aka to seen-by (zonegating link must strip our aka) */
402 if (echo->useAka->point==0) {
403
404 for (i=0; i < *seenByCount; i++) {
405 if ((*seenBys)[i].net == echo->useAka->net &&
406 (*seenBys)[i].node == echo->useAka->node) break;
407 }
408
409 if (*seenByCount==i) {
410 (*seenBys) = (s_seenBy*)
411 safe_realloc((*seenBys), sizeof(s_seenBy) * (*seenByCount+1));
412 (*seenBys)[*seenByCount].net = (UINT16) echo->useAka->net;
413 (*seenBys)[*seenByCount].node = (UINT16) echo->useAka->node;
414 (*seenByCount)++;
415 }
416 }
417
418 /* add seenBy for newLinks */
419 for (i=0; i<echo->downlinkCount; i++) {
420
421 /* no link at this index -> break */
422 if (newLinks[i] == NULL) break;
423 /* don't include points in SEEN-BYs */
424 if (newLinks[i]->link->hisAka.point != 0) continue;
425 /* fix for IgnoreSeen & -sbign */
426 if (newLinks[i]->link->sb == 1) continue;
427
428 (*seenBys) = (s_seenBy*) safe_realloc((*seenBys), sizeof(s_seenBy) * (*seenByCount+1));
429 (*seenBys)[*seenByCount].net = (UINT16) newLinks[i]->link->hisAka.net;
430 (*seenBys)[*seenByCount].node = (UINT16) newLinks[i]->link->hisAka.node;
431 (*seenByCount)++;
432 }
433
434 sortSeenBys((*seenBys), *seenByCount);
435
436 #ifdef DEBUG_HPT
437 for (i=0; i< *seenByCount;i++) printf("%u/%u ", (*seenBys)[i].net, (*seenBys)[i].node);
438 #endif
439
440 if (*pathCount > 0) {
441 if (((*path)[*pathCount-1].net != echo->useAka->net) ||
442 ((*path)[*pathCount-1].node != echo->useAka->node)) {
443 /* add our aka to path */
444 (*path) = (s_seenBy*) safe_realloc((*path), sizeof(s_seenBy) * (*pathCount+1));
445 (*path)[*pathCount].net = (UINT16) echo->useAka->net;
446 (*path)[*pathCount].node = (UINT16) echo->useAka->node;
447 (*pathCount)++;
448 }
449 } else {
450 (*pathCount) = 0;
451 (*path) = (s_seenBy*) safe_realloc((*path),sizeof(s_seenBy));
452 (*path)[*pathCount].net = (UINT16) echo->useAka->net;
453 (*path)[*pathCount].node = (UINT16) echo->useAka->node;
454 (*pathCount) = 1;
455 }
456
457 #ifdef DEBUG_HPT
458 for (i=0; i< *pathCount;i++) printf("%u/%u ", (*path)[i].net, (*path)[i].node);
459 #endif
460
461 text = strrstr(msg->text, " * Origin:"); /* jump over Origin */
462 if (text) { /* origin was found */
463 start = strrchr(text, ')');
464 if (start) start++; /* normal origin */
465 else {
466 start = text; /* broken origin */
467 while(*start && *start!='\r') start++;
468 }
469 *start='\0';
470 } else { /* no Origin found */
471 text = msg->text;
472 start = strstr(text, "\rSEEN-BY: ");
473 if (start == NULL) start = strstr(text, "SEEN-BY: ");
474 if (start) *start='\0';
475 /* find start of PATH in Msg */
476 start = strstr(text, "\001PATH: ");
477 if (start) *start='\0';
478 else start = text+strlen(text);
479 }
480 msg->textLength = (size_t) (start - msg->text);
481
482 /* create new seenByText */
483 seenByText = createControlText(*seenBys, *seenByCount, "SEEN-BY: ");
484 pathText = createControlText(*path, *pathCount, "\001PATH: ");
485 xstrscat(&msg->text, "\r", seenByText, pathText, NULLP);
486 msg->textLength += 1 + strlen(seenByText) + strlen(pathText);
487 nfree(seenByText);
488 nfree(pathText);
489
490 if (echo->debug) {
491 debug = (char *) GetCtrlToken((byte *)msg->text, (byte *)"MSGID");
492 if (f && debug) {
493 fputs("\n[",f);
494 fputs(debug,f);
495 fputs("] ",f);
496 }
497 nfree(debug);
498 }
499
500 /* add msg to the pkt's of the downlinks */
501 if (maxopenpkt == 0) setmaxopen();
502 for (i = 0; i<echo->downlinkCount; i++) {
503
504 /* no link at this index -> break; */
505 if (newLinks[i] == NULL) break;
506 #ifdef DO_PERL
507 if ( !perl_export(echo, newLinks[i]->link, msg) ) continue;
508 #endif
509 /* check packet size */
510 if (newLinks[i]->link->pktFile != NULL && newLinks[i]->link->pktSize != 0) {
511 len = newLinks[i]->link->pkt ? ftell(newLinks[i]->link->pkt) : fsize(newLinks[i]->link->pktFile);
512 if (len >= (newLinks[i]->link->pktSize * 1024L)) { /* Stop writing to pkt */
513 if (newLinks[i]->link->pkt) {
514 fclose(newLinks[i]->link->pkt);
515 newLinks[i]->link->pkt = NULL;
516 nopenpkt--;
517 }
518 nfree(newLinks[i]->link->pktFile);
519 nfree(newLinks[i]->link->packFile);
520 }
521 }
522
523 /* create pktfile if necessary */
524 if (newLinks[i]->link->pktFile == NULL) {
525 /* pktFile does not exist */
526 if ( createTempPktFileName(newLinks[i]->link) )
527 exit_hpt("Could not create new pkt!",1);
528 }
529
530 makePktHeader(NULL, &header);
531 header.origAddr = *(newLinks[i]->link->ourAka);
532 header.destAddr = newLinks[i]->link->hisAka;
533 if (newLinks[i]->link->pktPwd != NULL)
534 strcpy(header.pktPassword, newLinks[i]->link->pktPwd);
535 if (newLinks[i]->link->pkt == NULL) {
536 newLinks[i]->link->pkt = openPktForAppending(newLinks[i]->link->pktFile, &header);
537 nopenpkt++;
538 }
539
540 /* an echomail msg must be adressed to the link */
541 msg->destAddr = header.destAddr;
542 /* .. and must come from us */
543 msg->origAddr = header.origAddr;
544 rc += writeMsgToPkt(newLinks[i]->link->pkt, *msg);
545 if (rc)
546 {
547 w_log(LL_ERR,"can't write msg to pkt: %s", newLinks[i]->link->pktFile);
548 exit_hpt("Can't write msg to pkt!", 1);
549 }
550 if (nopenpkt >= maxopenpkt-12 || /* std streams, in pkt, msgbase, log */
551 (newLinks[i]->link->pktSize && ftell(newLinks[i]->link->pkt)>= (long)newLinks[i]->link->pktSize*1024L)) {
552 rc += closeCreatedPkt(newLinks[i]->link->pkt);
553 if (rc) w_log(LL_ERR,"can't close pkt: %s",
554 newLinks[i]->link->pktFile);
555 newLinks[i]->link->pkt = NULL;
556 nopenpkt--;
557 }
558 if (f) {
559 if (rc) fputs(" failed: ",f);
560 fputs(aka2str(header.destAddr),f);
561 fputc('>',f);
562 fputs(get_filename(newLinks[i]->link->pktFile),f);
563 fputc(' ',f);
564 }
565 if (rc==0) statToss.exported++;
566 else rc=0;
567 #ifdef ADV_STAT
568 if (config->advStatisticsFile != NULL) put_stat(echo, &(header.destAddr), stOUT, msg->textLength+strlen(msg->text+msg->textLength));
569 #endif
570 }
571
572 if (f) fclose(f);
573 return;
574 }
575
forwardMsgToLinks(s_area * echo,s_message * msg,hs_addr pktOrigAddr)576 void forwardMsgToLinks(s_area *echo, s_message *msg, hs_addr pktOrigAddr)
577 {
578 s_seenBy *seenBys = NULL, *tempSeenBys = NULL, *path = NULL;
579 UINT seenByCount = 0 , tempSeenByCount = 0, pathCount = 0;
580
581 /* links who does not have their aka in seenBys and thus have not got the echomail */
582 s_arealink **newLinks = NULL, **zoneLinks = NULL, **otherLinks = NULL;
583
584 createSeenByArrayFromMsg(echo, msg, &seenBys, &seenByCount);
585 createPathArrayFromMsg(msg, &path, &pathCount);
586
587 createNewLinkArray(seenBys, seenByCount, echo, &newLinks, &zoneLinks, &otherLinks, pktOrigAddr);
588
589 if(newLinks)
590 forwardToLinks(msg, echo, newLinks, &seenBys, &seenByCount, &path, &pathCount);
591
592 if (zoneLinks) {
593 /* strip SEEN-BYs when zone-gating and sbkeepAll is disabled */
594 if ((echo->sbkeep_all == 0) && (echo->useAka->zone != pktOrigAddr.zone)) {
595 if (echo->sbkeepCount == 0) {
596 seenByCount = 0; /* strip all SEEN-BYs */
597 }
598 else {
599 /* keep SEEN-BYs found in sbkeep */
600 createFilteredSeenByArray(seenBys, seenByCount, &tempSeenBys,
601 &tempSeenByCount, echo->sbkeep, echo->sbkeepCount);
602 nfree(seenBys);
603 seenBys = tempSeenBys;
604 seenByCount = tempSeenByCount;
605 }
606 }
607
608 forwardToLinks(msg, echo, zoneLinks, &seenBys, &seenByCount, &path, &pathCount);
609 }
610
611 if(otherLinks)
612 {
613 nfree(seenBys);
614 seenBys = memdup( path, sizeof(s_seenBy) * pathCount );
615 seenByCount = pathCount;
616 forwardToLinks(msg, echo, otherLinks, &seenBys, &seenByCount, &path, &pathCount);
617 }
618
619 nfree(seenBys);
620 nfree(path);
621 nfree(newLinks);
622 nfree(zoneLinks);
623 nfree(otherLinks);
624 }
625
626 /* return value: 1 if success, 0 if fail */
627 /* writeAccess MUST BE unsigned !!! */
putMsgInBadArea(s_message * msg,hs_addr pktOrigAddr,unsigned writeAccess)628 int putMsgInBadArea(s_message *msg, hs_addr pktOrigAddr, unsigned writeAccess)
629 {
630 char *tmp = NULL, *line = NULL, *textBuff=NULL, *areaName=NULL, *reason=NULL;
631 char buff[128] = "";
632
633 w_log(LL_FUNC, "putMsgInBadArea() begin");
634 statToss.bad++;
635
636 /* get real name area */
637 line = strchr(msg->text, '\r');
638 if(line == NULL || strncmp(msg->text,"AREA:",5)!=0)
639 areaName = xstrcat(&areaName, "no areatag");
640 else {
641 *line = 0;
642 xstrcat(&areaName, msg->text+5);
643 *line = '\r';
644 }
645
646 if(writeAccess>BM_MAXERROR){
647 reason = "Another error";
648 }else if(writeAccess==BM_MSGAPI_ERROR){
649 reason = strncat( strcpy(buff,"MSGAPIERR: "), strmerr(msgapierr), sizeof(buff)-sizeof("MSGAPIERR: ") );
650 }else{
651 reason = BadmailReasonString[writeAccess];
652 }
653 w_log(LL_ECHOMAIL, "Badmail reason: %s (AREA: %s)", reason, areaName);
654
655 #ifdef DO_PERL
656 if (perltossbad(msg, areaName, pktOrigAddr, reason)) {
657 nfree(areaName);
658 nfree(msg->text);
659 w_log(LL_FUNC, "putMsgInBadArea():perltossbad OK (rc=1)");
660 return 1;
661 }
662 #endif
663
664 tmp = msg->text;
665
666 while ((line = strchr(tmp, '\r')) != NULL) {
667 if (*(line+1) == '\x01') tmp = line+1;
668 else { tmp = line+1; *line = 0; break; }
669 }
670
671 xstrscat(&textBuff, msg->text, "\rFROM: ", aka2str(pktOrigAddr), "\rREASON: ", reason, "\r", NULLP);
672
673 if (areaName) xscatprintf(&textBuff, "AREANAME: %s\r\r", areaName);
674 xstrcat(&textBuff, tmp);
675 nfree(areaName);
676 nfree(msg->text);
677 msg->text = textBuff;
678 msg->textLength = strlen(msg->text);
679 if (putMsgInArea(&(config->badArea), msg, 0, 0)) {
680 config->badArea.imported++;
681 w_log(LL_FUNC, "putMsgInBadArea() OK");
682 return 1;
683 }
684 w_log(LL_FUNC, "putMsgInBadArea() failed");
685 return 0;
686 }
687
makeMsgToSysop(char * areaName,hs_addr fromAddr,ps_addr uplinkAddr)688 void makeMsgToSysop(char *areaName, hs_addr fromAddr, ps_addr uplinkAddr)
689 {
690 s_area *echo = NULL;
691 unsigned int i, netmail=0;
692 char *buff=NULL;
693 char *strbeg=NULL;
694
695 if (config->ReportTo) {
696 if (stricmp(config->ReportTo,"netmail")==0) netmail=1;
697 else if (getNetMailArea(config, config->ReportTo) != NULL) netmail=1;
698 } else netmail=1;
699
700 echo = getArea(config, areaName);
701
702 if (echo == &(config->badArea)) return;
703
704 for (i = 0; i < config->addrCount; i++) {
705 if (echo->useAka == &(config->addr[i])) {
706 if (msgToSysop[i] == NULL) {
707
708 msgToSysop[i] = makeMessage(echo->useAka,
709 echo->useAka,
710 robot->fromName ? robot->fromName : versionStr,
711 netmail ? (config->sysop ? config->sysop : "Sysop") : "All", "Created new areas",
712 netmail,
713 robot->reportsAttr);
714 msgToSysop[i]->text = createKludges(config,
715 netmail ? NULL : config->ReportTo,
716 echo->useAka, echo->useAka,
717 versionStr);
718
719 if (robot->reportsFlags)
720 xstrscat(&(msgToSysop[i]->text), "\001FLAGS ",
721 robot->reportsFlags, "\r", NULLP);
722 xstrscat(&(msgToSysop[i]->text), "Action Name",
723 print_ch(49, ' '), "By\r", NULLP);
724 /* Shitty static variables .... */
725 xstrscat(&(msgToSysop[i]->text), print_ch(79, '-'), "\r", NULLP);
726 msgToSysop[i]->recode |= (REC_HDR|REC_TXT);
727 w_log(LL_NETMAIL,"Created msg to sysop");
728 }
729
730 /* New report generation */
731 buff = safe_strdup("");
732 if (config->reportRequester) xstrcat(&buff, aka2str(fromAddr));
733 if (uplinkAddr != NULL) { /* autocreation with forward request */
734 xstrscat(&buff, " from ", aka2str(*uplinkAddr), NULLP);
735 }
736 xstrscat(&strbeg, "Created ", echo->areaName, NULLP);
737
738 if (echo->description) {
739 if (strlen(strbeg) + strlen(echo->description) >=77) {
740 xstrscat(&(msgToSysop[i]->text), strbeg, "\r", NULLP);
741 nfree(strbeg);
742 xstrcat(&strbeg, print_ch(9, ' '));
743 } else {
744 xstrcat(&strbeg, " ");
745 }
746 xstrscat(&strbeg, "\"", echo->description, "\"", NULLP);
747 }
748
749 xstrcat(&(msgToSysop[i]->text), strbeg);
750
751 if (strlen(strbeg) + strlen(buff) >= 79) {
752 xstrscat(&(msgToSysop[i]->text), "\r", print_ch(79-strlen(buff), ' '), buff, "\r", NULLP);
753 } else if (strlen(strbeg) <62 && strlen(buff) < 79-62) { /* most beautiful */
754 xstrscat(&(msgToSysop[i]->text), print_ch(62-strlen(strbeg), ' '), buff, "\r", NULLP);
755 } else {
756 xstrscat(&(msgToSysop[i]->text), print_ch(79-strlen(strbeg)-strlen(buff), ' '), buff, "\r", NULLP);
757 }
758 nfree(buff);
759 nfree(strbeg);
760
761 break;
762 }
763 }
764
765 }
766
writeMsgToSysop()767 void writeMsgToSysop()
768 {
769 char *ptr = NULL, *seenByPath = NULL;
770 s_area *echo = NULL;
771 unsigned int i, ccrc = 0;
772 s_seenBy *seenBys = NULL;
773
774 for (i = 0; i < config->addrCount; i++) {
775 if (msgToSysop[i]) {
776 xscatprintf(&(msgToSysop[i]->text), " \r--- %s\r * Origin: %s (%s)\r",
777 (config->tearline) ? config->tearline : "",
778 (config->origin) ? config->origin : config->name,
779 aka2str(msgToSysop[i]->origAddr));
780 msgToSysop[i]->textLength = strlen(msgToSysop[i]->text);
781
782 #ifdef DO_PERL
783 perl_robotmsg(msgToSysop[i], "tosysop");
784 #endif
785
786 if (msgToSysop[i]->netMail == 1)
787 {
788 /* FIXME: should be putMsgInArea */
789 processNMMsg(msgToSysop[i], NULL, config->ReportTo ?
790 getNetMailArea(config, config->ReportTo) : NULL, 1, 0);
791 writeEchoTossLogEntry(config->ReportTo?config->ReportTo:config->netMailAreas[0].areaName);
792 }
793 else {
794 /* get echoarea for this msg */
795 ptr = strchr(msgToSysop[i]->text, '\r');
796 *ptr = '\0'; echo = getArea(config, msgToSysop[i]->text + 5); *ptr = '\r';
797
798 if (echo != &(config->badArea)) {
799 if (config->carbonCount != 0)
800 ccrc = carbonCopy(msgToSysop[i], NULL, echo);
801 if (echo->msgbType != MSGTYPE_PASSTHROUGH && ccrc <= 1) {
802 putMsgInArea(echo, msgToSysop[i],1, (MSGSCANNED|MSGSENT|MSGLOCAL));
803 echo->imported++; /* area has got new messages */
804 }
805
806 seenBys = (s_seenBy*) safe_malloc(sizeof(s_seenBy)*(echo->downlinkCount+1));
807 seenBys[0].net = (UINT16) echo->useAka->net;
808 seenBys[0].node = (UINT16) echo->useAka->node;
809 sortSeenBys(seenBys, 1);
810
811 seenByPath = createControlText(seenBys, 1, "SEEN-BY: ");
812 nfree(seenBys);
813
814 /* path line */
815 /* only include node-akas in path */
816 if (echo->useAka->point == 0)
817 xscatprintf(&seenByPath, "\001PATH: %u/%u\r", echo->useAka->net, echo->useAka->node);
818 xstrcat(&(msgToSysop[i]->text), seenByPath);
819 nfree(seenByPath);
820 if (echo->downlinkCount > 0) {
821 /* recoding from internal to transport charSet */
822 if (config->outtab) {
823 if (msgToSysop[i]->recode & REC_HDR) {
824 recodeToTransportCharset((char*)msgToSysop[i]->fromUserName);
825 recodeToTransportCharset((char*)msgToSysop[i]->toUserName);
826 recodeToTransportCharset((char*)msgToSysop[i]->subjectLine);
827 msgToSysop[i]->recode &= ~REC_HDR;
828 }
829 if (msgToSysop[i]->recode & REC_TXT) {
830 recodeToTransportCharset((char*)msgToSysop[i]->text);
831 msgToSysop[i]->recode &= ~REC_TXT;
832 }
833 }
834 forwardMsgToLinks(echo, msgToSysop[i], msgToSysop[i]->origAddr);
835 closeOpenedPkt();
836 writeEchoTossLogEntry(echo->areaName);
837 tossTempOutbound(config->tempOutbound);
838 }
839 } else {
840 putMsgInBadArea(msgToSysop[i], msgToSysop[i]->origAddr, 0);
841 }
842 }
843 }
844 }
845
846 }
847
processEMMsg(s_message * msg,hs_addr pktOrigAddr,int dontdocc,dword forceattr)848 int processEMMsg(s_message *msg, hs_addr pktOrigAddr, int dontdocc, dword forceattr)
849 {
850 char *area=NULL, *p = NULL, *q = NULL;
851 s_message* messCC = NULL;
852 s_area *echo=&(config->badArea);
853 s_link *link = NULL;
854 unsigned int days = 0;
855 struct tm msg_tm;
856 time_t msgTime, diffTime;
857 flag_t tFlag;
858 int writeAccess = 0, rc = 0, ccrc = 0;
859
860 w_log(LL_FUNC, "%s::processEMMsg() begin", __FILE__);
861
862 p = strchr(msg->text,'\r');
863 if (p) {
864 *p='\0';
865 q = msg->text+5;
866 while (*q == ' ') q++;
867 xstrcat(&area, q);
868 echo = getArea(config, area);
869 *p='\r';
870 }
871
872 link = getLinkFromAddr(config, pktOrigAddr);
873
874 /* no area found -- trying to autocreate echoarea */
875 if (echo == &(config->badArea)) {
876 /* check if we should not refuse this area */
877 /* checking for autocreate option */
878 if ((link != NULL) && (link->areafix.autoCreate != 0)) {
879 if (BM_MAIL_OK == (writeAccess = autoCreate(area, NULL, pktOrigAddr, NULL)))
880 echo = getArea(config, area);
881 else rc = putMsgInBadArea(msg, pktOrigAddr, writeAccess);
882 } /* can't create echoarea - put msg in BadArea */
883 else rc = putMsgInBadArea(msg, pktOrigAddr, writeAccess);
884 }
885
886 nfree(area);
887
888 if (echo != &(config->badArea)) {
889 /* area is autocreated! */
890
891 /* cheking access of this link */
892 writeAccess = checkAreaLink(echo, pktOrigAddr, 0);
893 if (writeAccess)
894 {
895 rc = putMsgInBadArea(msg, pktOrigAddr, writeAccess);
896 #ifdef ADV_STAT
897 if (config->advStatisticsFile != NULL) put_stat(echo, &pktOrigAddr, stBAD, 0);
898 #endif
899 /* notify link about bad post */
900 if ((link != NULL) && (link->sendNotifyMessages)) {
901 s_message *tmpmsg;
902 char *reason = NULL;
903
904 if (writeAccess > BM_MAXERROR) {
905 reason = "Unknown error";
906 } else {
907 reason = BadmailReasonString[writeAccess];
908 }
909
910 tmpmsg = makeMessage(link->ourAka, &(link->hisAka),
911 robot->fromName ? robot->fromName : versionStr,
912 link->name, "Notification message", 1,
913 link->areafix.reportsAttr ? link->areafix.reportsAttr : robot->reportsAttr);
914 tmpmsg->text = createKludges(config, NULL, link->ourAka,
915 &(link->hisAka), versionStr);
916 if (link->areafix.reportsFlags)
917 xstrscat(&(tmpmsg->text), "\001FLAGS ", link->areafix.reportsFlags, "\r",NULLP);
918 else if (robot->reportsFlags)
919 xstrscat(&(tmpmsg->text), "\001FLAGS ", robot->reportsFlags, "\r",NULLP);
920
921 xstrcat(&tmpmsg->text, "\r Your message was moved to badmail with the following reason:\r\r");
922 xscatprintf(&tmpmsg->text, " %s\r\r", reason);
923 xstrcat(&tmpmsg->text, " Header of original message:\r\r");
924 xscatprintf(&tmpmsg->text, " Area: %s\r", echo->areaName);
925 xscatprintf(&tmpmsg->text, " Date: %s\r", msg->datetime);
926 xscatprintf(&tmpmsg->text, " From: %s, %s\r", msg->fromUserName, aka2str(msg->origAddr));
927 xscatprintf(&tmpmsg->text, " To: %s\r", msg->toUserName);
928 xscatprintf(&tmpmsg->text, " Subject: %s\r", msg->subjectLine);
929 xstrcat(&tmpmsg->text, "\r Please contact sysop if you think this is a mistake!\r");
930 xscatprintf(&tmpmsg->text, "\r\r--- %s areafix\r", versionStr);
931
932 tmpmsg->textLength = strlen(tmpmsg->text);
933 processNMMsg(tmpmsg, NULL, getRobotsArea(config), 0, MSGLOCAL);
934 writeEchoTossLogEntry(getRobotsArea(config)->areaName);
935 closeOpenedPkt();
936 freeMsgBuffers(tmpmsg);
937 nfree(tmpmsg);
938 nfree(reason);
939
940 w_log( LL_AREAFIX, "areafix: write notification msg for %s",aka2str(link->hisAka));
941 }
942 }
943
944 /* check age of message */
945 if (writeAccess == 0) /* ok to proceed */
946 {
947 /* get message age if tooOld or tooNew feature is enabled */
948 if ( (echo->tooOld > 0) || (echo->tooNew > 0) )
949 {
950 /* get time from message */
951 tFlag = parse_ftsc_date(&msg_tm, (char*)msg->datetime);
952 if (! (tFlag & FTSC_BROKEN))
953 {
954 msgTime = mktime(&msg_tm);
955 if (msgTime != (time_t)-1)
956 {
957 diffTime = abs(globalTime - msgTime);
958 diffTime /= (60 * 60 * 24); /* convert to days */
959 days = (unsigned int)diffTime;
960 /* tooOld */
961 if ((echo->tooOld > 0) && globalTime > msgTime) {
962 if (days > echo->tooOld) writeAccess = BM_TOO_OLD;
963 }
964 /* tooNew */
965 else if ((echo->tooNew > 0) && globalTime < msgTime) {
966 if (days > echo->tooNew) writeAccess = BM_TOO_NEW;
967 }
968 }
969 }
970 }
971
972 if (writeAccess) /* on any problem move message to BadArea */
973 {
974 rc = putMsgInBadArea(msg, pktOrigAddr, writeAccess);
975 }
976 }
977
978 if (writeAccess == 0) /* ok to proceed */
979 { /* access ok - process msg */
980 int not_dupe = 1;
981
982 #ifdef DO_PERL
983 w_log(LL_SRCLINE, "toss.c:%u:processEMMsg() #ifdef DO_PERL", __LINE__);
984 if ((rc = perlfilter(msg, pktOrigAddr, -1)) == 1)
985 return not_dupe = 0;
986 else if (rc == 2)
987 return 1;
988 #endif
989
990 if (not_dupe) not_dupe = dupeDetection(echo, *msg);
991 if (not_dupe) {
992 /* no dupe */
993
994 messCC = MessForCC(msg); /* make copy of original message */
995
996 statToss.echoMail++;
997
998 /* if only one downlink, we've got the mail from him */
999 if ((echo->downlinkCount > 1) ||
1000 ((echo->downlinkCount > 0) &&
1001 /* mail from us */
1002 (addrComp(pktOrigAddr,*echo->useAka)==0)))
1003 forwardMsgToLinks(echo, msg, pktOrigAddr);
1004 w_dbglog( LL_SRCLINE, "%s::processEMMsg():%d", __FILE__, __LINE__);
1005 /* todo: remove TID from local-generated msgs by hpt post -x
1006 * (if (addrComp(pktOrigAddr,*echo->useAka)==0)) */
1007
1008 if (messCC && !dontdocc)
1009 ccrc=carbonCopy(messCC, NULL, echo);
1010 w_dbglog( LL_SRCLINE, "%s::processEMMsg():%d", __FILE__, __LINE__);
1011 if (ccrc <= 1) {
1012 echo->imported++; /* area has got new messages */
1013 #ifdef ADV_STAT
1014 if (config->advStatisticsFile != NULL) put_stat(echo, &pktOrigAddr, stNORM, msg->textLength);
1015 #endif
1016 if (echo->msgbType != MSGTYPE_PASSTHROUGH) {
1017 if(messCC)
1018 rc = putMsgInArea(echo, messCC, 1, forceattr);
1019 else
1020 rc = putMsgInArea(echo, msg, 1, forceattr);
1021 statToss.saved += rc;
1022 }
1023 else { /* passthrough */
1024 /*
1025 if (echo->downlinkCount==1 && dontdocc==0)
1026 rc = putMsgInBadArea(msg, pktOrigAddr, 10);
1027 else {
1028 statToss.passthrough++;
1029 rc = 1;
1030 }
1031 */
1032 statToss.passthrough++;
1033 rc = 1;
1034 }
1035 } else rc = 1; /* normal exit for carbon move & delete */
1036 freeMsgBuffers(messCC);
1037 nfree(messCC);
1038 } else {
1039 /* msg is dupe */
1040 if (echo->dupeCheck == dcMove) {
1041 /* rc = putMsgInDupeArea(pktOrigAddr, msg, forceattr); */
1042 rc = putMsgInArea(&(config->dupeArea), msg, 0, forceattr);
1043 } else rc = 1;
1044 statToss.dupes++;
1045 #ifdef ADV_STAT
1046 if (config->advStatisticsFile != NULL) put_stat(echo, &pktOrigAddr, stDUPE, 0);
1047 #endif
1048 if (rc) config->dupeArea.imported++;
1049 }
1050 }
1051 }
1052 w_log(LL_FUNC, "%s::processEMMsg() rc=%d", __FILE__, rc);
1053 return rc;
1054 }
1055
processNMMsg(s_message * msg,s_pktHeader * pktHeader,s_area * area,int dontdocc,dword forceattr)1056 int processNMMsg(s_message *msg, s_pktHeader *pktHeader, s_area *area, int dontdocc, dword forceattr)
1057 {
1058 HAREA netmail;
1059 HMSG msgHandle;
1060 UINT len = 0;
1061 char *bodyStart = NULL; /* msg-body without kludgelines start */
1062 char *ctrlBuf = NULL; /* Kludgelines */
1063 XMSG msgHeader;
1064 /* char *slash = NULL; */
1065 unsigned int rc = 0, ccrc = 0, i;
1066
1067 if (area == NULL) {
1068 area = &(config->netMailAreas[0]);
1069 for(i=0; i<config->netMailAreaCount; i++) {
1070 if(addrComp(msg->destAddr,*(config->netMailAreas[i].useAka))==0) {
1071 area = &(config->netMailAreas[i]);
1072 break;
1073 }
1074 }
1075 }
1076
1077 if (dupeDetection(area, *msg)==0) {
1078 /* msg is dupe */
1079 if (area->dupeCheck == dcMove) {
1080 rc = putMsgInArea(&(config->dupeArea), msg, 0, forceattr);
1081 } else rc = 1;
1082 statToss.dupes++;
1083 if (rc) config->dupeArea.imported++;
1084 return rc;
1085 }
1086
1087 if ((config->carbonCount!=0)&&(!dontdocc)) ccrc = carbonCopy(msg, NULL, area);
1088 if (ccrc > 1) return 1; /* carbon del or move */
1089
1090 netmail = MsgOpenArea((unsigned char *) area -> fileName, MSGAREA_CRIFNEC,
1091 (word) area -> msgbType);
1092
1093 if (netmail != NULL) {
1094 msgHandle = MsgOpenMsg(netmail, MOPEN_CREATE, 0);
1095
1096 if (msgHandle != NULL) {
1097 area -> imported++; /* area has got new messages */
1098
1099 /* recode from TransportCharset to internal Charset */
1100 if ((config->recodeMsgBase) && (config->intab != NULL)) {
1101 if ((msg->recode & REC_HDR)==0) {
1102 recodeToInternalCharset((char*)msg->fromUserName);
1103 recodeToInternalCharset((char*)msg->toUserName);
1104 recodeToInternalCharset((char*)msg->subjectLine);
1105 msg->recode |= REC_HDR;
1106 }
1107 if ((msg->recode & REC_TXT)==0) {
1108 recodeToInternalCharset((char*)msg->text);
1109 msg->recode |= REC_TXT;
1110 }
1111 }
1112
1113 msgHeader = createXMSG(config,msg, pktHeader, forceattr,tossDir);
1114 #ifdef DO_PERL
1115 /* val: force attrs set by perlfilter() hook */
1116 if (perl_setattr) msgHeader.attr = msg->attributes;
1117 #endif
1118 /* Create CtrlBuf for SMAPI */
1119 len = msg->textLength;
1120 ctrlBuf = (char *) CopyToControlBuf((UCHAR *) msg->text, (UCHAR **)&bodyStart, &len);
1121 /* write message */
1122 if (MsgWriteMsg(msgHandle, 0, &msgHeader, (UCHAR *)
1123 bodyStart, len, len, strlen(ctrlBuf)+1,
1124 (UCHAR *) ctrlBuf)!=0)
1125 w_log(LL_ERR, "Could not write msg to NetmailArea %s! Check the wholeness of messagebase, please.", area->areaName);
1126 else rc = 1; /* normal exit */
1127 nfree(ctrlBuf);
1128 if (MsgCloseMsg(msgHandle)!=0) { /* can't close */
1129 w_log(LL_ERR,"Could not close msg in NetmailArea %s",area->areaName);
1130 rc = 0;
1131 } else { /* normal close */
1132 w_log(LL_NETMAIL, "Wrote Netmail: %u:%u/%u.%u -> %u:%u/%u.%u", msg->origAddr.zone, msg->origAddr.net, msg->origAddr.node, msg->origAddr.point, msg->destAddr.zone, msg->destAddr.net, msg->destAddr.node, msg->destAddr.point);
1133 statToss.netMail++;
1134 }
1135
1136 } else {
1137 w_log(LL_ERR, "Could not create new msg in NetmailArea %s", area -> areaName);
1138 } /* endif */
1139
1140 MsgCloseArea(netmail);
1141 } else {
1142 fprintf(stderr, "msgapierr - %u\n", msgapierr);
1143 w_log(LL_ERR, "Could not open NetmailArea %s", area -> areaName);
1144 } /* endif */
1145 return rc;
1146 }
1147
processMsg(s_message * msg,s_pktHeader * pktHeader,int secure)1148 int processMsg(s_message *msg, s_pktHeader *pktHeader, int secure)
1149 {
1150 int rc;
1151
1152 w_log(LL_FUNC,"toss.c::processMsg()");
1153 statToss.msgs++;
1154 #ifdef DO_PERL
1155 w_log(LL_SRCLINE, "toss.c:%u:processMsg() #ifdef DO_PERL", __LINE__);
1156 if ((rc = perlfilter(msg, pktHeader->origAddr, secure)) == 1)
1157 return putMsgInBadArea(msg, pktHeader->origAddr, BM_DENY_BY_FILTER);
1158 else if (rc == 2)
1159 return 1;
1160 #else
1161 unused(secure);
1162 #endif
1163 if (msg->netMail == 1) {
1164 w_log(LL_NETMAIL, "Netmail from %s to %u:%u/%u.%u", aka2str(msg->origAddr),
1165 msg->destAddr.zone, msg->destAddr.net, msg->destAddr.node, msg->destAddr.point);
1166 if (config->areafixFromPkt &&
1167 isOurAka(config, msg->destAddr) &&
1168 strlen(msg->toUserName)>0 &&
1169 findInStrArray(robot->names,msg->toUserName) >=0) {
1170 rc = processAreaFix(msg, pktHeader, 0);
1171 } else
1172 rc = processNMMsg(msg, pktHeader, NULL, 0, 0);
1173 } else {
1174 rc = processEMMsg(msg, pktHeader->origAddr, 0, 0);
1175 } /* endif */
1176 w_log(LL_FUNC,"toss.c::processMsg() rc=%d", rc);
1177 return rc;
1178 }
1179
processPkt(char * fileName,e_tossSecurity sec)1180 int processPkt(char *fileName, e_tossSecurity sec)
1181 {
1182 FILE *pkt = NULL;
1183 s_pktHeader *header = NULL;
1184 s_message *msg = NULL;
1185 s_link *link = NULL;
1186 int rc = 0, msgrc = 0;
1187 long pktlen;
1188
1189 /* +AS+ */
1190 char *extcmd = NULL;
1191 int cmdexit;
1192 /* -AS- */
1193 char processIt = 0; /* processIt = 1, process all mails */
1194 /* processIt = 2, process only Netmail */
1195 /* processIt = 0, do not process pkt */
1196
1197 w_log(LL_FUNC,"toss.c::processPkt()");
1198
1199 if ((pktlen = fsize(fileName)) > 60) {
1200
1201 statToss.inBytes += pktlen;
1202
1203 /* +AS+ */
1204 if (config->processPkt)
1205 {
1206 extcmd = safe_malloc(strlen(config->processPkt)+strlen(fileName)+2);
1207 sprintf(extcmd,"%s %s",config->processPkt,fileName);
1208 w_log(LL_EXEC, "ProcessPkt: execute string \"%s\"",extcmd);
1209 if ((cmdexit = cmdcall(extcmd)) != 0)
1210 w_log(LL_ERR, "exec failed, code %d", cmdexit);
1211 nfree(extcmd);
1212 }
1213 /* -AS- */
1214 #ifdef DO_PERL
1215 if (perlpkt(fileName, (sec==secLocalInbound || sec==secProtInbound) ? 1 : 0))
1216 return 6;
1217 #endif
1218
1219 pkt = fopen(fileName, "rb");
1220 if (pkt == NULL) return 2;
1221 w_log(LL_FILE,"toss.c:processPkt(): opened '%s' (\"rb\" mode)",fileName);
1222
1223 header = openPkt(pkt);
1224 if (header != NULL) {
1225 /* if ((to_us(header->destAddr)==0) || (sec == secLocalInbound)) { */
1226 if ( isOurAka(config,header->destAddr) || (sec == secLocalInbound)) {
1227 w_log(LL_PKT, "pkt: %s [%s]", fileName, aka2str(header->origAddr));
1228 statToss.pkts++;
1229 link = getLinkFromAddr(config, header->origAddr);
1230 if ((link!=NULL) && (link->pktPwd==NULL) && (header->pktPassword[0]!='\000'))
1231 w_log(LL_ERR, "Unexpected Password %s.", header->pktPassword);
1232
1233 switch (sec) {
1234 case secLocalInbound:
1235 processIt = 1;
1236 break;
1237
1238 case secProtInbound:
1239 if ((link != NULL) && (link->pktPwd != NULL) && link->pktPwd[0]) {
1240 if (stricmp(link->pktPwd, header->pktPassword)==0) {
1241 processIt = 1;
1242 } else {
1243 if ( (header->pktPassword == NULL || header->pktPassword[0] == '\0') &&
1244 ((link->allowEmptyPktPwd == eSecure) || (link->allowEmptyPktPwd == eOn)) )
1245 {
1246 w_log(LL_WARN, "pkt: %s Warning: missing packet password from %i:%i/%i.%i",
1247 fileName, header->origAddr.zone, header->origAddr.net,
1248 header->origAddr.node, header->origAddr.point);
1249 processIt = 1;
1250 } else {
1251 w_log(LL_WARN, "pkt: %s Password Error for %i:%i/%i.%i",
1252 fileName, header->origAddr.zone, header->origAddr.net,
1253 header->origAddr.node, header->origAddr.point);
1254 rc = 1;
1255 }
1256 }
1257 } else if ((link != NULL) && ((link->pktPwd == NULL) || (strcmp(link->pktPwd, "")==0))) {
1258 processIt=1;
1259 } else /* if (link == NULL) */ {
1260 w_log(LL_ERR, "pkt: %s No Link for %i:%i/%i.%i, processing only Netmail",
1261 fileName, header->origAddr.zone, header->origAddr.net,
1262 header->origAddr.node, header->origAddr.point);
1263 processIt = 2;
1264 }
1265 break;
1266
1267 case secInbound:
1268 if ((link != NULL) && (link->pktPwd != NULL) && link->pktPwd[0]) {
1269
1270 if (header->pktPassword && stricmp(link->pktPwd, header->pktPassword)==0) {
1271 processIt = 1;
1272 } else {
1273 if ( (header->pktPassword == NULL || header->pktPassword[0] == '\0') &&
1274 (link->allowEmptyPktPwd == eOn) )
1275 {
1276 w_log(LL_ERR, "pkt: %s Warning: missing packet password from %i:%i/%i.%i",
1277 fileName, header->origAddr.zone, header->origAddr.net,
1278 header->origAddr.node, header->origAddr.point);
1279 processIt = 2; /* Unsecure inbound, do not process echomail */
1280 } else {
1281 w_log(LL_ERR, "pkt: %s Password Error for %i:%i/%i.%i",
1282 fileName, header->origAddr.zone, header->origAddr.net,
1283 header->origAddr.node, header->origAddr.point);
1284 rc = 1;
1285 }
1286 }
1287 } else if ((link != NULL) && ((link->pktPwd == NULL) || (strcmp(link->pktPwd, "")==0))) {
1288 processIt=1;
1289 } else /* if (link == NULL) */ {
1290 w_log(LL_ERR, "pkt: %s No Link for %i:%i/%i.%i, processing only Netmail",
1291 fileName, header->origAddr.zone, header->origAddr.net,
1292 header->origAddr.node, header->origAddr.point);
1293 processIt = 2;
1294 }
1295 break;
1296
1297 }
1298
1299 if (processIt != 0) {
1300 while ((msgrc = readMsgFromPkt(pkt, header, &msg)) == 1) {
1301 if (msg != NULL) {
1302 if ((processIt == 1) || ((processIt==2) && (msg->netMail==1))) {
1303 if (processMsg(msg, header,
1304 (sec==secLocalInbound ||
1305 sec==secProtInbound ||
1306 processIt == 1) ? 1 : 0) != 1 )
1307 if (putMsgInBadArea(msg, header->origAddr, BM_MSGAPI_ERROR)==0)
1308 rc = 5; /* can't write to badArea - rename to .err */
1309 } else rc = 1;
1310 freeMsgBuffers(msg);
1311 nfree(msg);
1312 }
1313 }
1314 if (msgrc==2) rc = 3; /* rename to .bad (wrong msg format) */
1315 /* real time of process pkt & msg without external programs */
1316 }
1317
1318 } else {
1319 while ((msgrc = readMsgFromPkt(pkt, header, &msg)) == 1) {
1320 if (msg != NULL) {
1321 if (msg->netMail==1)
1322 { if (processMsg(msg, header, (sec==secLocalInbound || sec==secProtInbound) ? 1 : 0) !=1 )
1323 rc=5;
1324 } else
1325 break;
1326 freeMsgBuffers(msg);
1327 nfree(msg);
1328 }
1329 }
1330 if (msg)
1331 { /* echomail pkt not for us */
1332 freeMsgBuffers(msg);
1333 nfree(msg);
1334
1335 /* PKT is not for us - try to forward it to our links */
1336
1337 w_log(LL_ERR, "pkt: %s addressed to %d:%d/%d.%d but not to us",
1338 fileName, header->destAddr.zone, header->destAddr.net,
1339 header->destAddr.node, header->destAddr.point);
1340
1341 fclose(pkt); pkt = NULL;
1342 rc = forwardPkt(fileName, header, sec);
1343 }
1344 }
1345
1346 nfree(header);
1347
1348 } else { /* header == NULL */
1349 w_log(LL_ERR, "pkt: %s wrong pkt-file", fileName);
1350 rc = 3;
1351 }
1352
1353 if (pkt) fclose(pkt);
1354
1355 } else statToss.empty++;
1356
1357 #ifdef DO_PERL
1358 perlpktdone(fileName, rc);
1359 #endif
1360 closeOpenedPkt();
1361 w_log(LL_FUNC,"toss.c::processPkt() OK");
1362 return rc;
1363 }
1364
1365
processArc(char * fileName,e_tossSecurity sec)1366 int processArc(char *fileName, e_tossSecurity sec)
1367 {
1368 unsigned int i;
1369 int found, j;
1370 signed int cmdexit;
1371 FILE *bundle = NULL;
1372 char cmd[256];
1373
1374 if (sec == secInbound) {
1375 w_log(LL_ERR, "bundle %s: tossing in unsecure inbound, security violation", fileName);
1376 return 1;
1377 };
1378
1379 /* find what unpacker to use */
1380 for (i = 0, found = 0; (i < config->unpackCount) && !found; i++) {
1381 bundle = fopen(fileName, "rb");
1382 if (bundle == NULL) return 2;
1383 w_log(LL_FILE,"toss.c:processArc(): opened '%s' (\"rb\" mode)",fileName);
1384
1385 /* is offset is negative we look at the end */
1386 fseek(bundle, config->unpack[i].offset, config->unpack[i].offset >= 0 ? SEEK_SET : SEEK_END);
1387 if (ferror(bundle)) { fclose(bundle); continue; };
1388 for (found = 1, j = 0; j < config->unpack[i].codeSize; j++) {
1389 if ((getc(bundle) & config->unpack[i].mask[j]) != config->unpack[i].matchCode[j])
1390 found = 0;
1391 }
1392 fclose(bundle);
1393 }
1394
1395 /* unpack bundle */
1396 if (found) {
1397 fillCmdStatement(cmd,config->unpack[i-1].call,fileName,"",config->tempInbound);
1398 if( fc_stristr(config->unpack[i-1].call, ZIPINTERNAL) )
1399 {
1400 w_log(LL_BUNDLE, "bundle %s: unpacking with zlib", fileName);
1401 #ifdef USE_HPTZIP
1402 cmdexit = UnPackWithZlib(fileName, NULL, config->tempInbound);
1403 #else
1404 cmdexit = 1;
1405 w_log(LL_ERR, "zlib not compiled into hpt", fileName);
1406 #endif
1407 }
1408 else
1409 {
1410 w_log(LL_EXEC, "bundle %s: unpacking with \"%s\"", fileName, cmd);
1411 cmdexit = cmdcall(cmd);
1412 }
1413
1414 if (cmdexit != 0) {
1415 w_log(LL_ERR, "exec failed, code %d", cmdexit);
1416 return 3;
1417 }
1418
1419 if (config->afterUnpack) {
1420 w_log(LL_EXEC, "afterUnpack: execute string \"%s\"", config->afterUnpack);
1421 if ((cmdexit = cmdcall(config->afterUnpack)) != 0) {
1422 w_log(LL_ERR, "exec failed, code %d", cmdexit);
1423 };
1424 }
1425 #ifdef DO_PERL
1426 perlafterunp();
1427 #endif
1428 } else {
1429 w_log(LL_ERR, "bundle %s: cannot find unpacker", fileName);
1430 return 3;
1431 };
1432 statToss.arch++;
1433 remove(fileName);
1434 processDir(config->tempInbound, sec);
1435 return 7;
1436 }
1437
1438
1439 typedef struct fileInDir {
1440 char *fileName;
1441 time_t fileTime;
1442 } s_fileInDir;
1443
filesComparer(const void * elem1,const void * elem2)1444 int filesComparer(const void *elem1, const void *elem2) {
1445 /* File times comparer for qsort */
1446 if (((s_fileInDir *) elem1) -> fileTime < ((s_fileInDir *) elem2) -> fileTime) return -1;
1447 if (((s_fileInDir *) elem1) -> fileTime > ((s_fileInDir *) elem2) -> fileTime) return 1;
1448 return strcasecmp(((s_fileInDir *) elem1) -> fileName, ((s_fileInDir *) elem2) -> fileName);
1449 }
1450
1451 static char *validExt[] = { "su", "mo", "tu", "we", "th", "fr", "sa" };
1452
isArcMail(char * fname)1453 int isArcMail(char *fname)
1454 {
1455 char *p;
1456 int i;
1457 p=strrchr(fname, PATH_DELIM);
1458 if (p) p++;
1459 else p=fname;
1460 /* Amiga? */
1461 for (i=0; i<8; i++)
1462 if (!isalnum((unsigned char)p[i]))
1463 break;
1464 if (i<8) {
1465 /* Amiga? */
1466 for (i=0; i<4; i++) {
1467 if (!isdigit((unsigned char)*p++)) return 0;
1468 while (isdigit((unsigned char)*p)) p++;
1469 if (*p++ != '.') return 0;
1470 }
1471 } else {
1472 p += i;
1473 if (*p++ != '.') return 0;
1474 }
1475 for (i=0; i<sizeof(validExt)/sizeof(validExt[0]); i++)
1476 if (strncasecmp(p, validExt[i], 2) == 0)
1477 break;
1478 if (i == sizeof(validExt)/sizeof(*validExt)) return 0;
1479 return (isalnum((unsigned char)p[2]) && (p[3] == '\0'));
1480 }
1481
processDir(char * directory,e_tossSecurity sec)1482 int processDir(char *directory, e_tossSecurity sec)
1483 {
1484 husky_DIR *dir = NULL;
1485 char *filename = NULL;
1486 char *dummy = NULL;
1487 int rc;
1488 int pktFile,
1489 arcFile;
1490 long pktCount = 0;
1491 s_fileInDir *files = NULL;
1492 long nfiles=0;
1493 struct stat st;
1494 int dirNameLen;
1495 int filenum;
1496 char *newFileName=NULL;
1497 char *ext[]={NULL, "sec", "asc", "bad", "ntu", "err", "flt"};
1498
1499 #ifndef __UNIX__
1500 unsigned fattrs;
1501 #endif
1502
1503 if (directory==NULL) return 0;
1504
1505 tossDir = directory;
1506
1507 dirNameLen = strlen(directory);
1508
1509 #ifdef NOSLASHES
1510 directory[dirNameLen-1]='\0';
1511 #endif
1512
1513 if (NULL == (dir = husky_opendir(directory))) {
1514 printf("Can't open dir: %s!\n",directory);
1515 return 0;
1516 }
1517
1518 w_log(LL_FUNC, "%s::processDir() begin", __FILE__);
1519
1520 #ifdef NOSLASHES
1521 directory[dirNameLen-1]='\\';
1522 #endif
1523
1524 while ((filename = husky_readdir(dir)) != NULL) {
1525 w_dbglog(LL_DEBUGV, "testing %s\n", filename);
1526
1527 dummy = (char *) safe_malloc(dirNameLen + strlen(filename) + 1);
1528 strcpy(dummy,directory);
1529 strcat(dummy,filename);
1530
1531 #if !defined(__UNIX__)
1532 #ifndef HAS_DIRENT_H /* FFindInfo() and FFindNext() store attributes */
1533 fattrs = dir->d_attr;
1534 #elif defined(__TURBOC__) || defined(__DJGPP__)
1535 _dos_getfileattr(dummy, &fattrs); /*unused, but stay for information*/
1536 #elif defined(__MINGW32__) /* May be move to dirlayer.c ? */
1537 fattrs = (GetFileAttributes(dummy) & 0x2) ? _A_HIDDEN : 0;
1538 #else
1539 fattrs = dir->d_attr;
1540 #endif
1541 if(fattrs & _A_HIDDEN) {
1542 nfree(dummy);
1543 } else
1544 #endif
1545 {
1546 nfiles++;
1547 files = (s_fileInDir *) safe_realloc(files,nfiles*sizeof(s_fileInDir));
1548 (files[nfiles-1]).fileName = dummy;
1549
1550 if(stat((files[nfiles-1]).fileName, &st)==0) {
1551 (files[nfiles-1]).fileTime = st.st_mtime;
1552 } else {
1553 /* FixMe - don't know what to set :( */
1554 (files[nfiles-1]).fileTime = 0L;
1555 }
1556
1557 }
1558 }
1559 husky_closedir(dir);
1560
1561 qsort (files, nfiles, sizeof(s_fileInDir), filesComparer);
1562
1563 for ( filenum=0; filenum < nfiles; filenum++) {
1564 arcFile = pktFile = 0;
1565 dummy = (files[filenum]).fileName;
1566 w_log(LL_FILE, "Look incoming file %s", dummy);
1567 w_dbglog(LL_DEBUGV,"testing sorted %s", dummy+dirNameLen);
1568 if ((pktFile = patimat(dummy+dirNameLen, "*.pkt")) == 0)
1569 if (isArcMail(dummy+dirNameLen))
1570 arcFile = 1;
1571
1572 if (pktFile || (arcFile && !config->noProcessBundles)) {
1573 pktCount++;
1574 rc = 3; /* nonsence, but compiler warns */
1575 if (config->tossingExt != NULL &&
1576 (newFileName=changeFileSuffix(dummy, config->tossingExt,1)) != NULL){
1577 if (arcFile)
1578 w_log(LL_BUNDLE, "bundle %s: renaming to .%s", dummy, config->tossingExt);
1579 nfree(dummy);
1580 dummy = newFileName;
1581 newFileName=NULL;
1582 }
1583 if (pktFile)
1584 rc = processPkt(dummy, sec);
1585 else /* if (arcFile) */
1586 rc = processArc(dummy, sec);
1587
1588 if (rc>=1 && rc<=6) {
1589 w_log(LL_ERR, "Renaming pkt/arc to .%s",ext[rc]);
1590 newFileName=changeFileSuffix(dummy, ext[rc], 1);
1591 } else {
1592 if (rc!=7) remove(dummy);
1593 }
1594 }
1595 nfree(dummy);
1596 nfree(newFileName);
1597 }
1598 nfree(files);
1599 w_log(LL_FUNC, "%s::processDir() returns %d", __FILE__, pktCount);
1600 return pktCount;
1601 }
1602
writeStatLog(void)1603 void writeStatLog(void) {
1604 /* write personal mail statistic logfile if statlog is defined in config */
1605 /* if the log file exists, the existing value is increased */
1606
1607 FILE *f = NULL;
1608 char buffer[256];
1609 int len, x, statNetmail, statCC;
1610
1611 statNetmail = statToss.netMail; /* number of just received netmails */
1612 statCC = statToss.CC; /* number of just received personal echo mails */
1613
1614 /* if there are new personal mails and statLog is defined in config */
1615 if (((statNetmail > 0) || (statCC > 0)) && (config->statlog != NULL)) {
1616 f = fopen(config->statlog, "r");
1617 if (f != NULL) { /* and statLog file is readable */
1618 w_log(LL_FILE,"toss.c:writeStatLog(): opened '%s' (\"r\" mode)",config->statlog);
1619
1620 /* then read last personal mail counter and add to actual counter */
1621 while(fgets(buffer,sizeof(buffer),f)) {
1622 len = strlen(buffer);
1623 for (x=0; x!=len; x++) {
1624 if (!strncasecmp(buffer+x, "netmail: ",9)) {
1625 /* netmail found */
1626 statNetmail += atoi(buffer+9);
1627 }
1628
1629 if (!strncasecmp(buffer+x, "CC: ",4)) {
1630 /* personal echomail (CC) found */
1631 statCC += atoi(buffer+4);
1632 }
1633 }
1634 }
1635
1636 fclose(f);
1637 }
1638
1639 /* and write personal mail counter for netmails and echo mails */
1640 f = fopen(config->statlog, "wt");
1641 if (f != NULL) {
1642 w_log(LL_FILE,"toss.c:writeStatLog(): opened '%s' (\"wt\" mode)",config->statlog);
1643 if (statNetmail > 0) {
1644 fprintf(f, "netmail: %d\n", statNetmail);
1645 }
1646 if (statCC > 0) {
1647 fprintf(f, "CC: %d\n", statCC);
1648 }
1649
1650 fclose(f);
1651 }
1652 }
1653 }
1654
writeTossStatsToLog(void)1655 void writeTossStatsToLog(void) {
1656 unsigned int i;
1657 float inMailsec, outMailsec, inKBsec;
1658 char logchar;
1659
1660 if (statToss.pkts==0 && statToss.msgs==0)
1661 logchar='1';
1662 else
1663 logchar='4';
1664
1665 if (statToss.realTime == 0) statToss.realTime = 1;
1666
1667 inMailsec = ((float)(statToss.msgs)) * 1000 / statToss.realTime;
1668 outMailsec = ((float)(statToss.exported)) * 1000 / statToss.realTime;
1669 inKBsec = ((float)(statToss.inBytes)) * 1000 / statToss.realTime / 1024;
1670
1671 w_log(logchar, "Statistics:");
1672 w_log(logchar, " arc: % 5d netMail: % 4d echoMail: % 5d CC: % 5d",
1673 statToss.arch, statToss.netMail, statToss.echoMail, statToss.CC);
1674 w_log(logchar, " pkt's: % 5d dupe: % 4d passthru: % 5d exported: % 5d",
1675 statToss.pkts, statToss.dupes, statToss.passthrough, statToss.exported);
1676 w_log(logchar, " msgs: % 5d bad: % 4d saved: % 5d empty: % 5d",
1677 statToss.msgs, statToss.bad, statToss.saved, statToss.empty);
1678 w_log(logchar, " Input: % 8.2f mails/sec Output: % 8.2f mails/sec", inMailsec, outMailsec);
1679 w_log(logchar, " % 8.2f kb/sec", inKBsec);
1680 w_log(logchar, " % 8.2f kb total, processed in %8.3f seconds", ((float) statToss.inBytes / 1024), (float)statToss.realTime / 1000);
1681
1682 /* write personal mail statistic logfile */
1683 writeStatLog();
1684
1685 /* Now write areas summary */
1686 w_log(logchar, "Areas summary:");
1687 for (i = 0; i < config->netMailAreaCount; i++)
1688 if (config->netMailAreas[i].imported > 0)
1689 w_log(logchar, "netmail area %s - %d msgs",
1690 config->netMailAreas[i].areaName, config->netMailAreas[i].imported);
1691 if (config->dupeArea.imported) w_log(logchar, "dupe area %s - %d msgs",
1692 config->dupeArea.areaName,
1693 config->dupeArea.imported);
1694 if (config->badArea.imported) w_log(logchar, "bad area %s - %d msgs",
1695 config->badArea.areaName,
1696 config->badArea.imported);
1697 for (i = 0; i < config->echoAreaCount; i++)
1698 if (config->echoAreas[i].imported > 0)
1699 w_log(logchar, "echo area %s - %d msgs",
1700 config->echoAreas[i].areaName, config->echoAreas[i].imported);
1701 for (i = 0; i < config->localAreaCount; i++)
1702 if (config->localAreas[i].imported > 0)
1703 w_log(logchar, "local area %s - %d msgs",
1704 config->localAreas[i].areaName, config->localAreas[i].imported);
1705 }
1706
find_old_arcmail(s_link * link,FILE * flo)1707 int find_old_arcmail(s_link *link, FILE *flo)
1708 {
1709 char *line = NULL, *bundle=NULL;
1710 ULONG len;
1711 unsigned as;
1712
1713 while ((line = readLine(flo)) != NULL) {
1714 #ifndef __UNIX__
1715 line = trimLine(line);
1716 #endif
1717 if ((*line=='^' || *line=='#') && isArcMail(line + 1)) {
1718 nfree(bundle);
1719 bundle = safe_strdup(line + 1);
1720 }
1721 nfree(line);
1722 }
1723 if (bundle == NULL) return 0;
1724 if (*bundle != '\000') {
1725 int ok = 0;
1726 len = fsize(bundle);
1727 if (len != -1L) {
1728 time_t t = fmtime(bundle);
1729 if (link->arcmailSize != 0)
1730 as = link->arcmailSize;
1731 else if (config->defarcmailSize != 0)
1732 as = config->defarcmailSize;
1733 else
1734 as = 500; /* default 500 kb max */
1735 /* check size */
1736 ok = (len < as * 1024L);
1737 /* check mtime */
1738 if (ok && t != -1L && link->dailyBundles) {
1739 time_t t0, cur = time(NULL);
1740 struct tm *tcur = localtime(&cur);
1741 tcur->tm_sec = tcur->tm_min = tcur->tm_hour = 0;
1742 t0 = mktime(tcur);
1743 if (t < t0) ok = 0;
1744 }
1745 /* use the bundle */
1746 if (ok) {
1747 link->packFile = (char*)safe_realloc(link->packFile, strlen(bundle)+1);
1748 strcpy(link->packFile,bundle);
1749 nfree(bundle);
1750 return 1;
1751 }
1752 }
1753 }
1754 nfree(bundle);
1755 return 0;
1756 }
1757
arcmail(s_link * tolink)1758 void arcmail(s_link *tolink) {
1759 char cmd[256], *pkt=NULL, *lastPathDelim = NULL, saveChar;
1760 UINT i;
1761 int cmdexit, foa = 0;
1762 FILE *flo = NULL;
1763 s_link *link = NULL;
1764 hs_addr *aka;
1765 e_bundleFileNameStyle bundleNameStyle;
1766
1767 closeOpenedPkt();
1768 if (config->beforePack) {
1769 w_log(LL_EXEC, "beforePack: execute string \"%s\"", config->beforePack);
1770 if ((cmdexit = cmdcall(config->beforePack)) != 0) {
1771 w_log(LL_ERR, "exec failed, code %d", cmdexit);
1772 }
1773 }
1774 #ifdef DO_PERL
1775 perlbeforepack();
1776 #endif
1777
1778 for (i = 0 ; i < config->linkCount; i++) {
1779 if(tolink) {
1780 link = tolink;
1781 i = config->linkCount;
1782 } else {
1783 link = config->links[i];
1784 }
1785
1786 /* only create floFile if we have mail for this link */
1787 if (link->pktFile != NULL) {
1788
1789 aka = SelectPackAka(link);
1790
1791 if (needUseFileBoxForLinkAka(config,link,aka)) {
1792
1793 if (!link->fileBox) link->fileBox = makeFileBoxNameAka (config,link,aka);
1794
1795 _createDirectoryTree (link->fileBox);
1796 if (link->packFile == NULL)
1797 if (createPackFileName(link))
1798 exit_hpt("Could not create new bundle!",1);
1799
1800 if (link->packerDef != NULL) {
1801 /* FIXME It's need to fix logic: MUST don't allow pack into filebox directly!!!
1802 Normal logic: make bundle in temporary dir, next move(rename!) it into filebox,
1803 and at scanning tempoutbound should to check bundles (not only PKT)
1804 */
1805 fillCmdStatement(cmd, link->packerDef->call,
1806 link->packFile,
1807 link->pktFile, "");
1808 w_log(LL_BUNDLE, "Packing for %s %s, %s > %s",
1809 aka2str(link->hisAka),
1810 link->name, get_filename(link->pktFile),
1811 get_filename(link->packFile));
1812 w_log(LL_EXEC, "cmd: %s", cmd);
1813 if( stricmp(link->packerDef->call, ZIPINTERNAL) == 0 )
1814 {
1815 #ifdef USE_HPTZIP
1816 cmdexit = PackWithZlib(link->packFile, link->pktFile);
1817 #else
1818 cmdexit = -1;
1819 w_log(LL_ERR, "zlib not compiled into hpt");
1820 #endif
1821 }else
1822 cmdexit = cmdcall(cmd);
1823
1824 if (cmdexit==0) remove(link->pktFile);
1825 else w_log(LL_ERR, "Error executing packer (errorlevel==%i)", cmdexit);
1826
1827 } /* end packerDef */
1828 else {
1829 /* there is no packer defined -> put pktFile into fileBox */
1830 xstrcat(&pkt, link->fileBox);
1831 xstrcat(&pkt, link->pktFile + strlen(config->tempOutbound));
1832
1833 cmdexit = move_file(link->pktFile, pkt, 0);
1834 if (cmdexit==0) w_log(LL_BUNDLE, "Leave non-packed mail for %s %s, %s",
1835 aka2str(link->hisAka), link->name,
1836 get_filename(link->pktFile));
1837 else w_log(LL_ERR, "error moving file for %s %s, %s->%s (errorlevel==%i)", aka2str(link->hisAka), link->name, link->pktFile, pkt, errno);
1838 nfree(pkt);
1839 }
1840
1841 } else if (createOutboundFileNameAka(link,link->echoMailFlavour, FLOFILE, aka) == 0) {
1842 /* process if the link not busy, else do not create 12345678.?lo */
1843 flo = fopen(link->floFile, "a+");
1844
1845 if (flo == NULL)
1846 w_log(LL_ERR, "Cannot open flo file %s",
1847 config->links[i]->floFile);
1848 else {
1849 w_log(LL_FILE,"toss.c:arcmail(): opened '%s' (\"a+\" mode)",link->floFile);
1850
1851 if (link->linkBundleNameStyle!=eUndef)
1852 bundleNameStyle=link->linkBundleNameStyle;
1853 else if (config->bundleNameStyle!=eUndef)
1854 bundleNameStyle=config->bundleNameStyle;
1855 else bundleNameStyle = eTimeStamp;
1856
1857 if (link->packerDef != NULL) {
1858 pack_retry:
1859 /*there is a packer defined -> put packFile into flo */
1860 /*if we are creating new arcmail bundle -> put packFile into flo*/
1861 fseek(flo, 0L, SEEK_SET);
1862 if (!foa) /* retry pack bundle? */
1863 foa = find_old_arcmail(link, flo);
1864 else { /* try to generate new bundle name */
1865 foa = 0;
1866 link->packFile = NULL;
1867 }
1868
1869 if (link->packFile == NULL)
1870 if (createPackFileName(link))
1871 exit_hpt("Could not create new bundle!",1);
1872
1873 fillCmdStatement(cmd, link->packerDef->call,
1874 link->packFile,
1875 link->pktFile, "");
1876 w_log(LL_BUNDLE, "Packing for %s %s, %s > %s",
1877 aka2str(link->hisAka), link->name,
1878 get_filename(link->pktFile),
1879 get_filename(link->packFile));
1880 w_log(LL_EXEC, "cmd: %s", cmd);
1881 if( stricmp(link->packerDef->call, ZIPINTERNAL) == 0 )
1882 {
1883 #ifdef USE_HPTZIP
1884 cmdexit = PackWithZlib(link->packFile, link->pktFile);
1885 #else
1886 cmdexit = -1;
1887 w_log(LL_ERR, "zlib not compiled into hpt");
1888 #endif
1889 }
1890 else
1891 {
1892 cmdexit = cmdcall(cmd);
1893 }
1894 if (cmdexit==0) {
1895 if (foa==0) {
1896 if (bundleNameStyle == eAddrDiff ||
1897 bundleNameStyle == eAddrsCRC32 ||
1898 bundleNameStyle == eAddrDiffAlways ||
1899 bundleNameStyle == eAddrsCRC32Always ||
1900 bundleNameStyle == eAmiga)
1901 fprintf(flo, "#%s\n", link->packFile);
1902 else
1903 fprintf(flo, "^%s\n", link->packFile);
1904 }
1905 remove(link->pktFile);
1906 } else {
1907 w_log(LL_ERR, "Error executing packer (errorlevel==%i, %s)",
1908 cmdexit, foa ? "retrying" : "permanent error");
1909 if (foa) goto pack_retry;
1910 }
1911
1912 } /* end packerDef */
1913 else {
1914 /* there is no packer defined -> put pktFile into flo */
1915 lastPathDelim = strrchr(link->floFile, PATH_DELIM);
1916
1917 /* change path of file to path of flofile */
1918 saveChar = *(++lastPathDelim);
1919 *lastPathDelim = '\0';
1920 xstrcat(&pkt, link->floFile);
1921 *lastPathDelim = saveChar;
1922
1923 if (config->separateBundles) {
1924
1925 if (bundleNameStyle==eAmiga)
1926 xscatprintf(&pkt, "%u.%u.%u.%u.sep%c",
1927 aka->zone, aka->net,
1928 aka->node, aka->point,
1929 PATH_DELIM);
1930 else {
1931 if (aka->point != 0)
1932 xscatprintf(&pkt,"%08x.sep%c",
1933 aka->point,PATH_DELIM);
1934 else
1935 xscatprintf(&pkt, "%04x%04x.sep%c",
1936 aka->net,
1937 aka->node,
1938 PATH_DELIM);
1939 }
1940 }
1941
1942 xstrcat(&pkt, link->pktFile + strlen(config->tempOutbound));
1943
1944 cmdexit = move_file(link->pktFile, pkt, 0);
1945 if (cmdexit==0) {
1946 fprintf(flo, "^%s\n", pkt);
1947 w_log(LL_BUNDLE, "Leave non-packed mail for %s %s, %s",
1948 aka2str(link->hisAka), link->name,
1949 get_filename(link->pktFile));
1950 }
1951 else w_log(LL_ERR, "error moving file for %s %s, %s->%s (errorlevel==%i)", aka2str(link->hisAka), link->name, link->pktFile, pkt, errno);
1952 nfree(pkt);
1953 }
1954
1955 fclose(flo);
1956 } /* end flo */
1957
1958 nfree(link->floFile);
1959 remove(link->bsyFile);
1960 nfree(link->bsyFile);
1961 } /* end outboundFileNameCreated */
1962
1963 nfree(link->pktFile);
1964 nfree(link->packFile);
1965 } /* end pkt file */
1966
1967 } /* endfor */
1968 return;
1969 }
1970
1971 static int forwardedPkts = 0;
1972
forwardPkt(const char * fileName,s_pktHeader * header,e_tossSecurity sec)1973 int forwardPkt(const char *fileName, s_pktHeader *header, e_tossSecurity sec)
1974 {
1975 unsigned int i;
1976 s_link *link = NULL;
1977 char *newfn = NULL;
1978
1979 for (i = 0 ; i < config->linkCount; i++) {
1980 if (addrComp(header->destAddr, config->links[i]->hisAka) == 0) {
1981 /* we found a link to forward the pkt file to */
1982
1983 link = config->links[i];
1984
1985 /* security checks */
1986
1987 if (link->forwardPkts==fOff) return 4;
1988 if ((link->forwardPkts==fSecure)&&(sec != secProtInbound)&&(sec != secLocalInbound)) return 4;
1989
1990 /* as we have feature freeze currently, */
1991 /* I enclose the following code with an ifdef ... */
1992
1993 newfn = makeUniqueDosFileName(config->tempOutbound, "pkt", config);
1994
1995 if (move_file(fileName, newfn, 0) == 0) { /* save if exist */
1996
1997 w_log(LL_PKT, "Forwarding %s to %s as %s",
1998 fileName, config->links[i]->name, newfn + strlen(config->tempOutbound));
1999
2000 nfree(newfn);
2001 forwardedPkts = 1;
2002 return 0;
2003 }
2004 else
2005 {
2006 w_log(LL_ERR, "Failed moving %s to %s (%s)", fileName,
2007 newfn, strerror(errno));
2008 nfree(newfn);
2009 return 4;
2010 }
2011
2012 }
2013 }
2014
2015 w_log(LL_ERR, "Packet %s is not for us or our links",fileName);
2016
2017 return 4; /* PKT is not for us and we did not find a link to
2018 forward the pkt file to */
2019 }
2020
2021
2022 /* According to the specs, a .QQQ file does not have two leading
2023 zeros. This routine checks if the file is a .QQQ file, and if so,
2024 it appends the zeros and renames the file to .PKT. */
2025
2026
fix_qqq(char * filename)2027 void fix_qqq(char *filename)
2028 {
2029 FILE *f = NULL;
2030 char buffer[2] = { '\0', '\0' };
2031 size_t l = strlen(filename);
2032 char *newname=NULL;
2033
2034 if (l > 3 && newname != NULL && toupper(filename[l-1]) == 'Q' &&
2035 toupper(filename[l-2]) == 'Q' && toupper(filename[l-3]) == 'Q')
2036 {
2037 newname = safe_strdup(filename);
2038
2039 strcpy(newname + l - 3, "pkt");
2040 if (move_file(newname, filename, 0) == 0)
2041 {
2042 strcpy(filename, newname);
2043
2044 if ((f = fopen(filename, "ab")) != NULL)
2045 {
2046 fwrite(buffer, 2, 1, f);
2047 fclose(f);
2048 }
2049 } else
2050 w_log(LL_ERR, "Failed moving %s to %s (%s)", newname,
2051 filename, strerror(errno));
2052 nfree(newname);
2053 }
2054 }
2055
2056
tossTempOutbound(char * directory)2057 void tossTempOutbound(char *directory)
2058 {
2059 husky_DIR *dir = NULL;
2060 FILE *pkt = NULL;
2061 char *filename = NULL;
2062 char *dummy = NULL;
2063 s_pktHeader *header = NULL;
2064 s_link *link = NULL;
2065 size_t l;
2066 #ifdef NOSLASHES
2067 int dirNameLen;
2068 #endif
2069
2070 if (directory==NULL) return;
2071
2072 #ifdef NOSLASHES
2073 dirNameLen = strlen(directory);
2074 directory[dirNameLen-1]='\0';
2075 #endif
2076
2077 if (NULL == (dir = husky_opendir(directory))) {
2078 printf("Can't open dir: %s!\n",directory);
2079 return;
2080 }
2081
2082 #ifdef NOSLASHES
2083 directory[dirNameLen-1]='\\';
2084 #endif
2085
2086 while ((filename = husky_readdir(dir)) != NULL) {
2087 l = strlen(filename);
2088 if (l > 4 && (stricmp(filename + l - 4, ".pkt") == 0 ||
2089 stricmp(filename + l - 4, ".qqq") == 0))
2090 {
2091 dummy = (char *) safe_malloc(strlen(directory)+l+1);
2092 strcpy(dummy, directory);
2093 strcat(dummy, filename);
2094
2095 fix_qqq(dummy);
2096
2097 pkt = fopen(dummy, "rb");
2098 if (pkt==NULL) continue;
2099
2100 header = openPkt(pkt);
2101 if (header != NULL) {
2102 link = getLinkFromAddr (config, header->destAddr);
2103 nfree(header);
2104 } else {
2105 link = NULL;
2106 }
2107
2108 if (link != NULL) {
2109
2110 if (link->packFile == NULL) {
2111 if ( createPackFileName(link) )
2112 exit_hpt("Could not create new bundle!",1);
2113 }
2114
2115 nfree(link->pktFile);
2116 link->pktFile = dummy;
2117
2118 fclose(pkt);
2119 arcmail(link);
2120 } else {
2121 nfree(dummy);
2122 w_log(LL_ERR, "found non packed mail without matching link in tempOutbound");
2123 fclose(pkt);
2124 }
2125 }
2126 }
2127
2128 husky_closedir(dir);
2129 return;
2130 }
2131
writeImportLog(void)2132 void writeImportLog(void) {
2133 unsigned int i;
2134 FILE *f = NULL;
2135 struct stat buf;
2136
2137 if (config->importlog) {
2138
2139 /* write importlog */
2140 f = fopen(config->importlog, "a");
2141 if (f != NULL) {
2142
2143 for (i = 0; i < config->netMailAreaCount; i++)
2144 if (config->netMailAreas[i].imported > 0)
2145 fprintf(f, "%s\n", config->netMailAreas[i].areaName);
2146
2147 for (i = 0; i < config->echoAreaCount; i++)
2148 if (config->echoAreas[i].imported > 0 &&
2149 config->echoAreas[i].msgbType != MSGTYPE_PASSTHROUGH)
2150 fprintf(f, "%s\n", config->echoAreas[i].areaName);
2151
2152 for (i = 0; i < config->localAreaCount; i++)
2153 if (config->localAreas[i].imported > 0)
2154 fprintf(f, "%s\n", config->localAreas[i].areaName);
2155
2156 fclose(f);
2157 #ifdef __UNIX__
2158 chown(config->importlog, config->loguid, config->loggid);
2159 if (config -> logperm != -1) chmod(config->importlog, config->logperm);
2160 #endif
2161
2162 } else w_log(LL_ERR, "Could not open importlogfile");
2163
2164 /* remove empty importlog */
2165 if (stat(config->importlog, &buf)==0) {
2166 if (buf.st_size==0) remove(config->importlog);
2167 }
2168
2169 }
2170 }
2171
2172 #define MAXOPEN_DEFAULT 512
2173
2174 #if defined(__OS2__)
2175
2176 #define INCL_DOS
2177
2178 /* From os2emx.h:
2179 ULONG DosSetMaxFH (ULONG ulCount);
2180 ULONG DosSetRelMaxFH (PLONG pulReqCount, PULONG pulCurMaxFH);
2181 */
2182
setmaxopen(void)2183 static void setmaxopen(void) {
2184 ULONG cur = 0, add = 0;
2185
2186 if (DosSetRelMaxFH(&add, &cur) == 0)
2187 if (cur>=maxopenpkt) return;
2188 if (DosSetMaxFH(maxopenpkt))
2189 while (cur<maxopenpkt) {
2190 add = 1;
2191 if (DosSetRelMaxFH(&add, &cur))
2192 break;
2193 }
2194 #ifdef __WATCOMC__
2195 _grow_handles(maxopenpkt);
2196 #endif
2197 cur = add = 0;
2198 if (DosSetRelMaxFH(&add, &cur) == 0) {
2199 maxopenpkt = cur;
2200 /* return; */
2201 }
2202
2203 #elif defined(__UNIX__)
2204
2205 #include <sys/resource.h>
2206
2207 static void setmaxopen(void) {
2208 #ifdef RLIMIT_NOFILE
2209 struct rlimit rl;
2210 unsigned maxopenpkt = MAXOPEN_DEFAULT;
2211
2212 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
2213 if (rl.rlim_cur >= MAXOPEN_DEFAULT)
2214 return;
2215 /* try to set max open */
2216 rl.rlim_cur = rl.rlim_max;
2217 if (setrlimit(RLIMIT_NOFILE, &rl) == 0 && rl.rlim_cur >= MAXOPEN_DEFAULT)
2218 return;
2219 rl.rlim_cur = rl.rlim_max = maxopenpkt;
2220 setrlimit(RLIMIT_NOFILE, &rl);
2221 if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
2222 maxopenpkt = rl.rlim_cur;
2223 return;
2224 }
2225 #endif
2226
2227 #else /* windows or unknown OS, just test */
2228
2229 static void setmaxopen(void) {
2230
2231 #endif
2232
2233 {
2234 int handles[MAXOPEN_DEFAULT];
2235 ULONG i;
2236 for (i=0; i<MAXOPEN_DEFAULT; i++)
2237 if ((handles[i]=dup(1)) == -1)
2238 break;
2239 maxopenpkt = i;
2240 for (i=0; i<maxopenpkt; i++)
2241 close(handles[i]);
2242 }
2243 if (maxopenpkt == 0) maxopenpkt = 1;
2244 }
2245
2246 void toss()
2247 {
2248 FILE *f = NULL;
2249 hs_time timer;
2250
2251 /* set stats to 0 */
2252 memset(&statToss, '\0', sizeof(s_statToss));
2253 w_log(LL_START, "Start tossing...");
2254 husky_SetTimer(&timer);
2255 while (processDir(config->localInbound, secLocalInbound));
2256 while (processDir(config->protInbound, secProtInbound));
2257 while (processDir(config->inbound, secInbound));
2258 nfree(globalBuffer); /* free msg->text global buffer */
2259
2260 writeDupeFiles();
2261 writeImportLog();
2262
2263 if (forwardedPkts) {
2264 tossTempOutbound(config->tempOutbound);
2265 forwardedPkts = 0;
2266 }
2267
2268
2269 statToss.realTime = husky_GetTimer(&timer);
2270 /* write statToss to Log */
2271 writeTossStatsToLog();
2272 tossTempOutbound(config->tempOutbound);
2273
2274 /* create flag for netmail trackers */
2275 if (config->netmailFlag && statToss.netMail) {
2276 if (NULL == (f = fopen(config->netmailFlag,"a"))) w_log(LL_ERR, "Could not create netmail flag: %s", config->netmailFlag);
2277 else {
2278 w_log(LL_FLAG, "Created netmail flag: %s", config->netmailFlag);
2279 fclose(f);
2280 }
2281 }
2282 w_log(LL_STOP, "End tossing");
2283 }
2284
2285 int packBadArea(HMSG hmsg, XMSG xmsg, char force)
2286 {
2287 int rc = 0;
2288 s_message msg;
2289 s_area *echo = &(config -> badArea);
2290 hs_addr pktOrigAddr;
2291 char *ptmp = NULL, *line = NULL, *areaName = NULL, *area=NULL, noexp=0;
2292 s_link *link = NULL;
2293
2294 makeMsg(hmsg, xmsg, &msg, &(config->badArea), 2);
2295 memset(&pktOrigAddr,'\0',sizeof(hs_addr));
2296 statToss.msgs++; /* really processed one more msg */
2297
2298 /* deleting valet string - "FROM:" and "REASON:" */
2299 ptmp = msg.text;
2300 while ((line = strchr(ptmp, '\r')) != NULL) {
2301 /* Temporary make it \0 terminated string */
2302 *line = '\000';
2303 if (strncmp(ptmp, "FROM: ", 6) == 0 ||
2304 strncmp(ptmp, "REASON: ", 8) == 0 ||
2305 strncmp(ptmp, "AREANAME: ", 10) == 0) {
2306 /* It's from address */
2307 if (*ptmp == 'F') parseFtnAddrZS(ptmp + 6, &pktOrigAddr);
2308 /* Don't export to links */
2309 if (*ptmp == 'R') {
2310 if (strstr(ptmp, "MSGAPIERR: ")!=NULL) noexp=1;
2311 }
2312 /* Cut this kludges */
2313 if (*ptmp=='A') {
2314 if (area==NULL) {
2315 echo = getArea(config, ptmp+10);
2316 xstrcat(&area, ptmp+10);
2317 }
2318 memmove(ptmp, line+1, strlen(line+1)+1);
2319 break;
2320 } else {
2321 memmove(ptmp, line+1, strlen(line+1)+1);
2322 continue;
2323 }
2324 } else {
2325 if ((strncmp(ptmp, "AREA:", 5)==0 ||
2326 strncmp(ptmp, "\001AREA:", 6)==0) && area==NULL) {
2327 /* translating name of the area to uppercase */
2328 strUpper(ptmp);
2329 areaName = (*ptmp!='\001') ? ptmp+5 : ptmp+6;
2330 /* if the areaname begins with a space */
2331 while (*areaName == ' ') areaName++;
2332 echo = getArea(config, areaName);
2333 xstrcat(&area, areaName);
2334 };
2335 ptmp = line+1;
2336 };
2337 *line = '\r';
2338 }
2339
2340 if (echo == &(config->badArea)) {
2341 link = getLinkFromAddr(config, pktOrigAddr);
2342 if (link && link->areafix.autoCreate && area) {
2343 if (0 == autoCreate(area, NULL, pktOrigAddr, NULL))
2344 echo = getArea(config, area);
2345 }
2346 }
2347 nfree(area);
2348
2349 if (echo == &(config->badArea)) {
2350 freeMsgBuffers(&msg);
2351 return rc;
2352 }
2353
2354 if (checkAreaLink(echo, pktOrigAddr, 0) == 0 || force) {
2355 if (dupeDetection(echo, msg)==1 || noexp) {
2356 /* no dupe or toss whithout export to links */
2357
2358 if (config->carbonCount != 0) carbonCopy(&msg, NULL, echo);
2359
2360 echo->imported++; /* area has got new messages */
2361 #ifdef ADV_STAT
2362 if (config->advStatisticsFile != NULL) put_stat(echo, &pktOrigAddr, stNORM, msg.textLength);
2363 #endif
2364 if (echo->msgbType != MSGTYPE_PASSTHROUGH) {
2365 rc = putMsgInArea(echo, &msg,1, 0);
2366 statToss.saved += rc;
2367 } else {
2368 statToss.passthrough++;
2369 rc = 1; /* passthrough always work */
2370 }
2371
2372 if (noexp==0) { /* recode & export to links */
2373 /* recoding from internal to transport charSet */
2374 if (config->outtab) {
2375 if (msg.recode & REC_HDR) {
2376 recodeToTransportCharset((char*)msg.fromUserName);
2377 recodeToTransportCharset((char*)msg.toUserName);
2378 recodeToTransportCharset((char*)msg.subjectLine);
2379 msg.recode &= ~REC_HDR;
2380 }
2381 if (msg.recode & REC_TXT) {
2382 recodeToTransportCharset((char*)msg.text);
2383 msg.recode &= ~REC_TXT;
2384 }
2385 }
2386
2387 if (echo->downlinkCount > 0) {
2388 forwardMsgToLinks(echo, &msg, pktOrigAddr);
2389 }
2390 }
2391
2392 } else {
2393 /* msg is dupe */
2394 if (echo->dupeCheck == dcMove) {
2395 rc = putMsgInArea(&(config->dupeArea), &msg, 0, 0);
2396 } else rc = 1; /* dupeCheck del */
2397 if (rc) config->dupeArea.imported++;
2398 #ifdef ADV_STAT
2399 if (config->advStatisticsFile != NULL) put_stat(echo, &pktOrigAddr, stDUPE, 0);
2400 #endif
2401 }
2402
2403 } else rc = 0;
2404
2405 freeMsgBuffers(&msg);
2406 return rc;
2407 }
2408
2409 void tossFromBadArea(char force)
2410 {
2411 HAREA area;
2412 HMSG hmsg;
2413 XMSG xmsg;
2414 dword highestMsg, i;
2415 int delmsg;
2416
2417 area = MsgOpenArea((UCHAR *) config->badArea.fileName,
2418 MSGAREA_NORMAL, (word)(config->badArea.msgbType|MSGTYPE_ECHO));
2419 if (area != NULL) {
2420 w_log(LL_START, "Scanning area: %s", config->badArea.areaName);
2421 highestMsg = MsgGetNumMsg(area);
2422
2423 for (i=1; i<=highestMsg; highestMsg--) {
2424 hmsg = MsgOpenMsg(area, MOPEN_RW, i);
2425 if (hmsg == NULL) continue; /* msg# does not exist */
2426 MsgReadMsg(hmsg, &xmsg, 0, 0, NULL, 0, NULL);
2427 delmsg = packBadArea(hmsg, xmsg, force);
2428
2429 MsgCloseMsg(hmsg);
2430
2431 if (delmsg) MsgKillMsg(area, i);
2432 else { i++; highestMsg++; }
2433 }
2434
2435 MsgCloseArea(area);
2436
2437 closeOpenedPkt();
2438 writeDupeFiles();
2439 writeImportLog();
2440
2441 w_log(LL_STAT, "Statistics");
2442 w_log(LL_STAT, " scanned: % 5d saved: % 7d CC: % 2d", statToss.msgs, statToss.saved, statToss.CC);
2443 w_log(LL_STAT, " exported: % 4d passthru: % 4d", statToss.exported, statToss.passthrough);
2444
2445 tossTempOutbound(config->tempOutbound);
2446
2447 } else w_log(LL_ERR, "Could not open %s", config->badArea.fileName);
2448 }
2449