1 #ifndef UNIX
2   #include <conio.h>
3 #else
4   #define getch getchar
5   #ifdef __FreeBSD__
6     #include <sys/time.h>
7     #include <sys/types.h>
8   #endif
9   #include <utime.h>
10 #endif
11 #if defined __BORLANDC__
12   #include <utime.h>
13 #endif
14 #include <stdlib.h>             // <malloc.h>
15 #include "buffer.hpp"
16 // #include "datetime.cpp"
17 #include "dirute.h"
18 
19 #include "structs.hpp"
20 
21 typedef	enum {formatMSG, formatSQUISH, formatJAM} format;
22 
23 typedef struct
24 {
25 	char FromUserName[36];
26 	char ToUserName[36];
27 	char Subject[72];
28 	char OrigDateTime[20];
29 	struct
30 	{
31 		short day,month,year;
32 	} date;
33 	struct
34 	{
35 		short hour,minute,second;
36 	} time;
37 	long ElapsedDays;
38 	byte DateParsed;
39 	unsigned short attrib;
40 	unsigned short attrib2;
41 	S_FQAddress Origin,Destination;
42 	S_FQAddress TransitAddr,*WishAddresses;
43 	short WishAddrCount;
44 	byte DetectedLoop;
45 	long MessageSize;
46 	byte Encrypted;
47 	short ProcessedHere;
48 	unsigned MSGIDZone;
49 	unsigned long MsgNumber;
50 	format formattype;
51 } S_Visu;
52 
53 
FlagAsSent(char * path)54 int FlagAsSent (char *path)
55 {
56     FILE *msg;
57     S_MSG header;
58 
59     msg=fopen (path,"r+b");
60     if (msg==NULL)
61         return EFAS_OPENFAILED;
62     if (!header.read(msg)) {
63         fclose(msg);
64         return EFAS_OPENFAILED;
65     }
66     if (fseek (msg,0,SEEK_SET)) {
67         fclose(msg);
68         return EFAS_OPENFAILED;
69     }
70     Set_Sent(header.Attribute,1);
71     if (!header.write(msg)) {
72         fclose (msg);
73         return EFAS_CANTWRITE;
74     }
75     fclose (msg);
76     return SUCCESS;
77 }
78 
FindAttachedFile(char * buffer,int maxlen)79 void FindAttachedFile(char *buffer, int maxlen)
80 {
81     char *buf2;
82 
83     int i;
84                                 // first, see if this is an absolute filename
85                                 // at all
86     if (strchr(buffer, '/') == NULL && strchr(buffer, '\\') == NULL &&
87         strchr(buffer, ':') == NULL)
88     {
89 
90         buf2 = (char *)malloc(maxlen + 1 + InboundHandler.GetLongestString());
91         if (buf2 == NULL)
92         {                       // can't help ...
93             adaptcase(buffer); return;
94         }
95 
96                                 // we have a relative path name. ouch.
97         for (i = 0; i < InboundHandler.GetInboundCount(); i++)
98         {
99             sprintf(buf2, "%s/%s", InboundHandler.GetInbound(i), buffer);
100 
101             if (file_exists((char *)buf2))
102             {
103                 buf2[maxlen - 1] = '\0';
104                 strcpy(buffer, buf2);
105                 return;
106             }
107         }
108 
109 #ifdef UNIX
110                                 // next try, this time using the slow adaptcase
111                                 // code
112         for (i = 0; i < InboundHandler.GetInboundCount(); i++)
113         {
114             sprintf(buf2, "%s/%s", InboundHandler.GetInbound(i), buffer);
115             adaptcase(buf2);
116 
117             if (file_exists((char *)buf2))
118             {
119                 buf2[maxlen - 1] = '\0';
120                 strcpy(buffer, buf2);
121                 return;
122             }
123         }
124 #endif
125 
126         adaptcase(buf2);
127     }
128     adaptcase(buffer);
129 }
130 
SubjectToFile(char * Subject,char * savepath,char * extattach,int Truncate,int Delete)131 int SubjectToFile (char *Subject,char *savepath,char *extattach,int Truncate,int Delete)
132 {
133 	FILE *out;
134 	char complete[256];
135 	strcpy (complete,savepath);
136 	strcat (complete,extattach);
137         adaptcase(complete);
138 	out=fopen (complete,"r+a");
139 	if (out==NULL)
140 	{
141 		out=makedirandfopen (complete,"w+a");
142 		if (out==NULL)
143 			return ESTF_FAILURE;
144 	}
145 	fseek (out,0,SEEK_END);
146 	while (Subject[0])
147 	{
148                 GetAndStripToken (Subject,complete+1);
149                 FindAttachedFile(complete + 1, (int)(sizeof(complete) - 1));
150 		if (Delete)
151 			complete[0]='^';
152 		else
153 		if (Truncate)
154 			complete[0]='#';
155 		else
156 			strcpy (complete,complete+1);
157 		fprintf (out,"%s\n",complete);
158 	}
159 	fclose (out);
160 	return SUCCESS;
161 }
162 
StripPath(char * source,char * storage)163 void StripPath (char *source, char *storage)
164 {
165 	char token[80],target[80],*c;
166 	strcpy (target,source);
167 	storage[0]=0;
168 	while (strlen (target))
169 	{
170 		GetAndStripToken (target,token);
171 		c=token+strlen (token)-1;
172 		while (c>=token && *c!=DIRSEPC && *c!=':')
173 			c--;
174 		strcat (storage,c+1);
175 		strcat (storage," ");
176 	}
177 	while (strlen (storage) && storage[strlen (storage)-1]==' ')
178 		storage[strlen (storage)-1]=0;
179 }
180 
SignNet(FILE * onet,S_FQAddress addressinnet)181 int SignNet (FILE *onet,S_FQAddress addressinnet)
182 {
183 	DateTime dt;
184 	char point[10];
185 	dt.getCurrentTime();
186 	char ViaLine[120];
187 	S_FQAddress OurAddress;
188 	AddressHandler.AKAMatch (addressinnet,&OurAddress);
189 	if (OurAddress.Point==0)
190 		point[0]=0;
191 	else
192 		sprintf (point,".%hu",OurAddress.Point);
193 	sprintf (ViaLine,"%cVia %hu:%hu/%hu%s%s%s @%04hu%02hu%02hu.%02hu%02hu%02hu %s\r",
194 		1,OurAddress.Zone,OurAddress.Net,OurAddress.Node,point,
195 						OurAddress.Domain[0]?"@":"",OurAddress.Domain,dt.year,
196 						dt.month,dt.day,dt.hours,dt.minutes,dt.seconds,
197 						IDENTString
198 						);
199 	fwrite (ViaLine,strlen (ViaLine)+1,1,onet);
200 	return SUCCESS;
201 }
202 
MSGToPKT(char * MSGPath,char * PKTPath,char * ext,S_FQAddress via,S_FQAddress OurAKA,S_FQAddress FinalDest,int UseT2,int is_qqq)203 int MSGToPKT (char *MSGPath,char *PKTPath,char *ext,S_FQAddress via,S_FQAddress
204               OurAKA,S_FQAddress FinalDest,int UseT2, int is_qqq)
205 {
206 	FILE *in,*out;
207 	S_MSG headerin;
208 	S_Packed headerout;
209 	S_PKT headerPKT;
210 	DateTime dt;
211 	char *buffer,completepath[256];
212 	char NoPathSubject[80],lasttwo[2];
213 	long ToCopy;
214 	size_t BufferSize,read;
215 	in=fopen (MSGPath,"rb");
216 	if (in==NULL)
217 		return ECONV_OPENFAILIN;
218 	strcpy (completepath,PKTPath);
219 	strcat (completepath,ext);
220         adaptcase(completepath);
221 	out=fopen (completepath,"r+b");
222 	if (out==NULL)
223 	{
224 		out=makedirandfopen (completepath,"w+b");
225 		if (out==NULL)
226 		{
227 			fclose (in);
228 			return ECONV_OPENFAILOUT;
229 		}
230 		// The file doesn't exist yet - we have to create it and add
231 		// a header
232 		dt.getCurrentTime();
233 		headerPKT.OrigNode=OurAKA.Node;
234 		headerPKT.DestNode=via.Node;
235 		headerPKT.Year=dt.year;
236 		headerPKT.Month=dt.month - 1;
237 		headerPKT.Day=dt.day;
238 		headerPKT.Hour=dt.hours;
239 		headerPKT.Minute=dt.minutes;
240 		headerPKT.Second=dt.seconds;
241 		headerPKT.Baud=0;
242 		headerPKT.Signature=2;
243 		headerPKT.OrigNet=OurAKA.Net;
244 		headerPKT.DestNet=via.Net;
245 		headerPKT.ProdCode=0;
246 		headerPKT.SerialNo=0;
247 		memset (&headerPKT.Password,0,8);
248 		PasswordHandler.GetPassword (via,headerPKT.Password);
249 		headerPKT.OrigZone=OurAKA.Zone;
250 		headerPKT.DestZone=via.Zone;
251 		memset (&headerPKT.dif.Fill,0,20);
252 		memset (&headerPKT.EndOfPKT,0,sizeof (headerPKT.EndOfPKT));
253 		if (UseT2==0) // Add type2+ data
254 		{
255 			headerPKT.dif.t2plus.CapabilitySwapped=256;
256 			headerPKT.dif.t2plus.Capability=1;
257 			headerPKT.dif.t2plus.PrdCodH=1;
258 			headerPKT.dif.t2plus.PVMinor=1;
259 			headerPKT.dif.t2plus.OrigZone=OurAKA.Zone;
260 			headerPKT.dif.t2plus.DestZone=via.Zone;
261 			headerPKT.dif.t2plus.OrigPoint=OurAKA.Point;
262 			headerPKT.dif.t2plus.DestPoint=via.Point;
263 		}
264                 headerPKT.write(out);
265 	}
266         if (!headerin.read(in))
267 	{
268 		fclose (in);
269 		fclose (out);
270 		return ECONV_SHORTIN;
271 	}
272 
273 	if (DoRecode) {
274 		recodeToTransportCharset (headerin.FromUserName, 36);
275 		recodeToTransportCharset (headerin.ToUserName, 36);
276 		recodeToTransportCharset (headerin.Subject, 72);
277 		recodeToTransportCharset (headerin.DateTime, 20);
278 	}
279 
280 	/* We truncate the last 2 bytes of the .PKT if they are both zero.
281 	   Otherwise it is likely that the .PKT is damaged and it is better
282 	   not to destroy anything on it */
283 	fseek (out,-2,SEEK_END);
284 	fread (lasttwo,1,2,out);
285 	if (lasttwo[0]==0 && lasttwo[1]==0)
286 		fseek (out,-2,SEEK_END);
287 
288 	headerout.Signature=2;
289 	headerout.OrigNode=headerin.OrigNode;
290 	headerout.OrigNet=headerin.OrigNet;
291 	headerout.DestNode=headerin.DestNode;
292 	headerout.DestNet=headerin.DestNet;
293 	headerout.Attrib=headerin.Attribute;
294 	// Note that the InTransit and local flags are stripped (!!)
295 	Set_InTransit(headerout.Attrib,0);
296 	Set_Local(headerout.Attrib,0);
297 	headerout.Cost=0;
298 	memcpy (&headerout.DateTime,&headerin.DateTime,20);
299         headerout.write(out);
300 	fwrite (&headerin.ToUserName,1,strlen (headerin.ToUserName)+1,out);
301 	fwrite (&headerin.FromUserName,1,strlen (headerin.FromUserName)+1,out);
302 	if (S_FileAttached(headerin.Attribute))
303             StripPath (headerin.Subject,NoPathSubject);
304 	else
305             strcpy (NoPathSubject,headerin.Subject);
306 	fwrite (NoPathSubject,1,strlen (NoPathSubject)+1,out);
307         ToCopy=lengthoffile(in)-headerin.get_filesize(); // sizeof (S_MSG);
308 	BufferSize=(ToCopy>32767)?32767:(size_t) ToCopy;
309 	while (((buffer=(char *) malloc (BufferSize)) == NULL) && (BufferSize>1024))
310 		BufferSize = (BufferSize / 10) * 9;
311 	if (buffer==NULL)
312 	{
313 		fclose (in);
314 		fclose (out);
315 		return NOMEMORY;
316 	}
317 	/* Note that in the body copy loop we copy up to, but not including,
318 	   the first zero. If there is something beyond that zero, it won't
319 	   be copied, because that would result in a damaged .PKT. */
320 	if (ToCopy>0)
321 	{
322 		while (ToCopy>0)
323 		{
324 			if (ToCopy>(long)((unsigned long)BufferSize))
325 				read=fread (buffer,1,BufferSize,in);
326 			else
327 				read=fread (buffer,1,(size_t) ToCopy,in);
328 			if (strlen (buffer)<read)
329 			{
330 				read=strlen (buffer);
331 				ToCopy=read;
332 			}
333 			if (DoRecode)
334 				recodeToTransportCharset (buffer, read);
335 			fwrite (buffer,1,read,out);
336 			ToCopy-=read;
337 		}
338 		if (buffer[read-1]!='\r')
339 			fwrite ("\r",1,1,out);
340 	}
341 	/* Add our via line - note that it has a zero to end the message */
342 	SignNet (out,FinalDest);
343 	/* End of PKT 00 00 - added UNLESS we are generating .QQQs, to
344 	   follow Tobias Burchhardt's specs */
345 	if (!is_qqq)
346 	{
347 		memset (&headerPKT.EndOfPKT,0,sizeof (headerPKT.EndOfPKT));
348 		fwrite (&headerPKT.EndOfPKT,1,sizeof (headerPKT.EndOfPKT),out);
349 	}
350 	free (buffer);
351 	fclose (in);
352 	fclose (out);
353 	return (SUCCESS);
354 }
355 
ToNextWord(char * begin)356 char *ToNextWord (char *begin)
357 {
358 	int sp=0;
359 	if (*begin=='\0')
360 		return NULL;
361 	if (*begin==' ')
362 		sp=1;
363 	while (*begin && *begin==' ') // Skip all spaces
364 		begin++;
365 	if (*begin=='\0')
366 		return NULL;
367 	if (sp)
368 		return begin; // We are a the beginning of a new world
369 	while (*begin && *begin!=' ') // To end of word
370 		begin++;
371 	while (*begin && *begin==' ') // Skip all spaces
372 		begin++;
373 	if (*begin=='\0')
374 		return NULL;
375 	return begin;
376 }
377 
378 // Scan begin for a possible address
ScanForAddress(char * begin)379 char *ScanForAddress (char *begin)
380 {
381 	char *store;
382 	char *s,*as;
383 	int qualify=0;
384 	S_FQAddress Address;
385 	store=(char *) malloc (strlen (begin)+1);
386 	if (!store)
387 		return NULL;
388 	s=begin;
389 	while (qualify==0 && s)
390 	{
391 		strcpy (store,s);
392 		as=strchr (store,' ');
393 		if (as) // Keep only to end of word
394 			*as=0;
395 		as=strchr (store,'@'); // We don't mind about domain stuff
396 		if (as)
397 			*as=0;
398 		if (GetFullQualifiedAddress (store,&Address,NULL)==SUCCESS)
399 			qualify=1;
400 		else
401 			s=ToNextWord (s);
402 	}
403 	free (store);
404 	return s;
405 }
406 
407 /* Process line for kludges, vias, etc */
ProcessLine(char * line,S_Visu * storage,C_StringList * SL_Via,C_StringList * SL_Path)408 void ProcessLine (char *line,S_Visu *storage,C_StringList *SL_Via, C_StringList *SL_Path)
409 {
410 	struct S_FQAddress FQA;
411 	C_FileRead FHandler;
412 	char *first,*search,*possible,newpath[26];
413 	char Parsing[21];
414 	first=(char *) line;
415 	if (first[0]==1) // Kludge!
416 	{
417 		if (strstr (first+1,"ENC")==first+1)
418 			storage->Encrypted=1;
419 		else
420 		if (strstr (first+1,"Via")==first+1) // Already processed...
421 		{
422  			possible=ScanForAddress (first);
423 			if (possible!=NULL)
424 			{
425 				GetFullQualifiedAddress (possible,&FQA,NULL);
426 				if (SL_Path!=NULL)
427 				{
428 					sprintf (newpath,"%u:%u/%u.%u",FQA.Zone,
429 						FQA.Net,FQA.Node,FQA.Point);
430 					if (SL_Path->GetStringCount ()==0)
431 							SL_Path->AddString (newpath);
432 				else
433 						if (strcmp (SL_Path->GetString (SL_Path->GetStringCount()-1),newpath))
434 							SL_Path->AddString (newpath);
435 				}
436 				if (AddressHandler.IsLocalAKA (FQA))
437 				{
438 					storage->ProcessedHere=1;
439 					if (!RecordViaLines)
440 						if (SL_Via != NULL)
441 							SL_Via->DestroyList ();
442 				}
443 				else
444 					/* If there was a previous Via line with one of
445 					   our addresses but current isn't local, then
446 					   we have a loop */
447 					if (storage->ProcessedHere==1)
448 						storage->DetectedLoop=1;
449 			}
450 			if (SL_Via!=NULL)
451 				SL_Via->AddString (first+1);
452 		}
453 		else
454 		if (strstr (first+1,"MSGID")==first+1) // MSGID
455 		{
456 			search=first+8;
457 			while (*search)
458 			{
459 				if (!isdigit (*search))
460 					break;
461 				search++;
462 			}
463 			if (*search==':') // It is a zone
464 			{
465 				*search=0;
466 				storage->MSGIDZone=atoi (first+8);
467 			}
468 		}
469 		else
470 		if (strstr (first+1,"TOPT")==first+1) // Destination point
471 		{
472 			if (isdigit (*(first+6))) // Always should but...
473 			{
474 				search=first+6;
475 				while (isdigit (*search))
476 					search++;
477 				*search=0;
478 				storage->Destination.Point=atoi (first+6);
479 			}
480 		}
481 		if (strstr (first+1,"FMPT")==first+1) // Destination point
482 		{
483 			if (isdigit (*(first+6))) // Always should but...
484 			{
485 				search=first+6;
486 				while (isdigit (*search))
487 					search++;
488 				*search=0;
489 				storage->Origin.Point=atoi (first+6);
490 			}
491 		}
492 		if (strstr (first+1,"INTL")==first+1) // Zones
493 		{
494 			search=strchr (first+6,' ');
495 			if (search)
496 			{
497 				*search=0;
498 				if (GetFullQualifiedAddress (first+6,&FQA,NULL)==SUCCESS)
499 				{
500 					storage->Destination.Zone=FQA.Zone;
501 					storage->Destination.Net=FQA.Net;
502 					storage->Destination.Node=FQA.Node;
503 					if (GetFullQualifiedAddress (search+1,&FQA,NULL)==SUCCESS)
504 					{
505 						storage->Origin.Zone=FQA.Zone;
506 						storage->Origin.Net=FQA.Net;
507 						storage->Origin.Node=FQA.Node;
508 					}
509 				}
510 			}
511 		}
512 		if (strstr (first+1,"FLAGS")==first+1)
513 		{
514 			first++;
515 			GetAndStripToken (first,Parsing); // remove 'flags'
516 			while (first[0])
517 			{
518 				GetAndStripToken (first,Parsing);
519 				switch (GetTokenType (Parsing))
520 				{
521                                 case TT_PVT:
522                                     Set_Private(storage->attrib,1);
523                                     break;
524                                 case TT_HLD:
525                                     Set_Hold(storage->attrib,1);
526                                     break;
527                                 case TT_CRA:
528                                     Set_Crash(storage->attrib,1);
529                                     break;
530                                 case TT_KS:
531                                     Set_KillSent(storage->attrib,1);
532                                     break;
533                                 case TT_SNT:
534                                     Set_Sent(storage->attrib,1);
535                                     break;
536                                 case TT_RCV:
537                                     Set_Recd(storage->attrib,1);
538                                     break;
539                                 case TT_AS:
540                                     Set_ArchiveSent(storage->attrib2,1);
541                                     break;
542                                 case TT_DIR:
543                                     Set_Direct(storage->attrib2,1);
544                                     break;
545                                 case TT_ZON:
546                                     Set_Zonegate(storage->attrib2,1);
547                                     break;
548                                 case TT_HUB:
549                                     Set_Hub(storage->attrib2,1);
550                                     break;
551                                 case TT_FIL:
552                                     Set_FileAttached(storage->attrib,1);
553                                     break;
554                                 case TT_FRQ:
555                                     Set_FileRequest(storage->attrib,1);
556                                     break;
557                                 case TT_IMM:
558                                     Set_Immediate(storage->attrib2,1);
559                                     break;
560                                 case TT_XMA:
561                                     Set_XMA(storage->attrib2,1);
562                                     break;
563                                 case TT_KFS:
564                                     Set_KillFileSent(storage->attrib2,1);
565                                     break;
566                                 case TT_TFS:
567                                     Set_Truncate(storage->attrib2,1);
568                                     break;
569                                 case TT_LOK:
570                                     Set_Lock(storage->attrib2,1);
571                                     break;
572                                 case TT_RRQ:
573                                    Set_ReturnReceiptRequest(storage->attrib,1);
574                                    break;
575                                 case TT_CFM:
576                                     Set_IsReturnReceipt(storage->attrib,1);
577                                     break;
578                                 case TT_HIR:
579                                     Set_HiRes(storage->attrib2,1);
580                                     break;
581                                 case TT_COV:
582                                     Set_CoverLetter(storage->attrib2,1);
583                                     break;
584                                 case TT_SIG:
585                                     Set_Signature(storage->attrib2,1);
586                                     break;
587                                 case TT_LET:
588                                     Set_LetterHead(storage->attrib2,1);
589                                     break;
590                                 case TT_FAX:
591                                     Set_Fax(storage->attrib2,1);
592                                     break;
593                                 case TT_FPU:
594                                     Set_ForcePickup(storage->attrib2,1);
595                                     break;
596 				}
597 			}
598 		}
599 	}
600 }
601 
602 // Transform the (useless) standard .MSG format in something we can
603 // handle easily.
GetVisibleInfo(char * path,S_Visu * storage,C_StringList * SL_Via,C_StringList * SL_Path)604 int GetVisibleInfo (char *path,S_Visu *storage,C_StringList *SL_Via, C_StringList *SL_Path)
605 {
606         DateTime dtnow;
607         S_MSG header;
608 	struct S_FQAddress FQA;
609 	C_FileRead FHandler;
610 	void *buffer;
611 	char newpath[26];
612 	char Parsing[21];
613 	int count;
614 	char *ptr;
615 	size_t path_len;
616 	storage->ProcessedHere=0;
617 	storage->MSGIDZone=0;
618 
619 	// try to get MsgNumber from path
620 	path_len = strlen (path);
621 	if (path_len >= 5 &&
622 			isdigit (path[path_len-5]) &&
623 			path[path_len-4] == '.' &&
624 			(path[path_len-3] == 'M' || path[path_len-3] == 'm') &&
625 			(path[path_len-2] == 'S' || path[path_len-2] == 's') &&
626 			(path[path_len-1] == 'G' || path[path_len-1] == 'g')) {
627 		ptr = path + path_len - 5;
628 		while (isdigit (*ptr))
629 			ptr--;
630 		ptr++;
631 		storage->MsgNumber = strtol (ptr, NULL, 10);
632 	} else
633 		storage->MsgNumber = 0;
634 	storage->formattype = formatMSG;
635 
636 	// Get as much info as possible from the header
637 	if (FHandler.OpenFile (path)!=SUCCESS)
638 		return ENH_OPENFAIL;
639         storage->MessageSize=FHandler.FileSize()-header.get_filesize();
640                                                              // sizeof (S_MSG);
641 	buffer=malloc (BUFFER_SIZE); // Buffer to get lines
642 	if (buffer==NULL)
643 	{
644 		FHandler.CloseFile ();
645 		return NOMEMORY;
646 	}
647 	// Read header
648         if (!header.read(FHandler))
649 	{
650 		FHandler.CloseFile ();
651 		free (buffer);
652 		return ENH_SHORTFILE;
653 	}
654 // Empty zones, point & domain
655 	AddressHandler.GetMain (&FQA);
656 	storage->Origin.Zone=storage->Destination.Zone=0;
657 	storage->Origin.Point=storage->Destination.Point=0;
658 	storage->Origin.Domain[0]=storage->Destination.Domain[0]=0;
659 	storage->DetectedLoop=0;
660 	// Empty encryption
661 	storage->Encrypted=0;
662 	// Names and subject
663 	strcpy (storage->FromUserName,header.FromUserName);
664 	strcpy (storage->ToUserName,header.ToUserName);
665 	strcpy (storage->Subject,header.Subject);
666         // Original date & time string
667 	strcpy (storage->OrigDateTime,header.DateTime);
668 	// Attempt to parse the time and date
669 	storage->DateParsed=0;
670 	strcpy (Parsing,header.DateTime);
671 	if (isdigit (Parsing[0]) && isdigit (Parsing[1]) && Parsing[2]==' ' &&
672 		isalpha (Parsing[3]) && isalpha (Parsing[4]) && isalpha(Parsing[5]) &&
673 		Parsing[6]==' ' && isdigit(Parsing[7]) && isdigit(Parsing[8]) &&
674 		Parsing[9]==' ' && Parsing[10]==' ' && isdigit(Parsing[11]) &&
675 		isdigit(Parsing[12]) && Parsing[13]==':' && isdigit(Parsing[14]) &&
676 		isdigit(Parsing[15]) && Parsing[16]==':' && isdigit(Parsing[17]) &&
677 		isdigit(Parsing[18]))
678 	{
679 		// If here it has the expected format - separate tokens
680 		Parsing[2]=Parsing[6]=Parsing[9]=Parsing[13]=Parsing[16]=0;
681 		storage->date.day=atoi (Parsing);
682 		storage->date.month=0;
683 		for (count=0;count<12;count++)
684 		{
685 			if (cistrcmp (Parsing+3,Months[count])==0)
686 			{
687 				storage->date.month=count+1;
688 				break;
689 			}
690 		}
691 		if (storage->date.month!=0) // If we don't have a month, quit parsing
692 		{
693 			storage->date.year=1900 + atoi (Parsing+7);
694 			storage->time.hour=atoi (Parsing+11);
695 			storage->time.minute=atoi (Parsing+14);
696 			storage->time.second=atoi (Parsing+17);
697 			storage->DateParsed=1;
698 
699                         /* sliding window adaption of year number */
700 
701                         dtnow.getCurrentTime();
702                         while (storage->date.year + 50 <= dtnow.year)
703                                 storage->date.year += 100;
704                         while (storage->date.year - 50 > dtnow.year)
705                                 storage->date.year -= 100;
706 		}
707 	}
708 	storage->attrib=header.Attribute;
709 	storage->attrib2=0;
710         Set_Direct(storage->attrib2, S_Unused(storage->attrib));
711 	storage->Origin.Net=header.OrigNet;
712 	storage->Origin.Node=header.OrigNode;
713 	storage->Destination.Net=header.DestNet;
714 	storage->Destination.Node=header.DestNode;
715 	// We still need the origin and destination zones & points
716 	// they are somewhere in the message text...
717 	while (FHandler.ReadUpTo (buffer,"\r\n")!=EBH_EOF)
718 	{
719 		ProcessLine ((char *) buffer,storage,SL_Via, SL_Path);
720 	}
721 	if (storage->Origin.Zone==0)
722 		storage->Origin.Zone=storage->MSGIDZone;
723 	if (storage->Destination.Zone==0)
724 		storage->Destination.Zone=storage->MSGIDZone;
725 	AddressHandler.GetMain (&FQA);
726 	if (storage->Origin.Zone==0)
727 		storage->Origin.Zone=FQA.Zone;
728 	if (storage->Destination.Zone==0)
729 		storage->Destination.Zone=FQA.Zone;
730 	memcpy (&storage->TransitAddr,&storage->Destination,sizeof (struct S_FQAddress));
731 	// Handle hostgated messages
732 	if (S_Hub(storage->attrib2)==1)
733 	{
734 		if (AddressHandler.OurNet (storage->Destination.Zone,storage->Destination.Net)==EAD_FOREIGN)
735 		{
736 				storage->TransitAddr.Node=0;
737 				storage->TransitAddr.Point=0;
738 		}
739 	}
740 	// Handle zonegated messages
741 	if (S_Zonegate(storage->attrib2)==1)
742 	{
743 		if (AddressHandler.OurZone (storage->Destination.Zone)==EAD_FOREIGN)
744 		{ // To a foreign zone...
745 			// Example: From 2:* to 1:* becomes 2:2/1.0.
746 			storage->TransitAddr.Net=storage->Destination.Zone;
747 			storage->TransitAddr.Zone=storage->Destination.Zone;
748 			storage->TransitAddr.Node=storage->Origin.Zone;
749 			storage->TransitAddr.Point=0;
750 		}
751 	}
752 	sprintf (newpath,"%u:%u/%u.%u",storage->Origin.Zone,
753 		storage->Origin.Net,storage->Origin.Node,storage->Origin.Point);
754 	if (SL_Path!=NULL)
755 	{
756 		if (SL_Path->GetStringCount ()==0)
757 			SL_Path->AddString (newpath);
758 		else
759 			if (strcmp (SL_Path->GetString (0),newpath))
760 				SL_Path->InsertString (newpath,0);
761 	}
762 	free (buffer);
763 	FHandler.CloseFile ();
764 	return SUCCESS;
765 }
766 
ShowNet(char * path)767 int ShowNet (char *path)
768 {
769         S_MSG header;
770         S_Visu extra;
771 	FILE *fnet;
772 	void *buffer;
773 	char *point,*first;
774 	int count=0;
775 	fnet=fopen (path,"rb");
776 	if (fnet==NULL)
777 		return ENH_OPENFAIL;
778 	buffer=malloc (2048);
779 	if (buffer==NULL)
780 	{
781 		fclose (fnet);
782 		return NOMEMORY;
783 	}
784 	fread (buffer,2048,1,fnet);
785 	((char *)buffer)[2047]=0;
786         header.Import((const unsigned char *)buffer);
787 	printf ("            From: %s\n",header.FromUserName);
788 	printf ("              To: %s\n",header.ToUserName);
789 	printf ("         Subject: %s\n",header.Subject);
790 	printf ("        DateTime: %s\n",header.DateTime);
791 	printf ("      Times read: %u\n",header.TimesRead);
792 	printf ("Destination node: %u\n",header.DestNode);
793 	printf ("     Origin node: %u\n",header.OrigNode);
794 	printf ("            Cost: %u\n",header.Cost);
795 	printf ("      Origin net: %u\n",header.OrigNet);
796 	printf (" Destination net: %u\n",header.DestNet);
797 	printf ("        Reply-to: %u\n",header.ReplyTo);
798 	printf ("      Attributes: %u\n",header.Attribute);
799 	printf ("       NextReply: %u\n",header.NextReply);
800 	printf ("    Rest of text: \n");
801 	first=((char *) buffer) + header.get_filesize();
802 	while ((point=strchr (first,'\r'))!=NULL && count<8)
803 	{
804 		if (first+75<point)
805 			point=first+75;
806 		*point=0;
807 		printf ("%s\r\n",first);
808 		first=point+1;
809 		count++;
810 	}
811 	free (buffer);
812 	fclose (fnet);
813 	getch ();
814 	GetVisibleInfo (path,&extra,NULL,NULL);
815         //clrscr ();
816 	printf ("Information as returned by GetVisibleInfo ().\n");
817 	printf ("    Sender: %s (%u:%u/%u.%u)\n",extra.FromUserName,
818 	extra.Origin.Zone,extra.Origin.Net,extra.Origin.Node,extra.Origin.Point);
819 	printf ("  Receiver: %s (%u:%u/%u.%u)\n",extra.ToUserName,
820 	extra.Destination.Zone,extra.Destination.Net,extra.Destination.Node,extra.Destination.Point);
821 	printf ("   Subject: %s\n",extra.Subject);
822 	printf ("Original date & time: %s  ",extra.OrigDateTime);
823 	if (extra.DateParsed)
824 	{
825 		printf ("Parsed: %02u-%02u-%04u  %02u:%02u:%02u",
826 		extra.date.day,extra.date.month,extra.date.year,
827 		extra.time.hour,extra.time.minute,extra.time.second);
828 	}
829 	printf ("\nAttributes: ");
830 	printf ("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s",
831 		S_Private(extra.attrib)?"Pvt":"   ",
832 		S_Crash(extra.attrib)?"Cra":"   ",
833 		S_Recd(extra.attrib)?"Rev":"   ",
834 		S_Sent(extra.attrib)?"Snt":"   ",
835 		S_FileAttached(extra.attrib)?"Att":"   ",
836 		S_InTransit(extra.attrib)?"Trs":"   ",
837 		S_Orphan(extra.attrib)?"Orp":"   ",
838 		S_KillSent(extra.attrib)?"K/S":"   ",
839 		S_Local(extra.attrib)?"Loc":"   ",
840 		S_Hold(extra.attrib)?"Hld":"   ",
841 		S_Unused(extra.attrib)?"Dir":"   ",
842 		S_FileRequest(extra.attrib)?"Frq":"   ",
843 		S_ReturnReceiptRequest(extra.attrib)?"RRQ":"   ",
844 		S_IsReturnReceipt(extra.attrib)?"ReR":"   ",
845 		S_AuditRequest(extra.attrib)?"Aud":"   ",
846 		S_FileUpdateReq(extra.attrib)?"UpR":"   ");
847 	getch ();
848 	return (SUCCESS);
849 }
850 
851 // DoQQQPack() determines whether a mail should be packed into the
852 // Binkley outbound or into a .QQQ files. A message only qualifies for
853 // being packed into a QQQ file if:
854 // - FASTECHOPACK has been specified in the cfroute cfg
855 // - FECFONIG     has been specified in the cfroute cfg
856 // - the mail is not crash, direct, immediate or hold, or has a file
857 //   attached
858 // - the destination system is listed in fastecho.cfg
859 //   (which can be seen from the fact if PasswordHandler knows this
860 //   system or not).
861 
DoQQQPack(S_FQAddress via,int AttribPack)862 int DoQQQPack(S_FQAddress via, int AttribPack)
863 {
864         if ((FastechoPack == 2)  ||    /* Pack anything as QQQ */
865             (FastechoPack == 1  &&     /* Pack mail to listed links only */
866              PasswordHandler.GetPassword(via, (char *)NULL) == SUCCESS &&
867                                        /* destination system is a link */
868              AttribPack == TT_NORMAL))
869                                        /* no "priority" flag is set */
870                 return 1;
871         return 0;
872 }
873 
FindUniqueQQQ(char * storage)874 void FindUniqueQQQ (char *storage)
875 {
876 	char rname[9],temp[80];
877 	int c,r;
878 	FILE *o;
879 	for (;;) /* Keep trying until we succeed */
880 	{
881 		for (c=0;c<8;c++)
882 		{
883 			r=rand()%16;
884 			if (r>=10)
885 				rname[c]=r+'A'-10;
886 			else
887 				rname[c]=r+'0';
888 		}
889 		rname[8]=0;
890 		sprintf (storage,"%s"DIRSEPS"%s.",QQQOutboundDirectory,rname);
891 		sprintf (temp,"%sQQQ",storage);
892                 adaptcase(temp);
893 		o=fopen (temp,"rb");
894 		if (o!=NULL)
895 			fclose (o);
896 		else /* Failed to open it - finally... */
897 			return;
898 	}
899 }
900 
FindPKTPath(S_FQAddress destination,char * storage)901 int FindPKTPath (S_FQAddress destination,char *storage)
902 {
903 	S_FQAddress work;
904 	int UseDefaultOutbound;
905 	*storage=0;
906 	char Domain[256],temp[256],*lookup;
907 	int count;
908 	if (AddressHandler.GetMain (&work)!=SUCCESS)
909 		return (EAD_NOMAIN);
910 	// If there isn't domain information, we use zones ONLY
911 	if (work.Domain[0]==0 || destination.Domain[0]==0)
912 		if (destination.Zone==work.Zone)
913 			UseDefaultOutbound=1;
914 		else
915 			UseDefaultOutbound=0;
916 	else
917 		// Use specified domain, if there is one
918 		if (cistrcmp (work.Domain,destination.Domain)==0 &&
919 			destination.Zone==work.Zone)
920 			UseDefaultOutbound=1;
921 		else
922 			UseDefaultOutbound=0;
923 	if (UseDefaultOutbound)
924 		sprintf (temp,"%s"DIRSEPS,OutboundDirectory);
925 	else
926 	{
927 		if (destination.Domain[0]!=0)
928 			strcpy (Domain,destination.Domain);
929 		else
930 		{
931 			Domain[0]=0;
932 			for (count=1;count<=AddressHandler.GetAKACount();count++)
933 			{
934 				AddressHandler.GetAKA (&work,count);
935 				if (destination.Zone==work.Zone)
936 				{
937 					strcpy (Domain,work.Domain);
938 					break;
939 				}
940 			}
941 		}
942 		// If no domain, simply add the zone number to the outbound
943 		if (Domain[0]==0 || NoDomainDir)
944 			sprintf (temp,"%s.%03X"DIRSEPS,OutboundDirectory,destination.Zone);
945 		else
946 		{
947 			lookup=strchr (Domain,'.');
948 			if (lookup!=NULL)
949 				*lookup=0;
950 			strcpy (temp,OutboundDirectory);
951 			lookup=temp+strlen (temp)-1;
952 			while (*lookup!=DIRSEPC)
953 				lookup--;
954 			sprintf (lookup+1,
955                                  "%s.%03X"DIRSEPS,Domain,destination.Zone);
956 		}
957 	}
958 	// OK, here we have the path - add the node
959 	sprintf (storage,"%s%04X%04X.",temp,destination.Net,destination.Node);
960 	// is it a point?
961 	if (destination.Point!=0)
962 	{
963 		sprintf (temp,"PNT"DIRSEPS"%08X.",destination.Point);
964 		strcat (storage,temp);
965 	}
966 	return SUCCESS;
967 }
968 
BufferHeader(S_Visu * header,C_StringList * SL_Header)969 void BufferHeader (S_Visu *header, C_StringList *SL_Header)
970 {
971 	char buffer[256];
972 	sprintf (buffer,"From: %-40s (%u:%u/%u.%u)\n",header->FromUserName,
973 		header->Origin.Zone,header->Origin.Net,header->Origin.Node,
974 		header->Origin.Point);
975 	SL_Header->AddString (buffer);
976 	sprintf (buffer,"  To: %-40s (%u:%u/%u.%u)\n",header->ToUserName,
977 		header->Destination.Zone,header->Destination.Net,
978 		header->Destination.Node,header->Destination.Point);
979 	SL_Header->AddString (buffer);
980 	sprintf (buffer,"Subj: %s\n",header->Subject);
981 	SL_Header->AddString (buffer);
982 	if (header->DateParsed)
983 	{
984 		sprintf (buffer,"Date: %02hu-%02hu-%04hu  %02hu:%02hu:%02hu - %ld days ago",
985 			header->date.day,header->date.month,header->date.year,
986 			header->time.hour,header->time.minute,header->time.second,
987 			(long) GetToday()-GetJulianDate (header->date.day,header->date.month,header->date.year));
988 	}
989 	else
990 		sprintf (buffer,"Date: %s (non-standard)",header->OrigDateTime);
991 	sprintf (buffer+strlen (buffer)," - Body size: %lu",header->MessageSize);
992 	if (header->Encrypted)
993 		strcat (buffer," - Encrypted");
994 	strcat (buffer,"\n");
995 	SL_Header->AddString (buffer);
996 	sprintf (buffer,"Attr: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
997 		S_Private(header->attrib)?"Pvt ":"", // Doesn't mind for routing
998 		S_Crash(header->attrib)?"Cra ":"", // Direct
999 		S_Recd(header->attrib)?"Rev ":"", // D.M.F.R.
1000 		S_Sent(header->attrib)?"Snt ":"", // Sent - do not touch
1001 		S_FileAttached(header->attrib)?"Att ":"",//D.M.F.R.
1002 		S_InTransit(header->attrib)?"Trs ":"", //D.M.F.R.
1003 		S_Orphan(header->attrib)?"Orp ":"", //D.M.F.R.
1004 		S_KillSent(header->attrib)?"K/S ":"",//D.M.F.R.
1005 		S_Local(header->attrib)?"Loc ":"", //D.M.F.R.
1006 		S_Hold(header->attrib)?"Hld ":"", // Direct
1007 		S_Unused(header->attrib)?"Dir ":"", // D.M.F.R.
1008 		S_FileRequest(header->attrib)?"Frq ":"", // Direct
1009 		S_ReturnReceiptRequest(header->attrib)?"RRQ ":"", // D.M.F.R.
1010 		S_IsReturnReceipt(header->attrib)?"ReR ":"", // D.M.F.R.
1011 		S_AuditRequest(header->attrib)?"Aud ":"", // D.M.F.R.
1012 		S_FileUpdateReq(header->attrib)?"UpR ":"", // Direct
1013 
1014 		S_ArchiveSent(header->attrib2)?"A/S ":"",
1015 		S_KillFileSent(header->attrib2)?"KFS ":"",
1016 		(S_Direct(header->attrib2)
1017                  && (!(S_Unused(header->attrib)))) ? "Dir ":"",
1018 		S_Zonegate(header->attrib2)?"Zon ":"",
1019 		S_Hub(header->attrib2)?"Hub ":"",
1020 		S_Immediate(header->attrib2)?"Imm ":"",
1021 		S_XMA(header->attrib2)?"XMA ":"",
1022 		S_Lock(header->attrib2)?"Lok ":"",
1023 		S_Truncate(header->attrib2)?"Tru ":"",
1024 		S_HiRes(header->attrib2)?"HiR ":"",
1025 		S_CoverLetter(header->attrib2)?"CvL ":"",
1026 		S_Signature(header->attrib2)?"Sig ":"",
1027 		S_LetterHead(header->attrib2)?"LeH ":"",
1028 		S_Fax(header->attrib2)?"Fax ":"",
1029 		S_ForcePickup(header->attrib2)?"FPU ":"");
1030 	SL_Header->AddString (buffer);
1031 }
1032 
GetSendType(S_Visu * header,C_StringList * SL_Routeto)1033 int GetSendType (S_Visu *header,C_StringList *SL_Routeto)
1034 {
1035 	int SendType;
1036 	char buffer[256];
1037 	SendType=ST_ROUTE;
1038 	if (AddressHandler.IsLocalAKA (header->Destination))
1039 	{
1040 		SL_Routeto->AddString (" Via: None (addressed to this system)\n");
1041 		SendType=ST_NOTOUCH;
1042 	}
1043 	else
1044 		// Determine the kind of routing
1045 		// Conditions that will force the message NOT to be processed
1046 	{
1047 		if (S_Crash(header->attrib) ||
1048                     S_Hold(header->attrib) ||
1049                     S_FileRequest(header->attrib) ||
1050                     S_FileUpdateReq(header->attrib) ||
1051 		    S_Direct(header->attrib2)==1 ||
1052                     S_Immediate(header->attrib2)==1 ||
1053                     S_ForcePickup(header->attrib2)==1)
1054 		{
1055 			SendType=ST_DIRECT;
1056 			if (header->Destination.Point!=0 && (RouteBossDirect==1 && (S_Crash(header->attrib) ||
1057 			S_Immediate(header->attrib2)==1 || S_Direct(header->attrib2)==1 &&
1058 			(S_FileRequest(header->attrib)==0 && S_FileUpdateReq(header->attrib)==0))))
1059 				SendType=ST_BOSS;
1060 			if (header->Destination.Point!=0 && (RouteBossHold==1 && (S_Hold(header->attrib) ||
1061 			S_ForcePickup(header->attrib2)==1)))
1062 				SendType=ST_BOSS;
1063                         if (SendType == ST_BOSS)
1064                         {
1065                                 S_FQAddress ShouldGo;
1066                                 memcpy (&ShouldGo,&header->Destination,
1067                                         sizeof (S_FQAddress));
1068           			ShouldGo.Point=0;
1069                                 if (AddressHandler.IsLocalAKA(ShouldGo))
1070                                 {
1071                                         SendType = ST_DIRECT;
1072                                         // Mail that is destined to a
1073                                         // point of our own is always
1074                                         // sent direct
1075                                 }
1076                         }
1077 
1078 		}
1079 		// Handle hostgated messages
1080 		if (S_Hub(header->attrib2)==1)
1081 		{
1082 			if (AddressHandler.OurNet (header->Destination.Zone,
1083                                                    header->Destination.Net)==
1084                             EAD_FOREIGN)
1085 			{
1086 				sprintf (buffer,"(Hostgated to %u:%u/%u.%u)\n",
1087 					 header->TransitAddr.Zone,
1088                                          header->TransitAddr.Net,
1089                                          header->TransitAddr.Node,
1090                                          header->TransitAddr.Point);
1091                                          SL_Routeto->AddString (buffer);
1092 			}
1093 		}
1094 		// Handle zonegated messages
1095 		if (S_Zonegate(header->attrib2)==1)
1096 		{
1097 			if (AddressHandler.OurZone (header->Destination.Zone)==EAD_FOREIGN)
1098 			{ // To a foreign zone...
1099 				// Example: From 2:* to 1:* becomes 2:2/1.0.
1100 				sprintf (buffer,"(Zonegated to %u:%u/%u.%u)\n",
1101 					header->TransitAddr.Zone,header->TransitAddr.Net,
1102 					header->TransitAddr.Node,header->TransitAddr.Point);
1103 				SL_Routeto->AddString (buffer);
1104 			}
1105 		}
1106 	}
1107 	return (SendType);
1108 }
1109 
DetermineRouteToSystem(S_Visu * header,int SendType,C_StringList * SL_Routeto,S_FQAddress * ShouldGo,int * AttribPack,char * ext,char * extattach)1110 int DetermineRouteToSystem (S_Visu *header,int SendType,
1111 	C_StringList *SL_Routeto,S_FQAddress *ShouldGo,int *AttribPack,
1112 	char *ext,char *extattach)
1113 {
1114 	int GotSystem=0;
1115 	char buffer[256];
1116 	switch (SendType)
1117 	{
1118 		case ST_NOTOUCH:
1119 			SL_Routeto->AddString ("Attributes caused message not to be processed.\n");
1120 			break;
1121 		case ST_ROUTE:
1122 			if (RouteHandler.FindPackSystem (header->TransitAddr,
1123 				header->Origin,S_FileAttached(header->attrib),
1124 				header->Encrypted,ShouldGo,AttribPack))
1125 			{
1126 				sprintf (buffer," Via: %u:%u/%u.%u as ",
1127 				ShouldGo->Zone,ShouldGo->Net,ShouldGo->Node,ShouldGo->Point);
1128 				GotSystem=1;
1129 			}
1130 			else
1131 			{
1132 				SL_Routeto->AddString (" Via: None (no route defined for this message).\n");
1133 				SendType=ST_NOTOUCH;
1134 				GotSystem=0;
1135 			}
1136 			break;
1137 		case ST_DIRECT:
1138 			memcpy (ShouldGo,&header->Destination,sizeof (S_FQAddress));
1139 			*AttribPack=TT_NORMAL;
1140 			sprintf (buffer," Via: Direct to %u:%u/%u.%u as ",
1141 				ShouldGo->Zone,ShouldGo->Net,ShouldGo->Node,ShouldGo->Point);
1142 				GotSystem=1;
1143 			break;
1144 		case ST_BOSS:
1145 			memcpy (ShouldGo,&header->Destination,sizeof (S_FQAddress));
1146 			ShouldGo->Point=0;
1147 			*AttribPack=TT_NORMAL;
1148 			sprintf (buffer," Via: Boss %u:%u/%u.%u as ",
1149 				ShouldGo->Zone,ShouldGo->Net,ShouldGo->Node,ShouldGo->Point);
1150 				GotSystem=1;
1151 			break;
1152 	}
1153 	// The final attribute may be different that the one
1154 	// on the route-to sentences
1155 	if (GotSystem==1)
1156 	{
1157 		if (S_Hold(header->attrib) && S_Crash(header->attrib))
1158 			*AttribPack=TT_DIR;
1159 		else
1160 		if (S_Hold(header->attrib))
1161 			*AttribPack=TT_HOLD;
1162 		else
1163 		if (S_Crash(header->attrib))
1164 			*AttribPack=TT_CRASH;
1165 		else
1166 		if (S_Direct(header->attrib2)==1)
1167 			*AttribPack=TT_DIR;
1168                 else
1169                 if (S_Immediate(header->attrib2)==1)
1170                         *AttribPack=TT_IMMEDIATE;
1171 		switch (*AttribPack)
1172 		{
1173 			case TT_NORMAL:
1174 				strcat (buffer,"NORMAL (OUT)");
1175 				strcpy (ext,"OUT");
1176 				strcpy (extattach,"FLO");
1177 				break;
1178 			case TT_HOLD:
1179 				strcat (buffer,"HOLD (HUT)");
1180 				strcpy (ext,"HUT");
1181 				strcpy (extattach,"HLO");
1182 				break;
1183 			case TT_CRASH:
1184 				strcat (buffer,"CRASH (CUT)");
1185 				strcpy (ext,"CUT");
1186 				strcpy (extattach,"CLO");
1187 				break;
1188 			case TT_DIR:
1189 				strcat (buffer,"DIRECT (DUT)");
1190 				strcpy (ext,"DUT");
1191 				strcpy (extattach,"DLO");
1192 				break;
1193                         case TT_IMMEDIATE:
1194                                 strcat (buffer,"IMMEDIATE (IUT)");
1195                                 strcpy (ext,"IUT");
1196                                 strcpy (extattach,"ILO");
1197                                 break;
1198 			default:
1199 				strcat (buffer,"*** corrupted attribute ***");
1200 				break;
1201 		} // switch (Attribpack);
1202 		strcat (buffer,".\n");
1203 		SL_Routeto->AddString (buffer);
1204 	} // if (GotSystem);
1205 	return (GotSystem);
1206 }
1207 
CheckAndCreateSem(char * path)1208 int CheckAndCreateSem (char *path)
1209 {
1210 	char *sav;
1211         FILE *f;
1212 #ifdef OS_2
1213 	FILEFINDBUF3 ffblk;
1214 	ULONG ulFileCount=1;
1215 	HDIR hdir=HDIR_SYSTEM;
1216 #else
1217 	struct ffblk ffblk;
1218 #endif
1219 	int result;
1220 	sav=(char *) malloc (strlen (path)+5);
1221 	strcpy (sav,path);
1222 	strcat (sav,"BSY");
1223         result = adaptcase(sav);
1224         if (!result) /* BSY file does not exist - create it! */
1225         {
1226                 f = fopen(sav, "wt");
1227                 if (f) fclose(f);
1228         }
1229 	free (sav);
1230 	return (result);
1231 }
1232 
ReleaseSem(char * path)1233 void ReleaseSem (char *path)
1234 {
1235 	char *sav;
1236         FILE *f;
1237 
1238 	int result;
1239 	sav=(char *) malloc (strlen (path)+5);
1240 	strcpy (sav,path);
1241 	strcat (sav,"BSY");
1242         result = adaptcase(sav);
1243         if (result) /* BSY file does  exist - delete it! */
1244                 remove(sav);
1245 	free (sav);
1246 }
1247 
1248 
CreatePathLines(C_StringList * source,C_StringList * target)1249 void CreatePathLines (C_StringList *source,C_StringList *target)
1250 {
1251 	char work[80];
1252 	int c;
1253 	if (PathLogStyle==0)
1254 		return;
1255         if (PathLogStyle==1)
1256 	{
1257 		strcpy (work,"Path: ");
1258 		for (c=0;c<source->GetStringCount();c++)
1259 		{
1260 			strcat (work,source->GetString (c));
1261 			if (c<source->GetStringCount()-1)
1262 				strcat (work," -> ");
1263 			if (strlen (work)>60)
1264 			{
1265 				strcat (work,"\n");
1266 				target->AddString (work);
1267 				strcpy (work,"Path: ");
1268 			}
1269 		}
1270 		strcat (work,"\n");
1271 		if (strlen (work)>7) /* 6=strlen ("Path: \n") */
1272 			target->AddString (work);
1273 		return;
1274 	}
1275 }
1276 
PostAnalysis(S_Visu * extra,struct S_Control * x)1277 int PostAnalysis (S_Visu *extra,struct S_Control *x)
1278 {
1279 	int count;
1280         DateTime dt;
1281 	if (RouteHandler.NoPack (extra->Destination,
1282                                  extra->Origin,S_FileAttached(extra->attrib),
1283                                  extra->Encrypted))
1284 		return RET_SUCCESS;
1285 	// If the message has any of the following flags, it is skipped
1286 	// without further check.
1287         if (S_Sent(extra->attrib)==1 ||
1288             (
1289                     (S_XMA(extra->attrib2)==1 ||
1290                      S_Lock(extra->attrib2)==1 ||
1291                      S_HiRes(extra->attrib2)==1 ||
1292                      S_HiRes(extra->attrib2)==1 ||
1293                      S_CoverLetter(extra->attrib2)==1 ||
1294                      S_CoverLetter(extra->attrib2)==1 ||
1295                      S_Signature(extra->attrib2)==1 ||
1296                      S_LetterHead(extra->attrib2)==1 ||
1297                      S_Fax(extra->attrib2)==1)
1298                     &&!IgnoreUnknownAttribs)
1299                 )
1300 	{
1301 #ifdef DEBUG
1302 		printf ("Skipped because of attributes (%u %u %d).\n",
1303                         extra->attrib, extra->attrib2, IgnoreUnknownAttribs);
1304 #endif
1305 		return RET_SUCCESS;
1306 	}
1307 	BufferHeader (extra,&x->SL_Header);
1308 	x->SendType=GetSendType (extra,&x->SL_Routeto);
1309 	if (x->SendType==ST_NOTOUCH)
1310 		return RET_SUCCESS;
1311 	x->GotSystem=DetermineRouteToSystem (extra,x->SendType,&x->SL_Routeto,
1312                                              &x->ShouldGo,&x->AttribPack,
1313                                              x->ext,x->extattach);
1314 	// At this point: The message has to be processed, and
1315 	// we have the header and route-to information. We log
1316 	// them.
1317 	Log.WriteOnLog ("------------------------------------------------------------------------------\n");
1318 
1319         printf ("Message: %lu, format: ",extra->MsgNumber);
1320         switch (extra->formattype) {
1321                 case formatMSG:         printf ("MSG.\n");
1322                                         break;
1323                 case formatSQUISH:      printf ("SQUISH.\n");
1324                                         break;
1325                 case formatJAM:         printf ("JAM.\n");
1326                                         break;
1327                 default:                printf ("unknown.\n");
1328         }
1329 
1330 	for (count=0;count<x->SL_Header.GetStringCount();count++)
1331 		Log.WriteOnLog ("%s",x->SL_Header.GetString (count));
1332 	CreatePathLines (&x->SL_Path,&x->SL_ToWrite);
1333 	for (count=0;count<x->SL_ToWrite.GetStringCount();count++)
1334 		Log.WriteOnLog ("%s",x->SL_ToWrite.GetString (count));
1335 	for (count=0;count<x->SL_Routeto.GetStringCount();count++)
1336 		Log.WriteOnLog ("%s",x->SL_Routeto.GetString (count));
1337 	if (extra->DetectedLoop==1)
1338 		Log.WriteOnLog ("Warning: %s already processed here - possible loop.\n",x->define);
1339 	if (extra->DetectedLoop==1 || RecordViaLines)
1340 	{
1341 		for (count=0;count<x->SL_Via.GetStringCount();count++)
1342 			Log.WriteOnLog ("%s\n",x->SL_Via.GetString (count));
1343 	}
1344         if (extra->DetectedLoop && NoLoopRoute)
1345         {
1346                 Log.WriteOnLog("Mail is looping - we do not route it.\n");
1347                 Log.WriteOnLog("\n");
1348                 printf ("Mail loop detected.\n");
1349                 return (RET_SUCCESS);
1350         }
1351 	if (!x->GotSystem)
1352 	{
1353 #ifdef DEBUG
1354 		printf ("No path.\n");
1355 #endif
1356 		Log.WriteOnLog ("\n");
1357 		return (RET_SUCCESS);
1358 	}
1359 #ifdef DEBUG
1360 	printf ("Found a path.\n");
1361 #endif
1362         if (DoQQQPack(x->ShouldGo, x->AttribPack))
1363         {
1364                 x->is_qqq = 1;
1365                 strcpy(x->ext, "QQQ");
1366 		FindUniqueQQQ (x->savepath);
1367         }
1368         else
1369                 FindPKTPath (x->ShouldGo,x->savepath);
1370 
1371         FindPKTPath (x->ShouldGo, x->savepathattach);
1372 
1373 	Log.WriteOnLog ("File: %s%s\n",x->savepath,x->ext);
1374         dt.getCurrentTime();
1375         Log.WriteOnLog ("Packed mail at %s %02d,%04d (%s) %02u:%02u:%02u\n",
1376                  Months[dt.month-1],dt.day,dt.year,
1377                  Days[GetDOW()],dt.hours,dt.minutes,dt.seconds);
1378 	Log.WriteOnLog ("------------------------------------------------------------------------------\n");
1379 	AddressHandler.AKAMatch (x->ShouldGo,&x->OurAKA);
1380 	printf ("%lu bytes from %hu:%hu/%hu.%hu to %hu:%hu/%hu.%hu "
1381                 "via %hu:%hu/%hu.%hu%s.\n", extra->MessageSize,
1382 		extra->Origin.Zone,extra->Origin.Net,
1383                 extra->Origin.Node,extra->Origin.Point,
1384 		extra->Destination.Zone,extra->Destination.Net,
1385 		extra->Destination.Node,extra->Destination.Point,
1386 		x->ShouldGo.Zone,x->ShouldGo.Net,
1387                 x->ShouldGo.Node,x->ShouldGo.Point,
1388 		Packet2Handler.DoesMatch (x->ShouldGo,
1389                                           x->ShouldGo,0,0)?" (Packet 2)":"");
1390 	return SUCCESS;
1391 }
1392 
touchFile(char * path)1393 void touchFile(char *path)
1394 {
1395     FILE *touch;
1396     unsigned char buffer[8];
1397     int nok = 1;
1398 
1399 #if defined(UNIX) && (defined(__FreeBSD__) || defined(__NetBSD__))
1400     nok=utimes(path, NULL);
1401 #endif
1402 #if defined(UNIX) || defined(__BORLANDC__)
1403     nok=utime(path, NULL);
1404 #endif
1405 
1406     if (nok)
1407     {
1408                                 // try conventional method
1409         touch=fopen (path,"r+b");
1410         if (!touch)
1411             touch=fopen (path, "wb");
1412         if (touch)
1413         {
1414             fseek (touch,0,SEEK_SET);
1415             if (fread (buffer,1,8,touch)==8)
1416             {
1417                 fseek (touch,0,SEEK_SET);
1418                 fwrite (buffer,1,8,touch);
1419             }
1420             fclose (touch);
1421         }
1422     }
1423 }
1424 
AnalyzeNet(char * path)1425 int AnalyzeNet (char *path)
1426 {
1427         S_Visu extra;
1428 	struct S_Control x;
1429 	char buffer[256];
1430 	x.GotSystem=0; x.is_qqq = 0;
1431         adaptcase(path);
1432 	strcpy (x.define,path);
1433 	if (GetVisibleInfo (path,&extra,&x.SL_Via,&x.SL_Path)!=SUCCESS)
1434 		return FATAL;
1435 	if (PostAnalysis (&extra,&x)==RET_SUCCESS)
1436 		return SUCCESS;
1437 	if (IgnoreBSY==0 && CheckAndCreateSem (x.savepath))
1438 	{
1439 		printf ("(System is now busy - message not exported)\n");
1440 		Log.WriteOnLog ("This message was not exported because"
1441                                 " the waypoint was busy.\n\n");
1442 		// Touch file so it is not skipped in the next run
1443 		// because of lastrun.cfr
1444 
1445                 touchFile(path);
1446 		return (ENH_DELAYED);
1447 	}
1448 
1449 	if (MSGToPKT (path,x.savepath,x.ext,x.ShouldGo,x.OurAKA,
1450                       extra.Destination,
1451                       Packet2Handler.DoesMatch(x.ShouldGo,x.ShouldGo,0,0), x.is_qqq)
1452             ==ECONV_OPENFAILOUT)
1453 	{
1454 		Log.WriteOnLog ("Warning: Failed to open/create PKT "
1455                                 "(%s).\n\n",x.savepath);
1456                 if (IgnoreBSY == 0)
1457                         ReleaseSem (x.savepath);
1458 		return (SUCCESS);
1459         }
1460 
1461 	// Process file-attaches and file-requests
1462 	if (S_FileAttached(extra.attrib))
1463 	{
1464 		if (SubjectToFile(extra.Subject,x.savepathattach,x.extattach,
1465                                   S_Truncate(extra.attrib2),
1466                                   S_KillFileSent(extra.attrib2) ||
1467                                     KillInTransitFiles)!=SUCCESS)
1468 			Log.WriteOnLog ("Warning: Failed to update "
1469                                         "fileattach queue.\n");
1470 	}
1471         if (S_FileRequest(extra.attrib))
1472 	{
1473 		strcpy (x.extattach,"REQ");
1474 		if (SubjectToFile (extra.Subject,x.savepathattach,
1475                                    x.extattach,0,0)!=SUCCESS)
1476 			Log.WriteOnLog ("Warning: Failed to update"
1477                                         " filerequest queue.\n");
1478 	}
1479 	if (S_KillSent(extra.attrib) ||
1480             (S_InTransit(extra.attrib) && KillInTransit))
1481 	{
1482 		if (remove (path))
1483 			Log.WriteOnLog ("Warning: Unable to delete %s.\n",
1484                                         x.define);
1485 	}
1486 	else
1487 	{
1488 		if (FlagAsSent (path)!=SUCCESS)
1489 			Log.WriteOnLog ("Warning: Can't flag %s "
1490                                         "as sent.\n",x.define);
1491 	}
1492 	Log.WriteOnLog ("\n");
1493 	if (IgnoreBSY==0)
1494                 ReleaseSem (x.savepath);
1495 	return (ENH_PROCESSED);
1496 }
1497