1
//Please refer to http://dansguardian.org/?page=copyright
2
//for the license for this code.
3
//Written by Daniel Barron (daniel@//jadeb/.com).
4
//For support go to http://groups.yahoo.com/group/dansguardian
6
// This program is free software; you can redistribute it and/or modify
7
// it under the terms of the GNU General Public License as published by
8
// the Free Software Foundation; either version 2 of the License, or
9
// (at your option) any later version.
11
// This program is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
// GNU General Public License for more details.
16
// You should have received a copy of the GNU General Public License
17
// along with this program; if not, write to the Free Software
18
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
#include "ListContainer.hpp"
23
#include "OptionContainer.hpp"
34
extern bool isDaemonised;
35
extern OptionContainer o;
37
ListContainer::ListContainer ():refcount (1), parent (false), filedate (0), used (false), bannedpfiledate (0), exceptionpfiledate (0), weightedpfiledate (0), sourceisexception (false), sourcestartswith (false), sourcefilters (0), data (new char[0]),
38
graphdata (new int[0]),
46
force_quick_search (0)
52
ListContainer::~ListContainer ()
59
for (unsigned int i = 0; i < morelists.size (); i++)
61
o.lm.deRefList (morelists[i]);
67
ListContainer::reset ()
71
for (unsigned int i = 0; i < morelists.size (); i++)
73
o.lm.deRefList (morelists[i]);
76
graphdata = new int[0];
84
force_quick_search = 0;
97
exceptionpfiledate = 0;
98
weightedpfiledate = 0;
101
// delete the memory block when the class is destryed
105
ListContainer::previousUseItem (const char *filename, bool startswith, int filters)
108
if (f == sourcefile && startswith == sourcestartswith && filters == sourcefilters)
117
bool ListContainer::readPhraseList (const char *filename, bool isexception)
119
sourcefile = filename;
120
sourceisexception = isexception;
121
std::string linebuffer; // a string line buffer ;)
123
temp; // a String for temporary manipulation
127
len = getFileLength (filename);
132
std::cerr << "Error reading file (does it exist?): " << filename << std::endl;
134
syslog (LOG_ERR, "%s", "Error reading file (does it exist?): ");
135
syslog (LOG_ERR, "%s", filename);
140
return true; // its blank - perhaps due to webmin editing
143
filedate = getFileDate (filename);
144
increaseMemoryBy (len + 1); // Allocate some memory to hold file
146
listfile (filename, ios::in); // open the file for reading
147
if (!listfile.good ())
151
std::cerr << "Error opening file (does it exist?): " << filename << std::endl;
153
syslog (LOG_ERR, "%s", "Error opening file (does it exist?): ");
154
syslog (LOG_ERR, "%s", filename);
157
while (!listfile.eof ())
158
{ // keep going until end of file
159
getline (listfile, linebuffer); // grab a line
160
if (linebuffer.length () != 0)
162
line = linebuffer.c_str ();
163
line.removeWhiteSpace ();
164
line.toLower (); // tidy up
165
if (line.startsWith ("<"))
167
readPhraseListHelper (line, isexception);
169
else if (line.startsWith ("."))
171
temp = line.after (".include<").before (">");
172
if (temp.length () > 0)
174
if (!readPhraseList (temp.toCharArray (), isexception))
184
return true; // sucessful read
189
ListContainer::readPhraseListHelper (String line, bool isexception)
191
int weighting = line.after ("><").before (">").toInteger ();
197
line = line.before ("><") + ">";
211
if (line.after (">,").length () > 2)
213
while (line.length () > 2)
215
line = line.after ("<");
216
readPhraseListHelper2 (line.before (">"), type + 11, weighting);
217
line = line.after (">,");
219
readPhraseListHelper2 ("", type + 21, weighting);
223
line = line.after ("<").before (">");
224
readPhraseListHelper2 (line, type, weighting);
230
ListContainer::readPhraseListHelper2 (String phrase, int type, int weighting)
235
// 10 = combination exception
236
// 11 = combination banned
237
// 12 = combination weighted
238
// 20,21,22 = end of combi marker
242
combilist.push_back (-2); // mark an end of a combi
243
combilist.push_back (type - 21); // store the combi type
244
combilist.push_back (weighting); // store the combi weight
249
if (phrase.length () > 127)
253
std::cerr << "Phrase length too long, truncating: " << phrase << std::endl;
255
syslog (LOG_ERR, "%s", "Phrase length too long, truncating:");
256
syslog (LOG_ERR, "%s", phrase.toCharArray ());
257
phrase = phrase.subString (0, 127);
260
if (phrase.length () < 1)
261
{ // its too small to use
267
if (!addToItemListPhrase (phrase.toCharArray (), phrase.length (), type, weighting, false))
271
std::cerr << "Duplicate phrase, dropping: " << phrase << std::endl;
273
syslog (LOG_ERR, "%s", "Duplicate phrase, dropping:");
274
syslog (LOG_ERR, "%s", phrase.toCharArray ());
278
// must be a combi or end marker if got here
280
// must be a combi if got here
282
addToItemListPhrase (phrase.toCharArray (), phrase.length (), type, weighting, true);
288
ListContainer::addToItemListPhrase (char *s, int len, int type, int weighting, bool combi)
291
list.push_back (data_length);
292
for (i = 0; i < len; i++)
294
data[data_length + i] = s[i];
296
data[data_length + len] = 0;
297
data_length += len + 1;
300
combilist.push_back (items);
303
weight.push_back (weighting);
304
itemtype.push_back (type);
310
ListContainer::readItemList (const char *filename, bool startswith, int filters)
312
sourcefile = filename;
313
sourcestartswith = startswith;
314
sourcefilters = filters;
315
std::string linebuffer;
317
re.comp ("^.*\\:[0-9]+\\/.*");
319
std::cout << filename << std::endl;
321
filedate = getFileDate (filename);
322
if (isCacheFileNewer (filename))
323
{ // see if cached .process file
324
linebuffer = filename; // is available and up to date
325
linebuffer += ".processed";
327
if (getFileLength (linebuffer.c_str ()) >= 4000)
329
// don't bother with small files
330
if (!readProcessedItemList (linebuffer.c_str (), startswith, filters))
334
issorted = true; // don't bother sorting cached file
339
int len = getFileLength (filename);
344
std::cerr << "Error reading file: " << filename << std::endl;
346
syslog (LOG_ERR, "%s", "Error reading file:");
347
syslog (LOG_ERR, "%s", filename);
352
return true; // its blank - perhaps due to webmin editing
355
increaseMemoryBy (len + 1); // Allocate some memory to hold file
356
// The plus one is to cope with files not ending in a new line
357
ifstream listfile (filename, ios::in);
358
if (!listfile.good ())
362
std::cerr << "Error opening :" << filename << std::endl;
364
syslog (LOG_ERR, "%s", "Error opening :");
365
syslog (LOG_ERR, "%s", filename);
368
String temp, inc, hostname, url;
369
while (!listfile.eof ())
371
getline (listfile, linebuffer);
372
if (linebuffer.length () < 2)
373
continue; // its jibberish
375
if (linebuffer[0] == '#')
376
continue; // its a comment
377
temp = (char *) linebuffer.c_str ();
378
if (temp.contains ("#"))
380
temp = temp.before ("#"); // tidy up
382
temp.removeWhiteSpace (); // tidy up and make it handle CRLF files
383
if (temp.startsWith (".Include<"))
384
{ // see if we have another list
385
inc = temp.after (".Include<"); // to include
386
inc = inc.before (">");
387
if (!readAnotherItemList (inc.toCharArray (), startswith, filters))
394
if (temp.endsWith ("/"))
396
temp.chop (); // tidy up
398
if (temp.startsWith ("ftp://"))
400
temp = temp.after ("ftp://"); // tidy up
403
{ // remove port addresses
404
if (temp.contains (":"))
405
{ // quicker than full regexp
406
if (re.match (temp.toCharArray ()))
408
hostname = temp.before (":");
409
url = temp.after ("/");
410
temp = hostname + "/" + url;
414
temp.toLower (); // tidy up
415
addToItemList (temp.toCharArray (), temp.length ()); // add to unsorted
419
return true; // sucessful read
424
ListContainer::readAnotherItemList (const char *filename, bool startswith, int filters)
427
int result = o.lm.newItemList (filename, startswith, filters, false);
432
std::cerr << "Error opening file:" << filename << std::endl;
434
syslog (LOG_ERR, "%s", "Error opening file:");
435
syslog (LOG_ERR, "%s", filename);
438
morelists.push_back ((unsigned) result);
443
bool ListContainer::inList (char *string)
445
if (findInList (string) != NULL)
454
bool ListContainer::inListEndsWith (char *string)
458
if (searchREW (0, items - 1, string) >= 0)
465
for (unsigned int i = 0; i < morelists.size (); i++)
467
rc = (*o.lm.l[morelists[i]]).inListEndsWith (string);
478
bool ListContainer::inListStartsWith (char *string)
482
if (searchRSW (0, items - 1, string) >= 0)
489
for (unsigned int i = 0; i < morelists.size (); i++)
491
rc = (*o.lm.l[morelists[i]]).inListStartsWith (string);
503
ListContainer::findInList (char *string)
511
r = searchRSWF (0, items - 1, string);
515
r = searchREWF (0, items - 1, string);
519
return (data + list[r]);
523
for (unsigned int i = 0; i < morelists.size (); i++)
525
rc = (*o.lm.l[morelists[i]]).findInList (string);
537
ListContainer::findStartsWith (char *string)
541
int r = searchRSW (0, items - 1, string);
544
return (data + list[r]);
548
for (unsigned int i = 0; i < morelists.size (); i++)
550
rc = (*o.lm.l[morelists[i]]).findStartsWith (string);
560
ListContainer::findStartsWithPartial (char *string)
564
int r = searchRSW (0, items - 1, string);
567
return (data + list[r]);
572
return (data + list[r]); // nearest match
576
for (unsigned int i = 0; i < morelists.size (); i++)
578
rc = (*o.lm.l[morelists[i]]).findStartsWithPartial (string);
590
ListContainer::findEndsWith (char *string)
594
int r = searchREW (0, items - 1, string);
597
return (data + list[r]);
601
for (unsigned int i = 0; i < morelists.size (); i++)
603
rc = (*o.lm.l[morelists[i]]).findEndsWith (string);
615
std::string ListContainer::getItemAt (char *index)
617
std::string s = index;
621
std::string ListContainer::getItemAtInt (int index)
624
o = data + list[index];
630
ListContainer::getWeightAt (unsigned int index)
632
return weight[index];
636
ListContainer::getTypeAt (unsigned int index)
638
return itemtype[index];
643
ListContainer::endsWithSort ()
644
{ // sort by ending of line
645
for (unsigned int i = 0; i < morelists.size (); i++)
647
(*o.lm.l[morelists[i]]).endsWithSort ();
649
if (items < 2 || issorted)
651
quicksortEW (0, items - 1);
660
ListContainer::startsWithSort ()
661
{ // sort by start of line
662
for (unsigned int i = 0; i < morelists.size (); i++)
664
(*o.lm.l[morelists[i]]).startsWithSort ();
666
if (items < 2 || issorted)
668
quicksortSW (0, items - 1);
675
bool ListContainer::createCacheFile ()
679
for (i = 0; i < morelists.size (); i++)
681
(*o.lm.l[morelists[i]]).createCacheFile ();
683
if (isCacheFileNewer (sourcefile.toCharArray ()))
684
{ // only do if it needs updating
688
{ // There is little to gain when there are so few
695
std::cout << "creating processed file:" << f << std::endl;
698
listfile (f.toCharArray (), ios::out);
699
if (listfile.fail ())
703
std::cerr << "Error creating cache file." << std::endl;
704
std::cerr << "Do you have write access to this area:" << std::endl;
705
std::cerr << f << std::endl;
707
syslog (LOG_ERR, "%s", "Error cache file.");
708
syslog (LOG_ERR, "%s", "Do you have write access to this area:");
709
syslog (LOG_ERR, "%s", f.toCharArray ());
713
for (i = 0; i < morelists.size (); i++)
716
f += (*o.lm.l[morelists[i]]).sourcefile;
718
listfile.write (f.toCharArray (), f.length ());
723
for (i = 0; i < (unsigned) items; i++)
724
{ // write the entries in order
725
offset = data + list[i];
726
listfile.write (offset, strlen (offset));
727
listfile.put ('\n'); // newline per entry
735
ListContainer::makeGraph (int fqs)
737
force_quick_search = fqs;
738
if (data_length == 0)
741
if (force_quick_search == 1)
743
for (i = 0; i < items; i++)
745
slowgraph.push_back (i);
752
graphdata = new int[64 * data_length];
754
memset (graphdata, 0, sizeof (int) * 64 * data_length);
755
std::deque < unsigned int >sizelist;
757
for (i = 0; i < items; i++)
759
sizelist.push_back (i);
761
graphSizeSort (0, items - 1, &sizelist);
763
for (i = 0; i < items; i++)
765
s = getItemAt (data + list[sizelist[i]]);
766
graphAdd (s.c_str (), 0, sizelist[i]);
768
int ml = graphdata[2];
771
for (i = ml - 1; i >= 0; i--)
773
branches = graphFindBranches (graphdata[4 + i]);
775
{ // quicker to use B-M on node with few branches
776
graphCopyNodePhrases (graphdata[4 + i]);
777
//remove link to this node and so effectively remove all nodes
778
// it links to but don't recover the memory as its not worth it
779
for (int j = i; j < ml; j++)
781
graphdata[4 + j] = graphdata[4 + j + 1];
791
ListContainer::graphSizeSort (int l, int r, std::deque < unsigned int >*sizelist)
797
unsigned int v = getItemAtInt ((*sizelist)[r]).length ();
798
int i = l - 1, j = r, p = i, q = r;
801
while (getItemAtInt ((*sizelist)[++i]).length () < v);
802
while (v < getItemAtInt ((*sizelist)[--j]).length ())
810
(*sizelist)[i] = (*sizelist)[j];
812
if (v == getItemAtInt ((*sizelist)[i]).length ())
816
(*sizelist)[p] = (*sizelist)[i];
819
if (v == getItemAtInt ((*sizelist)[j]).length ())
823
(*sizelist)[q] = (*sizelist)[j];
828
(*sizelist)[i] = (*sizelist)[r];
832
for (k = l; k <= p; k++, j--)
835
(*sizelist)[k] = (*sizelist)[j];
838
for (k = r - 1; k >= q; k--, i++)
841
(*sizelist)[k] = (*sizelist)[i];
844
graphSizeSort (l, j, sizelist);
845
graphSizeSort (i, r, sizelist);
849
// find the number of branches a node has
851
ListContainer::graphFindBranches (unsigned int pos)
854
int links = graphdata[pos * 64 + 2];
855
for (int i = 0; i < links; i++)
857
branches += graphFindBranches (graphdata[pos * 64 + 4 + i]);
861
branches += links - 1;
869
ListContainer::graphCopyNodePhrases (unsigned int pos)
871
// copy into slowgraph deque all different phrases from a root link
872
int links = graphdata[pos * 64 + 2];
874
for (i = 0; i < links; i++)
876
graphCopyNodePhrases (graphdata[pos * 64 + 4 + i]);
879
int size = slowgraph.size ();
880
unsigned int phrasenumber = graphdata[pos * 64 + 3];
881
for (i = 0; i < size; i++)
883
if (slowgraph[i] == phrasenumber)
891
slowgraph.push_back (phrasenumber);
898
ListContainer::bmsearch (char *file, int fl, std::string s)
901
int j, l; // counters
902
int p; // to hold precalcuated value for speed
904
int qsBc[256]; // Quick Search Boyer Moore shift table (256 alphabet)
905
char *k; // pointer used in matching
909
int pl = s.length ();
910
char *phrase = new char[pl + 1];
911
for (j = 0; j < pl; j++)
918
return 0; // reality checking
920
return 0; // reality checking
922
// For speed we append the phrase to the end of the memory block so it
923
// is always found, thus eliminating some checking. This is possible as
924
// we know an extra 127 bytes have been provided by NaughtyFilter.cpp
925
// and also the OptionContainer does not allow phrase lengths greater
928
for (j = 0; j < pl; j++)
933
// Next we need to make the Quick Search Boyer Moore shift table
936
for (j = 0; j < 256; j++)
940
for (j = 0; j < pl; j++)
942
qsBc[(unsigned char) phrase[j]] = pl - j;
945
// Now do the searching!
951
for (l = 0; l < pl; l++)
952
{ // quiv, but faster, memcmp()
953
if (k[l] != phrase[l])
963
break; // is the end of file marker
967
j += qsBc[(unsigned char) file[j + pl]]; // shift
974
std::deque < unsigned int >
975
ListContainer::graphSearch (char *doc, int len)
977
std::deque < unsigned int >result;
981
sl = slowgraph.size ();
982
for (i = 0; i < sl; i++)
985
j = bmsearch (doc, len, getItemAtInt (ppos));
986
for (k = 0; k < j; k++)
988
result.push_back (ppos);
991
if (force_quick_search == 1 || graphitems == 0)
996
int *stack = new int[1024];
1001
ml = graphdata[2] + 4;
1002
for (i = 0; i < len; i++)
1004
for (j = 4; j < ml; j++)
1010
p = graphdata[ppos];
1011
if (p == doc[i + depth])
1013
if (graphdata[ppos + 1] == 1)
1015
result.push_back (graphdata[ppos + 3]);
1017
sl = graphdata[ppos + 2];
1021
for (k = 1; k < sl; k++)
1023
stack[stacksize++] = graphdata[ppos + 4 + k];
1024
stack[stacksize++] = depth;
1026
pos = graphdata[ppos + 4];
1032
depth = stack[--stacksize];
1033
pos = stack[--stacksize];
1044
// Format of the data is each entry has 64 int values with format of:
1045
// [letter][last letter flag][num links][from phrase][link0][link1]...
1048
ListContainer::graphAdd (String s, int inx, int item)
1050
unsigned char p = s.charAt (0);
1056
for (i = 0; i < graphdata[inx * 64 + 2]; i++)
1058
c = (unsigned char) graphdata[(graphdata[inx * 64 + 4 + i]) * 64];
1063
if (t.length () > 0)
1065
graphAdd (t, graphdata[inx * 64 + 4 + i], item);
1069
// this means the phrase is already there
1070
// as part of an existing phrase
1071
px = graphdata[(graphdata[inx * 64 + 4 + i]) * 64 + 1];
1073
{ // the exact phrase is already there
1075
px = graphdata[(graphdata[inx * 64 + 4 + i]) * 64 + 3];
1078
if ((it > 9 && itemtype[item] < 10) || itemtype[item] == -1)
1080
// exists as a combi entry already
1081
// if got here existing entry must be a combi AND
1082
// new entry is not a combi so we overwrite the
1083
// existing values as combi values and types are
1084
// stored in the combilist
1086
// its a an exception
1087
// exception phrases take presidence
1088
itemtype[px] = itemtype[item];
1089
weight[px] = weight[item];
1098
numlinks = graphdata[inx * 64 + 2];
1099
graphdata[inx * 64 + 2] = numlinks + 1;
1100
graphdata[inx * 64 + 4 + numlinks] = i;
1101
graphdata[i * 64] = p;
1102
graphdata[i * 64 + 3] = item;
1104
while (s.length () > 0)
1106
numlinks = graphdata[i * 64 + 2];
1107
graphdata[i * 64 + 2] = numlinks + 1;
1108
graphdata[i * 64 + 4 + numlinks] = i + 1;
1112
graphdata[i * 64] = p;
1113
graphdata[i * 64 + 3] = item;
1116
graphdata[i * 64 + 1] = 1;
1122
// quicksort with 3 way partitioning sorted by the end of the line
1124
ListContainer::quicksortEW (int l, int r)
1130
char *v = data + list[r];
1131
int i = l - 1, j = r, p = i, q = r;
1134
while (greaterThanEWF (data + list[++i], v) > 0);
1135
while (greaterThanEWF (v, data + list[--j]) > 0)
1145
if (greaterThanEWF (v, data + list[i]) == 0)
1152
if (greaterThanEWF (v, data + list[j]) == 0)
1165
for (k = l; k <= p; k++, j--)
1171
for (k = r - 1; k >= q; k--, i++)
1181
// quicksort with 3 way partitioning sorted by the start of the line
1183
ListContainer::quicksortSW (int l, int r)
1189
char *v = data + list[r];
1190
int i = l - 1, j = r, p = i, q = r;
1193
while (greaterThanSWF (data + list[++i], v) > 0);
1194
while (greaterThanSWF (v, data + list[--j]) > 0)
1204
if (greaterThanSWF (v, data + list[i]) == 0)
1211
if (greaterThanSWF (v, data + list[j]) == 0)
1224
for (k = l; k <= p; k++, j--)
1230
for (k = r - 1; k >= q; k--, i++)
1241
ListContainer::readProcessedItemList (const char *filename, bool startswith, int filters)
1244
std::cout << "reading processed file:" << filename << std::endl;
1246
int len = getFileLength (filename);
1252
std::cerr << "Error reading file: " << filename << std::endl;
1254
syslog (LOG_ERR, "%s", "Error reading file:");
1255
syslog (LOG_ERR, "%s", filename);
1262
std::cerr << "File too small (less than 5 bytes - is it corrupt?): " << filename << std::endl;
1264
syslog (LOG_ERR, "%s", "File too small (less than 5 bytes - is it corrupt?):");
1265
syslog (LOG_ERR, "%s", filename);
1268
increaseMemoryBy (len + 2);
1269
ifstream listfile (filename, ios::in);
1270
if (!listfile.good ())
1274
std::cerr << "Error opening: " << filename << std::endl;
1276
syslog (LOG_ERR, "%s", "Error opening:");
1277
syslog (LOG_ERR, "%s", filename);
1280
std::string linebuffer;
1282
while (!listfile.eof ())
1284
getline (listfile, linebuffer);
1285
if (linebuffer[0] == '.')
1287
temp = linebuffer.c_str ();
1288
if (temp.startsWith (".Include<"))
1289
{ // see if we have another list
1290
inc = temp.after (".Include<").before (">"); // to include
1291
if (!readAnotherItemList (inc.toCharArray (), startswith, filters))
1299
slen = linebuffer.length ();
1303
list.push_back (data_length);
1306
data[data_length + i] = linebuffer[i];
1308
data[data_length + slen] = 0;
1309
data_length += slen + 1;
1318
ListContainer::addToItemList (char *s, int len)
1321
list.push_back (data_length);
1322
for (i = 0; i < len; i++)
1324
data[data_length + i] = s[i];
1326
data[data_length + len] = 0;
1327
data_length += len + 1;
1334
ListContainer::searchRSWF (int a, int s, const char *p)
1338
int m = (a + s) / 2;
1339
int r = greaterThanSWF (p, data + list[m]);
1343
return searchRSWF (m + 1, s, p);
1346
return searchRSWF (a, m - 1, p);
1350
ListContainer::searchRSW (int a, int s, const char *p)
1354
int m = (a + s) / 2;
1355
int r = greaterThanSW (p, data + list[m]);
1359
return searchRSW (m + 1, s, p);
1362
return searchRSW (a, m - 1, p);
1366
ListContainer::searchREWF (int a, int s, const char *p)
1370
int m = (a + s) / 2;
1371
int r = greaterThanEWF (p, data + list[m]);
1375
return searchREWF (m + 1, s, p);
1378
return searchREWF (a, m - 1, p);
1383
ListContainer::searchREW (int a, int s, const char *p)
1387
int m = (a + s) / 2;
1388
int r = greaterThanEW (p, data + list[m]);
1392
return searchREW (m + 1, s, p);
1395
return searchREW (a, m - 1, p);
1400
ListContainer::greaterThanEWF (const char *a, const char *b)
1402
int alen = strlen (a);
1403
int blen = strlen (b);
1404
int maxlen = alen < blen ? alen : blen;
1405
char *apos = (char *) a + alen - 1;
1406
char *bpos = (char *) b + blen - 1;
1407
unsigned char achar;
1408
unsigned char bchar;
1433
return 0; // both equal
1438
ListContainer::greaterThanSWF (const char *a, const char *b)
1440
int alen = strlen (a);
1441
int blen = strlen (b);
1442
int maxlen = alen < blen ? alen : blen;
1443
char *apos = (char *) a;
1444
char *bpos = (char *) b;
1446
unsigned char achar;
1447
unsigned char bchar;
1472
return 0; // both equal
1476
ListContainer::greaterThanSW (const char *a, const char *b)
1478
int alen = strlen (a);
1479
int blen = strlen (b);
1480
int maxlen = alen < blen ? alen : blen;
1481
char *apos = (char *) a;
1482
char *bpos = (char *) b;
1483
int i = 0; // this used to be set to 1 - I don't know why
1484
unsigned char achar;
1485
unsigned char bchar;
1504
return 0; // both equal
1508
ListContainer::greaterThanEW (const char *a, const char *b)
1510
int alen = strlen (a);
1511
int blen = strlen (b);
1512
int maxlen = alen < blen ? alen : blen;
1513
char *apos = (char *) a + alen - 1;
1514
char *bpos = (char *) b + blen - 1;
1515
unsigned char achar;
1516
unsigned char bchar;
1535
return 0; // both equal
1538
bool ListContainer::isCacheFileNewer (const char *filename)
1541
len = getFileLength (filename);
1546
std::cerr << "Error reading file: " << filename << std::endl;
1548
syslog (LOG_ERR, "%s", "Error reading file:");
1549
syslog (LOG_ERR, "%s", filename);
1553
bannedlistdate = getFileDate (filename);
1554
std::string linebuffer = filename;
1555
linebuffer += ".processed";
1557
cachedate = getFileDate (linebuffer.c_str ());
1558
if (cachedate < bannedlistdate)
1560
return false; // cache file is older than list file
1566
ListContainer::increaseMemoryBy (int bytes)
1568
if (data_memory > 0)
1570
char *temp = new char[data_memory + bytes]; // replacement store
1571
memcpy (temp, data, data_length);
1574
data_memory = data_memory + bytes;
1579
data = new char[bytes];
1580
data_memory = bytes;
1586
std::string ListContainer::toLower (std::string s)
1590
for (int i = 0; i < l; i++)
1592
if ((s[i] >= 'A') && (s[i] <= 'Z'))
1594
s[i] = 'a' + s[i] - 'A';
1602
ListContainer::getFileLength (const char *filename)
1606
file = fopen (filename, "r");
1609
if (!fseek (file, 0, SEEK_END))
1624
ListContainer::getFileDate (const char *filename)
1627
int rc = stat (filename, &status);
1632
struct tm *tmnow = localtime (&status.st_mtime);
1634
int date = (tmnow->tm_year - 100) * 31536000;
1635
date += tmnow->tm_mon * 2628000;
1636
date += tmnow->tm_mday * 86400;
1637
date += tmnow->tm_hour * 3600;
1638
date += tmnow->tm_min * 60;
1639
date += tmnow->tm_sec;
1640
return date; // a nice int rather than a horrid struct
1644
bool ListContainer::upToDate ()
1646
if (getFileDate (sourcefile.toCharArray ()) > filedate)
1650
for (unsigned int i = 0; i < morelists.size (); i++)
1652
if (!(*o.lm.l[morelists[i]]).upToDate ())