1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <assert.h>
5 
6 #include "mlocale.h"
7 #include "mhash.h"
8 #include "misc.h"
9 
10 #include "datatypes/count/datatype.h"
11 
12 #include "mail.h"
13 #include "plugin_config.h"
14 #include "pictures.h"
15 #include "template.h"
16 #include "generate.h"
17 
18 #define M_REPORT_MAIL_SENDER      "mail_sender"
19 #define M_REPORT_MAIL_SENDER_TRAFFIC      "mail_sender_traffic"
20 #define M_REPORT_MAIL_RECEIPIENT  "mail_receipient"
21 #define M_REPORT_MAIL_RECEIPIENT_TRAFFIC  "mail_receipient_traffic"
22 #define M_REPORT_MAIL_DOM_IN      "mail_incoming_domains"
23 #define M_REPORT_MAIL_DOM_IN_TRAFFIC      "mail_incoming_domains_traffic"
24 #define M_REPORT_MAIL_DOM_OUT     "mail_outgoing_domains"
25 #define M_REPORT_MAIL_DOM_OUT_TRAFFIC     "mail_outgoing_domains_traffic"
26 #define M_REPORT_MAIL_DAILY       "mail_daily"
27 #define	M_REPORT_MAIL_HOURLY      "mail_hourly"
28 #define	M_REPORT_MAIL_QUEUE_POLLUTION "mail_qmail_queue_pollution"
29 #define M_REPORT_MAIL_VIRUS       "mail_virus"
30 #define	M_REPORT_MAIL_SUBJECT     "mail_subject"
31 #define	M_REPORT_MAIL_SCANNER     "mail_scanner"
32 
33 #define HIGHLIGHT	1
34 #define GROUPING	2
35 #define VISITS		4
36 #define INDEX		8
37 #define BROKEN_LINK	16
38 #define PERCENT		32
39 #define RESOLVE_TLD     64
40 #define VISITS_TRAFFIC  128
41 #define SORT_BY_KEY     256
42 #define VIEW_DURATION   512
43 #define TIME            1024
44 #define SORT_BY_VCOUNT	2048
45 #define SORT_BY_QUOTIENT	4096
46 
47 #define BOTTOM_THRESHOLD	16
48 
show_mhash_mail(mconfig * ext_conf,tmpl_main * tmpl,mhash * h,int count,int opt)49 int show_mhash_mail (mconfig *ext_conf, tmpl_main *tmpl, mhash *h, int count, int opt) {
50 	int i;
51 	long sum = 0;
52 	double sum_vcount = 0;
53 	mdata **md;
54 
55 	if (!h) return 0;
56 
57 	sum = mhash_sumup(h);
58 	if (opt & VISITS && opt & PERCENT)
59 		sum_vcount = mhash_sumup_vcount(h);
60 
61 	if (opt & SORT_BY_KEY) {
62 		md = mhash_sorted_to_marray(h, M_SORTBY_KEY, M_SORTDIR_ASC);
63 	} else if (opt & SORT_BY_VCOUNT) {
64 		md = mhash_sorted_to_marray(h, M_SORTBY_VCOUNT, M_SORTDIR_DESC);
65 	} else if (opt & SORT_BY_QUOTIENT) {
66 		md = mhash_sorted_to_marray(h, M_SORTBY_QUOTIENT, M_SORTDIR_DESC);
67 	} else {
68 		md = mhash_sorted_to_marray(h, M_SORTBY_COUNT, M_SORTDIR_DESC);
69 	}
70 
71 	for (i = 0; md[i] && (i < count); i++) {
72 		mdata *data = md[i];
73 
74 		if (data) {
75 			unsigned int c = 0;
76 			char buf[255];
77 
78 			if (opt & INDEX) {
79 				sprintf(buf,"%d", i+1);
80 
81 				tmpl_set_current_block(tmpl, "table_cell");
82 				tmpl_set_var(tmpl, "CELL_ALIGN", "right");
83 				tmpl_set_var(tmpl, "CELL_CONTENT", buf);
84 				tmpl_parse_current_block(tmpl);
85 			}
86 
87 			c = mdata_get_count(data);
88 
89 			tmpl_set_current_block(tmpl, "table_cell");
90 			tmpl_set_var(tmpl, "CELL_ALIGN", "right");
91 			if (opt & TIME) {
92 				/*tmpl_set_var(tmpl, "CELL_CONTENT", get_duration_string(c));*/
93 			} else {
94 				sprintf(buf,"%d", c);
95 				tmpl_set_var(tmpl, "CELL_CONTENT", buf);
96 			}
97 			tmpl_parse_current_block(tmpl);
98 
99 			if (opt & PERCENT && sum) {
100 				tmpl_set_current_block(tmpl, "table_cell");
101 				tmpl_set_var(tmpl, "CELL_ALIGN", "right");
102 				sprintf(buf,"%.2f", c * 100.0 / sum);
103 				tmpl_set_var(tmpl, "CELL_CONTENT", buf);
104 				tmpl_parse_current_block(tmpl);
105 			}
106 
107 			if (opt & VISITS && data->type == M_DATA_TYPE_VISITED ) {
108 				tmpl_set_current_block(tmpl, "table_cell");
109 				tmpl_set_var(tmpl, "CELL_ALIGN", "right");
110 				if (opt & VISITS_TRAFFIC) {
111 					tmpl_set_var(tmpl, "CELL_CONTENT",
112 						     bytes_to_string(mdata_get_vcount(data)));
113 				} else {
114 					sprintf(buf,"%.0f", mdata_get_vcount(data));
115 					tmpl_set_var(tmpl, "CELL_CONTENT", buf);
116 				}
117 				tmpl_parse_current_block(tmpl);
118 				if (opt & PERCENT && sum) {
119 					tmpl_set_current_block(tmpl, "table_cell");
120 					tmpl_set_var(tmpl, "CELL_ALIGN", "right");
121 					sprintf(buf,"%.2f", mdata_get_vcount(data) * 100.0 / sum_vcount);
122 					tmpl_set_var(tmpl, "CELL_CONTENT", buf);
123 					tmpl_parse_current_block(tmpl);
124 				}
125 			}
126 #if 0
127 			if (opt & VIEW_DURATION && data->type == M_DATA_TYPE_VISITED ) {
128 				/* use count as duration and vcount as hits per page view */
129 
130 				tmpl_set_current_block(tmpl, "table_cell");
131 				tmpl_set_var(tmpl, "CELL_ALIGN", "right");
132 				sprintf(buf, "%.0f", data->data.visited.vcount);
133 				tmpl_set_var(tmpl, "CELL_CONTENT", buf);
134 				tmpl_parse_current_block(tmpl);
135 
136 				tmpl_set_current_block(tmpl, "table_cell");
137 				tmpl_set_var(tmpl, "CELL_ALIGN", "right");
138 				tmpl_set_var(tmpl, "CELL_CONTENT", data->data.visited.vcount ?
139 					     get_duration_string(data->data.visited.count / data->data.visited.vcount) :
140 					     "--");
141 				tmpl_parse_current_block(tmpl);
142 			}
143 #endif
144 			if ((opt & GROUPING) && mdata_is_grouped(data)) {
145 				tmpl_set_current_block(tmpl, "table_cell");
146 				tmpl_set_var(tmpl, "CELL_ALIGN", "left");
147 				tmpl_set_var(tmpl, "CELL_CLASS", "grouping");
148 				tmpl_set_var(tmpl, "CELL_CONTENT", data->key);
149 				tmpl_parse_current_block(tmpl);
150 
151 				tmpl_clear_var(tmpl, "CELL_CLASS");
152 			} else {
153 				if (opt & HIGHLIGHT) {
154 					tmpl_set_current_block(tmpl, "table_cell");
155 					tmpl_set_var(tmpl, "CELL_ALIGN", "left");
156 					sprintf(buf,"<a href=\"mailto:%s\">%s</a>",
157 						data->key,
158 						data->key);
159 					tmpl_set_var(tmpl, "CELL_CONTENT", buf);
160 					tmpl_parse_current_block(tmpl);
161 				} else {
162 					/* added option to resolve tlds on the fly */
163 					if (opt & RESOLVE_TLD) {
164 						tmpl_set_current_block(tmpl, "table_cell");
165 						tmpl_set_var(tmpl, "CELL_ALIGN", "left");
166 						tmpl_set_var(tmpl, "CELL_CONTENT", misoname(data->key));
167 						tmpl_parse_current_block(tmpl);
168 					} else {
169 						tmpl_set_current_block(tmpl, "table_cell");
170 						tmpl_set_var(tmpl, "CELL_ALIGN", "left");
171 						tmpl_set_var(tmpl, "CELL_CONTENT", data->key);
172 						tmpl_parse_current_block(tmpl);
173 					}
174 				}
175 			}
176 
177 			if (opt & BROKEN_LINK && data->type == M_DATA_TYPE_BROKENLINK) {
178 				struct tm *_tm;
179 				char timebuf[32] = "";
180 
181 				if (data->data.brokenlink.referrer &&
182 				    (0 != strcmp(data->data.brokenlink.referrer, "-"))) {
183 					tmpl_set_current_block(tmpl, "table_cell");
184 					tmpl_set_var(tmpl, "CELL_ALIGN", "left");
185 					tmpl_set_var(tmpl, "CELL_CONTENT", "<a href=\"");
186 					tmpl_append_var(tmpl, "CELL_CONTENT", data->data.brokenlink.referrer);
187 					tmpl_append_var(tmpl, "CELL_CONTENT", "\">");
188 					tmpl_append_var(tmpl, "CELL_CONTENT", data->data.brokenlink.referrer);
189 					tmpl_append_var(tmpl, "CELL_CONTENT", "</a>");
190 					tmpl_parse_current_block(tmpl);
191 				} else {
192 					tmpl_set_current_block(tmpl, "table_cell");
193 					tmpl_set_var(tmpl, "CELL_ALIGN", "left");
194 					tmpl_set_var(tmpl, "CELL_CONTENT", "-");
195 					tmpl_parse_current_block(tmpl);
196 				}
197 
198 				_tm = localtime(&(data->data.brokenlink.timestamp));
199 				if (strftime(timebuf, sizeof(timebuf)-1, "%x", _tm) == 0) {
200 					fprintf(stderr, "output::modlogan.show_mhash: strftime failed\n");
201 				}
202 				tmpl_set_current_block(tmpl, "table_cell");
203 				tmpl_set_var(tmpl, "CELL_ALIGN", "left");
204 				tmpl_set_var(tmpl, "CELL_CONTENT", timebuf);
205 				tmpl_parse_current_block(tmpl);
206 			}
207 
208 			tmpl_set_current_block(tmpl, "table_row");
209 			tmpl_parse_current_block(tmpl);
210 			tmpl_clear_block(tmpl, "table_cell");
211 		}
212 	}
213 
214 	free(md);
215 
216 	return 0;
217 }
218 
get_reports_mail(mconfig * ext_conf)219 reports_def *get_reports_mail (mconfig *ext_conf) {
220 	config_output *conf = ext_conf->plugin_conf;
221 
222 	reports_def reports[] = {
223 		/* 0 */
224 		  /* id             data  title */
225 		{ M_REPORT_MAIL_SENDER, _("Mails by Sender"),
226 			/* options */
227 			HIGHLIGHT | GROUPING | INDEX | PERCENT | VISITS | VISITS_TRAFFIC,
228 				0, /* show graph */
229 				NULL, /* graph function */
230 			{ /* fields */
231 				{ _("Hits"), "hits" },
232 				{ _("Traffic"), "traffic" },
233 				{ _("Mail-Address"), NULL },
234 				{ NULL, NULL },
235 				{ NULL, NULL }
236 			}
237 		},
238 		/* 1 */
239 		  /* id             data  title */
240 		{ M_REPORT_MAIL_SENDER_TRAFFIC, _("Mails by Sender Traffic"),
241 			/* options */
242 			HIGHLIGHT | GROUPING | INDEX | PERCENT | VISITS | VISITS_TRAFFIC | SORT_BY_VCOUNT,
243 				0, /* show graph */
244 				NULL, /* graph function */
245 			{ /* fields */
246 				{ _("Hits"), "hits" },
247 				{ _("Traffic"), "traffic" },
248 				{ _("Mail-Address"), NULL },
249 				{ NULL, NULL },
250 				{ NULL, NULL }
251 			}
252 		},
253 		/* 2 */
254 		{ M_REPORT_MAIL_RECEIPIENT, _("Mails by Receipient"),
255 			/* options */
256 			HIGHLIGHT | GROUPING | INDEX | PERCENT | VISITS | VISITS_TRAFFIC,
257 				0, /* show graph */
258 				NULL, /* graph function */
259 			{ /* fields */
260 				{ _("Hits"), "hits" },
261 				{ _("Traffic"), "traffic" },
262 				{ _("Mail-Address"), NULL },
263 				{ NULL, NULL },
264 				{ NULL, NULL }
265 			}
266 		},
267 
268 		/* 3 */
269 		{ M_REPORT_MAIL_RECEIPIENT_TRAFFIC, _("Mails by Receipient Traffic"),
270 			/* options */
271 			HIGHLIGHT | GROUPING | INDEX | PERCENT | VISITS | VISITS_TRAFFIC | SORT_BY_VCOUNT,
272 				0, /* show graph */
273 				NULL, /* graph function */
274 			{ /* fields */
275 				{ _("Hits"), "hits" },
276 				{ _("Traffic"), "traffic" },
277 				{ _("Mail-Address"), NULL },
278 				{ NULL, NULL },
279 				{ NULL, NULL }
280 			}
281 		},
282 
283 		/* 4 */
284 		{ M_REPORT_MAIL_DOM_IN, _("Domains by Destination"),
285 			/* options */
286 			HIGHLIGHT | GROUPING | INDEX | PERCENT | VISITS | VISITS_TRAFFIC,
287 				0, /* show graph */
288 				NULL, /* graph function */
289 			{ /* fields */
290 				{ _("Hits"), "hits" },
291 				{ _("Traffic"), "traffic" },
292 				{ _("Domain"), NULL },
293 				{ NULL, NULL },
294 				{ NULL, NULL }
295 			}
296 		},
297 
298 		/* 5 */
299 		{ M_REPORT_MAIL_DOM_IN_TRAFFIC, _("Domains by Destination Traffic"),
300 			/* options */
301 			HIGHLIGHT | GROUPING | INDEX | PERCENT | VISITS | VISITS_TRAFFIC | SORT_BY_VCOUNT,
302 				0, /* show graph */
303 				NULL, /* graph function */
304 			{ /* fields */
305 				{ _("Hits"), "hits" },
306 				{ _("Traffic"), "traffic" },
307 				{ _("Domain"), NULL },
308 				{ NULL, NULL },
309 				{ NULL, NULL }
310 			}
311 		},
312 
313 		/* 6 */
314 		{ M_REPORT_MAIL_DOM_OUT, _("Domains by Source"),
315 			/* options */
316 			HIGHLIGHT | GROUPING | INDEX | PERCENT | VISITS | VISITS_TRAFFIC,
317 				0, /* show graph */
318 				NULL, /* graph function */
319 			{ /* fields */
320 				{ _("Hits"), "hits" },
321 				{ _("Traffic"), "traffic" },
322 				{ _("Domain"), NULL },
323 				{ NULL, NULL },
324 				{ NULL, NULL }
325 			}
326 		},
327 
328 		/* 7 */
329 		{ M_REPORT_MAIL_DOM_OUT_TRAFFIC, _("Domains by Source Traffic"),
330 			/* options */
331 			HIGHLIGHT | GROUPING | INDEX | PERCENT | VISITS | VISITS_TRAFFIC | SORT_BY_VCOUNT,
332 				0, /* show graph */
333 				NULL, /* graph function */
334 			{ /* fields */
335 				{ _("Hits"), "hits" },
336 				{ _("Traffic"), "traffic" },
337 				{ _("Domain"), NULL },
338 				{ NULL, NULL },
339 				{ NULL, NULL }
340 			}
341 		},
342 
343 		/* 8 */
344 		{ M_REPORT_MAIL_VIRUS, _("Virus"),
345 			/* options */
346 			HIGHLIGHT | GROUPING | INDEX | PERCENT,
347 				0, /* show graph */
348 				NULL, /* graph function */
349 			{ /* fields */
350 				{ _("Hits"), "hits" },
351 				{ _("Mail-Address"), NULL },
352 				{ NULL, NULL },
353 				{ NULL, NULL },
354 				{ NULL, NULL }
355 			}
356 		},
357 
358 		/* 9 */
359 		{ M_REPORT_MAIL_SUBJECT, _("Subject used by a Virus"),
360 			/* options */
361 			HIGHLIGHT | GROUPING | INDEX | PERCENT,
362 				0, /* show graph */
363 				NULL, /* graph function */
364 			{ /* fields */
365 				{ _("Hits"), "hits" },
366 				{ _("Domain"), NULL },
367 				{ NULL, NULL },
368 				{ NULL, NULL },
369 				{ NULL, NULL }
370 			}
371 		},
372 
373 		/* 10 */
374 		{ M_REPORT_MAIL_SCANNER, _("Virus Scanner"),
375 			/* options */
376 			HIGHLIGHT | GROUPING | INDEX | PERCENT,
377 				0, /* show graph */
378 				NULL, /* graph function */
379 			{ /* fields */
380 				{ _("Hits"), "hits" },
381 				{ _("Domain"), NULL },
382 				{ NULL, NULL },
383 				{ NULL, NULL },
384 				{ NULL, NULL }
385 			}
386 		},
387 
388 		{0, NULL, 0, 0, NULL,
389 			{
390 				{ NULL, NULL },
391 				{ NULL, NULL },
392 				{ NULL, NULL },
393 				{ NULL, NULL },
394 				{ NULL, NULL }
395 			}
396 		}
397 	};
398 
399 	if (conf->mail_reports == NULL) {
400 		conf->mail_reports = malloc(sizeof(reports));
401 		memcpy(conf->mail_reports, reports, sizeof(reports));
402 	}
403 
404 	return conf->mail_reports;
405 }
406 
generate_mail_cleanup(mconfig * ext_conf)407 void generate_mail_cleanup(mconfig *ext_conf) {
408 	config_output *conf = ext_conf->plugin_conf;
409 
410 	if (conf->mail_reports) free(conf->mail_reports);
411 	conf->mail_reports = NULL;
412 }
413 
generate_mail_daily(mconfig * ext_conf,mstate * state,const char * current,int max)414 char * generate_mail_daily(mconfig * ext_conf, mstate * state, const char *current, int max) {
415 	config_output *conf = ext_conf->plugin_conf;
416 	int i;
417 	tmpl_main *tmpl;
418 	char *s, buf[255], *fn;
419 	mstate_mail *stamail = NULL;
420 	marray_mail sum;
421 
422 	if (state == NULL)
423 		return NULL;
424 
425 	if (state->ext == NULL)
426 		return NULL;
427 
428 	if (state->ext_type != M_STATE_TYPE_MAIL)
429 		return NULL;
430 
431 	stamail = state->ext;
432 
433 	sum.incoming_mails = 0;
434 	sum.outgoing_mails = 0;
435 	sum.incoming_bytes = 0;
436 	sum.outgoing_bytes = 0;
437 
438 	tmpl = tmpl_init();
439 	assert(tmpl);
440 
441 	if ((fn = generate_template_filename(ext_conf, M_TMPL_TABLE)) == NULL) {
442 		fprintf(stderr, "generating filename failed for '%s'\n", current);
443 		tmpl_free(tmpl);
444 		return NULL;
445 	}
446 
447 	if (tmpl_load_template(tmpl, fn) != 0) {
448 		free(fn);
449 		fprintf(stderr, "parsing template failed for '%s'\n", current);
450 		tmpl_free(tmpl);
451 		return NULL;
452 	}
453 	free(fn);
454 
455 	/* header */
456 
457 	tmpl_set_current_block(tmpl, "table_cell");
458 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Day"));
459 	tmpl_set_var(tmpl, "CELL_CLASS", "none");
460 	tmpl_parse_current_block(tmpl);
461 
462 	tmpl_set_current_block(tmpl, "table_cell");
463 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Mail - incoming"));
464 	tmpl_set_var(tmpl, "CELL_CLASS", "hits");
465 	tmpl_parse_current_block(tmpl);
466 
467 	tmpl_set_current_block(tmpl, "table_cell");
468 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Mail - outgoing"));
469 	tmpl_set_var(tmpl, "CELL_CLASS", "hits");
470 	tmpl_parse_current_block(tmpl);
471 
472 	tmpl_set_current_block(tmpl, "table_cell");
473 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Traffic - incoming"));
474 	tmpl_set_var(tmpl, "CELL_CLASS", "traffic");
475 	tmpl_parse_current_block(tmpl);
476 
477 	tmpl_set_current_block(tmpl, "table_cell");
478 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Traffic - outgoing"));
479 	tmpl_set_var(tmpl, "CELL_CLASS", "traffic");
480 	tmpl_parse_current_block(tmpl);
481 
482 	tmpl_set_current_block(tmpl, "table_row");
483 	tmpl_parse_current_block(tmpl);
484 
485 	tmpl_clear_block(tmpl, "table_cell");
486 
487 	for ( i = 0; i < 31; i++) {
488 		tmpl_set_current_block(tmpl, "table_cell");
489 		sprintf(buf, "%d", i);
490 		tmpl_set_var(tmpl, "CELL_CONTENT", buf);
491 		tmpl_set_var(tmpl, "CELL_CLASS", "none");
492 		tmpl_set_var(tmpl, "CELL_ALIGN", "right");
493 		tmpl_parse_current_block(tmpl);
494 
495 		tmpl_set_current_block(tmpl, "table_cell");
496 		sprintf(buf, "%ld", stamail->days[i].incoming_mails);
497 		tmpl_set_var(tmpl, "CELL_CONTENT", buf);
498 		tmpl_set_var(tmpl, "CELL_CLASS", "none");
499 		tmpl_set_var(tmpl, "CELL_ALIGN", "right");
500 		tmpl_parse_current_block(tmpl);
501 
502 		tmpl_set_current_block(tmpl, "table_cell");
503 		sprintf(buf, "%ld", stamail->days[i].outgoing_mails);
504 		tmpl_set_var(tmpl, "CELL_CONTENT", buf);
505 		tmpl_set_var(tmpl, "CELL_CLASS", "none");
506 		tmpl_set_var(tmpl, "CELL_ALIGN", "right");
507 		tmpl_parse_current_block(tmpl);
508 
509 		tmpl_set_current_block(tmpl, "table_cell");
510 		tmpl_set_var(tmpl, "CELL_CONTENT",
511 			     bytes_to_string(stamail->days[i].incoming_bytes));
512 		tmpl_set_var(tmpl, "CELL_CLASS", "none");
513 		tmpl_set_var(tmpl, "CELL_ALIGN", "right");
514 		tmpl_parse_current_block(tmpl);
515 
516 		tmpl_set_current_block(tmpl, "table_cell");
517 		tmpl_set_var(tmpl, "CELL_CONTENT",
518 			     bytes_to_string(stamail->days[i].outgoing_bytes));
519 		tmpl_set_var(tmpl, "CELL_CLASS", "none");
520 		tmpl_set_var(tmpl, "CELL_ALIGN", "right");
521 		tmpl_parse_current_block(tmpl);
522 
523 		tmpl_set_current_block(tmpl, "table_row");
524 		tmpl_parse_current_block(tmpl);
525 
526 		tmpl_clear_block(tmpl, "table_cell");
527 
528 		sum.incoming_mails += stamail->days[i].incoming_mails;
529 		sum.outgoing_mails += stamail->days[i].outgoing_mails;
530 		sum.incoming_bytes += stamail->days[i].incoming_bytes;
531 		sum.outgoing_bytes += stamail->days[i].outgoing_bytes;
532 	}
533 
534 	sprintf(buf, "%d", 6);
535 	tmpl_set_var(tmpl, "TABLE_TITLE", _("Mails and Traffic per hour"));
536 	tmpl_set_var(tmpl, "TABLE_COL_SPAN", buf);
537 
538 	if (tmpl_replace(tmpl, conf->tmp_buf)) {
539 		tmpl_free(tmpl);
540 
541 		return NULL;
542 	}
543 
544 	tmpl_free(tmpl);
545 
546 	s = strdup(conf->tmp_buf->ptr);
547 
548 	return s;
549 }
550 
generate_mail_hourly(mconfig * ext_conf,mstate * state,const char * current,int max)551 char * generate_mail_hourly(mconfig * ext_conf, mstate * state, const char *current, int max) {
552 	config_output *conf = ext_conf->plugin_conf;
553 	int i;
554 	tmpl_main *tmpl;
555 	char *s, buf[255], *fn;
556 	mstate_mail *stamail = NULL;
557 	marray_mail sum;
558 
559 	if (state == NULL)
560 		return NULL;
561 
562 	if (state->ext == NULL)
563 		return NULL;
564 
565 	if (state->ext_type != M_STATE_TYPE_MAIL)
566 		return NULL;
567 
568 	stamail = state->ext;
569 
570 	sum.incoming_mails = 0;
571 	sum.outgoing_mails = 0;
572 	sum.incoming_bytes = 0;
573 	sum.outgoing_bytes = 0;
574 
575 	tmpl = tmpl_init();
576 	assert(tmpl);
577 
578 	if ((fn = generate_template_filename(ext_conf, M_TMPL_TABLE)) == NULL) {
579 		fprintf(stderr, "generating filename failed for '%s'\n", current);
580 		tmpl_free(tmpl);
581 		return NULL;
582 	}
583 
584 	if (tmpl_load_template(tmpl, fn) != 0) {
585 		free(fn);
586 		fprintf(stderr, "parsing template failed for '%s'\n", current);
587 		tmpl_free(tmpl);
588 		return NULL;
589 	}
590 	free(fn);
591 
592 	/* header */
593 
594 	tmpl_set_current_block(tmpl, "table_cell");
595 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Hour"));
596 	tmpl_set_var(tmpl, "CELL_CLASS", "none");
597 	tmpl_parse_current_block(tmpl);
598 
599 	tmpl_set_current_block(tmpl, "table_cell");
600 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Mail - incoming"));
601 	tmpl_set_var(tmpl, "CELL_CLASS", "hits");
602 	tmpl_parse_current_block(tmpl);
603 
604 	tmpl_set_current_block(tmpl, "table_cell");
605 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Mail - outgoing"));
606 	tmpl_set_var(tmpl, "CELL_CLASS", "hits");
607 	tmpl_parse_current_block(tmpl);
608 
609 	tmpl_set_current_block(tmpl, "table_cell");
610 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Traffic - incoming"));
611 	tmpl_set_var(tmpl, "CELL_CLASS", "traffic");
612 	tmpl_parse_current_block(tmpl);
613 
614 	tmpl_set_current_block(tmpl, "table_cell");
615 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Traffic - outgoing"));
616 	tmpl_set_var(tmpl, "CELL_CLASS", "traffic");
617 	tmpl_parse_current_block(tmpl);
618 
619 	tmpl_set_current_block(tmpl, "table_row");
620 	tmpl_parse_current_block(tmpl);
621 
622 	tmpl_clear_block(tmpl, "table_cell");
623 
624 	for ( i = 0; i < 24; i++) {
625 		tmpl_set_current_block(tmpl, "table_cell");
626 		sprintf(buf, "%d", i);
627 		tmpl_set_var(tmpl, "CELL_CONTENT", buf);
628 		tmpl_set_var(tmpl, "CELL_CLASS", "none");
629 		tmpl_set_var(tmpl, "CELL_ALIGN", "right");
630 		tmpl_parse_current_block(tmpl);
631 
632 		tmpl_set_current_block(tmpl, "table_cell");
633 		sprintf(buf, "%ld", stamail->hours[i].incoming_mails);
634 		tmpl_set_var(tmpl, "CELL_CONTENT", buf);
635 		tmpl_set_var(tmpl, "CELL_CLASS", "none");
636 		tmpl_set_var(tmpl, "CELL_ALIGN", "right");
637 		tmpl_parse_current_block(tmpl);
638 
639 		tmpl_set_current_block(tmpl, "table_cell");
640 		sprintf(buf, "%ld", stamail->hours[i].outgoing_mails);
641 		tmpl_set_var(tmpl, "CELL_CONTENT", buf);
642 		tmpl_set_var(tmpl, "CELL_CLASS", "none");
643 		tmpl_set_var(tmpl, "CELL_ALIGN", "right");
644 		tmpl_parse_current_block(tmpl);
645 
646 		tmpl_set_current_block(tmpl, "table_cell");
647 		tmpl_set_var(tmpl, "CELL_CONTENT",
648 			     bytes_to_string(stamail->hours[i].incoming_bytes));
649 		tmpl_set_var(tmpl, "CELL_CLASS", "none");
650 		tmpl_set_var(tmpl, "CELL_ALIGN", "right");
651 		tmpl_parse_current_block(tmpl);
652 
653 		tmpl_set_current_block(tmpl, "table_cell");
654 		tmpl_set_var(tmpl, "CELL_CONTENT",
655 			     bytes_to_string(stamail->hours[i].outgoing_bytes));
656 		tmpl_set_var(tmpl, "CELL_CLASS", "none");
657 		tmpl_set_var(tmpl, "CELL_ALIGN", "right");
658 		tmpl_parse_current_block(tmpl);
659 
660 		tmpl_set_current_block(tmpl, "table_row");
661 		tmpl_parse_current_block(tmpl);
662 
663 		tmpl_clear_block(tmpl, "table_cell");
664 
665 		sum.incoming_mails += stamail->hours[i].incoming_mails;
666 		sum.outgoing_mails += stamail->hours[i].outgoing_mails;
667 		sum.incoming_bytes += stamail->hours[i].incoming_bytes;
668 		sum.outgoing_bytes += stamail->hours[i].outgoing_bytes;
669 	}
670 
671 	sprintf(buf, "%d", 6);
672 	tmpl_set_var(tmpl, "TABLE_TITLE", _("Mails and Traffic per hour"));
673 	tmpl_set_var(tmpl, "TABLE_COL_SPAN", buf);
674 
675 	if (tmpl_replace(tmpl, conf->tmp_buf)) {
676 		tmpl_free(tmpl);
677 
678 		return NULL;
679 	}
680 
681 	tmpl_free(tmpl);
682 
683 	s = strdup(conf->tmp_buf->ptr);
684 
685 
686 	return s;
687 }
688 
generate_mail_qmail_queue(mconfig * ext_conf,mstate * state,const char * current,int max)689 char * generate_mail_qmail_queue(mconfig * ext_conf, mstate * state, const char *current, int max) {
690 	config_output *conf = ext_conf->plugin_conf;
691 	int i;
692 	tmpl_main *tmpl;
693 	char *s, buf[255], *fn;
694 	mstate_mail *stamail = NULL;
695 
696 	if (state == NULL)
697 		return NULL;
698 
699 	if (state->ext == NULL)
700 		return NULL;
701 
702 	if (state->ext_type != M_STATE_TYPE_MAIL)
703 		return NULL;
704 
705 	stamail = state->ext;
706 
707 	tmpl = tmpl_init();
708 	assert(tmpl);
709 
710 	if ((fn = generate_template_filename(ext_conf, M_TMPL_TABLE)) == NULL) {
711 		fprintf(stderr, "generating filename failed for '%s'\n", current);
712 		tmpl_free(tmpl);
713 		return NULL;
714 	}
715 
716 	if (tmpl_load_template(tmpl, fn) != 0) {
717 		free(fn);
718 		fprintf(stderr, "parsing template failed for '%s'\n", current);
719 		tmpl_free(tmpl);
720 		return NULL;
721 	}
722 	free(fn);
723 
724 	/* header */
725 
726 	tmpl_set_current_block(tmpl, "table_cell");
727 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Day"));
728 	tmpl_set_var(tmpl, "CELL_CLASS", "none");
729 	tmpl_parse_current_block(tmpl);
730 
731 	tmpl_set_current_block(tmpl, "table_cell");
732 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Hour"));
733 	tmpl_set_var(tmpl, "CELL_CLASS", "none");
734 	tmpl_parse_current_block(tmpl);
735 
736 	tmpl_set_current_block(tmpl, "table_cell");
737 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Local - cur"));
738 	tmpl_set_var(tmpl, "CELL_CLASS", "hits");
739 	tmpl_parse_current_block(tmpl);
740 
741 	tmpl_set_current_block(tmpl, "table_cell");
742 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Local - max"));
743 	tmpl_set_var(tmpl, "CELL_CLASS", "hits");
744 	tmpl_parse_current_block(tmpl);
745 
746 	tmpl_set_current_block(tmpl, "table_cell");
747 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Remote - cur"));
748 	tmpl_set_var(tmpl, "CELL_CLASS", "hits");
749 	tmpl_parse_current_block(tmpl);
750 
751 	tmpl_set_current_block(tmpl, "table_cell");
752 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Remote - max"));
753 	tmpl_set_var(tmpl, "CELL_CLASS", "hits");
754 	tmpl_parse_current_block(tmpl);
755 
756 	tmpl_set_current_block(tmpl, "table_cell");
757 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Delivery - cur"));
758 	tmpl_set_var(tmpl, "CELL_CLASS", "hits");
759 	tmpl_parse_current_block(tmpl);
760 
761 	tmpl_set_current_block(tmpl, "table_cell");
762 	tmpl_set_var(tmpl, "CELL_CONTENT", _("Queue - cur"));
763 	tmpl_set_var(tmpl, "CELL_CLASS", "hits");
764 	tmpl_parse_current_block(tmpl);
765 
766 
767 	tmpl_set_current_block(tmpl, "table_row");
768 	tmpl_parse_current_block(tmpl);
769 
770 	tmpl_clear_block(tmpl, "table_cell");
771 
772 	for (i = 0; i < 31; i++) {
773 		int j;
774 		for (j = 0; j < 24; j++) {
775 			if (stamail->qstat[i][j].count) {
776 				tmpl_set_current_block(tmpl, "table_cell");
777 				sprintf(buf, "%d", i + 1);
778 				tmpl_set_var(tmpl, "CELL_CONTENT", buf);
779 				tmpl_set_var(tmpl, "CELL_CLASS", "none");
780 				tmpl_set_var(tmpl, "CELL_ALIGN", "right");
781 				tmpl_parse_current_block(tmpl);
782 
783 				tmpl_set_current_block(tmpl, "table_cell");
784 				sprintf(buf, "%d", j);
785 				tmpl_set_var(tmpl, "CELL_CONTENT", buf);
786 				tmpl_set_var(tmpl, "CELL_CLASS", "none");
787 				tmpl_set_var(tmpl, "CELL_ALIGN", "right");
788 				tmpl_parse_current_block(tmpl);
789 
790 				tmpl_set_current_block(tmpl, "table_cell");
791 				sprintf(buf, "%.0f", stamail->qstat[i][j].local_cur / stamail->qstat[i][j].count);
792 				tmpl_set_var(tmpl, "CELL_CONTENT", buf);
793 				tmpl_set_var(tmpl, "CELL_CLASS", "none");
794 				tmpl_set_var(tmpl, "CELL_ALIGN", "right");
795 				tmpl_parse_current_block(tmpl);
796 
797 				tmpl_set_current_block(tmpl, "table_cell");
798 				sprintf(buf, "%.0f", stamail->qstat[i][j].local_max / stamail->qstat[i][j].count);
799 				tmpl_set_var(tmpl, "CELL_CONTENT", buf);
800 				tmpl_set_var(tmpl, "CELL_CLASS", "none");
801 				tmpl_set_var(tmpl, "CELL_ALIGN", "right");
802 				tmpl_parse_current_block(tmpl);
803 
804 				tmpl_set_current_block(tmpl, "table_cell");
805 				sprintf(buf, "%.0f", stamail->qstat[i][j].remote_cur / stamail->qstat[i][j].count);
806 				tmpl_set_var(tmpl, "CELL_CONTENT", buf);
807 				tmpl_set_var(tmpl, "CELL_CLASS", "none");
808 				tmpl_set_var(tmpl, "CELL_ALIGN", "right");
809 				tmpl_parse_current_block(tmpl);
810 
811 				tmpl_set_current_block(tmpl, "table_cell");
812 				sprintf(buf, "%.0f", stamail->qstat[i][j].remote_max / stamail->qstat[i][j].count);
813 				tmpl_set_var(tmpl, "CELL_CONTENT", buf);
814 				tmpl_set_var(tmpl, "CELL_CLASS", "none");
815 				tmpl_set_var(tmpl, "CELL_ALIGN", "right");
816 				tmpl_parse_current_block(tmpl);
817 
818 				tmpl_set_current_block(tmpl, "table_cell");
819 				sprintf(buf, "%.0f", stamail->qstat[i][j].deliver_cur / stamail->qstat[i][j].count);
820 				tmpl_set_var(tmpl, "CELL_CONTENT", buf);
821 				tmpl_set_var(tmpl, "CELL_CLASS", "none");
822 				tmpl_set_var(tmpl, "CELL_ALIGN", "right");
823 				tmpl_parse_current_block(tmpl);
824 
825 				tmpl_set_current_block(tmpl, "table_cell");
826 				sprintf(buf, "%.0f", stamail->qstat[i][j].queue_cur / stamail->qstat[i][j].count);
827 				tmpl_set_var(tmpl, "CELL_CONTENT", buf);
828 				tmpl_set_var(tmpl, "CELL_CLASS", "none");
829 				tmpl_set_var(tmpl, "CELL_ALIGN", "right");
830 				tmpl_parse_current_block(tmpl);
831 
832 				tmpl_set_current_block(tmpl, "table_row");
833 				tmpl_parse_current_block(tmpl);
834 
835 				tmpl_clear_block(tmpl, "table_cell");
836 			}
837 		}
838 	}
839 
840 	sprintf(buf, "%d", 8);
841 	tmpl_set_var(tmpl, "TABLE_TITLE", _("Qmail Queue Pollution"));
842 	tmpl_set_var(tmpl, "TABLE_COL_SPAN", buf);
843 
844 	if (tmpl_replace(tmpl, conf->tmp_buf)) {
845 		tmpl_free(tmpl);
846 
847 		return NULL;
848 	}
849 
850 	tmpl_free(tmpl);
851 
852 	s = strdup(conf->tmp_buf->ptr);
853 
854 	return s;
855 }
856 
857 
858 
register_reports_mail(mconfig * ext_conf,tmpl_reports * r)859 int register_reports_mail (mconfig *ext_conf, tmpl_reports *r) {
860 	int i, j;
861 
862 	reports_def *reports = get_reports_mail(ext_conf);
863 	const char *bla[] = {
864 		M_REPORT_MAIL_DAILY,
865 			M_REPORT_MAIL_HOURLY,
866 			M_REPORT_MAIL_QUEUE_POLLUTION,
867 			NULL };
868 
869 	for (i = 0; i < M_TMPL_MAX_REPORTS && r[i].key != NULL; i++);
870 
871 	if (i != M_TMPL_MAX_REPORTS) {
872 		for (j = 0; reports[j].key && i < M_TMPL_MAX_REPORTS; j++, i++) {
873 			r[i].key = reports[j].key;
874 			r[i].func = generate_mail;
875 			r[i].title = reports[j].title;
876 		}
877 	}
878 
879 	if (i < M_TMPL_MAX_REPORTS) {
880 		r[i].key = bla[0];
881 		r[i].func = generate_mail_hourly;
882 		r[i].title = _("Hourly Statistics");
883 	}
884 
885 	if (++i < M_TMPL_MAX_REPORTS) {
886 		r[i].key = bla[1];
887 		r[i].func = generate_mail_daily;
888 		r[i].title = _("Daily Statistics");
889 	}
890 
891 	if (++i < M_TMPL_MAX_REPORTS) {
892 		r[i].key = bla[2];
893 		r[i].func = generate_mail_qmail_queue;
894 		r[i].title = _("Qmail Queue Stats");
895 	}
896 
897 
898 	return 0;
899 }
900 
generate_mail(mconfig * ext_conf,mstate * state,const char * current,int max)901 char * generate_mail(mconfig * ext_conf, mstate * state, const char *current, int max) {
902 	config_output *conf = ext_conf->plugin_conf;
903 	mstate_mail *stamail = NULL;
904 	int i,j;
905 	int w = 0;
906 	char *s = NULL;
907 	char buf[255];
908 	tmpl_main *tmpl;
909 	reports_def *reports;
910 	char *fn;
911 	mhash *data;
912 
913 	if (state == NULL) {
914 		M_DEBUG0(ext_conf->debug_level, M_DEBUG_SECTION_PARSING, M_DEBUG_LEVEL_ERRORS,
915 			"state = NULL\n");
916 		return NULL;
917 	}
918 
919 	if (state->ext == NULL) {
920 		M_DEBUG3(ext_conf->debug_level, M_DEBUG_SECTION_PARSING, M_DEBUG_LEVEL_ERRORS,
921 			"state->ext = NULL, (%d, %d, %d)\n",
922 			 state->year,
923 			 state->month,
924 			 state->ext_type
925 			 );
926 		return NULL;
927 	}
928 
929 	if (state->ext_type != M_STATE_TYPE_MAIL) {
930 		M_DEBUG0(ext_conf->debug_level, M_DEBUG_SECTION_PARSING, M_DEBUG_LEVEL_ERRORS,
931 			"state extension != web\n");
932 		return NULL;
933 	}
934 
935 	stamail = state->ext;
936 
937 	reports = get_reports_mail(ext_conf);
938 
939 	for (i = 0; reports[i].key; i++) {
940 		if (0 == strcmp(reports[i].key, current))
941 			break;
942 	}
943 
944 	/* unknown report */
945 	if (reports[i].key == NULL) {
946 		M_DEBUG1(ext_conf->debug_level, M_DEBUG_SECTION_PARSING, M_DEBUG_LEVEL_ERRORS,
947 			 "report '%s' no found here\n", current);
948 		return NULL;
949 	}
950 
951 	switch(i) {
952 	case 0: data = stamail->sender; break;
953 	case 1: data = stamail->sender; break;
954 	case 2: data = stamail->receipient; break;
955 	case 3: data = stamail->receipient; break;
956 	case 4: data = stamail->recp_domain; break;
957 	case 5: data = stamail->recp_domain; break;
958 	case 6: data = stamail->send_domain; break;
959 	case 7: data = stamail->send_domain; break;
960 	case 8: data = stamail->virus; break;
961 	case 9: data = stamail->subject; break;
962 	case 10: data = stamail->scanner; break;
963 	default:
964 		M_DEBUG1(ext_conf->debug_level, M_DEBUG_SECTION_PARSING, M_DEBUG_LEVEL_ERRORS,
965 			 "report '%s' no found here - what's up ??\n", current);
966 		return NULL;
967 	}
968 
969 	tmpl = tmpl_init();
970 	assert(tmpl);
971 
972 	if ((fn = generate_template_filename(ext_conf, M_TMPL_TABLE)) == NULL) {
973 		M_DEBUG1(ext_conf->debug_level, M_DEBUG_SECTION_PARSING, M_DEBUG_LEVEL_ERRORS,
974 			 "generating filename failed for '%s'\n", current);
975 		tmpl_free(tmpl);
976 		return NULL;
977 	}
978 
979 	if (tmpl_load_template(tmpl, fn) != 0) {
980 		free(fn);
981 		M_DEBUG1(ext_conf->debug_level, M_DEBUG_SECTION_PARSING, M_DEBUG_LEVEL_ERRORS,
982 			 "parsing template failed for '%s'\n", current);
983 		tmpl_free(tmpl);
984 		return NULL;
985 	}
986 	free(fn);
987 
988 	/* only create the report if we have data */
989 	if (mhash_count(data)) {
990 		if (reports[i].show_graph && reports[i].draw_graph) {
991 			char *ref = reports[i].draw_graph(ext_conf, state);
992 
993 			if (ref && strlen(ref)) {
994 				tmpl_set_var(tmpl, "IMAGE", ref);
995 			}
996 		}
997 
998 		/* calculate the number columns */
999 		for (w = 0; reports[i].fields[w].name != NULL; w++);
1000 		if (reports[i].options & INDEX) w++;
1001 		if (reports[i].options & PERCENT) w++;
1002 		if (reports[i].options & PERCENT && reports[i].options & VISITS) w++;
1003 
1004 		if (reports[i].options & INDEX) {
1005 			tmpl_set_current_block(tmpl, "table_cell");
1006 			tmpl_set_var(tmpl, "CELL_CONTENT", "#");
1007 			tmpl_parse_current_block(tmpl);
1008 		}
1009 
1010 		for (j = 0; reports[i].fields[j].name != NULL; j++) {
1011 			tmpl_set_current_block(tmpl, "table_cell");
1012 
1013 			if (reports[i].fields[j].class) {
1014 				tmpl_set_var(tmpl, "CELL_CONTENT", reports[i].fields[j].name);
1015 				tmpl_set_var(tmpl, "CELL_CLASS", reports[i].fields[j].class);
1016 			} else {
1017 				tmpl_set_var(tmpl, "CELL_CONTENT", reports[i].fields[j].name);
1018 				tmpl_set_var(tmpl, "CELL_CLASS", "none");
1019 			}
1020 			tmpl_parse_current_block(tmpl);
1021 
1022 			if (j == 0 && reports[i].options & PERCENT) {
1023 				tmpl_set_current_block(tmpl, "table_cell");
1024 				tmpl_set_var(tmpl, "CELL_CONTENT", "%");
1025 				tmpl_parse_current_block(tmpl);
1026 			}
1027 			if (j == 1 && reports[i].options & VISITS && reports[i].options & PERCENT) {
1028 				tmpl_set_current_block(tmpl, "table_cell");
1029 				tmpl_set_var(tmpl, "CELL_CONTENT", "%");
1030 				tmpl_parse_current_block(tmpl);
1031 			}
1032 		}
1033 
1034 		tmpl_set_current_block(tmpl, "table_row");
1035 		tmpl_parse_current_block(tmpl);
1036 
1037 		tmpl_clear_block(tmpl, "table_cell");
1038 
1039 #if 0
1040 		fprintf(stderr, "%s.%d: %d (%s - %d)\n", __FILE__, __LINE__, i, reports[i].title, max);
1041 #endif
1042 		if (show_mhash_mail(ext_conf, tmpl, data, max, reports[i].options)) {
1043 			fprintf(stderr, "show mhash web failed for '%s'\n", current);
1044 		}
1045 
1046 		tmpl_clear_var(tmpl, "CELL_ALIGN");
1047 		if (max > BOTTOM_THRESHOLD) {
1048 			if (reports[i].options & INDEX) {
1049 				tmpl_set_current_block(tmpl, "table_cell");
1050 				tmpl_set_var(tmpl, "CELL_CONTENT", "#");
1051 				tmpl_parse_current_block(tmpl);
1052 			}
1053 
1054 			for (j = 0; reports[i].fields[j].name != NULL; j++) {
1055 				tmpl_set_current_block(tmpl, "table_cell");
1056 
1057 				if (reports[i].fields[j].class) {
1058 					tmpl_set_var(tmpl, "CELL_CONTENT", reports[i].fields[j].name);
1059 					tmpl_set_var(tmpl, "CELL_CLASS", reports[i].fields[j].class);
1060 				} else {
1061 					tmpl_set_var(tmpl, "CELL_CONTENT", reports[i].fields[j].name);
1062 					tmpl_set_var(tmpl, "CELL_CLASS", "none");
1063 				}
1064 				tmpl_parse_current_block(tmpl);
1065 
1066 				if (j == 0 && reports[i].options & PERCENT) {
1067 					tmpl_set_current_block(tmpl, "table_cell");
1068 					tmpl_set_var(tmpl, "CELL_CONTENT", "%");
1069 					tmpl_parse_current_block(tmpl);
1070 				}
1071 				if (j == 1 && reports[i].options & VISITS && reports[i].options & PERCENT) {
1072 					tmpl_set_current_block(tmpl, "table_cell");
1073 					tmpl_set_var(tmpl, "CELL_CONTENT", "%");
1074 					tmpl_parse_current_block(tmpl);
1075 				}
1076 			}
1077 
1078 			tmpl_set_current_block(tmpl, "table_row");
1079 			tmpl_parse_current_block(tmpl);
1080 			tmpl_clear_block(tmpl, "table_cell");
1081 		}
1082 	} else {
1083 		/* generate a dummy page if we have no data to process */
1084 		w = 1;
1085 
1086 		tmpl_set_current_block(tmpl, "table_cell");
1087 		tmpl_set_var(tmpl, "CELL_CONTENT", _("Sorry, no data to display"));
1088 		tmpl_parse_current_block(tmpl);
1089 
1090 		tmpl_set_current_block(tmpl, "table_row");
1091 		tmpl_parse_current_block(tmpl);
1092 		tmpl_clear_block(tmpl, "table_cell");
1093 	}
1094 
1095 
1096 	sprintf(buf, "%d", w);
1097 	tmpl_set_var(tmpl, "TABLE_TITLE", reports[i].title);
1098 	tmpl_set_var(tmpl, "TABLE_COL_SPAN", buf);
1099 
1100 	if (tmpl_replace(tmpl, conf->tmp_buf)) {
1101 		s = NULL;
1102 	} else {
1103 		s = strdup(conf->tmp_buf->ptr);
1104 	}
1105 
1106 	tmpl_free(tmpl);
1107 
1108 #ifdef MTIMER_ENABLED
1109 	MTIMER_STOP(timer);
1110 	MTIMER_CALC(timer);
1111 
1112 	fprintf(stderr, "timer %s: %ld msec\n",
1113 		__FUNCTION__, timer.span );
1114 #endif
1115 	return s;
1116 }
1117 
set_line(tmpl_main * tmpl,const char * desc,long incoming_mails,long outgoing_mails,long incoming_bytes,long outgoing_bytes,int days_passed)1118 static int set_line(tmpl_main *tmpl, const char *desc,
1119 	     long incoming_mails,
1120 	     long outgoing_mails,
1121 	     long incoming_bytes,
1122 	     long outgoing_bytes,
1123 	     int days_passed
1124 	     ) {
1125 
1126 	char buf[255];
1127 
1128 	tmpl_set_current_block(tmpl, "row");
1129 
1130 	tmpl_set_var(tmpl, "DESC", desc);
1131 
1132 	sprintf(buf, "%ld", incoming_mails / days_passed);
1133 	tmpl_set_var(tmpl, "AVG_MAILS_OUT", buf);
1134 	sprintf(buf, "%ld", outgoing_mails / days_passed);
1135 	tmpl_set_var(tmpl, "AVG_MAILS_IN", buf);
1136 	tmpl_set_var(tmpl, "AVG_BYTES_OUT",
1137 		     bytes_to_string(incoming_bytes / days_passed));
1138 
1139 	tmpl_set_var(tmpl, "AVG_BYTES_IN",
1140 		     bytes_to_string(outgoing_bytes / days_passed));
1141 
1142 	sprintf(buf, "%ld", incoming_mails);
1143 	tmpl_set_var(tmpl, "TOT_MAILS_OUT", buf);
1144 	sprintf(buf, "%ld", outgoing_mails);
1145 	tmpl_set_var(tmpl, "TOT_MAILS_IN", buf);
1146 	tmpl_set_var(tmpl, "TOT_BYTES_OUT",
1147 		     bytes_to_string(incoming_bytes));
1148 	tmpl_set_var(tmpl, "TOT_BYTES_IN",
1149 		     bytes_to_string(outgoing_bytes));
1150 
1151 	tmpl_parse_current_block(tmpl);
1152 
1153 	return 0;
1154 }
1155 
1156 
mplugins_output_generate_history_output_mail(mconfig * ext_conf,mlist * history,tmpl_main * tmpl)1157 int mplugins_output_generate_history_output_mail(mconfig *ext_conf, mlist *history, tmpl_main *tmpl) {
1158 	mlist *l = history;
1159 	data_History hist, yearly;
1160 	char  *first_report;
1161 	config_output *conf = ext_conf->plugin_conf;
1162 	char buf[255];
1163 
1164 	/* header vars */
1165 
1166 #define HIST(x) \
1167 	hist.data.mail.x = 0;
1168 
1169 	HIST(incoming_mails);
1170 	HIST(outgoing_mails);
1171 	HIST(incoming_bytes);
1172 	HIST(outgoing_bytes);
1173 #undef HIST
1174 	hist.days_passed = 0;
1175 
1176 #define HIST(x) \
1177 	yearly.data.mail.x = 0;
1178 
1179 	HIST(incoming_mails);
1180 	HIST(outgoing_mails);
1181 	HIST(incoming_bytes);
1182 	HIST(outgoing_bytes);
1183 #undef HIST
1184 	yearly.days_passed = 0;
1185 	yearly.year = 0;
1186 
1187 	/* set the correct link */
1188 	if (conf->menu && conf->menu->data && conf->menu->data->key) {
1189 		first_report = conf->menu->data->key;
1190 	} else {
1191 		first_report = conf->reports->data->key;
1192 	}
1193 
1194 	/* go to the last element */
1195 	while (l->next) l = l->next;
1196 
1197 	while (l) {
1198 		mdata *data = l->data;
1199 
1200 		if (!data) break;
1201 
1202 		if (data->data.hist->days_passed != 0) {
1203 			char *lnk;
1204 			if (yearly.year > data->data.hist->year) {
1205 				sprintf(buf, "%04d",
1206 					yearly.year
1207 					);
1208 
1209 				set_line(tmpl,
1210 					 buf,
1211 					 yearly.data.mail.incoming_mails,
1212 					 yearly.data.mail.outgoing_mails,
1213 					 yearly.data.mail.incoming_bytes,
1214 					 yearly.data.mail.outgoing_bytes,
1215 					 yearly.days_passed
1216 					 );
1217 			}
1218 
1219 			lnk = generate_output_link(ext_conf,
1220 						   data->data.hist->year,
1221 						   data->data.hist->month,
1222 						   first_report);
1223 
1224 			sprintf(buf, "<a href=\"%s\">%s&nbsp;%04d</a>",
1225 				lnk,
1226 				get_month_string(data->data.hist->month, 1),
1227 				data->data.hist->year
1228 				);
1229 			free(lnk);
1230 
1231 			set_line(tmpl,
1232 				 buf,
1233 				 data->data.hist->data.mail.incoming_mails,
1234 				 data->data.hist->data.mail.outgoing_mails,
1235 				 data->data.hist->data.mail.incoming_bytes,
1236 				 data->data.hist->data.mail.outgoing_bytes,
1237 				 data->data.hist->days_passed
1238 				 );
1239 
1240 			if (yearly.year > data->data.hist->year) {
1241 				yearly.year = data->data.hist->year;
1242 				yearly.days_passed = data->data.hist->days_passed;
1243 
1244 #define HIST(x) \
1245 	yearly.data.mail.x = data->data.hist->data.mail.x;
1246 				HIST(incoming_mails);
1247 				HIST(outgoing_mails);
1248 				HIST(incoming_bytes);
1249 				HIST(outgoing_bytes);
1250 #undef HIST
1251 
1252 			} else {
1253 #define HIST(x) \
1254 	yearly.data.mail.x += data->data.hist->data.mail.x
1255 				yearly.year = data->data.hist->year;
1256 				yearly.days_passed += data->data.hist->days_passed; /* CHECKME */
1257 
1258 				HIST(incoming_mails);
1259 				HIST(outgoing_mails);
1260 				HIST(incoming_bytes);
1261 				HIST(outgoing_bytes);
1262 #undef HIST
1263 			}
1264 #define HIST(x) \
1265 	hist.data.mail.x += data->data.hist->data.mail.x
1266 
1267 			HIST(incoming_mails);
1268 			HIST(outgoing_mails);
1269 			HIST(incoming_bytes);
1270 			HIST(outgoing_bytes);
1271 
1272 			hist.days_passed += data->data.hist->days_passed;
1273 #undef HIST
1274 		} else {
1275 			M_DEBUG1(ext_conf->debug_level, M_DEBUG_SECTION_OUTPUT, M_DEBUG_LEVEL_WARNINGS,
1276 				 "count == 0, is this ok ?? splitby for '%s' without an entry ??\n",
1277 				 data->key);
1278 		}
1279 		l = l->prev;
1280 	}
1281 
1282 	if (yearly.year && yearly.days_passed) {
1283 		sprintf(buf, "%04d",
1284 			yearly.year
1285 			);
1286 
1287 		set_line(tmpl,
1288 			 buf,
1289 			 yearly.data.mail.incoming_mails,
1290 			 yearly.data.mail.outgoing_mails,
1291 			 yearly.data.mail.incoming_bytes,
1292 			 yearly.data.mail.outgoing_bytes,
1293 			 yearly.days_passed
1294 			 );
1295 	}
1296 
1297 	if (hist.days_passed) {
1298 		set_line(tmpl,
1299 			 _("totals"),
1300 			 hist.data.mail.incoming_mails,
1301 			 hist.data.mail.outgoing_mails,
1302 			 hist.data.mail.incoming_bytes,
1303 			 hist.data.mail.outgoing_bytes,
1304 			 hist.days_passed
1305 			 );
1306 	}
1307 
1308 	return 0;
1309 }
1310