~ubuntu-branches/ubuntu/precise/dspam/precise

« back to all changes in this revision

Viewing changes to src/sqlite3_drv.c

  • Committer: Bazaar Package Importer
  • Author(s): Julien Valroff, Kurt B. Kaiser, Julien Valroff
  • Date: 2011-03-28 15:04:10 UTC
  • mfrom: (1.1.3 upstream)
  • mto: (8.1.5 sid)
  • mto: This revision was merged to the branch mainline in revision 23.
  • Revision ID: james.westby@ubuntu.com-20110328150410-3zsgfxn4lcc708kt
Tags: 3.9.1~rc1+git20110312.9a9050f+dfsg-1
[ Kurt B. Kaiser ]
* debian/rules: don't use --build config option if host equals target.
* debian/rules: dpkg-dev now handles CFLAGS.
* Use maintainer-clean in clean target and remove any Makefile.in left over.
* Remove libapache2-mod-auth-shadow - no longer available in unstable
* Suggest clamav-daemon instead of recommending it.
* Suggest dspam-webfrontend.
* Add amavis to trusted users (Closes: #477508)
* Use dh_lintian to install the webfrontend conffile override
* Webfrontend improvements:
  - Delete the old, obsolete apache.conf file from the package, and
    purge it when dspam-webfrontend is purged if it is present in
    /etc/dspam/.
  - Move the html templates to /etc/dspam/templates/
  - Install the apache conf fragment as an example in dspam-webfrontend 
  - Modify apache2.conf to install a working example website. Use
    /etc/dspam/passwd, which doesn't need access to /etc/shadow.
    (Closes: #430589)
  - Clean up customize-cgi.txt and add it to README.Debian. 

[ Julien Valroff ]
* New upstream release
  (Closes: #418736, #491387, #505010, #514498, #577661, #445890, #383964,
  #430840, #568068)
* Bump Standards to 3.9.1:
  - Add README.source, as per Debian Policy Manual 4.14
* Bump debhelper compatibility to 8
* Update/remove patches for new release
* Add misc depends to all binary packages
* Rewrite package descriptions
* Use dh_prep instead of dh_clean -k
* Drop obsolete db4 driver (Closes: #601209)
* Update copyright information
* Add Vcs-* and Homepage fields in control file
* Remove useless DMUA field 
* Add TODO.Debian file to describe planned changes to DSPAM Debian packages
* Fix watch file to track upstream releases on new hosting location
* Remove /var/run/dspam from dspam.dirs to make lintian happy - the init
  script makes sure the directory is created before starting dspam
* Install examples scripts using dh_installexamples
* Update SQL schemas and make sure the databases are updated when upgrading
  from 3.6.8 using dbconfig-common
* Set default database name and user name to dspam for both MySQL and PgSQL
* Make dspam-webfrontend suggest apache2
* Remove inactive & MIA uploaders (Closes: #503488)
* Add myself as uploader
* Add depends on other MDAs than procmail (Closes: #506312)
* Honour $USER in call to chmod (Closes: #505217)
* Fix MySQL daily cronjob to work correctly when using storage profiles
* Make MySQL daily cronjob quiet
* Fix build-dependencies to use current automake version and use
  unversionned libmysqclient-dev
* Drop runtime dependencies on debconf - unneeded as this package
  is "required"
* Purge ucf database and ucf config files on package purge
* Remove unused lintian overrides
* Add description to all patches
* Rewrite init script based on the current skeleton shipped in the
  initscripts package
* Add numerical prefixes to Debian patches 
* Fix verbose_bug build option
* Add logrotate entry for dspam.messages and sql.errors
* Add 'notifempty' option for logrotate
* Fix 'hyphen-used-as-minus-sign' lintian information: escape all --
  in manpages
* Update dspam_admin manpage to list aggregate feature
* Makes drv-sqlite3 daily cronjob quiet if package is removed and
  not purged - thanks to Petter Reinholdtsen <pere@hungry.com>
  (Closes: #540064, #562857)
* Converted source package to 3.0 (quilt) format
* Add dependency to libhtml-parser-perl for the webfrontend
* Opt Out is now the default condfiguration, as per upstream default
* Default daemon port is set to 2424 as dspam daemon is run by an
  unprivileged user (Closes: #385760)
* Add explicit dependency on perl
* Fix typo in README.source
* Fix daily cron scripts to avoid problems if the user has added
  two identical entries for certain values
  (thanks to Stevan Bajić <stevan@bajic.ch>)
* Add automatic configuration file splitting snippet in rules
  (thanks to Stevan Bajić <stevan@bajic.ch>)
* Make use of dspam_maintenance.sh script instead of homemade purge scripts
* Only ships SQL files for MySQL >= 4.1 as no older version is available
  in Debian
* Add dspam_notify script in dspam-webfrontend to send automatic quarantine
  email notification
* Add debug package which ships debugging symbols
* Switch to dh style rules file
* Repack upstream tarball to make DFSG clean sources and add explanations to
  README.source file

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: sqlite3_drv.c,v 1.14 2006/05/13 15:08:05 jonz Exp $ */
 
1
/* $Id: sqlite3_drv.c,v 1.185 2010/02/12 12:27:20 sbajic Exp $ */
2
2
 
3
3
/*
4
4
 DSPAM
5
 
 COPYRIGHT (C) 2002-2006 JONATHAN A. ZDZIARSKI
 
5
 COPYRIGHT (C) 2002-2010 DSPAM PROJECT
6
6
 
7
7
 This program is free software; you can redistribute it and/or
8
8
 modify it under the terms of the GNU General Public License
96
96
  memset(&CTX->totals, 0, sizeof(struct _ds_spam_totals));
97
97
 
98
98
  snprintf (query, sizeof (query),
99
 
            "select spam_learned, innocent_learned, "
100
 
            "spam_misclassified, innocent_misclassified, "
101
 
            "spam_corpusfed, innocent_corpusfed, "
102
 
            "spam_classified, innocent_classified "
103
 
            " from dspam_stats");
 
99
            "SELECT spam_learned,innocent_learned,"
 
100
            "spam_misclassified,innocent_misclassified,"
 
101
            "spam_corpusfed,innocent_corpusfed,"
 
102
            "spam_classified,innocent_classified"
 
103
            " FROM dspam_stats");
104
104
 
105
105
  if ((sqlite3_get_table(s->dbh, query, &row, &nrow, &ncolumn, &err))!=SQLITE_OK)
106
106
  {
109
109
  }
110
110
 
111
111
  if (nrow>0 && row != NULL) {
112
 
    CTX->totals.spam_learned            = strtol (row[ncolumn], NULL, 0);
113
 
    CTX->totals.innocent_learned        = strtol (row[ncolumn+1], NULL, 0);
114
 
    CTX->totals.spam_misclassified      = strtol (row[ncolumn+2], NULL, 0);
115
 
    CTX->totals.innocent_misclassified  = strtol (row[ncolumn+3], NULL, 0);
116
 
    CTX->totals.spam_corpusfed          = strtol (row[ncolumn+4], NULL, 0);
117
 
    CTX->totals.innocent_corpusfed      = strtol (row[ncolumn+5], NULL, 0);
118
 
    CTX->totals.spam_classified         = strtol (row[ncolumn+6], NULL, 0);
119
 
    CTX->totals.innocent_classified     = strtol (row[ncolumn+7], NULL, 0);
 
112
    CTX->totals.spam_learned            = strtoul (row[ncolumn], NULL, 0);
 
113
    if (CTX->totals.spam_learned == ULONG_MAX && errno == ERANGE) {
 
114
      LOGDEBUG("_sqlite_drv_get_spamtotals: failed converting %s to CTX->totals.spam_learned", row[ncolumn]);
 
115
      rc = EFAILURE;
 
116
      goto FAIL;
 
117
    }
 
118
    CTX->totals.innocent_learned        = strtoul (row[ncolumn+1], NULL, 0);
 
119
    if (CTX->totals.innocent_learned == ULONG_MAX && errno == ERANGE) {
 
120
      LOGDEBUG("_sqlite_drv_get_spamtotals: failed converting %s to CTX->totals.innocent_learned", row[ncolumn+1]);
 
121
      rc = EFAILURE;
 
122
      goto FAIL;
 
123
    }
 
124
    CTX->totals.spam_misclassified      = strtoul (row[ncolumn+2], NULL, 0);
 
125
    if (CTX->totals.spam_misclassified == ULONG_MAX && errno == ERANGE) {
 
126
      LOGDEBUG("_sqlite_drv_get_spamtotals: failed converting %s to CTX->totals.spam_misclassified", row[ncolumn+2]);
 
127
      rc = EFAILURE;
 
128
      goto FAIL;
 
129
    }
 
130
    CTX->totals.innocent_misclassified  = strtoul (row[ncolumn+3], NULL, 0);
 
131
    if (CTX->totals.innocent_misclassified == ULONG_MAX && errno == ERANGE) {
 
132
      LOGDEBUG("_sqlite_drv_get_spamtotals: failed converting %s to CTX->totals.innocent_misclassified", row[ncolumn+3]);
 
133
      rc = EFAILURE;
 
134
      goto FAIL;
 
135
    }
 
136
    CTX->totals.spam_corpusfed          = strtoul (row[ncolumn+4], NULL, 0);
 
137
    if (CTX->totals.spam_corpusfed == ULONG_MAX && errno == ERANGE) {
 
138
      LOGDEBUG("_sqlite_drv_get_spamtotals: failed converting %s to CTX->totals.spam_corpusfed", row[ncolumn+4]);
 
139
      rc = EFAILURE;
 
140
      goto FAIL;
 
141
    }
 
142
    CTX->totals.innocent_corpusfed      = strtoul (row[ncolumn+5], NULL, 0);
 
143
    if (CTX->totals.innocent_corpusfed == ULONG_MAX && errno == ERANGE) {
 
144
      LOGDEBUG("_sqlite_drv_get_spamtotals: failed converting %s to CTX->totals.innocent_corpusfed", row[ncolumn+5]);
 
145
      rc = EFAILURE;
 
146
      goto FAIL;
 
147
    }
 
148
    if (row[ncolumn+6] != NULL && row[ncolumn+7] != NULL) {
 
149
      CTX->totals.spam_classified       = strtoul (row[ncolumn+6], NULL, 0);
 
150
      if (CTX->totals.spam_classified == ULONG_MAX && errno == ERANGE) {
 
151
        LOGDEBUG("_sqlite_drv_get_spamtotals: failed converting %s to CTX->totals.spam_classified", row[ncolumn+6]);
 
152
        rc = EFAILURE;
 
153
        goto FAIL;
 
154
      }
 
155
      CTX->totals.innocent_classified   = strtoul (row[ncolumn+7], NULL, 0);
 
156
      if (CTX->totals.innocent_classified == ULONG_MAX && errno == ERANGE) {
 
157
        LOGDEBUG("_sqlite_drv_get_spamtotals: failed converting %s to CTX->totals.innocent_classified", row[ncolumn+7]);
 
158
        rc = EFAILURE;
 
159
        goto FAIL;
 
160
      }
 
161
    } else {
 
162
      CTX->totals.spam_classified       = 0;
 
163
      CTX->totals.innocent_classified   = 0;
 
164
    }
120
165
    rc = 0;
121
166
  } else {
122
167
    rc = EFAILURE;
123
168
  }
124
169
 
 
170
FAIL:
125
171
  sqlite3_free_table(row);
126
172
  if ( !rc )
127
173
    memcpy(&s->control_totals, &CTX->totals, sizeof(struct _ds_spam_totals));
135
181
  struct _sqlite_drv_storage *s = (struct _sqlite_drv_storage *) CTX->storage;
136
182
  char query[1024];
137
183
  char *err=NULL;
138
 
  int result;
 
184
  int result = SQLITE_OK;
139
185
 
140
186
  if (s->dbh == NULL)
141
187
  {
154
200
  if (s->control_totals.innocent_learned == 0)
155
201
  {
156
202
    snprintf (query, sizeof (query),
157
 
              "insert into dspam_stats(dspam_stat_id, spam_learned, " 
158
 
              "innocent_learned, spam_misclassified, innocent_misclassified, "
159
 
              "spam_corpusfed, innocent_corpusfed, "
160
 
              "spam_classified, innocent_classified) "
161
 
              "values(%d, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld)",
 
203
              "INSERT INTO dspam_stats (dspam_stat_id,spam_learned,"
 
204
              "innocent_learned,spam_misclassified,innocent_misclassified,"
 
205
              "spam_corpusfed,innocent_corpusfed,"
 
206
              "spam_classified,innocent_classified)"
 
207
              " VALUES (%d,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu)",
162
208
              0,
163
209
              CTX->totals.spam_learned,
164
 
              CTX->totals.innocent_learned, 
165
 
              CTX->totals.spam_misclassified,
166
 
              CTX->totals.innocent_misclassified, 
167
 
              CTX->totals.spam_corpusfed,
168
 
              CTX->totals.innocent_corpusfed, 
169
 
              CTX->totals.spam_classified,
 
210
              CTX->totals.innocent_learned, CTX->totals.spam_misclassified,
 
211
              CTX->totals.innocent_misclassified, CTX->totals.spam_corpusfed,
 
212
              CTX->totals.innocent_corpusfed, CTX->totals.spam_classified,
170
213
              CTX->totals.innocent_classified);
171
 
    result = sqlite3_exec(s->dbh, query, NULL, NULL, &err);
 
214
    result = sqlite3_exec(s->dbh, query, NULL, NULL, NULL);
172
215
  }
173
216
 
174
217
  if (s->control_totals.innocent_learned != 0 || result != SQLITE_OK)
175
218
  {
176
219
    snprintf (query, sizeof (query),
177
 
              "update dspam_stats set spam_learned = spam_learned %s %d, "
178
 
              "innocent_learned = innocent_learned %s %d, "
179
 
              "spam_misclassified = spam_misclassified %s %d, "
180
 
              "innocent_misclassified = innocent_misclassified %s %d, "
181
 
              "spam_corpusfed = spam_corpusfed %s %d, "
182
 
              "innocent_corpusfed = innocent_corpusfed %s %d, "
183
 
              "spam_classified = spam_classified %s %d, "
184
 
              "innocent_classified = innocent_classified %s %d ",
 
220
              "UPDATE dspam_stats SET spam_learned=spam_learned%s%d,"
 
221
              "innocent_learned=innocent_learned%s%d,"
 
222
              "spam_misclassified=spam_misclassified%s%d,"
 
223
              "innocent_misclassified=innocent_misclassified%s%d,"
 
224
              "spam_corpusfed=spam_corpusfed%s%d,"
 
225
              "innocent_corpusfed=innocent_corpusfed%s%d,"
 
226
              "spam_classified=spam_classified%s%d,"
 
227
              "innocent_classified=innocent_classified%s%d",
185
228
              (CTX->totals.spam_learned >
186
229
               s->control_totals.spam_learned) ? "+" : "-",
187
230
              abs (CTX->totals.spam_learned -
233
276
  ds_term_t ds_term;
234
277
  ds_cursor_t ds_c;
235
278
  char scratch[1024];
 
279
  char queryhead[1024];
236
280
  struct _ds_spam_stat stat;
237
281
  unsigned long long token = 0;
238
 
  char *err=NULL, **row;
239
 
  int nrow, ncolumn, get_one = 0, i;
 
282
  char *err=NULL, **row=NULL;
 
283
  int nrow, ncolumn, i;
 
284
 
 
285
  if (diction->items < 1)
 
286
    return 0;
240
287
 
241
288
  if (s->dbh == NULL)
242
289
  {
246
293
 
247
294
  stat.spam_hits = 0;
248
295
  stat.innocent_hits = 0;
 
296
  stat.probability   = 0.00000;
249
297
 
250
298
  query = buffer_create (NULL);
251
299
  if (query == NULL)
254
302
    return EUNKNOWN;
255
303
  }
256
304
 
257
 
  snprintf (scratch, sizeof (scratch),
258
 
            "select token, spam_hits, innocent_hits "
259
 
            "from dspam_token_data where token in(");
 
305
  snprintf (queryhead, sizeof (queryhead),
 
306
            "SELECT token,spam_hits,innocent_hits"
 
307
            " FROM dspam_token_data WHERE token IN (");
260
308
 
261
 
  buffer_cat (query, scratch);
262
309
  ds_c = ds_diction_cursor(diction);
263
310
  ds_term = ds_diction_next(ds_c);
264
 
  while (ds_term)
265
 
  {
266
 
    snprintf (scratch, sizeof (scratch), "'%" LLU_FMT_SPEC "'", ds_term->key);
267
 
    buffer_cat (query, scratch);
268
 
    ds_term->s.innocent_hits = 0;
269
 
    ds_term->s.spam_hits = 0;
270
 
    ds_term->s.probability = 0;
271
 
    ds_term->s.status &= ~TST_DISK;
272
 
    ds_term = ds_diction_next(ds_c);
273
 
    if (ds_term)
274
 
      buffer_cat (query, ",");
275
 
    get_one = 1;
276
 
  }
277
 
  ds_diction_close(ds_c);
278
 
  buffer_cat (query, ")");
 
311
  while (ds_term) {
 
312
    scratch[0] = 0;
 
313
    buffer_copy(query, queryhead);
 
314
    while (ds_term) {
 
315
      snprintf (scratch, sizeof (scratch), "'%" LLU_FMT_SPEC "'", ds_term->key);
 
316
      buffer_cat (query, scratch);
 
317
      ds_term->s.innocent_hits = 0;
 
318
      ds_term->s.spam_hits = 0;
 
319
      ds_term->s.probability = 0.00000;
 
320
      ds_term->s.status = 0;
 
321
      if((query->used + 1024) > 1000000) {
 
322
        LOGDEBUG("_ds_getall_spamrecords: Splitting query at %ld characters", query->used);
 
323
        break;
 
324
      }
 
325
      ds_term = ds_diction_next(ds_c);
 
326
      if (ds_term)
 
327
        buffer_cat (query, ",");
 
328
    }
 
329
    buffer_cat (query, ")");
279
330
 
280
331
#ifdef VERBOSE
281
 
  LOGDEBUG ("sqlite query length: %ld\n", query->used);
282
 
  _sqlite_drv_query_error (strdup("VERBOSE DEBUG (INFO ONLY - NOT AN ERROR)"), query->data);
 
332
    LOGDEBUG ("SQLite query length: %ld\n", query->used);
 
333
    _sqlite_drv_query_error (strdup("VERBOSE DEBUG (INFO ONLY - NOT AN ERROR)"), query->data);
283
334
#endif
284
335
 
285
 
  if (!get_one) 
286
 
    return 0;
287
 
 
288
 
  if ((sqlite3_get_table(s->dbh, query->data, &row, &nrow, &ncolumn, &err))
289
 
      !=SQLITE_OK)
290
 
  {
291
 
    _sqlite_drv_query_error (err, query->data);
292
 
    buffer_destroy(query);
293
 
    return EFAILURE;
294
 
  }
295
 
 
296
 
  if (nrow < 1) {
297
 
    sqlite3_free_table(row);
298
 
    buffer_destroy(query);
299
 
    return 0;
300
 
  }
301
 
 
302
 
  if (row == NULL)
303
 
    return 0;
304
 
 
305
 
  stat.probability = 0;
306
 
  stat.status |= TST_DISK;
307
 
  for(i=1;i<=nrow;i++) {
308
 
    token = strtoull (row[(i*ncolumn)], NULL, 0);
309
 
    stat.spam_hits = strtol (row[1+(i*ncolumn)], NULL, 0);
310
 
    stat.innocent_hits = strtol (row[2+(i*ncolumn)], NULL, 0);
311
 
 
312
 
    if (stat.spam_hits < 0)
313
 
      stat.spam_hits = 0;
314
 
    if (stat.innocent_hits < 0)
315
 
      stat.innocent_hits = 0;
316
 
 
317
 
    ds_diction_addstat(diction, token, &stat);
318
 
  }
319
 
 
320
 
  sqlite3_free_table(row);
321
 
 
322
 
  ds_c = ds_diction_cursor(diction);
323
 
  ds_term = ds_diction_next(ds_c);
324
 
  while(ds_term && !s->control_token) {
325
 
    if (ds_term->s.spam_hits && ds_term->s.innocent_hits) {
326
 
      s->control_token = ds_term->key;
327
 
      s->control_sh = ds_term->s.spam_hits;
328
 
      s->control_ih = ds_term->s.innocent_hits;
329
 
    }
 
336
    if ((sqlite3_get_table(s->dbh, query->data, &row, &nrow, &ncolumn, &err))
 
337
        !=SQLITE_OK)
 
338
    {
 
339
      _sqlite_drv_query_error (err, query->data);
 
340
      LOGDEBUG ("_ds_getall_spamrecords: unable to run query: %s", query->data);
 
341
      buffer_destroy(query);
 
342
      ds_diction_close(ds_c);
 
343
      return EFAILURE;
 
344
    }
 
345
 
 
346
    if (nrow < 1) {
 
347
      sqlite3_free_table(row);
 
348
      buffer_destroy(query);
 
349
      ds_diction_close(ds_c);
 
350
      return 0;
 
351
    }
 
352
 
 
353
    if (row == NULL) {
 
354
      buffer_destroy(query);
 
355
      ds_diction_close(ds_c);
 
356
      return 0;
 
357
    }
 
358
 
 
359
    for(i=1;i<=nrow;i++) {
 
360
      token = strtoull (row[(i*ncolumn)], NULL, 0);
 
361
      stat.spam_hits = strtoul (row[1+(i*ncolumn)], NULL, 0);
 
362
      if (stat.spam_hits == ULONG_MAX && errno == ERANGE) {
 
363
        LOGDEBUG("_ds_getall_spamrecords: failed converting %s to stat.spam_hits", row[1+(i*ncolumn)]);
 
364
        sqlite3_free_table(row);
 
365
        return EFAILURE;
 
366
      }
 
367
      stat.innocent_hits = strtoul (row[2+(i*ncolumn)], NULL, 0);
 
368
      if (stat.innocent_hits == ULONG_MAX && errno == ERANGE) {
 
369
        LOGDEBUG("_ds_getall_spamrecords: failed converting %s to stat.innocent_hits", row[2+(i*ncolumn)]);
 
370
        sqlite3_free_table(row);
 
371
        return EFAILURE;
 
372
      }
 
373
      stat.status = 0;
 
374
      stat.status |= TST_DISK;
 
375
      if (stat.spam_hits < 0)
 
376
        stat.spam_hits = 0;
 
377
      if (stat.innocent_hits < 0)
 
378
        stat.innocent_hits = 0;
 
379
      ds_diction_addstat(diction, token, &stat);
 
380
    }
 
381
    if (row != NULL)
 
382
      sqlite3_free_table(row);
 
383
    row = NULL;
330
384
    ds_term = ds_diction_next(ds_c);
331
385
  }
332
386
  ds_diction_close(ds_c);
333
 
 
334
 
  if (!s->control_token)
335
 
  {
336
 
    ds_c = ds_diction_cursor(diction);
337
 
    ds_term = ds_diction_next(ds_c);
338
 
    s->control_token = ds_term->key;
339
 
    s->control_sh = ds_term->s.spam_hits;
340
 
    s->control_ih = ds_term->s.innocent_hits;
341
 
    ds_diction_close(ds_c);
342
 
  }
343
 
 
344
387
  buffer_destroy (query);
 
388
  if (row != NULL)
 
389
    sqlite3_free_table(row);
 
390
  row = NULL;
 
391
 
 
392
  /* Control token */
 
393
  stat.spam_hits = 10;
 
394
  stat.innocent_hits = 10;
 
395
  stat.status = 0;
 
396
  ds_diction_touch(diction, CONTROL_TOKEN, "$$CONTROL$$", 0);
 
397
  ds_diction_addstat(diction, CONTROL_TOKEN, &stat);
 
398
  s->control_token = CONTROL_TOKEN;
 
399
  s->control_ih = 10;
 
400
  s->control_sh = 10;
 
401
 
345
402
  return 0;
346
403
}
347
404
 
349
406
_ds_setall_spamrecords (DSPAM_CTX * CTX, ds_diction_t diction)
350
407
{
351
408
  struct _sqlite_drv_storage *s = (struct _sqlite_drv_storage *) CTX->storage;
352
 
  struct _ds_spam_stat stat, stat2;
 
409
  struct _ds_spam_stat control, stat;
353
410
  ds_term_t ds_term;
354
411
  ds_cursor_t ds_c;
 
412
  char queryhead[1024];
355
413
  buffer *query;
356
414
  char scratch[1024];
357
415
  char *err=NULL;
358
 
  int update_one = 0;
 
416
  int update_any = 0;
 
417
 
 
418
  if (diction->items < 1)
 
419
    return 0;
359
420
 
360
421
  if (s->dbh == NULL)
361
422
  {
375
436
    return EUNKNOWN;
376
437
  }
377
438
 
378
 
  if (s->control_token == 0)
379
 
  {
380
 
    ds_c = ds_diction_cursor(diction);
381
 
    ds_term = ds_diction_next(ds_c);
382
 
    if (ds_term == NULL)
383
 
    {
384
 
      stat.spam_hits = 0;
385
 
      stat.innocent_hits = 0;
386
 
    }
387
 
    else
388
 
    {
389
 
      stat.spam_hits = ds_term->s.spam_hits;
390
 
      stat.innocent_hits = ds_term->s.innocent_hits;
391
 
    }
392
 
    ds_diction_close(ds_c);
393
 
  }
394
 
  else
395
 
  {
396
 
    ds_diction_getstat(diction, s->control_token, &stat);
397
 
  }
398
 
 
399
 
  snprintf (scratch, sizeof (scratch),
400
 
            "update dspam_token_data set last_hit = date('now'), "
401
 
            "spam_hits = max(0, spam_hits %s %d), "
402
 
            "innocent_hits = max(0, innocent_hits %s %d) "
403
 
            "where token in(",
404
 
            (stat.spam_hits > s->control_sh) ? "+" : "-",
405
 
            abs (stat.spam_hits - s->control_sh),
406
 
            (stat.innocent_hits > s->control_ih) ? "+" : "-",
407
 
            abs (stat.innocent_hits - s->control_ih));
408
 
 
409
 
  buffer_cat (query, scratch);
 
439
  ds_diction_getstat(diction, s->control_token, &control);
 
440
 
 
441
  snprintf (queryhead, sizeof (queryhead),
 
442
            "UPDATE dspam_token_data SET last_hit=date('now'),"
 
443
            "spam_hits=max(0,spam_hits%s%d),"
 
444
            "innocent_hits=max(0,innocent_hits%s%d)"
 
445
            " WHERE token IN (",
 
446
            (control.spam_hits > s->control_sh) ? "+" : "-",
 
447
            abs (control.spam_hits - s->control_sh),
 
448
            (control.innocent_hits > s->control_ih) ? "+" : "-",
 
449
            abs (control.innocent_hits - s->control_ih));
 
450
 
 
451
  buffer_copy (query, queryhead);
 
452
 
 
453
 
 
454
  /*
 
455
   *  Add each token in the diction to either an update or an insert queue
 
456
   */
410
457
 
411
458
  ds_c = ds_diction_cursor(diction);
412
459
  ds_term = ds_diction_next(ds_c);
413
460
  while(ds_term)
414
461
  {
415
 
    int wrote_this = 0;
416
 
    if (CTX->training_mode == DST_TOE           && 
417
 
        CTX->classification == DSR_NONE         &&
418
 
        CTX->operating_mode == DSM_CLASSIFY     &&
419
 
        diction->whitelist_token != ds_term->key  &&
420
 
        (!ds_term->name || strncmp(ds_term->name, "bnr.", 4)))  
421
 
    {
422
 
      ds_term = ds_diction_next(ds_c);
423
 
      continue;
424
 
    }
425
 
 
426
 
    if (!(ds_term->s.status & TST_DIRTY)) {
427
 
      ds_term = ds_diction_next(ds_c);
428
 
      continue;
429
 
    }
430
 
 
431
 
    ds_diction_getstat(diction, ds_term->key, &stat2);
432
 
 
433
 
    if (!(stat2.status & TST_DISK))
434
 
    {
435
 
      char insert[1024];
436
 
 
437
 
        snprintf(insert, sizeof (insert),
438
 
                 "insert into dspam_token_data(token, spam_hits, "
439
 
                 "innocent_hits, last_hit) values('%" LLU_FMT_SPEC "', %ld, %ld, "
440
 
                 "date('now'))",
441
 
                 ds_term->key,
442
 
                 stat2.spam_hits > 0 ? (long) 1 : (long) 0, 
443
 
                 stat2.innocent_hits > 0 ? (long) 1 : (long) 0);
444
 
 
445
 
      if ((sqlite3_exec(s->dbh, insert, NULL, NULL, &err)) != SQLITE_OK)
446
 
      {
447
 
        stat2.status |= TST_DISK;
448
 
        free(err);
449
 
      }
450
 
    }
451
 
 
452
 
    if ((stat2.status & TST_DISK))
453
 
    {
 
462
    int use_comma = 0;
 
463
    if (ds_term->key == s->control_token) {
 
464
      ds_term = ds_diction_next(ds_c);
 
465
      continue;
 
466
    }
 
467
 
 
468
    /* Don't write lexical tokens if we're in TOE mode classifying */
 
469
 
 
470
    if (CTX->training_mode == DST_TOE            &&
 
471
        CTX->operating_mode == DSM_CLASSIFY      &&
 
472
        ds_term->key != diction->whitelist_token &&
 
473
        (!ds_term->name || strncmp(ds_term->name, "bnr.", 4)))
 
474
    {
 
475
      ds_term = ds_diction_next(ds_c);
 
476
      continue;
 
477
    }
 
478
 
 
479
    ds_diction_getstat(diction, ds_term->key, &stat);
 
480
 
 
481
    /* Changed tokens are marked as "dirty" by libdspam */
 
482
 
 
483
    if (!(stat.status & TST_DIRTY)) {
 
484
      ds_term = ds_diction_next(ds_c);
 
485
      continue;
 
486
    } else {
 
487
      stat.status &= ~TST_DIRTY;
 
488
    }
 
489
 
 
490
    /* This token wasn't originally loaded from disk, so try an insert */
 
491
 
 
492
    if (!(stat.status & TST_DISK))
 
493
    {
 
494
      char ins[1024];
 
495
      snprintf(ins, sizeof (ins),
 
496
               "INSERT INTO dspam_token_data (token,spam_hits,"
 
497
               "innocent_hits,last_hit) VALUES ('%" LLU_FMT_SPEC "',%d,%d,"
 
498
               "date('now'))",
 
499
               ds_term->key,
 
500
               stat.spam_hits > 0 ? 1 : 0,
 
501
               stat.innocent_hits > 0 ? 1 : 0);
 
502
      if ((sqlite3_exec(s->dbh, ins, NULL, NULL, NULL)) != SQLITE_OK)
 
503
        stat.status |= TST_DISK;
 
504
    }
 
505
 
 
506
    if (stat.status & TST_DISK) {
454
507
      snprintf (scratch, sizeof (scratch), "'%" LLU_FMT_SPEC "'", ds_term->key);
455
508
      buffer_cat (query, scratch);
456
 
      update_one = 1;
457
 
      wrote_this = 1;
458
 
      ds_term->s.status |= TST_DISK;
 
509
      update_any = 1;
 
510
      use_comma = 1;
459
511
    }
 
512
 
 
513
    ds_term->s.status |= TST_DISK;
 
514
 
460
515
    ds_term = ds_diction_next(ds_c);
461
 
    if (ds_term && wrote_this)
 
516
    if((query->used + 1024) > 1000000) {
 
517
      LOGDEBUG("_ds_setall_spamrecords: Splitting update query at %ld characters", query->used);
 
518
      buffer_cat (query, ")");
 
519
      if (update_any) {
 
520
        if ((sqlite3_exec(s->dbh, query->data, NULL, NULL, &err)) != SQLITE_OK) {
 
521
          _sqlite_drv_query_error (err, query->data);
 
522
          LOGDEBUG ("_ds_setall_spamrecords: unable to run query: %s", query->data);
 
523
          ds_diction_close(ds_c);
 
524
          buffer_destroy(query);
 
525
          return EFAILURE;
 
526
        }
 
527
      }
 
528
      buffer_copy (query, queryhead);
 
529
    } else if (ds_term && use_comma)
462
530
      buffer_cat (query, ",");
463
531
  }
464
532
  ds_diction_close(ds_c);
465
533
 
 
534
  /* Just incase */
 
535
 
466
536
  if (query->used && query->data[strlen (query->data) - 1] == ',')
467
537
  {
468
538
    query->used--;
469
539
    query->data[strlen (query->data) - 1] = 0;
470
 
 
471
540
  }
472
541
 
473
542
  buffer_cat (query, ")");
474
543
 
475
 
  LOGDEBUG("Control: [%ld %ld] [%ld %ld]", s->control_sh, s->control_ih, stat.spam_hits, stat.innocent_hits);
 
544
  LOGDEBUG("Control: [%ld %ld] [%lu %lu] Delta: [%lu %lu]",
 
545
    s->control_sh, s->control_ih,
 
546
    control.spam_hits, control.innocent_hits,
 
547
    control.spam_hits - s->control_sh, control.innocent_hits - s->control_ih);
476
548
 
477
 
  if (update_one)
 
549
  if (update_any)
478
550
  {
479
551
    if ((sqlite3_exec(s->dbh, query->data, NULL, NULL, &err))!=SQLITE_OK)
480
552
    {
481
553
      _sqlite_drv_query_error (err, query->data);
 
554
      LOGDEBUG ("_ds_setall_spamrecords: unable to run query: %s", query->data);
482
555
      buffer_destroy(query);
483
556
      return EFAILURE;
484
557
    }
505
578
  }
506
579
 
507
580
  snprintf (query, sizeof (query),
508
 
            "select spam_hits, innocent_hits from dspam_token_data "
509
 
            "where token = '%" LLU_FMT_SPEC "' ", token);
 
581
            "SELECT spam_hits,innocent_hits FROM dspam_token_data"
 
582
            " WHERE token='%" LLU_FMT_SPEC "'", token);
510
583
 
511
 
  stat->probability = 0.0;
 
584
  stat->probability = 0.00000;
512
585
  stat->spam_hits = 0;
513
586
  stat->innocent_hits = 0;
514
587
  stat->status &= ~TST_DISK;
516
589
  if ((sqlite3_get_table(s->dbh, query, &row, &nrow, &ncolumn, &err))!=SQLITE_OK)
517
590
  {
518
591
    _sqlite_drv_query_error (err, query);
 
592
    LOGDEBUG ("_ds_get_spamrecord: unable to run query: %s", query);
519
593
    return EFAILURE;
520
594
  }
521
595
 
525
599
  if (nrow < 1 || row == NULL)
526
600
    return 0;
527
601
 
528
 
  stat->spam_hits = strtol (row[0], NULL, 0);
529
 
  stat->innocent_hits = strtol (row[1], NULL, 0);
 
602
  stat->spam_hits = strtoul (row[0], NULL, 0);
 
603
  if (stat->spam_hits == ULONG_MAX && errno == ERANGE) {
 
604
    LOGDEBUG("_ds_get_spamrecord: failed converting %s to stat->spam_hits", row[0]);
 
605
    sqlite3_free_table(row);
 
606
    return EFAILURE;
 
607
  }
 
608
  stat->innocent_hits = strtoul (row[1], NULL, 0);
 
609
  if (stat->innocent_hits == ULONG_MAX && errno == ERANGE) {
 
610
    LOGDEBUG("_ds_get_spamrecord: failed converting %s to stat->innocent_hits", row[1]);
 
611
    sqlite3_free_table(row);
 
612
    return EFAILURE;
 
613
  }
530
614
  stat->status |= TST_DISK;
531
615
  sqlite3_free_table(row);
532
616
  return 0;
554
638
  if (!(stat->status & TST_DISK))
555
639
  {
556
640
    snprintf (query, sizeof (query),
557
 
              "insert into dspam_token_data(token, spam_hits, "
558
 
              "innocent_hits, last_hit)"
559
 
              " values('%" LLU_FMT_SPEC "', %ld, %ld, date('now'))",
560
 
              token, 
 
641
              "INSERT INTO dspam_token_data (token,spam_hits,innocent_hits,last_hit)"
 
642
              " VALUES ('%" LLU_FMT_SPEC "',%lu,%lu,date('now'))",
 
643
              token,
561
644
              stat->spam_hits > 0 ? stat->spam_hits : 0,
562
645
              stat->innocent_hits > 0 ? stat->innocent_hits : 0);
563
 
    result = sqlite3_exec(s->dbh, query, NULL, NULL, &err);
 
646
    result = sqlite3_exec(s->dbh, query, NULL, NULL, NULL);
564
647
  }
565
648
 
566
649
  if ((stat->status & TST_DISK) || result)
567
650
  {
568
651
    /* insert failed; try updating instead */
569
 
    snprintf (query, sizeof (query), "update dspam_token_data "
570
 
              "set spam_hits = %ld, "
571
 
              "innocent_hits = %ld "
572
 
              "where token = %" LLD_FMT_SPEC,
 
652
    snprintf (query, sizeof (query), "UPDATE dspam_token_data"
 
653
              " SET spam_hits=%lu,"
 
654
              "innocent_hits=%lu"
 
655
              " WHERE token='%" LLU_FMT_SPEC "'",
573
656
              stat->spam_hits > 0 ? stat->spam_hits : 0,
574
657
              stat->innocent_hits > 0 ? stat->innocent_hits : 0,
575
658
              token);
576
659
 
577
 
    if ((sqlite3_exec(s->dbh, query, NULL, NULL, &err))!=SQLITE_OK)
578
 
    {
 
660
    if ((sqlite3_exec(s->dbh, query, NULL, NULL, &err))!=SQLITE_OK) {
579
661
      _sqlite_drv_query_error (err, query);
 
662
      LOGDEBUG ("_ds_set_spamrecord: unable to run query: %s", query);
580
663
      return EFAILURE;
581
664
    }
582
665
  }
612
695
    return EINVAL;
613
696
  }
614
697
 
615
 
  s = malloc (sizeof (struct _sqlite_drv_storage));
 
698
  s = calloc (1, sizeof (struct _sqlite_drv_storage));
616
699
  if (s == NULL)
617
700
  {
618
701
    LOG (LOG_CRIT, ERR_MEM_ALLOC);
639
722
 
640
723
  if (dbh)
641
724
    s->dbh = dbh;
642
 
  else
643
 
    if ((sqlite3_open(filename, &s->dbh))!=SQLITE_OK)
644
 
      s->dbh = NULL;
645
 
                                                                                
 
725
  else if ((sqlite3_open(filename, &s->dbh))!=SQLITE_OK)
 
726
    s->dbh = NULL;
 
727
 
646
728
  if (s->dbh == NULL)
647
729
  {
 
730
    free(s);
648
731
    LOGDEBUG
649
 
      ("_ds_init_storage: sqlite3_open: unable to initialize database: %s", err);    return EUNKNOWN;
 
732
      ("_ds_init_storage: unable to initialize database: %s", filename);
 
733
    return EFAILURE;
650
734
  }
651
735
 
652
736
  /* Commit timeout of 20 minutes */
656
740
 
657
741
  if (noexist) {
658
742
 
659
 
    sqlite3_exec(s->dbh, 
660
 
                "create table dspam_token_data (token char(20) primary key, "
661
 
                "spam_hits int, innocent_hits int, last_hit date)",
662
 
                NULL,
663
 
                NULL,
664
 
                &err);
665
 
 
666
 
    sqlite3_exec(s->dbh,
667
 
                "create index id_token_data_02 on dspam_token_data"
668
 
                "(innocent_hits)",
669
 
                NULL,
670
 
                NULL,
671
 
                &err);
672
 
 
673
 
    sqlite3_exec(s->dbh,
674
 
                "create table dspam_signature_data ("
675
 
                "signature char(128) primary key, data blob, created_on date)",
676
 
                NULL,
677
 
                NULL,
678
 
                &err);
679
 
                                                                                
680
 
    sqlite3_exec(s->dbh,
681
 
                "create table dspam_stats (dspam_stat_id int primary key, "
682
 
                "spam_learned int, innocent_learned int, "
683
 
                "spam_misclassified int, innocent_misclassified int, "
684
 
                "spam_corpusfed int, innocent_corpusfed int, "
685
 
                "spam_classified int, innocent_classified int)",
686
 
                NULL,
687
 
                NULL,
688
 
                &err);
 
743
    LOGDEBUG ("_ds_init_storage: Creating object structure in database: %s", filename);
 
744
 
 
745
    buff[0] = 0;
 
746
    snprintf (buff, sizeof (buff),
 
747
                "CREATE TABLE dspam_token_data (token CHAR(20) PRIMARY KEY,"
 
748
                "spam_hits INT,innocent_hits INT,last_hit DATE)");
 
749
    if ((sqlite3_exec(s->dbh, buff, NULL, NULL, &err))!=SQLITE_OK) {
 
750
      _sqlite_drv_query_error (err, buff);
 
751
      free(s);
 
752
      return EFAILURE;
 
753
    }
 
754
 
 
755
    buff[0] = 0;
 
756
    snprintf (buff, sizeof (buff),
 
757
                "CREATE INDEX id_token_data_02 ON dspam_token_data"
 
758
                "(innocent_hits)");
 
759
    if ((sqlite3_exec(s->dbh, buff, NULL, NULL, &err))!=SQLITE_OK) {
 
760
      _sqlite_drv_query_error (err, buff);
 
761
      free(s);
 
762
      return EFAILURE;
 
763
    }
 
764
 
 
765
    buff[0] = 0;
 
766
    snprintf (buff, sizeof (buff),
 
767
                "CREATE TABLE dspam_signature_data ("
 
768
                "signature CHAR(128) PRIMARY KEY,data BLOB,created_on DATE)");
 
769
    if ((sqlite3_exec(s->dbh, buff, NULL, NULL, &err))!=SQLITE_OK) {
 
770
      _sqlite_drv_query_error (err, buff);
 
771
      free(s);
 
772
      return EFAILURE;
 
773
    }
 
774
 
 
775
    buff[0] = 0;
 
776
    snprintf (buff, sizeof (buff),
 
777
                "CREATE TABLE dspam_stats (dspam_stat_id INT PRIMARY KEY,"
 
778
                "spam_learned INT,innocent_learned INT,"
 
779
                "spam_misclassified INT,innocent_misclassified INT,"
 
780
                "spam_corpusfed INT,innocent_corpusfed INT,"
 
781
                "spam_classified INT,innocent_classified INT)");
 
782
    if ((sqlite3_exec(s->dbh, buff, NULL, NULL, &err))!=SQLITE_OK) {
 
783
      _sqlite_drv_query_error (err, buff);
 
784
      free(s);
 
785
      return EFAILURE;
 
786
    }
 
787
 
 
788
    buff[0] = 0;
689
789
  }
690
790
 
691
791
  if (_ds_read_attribute(CTX->config->attributes, "SQLitePragma")) {
699
799
        _sqlite_drv_query_error (err, pragma);
700
800
      }
701
801
      t = t->next;
702
 
    } 
 
802
    }
703
803
  } else {
704
804
    snprintf(filename, MAX_FILENAME_LENGTH, "%s/sqlite.pragma", CTX->home);
705
805
    file = fopen(filename, "r");
717
817
  }
718
818
 
719
819
  CTX->storage = s;
 
820
 
720
821
  s->dir_handles = nt_create (NT_INDEX);
721
 
 
722
822
  s->control_token = 0;
 
823
  s->control_sh = 0;
723
824
  s->control_ih = 0;
724
 
  s->control_sh = 0; 
725
825
 
726
826
  /* get spam totals on successful init */
727
827
  if (CTX->username != NULL)
728
828
  {
729
829
      if (_sqlite_drv_get_spamtotals (CTX))
730
830
      {
731
 
        LOGDEBUG ("unable to load totals.  using zero values.");
 
831
        LOGDEBUG ("_ds_init_storage: unable to load totals. Using zero values.");
732
832
      }
733
833
  }
734
834
  else
761
861
    closedir (dir);
762
862
    node_nt = c_nt_next (s->dir_handles, &c_nt);
763
863
  }
764
 
                                                                                
 
864
 
765
865
  nt_destroy (s->dir_handles);
766
866
 
767
867
 
819
919
  }
820
920
 
821
921
  snprintf (query, sizeof (query),
822
 
            "select data from dspam_signature_data where signature = \"%s\"",
 
922
            "SELECT data FROM dspam_signature_data WHERE signature=\"%s\"",
823
923
            signature);
824
924
 
825
925
  if ((sqlite3_prepare(s->dbh, query, -1, &stmt, &query_tail))
830
930
  }
831
931
 
832
932
  if ((sqlite3_step(stmt))!=SQLITE_ROW) {
833
 
    sqlite3_finalize(stmt); 
 
933
    sqlite3_finalize(stmt);
834
934
    return EFAILURE;
835
935
  }
836
936
 
845
945
  memcpy(SIG->data, sqlite3_column_blob(stmt, 0), SIG->length);
846
946
 
847
947
  if ((sqlite3_finalize(stmt)!=SQLITE_OK))
848
 
    LOGDEBUG("sqlite3_finalize() failed: %s", strerror(errno));
 
948
    LOGDEBUG("_ds_get_signature: sqlite3_finalize() failed: %s", strerror(errno));
849
949
 
850
950
  return 0;
851
951
}
855
955
                   const char *signature)
856
956
{
857
957
  struct _sqlite_drv_storage *s = (struct _sqlite_drv_storage *) CTX->storage;
858
 
  char *mem;
859
958
  char scratch[1024];
860
959
  char *err=NULL;
861
960
  const char *query_tail=NULL;
862
961
  sqlite3_stmt *stmt;
863
 
  int r;
864
962
 
865
963
  if (s->dbh == NULL)
866
964
  {
867
 
    LOGDEBUG ("_ds_set_signature; invalid database handle (NULL)");
 
965
    LOGDEBUG ("_ds_set_signature: invalid database handle (NULL)");
868
966
    return EINVAL;
869
967
  }
870
968
 
871
 
  mem = calloc (1, 2 + (257*SIG->length)/254);
872
 
  if (mem == NULL)
873
 
  {
874
 
    LOG (LOG_CRIT, ERR_MEM_ALLOC);
875
 
    return EUNKNOWN;
876
 
  }
877
 
 
878
969
  snprintf (scratch, sizeof (scratch),
879
 
            "insert into dspam_signature_data(signature, created_on, data) "
880
 
            "values(\"%s\", date('now'), ?)", signature);
 
970
            "INSERT INTO dspam_signature_data (signature,created_on,data)"
 
971
            " VALUES (\"%s\",date('now'),?)", signature);
881
972
 
882
 
  if ((r = sqlite3_prepare(s->dbh, scratch, -1, &stmt, &query_tail))
883
 
        !=SQLITE_OK)
 
973
  if ((sqlite3_prepare(s->dbh, scratch, -1, &stmt, &query_tail))!=SQLITE_OK)
884
974
  {
885
 
    _sqlite_drv_query_error ("sqlite3_prepare() failed", scratch);
 
975
    _sqlite_drv_query_error ("_ds_set_signature: sqlite3_prepare() failed", scratch);
886
976
    return EFAILURE;
887
977
  }
888
978
 
895
985
 
896
986
  sqlite3_finalize(stmt);
897
987
 
898
 
  free (mem);
899
988
  return 0;
900
989
}
901
990
 
913
1002
  }
914
1003
 
915
1004
  snprintf (query, sizeof (query),
916
 
            "delete from dspam_signature_data where signature = \"%s\"",
 
1005
            "DELETE FROM dspam_signature_data WHERE signature=\"%s\"",
917
1006
             signature);
918
1007
 
919
1008
  if ((sqlite3_exec(s->dbh, query, NULL, NULL, &err))!=SQLITE_OK)
940
1029
  }
941
1030
 
942
1031
  snprintf (query, sizeof (query),
943
 
        "select signature from dspam_signature_data where signature = \"%s\"",
 
1032
        "SELECT signature FROM dspam_signature_data WHERE signature=\"%s\"",
944
1033
        signature);
945
1034
 
946
1035
  if ((sqlite3_get_table(s->dbh, query, &row, &nrow, &ncolumn, &err))!=SQLITE_OK)  {
978
1067
    if (dir == NULL)
979
1068
    {
980
1069
      LOG (LOG_WARNING,
981
 
           "unable to open directory '%s' for reading: %s",
 
1070
           "_ds_get_nextuser: unable to open directory '%s' for reading: %s",
982
1071
           CTX->home, strerror (errno));
983
1072
      return NULL;
984
1073
    }
997
1086
    }
998
1087
  }
