~ubuntu-branches/ubuntu/intrepid/dansguardian/intrepid-security

« back to all changes in this revision

Viewing changes to ListContainer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alexander Wirt
  • Date: 2008-04-06 14:47:06 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20080406144706-2r26l1rougdmb1sd
Tags: 2.9.9.3-2
This time build with gcc 4.3 (Closes: #454889) 

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
5
 
 
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.
10
 
//
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.
15
 
//
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
19
 
 
20
 
#include <syslog.h>
21
 
#include <algorithm>
22
 
#include "ListContainer.hpp"
23
 
#include "OptionContainer.hpp"
24
 
#include "RegExp.hpp"
25
 
#include <cstdlib>
26
 
#include <cstdio>
27
 
#include <unistd.h>
28
 
#include "String.hpp"
29
 
#include <iostream>
30
 
#include <fstream>
31
 
#include <sys/stat.h>
32
 
#include <sys/time.h>
33
 
 
34
 
extern bool isDaemonised;
35
 
extern OptionContainer o;
36
 
 
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]),
39
 
graphitems (0),
40
 
data_length (0),
41
 
data_memory (0),
42
 
items (0),
43
 
isSW (false),
44
 
issorted (false),
45
 
graphused (false),
46
 
force_quick_search (0)
47
 
{
48
 
}
49
 
 
50
 
 
51
 
 
52
 
ListContainer::~ListContainer ()
53
 
{
54
 
  delete[]data;
55
 
  if (graphused)
56
 
    {
57
 
      delete[]graphdata;
58
 
    }
59
 
  for (unsigned int i = 0; i < morelists.size (); i++)
60
 
    {
61
 
      o.lm.deRefList (morelists[i]);
62
 
    }
63
 
}
64
 
 
65
 
 
66
 
void
67
 
ListContainer::reset ()
68
 
{
69
 
  delete[]data;
70
 
  delete[]graphdata;
71
 
  for (unsigned int i = 0; i < morelists.size (); i++)
72
 
    {
73
 
      o.lm.deRefList (morelists[i]);
74
 
    }
75
 
  data = new char[0];
76
 
  graphdata = new int[0];
77
 
  graphitems = 0;
78
 
  data_length = 0;
79
 
  data_memory = 0;
80
 
  items = 0;
81
 
  isSW = false;
82
 
  issorted = false;
83
 
  graphused = false;
84
 
  force_quick_search = 0;
85
 
  combilist.clear ();
86
 
  slowgraph.clear ();
87
 
  list.clear ();
88
 
  weight.clear ();
89
 
  itemtype.clear ();
90
 
  morelists.clear ();
91
 
  used = false;
92
 
  parent = false;
93
 
  bannedpfile = "";
94
 
  exceptionpfile = "";
95
 
  weightedpfile = "";
96
 
  bannedpfiledate = 0;
97
 
  exceptionpfiledate = 0;
98
 
  weightedpfiledate = 0;
99
 
}
100
 
 
101
 
// delete the memory block when the class is destryed
102
 
 
103
 
 
104
 
bool
105
 
ListContainer::previousUseItem (const char *filename, bool startswith, int filters)
106
 
{
107
 
  String f = filename;
108
 
  if (f == sourcefile && startswith == sourcestartswith && filters == sourcefilters)
109
 
    {
110
 
      return true;
111
 
    }
112
 
  return false;
113
 
}
114
 
 
115
 
 
116
 
 
117
 
bool ListContainer::readPhraseList (const char *filename, bool isexception)
118
 
{
119
 
  sourcefile = filename;
120
 
  sourceisexception = isexception;
121
 
  std::string linebuffer;       // a string line buffer ;)
122
 
  String
123
 
    temp;                       // a String for temporary manipulation
124
 
  String
125
 
    line;
126
 
  int
127
 
    len = getFileLength (filename);
128
 
  if (len < 0)
129
 
    {
130
 
      if (!isDaemonised)
131
 
        {
132
 
          std::cerr << "Error reading file (does it exist?): " << filename << std::endl;
133
 
        }
134
 
      syslog (LOG_ERR, "%s", "Error reading file (does it exist?): ");
135
 
      syslog (LOG_ERR, "%s", filename);
136
 
      return false;
137
 
    }
138
 
  if (len < 2)
139
 
    {
140
 
      return true;              // its blank - perhaps due to webmin editing
141
 
      // just return
142
 
    }
143
 
  filedate = getFileDate (filename);
144
 
  increaseMemoryBy (len + 1);   // Allocate some memory to hold file
145
 
  ifstream
146
 
  listfile (filename, ios::in); // open the file for reading
147
 
  if (!listfile.good ())
148
 
    {
149
 
      if (!isDaemonised)
150
 
        {
151
 
          std::cerr << "Error opening file (does it exist?): " << filename << std::endl;
152
 
        }
153
 
      syslog (LOG_ERR, "%s", "Error opening file (does it exist?): ");
154
 
      syslog (LOG_ERR, "%s", filename);
155
 
      return false;
156
 
    }
157
 
  while (!listfile.eof ())
158
 
    {                           // keep going until end of file
159
 
      getline (listfile, linebuffer);   // grab a line
160
 
      if (linebuffer.length () != 0)
161
 
        {                       // sanity checkin
162
 
          line = linebuffer.c_str ();
163
 
          line.removeWhiteSpace ();
164
 
          line.toLower ();      // tidy up
165
 
          if (line.startsWith ("<"))
166
 
            {
167
 
              readPhraseListHelper (line, isexception);
168
 
            }
169
 
          else if (line.startsWith ("."))
170
 
            {
171
 
              temp = line.after (".include<").before (">");
172
 
              if (temp.length () > 0)
173
 
                {
174
 
                  if (!readPhraseList (temp.toCharArray (), isexception))
175
 
                    {
176
 
                      listfile.close ();
177
 
                      return false;
178
 
                    }
179
 
                }
180
 
            }
181
 
        }
182
 
    }
183
 
  listfile.close ();
184
 
  return true;                  // sucessful read
185
 
}
186
 
 
187
 
 
188
 
void
189
 
ListContainer::readPhraseListHelper (String line, bool isexception)
190
 
