1 // Provide some basic string handling
2 #include <ctype.h>
3 #if !defined(OS_2) && !defined(UNIX)
4 #include <dos.h>
5 #else
6 // #include <direct.h>
7 #endif
8 
9 #ifdef UNIX
10 #include <sys/stat.h>
11 #if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(_AIX) && !defined(__GLIBC__) && !defined(mkdir)
12 #define mkdir __mkdir
13 #endif
14 #else
15 #include <io.h>
16 #endif
17 
18 #ifdef EMX
19 #define S_IRWXU 0
20 #define S_IRWXG 0
21 #endif
22 
23 #include "structs.hpp"
24 
25 #ifndef OS_2
26 typedef unsigned long ULONG;
27 typedef short SHORT;
28 typedef unsigned short USHORT;
29 
30 
31 #ifdef UNIX
32 #include <time.h>
getCurrentTime(void)33 void DateTime::getCurrentTime (void)
34 {
35         time_t t;
36         struct tm *ltm;
37 
38         time(&t);
39         ltm = localtime(&t);
40 
41         hours   = ltm->tm_hour;
42         minutes = ltm->tm_min;
43         seconds = ltm->tm_sec;
44         day     = ltm->tm_mday;
45         month   = ltm->tm_mon + 1;
46         year    = ltm->tm_year + 1900;
47 }
48 #else
getCurrentTime(void)49 void DateTime::getCurrentTime (void)
50 {
51         struct date d;
52 	struct time t;
53 
54         getdate (&d);
55 	gettime (&t);
56 	hours=t.ti_hour;
57 	minutes=t.ti_min;
58 	seconds=t.ti_sec;
59 	day=d.da_day;
60 	month=d.da_mon;
61 	year=d.da_year;
62 }
63 #endif
64 #else
65                                 // OS/2 routine
getCurrentTime(void)66 void DateTime::getCurrentTime(void)
67 {
68     DATETIME dt;
69     DosGetDateTime(&dt);
70     hours=dt.hours;
71     minutes=dt.minutes;
72     seconds=dt.seconds;
73     day=dt.day;
74     month=dt.month;
75     year=dt.year;
76 }
77 #endif
78 
cistrcmp(char * c1,char * c2)79 int cistrcmp (char *c1,char *c2)
80 {
81 		char *s1,*s2;
82         s1=c1; s2=c2;
83         while (*s1 || *s2)
84         {
85 				if (toupper (*s1)==toupper (*s2))
86                 {
87                         s1++;
88                         s2++;
89                 }
90                 else
91                         return (toupper (*s1)-toupper (*s2));
92         }
93         return 0;
94 }
95 
96 // Copy first token from string to token and strip it
GetAndStripToken(char * string,char * token)97 int GetAndStripToken (char *string, char *token)
98 {
99 	char *search;
100 	if (*string==0)
101 		return SH_ZERO;
102 	if (string[0]=='"')
103 	{
104 		strcpy (string,string+1); // Strip "
105 		search=strchr (string,'"');
106 	}
107 	else
108 		search=strchr (string,' ');
109 	if (search!=NULL)
110 		*search=0;
111 	strcpy (token,string);
112 	if (search!=NULL)
113 	{
114 		strcpy (string,search+1);
115 		while (*string==' ')
116 			strcpy (string,string+1);
117 	}
118 	else
119 		*string=0;
120 	return SUCCESS;
121 }
122 
123 #if 0
124 int IsCommand (int TokenType)
125 {
126 	switch (TokenType)
127 	{
128 		case TT_MAIN:
129 		case TT_AKA:
130 		case TT_NETMAILDIR:
131                 case TT_NETSQUISH:
132                 case TT_NETJAM:
133 		case TT_OUTBOUND:
134                 case TT_QQQOUTBOUND:
135 		case TT_LOGFILENAME:
136 		case TT_TOPDOWN:
137 		case TT_UNKNOWN:
138 		case TT_ROUTETO:
139 		case TT_DIRECT:
140 		case TT_ROUTEMAIL:
141 		case TT_ROUTEFILES:
142 		case TT_DIRECTMAIL:
143 		case TT_DIRECTFILES:
144 		case TT_NOROUTE:
145 		case TT_NOROUTEMAIL:
146 		case TT_NOROUTEFILES:
147 		case TT_PACKET2:
148 		case TT_PASSWORD:
149 		case TT_INCLUDE:
150                 case TT_INBOUND:
151 			return 1;
152 		default:
153 			return 0;
154 	}
155 }
156 
157 #endif
158 
159 struct S_Codes
160 CodeTable[]={               {"OUTBOUND",TT_OUTBOUND,NULL,ProcParOutboundDir,1,PT_COMMAND},
161                             {"QQQOUTBOUND", TT_QQQOUTBOUND, NULL, ProcParQQQOutboundDir, 1, PT_COMMAND},
162                             {"NETMAIL",TT_NETMAILDIR,NULL,ProcParNetmail,1,PT_COMMAND},
163 #ifdef SQUISHCFS
164                             {"NETSQUISH",TT_NETSQUISH,NULL,ProcParNetSquish,1,PT_COMMAND},
165                             {"NETJAM",TT_NETJAM,NULL,ProcParNetJam,1,PT_COMMAND},
166 #endif
167                             {"LOG",TT_LOGFILENAME,NULL,ProcParLogFilename,1,PT_COMMAND},
168 			    {"RECODE",TT_RECODEFILENAME,NULL,ProcParRecode,1,PT_COMMAND},
169                             {"PASSWORD",TT_PASSWORD,InitComPassword,ProcParPassword,1,PT_COMMAND},
170                             {"INBOUND",TT_INBOUND,NULL,ProcParInbound,1,PT_COMMAND},
171                             {"LOGPATH",TT_LOGPATH,InitComLogpath,NULL,0,PT_COMMAND},
172                             {"INCLUDE",TT_INCLUDE,NULL,ProcParInclude,1,PT_COMMAND},
173                             {"DEFINE",TT_DEFINE,NULL,ProcParDefine,1,PT_COMMAND},
174                             {"ENDDEFINE",TT_ENDDEFINE,InitComEndDefine,NULL,0,PT_COMMAND},
175                             {"CHECKFILE",TT_CHECKFILE,NULL,ProcParCheckFile,1,PT_COMMAND},
176                             {"TOPDOWN",TT_TOPDOWN,InitComTopdown,NULL,0,PT_COMMAND},
177                             {"FECONFIG",TT_FECONFIG,InitComFEConfig,ProcParFEConfig,0,PT_COMMAND},
178                             {"ROUTETO",TT_ROUTETO,InitComRouteTo,ProcParRoute,0,PT_COMMAND},
179                             {"ROUTE",TT_ROUTETO,InitComRouteTo,ProcParRoute,0,PT_COMMAND},
180                             {"SEND",TT_ROUTETO,InitComRouteTo,ProcParRoute,0,PT_COMMAND},
181                             {"ROUTEMAIL",TT_ROUTEMAIL,InitComRouteMail,ProcParRoute,0,PT_COMMAND},
182                             {"PRODUCTINFO",TT_PRODUCTINFO,InitComProductInfo,ProcParProductInfo,1,PT_COMMAND},
183                             {"ROUTEFILES",TT_ROUTEFILES,InitComRouteFiles,ProcParRoute,0,PT_COMMAND},
184                             {"DIRECT",TT_DIRECT,InitComDirect,ProcParRoute,0,PT_COMMAND},
185                             {"DIRECTTO",TT_DIRECT,InitComDirect,ProcParRoute,0,PT_COMMAND},
186                             {"DIRECTMAIL",TT_DIRECTMAIL,InitComDirectMail,ProcParRoute,0,PT_COMMAND},
187                             {"DIRECTFILES",TT_DIRECTFILES,InitComDirectFiles,ProcParRoute,0,PT_COMMAND},
188                             {"NOROUTE",TT_NOROUTE,InitComNoroute,ProcParRoute,0,PT_COMMAND},
189                             {"NOROUTETO",TT_NOROUTE,InitComNoroute,ProcParRoute,0,PT_COMMAND},
190                             {"ROUTEBOSS",TT_NOROUTE,InitComNoroute,ProcParRoute,0,PT_COMMAND},
191                             {"NOROUTEMAIL",TT_NOROUTEMAIL,InitComNorouteMail,ProcParRoute,0,PT_COMMAND},
192                             {"ROUTEBOSSMAIL",TT_NOROUTEMAIL,InitComNorouteMail,ProcParRoute,0,PT_COMMAND},
193                             {"NOROUTEFILES",TT_NOROUTEFILES,InitComNorouteFiles,ProcParRoute,0,PT_COMMAND},
194                             {"ROUTEBOSSFILES",TT_NOROUTEFILES,InitComNorouteFiles,ProcParRoute,0,PT_COMMAND},
195                             {"NOPACK",TT_NOPACK,InitComNoPack,ProcParRoute,0,PT_COMMAND},
196                             {"NOPACKTO",TT_NOPACK,InitComNoPack,ProcParRoute,0,PT_COMMAND},
197                             {"NOPACKMAIL",TT_NOPACKMAIL,InitComNoPackMail,ProcParRoute,0,PT_COMMAND},
198                             {"IGNOREUNKNOWNATTRIBS",TT_IGNOREUNKNOWNATTRIBS,InitComIgnoreUnknownAttribs,NULL,0,PT_COMMAND},
199                             {"NOPACKFILES",TT_NOPACKFILES,InitComNoPackFiles,ProcParRoute,0,PT_COMMAND},
200                             {"VIABOSSHOLD",TT_VIABOSSHOLD,InitComViaBossHold,NULL,0,PT_COMMAND},
201                             {"VIABOSSDIRECT",TT_VIABOSSDIRECT,InitComViaBossDirect,NULL,0,PT_COMMAND},
202                             {"IGNOREBSY",TT_IGNOREBSY,InitComIgnoreBSY,NULL,0,PT_COMMAND},
203                             {"NODOMAINDIR",TT_NODOMAINDIR,InitComNoDomainDir,NULL,0,PT_COMMAND},
204                             {"KILLINTRANSIT",TT_KILLINTRANSIT,InitComKillInTransit,NULL,0,PT_COMMAND},
205                             {"KILLTRANSITFILES",TT_KILLTRANSITFILES,InitComKillInTransitFiles,NULL,0,PT_COMMAND},
206                             {"FASTECHOPACK",TT_FASTECHOPACK,InitComFastechoPack,ProcParFastechoPack,0,PT_COMMAND},
207                             {"NOLOOPROUTE",TT_NOLOOPROUTE,InitComNoLoopRoute,NULL,0,PT_COMMAND},
208                             {"ALL",TT_QQQALL,NULL,NULL,0,PT_QQQMODE},
209                             {"ENC",TT_ENCRYPTED,NULL,NULL,0,PT_ENC},
210                             {"NONENC",TT_NONENCRYPTED,NULL,NULL,0,PT_ENC},
211                             {"CRASH",TT_CRASH,NULL,NULL,0,PT_FLAVOUR},
212                             {"IMMEDIATE",TT_IMMEDIATE,NULL,NULL,0,PT_FLAVOUR},
213                             {"HOLD",TT_HOLD,NULL,NULL,0,PT_FLAVOUR},
214                             {"DIR",TT_DIR,NULL,NULL,0,PT_FLAVOUR},
215                             {"NORMAL",TT_NORMAL,NULL,NULL,0,PT_FLAVOUR},
216                             {"MYZONES",TT_MYZONES,NULL,NULL,0,PT_MACRO},
217                             {"MYNETS",TT_MYNETS,NULL,NULL,0,PT_MACRO},
218                             {"MYPOINTS",TT_MYPOINTS,NULL,NULL,0,PT_MACRO},
219                             {"LOCAL",TT_LOCAL,NULL,NULL,0,PT_MACRO},
220                             {"PACKET2",TT_PACKET2,InitComPacket2,ProcParPacket2,0,PT_COMMAND},
221                             {"MAIN",TT_MAIN,NULL,ProcParMain,0,PT_COMMAND},
222                             {"AKA",TT_AKA,NULL,ProcParAKA,0,PT_COMMAND},
223                             {"FROM",TT_FROM,NULL,NULL,0,PT_FROM},
224                             {"EXCEPT",TT_EXCEPT,NULL,NULL,0,PT_EXCEPT},
225                             {"ASSUMEPOINTS",TT_ASSUMEPOINTS,InitComAssumePoints,NULL,0,PT_COMMAND},
226                             {"ASSUMEWAYPOINTS",TT_ASSUMEWAYPOINTS,InitComAssumeWaypoints,NULL,0,PT_COMMAND},
227                             {"EOLENDSCOMMAND",TT_EOLENDSCOMMAND,InitComEOLEndsCommand,NULL,0,PT_COMMAND},
228                             {"PVT",TT_PVT,NULL,NULL,0,PT_ATTRIB},
229                             {"HLD",TT_HLD,NULL,NULL,0,PT_ATTRIB},
230                             {"CRA",TT_CRA,NULL,NULL,0,PT_ATTRIB},
231                             {"K/S",TT_KS,NULL,NULL,0,PT_ATTRIB},
232                             {"SNT",TT_SNT,NULL,NULL,0,PT_ATTRIB},
233                             {"RCV",TT_RCV,NULL,NULL,0,PT_ATTRIB},
234                             {"A/S",TT_AS,NULL,NULL,0,PT_ATTRIB},
235                             {"ZON",TT_ZON,NULL,NULL,0,PT_ATTRIB},
236                             {"HUB",TT_HUB,NULL,NULL,0,PT_ATTRIB},
237                             {"FIL",TT_FIL,NULL,NULL,0,PT_ATTRIB},
238                             {"FRQ",TT_FRQ,NULL,NULL,0,PT_ATTRIB},
239                             {"IMM",TT_IMM,NULL,NULL,0,PT_ATTRIB},
240                             {"XMA",TT_XMA,NULL,NULL,0,PT_ATTRIB},
241                             {"KFS",TT_KFS,NULL,NULL,0,PT_ATTRIB},
242                             {"TFS",TT_TFS,NULL,NULL,0,PT_ATTRIB},
243                             {"LOK",TT_LOK,NULL,NULL,0,PT_ATTRIB},
244                             {"RRQ",TT_RRQ,NULL,NULL,0,PT_ATTRIB},
245                             {"CFM",TT_CFM,NULL,NULL,0,PT_ATTRIB},
246                             {"HIR",TT_HIR,NULL,NULL,0,PT_ATTRIB},
247                             {"COV",TT_COV,NULL,NULL,0,PT_ATTRIB},
248                             {"SIG",TT_SIG,NULL,NULL,0,PT_ATTRIB},
249                             {"LET",TT_LET,NULL,NULL,0,PT_ATTRIB},
250                             {"FAX",TT_FAX,NULL,NULL,0,PT_ATTRIB},
251                             {"FPU",TT_FPU,NULL,NULL,0,PT_ATTRIB},
252                             {"",0,NULL,NULL,0,PT_END}
253 };
254 
255 // Get Token Info
GetTokenInfo(char * Token,struct S_Codes * storage)256 int GetTokenInfo (char *Token, struct S_Codes *storage)
257 {
258 	char *Mess,*Update;
259 	int count,canbedow;
260 	if (Token[0]==0)
261 		return SH_ZERO;
262 	count=0;
263 	Mess=(char *) malloc (strlen (Token)+1);
264 	strcpy (Mess,Token);
265 	Update=Mess;
266 	while (*Update)
267 	{
268 		*Update=toupper (*Update);
269 		Update++;
270 	}
271 	Update=Mess;
272 	while (*Update)
273 	{
274 		if (*Update=='-'|| *Update=='_')
275 			strcpy (Update,Update+1);
276 		else
277 			Update++;
278 	}
279 
280 	while (CodeTable[count].Keyword[0]!=0)
281 	{
282                 if (!cistrcmp (Mess,CodeTable[count].Keyword))
283 		{
284 			memcpy (storage,&CodeTable[count],sizeof (struct S_Codes));
285 			free (Mess);
286 			return (CodeTable[count].Group);
287 		}
288 		count++;
289 	}
290 	// Not a known keyword
291 	// Check for a day of the week spec.
292 	canbedow=1;
293 	Update=Mess;
294 	while (*Update && canbedow)
295 	{
296 		if (*Update!='M' && *Update!='T' && *Update!='W' &&
297 			*Update!='H' && *Update!='F' && *Update!='S' &&
298 			*Update!='U')
299 		{
300 			canbedow=0;
301 			break;
302 		}
303 		Update++;
304 	}
305 	if (canbedow)
306 	{
307 		free (Mess);
308 		storage->Keyword=Token;
309 		storage->Code=TT_DOW;
310 		storage->Group=PT_DOW;
311 		return False;
312 	}
313 	if (isdigit (Mess[0]) || Mess[0]=='.' || Mess[0]=='!' || Mess[0]=='*' ||
314 		Mess[0]=='?' || Mess[0]=='#')
315 	{
316 		free (Mess);
317 		storage->Keyword=Token;
318 		storage->Code=TT_ADDRESS;
319 		storage->Group=PT_ADDRESS;
320 		return (PT_ADDRESS);
321 	}
322 	// Check if it is a definition
323 	storage->Code=TT_UNKNOWN;
324 	storage->Group=PT_OTHER;
325 	return TT_UNKNOWN;
326 }
327 
328 
329 // Attempt to determine token type
GetTokenType(char * Token)330 int GetTokenType (char *Token)
331 {
332 	char *Mess,*Update;
333 	int count,canbedow;
334 	if (Token[0]==0)
335 		return SH_ZERO;
336 	// Tokens starting with a digit are most probably network addresses
337 	Mess=(char *) malloc (strlen (Token)+1);
338 	strcpy (Mess,Token);
339 	Update=Mess;
340 	while (*Update)
341 	{
342 		*Update=toupper (*Update);
343 		Update++;
344 	}
345 	Update=Mess;
346 	while (*Update)
347 	{
348 		if (*Update=='-'|| *Update=='_')
349 			strcpy (Update,Update+1);
350 		else
351 			Update++;
352 	}
353 	canbedow=1;
354 	Update=Mess;
355 	while (*Update && canbedow)
356 	{
357 		if (*Update!='M' && *Update!='T' && *Update!='W' &&
358 			*Update!='H' && *Update!='F' && *Update!='S' &&
359 			*Update!='U')
360 		{
361 			canbedow=0;
362 			break;
363 		}
364 		Update++;
365 	}
366 	if (canbedow)
367 	{
368 		free (Mess);
369 		return TT_DOW;
370 	}
371 	if (isdigit (Mess[0]) || Mess[0]=='.' || Mess[0]=='!' || Mess[0]=='*' ||
372 		Mess[0]=='?' || Mess[0]=='#')
373 	{
374 		free (Mess);
375 		return (TT_ADDRESS);
376 	}
377 	count=0;
378 	while (CodeTable[count].Keyword[0]!=0)
379 	{
380                 if (!cistrcmp (Mess,CodeTable[count].Keyword))
381 		{
382 			free (Mess);
383 			return (CodeTable[count].Code);
384 		}
385         count++;
386 	}
387 	free (Mess);
388 	return TT_UNKNOWN;
389 }
390 
GetFullQualifiedAddress(char * Saddress,struct S_FQAddress * storage,struct S_FQAddress * Main)391 int GetFullQualifiedAddress (char *Saddress, struct S_FQAddress *storage,struct S_FQAddress *Main)
392 {
393 	int NoMain;
394         size_t count,count2;
395 	char Compo[25]; // Maximum: AAAAA:BBBBB:CCCCC:DDDDD\0
396 	char *search,*first,*colon,*slash,*point;
397 	char address[80];
398 	if (strlen (Saddress)>79)
399 		return EAD_INVALID;
400 	strcpy (address,Saddress);
401 	search=strchr (address,' ');
402 	if (search)
403 		*search=0;
404 	if (Main==NULL || (Main->Zone==0xFFFF && Main->Net==0xFFFF &&
405 		Main->Node==0xFFFF && Main->Point==0xFFFF))
406 		NoMain=1;
407 	else
408 		NoMain=0;
409 	if (*address=='\0')
410 		return EAD_ZERO;
411     // First thing to do is parse the domain
412 	search=strchr (address,'@');
413 	if (search!=NULL)
414 	{
415 		strcpy (storage->Domain,search+1);
416 		*search=0;
417 	}
418 	else
419         {
420                 storage->Domain[0]=0;
421                 search=address+strlen(address)-1; /* Last char */
422                 while (search >= address &&
423                        !isdigit (*search) && *search!=':' && *search!='/' &&
424                        *search!='.')
425                         *(search--)=0;
426         }
427 	for (count=0;count<strlen (address);count++)
428 		if (!isdigit (address[count]) && address[count]!=':' &&
429 			address[count]!='/' && address[count]!='.')
430 			return EAD_INVALID;
431 	count2=0;
432 	for (count=0;count<strlen (address);count++)
433 		if (address[count]==':')
434 			count2++;
435 	if (count2>1)
436 		return EAD_INVALID;
437 	count2=0;
438 	for (count=0;count<strlen (address);count++)
439 		if (address[count]=='/')
440 			count2++;
441 	if (count2>1)
442 		return EAD_INVALID;
443 	count2=0;
444 	for (count=0;count<strlen (address);count++)
445 		if (address[count]=='.')
446 			count2++;
447 	if (count2>1)
448 		return EAD_INVALID;
449     // count2=0;
450 	// for (count=0;count<strlen (address);count++)
451 
452 	// Discard any address with wildcards
453 	if (strchr (address,'*') || strchr (address,'?'))
454 		return EAD_WILDCARDS;
455 	// At the very least, there must be a : and a / to be a FQA.
456 	if ((!strchr (address,':') || !strchr (address,'/')) && NoMain)
457 		return EAD_CANTRESOLVE;
458 	// Add what's missing, if anything, to get a 4D address
459 	// Zone
460 	first=address;
461 	search=strchr (first,':');
462 	if (!search)
463 		if (NoMain)
464 			return EAD_CANTRESOLVE;
465 		else
466 						sprintf (Compo,"%u",Main->Zone);
467 	else
468 	{
469 		*search=0;
470 		strcpy (Compo,first);
471 		first=search+1;
472 	}
473 	strcat (Compo,":");
474 	// So far compo has the zone number and the :.
475 	// Test for net
476 	search=strchr (first,'/');
477 	if (!search)
478 		if (NoMain)
479 			return EAD_CANTRESOLVE;
480 		else
481                         sprintf (Compo+strlen(Compo),"%u",Main->Net);
482 	else
483 	{
484 		*search=0;
485 		strcat (Compo,first);
486 		first=search+1;
487 	}
488 	strcat (Compo,"/");
489 	// Compo: XXXX:YYYY/    ->
490 	// Node & Point
491 	search=strchr (first,'.');
492 	if (first==search) // No hay nodo
493                 sprintf ("%u",&Compo[strlen (Compo)],Main->Node);
494 	strcat (Compo,first);
495 	if (!search) // The rest is only the node
496 		strcat (Compo,".0");
497 	// FQA completed - now we have to split it to get the number
498 #ifdef DEBUG
499 	printf ("FQA: %s (",Compo);
500 #endif
501 	colon=strchr (Compo,':');
502 	slash=strchr (Compo,'/');
503 	point=strchr (Compo,'.');
504 	if ((slash==colon+1) || (point==slash+1))
505 		return EAD_INVALID;
506 	*colon=*slash=*point=0;
507 	storage->Zone=atoi (Compo);
508 	storage->Net=atoi (colon+1);
509 	storage->Node=atoi (slash+1);
510 	storage->Point=atoi (point+1);
511 	if (storage->Domain[0]==0 && NoMain==0)
512     	strcpy (storage->Domain,Main->Domain);
513 #ifdef DEBUG
514 	printf ("%u:%u/%u.%u)\n",storage->Zone,storage->Net,storage->Node,storage->Point);
515 #endif
516 	return SUCCESS;
517 }
518 
HasWildcards(char * address)519 int HasWildcards (char *address)
520 {
521 	size_t count;
522 	for (count=0;count<strlen (address);count++)
523 		if ((address[count]=='#') ||
524 			(address[count]=='?') ||
525 			(address[count]=='*'))
526 			return 1;
527 	return 0;
528 }
529 
SplitWildcardedAddress(char * origaddress,struct S_WAddress * storage,struct S_WAddress * Main)530 int SplitWildcardedAddress (char *origaddress, struct S_WAddress *storage,struct S_WAddress *Main)
531 {
532 	int NoMain;
533         size_t count,count2;
534 	char *colon,*slash,*point;
535 	char address[81];
536 	if (Main==NULL)
537 		NoMain=1;
538 	else
539 		NoMain=0;
540 	if (strlen (origaddress)>80)
541 		return EAD_INVALID;
542 	strcpy (address,origaddress);
543 	if (*address=='\0')
544 		return EAD_ZERO;
545 	storage->Reverse=0;
546 	colon=strchr (address,'@');
547 	if (colon)
548 	{
549 		*colon=0;
550 		strcpy (storage->Domain,colon+1);
551 	}
552 	else
553 		storage->Domain[0]=0;
554 	if (address[0]=='!')
555 	{
556 		storage->Reverse=1;
557 		strcpy (address,address+1);
558 	}
559 	for (count=0;count<strlen (address);count++)
560 		if (!isdigit (address[count]) && address[count]!=':' &&
561 			address[count]!='/' && address[count]!='.' &&
562 			address[count]!='*' && address[count]!='?' &&
563 			address[count]!='#')
564 			return EAD_INVALID;
565 	count2=0;
566 	for (count=0;count<strlen (address);count++)
567 		if (address[count]==':')
568 			count2++;
569 	if (count2>1)
570 		return EAD_INVALID;
571 	count2=0;
572 	for (count=0;count<strlen (address);count++)
573 		if (address[count]=='/')
574 			count2++;
575 	if (count2>1)
576 		return EAD_INVALID;
577 	count2=0;
578 	for (count=0;count<strlen (address);count++)
579 		if (address[count]=='.')
580 			count2++;
581 	if (count2>1)
582 		return EAD_INVALID;
583 	storage->Zone[0]=storage->Net[0]=storage->Node[0]=storage->Point[0]=0;
584 	colon=strchr (address,':');
585 	slash=strchr (address,'/');
586 	point=strchr (address,'.');
587 	// There are eight possibilities, based on the separators found
588 	switch ((colon!=NULL)*4+(slash!=NULL)*2+(point!=NULL))
589 	{
590 		case 0: // No separators -> anything there is the node specification
591 			if (address[0]=='*')
592 			{
593 				strcpy (storage->Zone,"*");
594 				strcpy (storage->Net,"*");
595 				strcpy (storage->Node,"*");
596 				strcpy (storage->Point,"*");
597 			}
598 			else
599 			{
600 				if (NoMain==1)
601 					return EAD_CANTRESOLVE;
602 				if (HasWildcards (Main->Zone) || HasWildcards (Main->Net))
603 					return EAD_CANTRESOLVE;
604 				strcpy ((char *) &storage->Node,address);
605 				if (HasWildcards (storage->Node))
606 					strcpy ((char *) &storage->Point,"*");
607 			}
608 			break;
609 		case 1: // Only a point
610 			*point=0;
611 			if (NoMain==1)
612 				return EAD_CANTRESOLVE;
613 			if (HasWildcards (Main->Zone) || HasWildcards (Main->Net) ||
614 				HasWildcards (Main->Node))
615 				return EAD_CANTRESOLVE;
616 			strcpy ((char *) &storage->Point,point+1);
617 			strcpy ((char *) &storage->Node,address);
618 			break;
619 		case 2: // Only a slash
620 			if (NoMain==1)
621 				return EAD_CANTRESOLVE;
622 			if (HasWildcards (Main->Zone))
623 				return EAD_CANTRESOLVE;
624 			*slash=0;
625 			strcpy ((char *) &storage->Node,slash+1);
626 			strcpy ((char *) &storage->Net,address);
627                         if ((storage->Node[strlen (storage->Node)-1]=='*') ||
628                                 (storage->Node[strlen (storage->Node)-1]=='?') ||
629                                 (storage->Node[strlen (storage->Node)-1]=='#'))
630 				 strcpy ((char *) &storage->Point,"*");
631 			break;
632 		case 3: // Slash & point
633 			if (slash>point)
634 				return EAD_INVALID;
635 			if (NoMain==1)
636 				return EAD_CANTRESOLVE;
637 			if (HasWildcards (Main->Zone))
638 				return EAD_CANTRESOLVE;
639 			*point=0;
640 			*slash=0;
641 			strcpy ((char *) &storage->Point,point+1);
642 			strcpy ((char *) &storage->Node,slash+1);
643 			strcpy ((char *) &storage->Net,address);
644 			break;
645 		case 4: // Only colon (ie 2: or 2:*)
646 			*colon=0;
647 			strcpy ((char *) &storage->Net,colon+1);
648 			strcpy ((char *) &storage->Zone,address);
649                         if ((storage->Net[strlen (storage->Net)-1]=='*') ||
650                                 (storage->Net[strlen (storage->Net)-1]=='?') ||
651                                 (storage->Net[strlen (storage->Net)-1]=='#'))
652 				{
653 					strcpy ((char *) &storage->Node,"*");
654 					strcpy ((char *) &storage->Point,"*");
655 				}
656 			break;
657 		case 5: // Colon & point (A:B.C -> nonsense)
658 			return EAD_INVALID;
659 		case 6: // Colon & slash (ie 2:40/32)
660 			if (colon>slash)
661 				return EAD_INVALID;
662 			*colon=0;
663 			*slash=0;
664 			strcpy ((char *) &storage->Node,slash+1);
665 			strcpy ((char *) &storage->Net,colon+1);
666 			strcpy ((char *) &storage->Zone,address);
667                         if ((storage->Node[strlen (storage->Node)-1]=='*') ||
668                                 (storage->Node[strlen (storage->Node)-1]=='?') ||
669                                 (storage->Node[strlen (storage->Node)-1]=='#'))
670 				 strcpy ((char *) &storage->Point,"*");
671 			break;
672 		case 7: // colon & slash & point
673 			if (colon>slash || slash>point)
674 				return EAD_INVALID;
675 			*colon=0;
676 			*slash=0;
677 			*point=0;
678 			strcpy ((char *) &storage->Point,point+1);
679 			strcpy ((char *) &storage->Node,slash+1);
680 			strcpy ((char *) &storage->Net,colon+1);
681 			strcpy ((char *) &storage->Zone,address);
682 			break;
683 	}
684 	if (storage->Node[0]=='*')
685 		storage->Node[0]=0;
686 	// Sixteen possibilities based on the filled fields
687 	switch ((storage->Zone[0]!=0)*8+(storage->Net[0]!=0)*4+
688 			(storage->Node[0]!=0)*2+(storage->Point[0]!=0))
689 	{
690 		case 0: // [ ]:[ ]/[ ].[ ]
691 			strcpy ((char *) storage->Zone,"*");
692 			strcpy ((char *) storage->Net,"*");
693 			strcpy ((char *) storage->Node,"*");
694 			strcpy ((char *) storage->Point,"*");
695 			break;
696 		case 1: // [ ]:[ ]/[ ].[X]
697 			if (NoMain)
698 				return EAD_CANTRESOLVE;
699 			strcpy (storage->Zone,Main->Zone);
700 			strcpy (storage->Net,Main->Net);
701 			strcpy (storage->Node,Main->Node);
702 			break;
703 		case 2: // [ ]:[ ]/[X].[ ]
704 			if (NoMain)
705 				return EAD_CANTRESOLVE;
706 			// Notice the following exception:
707 			//	* is not be parsed as *:*/*.* at not as z:n/*.* !!!!
708 			strcpy (storage->Zone,Main->Zone);
709 			strcpy (storage->Net,Main->Net);
710 			strcpy ((char *) storage->Point,"0");
711 		case 3: // [ ]:[ ]/[X].[X]
712 			if (NoMain)
713 				return EAD_CANTRESOLVE;
714 			strcpy (storage->Zone,Main->Zone);
715 			strcpy (storage->Net,Main->Net);
716 			break;
717 		case 4: // [ ]:[X]/[ ].[ ]
718 			strcpy (storage->Zone,Main->Zone);
719 			strcpy ((char *) storage->Node,"*");
720 			strcpy ((char *) storage->Point,"*");
721 			break;
722 		case 5: // [ ]:[X]/[ ].[X] (node was a *, so 341/*.34).
723 			strcpy (storage->Zone,Main->Zone);
724 			strcpy ((char *) storage->Node,"*");
725 			break;
726 		case 6: // [ ]:[X]/[X].[ ]
727 			strcpy (storage->Zone,Main->Zone);
728 			strcpy ((char *) storage->Point,"0");
729 			break;
730 		case 7: // [ ]:[X]/[X].[X]
731 			strcpy (storage->Zone,Main->Zone);
732 			break;
733 		case 8: // [X]:[ ]/[ ].[ ]
734 			strcpy ((char *) storage->Net,"*");
735 			strcpy ((char *) storage->Node,"*");
736 			strcpy ((char *) storage->Point,"*");
737 			break;
738 		case 9:  // [X]:[ ]/[ ].[X]
739 		case 10: // [X]:[ ]/[X].[ ]
740 		case 11: // [X]:[ ]/[X].[X]
741 			return EAD_INVALID;
742 		case 12: // [X]:[X]/[ ].[ ]
743 			strcpy ((char *) storage->Node,"*");
744 			strcpy ((char *) storage->Point,"*");
745 			break;
746 		case 13: // [X].[X]/[ ].[X] // (ie 2:341/*.0)
747 			strcpy ((char *) storage->Node,"*");
748 			break;
749 		case 14: // [X].[X]/[X].[ ]
750 			strcpy ((char *) storage->Point,"0");
751 			break;
752 		case 15: // [X].[X].[X].[X]
753 			;
754 	}
755 #ifdef DEBUG
756 	printf ("%s,%s,%s,%s)\n",storage->Zone,storage->Net,storage->Node,storage->Point);
757 #endif
758 	return SUCCESS;
759 }
760 
CompareBit(word Number,char * string)761 int CompareBit (word Number,char *string)
762 {
763 	char SNum[6];
764 	char *pos1,*pos2;
765 	pos1=SNum; pos2=string;
766         sprintf (SNum,"%u",Number);
767 	// Pos1 point to the number and cannot have wildcards
768 	while (*pos1 && *pos2) // Until a end-of-string is reached
769 	{
770 		if (*pos2=='*') // No need to check more. It is a match
771 			return 1;
772 		if (*pos2=='?') // Everything is ok - check next character
773 			{pos1++; pos2++;}
774 		else
775 		if (*pos2=='#')
776 		{
777 			if (*pos2) // There must be a character - no matter which
778 				{pos1++; pos2++;}
779 			else
780 				return 0; // No match
781 		}
782 		else // If here, no wildcard in pos2
783 		if (*pos1==*pos2)
784 			{pos1++;pos2++;}
785 		else
786 			return 0; // No match
787 	}
788 	// If here, all the characters in the shortest string matches
789 	// the first characters in the largest. What next...?
790 	if (*pos1==*pos2 || (*pos1==0 && *pos2=='*'))
791 		return 1; // Match
792 	else
793 		return 0;
794 }
795 
796 // Determine whether an address matches a wildcard or not...
CompareAddress(struct S_FQAddress FQA,struct S_WAddress * WA)797 int CompareAddress (struct S_FQAddress FQA,struct S_WAddress *WA)
798 {
799 	if (CompareBit (FQA.Zone,WA->Zone) && CompareBit (FQA.Net,WA->Net) &&
800 		CompareBit (FQA.Node,WA->Node) && CompareBit (FQA.Point,WA->Point))
801 		return 1;
802 	else
803     	return 0;
804 }
805 
lengthoffile(FILE * f)806 long lengthoffile(FILE *f)
807 {
808 #ifndef UNIX
809         return (filelength (fileno(f)));
810 #else
811         long curofs = ftell(f);
812         long rv = 0x7FFFFFFFL;
813 
814         fseek(f, 0, SEEK_END);
815         rv = ftell(f);
816         fseek(f, curofs, SEEK_SET);
817 
818         return rv;
819 #endif
820 }
821 
makedirandfopen(char * filename,const char * mode)822 FILE *makedirandfopen (char *filename,const char *mode)
823 {
824 	FILE *fp;
825 	char *workout,*pos;
826 	char *mkdirwork;
827         adaptcase(filename);
828 	fp=fopen (filename,mode);
829 	if (fp!=NULL)
830 		return fp; // End of problem :-)
831 	if (strchr (filename,DIRSEPC)==NULL)
832 		return NULL; // Nothing to do without a slash...
833 	workout=(char *) malloc (strlen (filename)+1);
834 	if (workout==NULL)
835 		return NULL;
836 	strcpy (workout,filename);
837 	pos=workout+strlen (workout)-1;
838 	while (*pos!=DIRSEPC)
839 		pos--;
840 	*pos=0;
841 	// OK, now we have just the directory name
842 	mkdirwork=(char *) malloc (strlen (workout)+1);
843 	if (mkdirwork==NULL)
844 	{
845 		free (workout);
846 		return NULL;
847 	}
848 	strcpy (mkdirwork,workout);
849 	pos=mkdirwork;
850 	/* pos=strchr (mkdirwork,':');
851 	if (pos==NULL)
852 		pos=mkdirwork;
853 	else      /
854 		pos++; */
855 	while (*pos)
856 	{
857 		while (*pos!=DIRSEPC && *pos)
858 			pos++;
859 		if (*pos)
860 		{
861 			*pos=0;
862 #if defined(EMX) || defined(UNIX)
863                         mkdir (mkdirwork,S_IRWXU|S_IRWXG);
864 #else
865                         mkdir (mkdirwork);
866 #endif
867 			*pos=DIRSEPC;
868 			pos++;
869 		}
870 	}
871 #if defined(EMX) || defined(UNIX)
872 		mkdir (mkdirwork,S_IRWXU|S_IRWXG);
873 #else
874 		mkdir (mkdirwork);
875 #endif
876 	fp=fopen (filename,mode);
877 	return fp;
878 }
879 
GetMatchLevel(struct S_FQAddress A1,struct S_FQAddress A2)880 int GetMatchLevel (struct S_FQAddress A1,struct S_FQAddress A2)
881 {
882 	int DomCounts;
883 	if (A1.Domain[0] && A2.Domain[0])
884 		DomCounts=1;
885 	else
886 		DomCounts=0;
887 	if (DomCounts)
888                 if (cistrcmp (A1.Domain,A2.Domain)) // Domain mismatch, goodbye!
889 			return 0;
890 	if (A1.Zone==A2.Zone && A1.Net==A2.Net && A1.Node==A2.Node &&
891 		A1.Point==A2.Point)
892 		return 4+DomCounts;
893 	if (A1.Zone==A2.Zone && A1.Net==A2.Net && A1.Node==A2.Node)
894 		return 3+DomCounts;
895 	if (A1.Zone==A2.Zone && A1.Net==A2.Net)
896 		return 2+DomCounts;
897 	if (A1.Zone==A2.Zone)
898 		return 1+DomCounts;
899 	return DomCounts; //0 = no domain info, 1=domain matches
900 }
901 
902 class C_WildAddress
903 {
904 	int inited;
905 	S_WAddress Last;
906 public:
907 	int ParseAddress (char *Token,S_WAddress *storage);
908 	C_WildAddress (void);
909 };
910 
C_WildAddress(void)911 C_WildAddress::C_WildAddress (void)
912 {
913 	inited=0;
914 }
915 
ParseAddress(char * Token,S_WAddress * storage)916 int C_WildAddress::ParseAddress (char *Token,S_WAddress *storage)
917 {
918 	int keep;
919 	if (inited==0)
920 		keep=SplitWildcardedAddress (Token,storage,NULL);
921 	else
922 		keep=SplitWildcardedAddress (Token,storage,&Last);
923 	if (keep==SUCCESS)
924 		inited=1;
925 	else
926 		inited=0;
927 	memcpy (&Last,storage,sizeof (struct S_WAddress));
928 	return (keep);
929 }
930