999
1088
 
1000
 
  while ((entry = readdir (dir)) != NULL)
1001
 
  {
1002
 
    struct stat st;
1003
 
    char filename[MAX_FILENAME_LENGTH];
1004
 
    snprintf (filename, sizeof (filename), "%s/%s", path, entry->d_name);
1005
 
 
1006
 
    if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, ".."))
1007
 
      continue;
1008
 
 
1009
 
    if (stat (filename, &st)) {
1010
 
      continue;
1011
 
    }
1012
 
 
1013
 
    /* push a new directory */
1014
 
    if (st.st_mode & S_IFDIR)
1015
 
    {
1016
 
      DIR *ndir;
1017
 
 
1018
 
      ndir = opendir (filename);
1019
 
      if (ndir == NULL)
1020
 
        continue;
1021
 
      strlcat (path, "/", sizeof (path));
1022
 
      strlcat (path, entry->d_name, sizeof (path));
1023
 
      nt_add (s->dir_handles, (void *) ndir);
1024
 
      return _ds_get_nextuser (CTX);
1025
 
    }
1026
 
    else if (!strncmp
1027
 
             (entry->d_name + strlen (entry->d_name) - 4, ".sdb", 4))
1028
 
    {
1029
 
      strlcpy (user, entry->d_name, sizeof (user));
1030
 
      user[strlen (user) - 4] = 0;
1031
 
      return user;
 
1089
  if (dir != NULL) {
 
1090
    while ((entry = readdir (dir)) != NULL)
 
1091
    {
 
1092
      struct stat st;
 
1093
      char filename[MAX_FILENAME_LENGTH];
 
1094
      snprintf (filename, sizeof (filename), "%s/%s", path, entry->d_name);
 
1095
 
 
1096
      if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, ".."))
 
1097
        continue;
 
1098
 
 
1099
      if (stat (filename, &st)) {
 
1100
        continue;
 
1101
      }
 
1102
 
 
1103
      /* push a new directory */
 
1104
      if (st.st_mode & S_IFDIR)
 
1105
      {
 
1106
        DIR *ndir;
 
1107
 
 
1108
        ndir = opendir (filename);
 
1109
        if (ndir == NULL)
 
1110
          continue;
 
1111
        strlcat (path, "/", sizeof (path));
 
1112
        strlcat (path, entry->d_name, sizeof (path));
 
1113
        nt_add (s->dir_handles, (void *) ndir);
 
1114
        return _ds_get_nextuser (CTX);
 
1115
      }
 
1116
      else if (!strncmp
 
1117
               (entry->d_name + strlen (entry->d_name) - 4, ".sdb", 4))
 
1118
      {
 
1119
        strlcpy (user, entry->d_name, sizeof (user));
 
1120
        user[strlen (user) - 4] = 0;
 
1121
        return user;
 
1122
      }
1032
1123
    }