{
191
 
  int weighting = line.after ("><").before (">").toInteger ();
192
 
  // defaults to 0
193
 
  int type;
194
 
  if (weighting != 0)
195
 
    {
196
 
      type = 1;
197
 
      line = line.before ("><") + ">";
198
 
    }
199
 
  else
200
 
    {
201
 
      if (isexception)
202
 
        {
203
 
          type = -1;
204
 
        }
205
 
      else
206
 
        {
207
 
          type = 0;
208
 
        }
209
 
    }
210
 
 
211
 
  if (line.after (">,").length () > 2)
212
 
    {
213
 
      while (line.length () > 2)
214
 
        {
215
 
          line = line.after ("<");
216
 
          readPhraseListHelper2 (line.before (">"), type + 11, weighting);
217
 
          line = line.after (">,");
218
 
        }
219
 
      readPhraseListHelper2 ("", type + 21, weighting);
220
 
    }
221
 
  else
222
 
    {
223
 
      line = line.after ("<").before (">");
224
 
      readPhraseListHelper2 (line, type, weighting);
225
 
    }
226
 
}
227
 
 
228
 
 
229
 
void
230
 
ListContainer::readPhraseListHelper2 (String phrase, int type, int weighting)
231
 
{
232
 
  // -1=exception
233
 
  // 0=banned
234
 
  // 1=weighted
235
 
  // 10 = combination exception
236
 
  // 11 = combination banned
237
 
  // 12 = combination weighted
238
 
  // 20,21,22 = end of combi marker
239
 
 
240
 
  if (type > 19)
241
 
    {
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
245
 
 
246
 
      return;
247
 
    }
248
 
 
249
 
  if (phrase.length () > 127)
250
 
    {
251
 
      if (!isDaemonised)
252
 
        {
253
 
          std::cerr << "Phrase length too long, truncating: " << phrase << std::endl;
254
 
        }
255
 
      syslog (LOG_ERR, "%s", "Phrase length too long, truncating:");
256
 
      syslog (LOG_ERR, "%s", phrase.toCharArray ());
257
 
      phrase = phrase.subString (0, 127);
258
 
    }
259
 
 
260
 
  if (phrase.length () < 1)
261
 
    {                           // its too small to use
262
 
      return;
263
 
    }
264
 
 
265
 
  if (type < 10)
266
 
    {
267
 
      if (!addToItemListPhrase (phrase.toCharArray (), phrase.length (), type, weighting, false))
268
 
        {
269
 
          if (!isDaemonised)
270
 
            {
271
 
              std::cerr << "Duplicate phrase, dropping: " << phrase << std::endl;
272
 
            }
273
 
          syslog (LOG_ERR, "%s", "Duplicate phrase, dropping:");
274
 
          syslog (LOG_ERR, "%s", phrase.toCharArray ());
275
 
        }
276
 
      return;
277
 
    }
278
 
  // must be a combi or end marker if got here
279
 
 
280
 
  // must be a combi if got here
281
 
 
282
 
  addToItemListPhrase (phrase.toCharArray (), phrase.length (), type, weighting, true);
283
 
 
284
 
}
285
 
 
286
 
 
287
 
bool
288
 
ListContainer::addToItemListPhrase (char *s, int len, int type, int weighting, bool combi)
289
 
{
290
 
  int i;
291
 
  list.push_back (data_length);
292
 
  for (i = 0; i < len; i++)
293
 
    {
294
 
      data[data_length + i] = s[i];
295
 
    }
296
 
  data[data_length + len] = 0;
297
 
  data_length += len + 1;
298
 
  if (combi)
299
 
    {
300
 
      combilist.push_back (items);
301
 
    }
302
 
  items++;
303
 
  weight.push_back (weighting);
304
 
  itemtype.push_back (type);
305
 
  return true;
306
 
}
307
 
 
308
 
 
309
 
bool
310
 
ListContainer::readItemList (const char *filename, bool startswith, int filters)
311
 
{
312
 
  sourcefile = filename;
313
 
  sourcestartswith = startswith;
314
 
  sourcefilters = filters;
315
 
  std::string linebuffer;
316
 
  RegExp re;
317
 
  re.comp ("^.*\\:[0-9]+\\/.*");
318
 
#ifdef DGDEBUG
319
 
  std::cout << filename << std::endl;
320
 
#endif
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";
326
 
 
327
 
      if (getFileLength (linebuffer.c_str ()) >= 4000)
328
 
        {
329
 
          // don't bother with small files
330
 
          if (!readProcessedItemList (linebuffer.c_str (), startswith, filters))
331
 
            {                   // read cached
332
 
              return false;
333
 
            }
334
 
          issorted = true;      // don't bother sorting cached file
335
 
          return true;
336
 
 
337
 
        }
338
 
    }
339
 
  int len = getFileLength (filename);
340
 
  if (len < 0)
341
 
    {
342
 
      if (!isDaemonised)
343
 
        {
344
 
          std::cerr << "Error reading file: " << filename << std::endl;
345
 
        }
346
 
      syslog (LOG_ERR, "%s", "Error reading file:");
347
 
      syslog (LOG_ERR, "%s", filename);
348
 
      return false;
349
 
    }
350
 
  if (len < 2)
351
 
    {
352
 
      return true;              // its blank - perhaps due to webmin editing
353
 
      // just return
354
 
    }
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 ())
359
 
    {
360
 
      if (!isDaemonised)
361
 
        {
362
 
          std::cerr << "Error opening :" << filename << std::endl;
363
 
        }
364
 
      syslog (LOG_ERR, "%s", "Error opening :");
365
 
      syslog (LOG_ERR, "%s", filename);
366
 
      return false;
367
 
    }
368
 
  String temp, inc, hostname, url;
369
 
  while (!listfile.eof ())
370
 
    {
371
 
      getline (listfile, linebuffer);
372
 
      if (linebuffer.length () < 2)
373
 
        continue;               // its jibberish
374
 
 
375
 
      if (linebuffer[0] == '#')
376
 
        continue;               // its a comment
377
 
      temp = (char *) linebuffer.c_str ();
378
 
      if (temp.contains ("#"))
379
 
        {
380
 
          temp = temp.before ("#");     // tidy up
381
 
        }
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))
388
 
            {                   // read it
389
 
              listfile.close ();
390
 
              return false;
391
 
            }
392
 
          continue;
393
 
        }
394
 
      if (temp.endsWith ("/"))
395
 
        {
396
 
          temp.chop ();         // tidy up
397
 
        }
398
 
      if (temp.startsWith ("ftp://"))
399
 
        {
400
 
          temp = temp.after ("ftp://"); // tidy up
401
 
        }
402
 
      if (filters == 1)
403
 
        {                       // remove port addresses
404
 
          if (temp.contains (":"))
405
 
            {                   // quicker than full regexp
406
 
              if (re.match (temp.toCharArray ()))
407
 
                {
408
 
                  hostname = temp.before (":");
409
 
                  url = temp.after ("/");
410
 
                  temp = hostname + "/" + url;
411
 
                }
412
 
            }
413
 
        }
