1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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
104
105
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
|
/**
* based on event.c,v 1.1.1.1 2006/02/26 14:11:02 lordjaxom
*
* version by Midas
*
*/
#include <ctype.h>
#include <vdr/status.h>
#include "event.h"
#include "setup.h"
char* cEventBlock::duptolower(const char *s) {
char *c = strdup(s);
char *p = c;
for (; *p; ++p)
*p = tolower(*p);
return c;
}
const char* cEventBlock::LastTitle="just initialized";
const bool* cEventBlock::ReplayingRecording=false;
cEventsBlock EventsBlock;
cEventBlock::cEventBlock(void):
mRegularExp(false),
mIgnoreCase(false),
mCompiled(false),
whitelisted(false)
{
strncpy(mPattern, tr("New Entry"), sizeof(mPattern));
}
cEventBlock::cEventBlock(const char *Pattern):
mRegularExp(false),
mIgnoreCase(false),
mCompiled(false),
whitelisted(false)
{
strncpy(mPattern, Pattern, sizeof(mPattern));
}
cEventBlock::cEventBlock(const cEventBlock &Src)
{
operator=(Src);
}
cEventBlock &cEventBlock::operator=(const cEventBlock &Src)
{
printf("copy construct\n");
strcpy(mPattern, Src.mPattern);
mRegularExp = Src.mRegularExp;
mIgnoreCase = Src.mIgnoreCase;
whitelisted = Src.whitelisted;
mCompiled = false;
Compile();
return *this;
}
/*
bool cEventBlock::operator==(const cEventBlock Src) //include whitelisting?
{
bool b1=(strcmp(duptolower(mPattern),duptolower(Src.mPattern))==0);
bool b2=(mRegularExp==Src.mRegularExp);
bool b3=(mIgnoreCase==Src.mIgnoreCase);
return b1&&b2&&b3;
}
*/
cEventBlock::~cEventBlock()
{
if (mRegularExp)
regfree(&mExpression);
}
bool cEventBlock::doesMatch(const char *Event) const
{//in fact here we only check if the current event has any match in the list
//of course Event is examined according to the rules defined in the blacklist
if (mRegularExp)
return !(regexec(&mExpression, Event, 0, NULL, 0) != 0);
if (strlen(mPattern)==0) //workaround for empty patterns
{
return (strlen(Event)==0);
}
if (mIgnoreCase)
{
char *ev = cEventBlock::duptolower(Event);
char *pa = cEventBlock::duptolower(mPattern);
printf("check for %s in %s\n", pa, ev);
bool res = strstr(ev, pa) == NULL;
free(ev); free(pa);
return !res;
} else
return !(strstr(Event, mPattern) == NULL);
}
bool cEventBlock::Parse(char *s)
{
char *patternbuf=NULL;
int fields=sscanf(s,"%d:%d:%a[^\n]", &mRegularExp, &mIgnoreCase, &patternbuf);
if (!patternbuf) return true;
if (fields==3)
{
strncpy(mPattern,patternbuf,sizeof(mPattern));
char c=NULL;
int fields2=0;
if (strcmp(patternbuf,"-:")==0)//workaround if pattern empty
{
fields2=2;
c='-';
patternbuf=(char*)"";
}
else
{
if (strcmp(patternbuf,"+:")==0)
{
fields2=2;
c='+';
patternbuf=(char*)"";
} //end of workaround
else
{
free(patternbuf); //normal entry handling
fields2=sscanf(mPattern,"%1c:%a[^\n]",&c,&patternbuf);
}
}
if (fields2==2)
{
if(c=='+')
{
whitelisted=true;
}
else whitelisted=false;
strncpy(mPattern,skipspace(stripspace(patternbuf)),sizeof(mPattern));
}
else
{
whitelisted=false;
}
}
else
{ // old taste backward compatibility
strncpy(mPattern, skipspace(stripspace(s)), sizeof(mPattern));
mRegularExp = false;
mIgnoreCase = false;
whitelisted = false;
}
return Compile();
}
bool cEventBlock::Compile(void) {
mCompiled = false;
if (mRegularExp) {
if (regcomp(&mExpression, mPattern, REG_EXTENDED | (mIgnoreCase ? REG_ICASE : 0)) != 0) {
esyslog("ERROR: malformed regular expression: %s", mPattern);
return false;
} else
mCompiled = true;
}
return true;
}
bool cEventBlock::Save(FILE *f) {
char c='c';
if (whitelisted) c='+';
else c='-';
return fprintf(f, "%d:%d:%c:%s\n", mRegularExp, mIgnoreCase, c, mPattern) > 0;
}
bool cEventsBlock::Acceptable(const char *src)
{
cVector<cEventBlock*> temp_vec (5);
cEventBlock stringmatch=*(new cEventBlock("nostringmatch"));
ListMatches(src,&temp_vec,stringmatch);
if(strcmp(stringmatch.Pattern(),"nostringmatch")!=0)
{
#ifdef LOGGING
dsyslog("plugin-block: exact string match found %s: ",stringmatch.Pattern());
#endif
if (stringmatch.isWhitelisted())
{
#ifdef LOGGING
dsyslog("plugin-block: string match entry is whitelisted - returning acceptable");
#endif
cSetupBlock::LastAcceptableChannel=cDevice::CurrentChannel();
return true;
}
#ifdef LOGGING
dsyslog("plugin-block: string match entry is not whitelisted - returning not acceptable");
#endif
return false;
}
int vec_size=temp_vec.Size();
if (vec_size<1)
{
#ifdef LOGGING
dsyslog("plugin-block: no matching pattern found at all - returning acceptable");
#endif
cSetupBlock::LastAcceptableChannel=cDevice::CurrentChannel();
return true;
}
bool b=temp_vec.At(0)->isWhitelisted();
int count=1;
for(;count<vec_size;count++)
{
if (temp_vec.At(count)->isWhitelisted()!=b)
{
#ifdef LOGGING
dsyslog("plugin-block: Contradictory rules detected - returning fuzzy fallback: %d",cSetupBlock::FuzzyFallback);
#endif
b=cSetupBlock::FuzzyFallback;
if (b) cSetupBlock::LastAcceptableChannel=cDevice::CurrentChannel();
return b;
}
}
#ifdef LOGGING
dsyslog("plugin-block: Acceptable returning: %d",b);
#endif
if (b) cSetupBlock::LastAcceptableChannel=cDevice::CurrentChannel();
return b;
}
cEventsBlock &cEventsBlock::operator=(const cEventsBlock &Source) {
cList<cEventBlock>::Clear();
const cEventBlock *event = Source.First();
while (event != NULL) {
printf("transferring %p\n", event);
Add(new cEventBlock(*event));
event = Source.Next(event);
}
return *this;
}
void cEventsBlock::ListMatches(const char *title, cVector <cEventBlock*> *match_vec, cEventBlock &stringmatch)
{
cEventBlock *event = First();
char* temp_title=strdup(title);
char* temp_pattern=NULL;
while (event != NULL) {
if (event->doesMatch(title)) //doesMatch examines if there is a match according to all properties of the blacklist entry
{
#ifdef LOGGING
char *condition=(char*)(event->isWhitelisted() ? "positive" : "negative");
dsyslog("plugin-block: Matching rule detected - Pattern: '%s' (%s)",event->Pattern(),condition);
#endif
match_vec->Append(event); //put match in the vector; of course there could be more than one match
//lets say you would block everything containing the word 'Judge'
//but 'Judge Dredd' also has an explicit entry
//in case Judge Dredd is the current show then both entries would match
//therefore it is necessary to do further analysis of the type of the matches
//or the according rules and priorities respectively
if (event->IgnoreCase())//now we check if there the current match is also a stringmatching entry
//first check if ignore case is set
//if so replace the strings to be compared by their lower case pendants
//so next we only have to do one comparison
{
temp_title=cEventBlock::duptolower(temp_title);
temp_pattern=cEventBlock::duptolower(event->Pattern());
}
else
{
temp_pattern=(char*)event->Pattern();
}
if (strcmp(temp_title,temp_pattern)==0) //check for stringmatch
{
#ifdef LOGGING
dsyslog("plugin-block: ListMatches: stringmatch found '%s'",event->Pattern());
#endif
stringmatch=*event;
}
if (event->IgnoreCase())
{
free(temp_title);
free(temp_pattern);
}
}
event = Next(event);
}
}
void cEventsBlock::ListMatches(const char *title, cVector <cEventBlock*> *match_vec)
{
cEventBlock *event = First();
while (event != NULL) {
if (event->doesMatch(title))
{
match_vec->Append(event);
}
event = Next(event);
}
}
cEventBlock* cEventsBlock::hasStringMatch(const char* src, bool ignorecase)
{
cEventBlock *event_ptr=First();
char *low_src=cEventBlock::duptolower(src);
while (event_ptr!=NULL)
{
if (event_ptr->IgnoreCase() || ignorecase)
{
char *low_pattern=cEventBlock::duptolower(event_ptr->Pattern());
if (strcmp(low_src,low_pattern)==0)
{
return event_ptr;
}
}
else
{
if (strcmp(src,event_ptr->Pattern())==0)
{
return event_ptr;
}
}
event_ptr=Next(event_ptr);
}
return NULL;
}
int cEventsBlock::getIndexOf(cEventBlock *src)
{
//TODO make this a recursive method taking a list pointer and lets begin search in the middle of the list
//(middle->Previous() and middle->Next())
//find out if the first char of Pattern is less or higher than src.char etc
//once the first char of src matches begin search there straight forward
//this might speedup setting cursor to the right position (New entry) in the OSD
//NO: it turned out that the Get method of cListBase will have a serious impact on this solution
//maybe a major rewrite and/or use of STL implementations of lists or vectors etc would be a better alternative
cEventBlock* listptr=First();
int list_count=0;
const char* src_pattern=src->Pattern();
while(listptr!=NULL)
{
if (strcmp(src_pattern,listptr->Pattern())==0)
{
return list_count;
}
list_count+=1;
listptr=Next(listptr);
}
return -1;
}
|