34
|
1 |
#include <stdlib.h>
|
|
2 |
#include <string.h>
|
|
3 |
#include "main.h"
|
|
4 |
|
|
5 |
#include "filter.h"
|
|
6 |
|
|
7 |
static struct FString new_fstring()
|
|
8 |
{
|
|
9 |
fs->p = p;
|
|
10 |
fs->len = len;
|
|
11 |
fs->actual_pos = 0;
|
|
12 |
fs->next_try = (int *) malloc(
|
|
13 |
sizeof(*fs->next_try) * len);
|
|
14 |
}
|
|
15 |
|
|
16 |
static void prepare_next_try(char *str, int len, int *next_try)
|
|
17 |
{
|
|
18 |
int s; /* skip */
|
|
19 |
|
|
20 |
/* at x = next_try[s], it means how many x characters
|
|
21 |
* have we matched, if we have matched (s+1)? */
|
|
22 |
next_try[0] = 0; /* not used */
|
|
23 |
for (s = 2; s <= len; ++s)
|
|
24 |
{
|
|
25 |
int i;
|
|
26 |
/* compare [0..s-1] to [len - s, len-1] */
|
|
27 |
/* strlen(cmp) = s */
|
|
28 |
/* String compare, exit when not equal, offset in 'i' */
|
|
29 |
for(i=0; i < s; ++i)
|
|
30 |
if (str[len-s-i] != str[i])
|
|
31 |
break;
|
|
32 |
next_try[s-1] = i;
|
|
33 |
}
|
|
34 |
}
|
|
35 |
|
|
36 |
void add_fstring(struct FilterRules *fr, char *p, int len, Fcallback cb)
|
|
37 |
{
|
|
38 |
struct FString *fs;
|
|
39 |
fr->nstrings += 1;
|
|
40 |
fr->strings = (struct FString **) realloc(fr->strings,
|
|
41 |
sizeof(*fr->strings) * fr->nstrings);
|
|
42 |
if (fr->strings == 0) error("realloc failed.");
|
|
43 |
|
|
44 |
/* Fill the last created space */
|
|
45 |
fs = (struct FString *) malloc(sizeof(*fs));
|
|
46 |
fr->strings[fr->nstrings-1] = fs;
|
|
47 |
if (fs == 0) error("malloc failed.");
|
|
48 |
|
|
49 |
new_fstring(fs, p, len);
|
|
50 |
|
|
51 |
/* Prepare the next_try array */
|
|
52 |
prepare_next_try(p, len, fs->next_try);
|
|
53 |
|
|
54 |
fs->callback = cb;
|
|
55 |
|
|
56 |
/* We will keep the fbuffers allocated for the longest
|
|
57 |
* string possible */
|
|
58 |
if (len > fr->fbuffer_allocated)
|
|
59 |
{
|
|
60 |
fr->fbuffer_allocated = len;
|
|
61 |
fr->fbuffer = realloc(fr->fbuffer, len);
|
|
62 |
}
|
|
63 |
}
|
|
64 |
|
|
65 |
struct FilterRules * new_filter_rules()
|
|
66 |
{
|
|
67 |
struct FilterRules *fr;
|
|
68 |
fr = (struct FilterRules *) malloc(sizeof(*fr));
|
|
69 |
if (fr == 0) error("malloc failed.");
|
|
70 |
|
|
71 |
fr->nstrings = 0;
|
|
72 |
fr->strings = 0; /* null for realloc */
|
|
73 |
fr->fbuffer = 0;
|
|
74 |
fr->fbuffer_len = 0;
|
|
75 |
fr->fbuffer_allocated = 0;
|
|
76 |
|
|
77 |
return fr;
|
|
78 |
}
|
|
79 |
|
|
80 |
/* We want to access index even before the 'buffer' limits.
|
|
81 |
* Those are at fr->fbuffer, and referred as -X indexes. */
|
|
82 |
static int get_char(struct FilterRules *fr, const unsigned char *buffer, int pos)
|
|
83 |
{
|
|
84 |
if (pos >= 0)
|
|
85 |
return buffer[pos];
|
|
86 |
else
|
|
87 |
{
|
|
88 |
if (-pos > fr->fbuffer_len)
|
|
89 |
return -1;
|
|
90 |
return fr->fbuffer[fr->fbuffer_len - pos];
|
|
91 |
}
|
|
92 |
}
|
|
93 |
|
|
94 |
static int set_char(struct FilterRules *fr, unsigned char *buffer, int pos, int c)
|
|
95 |
{
|
|
96 |
if (pos >= 0)
|
|
97 |
{
|
|
98 |
buffer[pos] = c;
|
|
99 |
return buffer[pos];
|
|
100 |
}
|
|
101 |
else
|
|
102 |
{
|
|
103 |
if (-pos > fr->fbuffer_len)
|
|
104 |
return -1;
|
|
105 |
fr->fbuffer[fr->fbuffer_len - pos] = c;
|
|
106 |
return fr->fbuffer[fr->fbuffer_len - pos];
|
|
107 |
}
|
|
108 |
}
|
|
109 |
|
|
110 |
/* Return 1 if matches */
|
|
111 |
static int filter_string(struct FilterRules *fr, struct FString *fs,
|
|
112 |
char *obuf, int *olen, const unsigned char *buffer, int pos)
|
|
113 |
{
|
|
114 |
while (fs->actual_pos > 0 && fs->p[fs->actual_pos] != buffer[pos])
|
|
115 |
{
|
|
116 |
/* next_try maps 1..len to 0..len-1 */
|
|
117 |
fs->actual_pos = fs->next_try[fs->actual_pos-1];
|
|
118 |
}
|
|
119 |
if (fs->p[fs->actual_pos] == buffer[pos])
|
|
120 |
fs->actual_pos += 1;
|
|
121 |
if (fs->actual_pos == fs->len)
|
|
122 |
{
|
|
123 |
/* String matches */
|
|
124 |
int shift;
|
|
125 |
shift = pos - fs->len;
|
|
126 |
/* Call callback */
|
|
127 |
fs->callback(fr, fs, obuf, olen, buffer, shift);
|
|
128 |
return 1;
|
|
129 |
}
|
|
130 |
return 0;
|
|
131 |
}
|
|
132 |
|
|
133 |
static void reset_actual_pos(struct FilterRules *fr)
|
|
134 |
{
|
|
135 |
int i;
|
|
136 |
for (i=0; i < fr->nstrings; ++i)
|
|
137 |
{
|
|
138 |
struct FString *fs;
|
|
139 |
fs = fr->strings[i];
|
|
140 |
fs->actual_pos = 0;
|
|
141 |
}
|
|
142 |
}
|
|
143 |
|
|
144 |
void filter_stream(struct FilterRules *fr, char *obuf, int *olen, const char *buffer, int len)
|
|
145 |
{
|
|
146 |
int i;
|
|
147 |
|
|
148 |
int ipos;
|
|
149 |
|
|
150 |
*olen = 0;
|
|
151 |
ipos = - fr->fbuffer_len;
|
|
152 |
for(i=0; i< len; ++i)
|
|
153 |
{ /* each char */
|
|
154 |
int j;
|
|
155 |
int old_maxlen = fr->maxlen_found;
|
|
156 |
int found;
|
|
157 |
fr->maxlen_found = 0;
|
|
158 |
for (j=0; j < fr->nstrings; ++j)
|
|
159 |
{
|
|
160 |
struct FString *fs;
|
|
161 |
fs = fr->strings[j];
|
|
162 |
found = filter_string(fr, fs, obuf, olen, buffer, i);
|
|
163 |
if (found)
|
|
164 |
break;
|
|
165 |
fr->maxlen_found = max(fr->maxlen_found, fs->actual_pos);
|
|
166 |
}
|
|
167 |
/* Some chars may not be needed for the filters
|
|
168 |
* already. */
|
|
169 |
if (found)
|
|
170 |
{
|
|
171 |
reset_actual_pos(fr);
|
|
172 |
}
|
|
173 |
else
|
|
174 |
{
|
|
175 |
for(j=0; j < old_maxlen + 1 - fr->maxlen_found; ++j)
|
|
176 |
{
|
|
177 |
obuf[(*olen)++] = get_char(fr, buffer, ipos++);
|
|
178 |
}
|
|
179 |
}
|
|
180 |
}
|
|
181 |
memcpy(fr->fbuffer, buffer + len - fr->maxlen_found, fr->maxlen_found);
|
|
182 |
fr->fbuffer_len = fr->maxlen_found;
|
|
183 |
}
|
|
184 |
|
|
185 |
void filter_flush(struct FilterRules *fr, char *obuf, int *olen)
|
|
186 |
{
|
|
187 |
memcpy(obuf, fr->fbuffer, fr->fbuffer_len);
|
|
188 |
*olen = fr->fbuffer_len;
|
|
189 |
fr->fbuffer_len = 0;
|
|
190 |
}
|