]> jfr.im git - irc/rqf/shadowircd.git/blame - src/match.c
Allow / in spoofed hosts
[irc/rqf/shadowircd.git] / src / match.c
CommitLineData
212380e3 1/************************************************************************
2 * IRC - Internet Relay Chat, src/match.c
3 * Copyright (C) 1990 Jarkko Oikarinen
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 1, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
df251055 19 * $Id: match.c 3532 2007-07-14 13:32:18Z jilles $
212380e3 20 *
21 */
22#include "stdinc.h"
23#include "config.h"
24#include "client.h"
25#include "ircd.h"
13ae2f4b 26#include "match.h"
212380e3 27
28/*
29 * Compare if a given string (name) matches the given
30 * mask (which can contain wild cards: '*' - match any
31 * number of chars, '?' - match any single character.
32 *
33 * return 1, if match
34 * 0, if no match
35 *
36 * Originally by Douglas A Lewis (dalewis@acsu.buffalo.edu)
37 * Rewritten by Timothy Vogelsang (netski), net@astrolink.org
38 */
39
40/** Check a string against a mask.
41 * This test checks using traditional IRC wildcards only: '*' means
42 * match zero or more characters of any type; '?' means match exactly
43 * one character of any type.
44 *
45 * @param[in] mask Wildcard-containing mask.
46 * @param[in] name String to check against \a mask.
47 * @return Zero if \a mask matches \a name, non-zero if no match.
48 */
49int match(const char *mask, const char *name)
50{
51 const char *m = mask, *n = name;
52 const char *m_tmp = mask, *n_tmp = name;
53 int star_p;
54
55 s_assert(mask != NULL);
56 s_assert(name != NULL);
57
58 for (;;)
59 {
60 switch (*m)
61 {
62 case '\0':
63 if (!*n)
64 return 1;
65 backtrack:
66 if (m_tmp == mask)
67 return 0;
68 m = m_tmp;
69 n = ++n_tmp;
70 break;
71 case '*':
72 case '?':
73 for (star_p = 0;; m++)
74 {
75 if (*m == '*')
76 star_p = 1;
77 else if (*m == '?')
78 {
79 if (!*n++)
80 goto backtrack;
81 }
82 else
83 break;
84 }
85 if (star_p)
86 {
87 if (!*m)
88 return 1;
89 else
90 {
91 m_tmp = m;
92 for (n_tmp = n; *n && ToLower(*n) != ToLower(*m); n++);
93 }
94 }
95 /* and fall through */
96 default:
97 if (!*n)
98 return (*m != '\0' ? 0 : 1);
99 if (ToLower(*m) != ToLower(*n))
100 goto backtrack;
101 m++;
102 n++;
103 break;
104 }
105 }
106}
107
df251055 108/** Check a mask against a mask.
109 * This test checks using traditional IRC wildcards only: '*' means
110 * match zero or more characters of any type; '?' means match exactly
111 * one character of any type.
112 * The difference between mask_match() and match() is that in mask_match()
113 * a '?' in mask does not match a '*' in name.
114 *
115 * @param[in] mask Existing wildcard-containing mask.
116 * @param[in] name New wildcard-containing mask.
117 * @return 1 if \a name is equal to or more specific than \a mask, 0 otherwise.
118 */
119int mask_match(const char *mask, const char *name)
120{
121 const char *m = mask, *n = name;
122 const char *m_tmp = mask, *n_tmp = name;
123 int star_p;
124
125 s_assert(mask != NULL);
126 s_assert(name != NULL);
127
128 for (;;)
129 {
130 switch (*m)
131 {
132 case '\0':
133 if (!*n)
134 return 1;
135 backtrack:
136 if (m_tmp == mask)
137 return 0;
138 m = m_tmp;
139 n = ++n_tmp;
140 break;
141 case '*':
142 case '?':
143 for (star_p = 0;; m++)
144 {
145 if (*m == '*')
146 star_p = 1;
147 else if (*m == '?')
148 {
149 /* changed for mask_match() */
150 if (*n == '*' || !*n)
151 goto backtrack;
152 n++;
153 }
154 else
155 break;
156 }
157 if (star_p)
158 {
159 if (!*m)
160 return 1;
161 else
162 {
163 m_tmp = m;
164 for (n_tmp = n; *n && ToLower(*n) != ToLower(*m); n++);
165 }
166 }
167 /* and fall through */
168 default:
169 if (!*n)
170 return (*m != '\0' ? 0 : 1);
171 if (ToLower(*m) != ToLower(*n))
172 goto backtrack;
173 m++;
174 n++;
175 break;
176 }
177 }
178}
179
180
638156ba
JT
181#define MATCH_MAX_CALLS 512 /* ACK! This dies when it's less that this
182 and we have long lines to parse */
212380e3 183/** Check a string against a mask.
638156ba
JT
184 * This test checks using extended wildcards: '*' means match zero
185 * or more characters of any type; '?' means match exactly one
186 * character of any type; '#' means match exactly one character that
187 * is a number; '@' means match exactly one character that is a
188 * letter; '\s' means match a space.
212380e3 189 *
190 * This function supports escaping, so that a wildcard may be matched
191 * exactly.
192 *
193 * @param[in] mask Wildcard-containing mask.
194 * @param[in] name String to check against \a mask.
195 * @return Zero if \a mask matches \a name, non-zero if no match.
196 */
638156ba
JT
197int
198match_esc(const char *mask, const char *name)
212380e3 199{
638156ba
JT
200 const unsigned char *m = (const unsigned char *)mask;
201 const unsigned char *n = (const unsigned char *)name;
202 const unsigned char *ma = (const unsigned char *)mask;
203 const unsigned char *na = (const unsigned char *)name;
204 int wild = 0;
205 int calls = 0;
206 int quote = 0;
207 int match1 = 0;
212380e3 208
209 s_assert(mask != NULL);
210 s_assert(name != NULL);
211
638156ba
JT
212 if(!mask || !name)
213 return 0;
214
215 /* if the mask is "*", it matches everything */
216 if((*m == '*') && (*(m + 1) == '\0'))
217 return 1;
218
219 while(calls++ < MATCH_MAX_CALLS)
212380e3 220 {
638156ba
JT
221 if(quote)
222 quote++;
223 if(quote == 3)
224 quote = 0;
225 if(*m == '\\' && !quote)
212380e3 226 {
638156ba
JT
227 m++;
228 quote = 1;
229 continue;
230 }
231 if(!quote && *m == '*')
232 {
233 /*
234 * XXX - shouldn't need to spin here, the mask should have been
235 * collapsed before match is called
236 */
237 while(*m == '*')
238 m++;
239
240 wild = 1;
241 ma = m;
242 na = n;
243
244 if(*m == '\\')
245 {
246 m++;
247 /* This means it is an invalid mask -A1kmm. */
248 if(!*m)
249 return 0;
250 quote++;
251 continue;
252 }
253 }
254
255 if(!*m)
256 {
257 if(!*n)
258 return 1;
259 if(quote)
260 return 0;
261 for(m--; (m > (const unsigned char *)mask) && (*m == '?'); m--);;
262
263 if(*m == '*' && (m > (const unsigned char *)mask))
264 return 1;
265 if(!wild)
266 return 0;
267 m = ma;
268 n = ++na;
269 }
270 else if(!*n)
271 {
272 /*
273 * XXX - shouldn't need to spin here, the mask should have been
274 * collapsed before match is called
275 */
276 if(quote)
277 return 0;
278 while(*m == '*')
279 m++;
280 return (*m == 0);
281 }
282
283 if(quote)
284 match1 = *m == 's' ? *n == ' ' : ToLower(*m) == ToLower(*n);
285 else if(*m == '?')
286 match1 = 1;
287 else if(*m == '@')
288 match1 = IsLetter(*n);
289 else if(*m == '#')
290 match1 = IsDigit(*n);
291 else
292 match1 = ToLower(*m) == ToLower(*n);
293 if(match1)
294 {
295 if(*m)
296 m++;
297 if(*n)
298 n++;
299 }
300 else
301 {
302 if(!wild)
303 return 0;
304 m = ma;
305 n = ++na;
212380e3 306 }
307 }
638156ba 308 return 0;
212380e3 309}
310
311int comp_with_mask(void *addr, void *dest, u_int mask)
312{
313 if (memcmp(addr, dest, mask / 8) == 0)
314 {
315 int n = mask / 8;
316 int m = ((-1) << (8 - (mask % 8)));
317 if (mask % 8 == 0 || (((u_char *) addr)[n] & m) == (((u_char *) dest)[n] & m))
318 {
319 return (1);
320 }
321 }
322 return (0);
323}
324
325int comp_with_mask_sock(struct sockaddr *addr, struct sockaddr *dest, u_int mask)
326{
327 void *iaddr = NULL;
328 void *idest = NULL;
329
330 if (addr->sa_family == AF_INET)
331 {
332 iaddr = &((struct sockaddr_in *)addr)->sin_addr;
333 idest = &((struct sockaddr_in *)dest)->sin_addr;
334 }
2c2e0aa9 335#ifdef RB_IPV6
212380e3 336 else
337 {
338 iaddr = &((struct sockaddr_in6 *)addr)->sin6_addr;
339 idest = &((struct sockaddr_in6 *)dest)->sin6_addr;
340
341 }
342#endif
343
344 return (comp_with_mask(iaddr, idest, mask));
345}
346
347/*
348 * match_ips()
349 *
350 * Input - cidr ip mask, address
351 */
352int match_ips(const char *s1, const char *s2)
353{
3ea5fee7 354 struct rb_sockaddr_storage ipaddr, maskaddr;
212380e3 355 char mask[BUFSIZE];
356 char address[HOSTLEN + 1];
357 char *len;
358 void *ipptr, *maskptr;
359 int cidrlen, aftype;
360
361 strcpy(mask, s1);
362 strcpy(address, s2);
363
364 len = strrchr(mask, '/');
365 if (len == NULL)
366 return 0;
367
368 *len++ = '\0';
369
370 cidrlen = atoi(len);
371 if (cidrlen == 0)
372 return 0;
373
2c2e0aa9 374#ifdef RB_IPV6
212380e3 375 if (strchr(mask, ':') && strchr(address, ':'))
376 {
377 aftype = AF_INET6;
378 ipptr = &((struct sockaddr_in6 *)&ipaddr)->sin6_addr;
379 maskptr = &((struct sockaddr_in6 *)&maskaddr)->sin6_addr;
380 }
381 else
382#endif
383 if (!strchr(mask, ':') && !strchr(address, ':'))
384 {
385 aftype = AF_INET;
386 ipptr = &((struct sockaddr_in *)&ipaddr)->sin_addr;
387 maskptr = &((struct sockaddr_in *)&maskaddr)->sin_addr;
388 }
389 else
390 return 0;
391
9879cd59
VY
392 rb_inet_pton(aftype, address, ipptr);
393 rb_inet_pton(aftype, mask, maskptr);
212380e3 394 if (comp_with_mask(ipptr, maskptr, cidrlen))
395 return 1;
396 else
397 return 0;
398}
399
400/* match_cidr()
401 *
402 * Input - mask, address
403 * Ouput - 1 = Matched 0 = Did not match
404 */
405
406int match_cidr(const char *s1, const char *s2)
407{
3ea5fee7 408 struct rb_sockaddr_storage ipaddr, maskaddr;
212380e3 409 char mask[BUFSIZE];
410 char address[NICKLEN + USERLEN + HOSTLEN + 6];
411 char *ipmask;
412 char *ip;
413 char *len;
414 void *ipptr, *maskptr;
415 int cidrlen, aftype;
416
417 strcpy(mask, s1);
418 strcpy(address, s2);
419
420 ipmask = strrchr(mask, '@');
421 if (ipmask == NULL)
422 return 0;
423
424 *ipmask++ = '\0';
425
426 ip = strrchr(address, '@');
427 if (ip == NULL)
428 return 0;
429 *ip++ = '\0';
430
431
432 len = strrchr(ipmask, '/');
433 if (len == NULL)
434 return 0;
435
436 *len++ = '\0';
437
438 cidrlen = atoi(len);
439 if (cidrlen == 0)
440 return 0;
441
2c2e0aa9 442#ifdef RB_IPV6
212380e3 443 if (strchr(ip, ':') && strchr(ipmask, ':'))
444 {
445 aftype = AF_INET6;
446 ipptr = &((struct sockaddr_in6 *)&ipaddr)->sin6_addr;
447 maskptr = &((struct sockaddr_in6 *)&maskaddr)->sin6_addr;
448 }
449 else
450#endif
451 if (!strchr(ip, ':') && !strchr(ipmask, ':'))
452 {
453 aftype = AF_INET;
454 ipptr = &((struct sockaddr_in *)&ipaddr)->sin_addr;
455 maskptr = &((struct sockaddr_in *)&maskaddr)->sin_addr;
456 }
457 else
458 return 0;
459
9879cd59
VY
460 rb_inet_pton(aftype, ip, ipptr);
461 rb_inet_pton(aftype, ipmask, maskptr);
212380e3 462 if (comp_with_mask(ipptr, maskptr, cidrlen) && match(mask, address))
463 return 1;
464 else
465 return 0;
466}
467
468/* collapse()
469 *
470 * collapses a string containing multiple *'s.
471 */
472char *collapse(char *pattern)
473{
474 char *p = pattern, *po = pattern;
475 char c;
476 int f = 0;
477
478 if (p == NULL)
479 return NULL;
480
481 while ((c = *p++))
482 {
483 if (c == '*')
484 {
485 if (!(f & 1))
486 *po++ = '*';
487 f |= 1;
488 }
489 else
490 {
491 *po++ = c;
492 f &= ~1;
493 }
494 }
495 *po++ = 0;
496
497 return pattern;
498}
499
500/* collapse_esc()
501 *
502 * The collapse() function with support for escaping characters
503 */
504char *collapse_esc(char *pattern)
505{
506 char *p = pattern, *po = pattern;
507 char c;
508 int f = 0;
509
510 if (p == NULL)
511 return NULL;
512
513 while ((c = *p++))
514 {
515 if (!(f & 2) && c == '*')
516 {
517 if (!(f & 1))
518 *po++ = '*';
519 f |= 1;
520 }
521 else if (!(f & 2) && c == '\\')
522 {
523 *po++ = '\\';
524 f |= 2;
525 }
526 else
527 {
528 *po++ = c;
529 f &= ~3;
530 }
531 }
532 *po++ = 0;
533 return pattern;
534}
535
536/*
537 * irccmp - case insensitive comparison of two 0 terminated strings.
538 *
539 * returns 0, if s1 equal to s2
540 * <0, if s1 lexicographically less than s2
541 * >0, if s1 lexicographically greater than s2
542 */
543int irccmp(const char *s1, const char *s2)
544{
545 const unsigned char *str1 = (const unsigned char *)s1;
546 const unsigned char *str2 = (const unsigned char *)s2;
547 int res;
548
549 s_assert(s1 != NULL);
550 s_assert(s2 != NULL);
551
552 while ((res = ToUpper(*str1) - ToUpper(*str2)) == 0)
553 {
554 if (*str1 == '\0')
555 return 0;
556 str1++;
557 str2++;
558 }
559 return (res);
560}
561
562int ircncmp(const char *s1, const char *s2, int n)
563{
564 const unsigned char *str1 = (const unsigned char *)s1;
565 const unsigned char *str2 = (const unsigned char *)s2;
566 int res;
567 s_assert(s1 != NULL);
568 s_assert(s2 != NULL);
569
570 while ((res = ToUpper(*str1) - ToUpper(*str2)) == 0)
571 {
572 str1++;
573 str2++;
574 n--;
575 if (n == 0 || (*str1 == '\0' && *str2 == '\0'))
576 return 0;
577 }
578 return (res);
579}
580
581const unsigned char ToLowerTab[] = {
582 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
583 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
584 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
585 0x1e, 0x1f,
586 ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
587 '*', '+', ',', '-', '.', '/',
588 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
589 ':', ';', '<', '=', '>', '?',
590 '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
591 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
592 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
593 '_',
594 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
595 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
596 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
597 0x7f,
598 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
599 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
600 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
601 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
602 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
603 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
604 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
605 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
606 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
607 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
608 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
609 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
610 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
611 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
612 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
613 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
614};
615
616const unsigned char ToUpperTab[] = {
617 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
618 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
619 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
620 0x1e, 0x1f,
621 ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
622 '*', '+', ',', '-', '.', '/',
623 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
624 ':', ';', '<', '=', '>', '?',
625 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
626 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
627 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
628 0x5f,
629 '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
630 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
631 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
632 0x7f,
633 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
634 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
635 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
636 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
637 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
638 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
639 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
640 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
641 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
642 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
643 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
644 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
645 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
646 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
647 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
648 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
649};
650
651/*
652 * CharAttrs table
653 *
654 * NOTE: RFC 1459 sez: anything but a ^G, comma, or space is allowed
655 * for channel names
656 */
657const unsigned int CharAttrs[] = {
658/* 0 */ CNTRL_C,
659/* 1 */ CNTRL_C | CHAN_C | NONEOS_C,
660/* 2 */ CNTRL_C | CHAN_C | FCHAN_C | NONEOS_C,
661/* 3 */ CNTRL_C | CHAN_C | FCHAN_C | NONEOS_C,
662/* 4 */ CNTRL_C | CHAN_C | NONEOS_C,
663/* 5 */ CNTRL_C | CHAN_C | NONEOS_C,
664/* 6 */ CNTRL_C | CHAN_C | NONEOS_C,
665/* 7 BEL */ CNTRL_C | NONEOS_C,
666/* 8 \b */ CNTRL_C | CHAN_C | NONEOS_C,
667/* 9 \t */ CNTRL_C | SPACE_C | CHAN_C | NONEOS_C,
668/* 10 \n */ CNTRL_C | SPACE_C | CHAN_C | NONEOS_C | EOL_C,
669/* 11 \v */ CNTRL_C | SPACE_C | CHAN_C | NONEOS_C,
670/* 12 \f */ CNTRL_C | SPACE_C | CHAN_C | NONEOS_C,
671/* 13 \r */ CNTRL_C | SPACE_C | CHAN_C | NONEOS_C | EOL_C,
672/* 14 */ CNTRL_C | CHAN_C | NONEOS_C,
673/* 15 */ CNTRL_C | CHAN_C | NONEOS_C,
674/* 16 */ CNTRL_C | CHAN_C | NONEOS_C,
675/* 17 */ CNTRL_C | CHAN_C | NONEOS_C,
676/* 18 */ CNTRL_C | CHAN_C | NONEOS_C,
677/* 19 */ CNTRL_C | CHAN_C | NONEOS_C,
678/* 20 */ CNTRL_C | CHAN_C | NONEOS_C,
679/* 21 */ CNTRL_C | CHAN_C | NONEOS_C,
680/* 22 */ CNTRL_C | CHAN_C | FCHAN_C | NONEOS_C,
681/* 23 */ CNTRL_C | CHAN_C | NONEOS_C,
682/* 24 */ CNTRL_C | CHAN_C | NONEOS_C,
683/* 25 */ CNTRL_C | CHAN_C | NONEOS_C,
684/* 26 */ CNTRL_C | CHAN_C | NONEOS_C,
685/* 27 */ CNTRL_C | CHAN_C | NONEOS_C,
686/* 28 */ CNTRL_C | CHAN_C | NONEOS_C,
687/* 29 */ CNTRL_C | CHAN_C | NONEOS_C,
688/* 30 */ CNTRL_C | CHAN_C | NONEOS_C,
689/* 31 */ CNTRL_C | CHAN_C | FCHAN_C | NONEOS_C,
690/* SP */ PRINT_C | SPACE_C,
691/* ! */ PRINT_C | KWILD_C | CHAN_C | NONEOS_C,
692/* " */ PRINT_C | CHAN_C | NONEOS_C,
693/* # */ PRINT_C | MWILD_C | CHANPFX_C | CHAN_C | NONEOS_C,
694/* $ */ PRINT_C | CHAN_C | NONEOS_C | USER_C,
695/* % */ PRINT_C | CHAN_C | NONEOS_C,
696/* & */ PRINT_C | CHANPFX_C | CHAN_C | NONEOS_C,
697/* ' */ PRINT_C | CHAN_C | NONEOS_C,
698/* ( */ PRINT_C | CHAN_C | NONEOS_C,
699/* ) */ PRINT_C | CHAN_C | NONEOS_C,
e5d9ca18 700/* * */ PRINT_C | KWILD_C | MWILD_C | CHAN_C | NONEOS_C,
212380e3 701/* + */ PRINT_C | CHAN_C | NONEOS_C,
702/* , */ PRINT_C | NONEOS_C,
703/* - */ PRINT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
704/* . */ PRINT_C | KWILD_C | CHAN_C | NONEOS_C | USER_C | HOST_C | SERV_C,
59bb8093 705/* / */ PRINT_C | CHAN_C | NONEOS_C | HOST_C,
212380e3 706/* 0 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
707/* 1 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
708/* 2 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
709/* 3 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
710/* 4 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
711/* 5 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
712/* 6 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
713/* 7 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
714/* 8 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
715/* 9 */ PRINT_C | DIGIT_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
716/* : */ PRINT_C | CHAN_C | NONEOS_C | HOST_C,
717/* ; */ PRINT_C | CHAN_C | NONEOS_C,
718/* < */ PRINT_C | CHAN_C | NONEOS_C,
719/* = */ PRINT_C | CHAN_C | NONEOS_C,
720/* > */ PRINT_C | CHAN_C | NONEOS_C,
721/* ? */ PRINT_C | KWILD_C | MWILD_C | CHAN_C | NONEOS_C,
722/* @ */ PRINT_C | KWILD_C | MWILD_C | CHAN_C | NONEOS_C,
723/* A */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
724/* B */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
725/* C */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
726/* D */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
727/* E */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
728/* F */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
729/* G */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
730/* H */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
731/* I */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
732/* J */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
733/* K */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
734/* L */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
735/* M */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
736/* N */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
737/* O */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
738/* P */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
739/* Q */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
740/* R */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
741/* S */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
742/* T */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
743/* U */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
744/* V */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
745/* W */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
746/* X */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
747/* Y */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
748/* Z */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
749/* [ */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
750/* \ */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
751/* ] */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
752/* ^ */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
753/* _ */ PRINT_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
754/* ` */ PRINT_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
755/* a */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
756/* b */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
757/* c */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
758/* d */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
759/* e */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
760/* f */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
761/* g */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
762/* h */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
763/* i */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
764/* j */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
765/* k */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
766/* l */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
767/* m */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
768/* n */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
769/* o */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
770/* p */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
771/* q */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
772/* r */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
773/* s */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
774/* t */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
775/* u */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
776/* v */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
777/* w */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
778/* x */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
779/* y */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
780/* z */ PRINT_C | ALPHA_C | LET_C | NICK_C | CHAN_C | NONEOS_C | USER_C | HOST_C,
781/* { */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
782/* | */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
783/* } */ PRINT_C | ALPHA_C | NICK_C | CHAN_C | NONEOS_C | USER_C,
784/* ~ */ PRINT_C | ALPHA_C | CHAN_C | NONEOS_C | USER_C,
785/* del */ CHAN_C | NONEOS_C,
786/* 0x80 */ CHAN_C | NONEOS_C,
787/* 0x81 */ CHAN_C | NONEOS_C,
788/* 0x82 */ CHAN_C | NONEOS_C,
789/* 0x83 */ CHAN_C | NONEOS_C,
790/* 0x84 */ CHAN_C | NONEOS_C,
791/* 0x85 */ CHAN_C | NONEOS_C,
792/* 0x86 */ CHAN_C | NONEOS_C,
793/* 0x87 */ CHAN_C | NONEOS_C,
794/* 0x88 */ CHAN_C | NONEOS_C,
795/* 0x89 */ CHAN_C | NONEOS_C,
796/* 0x8A */ CHAN_C | NONEOS_C,
797/* 0x8B */ CHAN_C | NONEOS_C,
798/* 0x8C */ CHAN_C | NONEOS_C,
799/* 0x8D */ CHAN_C | NONEOS_C,
800/* 0x8E */ CHAN_C | NONEOS_C,
801/* 0x8F */ CHAN_C | NONEOS_C,
802/* 0x90 */ CHAN_C | NONEOS_C,
803/* 0x91 */ CHAN_C | NONEOS_C,
804/* 0x92 */ CHAN_C | NONEOS_C,
805/* 0x93 */ CHAN_C | NONEOS_C,
806/* 0x94 */ CHAN_C | NONEOS_C,
807/* 0x95 */ CHAN_C | NONEOS_C,
808/* 0x96 */ CHAN_C | NONEOS_C,
809/* 0x97 */ CHAN_C | NONEOS_C,
810/* 0x98 */ CHAN_C | NONEOS_C,
811/* 0x99 */ CHAN_C | NONEOS_C,
812/* 0x9A */ CHAN_C | NONEOS_C,
813/* 0x9B */ CHAN_C | NONEOS_C,
814/* 0x9C */ CHAN_C | NONEOS_C,
815/* 0x9D */ CHAN_C | NONEOS_C,
816/* 0x9E */ CHAN_C | NONEOS_C,
817/* 0x9F */ CHAN_C | NONEOS_C,
818/* 0xA0 */ CHAN_C | FCHAN_C | NONEOS_C,
819/* 0xA1 */ CHAN_C | NONEOS_C,
820/* 0xA2 */ CHAN_C | NONEOS_C,
821/* 0xA3 */ CHAN_C | NONEOS_C,
822/* 0xA4 */ CHAN_C | NONEOS_C,
823/* 0xA5 */ CHAN_C | NONEOS_C,
824/* 0xA6 */ CHAN_C | NONEOS_C,
825/* 0xA7 */ CHAN_C | NONEOS_C,
826/* 0xA8 */ CHAN_C | NONEOS_C,
827/* 0xA9 */ CHAN_C | NONEOS_C,
828/* 0xAA */ CHAN_C | NONEOS_C,
829/* 0xAB */ CHAN_C | NONEOS_C,
830/* 0xAC */ CHAN_C | NONEOS_C,
831/* 0xAD */ CHAN_C | NONEOS_C,
832/* 0xAE */ CHAN_C | NONEOS_C,
833/* 0xAF */ CHAN_C | NONEOS_C,
834/* 0xB0 */ CHAN_C | NONEOS_C,
835/* 0xB1 */ CHAN_C | NONEOS_C,
836/* 0xB2 */ CHAN_C | NONEOS_C,
837/* 0xB3 */ CHAN_C | NONEOS_C,
838/* 0xB4 */ CHAN_C | NONEOS_C,
839/* 0xB5 */ CHAN_C | NONEOS_C,
840/* 0xB6 */ CHAN_C | NONEOS_C,
841/* 0xB7 */ CHAN_C | NONEOS_C,
842/* 0xB8 */ CHAN_C | NONEOS_C,
843/* 0xB9 */ CHAN_C | NONEOS_C,
844/* 0xBA */ CHAN_C | NONEOS_C,
845/* 0xBB */ CHAN_C | NONEOS_C,
846/* 0xBC */ CHAN_C | NONEOS_C,
847/* 0xBD */ CHAN_C | NONEOS_C,
848/* 0xBE */ CHAN_C | NONEOS_C,
849/* 0xBF */ CHAN_C | NONEOS_C,
850/* 0xC0 */ CHAN_C | NONEOS_C,
851/* 0xC1 */ CHAN_C | NONEOS_C,
852/* 0xC2 */ CHAN_C | NONEOS_C,
853/* 0xC3 */ CHAN_C | NONEOS_C,
854/* 0xC4 */ CHAN_C | NONEOS_C,
855/* 0xC5 */ CHAN_C | NONEOS_C,
856/* 0xC6 */ CHAN_C | NONEOS_C,
857/* 0xC7 */ CHAN_C | NONEOS_C,
858/* 0xC8 */ CHAN_C | NONEOS_C,
859/* 0xC9 */ CHAN_C | NONEOS_C,
860/* 0xCA */ CHAN_C | NONEOS_C,
861/* 0xCB */ CHAN_C | NONEOS_C,
862/* 0xCC */ CHAN_C | NONEOS_C,
863/* 0xCD */ CHAN_C | NONEOS_C,
864/* 0xCE */ CHAN_C | NONEOS_C,
865/* 0xCF */ CHAN_C | NONEOS_C,
866/* 0xD0 */ CHAN_C | NONEOS_C,
867/* 0xD1 */ CHAN_C | NONEOS_C,
868/* 0xD2 */ CHAN_C | NONEOS_C,
869/* 0xD3 */ CHAN_C | NONEOS_C,
870/* 0xD4 */ CHAN_C | NONEOS_C,
871/* 0xD5 */ CHAN_C | NONEOS_C,
872/* 0xD6 */ CHAN_C | NONEOS_C,
873/* 0xD7 */ CHAN_C | NONEOS_C,
874/* 0xD8 */ CHAN_C | NONEOS_C,
875/* 0xD9 */ CHAN_C | NONEOS_C,
876/* 0xDA */ CHAN_C | NONEOS_C,
877/* 0xDB */ CHAN_C | NONEOS_C,
878/* 0xDC */ CHAN_C | NONEOS_C,
879/* 0xDD */ CHAN_C | NONEOS_C,
880/* 0xDE */ CHAN_C | NONEOS_C,
881/* 0xDF */ CHAN_C | NONEOS_C,
882/* 0xE0 */ CHAN_C | NONEOS_C,
883/* 0xE1 */ CHAN_C | NONEOS_C,
884/* 0xE2 */ CHAN_C | NONEOS_C,
885/* 0xE3 */ CHAN_C | NONEOS_C,
886/* 0xE4 */ CHAN_C | NONEOS_C,
887/* 0xE5 */ CHAN_C | NONEOS_C,
888/* 0xE6 */ CHAN_C | NONEOS_C,
889/* 0xE7 */ CHAN_C | NONEOS_C,
890/* 0xE8 */ CHAN_C | NONEOS_C,
891/* 0xE9 */ CHAN_C | NONEOS_C,
892/* 0xEA */ CHAN_C | NONEOS_C,
893/* 0xEB */ CHAN_C | NONEOS_C,
894/* 0xEC */ CHAN_C | NONEOS_C,
895/* 0xED */ CHAN_C | NONEOS_C,
896/* 0xEE */ CHAN_C | NONEOS_C,
897/* 0xEF */ CHAN_C | NONEOS_C,
898/* 0xF0 */ CHAN_C | NONEOS_C,
899/* 0xF1 */ CHAN_C | NONEOS_C,
900/* 0xF2 */ CHAN_C | NONEOS_C,
901/* 0xF3 */ CHAN_C | NONEOS_C,
902/* 0xF4 */ CHAN_C | NONEOS_C,
903/* 0xF5 */ CHAN_C | NONEOS_C,
904/* 0xF6 */ CHAN_C | NONEOS_C,
905/* 0xF7 */ CHAN_C | NONEOS_C,
906/* 0xF8 */ CHAN_C | NONEOS_C,
907/* 0xF9 */ CHAN_C | NONEOS_C,
908/* 0xFA */ CHAN_C | NONEOS_C,
909/* 0xFB */ CHAN_C | NONEOS_C,
910/* 0xFC */ CHAN_C | NONEOS_C,
911/* 0xFD */ CHAN_C | NONEOS_C,
912/* 0xFE */ CHAN_C | NONEOS_C,
913/* 0xFF */ CHAN_C | NONEOS_C
914};