414
 
      temp.toLower ();          // tidy up
415
 
      addToItemList (temp.toCharArray (), temp.length ());      // add to unsorted
416
 
      // list
417
 
    }
418
 
  listfile.close ();
419
 
  return true;                  // sucessful read
420
 
}
421
 
 
422
 
 
423
 
bool
424
 
ListContainer::readAnotherItemList (const char *filename, bool startswith, int filters)
425
 
{
426
 
 
427
 
  int result = o.lm.newItemList (filename, startswith, filters, false);
428
 
  if (result < 0)
429
 
    {
430
 
      if (!isDaemonised)
431
 
        {
432
 
          std::cerr << "Error opening file:" << filename << std::endl;
433
 
        }
434
 
      syslog (LOG_ERR, "%s", "Error opening file:");
435
 
      syslog (LOG_ERR, "%s", filename);
436
 
      return false;
437
 
    }
438
 
  morelists.push_back ((unsigned) result);
439
 
  return true;
440
 
}
441
 
 
442
 
 
443
 
bool ListContainer::inList (char *string)
444
 
{
445
 
  if (findInList (string) != NULL)
446
 
    {
447
 
      return true;
448
 
    }
449
 
  return false;
450
 
}
451
 
 
452
 
 
453
 
 
454
 
bool ListContainer::inListEndsWith (char *string)
455
 
{
456
 
  if (items > 0)
457
 
    {
458
 
      if (searchREW (0, items - 1, string) >= 0)
459
 
        {
460
 
          return true;
461
 
        }
462
 
    }
463
 
  bool
464
 
    rc;
465
 
  for (unsigned int i = 0; i < morelists.size (); i++)
466
 
    {
467
 
      rc = (*o.lm.l[morelists[i]]).inListEndsWith (string);
468
 
      if (rc)
469
 
        {
470
 
          return true;
471
 
        }
472
 
    }
473
 
  return false;
474
 
}
475
 
 
476
 
 
477
 
 
478
 
bool ListContainer::inListStartsWith (char *string)
479
 
{
480
 
  if (items > 0)
481
 
    {
482
 
      if (searchRSW (0, items - 1, string) >= 0)
483
 
        {
484
 
          return true;
485
 
        }
486
 
    }
487
 
  bool
488
 
    rc;
489
 
  for (unsigned int i = 0; i < morelists.size (); i++)
490
 
    {
491
 
      rc = (*o.lm.l[morelists[i]]).inListStartsWith (string);
492
 
      if (rc)
493
 
        {
494
 
          return true;
495
 
        }
496
 
    }
497
 
  return false;
498
 
}
499
 
 
500
 
 
501
 
 
502
 
char *
503
 
ListContainer::findInList (char *string)
504
 
{
505
 
 
506
 
  if (items > 0)
507
 
    {
508
 
      int r;
509
 
      if (isSW)
510
 
        {
511
 
          r = searchRSWF (0, items - 1, string);
512
 
        }
513
 
      else
514
 
        {
515
 
          r = searchREWF (0, items - 1, string);
516
 
        }
517
 
      if (r >= 0)
518
 
        {
519
 
          return (data + list[r]);
520
 
        }
521
 
    }
522
 
  char *rc;
523
 
  for (unsigned int i = 0; i < morelists.size (); i++)
524
 
    {
525
 
      rc = (*o.lm.l[morelists[i]]).findInList (string);
526
 
      if (rc != NULL)
527
 
        {
528
 
          return rc;
529
 
        }
530
 
    }
531
 
  return NULL;
532
 
}
533
 
 
534
 
 
535
 
 
536
 
char *
537
 
ListContainer::findStartsWith (char *string)
538
 
{
539
 
  if (items > 0)
540
 
    {
541
 
      int r = searchRSW (0, items - 1, string);
542
 
      if (r >= 0)
543
 
        {
544
 
          return (data + list[r]);
545
 
        }
546
 
    }
547
 
  char *rc;
548
 
  for (unsigned int i = 0; i < morelists.size (); i++)
549
 
    {
550
 
      rc = (*o.lm.l[morelists[i]]).findStartsWith (string);
551
 
      if (rc != NULL)
552
 
        {
553
 
          return rc;
554
 
        }
555
 
    }
556
 
  return NULL;
557
 
}
558
 
 
559
 
char *
560
 
ListContainer::findStartsWithPartial (char *string)
561
 
{
562
 
  if (items > 0)
563
 
    {
564
 
      int r = searchRSW (0, items - 1, string);
565
 
      if (r >= 0)
566
 
        {
567
 
          return (data + list[r]);
568
 
        }
569
 
      if (r < -1)
570
 
        {
571
 
          r = 0 - r - 2;
572
 
          return (data + list[r]);      // nearest match
573
 
        }
574
 
    }
575
 
  char *rc;
576
 
  for (unsigned int i = 0; i < morelists.size (); i++)
577
 
    {
578
 
      rc = (*o.lm.l[morelists[i]]).findStartsWithPartial (string);
579
 
      if (rc != NULL)
580
 
        {
581
 
          return rc;
582
 
        }
583
 
    }
584
 
  return NULL;
585
 
}
586
 
 
587
 
 
588
 
 
589
 
char *
590
 
ListContainer::findEndsWith (char *string)
591
 
{
592
 
  if (items > 0)
593
 
    {
594
 
      int r = searchREW (0, items - 1, string);
595
 
      if (r >= 0)
596
 
        {
597
 
          return (data + list[r]);
598
 
        }
599
 
    }
600
 
  char *rc;
601
 
  for (unsigned int i = 0; i < morelists.size (); i++)
602
 
    {
603
 
      rc = (*o.lm.l[morelists[i]]).findEndsWith (string);
604
 
      if (rc != NULL)
605
 
        {
606
 
          return rc;
607
 
        }
608
 
    }
609
 
  return NULL;
610
 
}
611
 
 
612
 
 
613
 
 
614
 
 
615
 
std::string ListContainer::getItemAt (char *index)
616
 
{
617
 
  std::string s = index;
618
 
  return s;
619
 
}
620
 
 
621
 
std::string ListContainer::getItemAtInt (int index)
622
 
{
623
 
  char *
624
 
    o = data + list[index];
625
 
  std::string s = o;
626
 
  return s;
627
 
}
628
 
 
629
 
int
630
 
ListContainer::getWeightAt (unsigned int index)
631
 
{
632
 
  return weight[index];
633
 
}
634
 
 
635
 
int
636
 
