Files
undernet-cservice/Sources/match.c
2015-01-25 18:26:44 -06:00

317 lines
6.6 KiB
C

/* @(#)$Id: match.c,v 1.10 1999/03/06 19:15:34 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
#include <regex.h>
static int matchX(char *, char *);
int mycasecmp(char *s1, char *s2)
{
register unsigned char *c1 = (unsigned char *)s1, *c2 = (unsigned char *)s2;
register int d;
while (!(d = (toupper(*c1) - toupper(*c2))) && *c1)
{
c1++;
c2++;
}
return d;
}
char *strcasestr(register char *s1, char *s2)
{
register char *a, *b;
while (*s1)
{
a = s1;
b = s2;
while (*b && *a && toupper(*a) == toupper(*b))
{
a++;
b++;
}
if (!*b)
return s1;
s1++;
}
return NULL;
}
/* xmatch() returns 1 if both pat1 and pat2 can *possibly*
* match the same string. It returns 0 otherwise.
*/
int xmatch(char *pat1, char *pat2)
{
if (!strcmp(pat1, "*") || !strcmp(pat2, "*"))
return 1;
while (*pat1 && *pat2)
{
if (*pat1 == '*' && *pat2 == '*')
return (matchX(pat1 + 1, pat2 + 1) || matchX(pat2 + 1, pat1 + 1));
if (*pat1 == '*')
return matchX(pat1 + 1, pat2);
if (*pat2 == '*')
return matchX(pat2 + 1, pat1);
if (*pat1 == '?' || *pat2 == '?' || toupper(*pat1) == toupper(*pat2))
{
pat1++;
pat2++;
if ((!*pat1 && !strcmp(pat2, "*")) ||
(!*pat2 && !strcmp(pat1, "*")))
return 1;
}
else
return 0;
}
if (*pat1 || *pat2)
return 0;
return 1;
}
static int matchX(char *pat1, char *pat2)
{
do
{
if (xmatch(pat1, pat2))
return 1;
}
while (*pat2++);
return 0;
}
int match(register char *string, register char *mask)
{
char *stack[200][2] = {{NULL, NULL}};
register char type = 0;
register short quote, level = 0;
while (*string)
{
quote = 0;
switch (*mask)
{
case '*':
type = '*';
if (++level == 200)
return 0;
stack[level][0] = mask;
stack[level][1] = string;
while (*++mask == '*'); /* '*' eats any following '*' */
break;
case '\\':
quote++;
mask++;
/* no break! */
default:
if (toupper(*string) == toupper(*mask) || (*mask == '?' && !quote))
{
mask++;
}
else
{
while (stack[level][0] == NULL && --level > 0);
if (level <= 0)
return 0;
mask = stack[level][0];
string = stack[level][1];
level--;
}
string++;
}
}
while (*mask == '*') /* Skip everything that can */
mask++; /* match an empty string. */
return (*mask) ? 0 : 1;
}
/* compare() will return 1 if p1 and p2 can match the same
* nick!user@host. p1 and p2 are nick!user@host masks.
*/
int compare(char *p1, char *p2)
{
char tmp1[200], tmp2[200];
register char *s1 = tmp1, *s2 = tmp2;
register int ip1, ip2, in_uh = 0;
do
{
ip1 = ip2 = 1;
while (*p1 && *p1 != '!' && *p1 != '@')
{
if (ip1 && !isdigit(*p1) && *p1 != '.' && (*p1 != '*' || p1[1]) && (*p1 == '*' || s1 != tmp1))
ip1 = 0;
*(s1++) = *(p1++);
}
if (!in_uh && *p1 == '\0')
in_uh = 1;
while (*p2 && *p2 != '!' && *p2 != '@')
{
if (ip2 && !isdigit(*p2) && *p2 != '.' && (*p2 != '*' || p2[1]) && (*p2 == '*' || s2 != tmp2))
ip2 = 0;
*(s2++) = *(p2++);
}
*s2 = *s1 = '\0';
if (*p1 != *p2)
{
if (*p1 == '!')
{
s1 = tmp1;
if (*p1)
p1++;
while (*p1 && *p1 != '@')
{
if (ip1 && !isdigit(*p1) && *p1 != '.' && (*p1 != '*' || p1[1]) && (*p1 == '*' || s1 != tmp1))
ip1 = 0;
*(s1++) = *(p1++);
}
if (!in_uh && *p1 == '\0')
in_uh = 1;
}
else
{
s2 = tmp2;
if (*p2)
p2++;
while (*p2 && *p2 != '@')
{
if (ip2 && !isdigit(*p2) && *p2 != '.' && (*p2 != '*' || p2[1]) && (*p1 == '*' || s2 != tmp2))
ip2 = 0;
*(s2++) = *(p2++);
}
}
*s2 = *s1 = '\0';
}
if ((in_uh && ip1 != ip2) || !xmatch(tmp1, tmp2))
return 0;
if (*p1)
p1++;
if (*p2)
p2++;
s1 = tmp1;
s2 = tmp2;
}
while (*p1);
return 1;
}
int key_match(char *s, char *tok[])
{
register int k;
for (k = 0; tok[k] != NULL; k++)
{
if (!strcasestr(s, tok[k]))
return 0;
}
return 1;
}
void string_swap(char *buf, size_t size, char *orig, char *new)
{
char *ptr, *buf2;
buf2 = (char *)alloca(sizeof(char) * size);
while ((ptr = strstr((buf), orig)))
{
*ptr = '\0';
strncpy(buf2, buf, size - 1);
strncat(buf2, new, size - strlen(buf) - 1);
strncat(buf2, ptr + strlen(orig), size - strlen(buf) - strlen(new) - 1);
strcpy(buf, buf2);
}
}
/* regex_cmp() (stolen from RCSD)
* This function compares a regular expression (patern) with a string.
* Return value: 1 if there is a match
* 0 otherwise
*
* Note: if patern is NULL, the last patern that was passed to the
* function is used.
*/
#define HAVE_REGEXEC
int regex_cmp(char *patern, char *string)
{
#if defined(HAVE_REGEXEC)
static regex_t preg;
static int called_once = 0;
register int cmpv = 0, execv;
if (patern != NULL)
{
if (called_once)
regfree(&preg);
cmpv = regcomp(&preg, patern, REG_EXTENDED | REG_ICASE | REG_NOSUB);
}
called_once = 1;
if (cmpv == 0)
execv = regexec(&preg, string, 0, NULL, 0);
return cmpv ? 0 : execv ? 0 : 1;
#elif defined(HAVE_RE_EXEC)
register char *ptr;
ptr = re_comp(patern);
return ptr ? 0 : re_exec(string);
#else
#error neither re_exec() nor rexexec() :/
#endif
}
#ifdef MATCHALONE
void main(void)
{
char str1[80];
char str2[80];
puts("#1");
gets(str1);
puts("#2");
gets(str2);
printf("match: %d\n", match(str1, str2));
}
#endif