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"
/****************************************************************************/
/* 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[256];
char* p = (char*)pattern;
char* last;
const char* splat;
size_t len;
BOOL found = FALSE;
if(pattern == NULL)
return FALSE;
if(*p == ';') /* comment */
return FALSE;
if(*p == '!') { /* reverse-match */
found = TRUE;
p++;
}
if(search == NULL)
return found;
SAFECOPY(buf, p);
p = buf;
61
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
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;
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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)
{
BOOL match = FALSE;
if(*p == '!')
match = TRUE;
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)
{
uint32_t cidr;
unsigned subnet;
if(ip_addr != 0 && (cidr = parse_cidr(pattern, &subnet)) != 0)
return is_cidr_match(pattern, ip_addr, cidr, subnet);
return findstr_in_string(str, pattern);
}
/****************************************************************************/
/* Pattern matching string search of 'insearchof' in 'list'. */
/****************************************************************************/
BOOL findstr_in_list(const char* insearchof, str_list_t list)
{
return find2strs_in_list(insearchof, NULL, list);
}
/****************************************************************************/
/* Pattern matching string search of 'str1' or 'str2' in 'list'. */
/****************************************************************************/
BOOL find2strs_in_list(const char* str1, const char* str2, str_list_t list)
{
size_t index;
BOOL found=FALSE;
char* p;
uint32_t ip_addr1, ip_addr2;
if(list == NULL)
return FALSE;
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);
if(!found && str2 != NULL)
found = findstr_compare(str2, ip_addr2, p);
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);
}
/****************************************************************************/
/* Pattern matching string search of 'str1' or 'str2' in 'fname'. */
/****************************************************************************/
BOOL find2strs(const char* str1, const char* str2, const char* fname)
{
char str[256];
BOOL found=FALSE;
FILE* fp;
uint32_t ip_addr1, ip_addr2;
if(fname == NULL || *fname == '\0')
return FALSE;
if((fp=fopen(fname,"r"))==NULL)
return FALSE;
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);
if(!found && str2 != NULL)
found = findstr_compare(str2, ip_addr2, p);
if(found != (*p=='!'))
break;
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
}
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;
if((fp=fopen(fname,"r"))==NULL)
return NULL;
list=strListReadFile(fp, NULL, /* Max line length: */255);
strListModifyEach(list, process_findstr_item, /* cbdata: */NULL);
fclose(fp);
return list;
}