1 /************************************************************************
2 * IRC - Internet Relay Chat, src/match.c
3 * Copyright (C) 1990 Jarkko Oikarinen
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)
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.
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.
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.
36 * Originally by Douglas A Lewis (dalewis@acsu.buffalo.edu)
37 * Rewritten by Timothy Vogelsang (netski), net@astrolink.org
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.
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.
49 int match(const char *mask
, const char *name
)
51 const char *m
= mask
, *n
= name
;
52 const char *m_tmp
= mask
, *n_tmp
= name
;
55 s_assert(mask
!= NULL
);
56 s_assert(name
!= NULL
);
73 for (star_p
= 0;; m
++)
92 for (n_tmp
= n
; *n
&& irctolower(*n
) != irctolower(*m
); n
++);
95 /* and fall through */
98 return (*m
!= '\0' ? 0 : 1);
99 if (irctolower(*m
) != irctolower(*n
))
108 /* Reorder runs of [?*] in mask to the form ``**...??...'' */
110 match_arrange_stars(char *mask
)
114 for (char *p
= mask
; *p
!= '\0'; p
++)
119 if (swap
== NULL
) break;
124 if (swap
== NULL
) swap
= p
;
133 /** Check a mask against a mask.
134 * This test checks using traditional IRC wildcards only: '*' means
135 * match zero or more characters of any type; '?' means match exactly
136 * one character of any type.
137 * The difference between mask_match() and match() is that in mask_match()
138 * a '?' in mask does not match a '*' in name.
140 * @param[in] mask Existing wildcard-containing mask.
141 * @param[in] name New wildcard-containing mask.
142 * @return 1 if \a name is equal to or more specific than \a mask, 0 otherwise.
144 int mask_match(const char *mask_
, const char *name
)
146 static char mask
[BUFSIZE
];
147 const char *m
= mask
, *n
= name
;
148 const char *m_tmp
= mask
, *n_tmp
= name
;
152 s_assert(mask_
!= NULL
);
153 s_assert(name
!= NULL
);
155 len
= rb_strlcpy(mask
, mask_
, sizeof mask
);
156 s_assert(len
< sizeof mask
);
157 (void) len
; /* for NDEBUG */
159 match_arrange_stars(mask
);
176 for (star_p
= 0;; m
++)
182 /* changed for mask_match() */
183 while (star_p
&& *n
== '*') n
++;
184 if (*n
== '*' || !*n
)
198 for (n_tmp
= n
; *n
&& irctolower(*n
) != irctolower(*m
); n
++);
201 /* and fall through */
204 return (*m
!= '\0' ? 0 : 1);
205 if (irctolower(*m
) != irctolower(*n
))
215 #define MATCH_MAX_CALLS 512 /* ACK! This dies when it's less that this
216 and we have long lines to parse */
217 /** Check a string against a mask.
218 * This test checks using extended wildcards: '*' means match zero
219 * or more characters of any type; '?' means match exactly one
220 * character of any type; '#' means match exactly one character that
221 * is a number; '@' means match exactly one character that is a
222 * letter; '\s' means match a space.
224 * This function supports escaping, so that a wildcard may be matched
227 * @param[in] mask Wildcard-containing mask.
228 * @param[in] name String to check against \a mask.
229 * @return Zero if \a mask matches \a name, non-zero if no match.
232 match_esc(const char *mask
, const char *name
)
234 const unsigned char *m
= (const unsigned char *)mask
;
235 const unsigned char *n
= (const unsigned char *)name
;
236 const unsigned char *ma
= (const unsigned char *)mask
;
237 const unsigned char *na
= (const unsigned char *)name
;
243 s_assert(mask
!= NULL
);
244 s_assert(name
!= NULL
);
249 /* if the mask is "*", it matches everything */
250 if((*m
== '*') && (*(m
+ 1) == '\0'))
253 while(calls
++ < MATCH_MAX_CALLS
)
259 if(*m
== '\\' && !quote
)
265 if(!quote
&& *m
== '*')
268 * XXX - shouldn't need to spin here, the mask should have been
269 * collapsed before match is called
281 /* This means it is an invalid mask -A1kmm. */
295 for(m
--; (m
> (const unsigned char *)mask
) && (*m
== '?'); m
--)
298 if(*m
== '*' && (m
> (const unsigned char *)mask
))
308 * XXX - shouldn't need to spin here, the mask should have been
309 * collapsed before match is called
319 match1
= *m
== 's' ? *n
== ' ' : irctolower(*m
) == irctolower(*n
);
323 match1
= IsLetter(*n
);
325 match1
= IsDigit(*n
);
327 match1
= irctolower(*m
) == irctolower(*n
);
346 int comp_with_mask(void *addr
, void *dest
, unsigned int mask
)
348 if (memcmp(addr
, dest
, mask
/ 8) == 0)
351 unsigned char m
= (0xFF << (8 - (mask
% 8)));
352 if (mask
% 8 == 0 || (((unsigned char *) addr
)[n
] & m
) == (((unsigned char *) dest
)[n
] & m
))
360 int comp_with_mask_sock(struct sockaddr
*addr
, struct sockaddr
*dest
, unsigned int mask
)
365 if (addr
->sa_family
== AF_INET
)
367 iaddr
= &((struct sockaddr_in
*)(void *)addr
)->sin_addr
;
368 idest
= &((struct sockaddr_in
*)(void *)dest
)->sin_addr
;
372 iaddr
= &((struct sockaddr_in6
*)(void *)addr
)->sin6_addr
;
373 idest
= &((struct sockaddr_in6
*)(void *)dest
)->sin6_addr
;
377 return (comp_with_mask(iaddr
, idest
, mask
));
383 * Input - cidr ip mask, address
385 int match_ips(const char *s1
, const char *s2
)
387 struct rb_sockaddr_storage ipaddr
, maskaddr
;
389 char address
[HOSTLEN
+ 1];
391 void *ipptr
, *maskptr
;
394 rb_strlcpy(mask
, s1
, sizeof(mask
));
395 rb_strlcpy(address
, s2
, sizeof(address
));
397 len
= strrchr(mask
, '/');
407 if (strchr(mask
, ':') && strchr(address
, ':'))
413 ipptr
= &((struct sockaddr_in6
*)&ipaddr
)->sin6_addr
;
414 maskptr
= &((struct sockaddr_in6
*)&maskaddr
)->sin6_addr
;
416 else if (!strchr(mask
, ':') && !strchr(address
, ':'))
422 ipptr
= &((struct sockaddr_in
*)&ipaddr
)->sin_addr
;
423 maskptr
= &((struct sockaddr_in
*)&maskaddr
)->sin_addr
;
428 if (rb_inet_pton(aftype
, address
, ipptr
) <= 0)
430 if (rb_inet_pton(aftype
, mask
, maskptr
) <= 0)
432 if (comp_with_mask(ipptr
, maskptr
, cidrlen
))
440 * Input - mask, address
441 * Ouput - 1 = Matched 0 = Did not match
444 int match_cidr(const char *s1
, const char *s2
)
446 struct rb_sockaddr_storage ipaddr
, maskaddr
;
448 char address
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
452 void *ipptr
, *maskptr
;
455 rb_strlcpy(mask
, s1
, sizeof(mask
));
456 rb_strlcpy(address
, s2
, sizeof(address
));
458 ipmask
= strrchr(mask
, '@');
464 ip
= strrchr(address
, '@');
470 len
= strrchr(ipmask
, '/');
480 if (strchr(ip
, ':') && strchr(ipmask
, ':'))
486 ipptr
= &((struct sockaddr_in6
*)&ipaddr
)->sin6_addr
;
487 maskptr
= &((struct sockaddr_in6
*)&maskaddr
)->sin6_addr
;
489 else if (!strchr(ip
, ':') && !strchr(ipmask
, ':'))
495 ipptr
= &((struct sockaddr_in
*)&ipaddr
)->sin_addr
;
496 maskptr
= &((struct sockaddr_in
*)&maskaddr
)->sin_addr
;
501 if (rb_inet_pton(aftype
, ip
, ipptr
) <= 0)
503 if (rb_inet_pton(aftype
, ipmask
, maskptr
) <= 0)
505 if (comp_with_mask(ipptr
, maskptr
, cidrlen
) && match(mask
, address
))
513 * collapses a string containing multiple *'s.
515 char *collapse(char *pattern
)
517 char *p
= pattern
, *po
= pattern
;
545 * The collapse() function with support for escaping characters
547 char *collapse_esc(char *pattern
)
549 char *p
= pattern
, *po
= pattern
;
558 if (!(f
& 2) && c
== '*')
564 else if (!(f
& 2) && c
== '\\')
580 * irccmp - case insensitive comparison of two 0 terminated strings.
582 * returns 0, if s1 equal to s2
583 * <0, if s1 lexicographically less than s2
584 * >0, if s1 lexicographically greater than s2
586 int irccmp(const char *s1
, const char *s2
)
588 const unsigned char *str1
= (const unsigned char *)s1
;
589 const unsigned char *str2
= (const unsigned char *)s2
;
592 s_assert(s1
!= NULL
);
593 s_assert(s2
!= NULL
);
595 while ((res
= irctoupper(*str1
) - irctoupper(*str2
)) == 0)
605 int ircncmp(const char *s1
, const char *s2
, int n
)
607 const unsigned char *str1
= (const unsigned char *)s1
;
608 const unsigned char *str2
= (const unsigned char *)s2
;
610 s_assert(s1
!= NULL
);
611 s_assert(s2
!= NULL
);
613 while ((res
= irctoupper(*str1
) - irctoupper(*str2
)) == 0)
618 if (n
== 0 || (*str1
== '\0' && *str2
== '\0'))
624 void matchset_for_client(struct Client
*who
, struct matchset
*m
)
626 bool hide_ip
= IsIPSpoof(who
) || (!ConfigChannel
.ip_bans_through_vhost
&& IsDynSpoof(who
));
630 struct sockaddr_in ip4
;
632 sprintf(m
->host
[hostn
++], "%s!%s@%s", who
->name
, who
->username
, who
->host
);
636 sprintf(m
->ip
[ipn
++], "%s!%s@%s", who
->name
, who
->username
, who
->sockhost
);
639 if (who
->localClient
->mangledhost
!= NULL
)
641 /* if host mangling mode enabled, also check their real host */
642 if (!strcmp(who
->host
, who
->localClient
->mangledhost
))
644 sprintf(m
->host
[hostn
++], "%s!%s@%s", who
->name
, who
->username
, who
->orighost
);
646 /* if host mangling mode not enabled and no other spoof,
647 * also check the mangled form of their host */
648 else if (!IsDynSpoof(who
))
650 sprintf(m
->host
[hostn
++], "%s!%s@%s", who
->name
, who
->username
, who
->localClient
->mangledhost
);
653 if (!hide_ip
&& GET_SS_FAMILY(&who
->localClient
->ip
) == AF_INET6
&&
654 rb_ipv4_from_ipv6((const struct sockaddr_in6
*)&who
->localClient
->ip
, &ip4
))
656 int n
= sprintf(m
->ip
[ipn
], "%s!%s@", who
->name
, who
->username
);
657 rb_inet_ntop_sock((struct sockaddr
*)&ip4
,
658 m
->ip
[ipn
] + n
, sizeof m
->ip
[ipn
] - n
);
662 for (int i
= hostn
; i
< ARRAY_SIZE(m
->host
); i
++)
664 m
->host
[i
][0] = '\0';
666 for (int i
= ipn
; i
< ARRAY_SIZE(m
->ip
); i
++)
672 bool client_matches_mask(struct Client
*who
, const char *mask
)
674 static struct matchset ms
;
675 matchset_for_client(who
, &ms
);
676 return matches_mask(&ms
, mask
);
679 bool matches_mask(const struct matchset
*m
, const char *mask
)
681 for (int i
= 0; i
< ARRAY_SIZE(m
->host
); i
++)
683 if (m
->host
[i
][0] == '\0')
685 if (match(mask
, m
->host
[i
]))
688 for (int i
= 0; i
< ARRAY_SIZE(m
->ip
); i
++)
690 if (m
->ip
[i
][0] == '\0')
692 if (match(mask
, m
->ip
[i
]))
694 if (match_cidr(mask
, m
->ip
[i
]))
700 const unsigned char irctolower_tab
[] = {
701 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
702 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
703 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
705 ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
706 '*', '+', ',', '-', '.', '/',
707 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
708 ':', ';', '<', '=', '>', '?',
709 '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
710 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
711 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
713 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
714 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
715 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
717 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
718 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
719 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
720 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
721 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
722 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
723 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
724 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
725 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
726 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
727 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
728 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
729 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
730 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
731 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
732 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
735 const unsigned char irctoupper_tab
[] = {
736 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
737 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
738 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
740 ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
741 '*', '+', ',', '-', '.', '/',
742 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
743 ':', ';', '<', '=', '>', '?',
744 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
745 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
746 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
748 '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
749 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
750 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
752 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
753 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
754 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
755 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
756 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
757 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
758 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
759 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
760 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
761 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
762 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
763 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
764 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
765 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
766 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
767 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
773 * NOTE: RFC 1459 sez: anything but a ^G, comma, or space is allowed
776 unsigned int CharAttrs
[] = {
778 /* 1 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
779 /* 2 */ CNTRL_C
| CHAN_C
| FCHAN_C
| NONEOS_C
,
780 /* 3 */ CNTRL_C
| CHAN_C
| FCHAN_C
| NONEOS_C
,
781 /* 4 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
782 /* 5 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
783 /* 6 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
784 /* 7 BEL */ CNTRL_C
| NONEOS_C
,
785 /* 8 \b */ CNTRL_C
| CHAN_C
| NONEOS_C
,
786 /* 9 \t */ CNTRL_C
| SPACE_C
| CHAN_C
| NONEOS_C
,
787 /* 10 \n */ CNTRL_C
| SPACE_C
| CHAN_C
| NONEOS_C
| EOL_C
,
788 /* 11 \v */ CNTRL_C
| SPACE_C
| CHAN_C
| NONEOS_C
,
789 /* 12 \f */ CNTRL_C
| SPACE_C
| CHAN_C
| NONEOS_C
,
790 /* 13 \r */ CNTRL_C
| SPACE_C
| CHAN_C
| NONEOS_C
| EOL_C
,
791 /* 14 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
792 /* 15 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
793 /* 16 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
794 /* 17 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
795 /* 18 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
796 /* 19 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
797 /* 20 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
798 /* 21 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
799 /* 22 */ CNTRL_C
| CHAN_C
| FCHAN_C
| NONEOS_C
,
800 /* 23 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
801 /* 24 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
802 /* 25 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
803 /* 26 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
804 /* 27 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
805 /* 28 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
806 /* 29 */ CNTRL_C
| CHAN_C
| FCHAN_C
| NONEOS_C
,
807 /* 30 */ CNTRL_C
| CHAN_C
| NONEOS_C
,
808 /* 31 */ CNTRL_C
| CHAN_C
| FCHAN_C
| NONEOS_C
,
809 /* SP */ PRINT_C
| SPACE_C
,
810 /* ! */ PRINT_C
| KWILD_C
| CHAN_C
| NONEOS_C
,
811 /* " */ PRINT_C
| CHAN_C
| NONEOS_C
,
812 /* # */ PRINT_C
| MWILD_C
| CHANPFX_C
| CHAN_C
| NONEOS_C
,
813 /* $ */ PRINT_C
| CHAN_C
| NONEOS_C
,
814 /* % */ PRINT_C
| CHAN_C
| NONEOS_C
,
815 /* & */ PRINT_C
| CHANPFX_C
| CHAN_C
| NONEOS_C
,
816 /* ' */ PRINT_C
| CHAN_C
| NONEOS_C
,
817 /* ( */ PRINT_C
| CHAN_C
| NONEOS_C
,
818 /* ) */ PRINT_C
| CHAN_C
| NONEOS_C
,
819 /* * */ PRINT_C
| KWILD_C
| MWILD_C
| CHAN_C
| NONEOS_C
,
820 /* + */ PRINT_C
| CHAN_C
| NONEOS_C
,
821 /* , */ PRINT_C
| NONEOS_C
,
822 /* - */ PRINT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
823 /* . */ PRINT_C
| KWILD_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
| SERV_C
,
824 /* / */ PRINT_C
| CHAN_C
| NONEOS_C
| HOST_C
,
825 /* 0 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
826 /* 1 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
827 /* 2 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
828 /* 3 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
829 /* 4 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
830 /* 5 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
831 /* 6 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
832 /* 7 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
833 /* 8 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
834 /* 9 */ PRINT_C
| DIGIT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
835 /* : */ PRINT_C
| CHAN_C
| NONEOS_C
| HOST_C
,
836 /* ; */ PRINT_C
| CHAN_C
| NONEOS_C
,
837 /* < */ PRINT_C
| CHAN_C
| NONEOS_C
,
838 /* = */ PRINT_C
| CHAN_C
| NONEOS_C
,
839 /* > */ PRINT_C
| CHAN_C
| NONEOS_C
,
840 /* ? */ PRINT_C
| KWILD_C
| MWILD_C
| CHAN_C
| NONEOS_C
,
841 /* @ */ PRINT_C
| KWILD_C
| MWILD_C
| CHAN_C
| NONEOS_C
,
842 /* A */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
843 /* B */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
844 /* C */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
845 /* D */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
846 /* E */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
847 /* F */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
848 /* G */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
849 /* H */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
850 /* I */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
851 /* J */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
852 /* K */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
853 /* L */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
854 /* M */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
855 /* N */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
856 /* O */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
857 /* P */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
858 /* Q */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
859 /* R */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
860 /* S */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
861 /* T */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
862 /* U */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
863 /* V */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
864 /* W */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
865 /* X */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
866 /* Y */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
867 /* Z */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
868 /* [ */ PRINT_C
| ALPHA_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
869 /* \ */ PRINT_C
| ALPHA_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
870 /* ] */ PRINT_C
| ALPHA_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
871 /* ^ */ PRINT_C
| ALPHA_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
872 /* _ */ PRINT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
873 /* ` */ PRINT_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
874 /* a */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
875 /* b */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
876 /* c */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
877 /* d */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
878 /* e */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
879 /* f */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
880 /* g */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
881 /* h */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
882 /* i */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
883 /* j */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
884 /* k */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
885 /* l */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
886 /* m */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
887 /* n */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
888 /* o */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
889 /* p */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
890 /* q */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
891 /* r */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
892 /* s */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
893 /* t */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
894 /* u */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
895 /* v */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
896 /* w */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
897 /* x */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
898 /* y */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
899 /* z */ PRINT_C
| ALPHA_C
| LET_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
| HOST_C
,
900 /* { */ PRINT_C
| ALPHA_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
901 /* | */ PRINT_C
| ALPHA_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
902 /* } */ PRINT_C
| ALPHA_C
| NICK_C
| CHAN_C
| NONEOS_C
| USER_C
,
903 /* ~ */ PRINT_C
| ALPHA_C
| CHAN_C
| NONEOS_C
| USER_C
,
904 /* del */ CHAN_C
| NONEOS_C
,
905 /* 0x80 */ CHAN_C
| NONEOS_C
,
906 /* 0x81 */ CHAN_C
| NONEOS_C
,
907 /* 0x82 */ CHAN_C
| NONEOS_C
,
908 /* 0x83 */ CHAN_C
| NONEOS_C
,
909 /* 0x84 */ CHAN_C
| NONEOS_C
,
910 /* 0x85 */ CHAN_C
| NONEOS_C
,
911 /* 0x86 */ CHAN_C
| NONEOS_C
,
912 /* 0x87 */ CHAN_C
| NONEOS_C
,
913 /* 0x88 */ CHAN_C
| NONEOS_C
,
914 /* 0x89 */ CHAN_C
| NONEOS_C
,
915 /* 0x8A */ CHAN_C
| NONEOS_C
,
916 /* 0x8B */ CHAN_C
| NONEOS_C
,
917 /* 0x8C */ CHAN_C
| NONEOS_C
,
918 /* 0x8D */ CHAN_C
| NONEOS_C
,
919 /* 0x8E */ CHAN_C
| NONEOS_C
,
920 /* 0x8F */ CHAN_C
| NONEOS_C
,
921 /* 0x90 */ CHAN_C
| NONEOS_C
,
922 /* 0x91 */ CHAN_C
| NONEOS_C
,
923 /* 0x92 */ CHAN_C
| NONEOS_C
,
924 /* 0x93 */ CHAN_C
| NONEOS_C
,
925 /* 0x94 */ CHAN_C
| NONEOS_C
,
926 /* 0x95 */ CHAN_C
| NONEOS_C
,
927 /* 0x96 */ CHAN_C
| NONEOS_C
,
928 /* 0x97 */ CHAN_C
| NONEOS_C
,
929 /* 0x98 */ CHAN_C
| NONEOS_C
,
930 /* 0x99 */ CHAN_C
| NONEOS_C
,
931 /* 0x9A */ CHAN_C
| NONEOS_C
,
932 /* 0x9B */ CHAN_C
| NONEOS_C
,
933 /* 0x9C */ CHAN_C
| NONEOS_C
,
934 /* 0x9D */ CHAN_C
| NONEOS_C
,
935 /* 0x9E */ CHAN_C
| NONEOS_C
,
936 /* 0x9F */ CHAN_C
| NONEOS_C
,
937 /* 0xA0 */ CHAN_C
| FCHAN_C
| NONEOS_C
,
938 /* 0xA1 */ CHAN_C
| NONEOS_C
,
939 /* 0xA2 */ CHAN_C
| NONEOS_C
,
940 /* 0xA3 */ CHAN_C
| NONEOS_C
,
941 /* 0xA4 */ CHAN_C
| NONEOS_C
,
942 /* 0xA5 */ CHAN_C
| NONEOS_C
,
943 /* 0xA6 */ CHAN_C
| NONEOS_C
,
944 /* 0xA7 */ CHAN_C
| NONEOS_C
,
945 /* 0xA8 */ CHAN_C
| NONEOS_C
,
946 /* 0xA9 */ CHAN_C
| NONEOS_C
,
947 /* 0xAA */ CHAN_C
| NONEOS_C
,
948 /* 0xAB */ CHAN_C
| NONEOS_C
,
949 /* 0xAC */ CHAN_C
| NONEOS_C
,
950 /* 0xAD */ CHAN_C
| NONEOS_C
,
951 /* 0xAE */ CHAN_C
| NONEOS_C
,
952 /* 0xAF */ CHAN_C
| NONEOS_C
,
953 /* 0xB0 */ CHAN_C
| NONEOS_C
,
954 /* 0xB1 */ CHAN_C
| NONEOS_C
,
955 /* 0xB2 */ CHAN_C
| NONEOS_C
,
956 /* 0xB3 */ CHAN_C
| NONEOS_C
,
957 /* 0xB4 */ CHAN_C
| NONEOS_C
,
958 /* 0xB5 */ CHAN_C
| NONEOS_C
,
959 /* 0xB6 */ CHAN_C
| NONEOS_C
,
960 /* 0xB7 */ CHAN_C
| NONEOS_C
,
961 /* 0xB8 */ CHAN_C
| NONEOS_C
,
962 /* 0xB9 */ CHAN_C
| NONEOS_C
,
963 /* 0xBA */ CHAN_C
| NONEOS_C
,
964 /* 0xBB */ CHAN_C
| NONEOS_C
,
965 /* 0xBC */ CHAN_C
| NONEOS_C
,
966 /* 0xBD */ CHAN_C
| NONEOS_C
,
967 /* 0xBE */ CHAN_C
| NONEOS_C
,
968 /* 0xBF */ CHAN_C
| NONEOS_C
,
969 /* 0xC0 */ CHAN_C
| NONEOS_C
,
970 /* 0xC1 */ CHAN_C
| NONEOS_C
,
971 /* 0xC2 */ CHAN_C
| NONEOS_C
,
972 /* 0xC3 */ CHAN_C
| NONEOS_C
,
973 /* 0xC4 */ CHAN_C
| NONEOS_C
,
974 /* 0xC5 */ CHAN_C
| NONEOS_C
,
975 /* 0xC6 */ CHAN_C
| NONEOS_C
,
976 /* 0xC7 */ CHAN_C
| NONEOS_C
,
977 /* 0xC8 */ CHAN_C
| NONEOS_C
,
978 /* 0xC9 */ CHAN_C
| NONEOS_C
,
979 /* 0xCA */ CHAN_C
| NONEOS_C
,
980 /* 0xCB */ CHAN_C
| NONEOS_C
,
981 /* 0xCC */ CHAN_C
| NONEOS_C
,
982 /* 0xCD */ CHAN_C
| NONEOS_C
,
983 /* 0xCE */ CHAN_C
| NONEOS_C
,
984 /* 0xCF */ CHAN_C
| NONEOS_C
,
985 /* 0xD0 */ CHAN_C
| NONEOS_C
,
986 /* 0xD1 */ CHAN_C
| NONEOS_C
,
987 /* 0xD2 */ CHAN_C
| NONEOS_C
,
988 /* 0xD3 */ CHAN_C
| NONEOS_C
,
989 /* 0xD4 */ CHAN_C
| NONEOS_C
,
990 /* 0xD5 */ CHAN_C
| NONEOS_C
,
991 /* 0xD6 */ CHAN_C
| NONEOS_C
,
992 /* 0xD7 */ CHAN_C
| NONEOS_C
,
993 /* 0xD8 */ CHAN_C
| NONEOS_C
,
994 /* 0xD9 */ CHAN_C
| NONEOS_C
,
995 /* 0xDA */ CHAN_C
| NONEOS_C
,
996 /* 0xDB */ CHAN_C
| NONEOS_C
,
997 /* 0xDC */ CHAN_C
| NONEOS_C
,
998 /* 0xDD */ CHAN_C
| NONEOS_C
,
999 /* 0xDE */ CHAN_C
| NONEOS_C
,
1000 /* 0xDF */ CHAN_C
| NONEOS_C
,
1001 /* 0xE0 */ CHAN_C
| NONEOS_C
,
1002 /* 0xE1 */ CHAN_C
| NONEOS_C
,
1003 /* 0xE2 */ CHAN_C
| NONEOS_C
,
1004 /* 0xE3 */ CHAN_C
| NONEOS_C
,
1005 /* 0xE4 */ CHAN_C
| NONEOS_C
,
1006 /* 0xE5 */ CHAN_C
| NONEOS_C
,
1007 /* 0xE6 */ CHAN_C
| NONEOS_C
,
1008 /* 0xE7 */ CHAN_C
| NONEOS_C
,
1009 /* 0xE8 */ CHAN_C
| NONEOS_C
,
1010 /* 0xE9 */ CHAN_C
| NONEOS_C
,
1011 /* 0xEA */ CHAN_C
| NONEOS_C
,
1012 /* 0xEB */ CHAN_C
| NONEOS_C
,
1013 /* 0xEC */ CHAN_C
| NONEOS_C
,
1014 /* 0xED */ CHAN_C
| NONEOS_C
,
1015 /* 0xEE */ CHAN_C
| NONEOS_C
,
1016 /* 0xEF */ CHAN_C
| NONEOS_C
,
1017 /* 0xF0 */ CHAN_C
| NONEOS_C
,
1018 /* 0xF1 */ CHAN_C
| NONEOS_C
,
1019 /* 0xF2 */ CHAN_C
| NONEOS_C
,
1020 /* 0xF3 */ CHAN_C
| NONEOS_C
,
1021 /* 0xF4 */ CHAN_C
| NONEOS_C
,
1022 /* 0xF5 */ CHAN_C
| NONEOS_C
,
1023 /* 0xF6 */ CHAN_C
| NONEOS_C
,
1024 /* 0xF7 */ CHAN_C
| NONEOS_C
,
1025 /* 0xF8 */ CHAN_C
| NONEOS_C
,
1026 /* 0xF9 */ CHAN_C
| NONEOS_C
,
1027 /* 0xFA */ CHAN_C
| NONEOS_C
,
1028 /* 0xFB */ CHAN_C
| NONEOS_C
,
1029 /* 0xFC */ CHAN_C
| NONEOS_C
,
1030 /* 0xFD */ CHAN_C
| NONEOS_C
,
1031 /* 0xFE */ CHAN_C
| NONEOS_C
,
1032 /* 0xFF */ CHAN_C
| NONEOS_C