25 |
|
#include "client.h" |
26 |
|
#include "ircd.h" |
27 |
|
|
28 |
– |
/* Fix "statement not reached" warnings on Sun WorkShop C */ |
29 |
– |
#ifdef __SUNPRO_C |
30 |
– |
# pragma error_messages(off, E_STATEMENT_NOT_REACHED) |
31 |
– |
#endif |
32 |
– |
|
33 |
– |
/* match() |
34 |
– |
* |
35 |
– |
* Compare if a given string (name) matches the given |
36 |
– |
* mask (which can contain wild cards: '*' - match any |
37 |
– |
* number of chars, '?' - match any single character. |
38 |
– |
* |
39 |
– |
* return 1, if match |
40 |
– |
* 0, if no match |
41 |
– |
* |
42 |
– |
* Originally by Douglas A Lewis (dalewis@acsu.buffalo.edu) |
43 |
– |
*/ |
44 |
– |
int |
45 |
– |
match(const char *mask, const char *name) |
46 |
– |
{ |
47 |
– |
const unsigned char *m = (const unsigned char *)mask; |
48 |
– |
const unsigned char *n = (const unsigned char *)name; |
49 |
– |
const unsigned char *ma = NULL; |
50 |
– |
const unsigned char *na = (const unsigned char *)name; |
51 |
– |
|
52 |
– |
assert(mask != NULL); |
53 |
– |
assert(name != NULL); |
54 |
– |
|
55 |
– |
while (1) |
56 |
– |
{ |
57 |
– |
if (*m == '*') |
58 |
– |
{ |
59 |
– |
while (*m == '*') |
60 |
– |
m++; |
61 |
– |
ma = m; |
62 |
– |
na = n; |
63 |
– |
} |
64 |
– |
|
65 |
– |
if (!*m) |
66 |
– |
{ |
67 |
– |
if (!*n) |
68 |
– |
return 0; |
69 |
– |
if (!ma) |
70 |
– |
return 1; |
71 |
– |
for (m--; (m > (const unsigned char *)mask) && (*m == '?'); m--) |
72 |
– |
; |
73 |
– |
if (*m == '*') |
74 |
– |
return 0; |
75 |
– |
m = ma; |
76 |
– |
n = ++na; |
77 |
– |
} |
78 |
– |
else if (!*n) |
79 |
– |
{ |
80 |
– |
while (*m == '*') |
81 |
– |
m++; |
82 |
– |
return *m != '\0'; |
83 |
– |
} |
84 |
– |
|
85 |
– |
if (ToLower(*m) != ToLower(*n) && *m != '?' && (*m != '#' || !IsDigit(*n))) |
86 |
– |
{ |
87 |
– |
if (!ma) |
88 |
– |
return 1; |
89 |
– |
m = ma; |
90 |
– |
n = ++na; |
91 |
– |
} |
92 |
– |
else |
93 |
– |
m++, n++; |
94 |
– |
} |
95 |
– |
|
96 |
– |
return 1; |
97 |
– |
} |
28 |
|
|
29 |
< |
/* match_esc() |
30 |
< |
* |
31 |
< |
* The match() function with support for escaping characters such |
32 |
< |
* as '*' and '?' |
29 |
> |
/*! \brief Check a string against a mask. |
30 |
> |
* This test checks using traditional IRC wildcards only: '*' means |
31 |
> |
* match zero or more characters of any type; '?' means match exactly |
32 |
> |
* one character of any type. A backslash escapes the next character |
33 |
> |
* so that a wildcard may be matched exactly. |
34 |
> |
* param mask Wildcard-containing mask. |
35 |
> |
* param name String to check against \a mask. |
36 |
> |
* return Zero if \a mask matches \a name, non-zero if no match. |
37 |
|
*/ |
38 |
|
int |
39 |
< |
match_esc(const char *mask, const char *name) |
39 |
> |
match(const char *mask, const char *name) |
40 |
|
{ |
41 |
< |
const unsigned char *m = (const unsigned char *)mask; |
42 |
< |
const unsigned char *n = (const unsigned char *)name; |
43 |
< |
const unsigned char *ma = NULL; |
110 |
< |
const unsigned char *na = (const unsigned char *)name; |
111 |
< |
|
112 |
< |
assert(mask != NULL); |
113 |
< |
assert(name != NULL); |
41 |
> |
const char *m = mask, *n = name; |
42 |
> |
const char *m_tmp = mask, *n_tmp = name; |
43 |
> |
int star = 0; |
44 |
|
|
45 |
|
while (1) |
46 |
|
{ |
47 |
< |
if (*m == '*') |
47 |
> |
switch (*m) |
48 |
|
{ |
49 |
< |
while (*m == '*') |
49 |
> |
case '\0': |
50 |
> |
if (!*n) |
51 |
> |
return 0; |
52 |
> |
backtrack: |
53 |
> |
if (m_tmp == mask) |
54 |
> |
return 1; |
55 |
> |
m = m_tmp; |
56 |
> |
n = ++n_tmp; |
57 |
> |
if (*n == '\0') |
58 |
> |
return 1; |
59 |
> |
break; |
60 |
> |
case '\\': |
61 |
|
m++; |
62 |
< |
ma = m; |
63 |
< |
na = n; |
64 |
< |
} |
62 |
> |
/* allow escaping to force capitalization */ |
63 |
> |
if (*m++ != *n++) |
64 |
> |
goto backtrack; |
65 |
> |
break; |
66 |
> |
case '*': |
67 |
> |
case '?': |
68 |
> |
for (star = 0; ; m++) |
69 |
> |
{ |
70 |
> |
if (*m == '*') |
71 |
> |
star = 1; |
72 |
> |
else if (*m == '?') |
73 |
> |
{ |
74 |
> |
if (!*n++) |
75 |
> |
goto backtrack; |
76 |
> |
} |
77 |
> |
else |
78 |
> |
break; |
79 |
> |
} |
80 |
|
|
81 |
< |
if (!*m) |
82 |
< |
{ |
83 |
< |
if (!*n) |
84 |
< |
return 0; |
85 |
< |
if (!ma) |
86 |
< |
return 1; |
87 |
< |
for (m--; (m > (const unsigned char *)mask) && (*m == '?'); m--) |
88 |
< |
; |
89 |
< |
if (*m == '*') |
90 |
< |
return 0; |
91 |
< |
m = ma; |
92 |
< |
n = ++na; |
93 |
< |
} |
94 |
< |
else if (!*n) |
95 |
< |
{ |
96 |
< |
while (*m == '*') |
81 |
> |
if (star) |
82 |
> |
{ |
83 |
> |
if (!*m) |
84 |
> |
return 0; |
85 |
> |
else if (*m == '\\') |
86 |
> |
{ |
87 |
> |
m_tmp = ++m; |
88 |
> |
if (!*m) |
89 |
> |
return 1; |
90 |
> |
for (n_tmp = n; *n && *n != *m; n++) |
91 |
> |
; |
92 |
> |
} |
93 |
> |
else |
94 |
> |
{ |
95 |
> |
m_tmp = m; |
96 |
> |
for (n_tmp = n; *n && ToLower(*n) != ToLower(*m); n++) |
97 |
> |
; |
98 |
> |
} |
99 |
> |
} |
100 |
> |
/* and fall through */ |
101 |
> |
default: |
102 |
> |
if (!*n) |
103 |
> |
return *m != '\0'; |
104 |
> |
if (ToLower(*m) != ToLower(*n)) |
105 |
> |
goto backtrack; |
106 |
|
m++; |
107 |
< |
return *m != '\0'; |
108 |
< |
} |
144 |
< |
|
145 |
< |
if (*m != '?' && (*m != '#' || IsDigit(*n))) |
146 |
< |
{ |
147 |
< |
if (*m == '\\') |
148 |
< |
if (!*++m) |
149 |
< |
return 1; |
150 |
< |
if (ToLower(*m) != ToLower(*n)) |
151 |
< |
{ |
152 |
< |
if (!ma) |
153 |
< |
return 1; |
154 |
< |
m = ma; |
155 |
< |
n = ++na; |
156 |
< |
} |
157 |
< |
else |
158 |
< |
m++, n++; |
107 |
> |
n++; |
108 |
> |
break; |
109 |
|
} |
160 |
– |
else |
161 |
– |
m++, n++; |
110 |
|
} |
111 |
|
|
112 |
|
return 1; |
113 |
|
} |
114 |
|
|
167 |
– |
/* match_chan() |
168 |
– |
* |
169 |
– |
* The match_esc() function doing channel prefix auto-escape, |
170 |
– |
* ie. mask: #blah*blah is seen like \#blah*blah |
171 |
– |
*/ |
172 |
– |
int |
173 |
– |
match_chan(const char *mask, const char *name) |
174 |
– |
{ |
175 |
– |
if (*mask == '#') |
176 |
– |
{ |
177 |
– |
if (*name != '#') |
178 |
– |
return 0; |
179 |
– |
++name, ++mask; |
180 |
– |
} |
181 |
– |
|
182 |
– |
return match_esc(mask, name) == 0; |
183 |
– |
} |
184 |
– |
|
115 |
|
/* |
116 |
|
* collapse() |
117 |
|
* Collapse a pattern string into minimal components. |
331 |
|
/* SP */ PRINT_C|SPACE_C, |
332 |
|
/* ! */ PRINT_C|KWILD_C|CHAN_C|VCHAN_C|NONEOS_C, |
333 |
|
/* " */ PRINT_C|CHAN_C|VCHAN_C|NONEOS_C, |
334 |
< |
/* # */ PRINT_C|KWILD_C|MWILD_C|CHANPFX_C|CHAN_C|VCHAN_C|NONEOS_C, |
334 |
> |
/* # */ PRINT_C|KWILD_C|CHANPFX_C|CHAN_C|VCHAN_C|NONEOS_C, |
335 |
|
/* $ */ PRINT_C|CHAN_C|VCHAN_C|NONEOS_C|USER_C, |
336 |
|
/* % */ PRINT_C|CHAN_C|VCHAN_C|NONEOS_C, |
337 |
|
/* & */ PRINT_C|CHAN_C|VCHAN_C|NONEOS_C, |