ListContainer::getTypeAt (unsigned int index)
637
 
{
638
 
  return itemtype[index];
639
 
}
640
 
 
641
 
 
642
 
void
643
 
ListContainer::endsWithSort ()
644
 
{                               // sort by ending of line
645
 
  for (unsigned int i = 0; i < morelists.size (); i++)
646
 
    {
647
 
      (*o.lm.l[morelists[i]]).endsWithSort ();
648
 
    }
649
 
  if (items < 2 || issorted)
650
 
    return;
651
 
  quicksortEW (0, items - 1);
652
 
  isSW = false;
653
 
  issorted = true;
654
 
  return;
655
 
}
656
 
 
657
 
 
658
 
 
659
 
void
660
 
ListContainer::startsWithSort ()
661
 
{                               // sort by start of line
662
 
  for (unsigned int i = 0; i < morelists.size (); i++)
663
 
    {
664
 
      (*o.lm.l[morelists[i]]).startsWithSort ();
665
 
    }
666
 
  if (items < 2 || issorted)
667
 
    return;
668
 
  quicksortSW (0, items - 1);
669
 
  isSW = true;
670
 
  issorted = true;
671
 
  return;
672
 
}
673
 
 
674
 
 
675
 
bool ListContainer::createCacheFile ()
676
 
{
677
 
  unsigned int
678
 
    i;
679
 
  for (i = 0; i < morelists.size (); i++)
680
 
    {
681
 
      (*o.lm.l[morelists[i]]).createCacheFile ();
682
 
    }
683
 
  if (isCacheFileNewer (sourcefile.toCharArray ()))
684
 
    {                           // only do if it needs updating
685
 
      return true;
686
 
    }
687
 
  if (items < 1000)
688
 
    {                           // There is little to gain when there are so few
689
 
      return true;
690
 
    }
691
 
  String
692
 
    f = sourcefile;
693
 
  f += ".processed";
694
 
#ifdef DGDEBUG
695
 
  std::cout << "creating processed file:" << f << std::endl;
696
 
#endif
697
 
  ofstream
698
 
  listfile (f.toCharArray (), ios::out);
699
 
  if (listfile.fail ())
700
 
    {
701
 
      if (!isDaemonised)
702
 
        {
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;
706
 
        }
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 ());
710
 
      return false;
711
 
    }
712
 
 
713
 
  for (i = 0; i < morelists.size (); i++)
714
 
    {
715
 
      f = ".Include<";
716
 
      f += (*o.lm.l[morelists[i]]).sourcefile;
717
 
      f += ">\n";
718
 
      listfile.write (f.toCharArray (), f.length ());
719
 
    }
720
 
 
721
 
  char *
722
 
    offset;
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
728
 
    }
729
 
  listfile.close ();
730
 
  return true;
731
 
}
732
 
 
733
 
 
734
 
void
735
 
ListContainer::makeGraph (int fqs)
736
 
{
737
 
  force_quick_search = fqs;
738
 
  if (data_length == 0)
739
 
    return;
740
 
  int i;
741
 
  if (force_quick_search == 1)
742
 
    {
743
 
      for (i = 0; i < items; i++)
744
 
        {
745
 
          slowgraph.push_back (i);
746
 
        }
747
 
      return;
748
 
    }
749
 
  std::string s;
750
 
  std::string lasts;
751
 
  graphused = true;
752
 
  graphdata = new int[64 * data_length];
753
 
  graphitems++;
754
 
  memset (graphdata, 0, sizeof (int) * 64 * data_length);
755
 
  std::deque < unsigned int >sizelist;
756
 
 
757
 
  for (i = 0; i < items; i++)
758
 
    {
759
 
      sizelist.push_back (i);
760
 
    }
761
 
  graphSizeSort (0, items - 1, &sizelist);
762
 
 
763
 
  for (i = 0; i < items; i++)
764
 
    {
765
 
      s = getItemAt (data + list[sizelist[i]]);
766
 
      graphAdd (s.c_str (), 0, sizelist[i]);
767
 
    }
768
 
  int ml = graphdata[2];
769
 
  int branches;
770
 
 
771
 
  for (i = ml - 1; i >= 0; i--)
772
 
    {
773
 
      branches = graphFindBranches (graphdata[4 + i]);
774
 
      if (branches < 12)
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++)
780
 
            {
781
 
              graphdata[4 + j] = graphdata[4 + j + 1];
782
 
            }
783
 
          graphdata[2]--;
784
 
        }
785
 
    }
786
 
 
787
 
}
788
 
 
789
 
 
790
 
void
791
 
ListContainer::graphSizeSort (int l, int r, std::deque < unsigned int >*sizelist)
792
 
{
793
 
  if (r <= l)
794
 
    return;
795
 
  unsigned int e;
796
 
  int k;
797
 
  unsigned int v = getItemAtInt ((*sizelist)[r]).length ();
798
 
  int i = l - 1, j = r, p = i, q = r;
799
 
  for (;;)
800
 
    {
801
 
      while (getItemAtInt ((*sizelist)[++i]).length () < v);
802
 
      while (v < getItemAtInt ((*sizelist)[--j]).length ())
803
 
        {
804
 
          if (j == l)
805
 
            break;
806
 
        }
807
 
      if (i >= j)
808
 
        break;
809
 
      e = (*sizelist)[i];
810
 
      (*sizelist)[i] = (*sizelist)[j];
811
 
      (*sizelist)[j] = e;
812
 
      if (v == getItemAtInt ((*sizelist)[i]).length ())
813
 
        {
814
 
          p++;
815
 
          e = (*sizelist)[p];
816
 
          (*sizelist)[p] = (*sizelist)[i];
817
 
          (*sizelist)[i] = e;
818
 
        }
819
 
      if (v == getItemAtInt ((*sizelist)[j]).length ())
820
 
        {
821
 
          q--;
822
 
          e = (*sizelist)[q];
823
 
          (*sizelist)[q] = (*sizelist)[j];
824
 
          (*sizelist)[j] = e;
825
 
        }
826
 
    }
827
 
  e = (*sizelist)[i];
828
 
  (*sizelist)[i] = (*sizelist)[r];
829
 
  (*sizelist)[r] = e;
830
 
  j = i - 1;
831
 
  i++;
832
 
  for (k = l; k <= p; k++, j--)
833
 
    {
834
 
      e = (*sizelist)[k];
835
 
      (*sizelist)[k] = (*sizelist)[j];
836
 
      (*sizelist)[j] = e;
837
 
    }
838
 
  for (k = r - 1; k >= q; k--, i++)
839
 
    {
840
 
      e = (*sizelist)[k];
841
 
      (*sizelist)[k] = (*sizelist)[i];
842
 
      (*sizelist)[i] = e;
843
 
    }
844
 
  graphSizeSort (l, j, sizelist);
845
 
  graphSizeSort (i, r, sizelist);
846
 
}
847
 
 
848
 
 
849
 
  // find the number of branches a node has
