53
|
1 |
/*
|
|
2 |
Terminal Mixer - multi-point multi-user access to terminal applications
|
|
3 |
Copyright (C) 2007 LluĂs Batlle i Rossell
|
|
4 |
|
|
5 |
Please find the license in the provided COPYING file.
|
|
6 |
*/
|
34
|
7 |
#include <stdlib.h>
|
|
8 |
#include <stdio.h>
|
|
9 |
#include <string.h>
|
|
10 |
#include "main.h"
|
|
11 |
|
|
12 |
#include "filter.h"
|
|
13 |
|
|
14 |
void add_ffilter(struct FilterRules *fr, struct FFilter *ff)
|
|
15 |
{
|
|
16 |
fr->nfilters += 1;
|
|
17 |
fr->filters = (struct FFilter **) realloc(fr->filters,
|
|
18 |
sizeof(*fr->filters) * fr->nfilters);
|
|
19 |
if (fr->filters == 0) error("realloc failed.");
|
|
20 |
|
|
21 |
fr->filters[fr->nfilters-1] = ff;
|
|
22 |
ff->matched = 0;
|
|
23 |
}
|
|
24 |
|
|
25 |
struct FilterRules * new_filter_rules()
|
|
26 |
{
|
|
27 |
struct FilterRules *fr;
|
|
28 |
fr = (struct FilterRules *) malloc(sizeof(*fr));
|
|
29 |
if (fr == 0) error("malloc failed.");
|
|
30 |
|
|
31 |
fr->nfilters = 0;
|
|
32 |
fr->filters = 0; /* null for realloc */
|
|
33 |
fr->fbuffer = 0;
|
|
34 |
fr->fbuffer_len = 0;
|
|
35 |
fr->fbuffer_allocated = 0;
|
|
36 |
|
|
37 |
return fr;
|
|
38 |
}
|
|
39 |
|
|
40 |
/* We want to access index even before the 'buffer' limits.
|
|
41 |
* Those are at fr->fbuffer, and referred as -X indexes. */
|
|
42 |
static int get_char(struct FilterRules *fr, const unsigned char *buffer, int pos)
|
|
43 |
{
|
|
44 |
if (pos >= 0)
|
|
45 |
return buffer[pos];
|
|
46 |
else
|
|
47 |
{
|
|
48 |
if (-pos > fr->fbuffer_len)
|
|
49 |
return -1;
|
|
50 |
/* pos is negative */
|
|
51 |
return fr->fbuffer[fr->fbuffer_len + pos];
|
|
52 |
}
|
|
53 |
}
|
|
54 |
|
|
55 |
static int set_char(struct FilterRules *fr, unsigned char *buffer, int pos, int c)
|
|
56 |
{
|
|
57 |
if (pos >= 0)
|
|
58 |
{
|
|
59 |
buffer[pos] = c;
|
|
60 |
return buffer[pos];
|
|
61 |
}
|
|
62 |
else
|
|
63 |
{
|
|
64 |
if (-pos > fr->fbuffer_len)
|
|
65 |
return -1;
|
|
66 |
fr->fbuffer[fr->fbuffer_len - pos] = c;
|
|
67 |
return fr->fbuffer[fr->fbuffer_len - pos];
|
|
68 |
}
|
|
69 |
}
|
|
70 |
|
|
71 |
/* Return 1 if matches */
|
|
72 |
static int apply_ffilter(struct FilterRules *fr, struct FFilter *ff,
|
|
73 |
char *obuf, int *olen, const unsigned char *buffer, int pos)
|
|
74 |
{
|
|
75 |
int res;
|
|
76 |
|
|
77 |
res = ff->function(ff, buffer[pos]);
|
|
78 |
if (res)
|
|
79 |
{
|
|
80 |
/* String matches */
|
|
81 |
if (ff->callback)
|
|
82 |
{
|
|
83 |
int shift;
|
|
84 |
shift = pos - ff->matched;
|
|
85 |
/* Call callback */
|
|
86 |
ff->callback(fr, ff, obuf, olen, buffer, shift);
|
|
87 |
}
|
|
88 |
return 1;
|
|
89 |
}
|
|
90 |
return 0;
|
|
91 |
}
|
|
92 |
|
|
93 |
static void reset_matched(struct FilterRules *fr)
|
|
94 |
{
|
|
95 |
int i;
|
|
96 |
for (i=0; i < fr->nfilters; ++i)
|
|
97 |
{
|
|
98 |
struct FFilter *ff;
|
|
99 |
ff = fr->filters[i];
|
|
100 |
ff->matched = 0;
|
|
101 |
if (ff->reset)
|
|
102 |
ff->reset(ff);
|
|
103 |
}
|
|
104 |
}
|
|
105 |
|
|
106 |
void filter_stream(struct FilterRules *fr, char *obuf, int *olen, const char *buffer, int len)
|
|
107 |
{
|
|
108 |
int i;
|
|
109 |
|
|
110 |
int ipos;
|
|
111 |
int max_matched;
|
|
112 |
|
|
113 |
*olen = 0;
|
|
114 |
ipos = - fr->fbuffer_len;
|
|
115 |
max_matched = fr->fbuffer_len;
|
|
116 |
for(i=0; i< len; ++i)
|
|
117 |
{ /* each char */
|
|
118 |
int j;
|
|
119 |
int old_max_matched = max_matched;
|
|
120 |
int found = 0;
|
|
121 |
max_matched = 0;
|
|
122 |
/*printf("Try '%c'...\n", buffer[i]);*/
|
|
123 |
for (j=0; j < fr->nfilters; ++j)
|
|
124 |
{
|
|
125 |
struct FFilter *ff;
|
|
126 |
ff = fr->filters[j];
|
|
127 |
found = apply_ffilter(fr, ff, obuf, olen, buffer, i);
|
|
128 |
max_matched = max(max_matched, ff->matched);
|
|
129 |
if (found)
|
|
130 |
break;
|
|
131 |
}
|
|
132 |
/* Some chars may not be needed for the filters
|
|
133 |
* already. */
|
|
134 |
/*printf("ipos: %i\n", ipos);*/
|
|
135 |
if (found)
|
|
136 |
{
|
|
137 |
/*printf("[match!]\n");*/
|
|
138 |
reset_matched(fr);
|
|
139 |
/* The longest string will be matched, sure. Right?*/
|
|
140 |
ipos += max_matched;
|
|
141 |
max_matched = 0;
|
|
142 |
}
|
|
143 |
else
|
|
144 |
{
|
|
145 |
int freed = old_max_matched + 1 /* new char */ - max_matched;
|
|
146 |
for(j=0; j < freed; ++j)
|
|
147 |
{
|
|
148 |
obuf[(*olen)++] = get_char(fr, buffer, ipos++);
|
|
149 |
}
|
|
150 |
}
|
|
151 |
}
|
|
152 |
if (max_matched > fr->fbuffer_allocated)
|
|
153 |
{
|
|
154 |
fr->fbuffer = realloc(fr->fbuffer, max_matched);
|
|
155 |
if (fr->fbuffer == 0) error("Cannot allocate fbuffer");
|
|
156 |
}
|
|
157 |
memcpy(fr->fbuffer, buffer + len - max_matched, max_matched);
|
|
158 |
fr->fbuffer_len = max_matched;
|
|
159 |
}
|
|
160 |
|
|
161 |
void filter_flush(struct FilterRules *fr, char *obuf, int *olen)
|
|
162 |
{
|
|
163 |
memcpy(obuf, fr->fbuffer, fr->fbuffer_len);
|
|
164 |
*olen = fr->fbuffer_len;
|
|
165 |
fr->fbuffer_len = 0;
|
|
166 |
}
|