diff -r 1fdbf4170ef4 -r b8bf95b39952 src/server/shexp.c --- a/src/server/shexp.c Sun Jan 08 15:46:47 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,496 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * - * THE BSD LICENSE - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * shexp.c: shell-like wildcard match routines - * - * - * See shexp.h for public documentation. - * - * Rob McCool - * - */ - -#include /* isalpha, tolower */ - -#include "shexp.h" - - -/* - * The observant engineer will notice 2 distinct sets of functions here. - * All of the noicmp flavor of functions do case sensitive compares on all - * platforms. The other set (public set) does case insensitive compares on NT. - */ -int _shexp_match_noicmp(const char *str, const char *exp) ; - - -/* ----------------------------- shexp_valid ------------------------------ */ - - -int valid_subexp(const char *exp, char stop) -{ - register int x,y,t; - int nsc,np,tld; - - x=0;nsc=0;tld=0; - - while(exp[x] && (exp[x] != stop)) { - switch(exp[x]) { - case '~': - if(tld) return INVALID_SXP; - else ++tld; - case '*': - case '?': - case '^': - case '$': - ++nsc; - break; - case '[': - ++nsc; - if((!exp[++x]) || (exp[x] == ']')) - return INVALID_SXP; - for(++x;exp[x] && (exp[x] != ']');++x) - if(exp[x] == '\\') - if(!exp[++x]) - return INVALID_SXP; - if(!exp[x]) - return INVALID_SXP; - break; - case '(': - ++nsc; - while(1) { - if(exp[++x] == ')') - return INVALID_SXP; - for(y=x;(exp[y]) && (exp[y] != '|') && (exp[y] != ')');++y) - if(exp[y] == '\\') - if(!exp[++y]) - return INVALID_SXP; - if(!exp[y]) - return INVALID_SXP; - t = valid_subexp(&exp[x],exp[y]); - if(t == INVALID_SXP) - return INVALID_SXP; - x+=t; - if(exp[x] == ')') { - break; - } - } - break; - case ')': - case ']': - return INVALID_SXP; - case '\\': - if(!exp[++x]) - return INVALID_SXP; - default: - break; - } - ++x; - } - if((!stop) && (!nsc)) - return NON_SXP; - return ((exp[x] == stop) ? x : INVALID_SXP); -} - -NSAPI_PUBLIC int shexp_valid(const char *exp) { - int x; - - x = valid_subexp(exp, '\0'); - if (x < 0) { - if (x == INVALID_SXP) { - //NsprError::setError(PR_INVALID_ARGUMENT_ERROR, - // XP_GetAdminStr(DBT_invalidshexp)); - // TODO - } - return x; - } - return VALID_SXP; -} - - -/* ----------------------------- shexp_match ----------------------------- */ - - -#define MATCH 0 -#define NOMATCH 1 -#define ABORTED -1 - -int _shexp_match(const char *str, const char *exp); - -int handle_union(const char *str, const char *exp) -{ - char *e2 = (char *) MALLOC(sizeof(char)*strlen(exp)); - register int t,p2,p1 = 1; - int cp; - - while(1) { - for(cp=1;exp[cp] != ')';cp++) - if(exp[cp] == '\\') - ++cp; - for(p2 = 0;(exp[p1] != '|') && (p1 != cp);p1++,p2++) { - if(exp[p1] == '\\') - e2[p2++] = exp[p1++]; - e2[p2] = exp[p1]; - } - for(t=cp+1;(e2[p2] = exp[t]);++t,++p2); - if(_shexp_match(str,e2) == MATCH) { - FREE(e2); - return MATCH; - } - if(p1 == cp) { - FREE(e2); - return NOMATCH; - } - else ++p1; - } -} - -int handle_union_noicmp(const char *str, const char *exp) -{ - char *e2 = (char *) MALLOC(sizeof(char)*strlen(exp)); - register int t,p2,p1 = 1; - int cp; - - while(1) { - for(cp=1;exp[cp] != ')';cp++) - if(exp[cp] == '\\') - ++cp; - for(p2 = 0;(exp[p1] != '|') && (p1 != cp);p1++,p2++) { - if(exp[p1] == '\\') - e2[p2++] = exp[p1++]; - e2[p2] = exp[p1]; - } - for(t=cp+1;(e2[p2] = exp[t]);++t,++p2); - if(_shexp_match_noicmp(str,e2) == MATCH) { - FREE(e2); - return MATCH; - } - if(p1 == cp) { - FREE(e2); - return NOMATCH; - } - else ++p1; - } -} - -int _shexp_match(const char *str, const char *exp) -{ - register int x,y; - int ret,neg; - - ret = 0; - for(x=0,y=0;exp[y];++y,++x) { - if((!str[x]) && (exp[y] != '(') && (exp[y] != '$') && (exp[y] != '*')) - ret = ABORTED; - else { - switch(exp[y]) { - case '$': - if( (str[x]) ) - ret = NOMATCH; - else - --x; /* we don't want loop to increment x */ - break; - case '*': - while(exp[++y] == '*'); - if(!exp[y]) - return MATCH; - while(str[x]) { - switch(_shexp_match(&str[x++],&exp[y])) { - case NOMATCH: - continue; - case ABORTED: - ret = ABORTED; - break; - default: - return MATCH; - } - break; - } - if((exp[y] == '$') && (exp[y+1] == '\0') && (!str[x])) - return MATCH; - else - ret = ABORTED; - break; - case '[': - if((neg = ((exp[++y] == '^') && (exp[y+1] != ']')))) - ++y; - - if((isalnum(exp[y])) && (exp[y+1] == '-') && - (isalnum(exp[y+2])) && (exp[y+3] == ']')) - { - int start = exp[y], end = exp[y+2]; - - /* Droolproofing for pinheads not included */ - if(neg ^ ((str[x] < start) || (str[x] > end))) { - ret = NOMATCH; - break; - } - y+=3; - } - else { - int matched; - - for(matched=0;exp[y] != ']';y++) - matched |= (str[x] == exp[y]); - if(neg ^ (!matched)) - ret = NOMATCH; - } - break; - case '(': - return handle_union(&str[x],&exp[y]); - break; - case '?': - break; - case '\\': - ++y; - default: -#ifdef XP_UNIX - if(str[x] != exp[y]) -#else /* XP_WIN32 */ - if(strnicmp(str + x, exp + y, 1)) -#endif /* XP_WIN32 */ - ret = NOMATCH; - break; - } - } - if(ret) - break; - } - return (ret ? ret : (str[x] ? NOMATCH : MATCH)); -} - -int _shexp_match_noicmp(const char *str, const char *exp) -{ - register int x,y; - int ret,neg; - - ret = 0; - for(x=0,y=0;exp[y];++y,++x) { - if((!str[x]) && (exp[y] != '(') && (exp[y] != '$') && (exp[y] != '*')) - ret = ABORTED; - else { - switch(exp[y]) { - case '$': - if( (str[x]) ) - ret = NOMATCH; - else - --x; /* we don't want loop to increment x */ - break; - case '*': - while(exp[++y] == '*'); - if(!exp[y]) - return MATCH; - while(str[x]) { - switch(_shexp_match_noicmp(&str[x++],&exp[y])) { - case NOMATCH: - continue; - case ABORTED: - ret = ABORTED; - break; - default: - return MATCH; - } - break; - } - if((exp[y] == '$') && (exp[y+1] == '\0') && (!str[x])) - return MATCH; - else - ret = ABORTED; - break; - case '[': - if((neg = ((exp[++y] == '^') && (exp[y+1] != ']')))) - ++y; - - if((isalnum(exp[y])) && (exp[y+1] == '-') && - (isalnum(exp[y+2])) && (exp[y+3] == ']')) - { - int start = exp[y], end = exp[y+2]; - - /* Droolproofing for pinheads not included */ - if(neg ^ ((str[x] < start) || (str[x] > end))) { - ret = NOMATCH; - break; - } - y+=3; - } - else { - int matched; - - for(matched=0;exp[y] != ']';y++) - matched |= (str[x] == exp[y]); - if(neg ^ (!matched)) - ret = NOMATCH; - } - break; - case '(': - return handle_union_noicmp(&str[x],&exp[y]); - break; - case '?': - break; - case '\\': - ++y; - default: - if(str[x] != exp[y]) - ret = NOMATCH; - break; - } - } - if(ret) - break; - } - return (ret ? ret : (str[x] ? NOMATCH : MATCH)); -} - -NSAPI_PUBLIC int shexp_match(const char *str, const char *exp) -{ - register int x; - char *expbase = NULL; - - for(x=strlen(exp)-1;x;--x) { - if((exp[x] == '~') && (exp[x-1] != '\\')) { - /* we're done if the negative subexp matches */ - if(_shexp_match(str,&exp[x+1]) == MATCH) - return 1; - /* we're done if the only thing in front of the subexp is '*' */ - if (x == 1 && exp[0] == '*') - return 0; - /* create a copy so we can strip off the subexp */ - expbase = STRDUP(exp); - expbase[x] = '\0'; - exp = expbase; - break; - } - } - if(_shexp_match(str,exp) == MATCH) { - if (expbase) - FREE(expbase); - return 0; - } - - if (expbase) - FREE(expbase); - return 1; -} - -NSAPI_PUBLIC int shexp_match_noicmp(const char *str, const char *exp) -{ - register int x; - char *expbase = NULL; - - for(x=strlen(exp)-1;x;--x) { - if((exp[x] == '~') && (exp[x-1] != '\\')) { - /* we're done if the negative subexp matches */ - if(_shexp_match_noicmp(str,&exp[x+1]) == MATCH) - return 1; - /* we're done if the only thing in front of the subexp is '*' */ - if (x == 1 && exp[0] == '*') - return 0; - /* create a copy so we can strip off the subexp */ - expbase = STRDUP(exp); - expbase[x] = '\0'; - exp = expbase; - break; - } - } - if(_shexp_match_noicmp(str,exp) == MATCH) { - if (expbase) - FREE(expbase); - return 0; - } - - if (expbase) - FREE(expbase); - return 1; -} - -/* ------------------------------ shexp_cmp ------------------------------- */ - - -NSAPI_PUBLIC int shexp_cmp(const char *str, const char *exp) -{ - switch(shexp_valid(exp)) { - case INVALID_SXP: - return -1; - case NON_SXP: -#ifdef XP_UNIX - return (strcmp(exp,str) ? 1 : 0); -#else /* XP_WIN32 */ - return (stricmp(exp,str) ? 1 : 0); -#endif /* XP_WIN32 */ - default: - return shexp_match(str, exp); - } -} - -/* ------------------------------ shexp_cmp ------------------------------- */ - -NSAPI_PUBLIC int shexp_noicmp(const char *str, const char *exp) -{ - switch(shexp_valid(exp)) { - case INVALID_SXP: - return -1; - case NON_SXP: - return (strcmp(exp,str) ? 1 : 0); - default: - return shexp_match_noicmp(str, exp); - } -} - -/* ---------------------------- shexp_casecmp ----------------------------- */ - - -NSAPI_PUBLIC int shexp_casecmp(const char *str, const char *exp) -{ - char *lstr = STRDUP(str), *lexp = STRDUP(exp), *t; - int ret; - - for(t = lstr; *t; t++) - if(isalpha(*t)) *t = tolower(*t); - for(t = lexp; *t; t++) - if(isalpha(*t)) *t = tolower(*t); - - switch(shexp_valid(lexp)) { - case INVALID_SXP: - ret = -1; - break; - case NON_SXP: - ret = (strcmp(lexp, lstr) ? 1 : 0); - break; - default: - ret = shexp_match(lstr, lexp); - } - FREE(lstr); - FREE(lexp); - return ret; -} -