Newer
Older
/* Synchronet find string routines */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright Rob Swindell - http://www.synchro.net/copyright.html *
* *
* 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. *
* See the GNU General Public License for more details: gpl.txt or *
* http://www.fsf.org/copyleft/gpl.html *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#include "genwrap.h"
#include "findstr.h"

Rob Swindell
committed
#include "nopen.h"
/****************************************************************************/
/* Pattern matching string search of 'search' in 'pattern'. */
/* pattern matching is case-insensitive */
/* patterns beginning with ';' are comments (never match) */
/* patterns beginning with '!' are reverse-matched (returns false if match) */
/* patterns ending in '~' will match string anywhere (sub-string search) */
/* patterns ending in '^' will match left string fragment only */
/* patterns including '*' must match both left and right string fragments */
/* all other patterns are exact-match checking */
/****************************************************************************/
bool findstr_in_string(const char* search, const char* pattern)
{
char buf[FINDSTR_MAX_LINE_LEN + 1];
char* p = (char*)pattern;
char* last;
const char* splat;
size_t len;
bool found = false;
if (pattern == NULL)
if (*p == ';') /* comment */
if (*p == '!') { /* reverse-match */
p++;
}
return found;
SAFECOPY(buf, p);
p = buf;
truncsp(p);
len = strlen(p);
last = p + len - 1;
*last = '\0';
if (strcasestr(search, p) != NULL)
found = !found;
}
else if (*last == '^') {
if (strnicmp(p, search, len - 1) == 0)
found = !found;
}
else if ((splat = strchr(p, '*')) != NULL) {
int left = splat - p;
int right = len - (left + 1);
int slen = strlen(search);
if (slen < left + right)
return found;
if (strnicmp(search, p, left) == 0
&& strnicmp(p + left + 1, search + (slen - right), right) == 0)
found = !found;
}
else if (stricmp(p, search) == 0)
found = !found;
}
return found;
}
static uint32_t encode_ipv4_address(unsigned int byte[])
{
if (byte[0] > 0xff || byte[1] > 0xff || byte[2] > 0xff || byte[3] > 0xff)
return 0;
return (byte[0] << 24) | (byte[1] << 16) | (byte[2] << 8) | byte[3];
}
static uint32_t parse_ipv4_address(const char* str)
{
unsigned int byte[4];
return 0;
if (sscanf(str, "%u.%u.%u.%u", &byte[0], &byte[1], &byte[2], &byte[3]) != 4)
return 0;
return encode_ipv4_address(byte);
}
static uint32_t parse_cidr(const char* p, unsigned* subnet)
{
unsigned int byte[4];
p++;
*subnet = 0;
if (sscanf(p, "%u.%u.%u.%u/%u", &byte[0], &byte[1], &byte[2], &byte[3], subnet) != 5 || *subnet > 32)
return 0;
return encode_ipv4_address(byte);
}
static bool is_cidr_match(const char *p, uint32_t ip_addr, uint32_t cidr, unsigned subnet)
{
if (((ip_addr ^ cidr) >> (32 - subnet)) == 0)
match = !match;
return match;
}
static bool findstr_compare(const char* str, uint32_t ip_addr, const char* pattern, char* metadata)
{
uint32_t cidr;
unsigned subnet;
char buf[FINDSTR_MAX_LINE_LEN + 1];
char* p;
if ((p = strchr(buf, '\t')) != NULL) {
snprintf(metadata, FINDSTR_MAX_LINE_LEN, "%s", p);
} else {
if (ip_addr != 0 && (cidr = parse_cidr(pattern, &subnet)) != 0)
return is_cidr_match(pattern, ip_addr, cidr, subnet);
return findstr_in_string(str, buf);
}
/****************************************************************************/
/* Pattern matching string search of 'insearchof' in 'list'. */
/****************************************************************************/
bool findstr_in_list(const char* insearchof, str_list_t list, char* metadata)
{
return find2strs_in_list(insearchof, NULL, list, metadata);
}
/****************************************************************************/
/* Pattern matching string search of 'str1' or 'str2' in 'list'. */
/****************************************************************************/
bool find2strs_in_list(const char* str1, const char* str2, str_list_t list, char* metadata)
{
size_t index;
bool found = false;
char* p;
uint32_t ip_addr1, ip_addr2;
ip_addr1 = parse_ipv4_address(str1);
ip_addr2 = parse_ipv4_address(str2);
for (index = 0; list[index] != NULL; index++) {
p = list[index];
if (*p == '\0')
continue;
found = findstr_compare(str1, ip_addr1, p, metadata);
if (!found && str2 != NULL)
found = findstr_compare(str2, ip_addr2, p, metadata);
if (found != (*p == '!'))
break;
}
return found;
}
/****************************************************************************/
/* Pattern matching string search of 'insearchof' in 'fname'. */
/****************************************************************************/
bool findstr(const char* insearchof, const char* fname)
{
return find2strs(insearchof, NULL, fname, NULL);
}
/****************************************************************************/
/* Pattern matching string search of 'str1' or 'str2' in 'fname'. */
/****************************************************************************/
bool find2strs(const char* str1, const char* str2, const char* fname, char* metadata)
{
char str[FINDSTR_MAX_LINE_LEN + 1];
bool found = false;
FILE* fp;
uint32_t ip_addr1, ip_addr2;
if (fname == NULL || *fname == '\0')

Rob Swindell
committed
if ((fp = fnopen(NULL, fname, O_RDONLY)) == NULL)
ip_addr1 = parse_ipv4_address(str1);
ip_addr2 = parse_ipv4_address(str2);
while (!feof(fp) && !ferror(fp)) {
if (!fgets(str, sizeof(str), fp))
break;
char* p = str;
SKIP_WHITESPACE(p);
continue;
c_unescape_str(p);
found = findstr_compare(str1, ip_addr1, p, metadata);
if (!found && str2 != NULL)
found = findstr_compare(str2, ip_addr2, p, metadata);
if (found != (*p == '!'))
break;
}
fclose(fp);
return found;
}
static char* process_findstr_item(size_t index, char *str, void* cbdata)
{
SKIP_WHITESPACE(str);
truncnl(str);
return c_unescape_str(str);
}
/****************************************************************************/
str_list_t findstr_list(const char* fname)
{
FILE* fp;
str_list_t list;

Rob Swindell
committed
if ((fp = fnopen(NULL, fname, O_RDONLY)) == NULL)
return NULL;
list = strListReadFile(fp, NULL, FINDSTR_MAX_LINE_LEN);
strListModifyEach(list, process_findstr_item, /* cbdata: */ NULL);
fclose(fp);
return list;
}