1 /*:ts=8*/
2 /*****************************************************************************
3  * FIDOGATE --- Gateway UNIX Mail/News <-> FTN NetMail/EchoMail
4  *
5  * $Id: parsenode.c,v 4.17 2004/08/22 20:19:11 n0ll Exp $
6  *
7  * Parse FTN address strings (Z:N/F.P)
8  *
9  *****************************************************************************
10  * Copyright (C) 1990-2004
11  *  _____ _____
12  * |     |___  |   Martin Junius             <mj.at.n0ll.dot.net>
13  * | | | |   | |   Radiumstr. 18
14  * |_|_|_|@home|   D-51069 Koeln, Germany
15  *
16  * This file is part of FIDOGATE.
17  *
18  * FIDOGATE is free software; you can redistribute it and/or modify it
19  * under the terms of the GNU General Public License as published by the
20  * Free Software Foundation; either version 2, or (at your option) any
21  * later version.
22  *
23  * FIDOGATE is distributed in the hope that it will be useful, but
24  * WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26  * General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with FIDOGATE; see the file COPYING.  If not, write to the Free
30  * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
31  *****************************************************************************/
32 
33 #include "fidogate.h"
34 
35 
36 
37 /*
38  * Return: >=0 number, ERROR (-1) error, WILDCARD (-2) "*" or "All"
39  */
znfp_get_number(char ** ps)40 int znfp_get_number(char **ps)
41 {
42     char *s = *ps;
43     int val = 0;
44 
45     if(*s == '*')
46     {
47 	s++;
48 	val = WILDCARD;
49     }
50     else if(strnieq(s, "all", 3))
51     {
52 	s += 3;
53 	val = WILDCARD;
54     }
55     else if(!is_digit(*s))
56 	return ERROR;
57     else
58 	while(is_digit(*s))
59 	    val = val*10 + *s++ - '0';
60 
61     *ps = s;
62 
63     return val;
64 }
65 
66 
67 
68 /*
69  * Convert partial Z:N/F.P address to Node, allowing "*" or "all" as wildcard
70  */
znfp_parse_partial(char * asc,Node * node)71 int znfp_parse_partial(char *asc, Node *node)
72 {
73     Node n;
74     char *s = asc;
75     int val1, val;
76 
77     val1    = -1;
78 
79     /* Set Node n to empty */
80     n.zone = n.net = n.node = n.point = EMPTY;
81     n.domain[0] = 0;
82 
83     /* Special case global wildcard "*", "All", or "World" */
84     if(streq(asc, "*") || strieq(asc, "all") || strieq(asc, "world"))
85     {
86 	n.zone = n.net = n.node = n.point = WILDCARD;
87 	if(node)
88 	    *node = n;
89 	return OK;
90     }
91 
92     /* Now for the dirty parsing ... ;-) */
93     if(!*s)
94 	return ERROR;
95 
96     /* A number must come first, exception point address only .N */
97     if(*s != '.')
98 	if( (val1 = znfp_get_number(&s)) == ERROR )
99 	    return ERROR;
100 
101     if(*s == ':')			/* val1 is zone */
102     {
103 	s++;
104 	if(val1 != -1)
105 	{
106 	    n.zone = val1;
107 	    val1   = -1;
108 	}
109 	if( (val = znfp_get_number(&s)) == ERROR )
110 	    return ERROR;
111 	n.net = val;
112     }
113     if(*s == '/')			/* val1 is net */
114     {
115 	s++;
116 	if(val1 != -1)
117 	{
118 	    n.net = val1;
119 	    val1  = -1;
120 	}
121 	if( (val = znfp_get_number(&s)) == ERROR )
122 	    return ERROR;
123 	n.node = val;
124     }
125     if(*s == '.')			/* val1 is node */
126     {
127 	s++;
128 	if(val1 != -1)
129 	{
130 	    n.node = val1;
131 	    val1   = -1;
132 	}
133 	/* Point address after "." */
134 	if( (val = znfp_get_number(&s)) == ERROR )
135 	    return ERROR;
136 	n.point = val;
137     }
138     if(val1 != -1)			/* number only: val1 is node */
139 	n.node = val1;
140 
141     if(*s == '@')			/* Domain address may follow */
142     {
143 	s++;
144 	BUF_COPY(n.domain, s);
145     }
146     else if(*s)
147 	return ERROR;
148 
149     if(node)
150 	*node = n;
151     return OK;
152 }
153 
154 
155 
156 /*
157  * Convert partial Z:N/F.P address to Node, using previous node address
158  */
znfp_parse_diff(char * asc,Node * node,Node * oldnode)159 int znfp_parse_diff(char *asc, Node *node, Node *oldnode)
160 {
161     /* Parse it ... */
162     if(znfp_parse_partial(asc, node) == ERROR)
163 	return ERROR;
164 
165     /* Replace empty parts (-1) with value from oldnode */
166     if(node)
167     {
168 	if(node->zone == EMPTY)
169 	{
170 	    /* No zone, use old zone address */
171 	    node->zone = oldnode->zone;
172 	    if(node->net == EMPTY)
173 	    {
174 		/* No net, use old net address */
175 		node ->net = oldnode->net;
176 		if(node->node == EMPTY)
177 		{
178 		    node->node = oldnode->node;
179 		}
180 	    }
181 	}
182     }
183 
184     return OK;
185 }
186 
187 
188 
189 /*
190  * Output node in Fido Z:N/F.P format
191  */
znfp_put_number(int val,int wildcards)192 char *znfp_put_number(int val, int wildcards)
193 {
194     static char buf[16];
195 
196     if(wildcards && val==WILDCARD)
197 	BUF_COPY(buf, "*");
198     else
199 	str_printf(buf, sizeof(buf), "%d", val);
200 
201     return buf;
202 }
203 
204 
205 #define LEN_ZNFP 48
206 
207 
s_znfp_print(Node * node,int point0,int wildcards)208 char *s_znfp_print(Node *node, int point0, int wildcards)
209 {
210     TmpS *s;
211 
212     s = tmps_alloc(LEN_ZNFP);
213     str_znfp_print(s->s, s->len, node, point0, wildcards);
214     tmps_stripsize(s);
215     return s->s;
216 }
217 
218 
str_znfp_print(char * s,size_t len,Node * node,int point0,int wildcards)219 char *str_znfp_print(char *s, size_t len,
220 		     Node *node, int point0, int wildcards)
221 {
222     /* Clear */
223     s[0] = 0;
224 
225     /* Always display point address if wildcards==TRUE */
226     if(wildcards)
227 	point0 = TRUE;
228 
229     /* Invalid address */
230     if(node->zone==INVALID && node->net==INVALID &&
231        node->node==INVALID && node->point==INVALID  )
232     {
233 	str_copy(s, len, "INVALID");
234 	return s;
235     }
236 
237     /* Global wildcard */
238     if(wildcards &&
239        node->zone==WILDCARD && node->net==WILDCARD &&
240        node->node==WILDCARD && node->point==WILDCARD  )
241     {
242 	str_copy(s, len, "*");
243 	return s;
244     }
245 
246 
247     /* Zone */
248     if(node->zone != EMPTY)
249     {
250 	str_append(s, len, znfp_put_number(node->zone, wildcards));
251 	str_append(s, len, ":");
252     }
253     /* Net */
254     if(node->net != EMPTY)
255     {
256 	str_append(s, len, znfp_put_number(node->net, wildcards));
257 	if(node->node != EMPTY)
258 	    str_append(s, len, "/");
259     }
260     /* Node */
261     if(node->node != EMPTY)
262     {
263 	str_append(s, len, znfp_put_number(node->node, wildcards));
264     }
265     /* Point */
266     if(! (node->point==EMPTY || (node->point==0 && !point0)) )
267     {
268 	str_append(s, len, ".");
269 	str_append(s, len, znfp_put_number(node->point, wildcards));
270     }
271 
272     /* Domain */
273     if(node->domain[0])
274     {
275 	str_append(s, len, "@");
276 	str_append(s, len, node->domain);
277     }
278 
279     return s;
280 }
281 
282 
s_znfp(Node * node)283 char *s_znfp(Node *node)
284 {
285     return s_znfp_print(node, TRUE, TRUE);
286 }
287 
288 
znfp1(Node * node)289 char *znfp1(Node *node)
290 {
291     static char buf[LEN_ZNFP];
292 
293     return str_znfp_print(buf, sizeof(buf), node, TRUE, TRUE);
294 }
295 
296 
znfp2(Node * node)297 char *znfp2(Node *node)
298 {
299     static char buf[LEN_ZNFP];
300 
301     return str_znfp_print(buf, sizeof(buf), node, TRUE, TRUE);
302 }
303 
304 
znfp3(Node * node)305 char *znfp3(Node *node)
306 {
307     static char buf[LEN_ZNFP];
308 
309     return str_znfp_print(buf, sizeof(buf), node, TRUE, TRUE);
310 }
311 
312 
znf1(Node * node)313 char *znf1(Node *node)
314 {
315     static char buf[LEN_ZNFP];
316 
317     return str_znfp_print(buf, sizeof(buf), node, FALSE, FALSE);
318 }
319 
320 
znf2(Node * node)321 char *znf2(Node *node)
322 {
323     static char buf[LEN_ZNFP];
324 
325     return str_znfp_print(buf, sizeof(buf), node, FALSE, FALSE);
326 }
327 
328 
329 
330 /***** TEST ******************************************************************/
331 
332 #ifdef TEST
333 /*
334  * Parser test
335  */
main(int argc,char * argv[])336 int main(int argc, char *argv[])
337 {
338     Node o, n;
339 
340     if(argc!=2 && argc!=3)
341     {
342 	fprintf(stderr,
343 		"usage: testparse Z:N/F.P\n"
344 		"       testparse Z:N/F.P Z:N/F.P\n");
345 	exit(1);
346     }
347 
348     /* Single FTN address */
349     if(argc == 2)
350     {
351 	if(znfp_parse_partial(argv[1], &n) == ERROR)
352 	{
353 	    fprintf(stderr, "testparse: can't parse %s\n", argv[1]);
354 	    exit(1);
355 	}
356 	printf("testparse 1: val=%d:%d/%d.%d\n",
357 	       n.zone, n.net, n.node, n.point   );
358 	printf("             str=%s\n", znfp1(&n));
359 	exit(0);
360     }
361 
362     /* Old and new FTN address */
363     if(argc == 3)
364     {
365 	if(znfp_parse_partial(argv[1], &o) == ERROR)
366 	{
367 	    fprintf(stderr, "testparse: can't parse %s\n", argv[1]);
368 	    exit(1);
369 	}
370 	if(znfp_parse_diff(argv[2], &n, &o) == ERROR)
371 	{
372 	    fprintf(stderr, "testparse: can't parse %s\n", argv[2]);
373 	    exit(1);
374 	}
375 	printf("testparse 2: val1=%d:%d/%d.%d val2=%d:%d/%d.%d\n",
376 	       o.zone, o.net, o.node, o.point, n.zone, n.net, n.node, n.point);
377 	printf("             str1=%s str2=%s\n", znfp1(&o), znfp2(&n));
378 	exit(0);
379     }
380 
381     exit(0);
382 }
383 #endif /**TEST**/
384