ze-filter  (ze-filter-0.8.0-develop-180218)
ze-msg-score.c
Go to the documentation of this file.
1 
2 /*
3  *
4  * ze-filter - Mail Server Filter for sendmail
5  *
6  * Copyright (c) 2001-2018 - Jose-Marcio Martins da Cruz
7  *
8  * Auteur : Jose Marcio Martins da Cruz
9  * jose.marcio.mc@gmail.org
10  *
11  * Historique :
12  * Creation : Tue Nov 28 21:56:02 CET 2006
13  *
14  * This program is free software, but with restricted license :
15  *
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * More details about ze-filter license can be found at ze-filter
22  * web site : http://foss.jose-marcio.org
23  */
24 
25 
26 #include <ze-sys.h>
27 #include <ze-filter.h>
28 #include <ze-msg-score.h>
29 
30 
31 #define SQR(x) ((x) * (x))
32 
33 #ifndef MAX_MSG_SCORE
34 #define MAX_MSG_SCORE 15
35 #endif
36 
37 /* ****************************************************************************
38  * *
39  * ###### # # ## # *
40  * # # # # # # *
41  * ##### # # # # # *
42  * # # # ###### # *
43  * # # # # # # *
44  * ###### ## # # ###### *
45  * *
46  **************************************************************************** */
47 #define EVAL_UNDEF -1
48 #define EVAL_SUM 0
49 #define EVAL_VECTOR 1
50 #define EVAL_SHLIB 2
51 #define EVAL_LOGIT 3
52 
53 typedef struct {
54  bool ok;
55  char buf_scale[256];
56  char buf_eval[256];
57 
59  int func;
60  union {
61  /*
62  * score is the module of the vector of components
63  */
64  struct {
65  double kbayes;
66  double koracle;
67  double kurlbl;
68  double kregex;
69  } vector;
70  /*
71  * score is a weigthed sum of components
72  */
73  struct {
74  double kbayes;
75  double koracle;
76  double kurlbl;
77  double kregex;
78  } sum;
79 
80  /*
81  * score is a weigthed sum of logits
82  */
83  struct {
84  double kbayes;
85  double koracle;
86  double kurlbl;
87  double kregex;
88  } logit;
89 
90  /*
91  * score is defined by an external function in a shared library
92  */
93 #if 0
94  struct {
95  char *dlname;
96  char *func;
97  } module;
98 #endif
99  } function;
101 
102 static msg_eval_func_T msg_eval = { FALSE };
103 
104 static pthread_mutex_t fmutex = PTHREAD_MUTEX_INITIALIZER;
105 
106 /* ****************************************************************************
107  * *
108  * *
109  **************************************************************************** */
110 static bool
111 init_msg_eval()
112 {
113  if (msg_eval.ok)
114  return TRUE;
115 
116  MUTEX_LOCK(&fmutex);
117 
118  if (msg_eval.ok)
119  goto fin;
120 
121  memset(&msg_eval, 0, sizeof msg_eval);
122  msg_eval.scale.kf1 = 1.;
123  msg_eval.scale.kf0 = 0.;
124  msg_eval.scale.bayes = 1.;
125  msg_eval.scale.urlbl = 1.;
126  msg_eval.scale.regex = 1.;
127  msg_eval.scale.oracle = 1.;
128  msg_eval.func = EVAL_VECTOR;
129  switch (msg_eval.func) {
130  case EVAL_VECTOR:
131  msg_eval.function.vector.kbayes = 1.;
132  msg_eval.function.vector.koracle = 1. / 12.;
133  msg_eval.function.vector.kurlbl = 1. / 4.;
134  msg_eval.function.vector.kregex = 1. / 10.;
135  break;
136  case EVAL_LOGIT:
137  msg_eval.function.logit.kbayes = 1.;
138  msg_eval.function.logit.koracle = 1. / 2.;
139  msg_eval.function.logit.kurlbl = 1.;
140  msg_eval.function.logit.kregex = 1. / 2.;
141  break;
142  case EVAL_SUM:
143  msg_eval.function.sum.kbayes = 1.;
144  msg_eval.function.sum.koracle = 1. / 12.;
145  msg_eval.function.sum.kurlbl = 1. / 4.;
146  msg_eval.function.sum.kregex = 1. / 10.;
147  break;
148  default:
149  break;
150  }
151  msg_eval.ok = TRUE;
152 
153 fin:
154  MUTEX_UNLOCK(&fmutex);
155 
156  return msg_eval.ok;
157 }
158 
159 /* ****************************************************************************
160  * *
161  * *
162  **************************************************************************** */
163 static bool
164 decode_msg_eval_token(q, val)
165  msg_eval_func_T *q;
166  char *val;
167 {
168  char *s = NULL;
169  bool result = TRUE;
170 
171  /*
172  * decode the function type
173  */
174  if (q->func == EVAL_UNDEF) {
175  s = "VECTOR";
176  if (STRNCASEEQUAL(s, val, strlen(s))) {
177  q->func = EVAL_VECTOR;
178  goto fin;
179  }
180 
181  s = "SUM";
182  if (STRNCASEEQUAL(s, val, strlen(s))) {
183  q->func = EVAL_SUM;
184  goto fin;
185  }
186 
187  s = "LOGIT";
188  if (STRNCASEEQUAL(s, val, strlen(s))) {
189  q->func = EVAL_SHLIB;
190  goto fin;
191  }
192 
193  s = "SHLIB";
194  if (STRNCASEEQUAL(s, val, strlen(s))) {
195  q->func = EVAL_SHLIB;
196  goto fin;
197  }
198 
199  result = FALSE;
200  goto fin;
201 
202  }
203 
204  /*
205  * function type already decoded - parameters now
206  */
207  s = "SSCORE1=";
208  if (STRNCASEEQUAL(s, val, strlen(s))) {
209  double k = 0.;
210 
211  s = val + strlen(s);
212  errno = 0;
213  k = strtod(s, NULL);
214  if (errno == 0)
215  q->scale.kf1 = k;
216  goto fin;
217  }
218  s = "SSCORE0=";
219  if (STRNCASEEQUAL(s, val, strlen(s))) {
220  double k = 0.;
221 
222  s = val + strlen(s);
223  errno = 0;
224  k = strtod(s, NULL);
225  if (errno == 0)
226  q->scale.kf0 = k;
227  goto fin;
228  }
229  s = "SBAYES=";
230  if (STRNCASEEQUAL(s, val, strlen(s))) {
231  double k = 0.;
232 
233  s = val + strlen(s);
234  errno = 0;
235  k = strtod(s, NULL);
236  if (errno == 0)
237  q->scale.bayes = k;
238  goto fin;
239  }
240  s = "SURLBL=";
241  if (STRNCASEEQUAL(s, val, strlen(s))) {
242  double k = 0.;
243 
244  s = val + strlen(s);
245  errno = 0;
246  k = strtod(s, NULL);
247  if (errno == 0)
248  q->scale.urlbl = k;
249  goto fin;
250  }
251  s = "SREGEX=";
252  if (STRNCASEEQUAL(s, val, strlen(s))) {
253  double k = 0.;
254 
255  s = val + strlen(s);
256  errno = 0;
257  k = strtod(s, NULL);
258  if (errno == 0)
259  q->scale.regex = k;
260  goto fin;
261  }
262  s = "SORACLE=";
263  if (STRNCASEEQUAL(s, val, strlen(s))) {
264  double k = 0.;
265 
266  s = val + strlen(s);
267  errno = 0;
268  k = strtod(s, NULL);
269  if (errno == 0)
270  q->scale.oracle = k;
271  goto fin;
272  }
273 
274  /*
275  * vector
276  */
277  if (q->func == EVAL_VECTOR) {
278  s = "KBAYES=";
279  if (STRNCASEEQUAL(s, val, strlen(s))) {
280  double k = 0.;
281 
282  s = val + strlen(s);
283  errno = 0;
284  k = strtod(s, NULL);
285  if (errno == 0)
286  q->function.vector.kbayes = k;
287  goto fin;
288  }
289 
290  s = "KURLBL=";
291  if (STRNCASEEQUAL(s, val, strlen(s))) {
292  double k;
293 
294  s = val + strlen(s);
295  errno = 0;
296  k = strtod(s, NULL);
297  if (errno == 0)
298  q->function.vector.kurlbl = k;
299  goto fin;
300  }
301 
302  s = "KORACLE=";
303  if (STRNCASEEQUAL(s, val, strlen(s))) {
304  double k;
305 
306  s = val + strlen(s);
307  errno = 0;
308  k = strtod(s, NULL);
309  if (errno == 0)
310  q->function.vector.koracle = k;
311  goto fin;
312  }
313 
314  s = "KREGEX=";
315  if (STRNCASEEQUAL(s, val, strlen(s))) {
316  double k;
317 
318  s = val + strlen(s);
319  errno = 0;
320  k = strtod(s, NULL);
321  if (errno == 0)
322  q->function.vector.kregex = k;
323  goto fin;
324  }
325  result = FALSE;
326  goto fin;
327  }
328 
329  /*
330  * logit
331  */
332  if (q->func == EVAL_LOGIT) {
333  s = "KBAYES=";
334  if (STRNCASEEQUAL(s, val, strlen(s))) {
335  double k = 0.;
336 
337  s = val + strlen(s);
338  errno = 0;
339  k = strtod(s, NULL);
340  if (errno == 0)
341  q->function.logit.kbayes = k;
342  goto fin;
343  }
344 
345  s = "KURLBL=";
346  if (STRNCASEEQUAL(s, val, strlen(s))) {
347  double k;
348 
349  s = val + strlen(s);
350  errno = 0;
351  k = strtod(s, NULL);
352  if (errno == 0)
353  q->function.logit.kurlbl = k;
354  goto fin;
355  }
356 
357  s = "KORACLE=";
358  if (STRNCASEEQUAL(s, val, strlen(s))) {
359  double k;
360 
361  s = val + strlen(s);
362  errno = 0;
363  k = strtod(s, NULL);
364  if (errno == 0)
365  q->function.logit.koracle = k;
366  goto fin;
367  }
368 
369  s = "KREGEX=";
370  if (STRNCASEEQUAL(s, val, strlen(s))) {
371  double k;
372 
373  s = val + strlen(s);
374  errno = 0;
375  k = strtod(s, NULL);
376  if (errno == 0)
377  q->function.logit.kregex = k;
378  goto fin;
379  }
380  result = FALSE;
381  goto fin;
382  }
383 
384  /*
385  * weighted sum
386  */
387  if (q->func == EVAL_SUM) {
388  s = "KBAYES=";
389  if (STRNCASEEQUAL(s, val, strlen(s))) {
390  double k;
391 
392  s = val + strlen(s);
393  errno = 0;
394  k = strtod(s, NULL);
395  if (errno == 0)
396  q->function.sum.kbayes = k;
397  goto fin;
398  }
399 
400  s = "KURLBL=";
401  if (STRNCASEEQUAL(s, val, strlen(s))) {
402  double k;
403 
404  s = val + strlen(s);
405  errno = 0;
406  k = strtod(s, NULL);
407  if (errno == 0)
408  q->function.sum.kurlbl = k;
409  goto fin;
410  }
411 
412  s = "KORACLE=";
413  if (STRNCASEEQUAL(s, val, strlen(s))) {
414  double k;
415 
416  s = val + strlen(s);
417  errno = 0;
418  k = strtod(s, NULL);
419  if (errno == 0)
420  q->function.sum.koracle = k;
421  goto fin;
422  }
423 
424  s = "KREGEX=";
425  if (STRNCASEEQUAL(s, val, strlen(s))) {
426  double k;
427 
428  s = val + strlen(s);
429  errno = 0;
430  k = strtod(s, NULL);
431  if (errno == 0)
432  q->function.sum.kregex = k;
433  goto fin;
434  }
435  result = FALSE;
436  goto fin;
437  }
438  result = FALSE;
439  goto fin;
440 
441 fin:
442  return result;
443 }
444 
445 /* ****************************************************************************
446  * *
447  * *
448  **************************************************************************** */
449 bool
451  char *val;
452 {
453  int argc;
454  char *argv[32];
455  int i;
456  msg_eval_func_T *q = &msg_eval;
457  char buf[256];
458 
459  if (!msg_eval.ok && !init_msg_eval())
460  return FALSE;
461 
462  if (val == NULL) {
463  bool r;
464  char *env = NULL;
465 
466  if ((env = getenv("MSG_EVAL")) == NULL)
467  env = DEFAULT_MSG_EVAL;
469  if (!r)
470  return FALSE;
471 
472  if ((env = getenv("MSG_SCALE")) == NULL)
473  env = DEFAULT_MSG_SCALE;
475 
476  return r;
477  }
478 
479  MUTEX_LOCK(&fmutex);
480 
481  strlcpy(q->buf_eval, val, sizeof (q->buf_eval));
482  strlcpy(buf, val, sizeof (buf));
483 
484  q->scale.kf1 = 1.;
485  q->scale.kf0 = 0.;
486  q->scale.bayes = 1.;
487  q->scale.urlbl = 0.2;
488  q->scale.regex = 0.2;
489  q->scale.oracle = 1.;
490  q->func = EVAL_UNDEF;
491 
492  argc = zeStr2Tokens(buf, 32, argv, ";, ");
493  for (i = 0; i < argc; i++) {
494  if (!decode_msg_eval_token(q, argv[i])) {
495  ZE_MessageWarning(9, "Hu... I didn't understand this : %s ???", argv[i]);
496  goto fin;
497  }
498  }
499 
500 fin:
501  MUTEX_UNLOCK(&fmutex);
502 
503  return q->func != EVAL_UNDEF;
504 }
505 
506 /* ****************************************************************************
507  * *
508  * *
509  **************************************************************************** */
510 bool
512  char *val;
513 {
514  int argc;
515  char *argv[32];
516  int i;
517  msg_eval_func_T *q = &msg_eval;
518  char buf[256];
519 
520  if (!msg_eval.ok && !init_msg_eval())
521  return FALSE;
522 
523  MUTEX_LOCK(&fmutex);
524 
525  strlcpy(q->buf_scale, val, sizeof (q->buf_scale));
526  strlcpy(buf, val, sizeof (buf));
527 
528  q->scale.kf1 = 1.;
529  q->scale.kf0 = 0.;
530  q->scale.bayes = 1.;
531  q->scale.urlbl = 0.2;
532  q->scale.regex = 0.2;
533  q->scale.oracle = 1.;
534 
535  argc = zeStr2Tokens(buf, 32, argv, ";, ");
536  for (i = 0; i < argc; i++) {
537  if (!decode_msg_eval_token(q, argv[i])) {
538  ZE_MessageWarning(9, "Hu... I didn't understand this : %s ???", argv[i]);
539  goto fin;
540  }
541  }
542 
543 fin:
544  MUTEX_UNLOCK(&fmutex);
545 
546  return q->func != EVAL_UNDEF;
547 }
548 
549 
550 /* ****************************************************************************
551  * *
552  * *
553  **************************************************************************** */
554 bool
556 {
557  msg_eval_func_T *q = &msg_eval;
558 
559  if (!q->ok)
560  return FALSE;
561 
562  MUTEX_LOCK(&fmutex);
563 
564  switch (q->func) {
565  case EVAL_UNDEF:
566  ZE_MessageInfo(10, "* UNDEFINED : %s", q->buf_eval);
567  ZE_MessageInfo(10, "");
568  break;
569  case EVAL_VECTOR:
570  ZE_MessageInfo(10, "* VECTOR : %s", q->buf_eval);
571  ZE_MessageInfo(10, " : %s", q->buf_scale);
572  ZE_MessageInfo(10, " * SCALES");
573  ZE_MessageInfo(10, " SSCORE1 : %6.3f", q->scale.kf1);
574  ZE_MessageInfo(10, " SSCORE0 : %6.3f", q->scale.kf0);
575  ZE_MessageInfo(10, " SBAYES : %6.3f", q->scale.bayes);
576  ZE_MessageInfo(10, " SURLBL : %6.3f", q->scale.urlbl);
577  ZE_MessageInfo(10, " SREGEX : %6.3f", q->scale.regex);
578  ZE_MessageInfo(10, " SORACLE : %6.3f", q->scale.oracle);
579  ZE_MessageInfo(10, " * COEFFICIENTS");
580  ZE_MessageInfo(10, " KBAYES : %6.3f", q->function.vector.kbayes);
581  ZE_MessageInfo(10, " KREGEX : %6.3f", q->function.vector.kregex);
582  ZE_MessageInfo(10, " KURLBL : %6.3f", q->function.vector.kurlbl);
583  ZE_MessageInfo(10, " KORACLE : %6.3f", q->function.vector.koracle);
584  ZE_MessageInfo(10, "");
585  break;
586  case EVAL_LOGIT:
587  ZE_MessageInfo(10, "* LOGIT : %s", q->buf_eval);
588  ZE_MessageInfo(10, " : %s", q->buf_scale);
589  ZE_MessageInfo(10, " * SCALES");
590  ZE_MessageInfo(10, " SSCORE1 : %6.3f", q->scale.kf1);
591  ZE_MessageInfo(10, " SSCORE0 : %6.3f", q->scale.kf0);
592  ZE_MessageInfo(10, " SBAYES : %6.3f", q->scale.bayes);
593  ZE_MessageInfo(10, " SURLBL : %6.3f", q->scale.urlbl);
594  ZE_MessageInfo(10, " SREGEX : %6.3f", q->scale.regex);
595  ZE_MessageInfo(10, " SORACLE : %6.3f", q->scale.oracle);
596  ZE_MessageInfo(10, " * COEFFICIENTS");
597  ZE_MessageInfo(10, " KBAYES : %6.3f", q->function.logit.kbayes);
598  ZE_MessageInfo(10, " KREGEX : %6.3f", q->function.logit.kregex);
599  ZE_MessageInfo(10, " KURLBL : %6.3f", q->function.logit.kurlbl);
600  ZE_MessageInfo(10, " KORACLE : %6.3f", q->function.logit.koracle);
601  ZE_MessageInfo(10, "");
602  break;
603  case EVAL_SUM:
604  ZE_MessageInfo(10, "* SUM : %s", q->buf_eval);
605  ZE_MessageInfo(10, " : %s", q->buf_scale);
606  ZE_MessageInfo(10, " * SCALES");
607  ZE_MessageInfo(10, " SSCORE1 : %6.3f", q->scale.kf1);
608  ZE_MessageInfo(10, " SSCORE0 : %6.3f", q->scale.kf0);
609  ZE_MessageInfo(10, " SBAYES : %6.3f", q->scale.bayes);
610  ZE_MessageInfo(10, " SURLBL : %6.3f", q->scale.urlbl);
611  ZE_MessageInfo(10, " SREGEX : %6.3f", q->scale.regex);
612  ZE_MessageInfo(10, " SORACLE : %6.3f", q->scale.oracle);
613  ZE_MessageInfo(10, " * COEFFICIENTS");
614  ZE_MessageInfo(10, " KBAYES : %6.3f", q->function.sum.kbayes);
615  ZE_MessageInfo(10, " KREGEX : %6.3f", q->function.sum.kregex);
616  ZE_MessageInfo(10, " KURLBL : %6.3f", q->function.sum.kurlbl);
617  ZE_MessageInfo(10, " KORACLE : %6.3f", q->function.sum.koracle);
618  ZE_MessageInfo(10, "");
619  break;
620  default:
621  break;
622  }
623 
624  MUTEX_UNLOCK(&fmutex);
625 
626  return TRUE;
627 }
628 
629 /* ****************************************************************************
630  * *
631  * *
632  **************************************************************************** */
633 double
635  msg_scores_T *scp;
636 {
637  msg_eval_func_T *q = &msg_eval;
638  double score = 0.;
639  int regex;
640 
641  ASSERT(scp != NULL);
642 
643  if (!q->ok)
644  return FALSE;
645 
646  MUTEX_LOCK(&fmutex);
647 
648  if (scp->bayes < 0.)
649  scp->bayes = 0;
650 
651  regex = scp->body + scp->headers;
652 
653  scp->combined = 0.;
654  switch (q->func) {
655  case EVAL_UNDEF:
656  ZE_MessageInfo(11, "* UNDEFINED : %s", q->buf_eval);
657  break;
658  case EVAL_VECTOR:
659  {
660  double k = 0.;
661 
662  ZE_MessageInfo(11, "* VECTOR : %s", q->buf_eval);
663  k = regex * q->function.vector.kregex;
664  score += SQR(k);
665  k = scp->urlbl * q->function.vector.kurlbl;
666  score += SQR(k);
667 
668  if (scp->do_bayes) {
669  double x;
670 
671  x = logit(scp->bayes) + 0.5 * logit(scp->noracle);
672  k = logitinv(x) * q->function.vector.kbayes;
673  score += SQR(k);
674  } else {
675  k = scp->oracle * q->function.vector.koracle;
676  score += SQR(k);
677  }
678 
679  score = sqrt(score);
680  scp->combined = score;
681  }
682  break;
683  case EVAL_LOGIT:
684  {
685  double k = 0.;
686 
687  ZE_MessageInfo(11, "* LOGIT : %s", q->buf_eval);
688  k = regex * q->function.logit.kregex;
689  score += k;
690  k = scp->urlbl * q->function.logit.kurlbl;
691  score += k;
692  k = scp->oracle * q->function.logit.koracle;
693  score += k;
694  if (scp->do_bayes) {
695  k = logit(scp->bayes) * q->function.logit.kbayes;
696  score += k;
697  }
698  scp->combined = logitinv(score);
699  }
700  break;
701  case EVAL_SUM:
702  {
703  double k = 0.;
704 
705  ZE_MessageInfo(11, "* SUM : %s", q->buf_eval);
706  k = regex * q->function.sum.kregex;
707  score += k;
708  k = scp->urlbl * q->function.sum.kurlbl;
709  score += k;
710  k = scp->bayes * q->function.sum.kbayes;
711  score += k;
712  k = scp->oracle * q->function.sum.koracle;
713  score += k;
714  scp->combined = score;
715  }
716  break;
717  default:
718  break;
719  }
720 
721  MUTEX_UNLOCK(&fmutex);
722 
723 #if 0
724  ZE_MessageInfo(10, " R=%.3f O=%.3f U=%.3f B=%.3f S=%.3f",
725  (double) regex, (double) scp->oracle, (double) scp->urlbl,
726  scp->bayes, score);
727 #endif
728 
729  return score;
730 }
731 
732 /* ****************************************************************************
733  * *
734  * *
735  **************************************************************************** */
736 bool
737 create_msg_score_header(buf, size, id, hostname, scp)
738  char *buf;
739  size_t size;
740  char *id;
741  char *hostname;
742  msg_scores_T *scp;
743 {
744  double score, nx;
745  char sout[512];
746  int n;
747  char sr[16], su[16], so[16];
748  int regex;
749 
750  ASSERT(scp != NULL);
751 
752  if (scp->bayes < 0.)
753  scp->bayes = 0.;
754  regex = scp->body + scp->headers;
755 
756  score = compute_msg_score(scp);
757 
758  nx = msg_eval.scale.kf1 * (score - msg_eval.scale.kf0);
759  nx = MAX(nx, 0);
760  n = MIN(nx, MAX_MSG_SCORE);
761  if (n > 0)
762  zeStrSet(sout, 'X', n);
763  else
764  strlcpy(sout, ".", sizeof (sout));
765  if (nx > MAX_MSG_SCORE)
766  strlcat(sout, "+", sizeof (sout));
767 
768  memset(sr, 0, sizeof (sr));
769  memset(su, 0, sizeof (su));
770  memset(so, 0, sizeof (so));
771 
772  nx = msg_eval.scale.regex * regex;
773  n = MIN(nx, sizeof (sr) - 1);
774  if (n > 0)
775  zeStrSet(sr, '#', n);
776  else
777  strlcpy(sr, ".", sizeof (sr));
778 
779  nx = msg_eval.scale.urlbl * scp->urlbl;
780  n = MIN(nx, sizeof (su) - 1);
781  if (n > 0)
782  zeStrSet(su, '#', n);
783  else
784  strlcpy(su, ".", sizeof (su));
785 
786  nx = msg_eval.scale.oracle * scp->oracle;
787  n = MIN(nx, sizeof (so) - 1);
788  if (n > 0)
789  zeStrSet(so, '#', n);
790  else
791  strlcpy(so, ".", sizeof (so));
792 
793  if (buf != NULL && size > 0) {
794  id = STRNULL(id, "NOID");
795  hostname = STRNULL(hostname, "UNKNOWN");
796 
797  snprintf(buf, size,
798  "MSGID : %s on %s : ze-filter score : %s : R=%s U=%s O=%s B=%.3f -> S=%.3f",
799  id, hostname, sout, sr, su, so, scp->bayes, score);
800  }
801 
802  return TRUE;
803 }
804 
805 /* ****************************************************************************
806  * *
807  * *
808  **************************************************************************** */
809 bool
811  scores_scale_T *scale;
812 {
813  ASSERT(scale != NULL);
814 
815  *scale = msg_eval.scale;
816 
817  return TRUE;
818 }
819 
820 /* ****************************************************************************
821  * *
822  * *
823  **************************************************************************** */
824 bool
825 fill_msg_scores(scores, do_bayes, bayes, do_regex, regex, do_urlbl, urlbl,
826  do_oracle, oracle)
827  msg_scores_T *scores;
828  bool do_bayes;
829  double bayes;
830  bool do_regex;
831  int regex;
832  bool do_urlbl;
833  int urlbl;
834  bool do_oracle;
835  int oracle;
836 {
837  ASSERT(scores != NULL);
838 
839  scores->do_bayes = do_bayes;
840  scores->bayes = bayes;
841  scores->do_regex = do_regex;
842  scores->body = regex;
843  scores->do_urlbl = do_urlbl;
844  scores->urlbl = urlbl;
845  scores->do_oracle = do_oracle;
846  scores->oracle = oracle;
847 
848  return TRUE;
849 }
850 
851 /* ****************************************************************************
852  * *
853  * ## #### ##### # #### # # *
854  * # # # # # # # # ## # *
855  * # # # # # # # # # # *
856  * ###### # # # # # # # # *
857  * # # # # # # # # # ## *
858  * # # #### # # #### # # *
859  * *
860  **************************************************************************** */
861 
862 typedef struct {
863  int action;
864  char buf[256]; /* configuration string */
865  int type; /* decoded type : THRESHOLD or REGEX */
866  union {
867  double threshold;
868  char regex[256];
869  } value;
871 
872 #define N_ACTIONS 16
873 
874 #define MATCH_THRESHOLD 0
875 #define MATCH_REGEX 1
876 
877 static bool ok_actions = FALSE;
878 static msg_eval_action_T msg_actions[N_ACTIONS];
879 static pthread_mutex_t amutex = PTHREAD_MUTEX_INITIALIZER;
880 
881 /* ****************************************************************************
882  * *
883  * *
884  **************************************************************************** */
885 static bool
886 init_msg_actions()
887 {
888  int i;
889 
890  if (ok_actions)
891  return TRUE;
892 
893  MUTEX_LOCK(&amutex);
894 
895  if (ok_actions)
896  goto fin;
897 
898  memset(msg_actions, 0, sizeof msg_actions);
899  for (i = 0; i < N_ACTIONS; i++)
900  msg_actions[i].action = MSG_ACTION_UNDEF;
901  ok_actions = TRUE;
902 
903 fin:
904  MUTEX_UNLOCK(&amutex);
905 
906  return ok_actions;
907 }
908 
909 static bool
910 set_message_action(q, which, val)
912  int which;
913  char *val;
914 {
915  char buf[256];
916  char *p = NULL, *s = NULL;
917  bool result = FALSE;
918 
919  ASSERT(q != NULL);
920  memset(q, 0, sizeof (*q));
921  if (val == NULL || strlen(val) == 0) {
922  result = TRUE;
923  goto fin;
924  }
925 
926  q->action = which;
927  strlcpy(q->buf, val, sizeof (q->buf));
928  strlcpy(buf, val, sizeof (buf));
929 
930  p = buf;
931 
932  s = "THRESHOLD:";
933  if (STRNCASEEQUAL(s, p, strlen(s))) {
934  double k;
935 
936  q->type = MATCH_THRESHOLD;
937  p += strlen(s);
938  errno = 0;
939  k = strtod(p, NULL);
940  if (errno == 0) {
941  q->value.threshold = k;
942  result = TRUE;
943  }
944  goto fin;
945  }
946  s = "REGEX:";
947  if (STRNCASEEQUAL(s, p, strlen(s))) {
948  q->type = MATCH_REGEX;
949  p += strlen(s);
950  strlcpy(q->value.regex, p, sizeof (q->value.regex));
951 
952  result = TRUE;
953  goto fin;
954  }
955 
956  ZE_MessageWarning(0, "Hu... I didn't understand this : %s ???", p);
957  goto fin;
958 
959 fin:
960  return result;
961 }
962 
963 /* ****************************************************************************
964  * *
965  * *
966  **************************************************************************** */
967 bool
969  int which;
970  char *val;
971 {
972  int i;
973  bool result = FALSE;
974 
975  if (!ok_actions && !init_msg_actions())
976  return FALSE;
977 
978  MUTEX_LOCK(&amutex);
979 
980  for (i = 0; i < N_ACTIONS; i++) {
981  if (msg_actions[i].action == MSG_ACTION_UNDEF) {
982  msg_eval_action_T *q = &msg_actions[i];
983 
984  result = set_message_action(q, which, val);
985  break;
986  }
987  if (msg_actions[i].action == which) {
988  msg_eval_action_T *q = &msg_actions[i];
989 
990  result = set_message_action(q, which, val);
991  break;
992  }
993  }
994 
995 fin:
996  MUTEX_UNLOCK(&amutex);
997 
998  return result;
999 }
1000 
1001 /* ****************************************************************************
1002  * *
1003  * *
1004  **************************************************************************** */
1005 bool
1006 evaluate_msg_action(action, scp, score, str)
1007  int action;
1008  msg_scores_T *scp;
1009  double score;
1010  char *str;
1011 {
1012  int i;
1013  bool result = FALSE;
1014 
1015  if (!ok_actions && !init_msg_actions())
1016  return FALSE;
1017 
1018  MUTEX_LOCK(&amutex);
1019 
1020  for (i = 0; i < N_ACTIONS; i++) {
1021  if (msg_actions[i].action == action) {
1022  msg_eval_action_T *q = &msg_actions[i];
1023 
1024  switch (q->type) {
1025  case MATCH_THRESHOLD:
1026  result = score > q->value.threshold;
1027  break;
1028  case MATCH_REGEX:
1029  if (str != NULL)
1030  result = zeStrRegex(str, q->value.regex, NULL, NULL, TRUE);
1031  else
1032  ZE_LogMsgError(0, "str : NULL pointer");
1033  break;
1034  default:
1035  break;
1036  }
1037  break;
1038  }
1039  }
1040 
1041 fin:
1042  MUTEX_UNLOCK(&amutex);
1043 
1044  return result;
1045 }
#define EVAL_LOGIT
Definition: ze-msg-score.c:51
#define MAX(a, b)
Definition: macros.h:139
double combined
Definition: ze-msg-score.h:73
bool register_msg_action(int which, char *val)
Definition: ze-msg-score.c:968
struct msg_eval_func_T::@7::@10 logit
scores_scale_T scale
Definition: ze-msg-score.c:58
struct msg_eval_func_T::@7::@9 sum
#define ASSERT(a)
Definition: macros.h:27
union msg_eval_action_T::@11 value
#define MUTEX_UNLOCK(mutex)
Definition: macros.h:101
#define STRNULL(x, r)
Definition: macros.h:81
bool configure_msg_eval_function(char *val)
Definition: ze-msg-score.c:450
#define STRNCASEEQUAL(a, b, n)
Definition: macros.h:75
#define MUTEX_LOCK(mutex)
Definition: macros.h:93
bool display_msg_eval()
Definition: ze-msg-score.c:555
#define FALSE
Definition: macros.h:160
#define strlcpy
Definition: zeString.h:32
#define ZE_LogMsgError(level,...)
Definition: zeSyslog.h:113
bool zeStrRegex(char *, char *, long *, long *, bool)
Definition: zeStrings.c:544
#define EVAL_VECTOR
Definition: ze-msg-score.c:49
int zeStr2Tokens(char *, int, char **, char *)
Definition: zeStrings.c:610
#define MIN(a, b)
Definition: macros.h:140
#define SQR(x)
Definition: ze-msg-score.c:31
bool evaluate_msg_action(int action, msg_scores_T *scp, double score, char *str)
#define strlcat
Definition: zeString.h:28
#define EVAL_SUM
Definition: ze-msg-score.c:48
#define MAX_MSG_SCORE
Definition: ze-msg-score.c:34
#define MATCH_THRESHOLD
Definition: ze-msg-score.c:874
union msg_eval_func_T::@7 function
bool fill_msg_scale(scores_scale_T *scale)
Definition: ze-msg-score.c:810
bool create_msg_score_header(char *buf, size_t size, char *id, char *hostname, msg_scores_T *scp)
Definition: ze-msg-score.c:737
bool configure_msg_score_scales(char *val)
Definition: ze-msg-score.c:511
char * zeStrSet(char *, int, int)
Definition: zeStrings.c:330
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
char buf_scale[256]
Definition: ze-msg-score.c:55
#define TRUE
Definition: macros.h:157
#define ZE_MessageWarning(level,...)
Definition: zeSyslog.h:92
bool fill_msg_scores(msg_scores_T *scores, bool do_bayes, double bayes, bool do_regex, int regex, bool do_urlbl, int urlbl, bool do_oracle, int oracle)
Definition: ze-msg-score.c:825
double logitinv(double x)
Definition: ze-logit.c:78
#define MATCH_REGEX
Definition: ze-msg-score.c:875
double bayes
Definition: ze-msg-score.h:88
double noracle
Definition: ze-msg-score.h:85
#define EVAL_SHLIB
Definition: ze-msg-score.c:50
char buf_eval[256]
Definition: ze-msg-score.c:56
#define N_ACTIONS
Definition: ze-msg-score.c:872
#define EVAL_UNDEF
Definition: ze-msg-score.c:47
double compute_msg_score(msg_scores_T *scp)
Definition: ze-msg-score.c:634
struct msg_eval_func_T::@7::@8 vector
#define DEFAULT_MSG_EVAL
Definition: ze-msg-score.h:122
#define DEFAULT_MSG_SCALE
Definition: ze-msg-score.h:126
double logit(double p)
Definition: ze-logit.c:34
#define MSG_ACTION_UNDEF
Definition: ze-msg-score.h:39