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;
if(pattern == NULL)
if(*p == ';') /* comment */
if(*p == '!') { /* reverse-match */
p++;
}
if(search == NULL)
return found;
SAFECOPY(buf, p);
p = buf;
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
truncsp(p);
len = strlen(p);
if(len > 0) {
last = p + len - 1;
if(*last == '~') {
*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];
if(str == NULL)
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];
if(*p == '!')
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(*p == '!')
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;
SAFECOPY(buf, pattern);
if((p = strchr(buf, '\t')) != NULL) {
*p = '\0';
p++;
if(metadata != NULL)
snprintf(metadata, FINDSTR_MAX_LINE_LEN, "%s", p);
} else {
if(metadata != NULL)
*metadata = '\0';
}
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;
char* p;
uint32_t ip_addr1, ip_addr2;
if(list == NULL)
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];
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);
if(*p == '\0')
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);
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;
}