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
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.
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 ***** */
39 * shexp.c: shell-like wildcard match routines
42 * See shexp.h for public documentation.
49 /* ----------------------------- shexp_valid ------------------------------ */
53 _valid_subexp(const char *exp
, char stop
)
60 while(exp
[x
] && (exp
[x
] != stop
)) {
63 if(tld
) return INVALID_SXP
;
73 if((!exp
[++x
]) || (exp
[x
] == ']'))
75 for(++x
;exp
[x
] && (exp
[x
] != ']');++x
)
87 for(y
=x
;(exp
[y
]) && (exp
[y
] != '|') && (exp
[y
] != ')');++y
)
95 t
= _valid_subexp(&exp
[x
],exp
[y
]);
117 if((!stop
) && (!nsc
))
119 return ((exp
[x
] == stop
) ? x
: INVALID_SXP
);
123 PORT_RegExpValid(const char *exp
)
127 x
= _valid_subexp(exp
, '\0');
128 return (x
< 0 ? x
: VALID_SXP
);
132 /* ----------------------------- shexp_match ----------------------------- */
139 static int _shexp_match(const char *str
, const char *exp
, PRBool case_insensitive
);
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;
149 for(cp
=1;exp
[cp
] != ')';cp
++)
152 for(p2
= 0;(exp
[p1
] != '|') && (p1
!= cp
);p1
++,p2
++) {
154 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
) {
172 _shexp_match(const char *str
, const char *exp
, PRBool case_insensitive
)
178 for(x
=0,y
=0;exp
[y
];++y
,++x
) {
179 if((!str
[x
]) && (exp
[y
] != '(') && (exp
[y
] != '$') && (exp
[y
] != '*'))
187 --x
; /* we don't want loop to increment x */
190 while(exp
[++y
] == '*'){}
194 switch(_shexp_match(&str
[x
++],&exp
[y
], case_insensitive
)) {
205 if((exp
[y
] == '$') && (exp
[y
+1] == '\0') && (!str
[x
]))
211 neg
= ((exp
[++y
] == '^') && (exp
[y
+1] != ']'));
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
))) {
230 for (matched
=0;exp
[y
] != ']';y
++)
231 matched
|= (str
[x
] == exp
[y
]);
232 if (neg
^ (!matched
))
237 return _handle_union(&str
[x
],&exp
[y
], case_insensitive
);
246 if(toupper(str
[x
]) != toupper(exp
[y
]))
260 return (ret
? ret
: (str
[x
] ? NOMATCH
: MATCH
));
264 port_RegExpMatch(const char *str
, const char *xp
, PRBool case_insensitive
) {
268 exp
= PORT_Strdup(xp
);
273 for(x
=strlen(exp
)-1;x
;--x
) {
274 if((exp
[x
] == '~') && (exp
[x
-1] != '\\')) {
276 if(_shexp_match(str
,&exp
[++x
], case_insensitive
) == MATCH
)
281 if(_shexp_match(str
,exp
, case_insensitive
) == MATCH
) {
292 /* ------------------------------ shexp_cmp ------------------------------- */
295 PORT_RegExpSearch(const char *str
, const char *exp
)
297 switch(PORT_RegExpValid(exp
))
302 return (strcmp(exp
,str
) ? 1 : 0);
304 return port_RegExpMatch(str
, exp
, PR_FALSE
);
309 PORT_RegExpCaseSearch(const char *str
, const char *exp
)
311 switch(PORT_RegExpValid(exp
))
316 return (PORT_Strcasecmp(exp
,str
) ? 1 : 0);
318 return port_RegExpMatch(str
, exp
, PR_TRUE
);