ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/match.C
Revision: 1.6
Committed: Sat Sep 22 14:27:30 2007 UTC (16 years, 8 months ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +1 -407 lines
Log Message:
split up ermyth into ermyth-modules, libermyth (currently just ermyth-util) and ermyth-core

File Contents

# User Rev Content
1 pippijn 1.1 /*
2     * match.C: Casemapping and matching functions.
3 pippijn 1.5 *
4     * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team
5     * Rights to this code are as documented in COPYING.
6     *
7     *
8     * Portions of this file were derived from sources bearing the following license:
9 pippijn 1.2 * Rights to this code are documented in doc/pod/license.pod.
10 pippijn 1.4 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
11 pippijn 1.1 */
12    
13 pippijn 1.6 static char const rcsid[] = "$Id: match.C,v 1.5 2007-09-16 18:54:45 pippijn Exp $";
14 pippijn 1.1
15     #include "atheme.h"
16    
17     #define BadPtr(x) (!(x) || (*(x) == '\0'))
18    
19     #define MAX_ITERATIONS 512
20     /*
21     ** Compare if a given string (name) matches the given
22     ** mask (which can contain wild cards: '*' - match any
23     ** number of chars, '?' - match any single character.
24     **
25     ** return 0, if match
26     ** 1, if no match
27     */
28    
29     /*
30     ** match()
31     ** Iterative matching function, rather than recursive.
32     ** Written by Douglas A Lewis (dalewis@acsu.buffalo.edu)
33     */
34    
35     int
36 pippijn 1.4 match (char const * const mask, char const * const name)
37 pippijn 1.1 {
38     const u_char *m = (const u_char *) mask, *n = (const u_char *) name;
39 pippijn 1.4 char const *ma = mask, *na = name;
40 pippijn 1.1 int wild = 0, q = 0, calls = 0;
41    
42     if (!mask || !name)
43     return 1;
44    
45     /* if the mask is "*", it matches everything */
46     if ((*m == '*') && (*(m + 1) == '\0'))
47     return 0;
48    
49     while (1)
50     {
51     #ifdef MAX_ITERATIONS
52     if (calls++ > MAX_ITERATIONS)
53     break;
54     #endif
55    
56     if (*m == '*')
57     {
58     while (*m == '*')
59     m++;
60     wild = 1;
61 pippijn 1.4 ma = reinterpret_cast<char const *> (m);
62     na = reinterpret_cast<char const *> (n);
63 pippijn 1.1 }
64    
65     if (!*m)
66     {
67     if (!*n)
68     return 0;
69     for (m--; (m > (const u_char *) mask) && (*m == '?' || *m == '&' || *m == '#'); m--)
70     ;
71     if ((m > (const u_char *) mask) && (*m == '*') && (m[-1] != '\\'))
72     return 0;
73     if (!wild)
74     return 1;
75     m = (const u_char *) ma;
76     n = (const u_char *) ++na;
77     }
78     else if (!*n)
79     return 1;
80     if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?') || (m[1] == '&') || (m[1] == '#') || (m[1] == '%')))
81     {
82     m++;
83     q = 1;
84     }
85     else
86     q = 0;
87    
88     if ((ToLower (*m) != ToLower (*n)) && (((*m != '?') && !(*m == '&' && IsAlpha (*n)) && !(*m == '#' && IsDigit (*n)) && !(*m == '%' && IsNon (*n))) || q))
89     {
90     if (!wild)
91     return 1;
92     m = (const u_char *) ma;
93     n = (const u_char *) ++na;
94     }
95     else
96     {
97     if (*m)
98     m++;
99     if (*n)
100     n++;
101     }
102     }
103    
104     return 1;
105     }
106    
107    
108     /*
109     ** collapse a pattern string into minimal components.
110     ** This particular version is "in place", so that it changes the pattern
111     ** which is to be reduced to a "minimal" size.
112     */
113     char *
114     collapse (char *pattern)
115     {
116     char *s = pattern, *s1, *t;
117    
118     if (BadPtr (pattern))
119     return pattern;
120     /*
121     * Collapse all \** into \*, \*[?]+\** into \*[?]+
122     */
123     for (; *s; s++)
124     if (*s == '\\')
125     if (!*(s + 1))
126     break;
127     else
128     s++;
129     else if (*s == '*')
130     {
131     if (*(t = s1 = s + 1) == '*')
132     while (*t == '*')
133     t++;
134     else if (*t == '?')
135     for (t++, s1++; *t == '*' || *t == '?'; t++)
136     if (*t == '?')
137     *s1++ = *t;
138     while ((*s1++ = *t++))
139     ;
140     }
141     return pattern;
142     }
143    
144     /*
145     * regex_compile()
146     * Compile a regex of `pattern' and return it.
147     */
148     regex_t *
149     regex_create (char *pattern, int flags)
150     {
151     static char errmsg[BUFSIZE];
152     int errnum;
153     regex_t *preg;
154    
155     if (pattern == NULL)
156     {
157     return NULL;
158     }
159    
160 pippijn 1.4 preg = new regex_t;
161 pippijn 1.1 errnum = regcomp (preg, pattern, (flags & AREGEX_ICASE ? REG_ICASE : 0) | REG_EXTENDED);
162    
163     if (errnum != 0)
164     {
165     regerror (errnum, preg, errmsg, BUFSIZE);
166     slog (LG_ERROR, "regex_match(): %s\n", errmsg);
167     regfree (preg);
168 pippijn 1.4 delete preg;
169 pippijn 1.1 return NULL;
170     }
171    
172     return preg;
173     }
174    
175     char *
176     regex_extract (char *pattern, char **pend, int *pflags)
177     {
178     char c, *p, *p2;
179     bool backslash = false;
180    
181     c = *pattern;
182     if (isalnum (c) || isspace (c) || c == '\\')
183     return NULL;
184     p = pattern + 1;
185     while (*p != c || backslash)
186     {
187     if (*p == '\0')
188     return NULL;
189     if (backslash || *p == '\\')
190     backslash = !backslash;
191     p++;
192     }
193     p2 = p;
194     p++;
195     *pflags = 0;
196     while (*p != '\0' && *p != ' ')
197     {
198     if (*p == 'i')
199     *pflags |= AREGEX_ICASE;
200     else if (!isalnum (*p))
201     return NULL;
202     p++;
203     }
204     *pend = p;
205     *p2 = '\0';
206     return pattern + 1;
207     }
208    
209     /*
210     * regex_match()
211     * Internal wrapper API for POSIX-based regex matching.
212     * `preg' is the regex to check with, `string' needs to be checked against.
213     * Returns `true' on match, `false' else.
214     */
215     bool
216     regex_match (regex_t * preg, char *string)
217     {
218     bool retval;
219    
220     if (preg == NULL || string == NULL)
221     {
222     slog (LG_ERROR, "regex_match(): we were given NULL string or pattern, bad!");
223     return false;
224     }
225    
226     /* match it */
227     if (regexec (preg, string, 0, NULL, 0) == 0)
228     retval = true;
229     else
230     retval = false;
231    
232     return retval;
233     }
234    
235     /*
236     * regex_destroy()
237     * Perform cleanup with regex `preg', free associated memory.
238     */
239     bool
240     regex_destroy (regex_t * preg)
241     {
242     regfree (preg);
243 pippijn 1.4 delete preg;
244 pippijn 1.1 return true;
245     }