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