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