1033
1124
  }
1034
1125
 
1059
1150
        s->dir_handles->first = NULL;
1060
1151
      free (node_nt);
1061
1152
      s->dir_handles->items--;
1062
 
      prev = node_nt;
1063
1153
      break;
1064
1154
    }
1065
1155
    prev = node_nt;
1100
1190
  if (s->iter_token == NULL)
1101
1191
  {
1102
1192
    snprintf (query, sizeof (query),
1103
 
              "select token, spam_hits, innocent_hits, strftime('%%s', "
1104
 
              "last_hit) from dspam_token_data");
 
1193
              "SELECT token,spam_hits,innocent_hits,strftime('%%s',"
 
1194
              "last_hit) FROM dspam_token_data");
1105
1195
 
1106
1196
    if ((sqlite3_prepare(s->dbh, query, -1, &s->iter_token, &query_tail))
1107
 
        !=SQLITE_OK) 
 
1197
        !=SQLITE_OK)
1108
1198
    {
1109
1199
      _sqlite_drv_query_error (err, query);
1110
 
      free(st); 
 
1200
      free(st);
1111
1201
      return NULL;
1112
1202
    }
1113
1203
  }
1126
1216
  }
1127
1217
 
1128
1218
  st->token = strtoull ((const char *) sqlite3_column_text(s->iter_token, 0), NULL, 0);
