Use ratbox's match_esc(), this allows \s for space.

This commit is contained in:
Jilles Tjoelker 2009-03-08 02:14:26 +01:00
parent cb4ddd7268
commit 638156bac9
1 changed files with 110 additions and 85 deletions

View File

@ -178,11 +178,14 @@ int mask_match(const char *mask, const char *name)
} }
#define MATCH_MAX_CALLS 512 /* ACK! This dies when it's less that this
and we have long lines to parse */
/** Check a string against a mask. /** Check a string against a mask.
* This test checks using traditional IRC wildcards only: '*' means * This test checks using extended wildcards: '*' means match zero
* match zero or more characters of any type; '?' means match exactly * or more characters of any type; '?' means match exactly one
* one character of any type; '#' means match exactly one character * character of any type; '#' means match exactly one character that
* that is a number. * is a number; '@' means match exactly one character that is a
* letter; '\s' means match a space.
* *
* This function supports escaping, so that a wildcard may be matched * This function supports escaping, so that a wildcard may be matched
* exactly. * exactly.
@ -191,96 +194,118 @@ int mask_match(const char *mask, const char *name)
* @param[in] name String to check against \a mask. * @param[in] name String to check against \a mask.
* @return Zero if \a mask matches \a name, non-zero if no match. * @return Zero if \a mask matches \a name, non-zero if no match.
*/ */
int match_esc(const char *mask, const char *name) int
match_esc(const char *mask, const char *name)
{ {
const char *m = mask, *n = name; const unsigned char *m = (const unsigned char *)mask;
const char *m_tmp = mask, *n_tmp = name; const unsigned char *n = (const unsigned char *)name;
int star_p; const unsigned char *ma = (const unsigned char *)mask;
const unsigned char *na = (const unsigned char *)name;
int wild = 0;
int calls = 0;
int quote = 0;
int match1 = 0;
s_assert(mask != NULL); s_assert(mask != NULL);
s_assert(name != NULL); s_assert(name != NULL);
for (;;) if(!mask || !name)
return 0;
/* if the mask is "*", it matches everything */
if((*m == '*') && (*(m + 1) == '\0'))
return 1;
while(calls++ < MATCH_MAX_CALLS)
{ {
switch (*m) if(quote)
quote++;
if(quote == 3)
quote = 0;
if(*m == '\\' && !quote)
{
m++;
quote = 1;
continue;
}
if(!quote && *m == '*')
{
/*
* XXX - shouldn't need to spin here, the mask should have been
* collapsed before match is called
*/
while(*m == '*')
m++;
wild = 1;
ma = m;
na = n;
if(*m == '\\')
{
m++;
/* This means it is an invalid mask -A1kmm. */
if(!*m)
return 0;
quote++;
continue;
}
}
if(!*m)
{ {
case '\0':
if(!*n) if(!*n)
return 1; return 1;
backtrack: if(quote)
if (m_tmp == mask)
return 0; return 0;
m = m_tmp; for(m--; (m > (const unsigned char *)mask) && (*m == '?'); m--);;
n = ++n_tmp;
break; if(*m == '*' && (m > (const unsigned char *)mask))
case '\\': return 1;
m++; if(!wild)
/* allow escaping to force capitalization */ return 0;
if (*m++ != *n++) m = ma;
goto backtrack; n = ++na;
break; }
case '*': else if(!*n)
case '?':
for (star_p = 0;; m++)
{ {
if (*m == '*') /*
star_p = 1; * XXX - shouldn't need to spin here, the mask should have been
* collapsed before match is called
*/
if(quote)
return 0;
while(*m == '*')
m++;
return (*m == 0);
}
if(quote)
match1 = *m == 's' ? *n == ' ' : ToLower(*m) == ToLower(*n);
else if(*m == '?') else if(*m == '?')
{ match1 = 1;
if (!*n++) else if(*m == '@')
goto backtrack; match1 = IsLetter(*n);
}
else
break;
}
if (star_p)
{
if (!*m)
return 1;
else if (*m == '\\')
{
m_tmp = ++m;
if (!*m)
return 0;
for (n_tmp = n; *n && *n != *m; n++);
}
else if(*m == '#') else if(*m == '#')
match1 = IsDigit(*n);
else
match1 = ToLower(*m) == ToLower(*n);
if(match1)
{ {
m_tmp = m; if(*m)
for (n_tmp = n; *n && !IsDigit(*n); n++); m++;
} if(*n)
else if (*m == '@') n++;
{
m_tmp = m;
for (n_tmp = n; *n && !IsLetter(*n); n++);
} }
else else
{ {
m_tmp = m; if(!wild)
for (n_tmp = n; *n && ToLower(*n) != ToLower(*m); n++); return 0;
} m = ma;
} n = ++na;
/* and fall through */
default:
if (!*n)
return (*m != '\0' ? 0 : 1);
if (*m == '#')
{
if (!IsDigit(*n))
goto backtrack;
}
else if (*m == '@')
{
if (!IsLetter(*n))
goto backtrack;
}
else if (ToLower(*m) != ToLower(*n))
goto backtrack;
m++;
n++;
break;
} }
} }
return 0;
} }
int comp_with_mask(void *addr, void *dest, u_int mask) int comp_with_mask(void *addr, void *dest, u_int mask)