Mercurial > trustbridge > nss-cmake-static
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 |