1129
 
  st->spam_hits = strtol ((const char *) sqlite3_column_text(s->iter_token, 1), NULL, 0);
1130
 
  st->innocent_hits = strtol ((const char *) sqlite3_column_text(s->iter_token, 2), NULL, 0);
 
1219
  st->spam_hits = strtoul ((const char *) sqlite3_column_text(s->iter_token, 1), NULL, 0);
 
1220
  if (st->spam_hits == ULONG_MAX && errno == ERANGE) {
 
1221
    LOGDEBUG("_ds_get_nexttoken: failed converting %s to st->spam_hits", (const char *) sqlite3_column_text(s->iter_token, 1));
 
1222
    s->iter_token = NULL;
 
1223
    free(st);
 
1224
    return NULL;
 
1225
  }
 
1226
  st->innocent_hits = strtoul ((const char *) sqlite3_column_text(s->iter_token, 2), NULL, 0);
 
1227
  if (st->innocent_hits == ULONG_MAX && errno == ERANGE) {
 
1228
    LOGDEBUG("_ds_get_nexttoken: failed converting %s to st->innocent_hits", (const char *) sqlite3_column_text(s->iter_token, 2));
 
1229
    s->iter_token = NULL;
 
1230
    free(st);
 
1231
    return NULL;
 
1232
  }
