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  * This file is part of HPT.
16  *
17  * HPT is free software; you can redistribute it and/or modify it
18  * under the terms of the GNU General Public License as published by the
19  * Free Software Foundation; either version 2, or (at your option) any
20  * later version.
21  *
22  * HPT is distributed in the hope that it will be useful, but
23  * WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with HPT; see the file COPYING.  If not, write to the Free
29  * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
30  *****************************************************************************
31  * $Id$
32  */
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <ctype.h>
37 
38 #include <huskylib/compiler.h>
39 #include <huskylib/huskylib.h>
40 
41 #include <fidoconf/fidoconf.h>
42 #include <fidoconf/common.h>
43 #include <huskylib/xstr.h>
44 #include <fidoconf/afixcmd.h>
45 #include <huskylib/log.h>
46 #include <huskylib/recode.h>
47 
48 #include <areafix/areafix.h>
49 #include <global.h>
50 #include <fcommon.h>
51 #include <pkt.h>
52 #include <global.h>
53 
readPktTime(FILE * pkt)54 time_t readPktTime(FILE *pkt)
55 {
56   struct tm time;
57 
58   time.tm_year  = getUINT16(pkt) - 1900; /* years since 1900 */
59   time.tm_mon   = getUINT16(pkt);
60   time.tm_mday  = getUINT16(pkt);
61   time.tm_hour  = getUINT16(pkt);
62   time.tm_min   = getUINT16(pkt);
63   time.tm_sec   = getUINT16(pkt);
64   time.tm_isdst = 0;                    /* disable daylight saving */
65 
66   return mktime(&time);
67 }
68 
readPktPassword(FILE * pkt,UCHAR * password)69 void readPktPassword(FILE *pkt, UCHAR *password)
70 {
71    int i;
72 
73    for (i=0 ;i<8 ;i++ ) {
74      password[i] = (UCHAR) getc(pkt); /* no EOF check :-( */
75    } /* endfor */
76    password[8] = 0;
77 }
78 
openPkt(FILE * pkt)79 s_pktHeader *openPkt(FILE *pkt)
80 {
81   s_pktHeader *header;
82   UINT16      pktVersion, capWord;
83 
84   header = (s_pktHeader *) safe_malloc(sizeof(s_pktHeader));
85   memset(header, '\0', sizeof(s_pktHeader));
86   header->origAddr.node = getUINT16(pkt);
87   header->destAddr.node = getUINT16(pkt);
88   header->pktCreated = readPktTime(pkt); /*  12 bytes */
89 
90   getUINT16(pkt); /* read 2 bytes for the unused baud field */
91 
92   pktVersion = getUINT16(pkt);
93   if (pktVersion != 2) {
94 	  nfree(header);
95 	  w_log(LL_ERR,"Invalid pkt version %u!",pktVersion);
96 	  return NULL;
97   } /* endif */
98 
99   header->origAddr.net = getUINT16(pkt);
100   header->destAddr.net = getUINT16(pkt);
101 
102   header->loProductCode = (UCHAR) getc(pkt);
103   header->majorProductRev = (UCHAR) getc(pkt);
104 
105   readPktPassword(pkt, (UCHAR *)header->pktPassword); /*  8 bytes */
106 
107   header->origAddr.zone = getUINT16(pkt);
108   header->destAddr.zone = getUINT16(pkt);
109 
110   header->auxNet = getUINT16(pkt);
111 
112   header->capabilityWord = (UINT16)((fgetc(pkt) << 8) + fgetc(pkt));
113   header->hiProductCode = (UCHAR) getc(pkt);
114   header->minorProductRev = (UCHAR) getc(pkt);
115 
116   capWord = getUINT16(pkt);
117 
118   if (!config->ignoreCapWord) {
119 	  /* if both capabilitywords aren't the same, abort */
120 	  /* but read stone-age pkt */
121 	  if (capWord!=header->capabilityWord && header->capabilityWord!=0) {
122 		  nfree(header);
123 		  w_log(LL_ERR,"CapabilityWord error in following pkt! rtfm: IgnoreCapWord.");
124 		  return NULL;
125 	  } /* endif */
126   }
127 
128   getUINT16(pkt); getUINT16(pkt); /* read the additional zone info */
129 
130   header->origAddr.point = getUINT16(pkt);
131   header->destAddr.point = getUINT16(pkt);
132 
133   getUINT16(pkt); getUINT16(pkt); /* read ProdData */
134 
135   if (((UINT16)header->origAddr.net) == 65535U) {
136 	  if (header->origAddr.point) header->origAddr.net = header->auxNet;
137 	  else header->origAddr.net = header->destAddr.net; /*  not in FSC ! */
138   }
139 
140   if (header->origAddr.zone == 0) {
141 	  for (capWord=0; capWord<config->addrCount; capWord++) {
142 		  if (header->origAddr.net==config->addr[capWord].net) {
143 			  header->origAddr.zone = config->addr[capWord].zone;
144 			  break;
145 		  }
146 	  }
147 	  if (header->origAddr.zone==0) header->origAddr.zone=config->addr[0].zone;
148   }
149   if (header->destAddr.zone == 0) {
150 	  for (capWord=0; capWord<config->addrCount; capWord++) {
151 		  if (header->destAddr.net==config->addr[capWord].net) {
152 			  header->destAddr.zone = config->addr[capWord].zone;
153 			  break;
154 		  }
155 	  }
156 	  if (header->destAddr.zone==0) header->destAddr.zone=config->addr[0].zone;
157   }
158 
159   return header;
160 }
161 
162 /* WARNING: *from and *to addresses should be properly initialized */
parseINTL(char * msgtxt,hs_addr * from,hs_addr * to)163 int parseINTL(char *msgtxt, hs_addr *from, hs_addr *to)
164 {
165    char *start;
166    hs_addr intl_from= *from, intl_to = *to; /* set defaults */
167    int result = 0, temp_point;
168 
169    /* Parse the INTL Kludge */
170 
171    start = strstr(msgtxt, "\001INTL ");
172    if (start)
173    {
174       start += 6;                 /*  skip "INTL " */
175 
176 	  if( !(parseFtnAddrZ(start, &intl_to, FTNADDR_GOOD, (const char**)(&start)) & FTNADDR_ERROR) &&
177 		  !(parseFtnAddrZ(start, &intl_from, FTNADDR_GOOD, (const char**)(&start)) & FTNADDR_ERROR))
178           /*  '(const char**)(&start)' is needs for prevent warning "passing arg 4 of `parseFtnAddrZ' from incompatible pointer type" */
179 	  {
180           /* INTL is valid, copy parsed data to output */
181 		  /* copying the whole structures is ok since they are initialized by from and to */
182           *from = intl_from;
183           *to = intl_to;
184 
185           result |= INTL_FOUND;
186 	  }
187    } else
188        w_log(LL_DEBUGB, "Warning: no INTL kludge found in message");
189 
190    start = strstr(msgtxt, "\001FMPT");
191    if (start)
192    {
193       start += 6;                  /* skip "FMPT " */
194       temp_point = atoi(start);
195       from->point = (temp_point >= 0 && temp_point <= 32767)?(sword)temp_point:0;
196 	  /* Actually there should not be */
197       result |= FMPT_FOUND;
198    }
199    else
200    /* while standard says that no FMPT kludge means zero point, we wont change
201 	* point nuber here but will rely on interpretation of caller function */
202    ;
203    /* and the same for TOPT */
204    start = strstr(msgtxt, "\001TOPT");
205    if (start)
206    {
207       start += 6;                  /* skip "TOPT " */
208       temp_point = atoi(start);
209       to->point = (temp_point >= 0 && temp_point <= 32767)?(sword)temp_point:0;
210       result |= TOPT_FOUND;
211    }
212    else
213    /* while standard says that no TOPT kludge means zero point, we wont change
214 	* point nuber here but will rely on interpretation of caller function */
215    ;
216 return result;
217 }
218 
correctEMAddr(s_message * msg)219 void correctEMAddr(s_message *msg)
220 {
221    char *start = NULL, *temp;
222 
223    /* Find originating address in Origin line */
224    start = strrstr(msg->text, " * Origin:");
225 
226    if (start) {
227       temp = start += 10; /* skip " * Origin:" */
228       while (*start && (*start != '\r') && (*start != '\n')) start++;  /*  get to end of line */
229       --start;
230       while (*(start) == ' ') --start; /* skip trailing spaces, just in case */
231 
232       if (*(start) == ')') {           /*  if there is no ')', there is no origin */
233 
234          while (--start > temp &&
235                 *start != '(' &&       /*  find beginning '(' */
236                 !isspace(*start));
237 
238 		 if (*start=='(' || *start==' ') {  /* "(1:2/3.4@dom)" or " 1:2/3.4@dom)" is found */
239 
240             start++;                   /*  skip '(' or ' ' */
241             if( !(parseFtnAddrZS(start,&msg->origAddr) & FTNADDR_ERROR) ){
242                return; /* FTN address is taken from Origin */
243             }
244          }
245       }
246    }
247 
248    /* Find originating address in MSGID line */
249    start = strrstr(msg->text, "\001MSGID:");
250    /* Standard requires "\001MSGID: " but not all software is compatible with FTS-9 :( */
251    if (start) {
252       start+=7;
253       if( !(parseFtnAddrZS(start, &msg->origAddr) & FTNADDR_ERROR) ){
254             return; /* FTN address is taken from MSGID */
255       }
256    }
257 
258    /*  Another try...
259 	*  But if MSGID isn't present or broken and origin is broken
260 	*  then PATH may be broken too...
261     */
262    start = strstr(msg->text, "\001PATH: ");
263    if (start) {
264       start += 7;
265       if( !(parseFtnAddrZ(start, &msg->origAddr, FTNADDR_2D, NULL) & FTNADDR_ERROR) ){
266          return; /* FTN address is taken from PATH */
267       }
268    }
269 
270    /* if nothing works then send report to RC ;) */
271 }
272 
correctNMAddr(s_message * msg,s_pktHeader * header)273 void correctNMAddr(s_message *msg, s_pktHeader *header)
274 {
275    char *text = NULL;
276    int valid_intl_kludge;
277    int zonegated = 0;
278    hs_addr intl_from = msg->origAddr, intl_to = msg->destAddr;
279    UINT i;
280 
281    valid_intl_kludge = parseINTL(msg->text, &intl_from, &intl_to);
282 
283    /* Assign point numbers if FMPT/TOPT kludges are found */
284    if(valid_intl_kludge & FMPT_FOUND)
285       msg->origAddr.point = intl_from.point;
286    if(valid_intl_kludge & TOPT_FOUND)
287       msg->destAddr.point = intl_to.point;
288    /* if no kludges are found then leave current values
289     *  which most possible are zeroes */
290 
291    /* now interpret the INTL kludge */
292 
293    if (valid_intl_kludge & INTL_FOUND)
294    {
295       /* the from part is easy - we can always use it */
296 
297       msg->origAddr.zone = intl_from.zone;
298       msg->origAddr.net  = intl_from.net;
299       msg->origAddr.node = intl_from.node;
300 
301       /* the to part is more complicated */
302 
303       zonegated = 0;
304 
305       if (msg->destAddr.net == intl_from.zone &&
306           msg->destAddr.node == intl_to.zone)
307       {
308          zonegated = 1;
309 
310          /* we want to ignore the zone gating if we are the zone gate */
311 
312          for (i = 0; i < config->addrCount; i++)
313          {
314             if (config->addr[i].zone == msg->destAddr.net &&
315                 config->addr[i].net == msg->destAddr.net &&
316                 config->addr[i].node == msg->destAddr.node &&
317                 config->addr[i].point == 0)
318             {
319                zonegated = 0;
320             }
321          }
322       }
323 
324       if (zonegated)
325       {
326          msg->destAddr.zone = intl_from.zone;
327          msg->destAddr.net  = intl_from.zone;
328          msg->destAddr.node = intl_to.zone;
329       }
330       else
331       {
332          msg->destAddr.zone = intl_to.zone;
333          msg->destAddr.net  = intl_to.net;
334          msg->destAddr.node = intl_to.node;
335       }
336 
337    } else {
338 
339       /* no INTL kludge */
340 
341       msg->destAddr.zone = header->destAddr.zone;
342       msg->origAddr.zone = header->origAddr.zone;
343 
344       msg->textLength += xscatprintf(&text,"\001INTL %u:%u/%u %u:%u/%u\r",msg->destAddr.zone,msg->destAddr.net,msg->destAddr.node,msg->origAddr.zone,msg->origAddr.net,msg->origAddr.node);
345       xstrcat(&text,msg->text);
346       nfree(msg->text);
347       msg->text = text;
348 
349       w_log( LL_PKT, "Mail without INTL-Kludge. Assuming %i:%i/%i.%i -> %i:%i/%i.%i",
350 		    msg->origAddr.zone, msg->origAddr.net, msg->origAddr.node, msg->origAddr.point,
351 		    msg->destAddr.zone, msg->destAddr.net, msg->destAddr.node, msg->destAddr.point);
352    } /* endif */
353 }
354 
correctAddr(s_message * msg,s_pktHeader * header)355 void correctAddr(s_message *msg,s_pktHeader *header)
356 {
357 	if (strncmp(msg->text, "AREA:",5) == 0) {
358 
359 		if (strncmp(msg->text+5, "NETMAIL\r",8) == 0) {
360 			switch (config->kludgeAreaNetmail) {
361 			case kanKill: /*  kill "AREA:NETMAIL\r" */
362 				memmove(msg->text, msg->text+13, msg->textLength-12);
363 			case kanIgnore: /*  process as netmail. don't touch kludge. */
364 				msg->netMail = 1;
365 			default: /*  process as echomail */
366 				break;
367 			}
368 		}
369 
370 	} else msg->netMail = 1;
371 
372 	if (msg->netMail) correctNMAddr(msg,header);
373 	else correctEMAddr(msg);
374 }
375 
376 /* Some toupper routines crash when they get invalid input. As this program
377    is intended to be portable and deal with any sort of malformed input,
378    we have to provide our own toupper routine. */
safe_toupper(char c)379 char safe_toupper(char c)
380 {
381     const char *from_table = "abcdefghijklmnopqrstuvwxyz";
382     const char *to_table   = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
383     const char *p;
384 
385     if ((p = strchr(from_table, c)) != NULL)
386     {
387         return (to_table[p - from_table]);
388     }
389 
390     return c;
391 }
392 
get_month(const char * pmon,flag_t * flag)393 int get_month(const char *pmon, flag_t *flag)
394 {
395     int i;
396 
397     if (strlen(pmon) != 3 && flag != NULL)
398     {
399         (*flag) |= FTSC_FLAWY;
400     }
401 
402     for (i=0; i < 12; i++)
403     {
404         if (pmon[0] == months_ab[i][0] &&
405             pmon[1] == months_ab[i][1] &&
406             pmon[2] == months_ab[i][2])
407         {
408             return i;
409         }
410     }
411 
412     for (i=0; i < 12; i++)
413     {
414         if (safe_toupper(pmon[0]) == safe_toupper(months_ab[i][0]) &&
415             safe_toupper(pmon[1]) == safe_toupper(months_ab[i][1]) &&
416             safe_toupper(pmon[2]) == safe_toupper(months_ab[i][2]))
417         {
418             (*flag) |= FTSC_FLAWY;
419             return i;
420         }
421     }
422 
423     (*flag) |= FTSC_BROKEN;
424     return 0;
425 }
426 
parse_ftsc_date(struct tm * ptm,char * pdatestr)427 flag_t parse_ftsc_date(struct tm * ptm, char *pdatestr)
428 {
429     const char *pday, *pmon, *pyear, *phour, *pminute, *psecond;
430     flag_t rval;
431     char buf[22];
432 	int fixseadog=0;
433 	struct tm *pnow;
434     time_t t_now;
435 
436     time(&t_now);
437     pnow = localtime(&t_now);   /* get the current time */
438 
439     pday = pmon = pyear = phour = pminute = psecond = NULL;
440 
441     rval = FTSC_BROKEN;
442 
443     memcpy(buf, pdatestr, 21); buf[21] = 0;
444 
445     if ((pday = strtok(buf, " ")) != NULL)
446         if ((pmon = strtok(NULL, " ")) != NULL)
447             if ((pyear = strtok(NULL, " ")) != NULL)
448                 if ((phour = strtok(NULL, ":")) != NULL)
449                     if ((pminute = strtok(NULL, ":")) != NULL)
450                         if ((psecond = strtok(NULL, " ")) != NULL)
451                             rval = 0;
452 
453     if (rval == FTSC_BROKEN)
454     {
455                  /* let's try and see if it might be the old SeaDog format */
456 
457         memcpy(buf, pdatestr, 21); buf[21] = 0;
458 
459         if ((strtok(buf, " ")) != NULL)
460             if ((pday = strtok(NULL, " ")) != NULL)
461                 if ((pmon = strtok(NULL, " ")) != NULL)
462                     if ((pyear = strtok(NULL, " ")) != NULL)
463                         if ((phour = strtok(NULL, ": ")) != NULL)
464                             if ((pminute = strtok(NULL, ": ")) != NULL)
465                             {
466                                 psecond = NULL;
467                                 if (fixseadog)
468                                     rval = FTSC_SEADOG;
469                                 else
470                                     rval = 0;
471                             }
472     }
473 
474 
475     ptm->tm_sec = ptm->tm_min = ptm->tm_hour = ptm->tm_mday = ptm->tm_mon =
476         ptm->tm_year = 0;
477 
478     while (rval != FTSC_BROKEN)    /* at least we could tokenize it! */
479     {
480         if (psecond != NULL)
481         {
482             ptm->tm_sec = atoi(psecond);   /* Is the number of seconds valid? */
483             if (strlen(psecond) == 1)
484             {
485                 rval |= FTSC_FLAWY;
486                 if (ptm->tm_sec < 6) (ptm->tm_sec *= 10);
487             }
488             if (ptm->tm_sec < 0 || ptm->tm_sec > 59)
489             {
490                 rval |= FTSC_TS_BROKEN; ptm->tm_sec = 0;
491             }
492         }
493         else
494         {
495             ptm->tm_sec = 0;
496         }
497 
498         ptm->tm_min = atoi(pminute);   /* Is the number of minutes valid? */
499         if (ptm->tm_min < 0 || ptm->tm_min > 59)
500         {
501             rval |= FTSC_TS_BROKEN; ptm->tm_min = 0;
502         }
503 
504         ptm->tm_hour = atoi(phour);    /* Is the number of hours valid? */
505         if (ptm->tm_hour < 0 || ptm->tm_hour>23)
506         {
507             rval |= FTSC_TS_BROKEN; ptm->tm_hour = 0;
508         }
509 
510         ptm->tm_mday = atoi(pday);     /* Is the day in the month valid? */
511         if (ptm->tm_mday < 1 || ptm->tm_mday>31) { rval |= FTSC_BROKEN; break; }
512 
513         ptm->tm_mon = get_month(pmon, &rval); /* Is the month valid? */
514 
515         if (strlen(pyear) != 2)        /* year field format check */
516         {
517             rval |= FTSC_FLAWY;
518         }
519 
520         if (*pyear)
521         {
522             ptm->tm_year = (*pyear - '0'); /* allows for the ":0" bug */
523             for (pyear++; isdigit((int)(*pyear)); pyear++)
524             {
525                 ptm->tm_year *= 10;
526                 ptm->tm_year += (*pyear - '0');
527             }
528             if (*pyear)
529             {
530                 rval |= FTSC_BROKEN;
531                 break;
532             }
533         }
534         else
535         {
536             rval |= FTSC_BROKEN;
537             break;
538         }
539 
540         if (ptm->tm_year < 100)  /* correct date field! */
541         {
542             while (pnow->tm_year - ptm->tm_year > 50)
543             {                         /* sliding window adaption */
544                 ptm->tm_year += 100;
545             }
546         }
547         else if (ptm->tm_year < 1900) /* probably the field directly */
548                                       /* contains tm_year, like produced */
549                                       /* by the Timed/Netmgr bug and others */
550         {
551             rval |= FTSC_FLAWY;
552         }
553         else                          /* 4 digit year field, not correct! */
554         {
555             ptm->tm_year -= 1900;
556             rval |= FTSC_FLAWY;
557         }
558         break;
559     }
560 
561 
562     return rval;
563 
564 }
565 
make_ftsc_date(char * pdate,const struct tm * ptm)566 void make_ftsc_date(char *pdate, const struct tm *ptm)
567 {
568     sprintf(pdate, "%02d %-3.3s %02d  %02d:%02d:%02d",
569             ptm->tm_mday % 100, months_ab[ptm->tm_mon], ptm->tm_year % 100,
570             ptm->tm_hour % 100, ptm->tm_min % 100, ptm->tm_sec % 100);
571 }
572 
readMsgFromPkt(FILE * pkt,s_pktHeader * header,s_message ** message)573 int readMsgFromPkt(FILE *pkt, s_pktHeader *header, s_message **message)
574 {
575     s_message *msg;
576     int len, badmsg=0;
577     struct tm tm;
578     long unread;
579 
580     if (2 != getUINT16(pkt)) {
581         *message = NULL;
582 
583         unread = ftell(pkt);
584         fseek(pkt, 0L, SEEK_END);
585         unread = ftell(pkt) - unread; /*  unread bytes */
586 
587         if (unread) {
588             w_log(LL_ERR,"There are %d bytes of unknown data at the end of pkt file!",
589                 unread);
590             return 2; /*  rename to bad */
591         }
592         else return 0; /*  end of pkt file */
593     }
594 
595     msg = (s_message*) safe_malloc(sizeof(s_message));
596     memset(msg, '\0', sizeof(s_message));
597 
598     msg->origAddr.node   = getUINT16(pkt);
599     msg->destAddr.node   = getUINT16(pkt);
600     msg->origAddr.net    = getUINT16(pkt);
601     msg->destAddr.net    = getUINT16(pkt);
602     msg->attributes      = getUINT16(pkt);
603 
604     getc(pkt); getc(pkt);                /*  read unused cost fields (2bytes) */
605 
606     /* val: fgetsUntil0 (msg->datetime, 22, pkt, NULL);*/
607     if ( fread(msg->datetime, 20, 1, pkt) != 1 )    /* read datetime field - 20 bytes */
608         badmsg++;
609     msg->datetime[20] = 0;               /* ensure it's null-terminated */
610     parse_ftsc_date(&tm, (char*)msg->datetime);
611     /* val: make_ftsc_date((char*)msg->datetime, &tm); */
612 
613     if (globalBuffer==NULL) {
614         globalBuffer = (UCHAR *) safe_malloc(BUFFERSIZE+1); /*  128K (32K in MS-DOS) */
615     }
616 
617     len = fgetsUntil0 ((UCHAR *) globalBuffer, BUFFERSIZE+1, pkt, NULL);
618     if (len > XMSG_TO_SIZE) {
619         if (config->intab) recodeToInternalCharset((char*) globalBuffer);
620         w_log(LL_ERR, "wrong msg header: toUserName (%s) is longer than %d bytes.",
621             globalBuffer, XMSG_TO_SIZE-1);
622         if (config->outtab) recodeToTransportCharset((char*) globalBuffer);
623         globalBuffer[XMSG_TO_SIZE-1]='\0';
624         badmsg++;
625     }
626     xstrcat(&msg->toUserName, (char *) globalBuffer);
627 
628     fgetsUntil0((UCHAR *) globalBuffer, BUFFERSIZE+1, pkt, NULL);
629     if (len > XMSG_FROM_SIZE) {
630         if (config->intab) recodeToInternalCharset((char*) globalBuffer);
631         w_log(LL_ERR, "wrong msg header: fromUserName (%s) is longer than %d bytes.",
632             globalBuffer, XMSG_FROM_SIZE-1);
633         if (config->outtab) recodeToTransportCharset((char*) globalBuffer);
634         globalBuffer[XMSG_FROM_SIZE-1]='\0';
635         badmsg++;
636     }
637     xstrcat(&msg->fromUserName, (char *) globalBuffer);
638 
639     len = fgetsUntil0((UCHAR *) globalBuffer, BUFFERSIZE+1, pkt, NULL);
640     if (len > XMSG_SUBJ_SIZE) {
641         if (config->intab) recodeToInternalCharset((char*) globalBuffer);
642         w_log(LL_ERR, "wrong msg header: subjectLine (%s) is longer than %d bytes.",
643             globalBuffer, XMSG_SUBJ_SIZE-1);
644         if (config->outtab) recodeToTransportCharset((char*) globalBuffer);
645         globalBuffer[XMSG_SUBJ_SIZE-1]='\0';
646         badmsg++;
647     }
648     xstrcat(&msg->subjectLine, (char *) globalBuffer);
649 
650     if (badmsg) {
651         freeMsgBuffers(msg);
652         *message = NULL;
653         w_log(LL_ERR, "wrong msg header: renaming pkt to bad.");
654         return 2; /*  exit with error */
655     }
656 
657 #if !defined(__DOS__) || defined(__FLAT__)
658     w_dbglog(LL_DEBUG, "readMsgFromPkt()  32bit");
659     do {
660         len = fgetsUntil0((UCHAR *) globalBuffer, BUFFERSIZE+1, pkt, "\n");
661         xstrcat(&msg->text, (char*)globalBuffer);
662         msg->textLength+=len-1; /*  trailing \0 is not the text */
663     } while (len == BUFFERSIZE+1);
664 #else
665     w_dbglog(LL_DEBUG, "readMsgFromPkt() DOS-16");
666     /* DOS: read only one segment of message */
667     len = fgetsUntil0((UCHAR *) globalBuffer, BUFFERSIZE+1, pkt, "\n");
668     xstrcat(&msg->text, globalBuffer);
669     msg->textLength+=len-1; /*  trailing \0 is not the text */
670 
671     if( (len == BUFFERSIZE+1) ) {
672         badmsg++;
673         xstrscat(&msg->text, "\r* Message too big, truncated by ", versionStr, "\r",NULLP);
674         do {
675             char *origin;
676 
677             len = fgetsUntil0((UCHAR *) globalBuffer, BUFFERSIZE+1, pkt, "\n");
678             /* add kludges to end of striped text */
679             if((origin=strstr(globalBuffer, " * Origin"))) {
680                 xstrcat(&msg->text, origin);
681             }
682         } while (len == BUFFERSIZE+1);
683         strncpy( globalBuffer, aka2str(msg->destAddr), BUFFERSIZE );
684         w_log(LL_ERR, "Message from %s to %s is too big!", aka2str(msg->origAddr),
685             globalBuffer);
686     }
687 #endif
688 
689     correctAddr(msg, header);
690 #ifndef DO_PERL
691     {
692         char *p, *q;
693         /*  del "\001FLAGS" from message text */
694         if (NULL != (p=strstr(msg->text,"\001FLAGS"))) {
695             for (q=p; *q && *q!='\r'; q++);
696             memmove(p,q+1,msg->textLength-(q-msg->text));
697             msg->textLength -= (q-p+1);
698         }
699     }
700 #endif
701     *message = msg;
702     return 1;
703 }
704