Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / util / portreg.c
blob869dab10afde75cefa885e1e828b2b6173c6c709
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Ken Key <key+mozilla@ksquared.net>
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 /*
39 * shexp.c: shell-like wildcard match routines
42 * See shexp.h for public documentation.
46 #include "seccomon.h"
47 #include "portreg.h"
49 /* ----------------------------- shexp_valid ------------------------------ */
52 static int
53 _valid_subexp(const char *exp, char stop)
55 register int x,y,t;
56 int nsc,np,tld;
58 x=0;nsc=0;tld=0;
60 while(exp[x] && (exp[x] != stop)) {
61 switch(exp[x]) {
62 case '~':
63 if(tld) return INVALID_SXP;
64 else ++tld;
65 case '*':
66 case '?':
67 case '^':
68 case '$':
69 ++nsc;
70 break;
71 case '[':
72 ++nsc;
73 if((!exp[++x]) || (exp[x] == ']'))
74 return INVALID_SXP;
75 for(++x;exp[x] && (exp[x] != ']');++x)
76 if(exp[x] == '\\')
77 if(!exp[++x])
78 return INVALID_SXP;
79 if(!exp[x])
80 return INVALID_SXP;
81 break;
82 case '(':
83 ++nsc;np = 0;
84 while(1) {
85 if(exp[++x] == ')')
86 return INVALID_SXP;
87 for(y=x;(exp[y]) && (exp[y] != '|') && (exp[y] != ')');++y)
88 if(exp[y] == '\\')
89 if(!exp[++y])
90 return INVALID_SXP;
91 if(!exp[y])
92 return INVALID_SXP;
93 if(exp[y] == '|')
94 ++np;
95 t = _valid_subexp(&exp[x],exp[y]);
96 if(t == INVALID_SXP)
97 return INVALID_SXP;
98 x+=t;
99 if(exp[x] == ')') {
100 if(!np)
101 return INVALID_SXP;
102 break;
105 break;
106 case ')':
107 case ']':
108 return INVALID_SXP;
109 case '\\':
110 if(!exp[++x])
111 return INVALID_SXP;
112 default:
113 break;
115 ++x;
117 if((!stop) && (!nsc))
118 return NON_SXP;
119 return ((exp[x] == stop) ? x : INVALID_SXP);
122 int
123 PORT_RegExpValid(const char *exp)
125 int x;
127 x = _valid_subexp(exp, '\0');
128 return (x < 0 ? x : VALID_SXP);
132 /* ----------------------------- shexp_match ----------------------------- */
135 #define MATCH 0
136 #define NOMATCH 1
137 #define ABORTED -1
139 static int _shexp_match(const char *str, const char *exp, PRBool case_insensitive);
141 static int
142 _handle_union(const char *str, const char *exp, PRBool case_insensitive)
144 char *e2 = (char *) PORT_Alloc(sizeof(char)*strlen(exp));
145 register int t,p2,p1 = 1;
146 int cp;
148 while(1) {
149 for(cp=1;exp[cp] != ')';cp++)
150 if(exp[cp] == '\\')
151 ++cp;
152 for(p2 = 0;(exp[p1] != '|') && (p1 != cp);p1++,p2++) {
153 if(exp[p1] == '\\')
154 e2[p2++] = exp[p1++];
155 e2[p2] = exp[p1];
157 for (t=cp+1; ((e2[p2] = exp[t]) != 0); ++t,++p2) {}
158 if(_shexp_match(str,e2, case_insensitive) == MATCH) {
159 PORT_Free(e2);
160 return MATCH;
162 if(p1 == cp) {
163 PORT_Free(e2);
164 return NOMATCH;
166 else ++p1;
171 static int
172 _shexp_match(const char *str, const char *exp, PRBool case_insensitive)
174 register int x,y;
175 int ret,neg;
177 ret = 0;
178 for(x=0,y=0;exp[y];++y,++x) {
179 if((!str[x]) && (exp[y] != '(') && (exp[y] != '$') && (exp[y] != '*'))
180 ret = ABORTED;
181 else {
182 switch(exp[y]) {
183 case '$':
184 if( (str[x]) )
185 ret = NOMATCH;
186 else
187 --x; /* we don't want loop to increment x */
188 break;
189 case '*':
190 while(exp[++y] == '*'){}
191 if(!exp[y])
192 return MATCH;
193 while(str[x]) {
194 switch(_shexp_match(&str[x++],&exp[y], case_insensitive)) {
195 case NOMATCH:
196 continue;
197 case ABORTED:
198 ret = ABORTED;
199 break;
200 default:
201 return MATCH;
203 break;
205 if((exp[y] == '$') && (exp[y+1] == '\0') && (!str[x]))
206 return MATCH;
207 else
208 ret = ABORTED;
209 break;
210 case '[':
211 neg = ((exp[++y] == '^') && (exp[y+1] != ']'));
212 if (neg)
213 ++y;
215 if ((isalnum(exp[y])) && (exp[y+1] == '-') &&
216 (isalnum(exp[y+2])) && (exp[y+3] == ']'))
218 int start = exp[y], end = exp[y+2];
220 /* no safeguards here */
221 if(neg ^ ((str[x] < start) || (str[x] > end))) {
222 ret = NOMATCH;
223 break;
225 y+=3;
227 else {
228 int matched;
230 for (matched=0;exp[y] != ']';y++)
231 matched |= (str[x] == exp[y]);
232 if (neg ^ (!matched))
233 ret = NOMATCH;
235 break;
236 case '(':
237 return _handle_union(&str[x],&exp[y], case_insensitive);
238 break;
239 case '?':
240 break;
241 case '\\':
242 ++y;
243 default:
244 if(case_insensitive)
246 if(toupper(str[x]) != toupper(exp[y]))
247 ret = NOMATCH;
249 else
251 if(str[x] != exp[y])
252 ret = NOMATCH;
254 break;
257 if(ret)
258 break;
260 return (ret ? ret : (str[x] ? NOMATCH : MATCH));
263 static int
264 port_RegExpMatch(const char *str, const char *xp, PRBool case_insensitive) {
265 register int x;
266 char *exp = 0;
268 exp = PORT_Strdup(xp);
270 if(!exp)
271 return 1;
273 for(x=strlen(exp)-1;x;--x) {
274 if((exp[x] == '~') && (exp[x-1] != '\\')) {
275 exp[x] = '\0';
276 if(_shexp_match(str,&exp[++x], case_insensitive) == MATCH)
277 goto punt;
278 break;
281 if(_shexp_match(str,exp, case_insensitive) == MATCH) {
282 PORT_Free(exp);
283 return 0;
286 punt:
287 PORT_Free(exp);
288 return 1;
292 /* ------------------------------ shexp_cmp ------------------------------- */
294 int
295 PORT_RegExpSearch(const char *str, const char *exp)
297 switch(PORT_RegExpValid(exp))
299 case INVALID_SXP:
300 return -1;
301 case NON_SXP:
302 return (strcmp(exp,str) ? 1 : 0);
303 default:
304 return port_RegExpMatch(str, exp, PR_FALSE);
309 PORT_RegExpCaseSearch(const char *str, const char *exp)
311 switch(PORT_RegExpValid(exp))
313 case INVALID_SXP:
314 return -1;
315 case NON_SXP:
316 return (PORT_Strcasecmp(exp,str) ? 1 : 0);
317 default:
318 return port_RegExpMatch(str, exp, PR_TRUE);