850
 
int
851
 
ListContainer::graphFindBranches (unsigned int pos)
852
 
{
853
 
  int branches = 0;
854
 
  int links = graphdata[pos * 64 + 2];
855
 
  for (int i = 0; i < links; i++)
856
 
    {
857
 
      branches += graphFindBranches (graphdata[pos * 64 + 4 + i]);
858
 
    }
859
 
  if (links > 1)
860
 
    {
861
 
      branches += links - 1;
862
 
    }
863
 
 
864
 
  return branches;
865
 
}
866
 
 
867
 
 
868
 
void
869
 
ListContainer::graphCopyNodePhrases (unsigned int pos)
870
 
{
871
 
// copy into slowgraph deque all different phrases from a root link
872
 
  int links = graphdata[pos * 64 + 2];
873
 
  int i;
874
 
  for (i = 0; i < links; i++)
875
 
    {
876
 
      graphCopyNodePhrases (graphdata[pos * 64 + 4 + i]);
877
 
    }
878
 
  bool found = false;
879
 
  int size = slowgraph.size ();
880
 
  unsigned int phrasenumber = graphdata[pos * 64 + 3];
881
 
  for (i = 0; i < size; i++)
882
 
    {
883
 
      if (slowgraph[i] == phrasenumber)
884
 
        {
885
 
          found = true;
886
 
          break;
887
 
        }
888
 
    }
889
 
  if (!found)
890
 
    {
891
 
      slowgraph.push_back (phrasenumber);
892
 
    }
893
 
 
894
 
}
895
 
 
896
 
 
897
 
int
898
 
ListContainer::bmsearch (char *file, int fl, std::string s)
899
 
{
900
 
  // must match all
901
 
  int j, l;                     // counters
902
 
  int p;                        // to hold precalcuated value for speed
903
 
  bool match;                   // flag
904
 
  int qsBc[256];                // Quick Search Boyer Moore shift table (256 alphabet)
905
 
  char *k;                      // pointer used in matching
906
 
 
907
 
  int count = 0;
908
 
 
909
 
  int pl = s.length ();
910
 
  char *phrase = new char[pl + 1];
911
 
  for (j = 0; j < pl; j++)
912
 
    {
913
 
      phrase[j] = s[j];
914
 
    }
915
 
  phrase[pl] = 0;
916
 
 
917
 
  if (fl < pl)
918
 
    return 0;                   // reality checking
919
 
  if (pl > 126)
920
 
    return 0;                   // reality checking
921
 
 
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
926
 
  // than 126 chars
927
 
  k = file + fl;
928
 
  for (j = 0; j < pl; j++)
929
 
    {
930
 
      k[j] = s[j];
931
 
    }
932
 
 
933
 
  // Next we need to make the Quick Search Boyer Moore shift table
934
 
 
935
 
  p = pl + 1;
936
 
  for (j = 0; j < 256; j++)
937
 
    {                           // Preprocessing
938
 
      qsBc[j] = p;
939
 
    }
940
 
  for (j = 0; j < pl; j++)
941
 
    {                           // Preprocessing
942
 
      qsBc[(unsigned char) phrase[j]] = pl - j;
943
 
    }
944
 
 
945
 
  // Now do the searching!
946
 
 
947
 
  for (j = 0;;)
948
 
    {
949
 
      k = file + j;
950
 
      match = true;
951
 
      for (l = 0; l < pl; l++)
952
 
        {                       // quiv, but faster, memcmp()
953
 
          if (k[l] != phrase[l])
954
 
            {
955
 
              match = false;
956
 
              break;
957
 
            }
958
 
        }
959
 
      if (match)
960
 
        {
961
 
          if (j >= fl)
962
 
            {
963
 
              break;            // is the end of file marker
964
 
            }
965
 
          count++;
966
 
        }
967
 
      j += qsBc[(unsigned char) file[j + pl]];  // shift
968
 
    }
969
 
  delete[]phrase;
970
 
  return count;
971
 
}
972
 
 
973
 
 
974
 
std::deque < unsigned int >
975
 
ListContainer::graphSearch (char *doc, int len)
976
 
{
977
 
  std::deque < unsigned int >result;
978
 
  int i, j, k;
979
 
  int sl;
980
 
  int ppos;
981
 
  sl = slowgraph.size ();
982
 
  for (i = 0; i < sl; i++)
983
 
    {
984
 
      ppos = slowgraph[i];
985
 
      j = bmsearch (doc, len, getItemAtInt (ppos));
986
 
      for (k = 0; k < j; k++)
987
 
        {
988
 
          result.push_back (ppos);
989
 
        }
990
 
    }
991
 
  if (force_quick_search == 1 || graphitems == 0)
992
 
    {
993
 
      return result;
994
 
    }
995
 
  int ml;
996
 
  int *stack = new int[1024];
997
 
  int stacksize = 0;
998
 
  unsigned char p;
999
 
  int pos;
1000
 
  int depth;
1001
 
  ml = graphdata[2] + 4;
1002
 
  for (i = 0; i < len; i++)
1003
 
    {
1004
 
      for (j = 4; j < ml; j++)
1005
 
        {
1006
 
          pos = graphdata[j];
1007
 
          for (depth = 0;;)
1008
 
            {
1009
 
              ppos = pos << 6;
1010
 
              p = graphdata[ppos];
1011
 
              if (p == doc[i + depth])
1012
 
                {
1013
 
                  if (graphdata[ppos + 1] == 1)
1014
 
                    {
1015
 
                      result.push_back (graphdata[ppos + 3]);
1016
 
                    }
1017
 
                  sl = graphdata[ppos + 2];
1018
 
                  if (sl > 0)
1019
 
                    {
1020
 
                      depth++;
1021
 
                      for (k = 1; k < sl; k++)
1022
 
                        {
1023
 
                          stack[stacksize++] = graphdata[ppos + 4 + k];
1024
 
                          stack[stacksize++] = depth;
1025
 
                        }
1026
 
                      pos = graphdata[ppos + 4];
1027
 
                      continue;
1028
 
                    }
1029
 
                }
1030
 
              if (stacksize > 0)
1031
 
                {
1032
 
                  depth = stack[--stacksize];
1033
 
                  pos = stack[--stacksize];
1034
 
                  continue;
1035
 
                }
1036
 
              break;
1037
 
            }
1038
 
        }
1039
 
    }
1040
 
  delete[]stack;
1041
 
  return result;
1042
 
}
1043
 
 
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]...
1046
 
 
1047
 
