comparison nss/lib/util/portreg.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 /*
6 * shexp.c: shell-like wildcard match routines
7 *
8 * See shexp.h for public documentation.
9 */
10
11 #include "seccomon.h"
12 #include "portreg.h"
13
14 /* ----------------------------- shexp_valid ------------------------------ */
15
16
17 static int
18 _valid_subexp(const char *exp, char stop1, char stop2)
19 {
20 register int x;
21 int nsc = 0; /* Number of special characters */
22 int np; /* Number of pipe characters in union */
23 int tld = 0; /* Number of tilde characters */
24
25 for (x = 0; exp[x] && (exp[x] != stop1) && (exp[x] != stop2); ++x) {
26 switch(exp[x]) {
27 case '~':
28 if(tld) /* at most one exclusion */
29 return INVALID_SXP;
30 if (stop1) /* no exclusions within unions */
31 return INVALID_SXP;
32 if (!exp[x+1]) /* exclusion cannot be last character */
33 return INVALID_SXP;
34 if (!x) /* exclusion cannot be first character */
35 return INVALID_SXP;
36 ++tld;
37 /* fall through */
38 case '*':
39 case '?':
40 case '$':
41 ++nsc;
42 break;
43 case '[':
44 ++nsc;
45 if((!exp[++x]) || (exp[x] == ']'))
46 return INVALID_SXP;
47 for(; exp[x] && (exp[x] != ']'); ++x) {
48 if(exp[x] == '\\' && !exp[++x])
49 return INVALID_SXP;
50 }
51 if(!exp[x])
52 return INVALID_SXP;
53 break;
54 case '(':
55 ++nsc;
56 if (stop1) /* no nested unions */
57 return INVALID_SXP;
58 np = -1;
59 do {
60 int t = _valid_subexp(&exp[++x], ')', '|');
61 if(t == 0 || t == INVALID_SXP)
62 return INVALID_SXP;
63 x+=t;
64 if(!exp[x])
65 return INVALID_SXP;
66 ++np;
67 } while (exp[x] == '|' );
68 if(np < 1) /* must be at least one pipe */
69 return INVALID_SXP;
70 break;
71 case ')':
72 case '|':
73 case ']':
74 return INVALID_SXP;
75 case '\\':
76 ++nsc;
77 if(!exp[++x])
78 return INVALID_SXP;
79 break;
80 default:
81 break;
82 }
83 }
84 if((!stop1) && (!nsc)) /* must be at least one special character */
85 return NON_SXP;
86 return ((exp[x] == stop1 || exp[x] == stop2) ? x : INVALID_SXP);
87 }
88
89 int
90 PORT_RegExpValid(const char *exp)
91 {
92 int x;
93
94 x = _valid_subexp(exp, '\0', '\0');
95 return (x < 0 ? x : VALID_SXP);
96 }
97
98
99 /* ----------------------------- shexp_match ----------------------------- */
100
101
102 #define MATCH 0
103 #define NOMATCH 1
104 #define ABORTED -1
105
106 static int
107 _shexp_match(const char *str, const char *exp, PRBool case_insensitive,
108 unsigned int level);
109
110 /* Count characters until we reach a NUL character or either of the
111 * two delimiter characters, stop1 or stop2. If we encounter a bracketed
112 * expression, look only for NUL or ']' inside it. Do not look for stop1
113 * or stop2 inside it. Return ABORTED if bracketed expression is unterminated.
114 * Handle all escaping.
115 * Return index in input string of first stop found, or ABORTED if not found.
116 * If "dest" is non-NULL, copy counted characters to it and NUL terminate.
117 */
118 static int
119 _scan_and_copy(const char *exp, char stop1, char stop2, char *dest)
120 {
121 register int sx; /* source index */
122 register char cc;
123
124 for (sx = 0; (cc = exp[sx]) && cc != stop1 && cc != stop2; sx++) {
125 if (cc == '\\') {
126 if (!exp[++sx])
127 return ABORTED; /* should be impossible */
128 } else if (cc == '[') {
129 while ((cc = exp[++sx]) && cc != ']') {
130 if(cc == '\\' && !exp[++sx])
131 return ABORTED;
132 }
133 if (!cc)
134 return ABORTED; /* should be impossible */
135 }
136 }
137 if (dest && sx) {
138 /* Copy all but the closing delimiter. */
139 memcpy(dest, exp, sx);
140 dest[sx] = 0;
141 }
142 return cc ? sx : ABORTED; /* index of closing delimiter */
143 }
144
145 /* On input, exp[0] is the opening parenthesis of a union.
146 * See if any of the alternatives in the union matches as a pattern.
147 * The strategy is to take each of the alternatives, in turn, and append
148 * the rest of the expression (after the closing ')' that marks the end of
149 * this union) to that alternative, and then see if the resultant expression
150 * matches the input string. Repeat this until some alternative matches,
151 * or we have an abort.
152 */
153 static int
154 _handle_union(const char *str, const char *exp, PRBool case_insensitive,
155 unsigned int level)
156 {
157 register int sx; /* source index */
158 int cp; /* source index of closing parenthesis */
159 int count;
160 int ret = NOMATCH;
161 char *e2;
162
163 /* Find the closing parenthesis that ends this union in the expression */
164 cp = _scan_and_copy(exp, ')', '\0', NULL);
165 if (cp == ABORTED || cp < 4) /* must be at least "(a|b" before ')' */
166 return ABORTED;
167 ++cp; /* now index of char after closing parenthesis */
168 e2 = (char *) PORT_Alloc(1 + strlen(exp));
169 if (!e2)
170 return ABORTED;
171 for (sx = 1; ; ++sx) {
172 /* Here, exp[sx] is one character past the preceding '(' or '|'. */
173 /* Copy everything up to the next delimiter to e2 */
174 count = _scan_and_copy(exp + sx, ')', '|', e2);
175 if (count == ABORTED || !count) {
176 ret = ABORTED;
177 break;
178 }
179 sx += count;
180 /* Append everything after closing parenthesis to e2. This is safe. */
181 strcpy(e2+count, exp+cp);
182 ret = _shexp_match(str, e2, case_insensitive, level + 1);
183 if (ret != NOMATCH || !exp[sx] || exp[sx] == ')')
184 break;
185 }
186 PORT_Free(e2);
187 if (sx < 2)
188 ret = ABORTED;
189 return ret;
190 }
191
192 /* returns 1 if val is in range from start..end, case insensitive. */
193 static int
194 _is_char_in_range(int start, int end, int val)
195 {
196 char map[256];
197 memset(map, 0, sizeof map);
198 while (start <= end)
199 map[tolower(start++)] = 1;
200 return map[tolower(val)];
201 }
202
203 static int
204 _shexp_match(const char *str, const char *exp, PRBool case_insensitive,
205 unsigned int level)
206 {
207 register int x; /* input string index */
208 register int y; /* expression index */
209 int ret,neg;
210
211 if (level > 20) /* Don't let the stack get too deep. */
212 return ABORTED;
213 for(x = 0, y = 0; exp[y]; ++y, ++x) {
214 if((!str[x]) && (exp[y] != '$') && (exp[y] != '*')) {
215 return NOMATCH;
216 }
217 switch(exp[y]) {
218 case '$':
219 if(str[x])
220 return NOMATCH;
221 --x; /* we don't want loop to increment x */
222 break;
223 case '*':
224 while(exp[++y] == '*'){}
225 if(!exp[y])
226 return MATCH;
227 while(str[x]) {
228 ret = _shexp_match(&str[x++], &exp[y], case_insensitive,
229 level + 1);
230 switch(ret) {
231 case NOMATCH:
232 continue;
233 case ABORTED:
234 return ABORTED;
235 default:
236 return MATCH;
237 }
238 }
239 if((exp[y] == '$') && (exp[y+1] == '\0') && (!str[x]))
240 return MATCH;
241 else
242 return NOMATCH;
243 case '[': {
244 int start, end = 0, i;
245 neg = ((exp[++y] == '^') && (exp[y+1] != ']'));
246 if (neg)
247 ++y;
248 i = y;
249 start = (unsigned char)(exp[i++]);
250 if (start == '\\')
251 start = (unsigned char)(exp[i++]);
252 if (isalnum(start) && exp[i++] == '-') {
253 end = (unsigned char)(exp[i++]);
254 if (end == '\\')
255 end = (unsigned char)(exp[i++]);
256 }
257 if (isalnum(end) && exp[i] == ']') {
258 /* This is a range form: a-b */
259 int val = (unsigned char)(str[x]);
260 if (end < start) { /* swap them */
261 start ^= end;
262 end ^= start;
263 start ^= end;
264 }
265 if (case_insensitive && isalpha(val)) {
266 val = _is_char_in_range(start, end, val);
267 if (neg == val)
268 return NOMATCH;
269 } else if (neg != ((val < start) || (val > end))) {
270 return NOMATCH;
271 }
272 y = i;
273 } else {
274 /* Not range form */
275 int matched = 0;
276 for (; exp[y] != ']'; y++) {
277 if (exp[y] == '\\')
278 ++y;
279 if(case_insensitive) {
280 matched |= (toupper(str[x]) == toupper(exp[y]));
281 } else {
282 matched |= (str[x] == exp[y]);
283 }
284 }
285 if (neg == matched)
286 return NOMATCH;
287 }
288 }
289 break;
290 case '(':
291 if (!exp[y+1])
292 return ABORTED;
293 return _handle_union(&str[x], &exp[y], case_insensitive, level);
294 case '?':
295 break;
296 case '|':
297 case ']':
298 case ')':
299 return ABORTED;
300 case '\\':
301 ++y;
302 /* fall through */
303 default:
304 if(case_insensitive) {
305 if(toupper(str[x]) != toupper(exp[y]))
306 return NOMATCH;
307 } else {
308 if(str[x] != exp[y])
309 return NOMATCH;
310 }
311 break;
312 }
313 }
314 return (str[x] ? NOMATCH : MATCH);
315 }
316
317 static int
318 port_RegExpMatch(const char *str, const char *xp, PRBool case_insensitive)
319 {
320 char *exp = 0;
321 int x, ret = MATCH;
322
323 if (!strchr(xp, '~'))
324 return _shexp_match(str, xp, case_insensitive, 0);
325
326 exp = PORT_Strdup(xp);
327 if(!exp)
328 return NOMATCH;
329
330 x = _scan_and_copy(exp, '~', '\0', NULL);
331 if (x != ABORTED && exp[x] == '~') {
332 exp[x++] = '\0';
333 ret = _shexp_match(str, &exp[x], case_insensitive, 0);
334 switch (ret) {
335 case NOMATCH: ret = MATCH; break;
336 case MATCH: ret = NOMATCH; break;
337 default: break;
338 }
339 }
340 if (ret == MATCH)
341 ret = _shexp_match(str, exp, case_insensitive, 0);
342
343 PORT_Free(exp);
344 return ret;
345 }
346
347
348 /* ------------------------------ shexp_cmp ------------------------------- */
349
350 int
351 PORT_RegExpSearch(const char *str, const char *exp)
352 {
353 switch(PORT_RegExpValid(exp))
354 {
355 case INVALID_SXP:
356 return -1;
357 case NON_SXP:
358 return (strcmp(exp,str) ? 1 : 0);
359 default:
360 return port_RegExpMatch(str, exp, PR_FALSE);
361 }
362 }
363
364 int
365 PORT_RegExpCaseSearch(const char *str, const char *exp)
366 {
367 switch(PORT_RegExpValid(exp))
368 {
369 case INVALID_SXP:
370 return -1;
371 case NON_SXP:
372 return (PORT_Strcasecmp(exp,str) ? 1 : 0);
373 default:
374 return port_RegExpMatch(str, exp, PR_TRUE);
375 }
376 }
377
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)