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