1131
1233
  st->last_hit = (time_t) strtol ((const char *) sqlite3_column_text(s->iter_token, 3), NULL, 0);
1132
1234
 
1133
1235
  return st;
1161
1263
  if (s->iter_sig == NULL)
1162
1264
  {
1163
1265
    snprintf (query, sizeof (query),
1164
 
              "select data, signature, strftime('%%s', created_on) "
1165
 
              "from dspam_signature_data");
 
1266
              "SELECT data,signature,strftime('%%s',created_on)"
 
1267
              " FROM dspam_signature_data");
1166
1268
 
1167
1269
   if ((sqlite3_prepare(s->dbh, query, -1, &s->iter_sig, &query_tail))
1168
1270
        !=SQLITE_OK)
1172
1274
      return NULL;
1173
1275
    }
1174
1276
  }
1175
 
                                                                                
 
1277
 
1176
1278
  if ((x = sqlite3_step(s->iter_sig)) !=SQLITE_ROW) {
1177
1279
    if (x != SQLITE_DONE) {
1178
1280
      _sqlite_drv_query_error (err, query);
1248
1350
 
1249
1351
  if (s->dbh == NULL)
1250
1352
  {
1251
 
    LOGDEBUG ("_ds_delete_signature: invalid database handle (NULL)");
 
1353
    LOGDEBUG ("_ds_del_spamrecord: invalid database handle (NULL)");
1252
1354
    return EINVAL;
1253
1355
  }
1254
 
                                                                                
 
1356
 
1255
1357
  snprintf (query, sizeof (query),
1256
 
            "delete from dspam_token_data where token = \"%" LLU_FMT_SPEC "\"",
 
1358
            "DELETE FROM dspam_token_data WHERE token='%" LLU_FMT_SPEC "'",
1257
1359
            token);
1258
 
                                                                                
 
1360
 
1259
1361
  if ((sqlite3_exec(s->dbh, query, NULL, NULL, &err))!=SQLITE_OK)
1260
1362
  {
1261
1363
    _sqlite_drv_query_error (err, query);
1293
1395
  }
1294
1396
 
1295
1397
  snprintf (queryhead, sizeof(queryhead),
1296
 
            "delete from dspam_token_data "
1297
 
            "where token in(");
 
1398
            "DELETE FROM dspam_token_data"
 
1399
            " WHERE token IN (");
1298
1400
 
1299
1401
  buffer_cat (query, queryhead);
1300
1402
 
1305
1407
    snprintf (scratch, sizeof (scratch), "'%" LLU_FMT_SPEC "'", ds_term->key);
1306
1408
    buffer_cat (query, scratch);
1307
1409
    ds_term = ds_diction_next(ds_c);
1308
 
   
 
1410
 
1309
1411
    if (writes > 2500 || ds_term == NULL) {
1310
1412
      buffer_cat (query, ")");
1311
1413
 
1318
1420
 
1319
1421
      buffer_copy(query, queryhead);
1320
1422
      writes = 0;
1321
 
   
1322
 
    } else { 
 
1423
 
 
1424
    } else {
1323
1425
      writes++;
1324
1426
      if (ds_term)
1325
1427
        buffer_cat (query, ",");