void
1048
 
ListContainer::graphAdd (String s, int inx, int item)
1049
 
{
1050
 
  unsigned char p = s.charAt (0);
1051
 
  unsigned char c;
1052
 
  bool found = false;
1053
 
  String t;
1054
 
  int i, px, it;
1055
 
  int numlinks;
1056
 
  for (i = 0; i < graphdata[inx * 64 + 2]; i++)
1057
 
    {
1058
 
      c = (unsigned char) graphdata[(graphdata[inx * 64 + 4 + i]) * 64];
1059
 
      if (p == c)
1060
 
        {
1061
 
          t = s;
1062
 
          t.lop ();
1063
 
          if (t.length () > 0)
1064
 
            {
1065
 
              graphAdd (t, graphdata[inx * 64 + 4 + i], item);
1066
 
              return;
1067
 
            }
1068
 
          found = true;
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];
1072
 
          if (px == 1)
1073
 
            {                   // the exact phrase is already there
1074
 
 
1075
 
              px = graphdata[(graphdata[inx * 64 + 4 + i]) * 64 + 3];
1076
 
              it = itemtype[px];
1077
 
 
1078
 
              if ((it > 9 && itemtype[item] < 10) || itemtype[item] == -1)
1079
 
                {
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
1085
 
                  // OR
1086
 
                  // its a an exception
1087
 
                  // exception phrases take presidence
1088
 
                  itemtype[px] = itemtype[item];
1089
 
                  weight[px] = weight[item];
1090
 
                }
1091
 
            }
1092
 
        }
1093
 
    }
1094
 
  if (!found)
1095
 
    {
1096
 
      i = graphitems;
1097
 
      graphitems++;
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;
1103
 
      s.lop ();
1104
 
      while (s.length () > 0)
1105
 
        {
1106
 
          numlinks = graphdata[i * 64 + 2];
1107
 
          graphdata[i * 64 + 2] = numlinks + 1;
1108
 
          graphdata[i * 64 + 4 + numlinks] = i + 1;
1109
 
          i++;
1110
 
          graphitems++;
1111
 
          p = s.charAt (0);
1112
 
          graphdata[i * 64] = p;
1113
 
          graphdata[i * 64 + 3] = item;
1114
 
          s.lop ();
1115
 
        }
1116
 
      graphdata[i * 64 + 1] = 1;
1117
 
    }
1118
 
}
1119
 
 
1120
 
 
1121
 
 
1122
 
// quicksort with 3 way partitioning sorted by the end of the line
1123
 
void
1124
 
ListContainer::quicksortEW (int l, int r)
1125
 
{
1126
 
  if (r <= l)
1127
 
    return;
1128
 
  unsigned int e;
1129
 
  int k;
1130
 
  char *v = data + list[r];
1131
 
  int i = l - 1, j = r, p = i, q = r;
1132
 
  for (;;)
1133
 
    {
1134
 
      while (greaterThanEWF (data + list[++i], v) > 0);
1135
 
      while (greaterThanEWF (v, data + list[--j]) > 0)
1136
 
        {
1137
 
          if (j == l)
1138
 
            break;
1139
 
        }
1140
 
      if (i >= j)
1141
 
        break;
1142
 
      e = list[i];
1143
 
      list[i] = list[j];
1144
 
      list[j] = e;
1145
 
      if (greaterThanEWF (v, data + list[i]) == 0)
1146
 
        {
1147
 
          p++;
1148
 
          e = list[p];
1149
 
          list[p] = list[i];
1150
 
          list[i] = e;
1151
 
        }
1152
 
      if (greaterThanEWF (v, data + list[j]) == 0)
1153
 
        {
1154
 
          q--;
1155
 
          e = list[q];
1156
 
          list[q] = list[j];
1157
 
          list[j] = e;
1158
 
        }
1159
 
    }
1160
 
  e = list[i];
1161
 
  list[i] = list[r];
1162
 
  list[r] = e;
1163
 
  j = i - 1;
1164
 
  i++;
1165
 
  for (k = l; k <= p; k++, j--)
1166
 
    {
1167
 
      e = list[k];
1168
 
      list[k] = list[j];
1169
 
      list[j] = e;
1170
 
    }
1171
 
  for (k = r - 1; k >= q; k--, i++)
1172
 
    {
1173
 
      e = list[k];
1174
 
      list[k] = list[i];
1175
 
      list[i] = e;
1176
 
    }
1177
 
  quicksortEW (l, j);
1178
 
  quicksortEW (i, r);
1179
 
}
1180
 
 
1181
 
// quicksort with 3 way partitioning sorted by the start of the line
1182
 
void
1183
 
ListContainer::quicksortSW (int l, int r)
1184
 
{
1185
 
  if (r <= l)
1186
 
    return;
1187
 
  unsigned int e;
1188
 
  int k;
1189
 
  char *v = data + list[r];
1190
 
  int i = l - 1, j = r, p = i, q = r;
1191
 
  for (;;)
1192
 
    {
1193
 
      while (greaterThanSWF (data + list[++i], v) > 0);
1194
 
      while (greaterThanSWF (v, data + list[--j]) > 0)
1195
 
        {
1196
 
          if (j == l)
1197
 
            break;
1198
 
        }
1199
 
      if (i >= j)
1200
 
        break;
1201
 
      e = list[i];
1202
 
      list[i] = list[j];
1203
 
      list[j] = e;
1204
 
      if (greaterThanSWF (v, data + list[i]) == 0)
1205
 
        {
1206
 
          p++;
1207
 
          e = list[p];
1208
 
          list[p] = list[i];
1209
 
          list[i] = e;
1210
 
        }
1211
 
      if (greaterThanSWF (v, data + list[j]) == 0)
1212
 
        {
1213
 
          q--;
1214
 
          e = list[q];
1215
 
          list[q] = list[j];
1216
 
          list[j] = e;
1217
 
        }
1218
 
    }
1219
 
  e = list[i];
1220
 
  list[i] = list[r];
1221
 
  list[r] = e;
1222
 
  j = i - 1;
1223
 
  i++;
1224
 
  for (k = l; k <= p; k++, j--)
1225
 
    {
1226
 
      e = list[k];
1227
 
      list[k] = list[j];
1228
 
      list[j] = e;
1229
 
    }
1230
 
  for (k = r - 1; k >= q; k--, i++)
1231
 
    {
1232
 
      e = list[k];
1233
 
      list[k] = list[i];
1234
 
      list[i] = e;
1235
 
    }
1236
 
  quicksortSW (l, j);
1237
 
  quicksortSW (i, r);
1238
 
}
1239
 
 
1240
 
