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