#include "cgi-private.h"
#include <regex.h>
void *
cgiCompileSearch(const char *query)
{
regex_t *re;
char *s,
*sptr,
*sword;
size_t slen;
const char *qptr,
*qend;
const char *prefix;
int quoted;
size_t wlen;
char *lword;
DEBUG_printf(("cgiCompileSearch(query=\"%s\")\n", query));
if (!query)
return (NULL);
if ((re = (regex_t *)calloc(1, sizeof(regex_t))) == NULL)
return (NULL);
slen = strlen(query) * 3;
if (slen < 1024)
slen = 1024;
if ((s = (char *)malloc(slen)) == NULL)
{
free(re);
return (NULL);
}
prefix = ".*";
qptr = query;
sptr = s;
lword = NULL;
while (*qptr)
{
while (isspace(*qptr & 255))
qptr ++;
if (!*qptr)
break;
if (*qptr == '\"' || *qptr == '\'')
{
quoted = *qptr ++;
for (qend = qptr; *qend && *qend != quoted; qend ++);
if (!*qend)
{
free(s);
free(re);
if (lword)
free(lword);
return (NULL);
}
}
else
{
quoted = 0;
for (qend = qptr + 1; *qend && !isspace(*qend); qend ++);
}
wlen = (size_t)(qend - qptr);
if (wlen == 3 && !_cups_strncasecmp(qptr, "AND", 3))
{
if (sptr > s)
prefix = ".*";
qptr = qend;
}
else if (wlen == 2 && !_cups_strncasecmp(qptr, "OR", 2))
{
if (sptr > s)
prefix = ".*|.*";
qptr = qend;
}
else
{
wlen = (size_t)(sptr - s) + 2 * 4 * wlen + 2 * strlen(prefix) + 11;
if (lword)
wlen += strlen(lword);
if (wlen > slen)
{
char *temp;
slen = wlen + 128;
temp = (char *)realloc(s, slen);
if (!temp)
{
free(s);
free(re);
if (lword)
free(lword);
return (NULL);
}
sptr = temp + (sptr - s);
s = temp;
}
memcpy(sptr, prefix, strlen(prefix) + 1);
sptr += strlen(sptr);
sword = sptr;
while (qptr < qend)
{
if (strchr("^.[$()|*+?{\\", *qptr))
*sptr++ = '\\';
*sptr++ = *qptr++;
}
*sptr = '\0';
if (!strcmp(prefix, ".*") && lword)
{
char *lword2;
if ((lword2 = strdup(sword)) == NULL)
{
free(lword);
free(s);
free(re);
return (NULL);
}
memcpy(sptr, ".*|.*", 6);
sptr += 5;
memcpy(sptr, lword2, strlen(lword2) + 1);
sptr += strlen(sptr);
memcpy(sptr, ".*", 3);
sptr += 2;
memcpy(sptr, lword, strlen(lword) + 1);
sptr += strlen(sptr);
free(lword);
lword = lword2;
}
else
{
if (lword)
free(lword);
lword = strdup(sword);
}
prefix = ".*|.*";
}
if (quoted)
qptr ++;
}
if (lword)
free(lword);
if (sptr > s)
memcpy(sptr, ".*", 3);
else
{
free(s);
free(re);
return (NULL);
}
DEBUG_printf((" s=\"%s\"\n", s));
if (regcomp(re, s, REG_EXTENDED | REG_ICASE))
{
free(re);
free(s);
return (NULL);
}
free(s);
return ((void *)re);
}
int
cgiDoSearch(void *search,
const char *text)
{
int i;
regmatch_t matches[100];
if (!search || !text)
return (0);
if (!regexec((regex_t *)search, text, sizeof(matches) / sizeof(matches[0]),
matches, 0))
{
for (i = 0; i < (int)(sizeof(matches) / sizeof(matches[0])); i ++)
if (matches[i].rm_so < 0)
break;
return (i);
}
else
return (0);
}
void
cgiFreeSearch(void *search)
{
regfree((regex_t *)search);
}