bool
1241
 
ListContainer::readProcessedItemList (const char *filename, bool startswith, int filters)
1242
 
{
1243
 
#ifdef DGDEBUG
1244
 
  std::cout << "reading processed file:" << filename << std::endl;
1245
 
#endif
1246
 
  int len = getFileLength (filename);
1247
 
  int slen, i;
1248
 
  if (len < 0)
1249
 
    {
1250
 
      if (!isDaemonised)
1251
 
        {
1252
 
          std::cerr << "Error reading file: " << filename << std::endl;
1253
 
        }
1254
 
      syslog (LOG_ERR, "%s", "Error reading file:");
1255
 
      syslog (LOG_ERR, "%s", filename);
1256
 
      return false;
1257
 
    }
1258
 
  if (len < 5)
1259
 
    {
1260
 
      if (!isDaemonised)
1261
 
        {
1262
 
          std::cerr << "File too small (less than 5 bytes - is it corrupt?): " << filename << std::endl;
1263
 
        }
1264
 
      syslog (LOG_ERR, "%s", "File too small (less than 5 bytes - is it corrupt?):");
1265
 
      syslog (LOG_ERR, "%s", filename);
1266
 
      return false;
1267
 
    }
1268
 
  increaseMemoryBy (len + 2);
1269
 
  ifstream listfile (filename, ios::in);
1270
 
  if (!listfile.good ())
1271
 
    {
1272
 
      if (!isDaemonised)
1273
 
        {
1274
 
          std::cerr << "Error opening: " << filename << std::endl;
1275
 
        }
1276
 
      syslog (LOG_ERR, "%s", "Error opening:");
1277
 
      syslog (LOG_ERR, "%s", filename);
1278
 
      return false;
1279
 
    }
1280
 
  std::string linebuffer;
1281
 
  String temp, inc;
1282
 
  while (!listfile.eof ())
1283
 
    {
1284
 
      getline (listfile, linebuffer);
1285
 
      if (linebuffer[0] == '.')
1286
 
        {
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))
1292
 
                {               // read it
1293
 
                  listfile.close ();
1294
 
                  return false;
1295
 
                }
1296
 
              continue;
1297
 
            }
1298
 
        }
1299
 
      slen = linebuffer.length ();
1300
 
      if (slen < 3)
1301
 
        continue;
1302
 
      i = slen - 1;
1303
 
      list.push_back (data_length);
1304
 
      for (; i >= 0; i--)
1305
 
        {
1306
 
          data[data_length + i] = linebuffer[i];
1307
 
        }
1308
 
      data[data_length + slen] = 0;
1309
 
      data_length += slen + 1;
1310
 
      items++;
1311
 
    }
1312
 
  listfile.close ();
1313
 
  return true;
1314
 
}
1315
 
 
1316
 
 
1317
 
void
1318
 
ListContainer::addToItemList (char *s, int len)
1319
 
{
1320
 
  int i;
1321
 
  list.push_back (data_length);
1322
 
  for (i = 0; i < len; i++)
1323
 
    {
1324
 
      data[data_length + i] = s[i];
1325
 
    }
1326
 
  data[data_length + len] = 0;
1327
 
  data_length += len + 1;
1328
 
  items++;
1329
 
}
1330
 
 
1331
 
 
1332
 
 
1333
 
int
1334
 
ListContainer::searchRSWF (int a, int s, const char *p)
1335
 
{
1336
 
  if (a > s)
1337
 
    return (-1 - a);
1338
 
  int m = (a + s) / 2;
1339
 
  int r = greaterThanSWF (p, data + list[m]);
1340
 
  if (r == 0)
1341
 
    return m;
1342
 
  if (r == -1)
1343
 
    return searchRSWF (m + 1, s, p);
1344
 
  if (a == s)
1345
 
    return (-1 - a);
1346
 
  return searchRSWF (a, m - 1, p);
1347
 
}
1348
 
 
1349
 
int
1350
 
ListContainer::searchRSW (int a, int s, const char *p)
1351
 
{
1352
 
  if (a > s)
1353
 
    return (-1 - a);
1354
 
  int m = (a + s) / 2;
1355
 
  int r = greaterThanSW (p, data + list[m]);
1356
 
  if (r == 0)
1357
 
    return m;
1358
 
  if (r == -1)
1359
 
    return searchRSW (m + 1, s, p);
1360
 
  if (a == s)
1361
 
    return (-1 - a);
1362
 
  return searchRSW (a, m - 1, p);
1363
 
}
1364
 
 
1365
 
int
1366
 
ListContainer::searchREWF (int a, int s, const char *p)
1367
 
{
1368
 
  if (a > s)
1369
 
    return (-1 - a);
1370
 
  int m = (a + s) / 2;
1371
 
  int r = greaterThanEWF (p, data + list[m]);
1372
 
  if (r == 0)
1373
 
    return m;
1374
 
  if (r == -1)
1375
 
    return searchREWF (m + 1, s, p);
1376
 
  if (a == s)
1377
 
    return (-1 - a);
1378
 
  return searchREWF (a, m - 1, p);
1379
 
}
1380
 
 
1381
 
 
1382
 
int
1383
 
ListContainer::searchREW (int a, int s, const char *p)
1384
 
{
1385
 
  if (a > s)
1386
 
    return (-1 - a);
1387
 
  int m = (a + s) / 2;
1388
 
  int r = greaterThanEW (p, data + list[m]);
1389
 
  if (r == 0)
1390
 
    return m;
1391
 
  if (r == -1)
1392
 
    return searchREW (m + 1, s, p);
1393
 
  if (a == s)
1394
 
    return (-1 - a);
1395
 
  return searchREW (a, m - 1, p);
1396
 
}
1397
 
 
1398
 
 
1399
 
int
1400
 
ListContainer::greaterThanEWF (const char *a, const char *b)
1401
 
{
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;
1409
 
  while (maxlen > 0)
1410
 
    {
1411
 
      achar = apos[0];
1412
 
      bchar = bpos[0];
1413
 
      if (achar > bchar)
1414
 
        {
1415
 
          return 1;
1416
 
        }
1417
 
      if (achar < bchar)
1418
 
        {
1419
 
          return -1;
1420
 
        }
1421
 
      maxlen--;
1422
 
      apos--;
1423
 
      bpos--;
1424
 
    }
1425
 
  if (alen > blen)
1426
 
    {
1427
 
      return 1;
1428
 
    }
1429
 
  if (alen < blen)
1430
 
    {
1431
 
      return -1;
1432
 
    }
1433
 
  return 0;                     // both equal
1434
 
}
1435
 
 
1436
 
 
1437
 
