1 /*
2 * Unreal Internet Relay Chat Daemon, 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 "struct.h"
22 #include "common.h"
23 #include "sys.h"
24
25 ID_Copyright("(C) 1990 Jarkko Oikarinen");
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 0, if match
33 * 1, if no match
34 */
35
36 #ifndef USE_LOCALE
37 u_char touppertab[], tolowertab[];
38 #define tolowertab2 tolowertab
39 #endif
40
41 #ifndef USE_LOCALE
42 #define lc(x) tolowertab2[x] /* use mylowertab, because registers are FASTER */
43 #else /* maybe in the old 4mb hard drive days but not anymore -- codemastr */
44 #define lc(x) tolower(x)
45 #endif
46
47
48 /* Match routine for special cases where escaping is needed in a normal fashion.
49 * Checks a string ('name') against a globbing(+more) pattern ('mask').
50 * Original by Douglas A Lewis (dalewis@acsu.buffalo.edu).
51 * Code based on hybrid7's version (match_esc()).
52 * Various modifications by Bram Matthys (Syzop).
53 * Instead of our previous code, this one is less optimized but actually _readable_ ;).
54 * Modifications I (Syzop) had to do vs the hybrid7 code:
55 * - Got rid of (u_char *) casts, since we already compile with
56 * chars defaulting to unsigned [or else major things break] ;).
57 * - Use 0 for match and non-zero for no match (a la strcmp), not the reverse.
58 * - Support for '_'.
59 * - Rip out support for '#'.
60 */
match_esc(const char * mask,const char * name)61 int match_esc(const char *mask, const char *name)
62 {
63 const u_char *m = mask;
64 const u_char *n = name;
65 const u_char *ma = NULL;
66 const u_char *na = name;
67
68 while(1)
69 {
70 if (*m == '*')
71 {
72 while (*m == '*') /* collapse.. */
73 m++;
74 ma = m;
75 na = n;
76 }
77
78 if (!*m)
79 {
80 if (!*n)
81 return 0;
82 if (!ma)
83 return 1;
84 for (m--; (m > (const u_char *)mask) && (*m == '?'); m--);
85 if (*m == '*')
86 return 0;
87 m = ma;
88 n = ++na;
89 } else
90 if (!*n)
91 {
92 while (*m == '*') /* collapse.. */
93 m++;
94 return (*m != 0);
95 }
96
97 if (*m != '?')
98 {
99 if (*m == '\\')
100 if (!*++m)
101 return 1; /* unfinished escape sequence */
102 if ((lc(*m) != lc(*n)) && !((*m == '_') && (*n == ' ')))
103 {
104 if (!ma)
105 return 1;
106 m = ma;
107 n = ++na;
108 } else
109 {
110 m++;
111 n++;
112 }
113 } else
114 {
115 m++;
116 n++;
117 }
118 }
119 return 1;
120 }
121
122 /** Same credit/copyright as match_esc() applies, except escaping removed.. ;p */
match2(const char * mask,const char * name)123 static inline int match2(const char *mask, const char *name)
124 {
125 const u_char *m = mask;
126 const u_char *n = name;
127 const u_char *ma = NULL;
128 const u_char *na = name;
129
130 while(1)
131 {
132 if (*m == '*')
133 {
134 while (*m == '*') /* collapse.. */
135 m++;
136 ma = m;
137 na = n;
138 }
139
140 if (!*m)
141 {
142 if (!*n)
143 return 0;
144 if (!ma)
145 return 1;
146 for (m--; (m > (const u_char *)mask) && (*m == '?'); m--);
147 if (*m == '*')
148 return 0;
149 m = ma;
150 n = ++na;
151 } else
152 if (!*n)
153 {
154 while (*m == '*') /* collapse.. */
155 m++;
156 return (*m != 0);
157 }
158
159 if ((lc(*m) != lc(*n)) && !((*m == '_') && (*n == ' ')) && (*m != '?'))
160 {
161 if (!ma)
162 return 1;
163 m = ma;
164 n = ++na;
165 } else
166 {
167 m++;
168 n++;
169 }
170 }
171 return 1;
172 }
173
174 /*
175 * collapse a pattern string into minimal components.
176 * This particular version is "in place", so that it changes the pattern
177 * which is to be reduced to a "minimal" size.
178 */
collapse(char * pattern)179 char *collapse(char *pattern)
180 {
181 char *s;
182 char *s1;
183 char *t;
184
185 s = pattern;
186
187 if (BadPtr(pattern))
188 return pattern;
189 /*
190 * Collapse all \** into \*, \*[?]+\** into \*[?]+
191 */
192 for (; *s; s++)
193 if (*s == '\\')
194 {
195 if (!*(s + 1))
196 break;
197 else
198 s++;
199 }
200 else if (*s == '*')
201 {
202 if (*(t = s1 = s + 1) == '*')
203 while (*t == '*')
204 t++;
205 else if (*t == '?')
206 for (t++, s1++; *t == '*' || *t == '?'; t++)
207 if (*t == '?')
208 *s1++ = *t;
209 while ((*s1++ = *t++))
210 ;
211 }
212 return pattern;
213 }
214
215
216 /*
217 * Case insensitive comparison of two NULL terminated strings.
218 *
219 * returns 0, if s1 equal to s2
220 * <0, if s1 lexicographically less than s2
221 * >0, if s1 lexicographically greater than s2
222 */
smycmp(const char * s1,const char * s2)223 int smycmp(const char *s1, const char *s2)
224 {
225 u_char *str1;
226 u_char *str2;
227 int res;
228
229 str1 = (u_char *)s1;
230 str2 = (u_char *)s2;
231
232 while ((res = toupper(*str1) - toupper(*str2)) == 0)
233 {
234 if (*str1 == '\0')
235 return 0;
236 str1++;
237 str2++;
238 }
239 return (res);
240 }
241
242
myncmp(const char * str1,const char * str2,int n)243 int myncmp(const char *str1, const char *str2, int n)
244 {
245 u_char *s1;
246 u_char *s2;
247 int res;
248
249 s1 = (u_char *)str1;
250 s2 = (u_char *)str2;
251
252 while ((res = toupper(*s1) - toupper(*s2)) == 0)
253 {
254 s1++;
255 s2++;
256 n--;
257 if (n == 0 || (*s1 == '\0' && *s2 == '\0'))
258 return 0;
259 }
260 return (res);
261 }
262
263 #ifndef USE_LOCALE
264 u_char tolowertab[] = {
265 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
266 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
267 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
268 0x1e, 0x1f,
269 ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
270 '*', '+', ',', '-', '.', '/',
271 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
272 ':', ';', '<', '=', '>', '?',
273 '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
274 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
275 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\', ']', '^',
276 '_',
277 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
278 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
279 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
280 0x7f,
281 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
282 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
283 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
284 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
285 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
286 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
287 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
288 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
289 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
290 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
291 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
292 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
293 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
294 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
295 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
296 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
297 };
298
299 u_char touppertab[] = {
300 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
301 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
302 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
303 0x1e, 0x1f,
304 ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
305 '*', '+', ',', '-', '.', '/',
306 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
307 ':', ';', '<', '=', '>', '?',
308 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
309 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
310 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
311 0x5f,
312 '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
313 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
314 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~',
315 0x7f,
316 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
317 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
318 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
319 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
320 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
321 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
322 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
323 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
324 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
325 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
326 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
327 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
328 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
329 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
330 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
331 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
332 };
333
334 #endif
335 u_char char_atribs[] = {
336 /* 0-7 */ CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL,
337 /* 8-12 */ CNTRL, CNTRL | SPACE, CNTRL | SPACE, CNTRL | SPACE,
338 CNTRL | SPACE,
339 /* 13-15 */ CNTRL | SPACE, CNTRL, CNTRL,
340 /* 16-23 */ CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL,
341 /* 24-31 */ CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL,
342 /* space */ PRINT | SPACE,
343 /* !"#$%&'( */ PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, PRINT,
344 /* )*+,-./ */ PRINT, PRINT, PRINT, PRINT, PRINT | ALLOW, PRINT | ALLOW,
345 PRINT,
346 /* 012 */ PRINT | DIGIT | ALLOW, PRINT | DIGIT | ALLOW,
347 PRINT | DIGIT | ALLOW,
348 /* 345 */ PRINT | DIGIT | ALLOW, PRINT | DIGIT | ALLOW,
349 PRINT | DIGIT | ALLOW,
350 /* 678 */ PRINT | DIGIT | ALLOW, PRINT | DIGIT | ALLOW,
351 PRINT | DIGIT | ALLOW,
352 /* 9:; */ PRINT | DIGIT | ALLOW, PRINT, PRINT,
353 /* <=>? */ PRINT, PRINT, PRINT, PRINT,
354 /* @ */ PRINT,
355 /* ABC */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
356 PRINT | ALPHA | ALLOW,
357 /* DEF */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
358 PRINT | ALPHA | ALLOW,
359 /* GHI */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
360 PRINT | ALPHA | ALLOW,
361 /* JKL */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
362 PRINT | ALPHA | ALLOW,
363 /* MNO */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
364 PRINT | ALPHA | ALLOW,
365 /* PQR */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
366 PRINT | ALPHA | ALLOW,
367 /* STU */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
368 PRINT | ALPHA | ALLOW,
369 /* VWX */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
370 PRINT | ALPHA | ALLOW,
371 /* YZ[ */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW, PRINT,
372 /* \]^ */ PRINT, PRINT, PRINT,
373 /* _` */ PRINT | ALLOW, PRINT,
374 /* abc */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
375 PRINT | ALPHA | ALLOW,
376 /* def */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
377 PRINT | ALPHA | ALLOW,
378 /* ghi */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
379 PRINT | ALPHA | ALLOW,
380 /* jkl */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
381 PRINT | ALPHA | ALLOW,
382 /* mno */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
383 PRINT | ALPHA | ALLOW,
384 /* pqr */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
385 PRINT | ALPHA | ALLOW,
386 /* stu */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
387 PRINT | ALPHA | ALLOW,
388 /* vwx */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
389 PRINT | ALPHA | ALLOW,
390 /* yz{ */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW, PRINT,
391 /* |}~ */ PRINT, PRINT, PRINT,
392 /* del */ 0,
393 /* 80-8f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
394 /* 90-9f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
395 /* a0-af */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
396 /* b0-bf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
397 /* c0-cf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
398 /* d0-df */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
399 /* e0-ef */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
400 /* f0-ff */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
401 };
402
403 /* Old match() */
_match(const char * mask,const char * name)404 int _match(const char *mask, const char *name) {
405 return match2(mask,name);
406 }
407
408
409 /* Old match() plus some optimizations from bahamut */
match(const char * mask,const char * name)410 int match(const char *mask, const char *name) {
411 if (mask[0] == '*' && mask[1] == '!') {
412 mask += 2;
413 while (*name != '!' && *name)
414 name++;
415 if (!*name)
416 return 1;
417 name++;
418 }
419
420 if (mask[0] == '*' && mask[1] == '@') {
421 mask += 2;
422 while (*name != '@' && *name)
423 name++;
424 if (!*name)
425 return 1;
426 name++;
427 }
428 return match2(mask,name);
429 }
430