int
1438
 
ListContainer::greaterThanSWF (const char *a, const char *b)
1439
 
{
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;
1445
 
  int i = 0;
1446
 
  unsigned char achar;
1447
 
  unsigned char bchar;
1448
 
  while (i < maxlen)
1449
 
    {
1450
 
      achar = apos[0];
1451
 
      bchar = bpos[0];
1452
 
      if (achar > bchar)
1453
 
        {
1454
 
          return 1;
1455
 
        }
1456
 
      if (achar < bchar)
1457
 
        {
1458
 
          return -1;
1459
 
        }
1460
 
      i++;
1461
 
      apos++;
1462
 
      bpos++;
1463
 
    }
1464
 
  if (alen > blen)
1465
 
    {
1466
 
      return 1;
1467
 
    }
1468
 
  if (alen < blen)
1469
 
    {
1470
 
      return -1;
1471
 
    }
1472
 
  return 0;                     // both equal
1473
 
}
1474
 
 
1475
 
int
1476
 
ListContainer::greaterThanSW (const char *a, const char *b)
1477
 
{
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;
1486
 
  while (i < maxlen)
1487
 
    {
1488
 
      achar = apos[0];
1489
 
      bchar = bpos[0];
1490
 
      if (achar > bchar)
1491
 
        {
1492
 
          return 1;
1493
 
        }
1494
 
      if (achar < bchar)
1495
 
        {
1496
 
          return -1;
1497
 
        }
1498
 
      i++;
1499
 
      apos++;
1500
 
      bpos++;
1501
 
    }
1502
 
  if (blen > alen)
1503
 
    return -1;
1504
 
  return 0;                     // both equal
1505
 
}
1506
 
 
1507
 
int
1508
 
ListContainer::greaterThanEW (const char *a, const char *b)
1509
 
{
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;
1517
 
  while (maxlen > 0)
1518
 
    {
1519
 
      achar = apos[0];
1520
 
      bchar = bpos[0];
1521
 
      if (achar > bchar)
1522
 
        {
1523
 
          return 1;
1524
 
        }
1525
 
      if (achar < bchar)
1526
 
        {
1527
 
          return -1;
1528
 
        }
1529
 
      maxlen--;
1530
 
      apos--;
1531
 
      bpos--;
1532
 
    }
1533
 
  if (blen > alen)
1534
 
    return -1;
1535
 
  return 0;                     // both equal
1536
 
}
1537
 
 
1538
 
bool ListContainer::isCacheFileNewer (const char *filename)
1539
 
{
1540
 
  int
1541
 
    len = getFileLength (filename);
1542
 
  if (len < 0)
1543
 
    {
1544
 
      if (!isDaemonised)
1545
 
        {
1546
 
          std::cerr << "Error reading file: " << filename << std::endl;
1547
 
        }
1548
 
      syslog (LOG_ERR, "%s", "Error reading file:");
1549
 
      syslog (LOG_ERR, "%s", filename);
1550
 
      return false;
1551
 
    }
1552
 
  int
1553
 
    bannedlistdate = getFileDate (filename);
1554
 
  std::string linebuffer = filename;
1555
 
  linebuffer += ".processed";
1556
 
  int
1557
 
    cachedate = getFileDate (linebuffer.c_str ());
1558
 
  if (cachedate < bannedlistdate)
1559
 
    {
1560
 
      return false;             // cache file is older than list file
1561
 
    }
1562
 
  return true;
1563
 
}
1564
 
 
1565
 
void
1566
 
ListContainer::increaseMemoryBy (int bytes)
1567
 
{
1568
 
  if (data_memory > 0)
1569
 
    {
1570
 
      char *temp = new char[data_memory + bytes];       // replacement store
1571
 
      memcpy (temp, data, data_length);
1572
 
      delete[]data;
1573
 
      data = temp;
1574
 
      data_memory = data_memory + bytes;
1575
 
    }
1576
 
  else
1577
 
    {
1578
 
      delete[]data;
1579
 
      data = new char[bytes];
1580
 
      data_memory = bytes;
1581
 
    }
1582
 
}
1583
 
 
1584
 
 
1585
 
 
1586
 
std::string ListContainer::toLower (std::string s)
1587
 
{
1588
 
  int
1589
 
    l = s.length ();
1590
 
  for (int i = 0; i < l; i++)
1591
 
    {
1592
 
      if ((s[i] >= 'A') && (s[i] <= 'Z'))
1593
 
        {
1594
 
          s[i] = 'a' + s[i] - 'A';
1595
 
        }
1596
 
    }
1597
 
  return s;
1598
 
}
1599
 
 
1600
 
 
1601
 
int
1602
 
ListContainer::getFileLength (const char *filename)
1603
 
{
1604
 
  int len;
1605
 
  FILE *file = NULL;
1606
 
  file = fopen (filename, "r");
1607
 
  if (file)
1608
 
    {
1609
 
      if (!fseek (file, 0, SEEK_END))
1610
 
        {
1611
 
          len = ftell (file);
1612
 
        }
1613
 
      else
1614
 
        {
1615
 
          len = -1;
1616
 
        }
1617
 
      fclose (file);
1618
 
      return len;
1619
 
    }
1620
 
  return -1;
1621
 
}
1622
 
 
1623
 
int
1624
 
ListContainer::getFileDate (const char *filename)
1625
 
{
1626
 
  struct stat status;
1627
 
  int rc = stat (filename, &status);
1628
 
  if (rc != 0)
1629
 
    {
1630
 
      return -1;
1631
 
    }
1632
 
  struct tm *tmnow = localtime (&status.st_mtime);
1633
 
 
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
1641
 
}
1642
 
 
1643
 
 
1644
 
bool ListContainer::upToDate ()
1645
 
{
1646
 
  if (getFileDate (sourcefile.toCharArray ()) > filedate)
1647
 
    {
1648
 
      return false;
1649
 
    }
1650
 
  for (unsigned int i = 0; i < morelists.size (); i++)
1651
 
    {
1652
 
      if (!(*o.lm.l[morelists[i]]).upToDate ())
1653
 
        {
1654
 
          return false;
1655
 
        }
1656
 
    }
1657
 
  return true;
1658
 
}