yasma.pl 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009
  1. #!/usr/bin/perl
  2. #
  3. # yasma.pl
  4. # (Yet Another Sendmail Log Analyzer)
  5. #
  6. # Copyright (c) 2006 by Peter_Siegrist(SystemLoesungen) (PSS@ZweierNet.ch)
  7. #
  8. # All Rights reserved.
  9. # This program is free software; you can redistribute it and/or
  10. # modify it under the terms of the GNU General Public License as
  11. # published by the Free Software Foundation.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. #
  18. require 5.006_001;
  19. use strict;
  20. use subs qw(lprint);
  21. use locale;
  22. use POSIX qw(locale_h);
  23. use CGI qw(:all); $| = 1; # flush
  24. eval { use Geo::IP::PurePerl; };
  25. use File::Basename;
  26. use IO::Handle;
  27. use Getopt::Std;
  28. use vars qw($opt_f $opt_c $opt_u);
  29. use lib "./lib";
  30. use Parse::Syslog::Mail; # modified version of Parse::Syslog::Mail
  31. my $VERSION = "V0.96";
  32. #--
  33. sub TRUE { 1; }
  34. sub FALSE { 0; }
  35. getopt('fc');
  36. #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>#
  37. my $conf_file = $opt_c || "yasma.conf";
  38. my $geoip_dbase = "";
  39. #- Hide user-part from mailaddresses ?
  40. my $HIDE_USERS = FALSE;
  41. #- print $OUT each message packet. !!long long list!!
  42. my $DEBUG = FALSE;
  43. #- Number of lines to show:
  44. #- of Top Sender Report
  45. my $max_top_snt = 20;
  46. #- of Top Recipients Report
  47. my $max_top_rcv = 20;
  48. #- of Top Senders Size Report
  49. my $max_top_siz = 20;
  50. #- of Top Recipient Size Report
  51. my $max_top_riz = 20;
  52. #- of Top Deferrer Report
  53. my $max_top_def = 25;
  54. #- of Top Rejects Report
  55. my $max_top_rej = 25;
  56. #- of Top Supposed Spammers Report
  57. my $max_top_ssp = 25;
  58. #- of Top Staus Messages
  59. my $max_top_sts = 25;
  60. #- of Top Relay Hosts
  61. my $max_top_rel = 25;
  62. #- of Top Mailer
  63. my $max_top_mlr = 25;
  64. #- of Top Mailer Hosts
  65. my $max_top_hst = 25;
  66. #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>#
  67. my %hash_bas = ();
  68. my %hash_def = ();
  69. my %hash_rej = ();
  70. my %hash_snt = ();
  71. my %hash_rcv = ();
  72. my %hash_ssp = ();
  73. my %hash_sts = ();
  74. my %hash_rel = ();
  75. my %hash_mlr = ();
  76. my %hash_hst = ();
  77. my %top_rsize = ();
  78. my %top_ssize = ();
  79. my %top_sender = ();
  80. my %top_recv = ();
  81. my %hash_present = ();
  82. my $t1 = time();
  83. my $t2 = 0;
  84. my $out_file;
  85. my $msg_total = 0;
  86. my $msg_outbound = 0;
  87. my $msg_inbound = 0;
  88. my $msg_relay = 0;
  89. my $msg_deferred = 0;
  90. my $msg_rejected = 0;
  91. my $msg_size = 0;
  92. my $msg_in_size = 0;
  93. my $msg_out_size = 0;
  94. my $msg_relay_size = 0;
  95. &read_config;
  96. #-- cmd line opts
  97. $out_file = $opt_f if $opt_f;
  98. $HIDE_USERS = TRUE if $opt_u;
  99. #-- output direction
  100. my $OUT = *STDOUT;
  101. $out_file && do { open($OUT, ">$out_file") or die "Cannot open $out_file: $!\n"; select $OUT; $| = 1; };
  102. #-- Read maillog
  103. foreach my $infile ( map { glob($_) } @ARGV ) {
  104. if ( ! -f $infile ) {
  105. print STDERR "File: '$infile' don't exist. Skipping ...\n";
  106. next;
  107. }
  108. my $log_year = "";
  109. print STDERR "Processing $infile\n";
  110. $log_year = substr( $1, 0, 4) if $infile =~ /[_\.\-](\d{8})[_\.\-]/;
  111. if ($infile =~ /(\.Z$|\.gz$)/) {
  112. open( INZ, "zcat $infile |" ) or die "err: INZ: $!\n";
  113. $infile = IO::Handle->new_from_fd( fileno(INZ), "r" ) or die "err-io-handle: $!\n";
  114. }
  115. my $maillog;
  116. if ( $log_year != "" ) {
  117. $maillog = new Parse::Syslog::Mail $infile, allow_future => 1, year=>$log_year or die $!;
  118. } else {
  119. $maillog = new Parse::Syslog::Mail $infile, allow_future => 1 or die $!;
  120. }
  121. while(my $log = $maillog->next) {
  122. if ( $$log{'timestamp'} ) {
  123. $t1 = $$log{'timestamp'} if $$log{'timestamp'} < $t1;
  124. $t2 = $$log{'timestamp'} if $$log{'timestamp'} > $t2;
  125. }
  126. if ( $$log{status} ) {
  127. (exists $$log{host}) && ($hash_hst{$$log{host}}{count} +=1);
  128. (exists $$log{mailer}) && ($hash_mlr{$$log{mailer}}{count} +=1);
  129. (exists $$log{program}) && ($hash_bas{program}{$$log{program}}{count} +=1);
  130. (exists $$log{relay}) && ($hash_rel{$$log{relay}}{count} +=1);
  131. CASE: {
  132. $$log{status} =~ /Deferred\: (.*)/i && do {
  133. my $txt = $1;
  134. $hash_def{$$log{id}}{count} +=1;
  135. $hash_def{$$log{id}}{timestamp} = localtime($$log{timestamp});
  136. $hash_def{$$log{id}}{status} = $txt;
  137. my $to = $$log{to};
  138. $to =~ s/^.+(?=\@)(.*)/$1/ if $HIDE_USERS;
  139. $to =~ s/\<//;
  140. $to =~ s/\>//;
  141. $to =~ s/^\\\\//;
  142. $to = "<>" if $to eq "";
  143. $hash_def{$$log{id}}{to} = lc($to);
  144. my $ctladdr = lc($$log{ctladdr});
  145. $ctladdr =~ s/^.+(?=\@)(.*)/$1/ if $HIDE_USERS;
  146. $ctladdr =~ s/\<//;
  147. $ctladdr =~ s/\>//;
  148. $ctladdr =~ s/^\\\\//;
  149. $ctladdr = "<>" if $ctladdr eq "";
  150. $hash_def{$$log{id}}{ctladdr} = $ctladdr;
  151. $hash_sts{'Deferred'}{count} +=1;
  152. last CASE;
  153. };
  154. $$log{status} =~ /sender notify\: (.*)/i && do {
  155. my $txt = $1;
  156. last CASE if not exists $hash_def{$$log{id}};
  157. my $id = $$log{id};
  158. $hash_def{$id}{notify} = "sender notify:" . $txt;
  159. $hash_sts{'Sender notify'}{count} +=1;
  160. last CASE;
  161. };
  162. $$log{status} =~ /^reject/i && do {
  163. $$log{reject} =~ s/\b[a-z0-9\.\-_\+]+(\@[a-z0-9\.\-_\+]+)\b/$1/gi if $HIDE_USERS;
  164. $hash_rej{$$log{reject}}{count} +=1;
  165. $hash_rej{$$log{reject}}{timestamp} = localtime($$log{timestamp});
  166. $hash_rej{$$log{reject}}{relay} = lc($$log{relay});
  167. if ( exists $$log{reject} ) {
  168. $$log{reject} =~ /(\d{3})\s+(\d\.\d\.\d)\s+(.*)$/;
  169. my $smtprc = $1;
  170. my $dsn = $2;
  171. my $dsn_text = $3;
  172. $dsn_text =~ s/(?:\w*)\s*\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(.*)/$1/g; # dsn
  173. $dsn_text =~ s/\<//g;
  174. $dsn_text =~ s/\>//g;
  175. $dsn_text =~ s/\b[a-z0-9\.\-_\+]+\@[a-z0-9\.\-_\+]+\b//gi;
  176. $dsn_text =~ s/^\s+//; # leading sp
  177. $dsn_text =~ s/\s{2,}/ /; # dbl sp
  178. $dsn_text =~ s/\.{2,}//g; # some n-dots
  179. $dsn_text =~ s/^\s+(.*)/$1/; # leading sp
  180. $dsn_text =~ s/\[\]//g; # empty []
  181. $dsn_text =~ s/(.*\s+)[^A-Za-z0-9]+(\s+.*)/$1$2/; # alles ausser
  182. $dsn_text =~ s/\s{2,}/ /; # dbl sp
  183. #-- suit to std messages
  184. $dsn_text =~ s/.*(Domain name required for sender address).*/$1/;
  185. $dsn_text =~ s/.*(Domain of sender address\s).*(does not resolve).*/$1$2/;
  186. $dsn_text =~ s/.*(Domain of sender address\s).*(does not exist).*/$1$2/;
  187. $dsn_text =~ s/.*(Fix reverse DNS Details.*)/$1/;
  188. #--
  189. if ( exists $$log{arg2} ) {
  190. $$log{arg2} =~ s/\<//;
  191. $$log{arg2} =~ s/\>//;
  192. $$log{arg2} = lc($$log{arg2});
  193. $hash_ssp{$dsn_text}{$$log{arg2}}{count} += 1;
  194. $hash_ssp{$dsn_text}{count} += 1;
  195. $hash_ssp{$dsn_text}{dsn} = $dsn;
  196. } elsif ( exists $$log{arg1} ) {
  197. $$log{arg1} =~ s/\<//;
  198. $$log{arg1} =~ s/\>//;
  199. $$log{arg1} = lc($$log{arg1});
  200. $hash_ssp{$dsn_text}{$$log{arg1}}{count} += 1;
  201. $hash_ssp{$dsn_text}{count} += 1;
  202. $hash_ssp{$dsn_text}{dsn} = $dsn;
  203. }
  204. }
  205. $hash_sts{'Reject'}{count} +=1;
  206. last CASE;
  207. };
  208. $$log{status} =~ /^Sent/i && do {
  209. last CASE if !exists $hash_present{$$log{id}}; # kein from
  210. $hash_snt{$$log{id}}{count} +=1;
  211. $hash_snt{$$log{id}}{timestamp} = localtime($$log{timestamp});
  212. $hash_snt{$$log{id}}{from} = lc($hash_present{$$log{id}}{from});
  213. $hash_snt{$$log{id}}{size} = $hash_present{$$log{id}}{size};
  214. $hash_snt{$$log{id}}{in_size} = $hash_present{$$log{id}}{size} if $$log{mailer} =~ /local/i;
  215. #-- vorab prog-mailer als inbound !!!!!!!!!!
  216. $hash_snt{$$log{id}}{in_size} = $hash_present{$$log{id}}{size} if $$log{mailer} =~ /prog/i;
  217. $hash_snt{$$log{id}}{out_size} = $hash_present{$$log{id}}{size} if $$log{mailer} =~ /esmtp/i;
  218. $hash_snt{$$log{id}}{relay_size} = $hash_present{$$log{id}}{size} if $$log{mailer} =~ /relay/i;;
  219. $hash_snt{$$log{id}}{mailer} = $$log{mailer};
  220. my $to = $$log{to};
  221. $to =~ s/^.+(?=\@)(.*)/$1/ if $HIDE_USERS;
  222. $to =~ s/\<//;
  223. $to =~ s/\>//;
  224. $to =~ s/^\\\\//;
  225. $to = "<>" if $to eq "";
  226. $hash_snt{$$log{id}}{to} = lc($to);
  227. $hash_sts{'Sent'}{count} +=1;
  228. last CASE;
  229. };
  230. #-- Defualt
  231. do {
  232. my $ls = $$log{status};
  233. $ls =~ s/^[A-Za-z_0-9]+\d{4}:\s//;
  234. $ls =~ s/\<//g;
  235. $ls =~ s/\>//g;
  236. my ($status) = $ls; # =~ /^(\w+)+\:.*/;
  237. $status =~ s/\b[a-z0-9\.\-_\+]+(\@[a-z0-9\.\-_\+]+)\b/$1/gi if $HIDE_USERS;
  238. $hash_sts{$status}{count} +=1;
  239. last CASE;
  240. };
  241. }
  242. } else {
  243. next if not exists $$log{from} or $$log{from} eq "";
  244. #next if not exists $$log{daemon} or $$log{daemon} !~ /MTA/i;
  245. my $from = $$log{from};
  246. $from =~ s/^.+(?=\@)(.*)/$1/ if $HIDE_USERS;
  247. $from =~ s/\<//;
  248. $from =~ s/\>//;
  249. $from = "<>" if $from eq "";
  250. $hash_present{$$log{id}}{from} = $from;
  251. if ( $$log{daemon} =~ /MTA/i ) {
  252. $hash_present{$$log{id}}{size} = $$log{size};
  253. }
  254. }
  255. }
  256. close INZ;
  257. }
  258. my $estim_day = "";
  259. my $estim_std = "";
  260. my $estim_min = "";
  261. $estim_day = qq(<span style="font-size:9px;"> &nbsp;&nbsp;&nbsp;(estimated)</span>) if (($t2 - $t1) < 86400);
  262. $estim_std = qq(<span style="font-size:9px;"> &nbsp;&nbsp;&nbsp;(estimated)</span>) if (($t2 - $t1) < 3600 );
  263. $estim_min = qq(<span style="font-size:9px;"> &nbsp;&nbsp;&nbsp;(estimated)</span>) if (($t2 - $t1) < 60 );
  264. my $std_period = round2(($t2 - $t1) / 3600);
  265. my $day_period = round2($std_period / 24);
  266. my ($a1,$a2,$a3,$a4,$a5) = (localtime($t1))[3,4,5,2,1];
  267. my ($e1,$e2,$e3,$e4,$e5) = (localtime($t2))[3,4,5,2,1];
  268. $a3 += 1900;
  269. $e3 += 1900;
  270. $a2 +=1;
  271. $e2 +=1;
  272. foreach my $key ( sort { $hash_def{$b}{count} <=> $hash_def{$a}{count} || $a cmp $b } keys %hash_def) {
  273. $msg_total += $hash_def{$key}{count};
  274. $msg_deferred += $hash_def{$key}{count};
  275. if ( $hash_def{$key}{mailer} =~ /local|esmtp|relay/i ) {
  276. $hash_def{$hash_snt{$key}{from}} +=1;
  277. $hash_def{$hash_snt{$key}{to}} +=1;
  278. }
  279. foreach my $key1 ( keys %{ $hash_def{$key} }) {
  280. lprint "Deferred: $key = $key1: $hash_def{$key}{$key1}\n";
  281. } lprint "-------\n";
  282. }
  283. foreach my $key ( sort { $hash_rej{$b}{count} <=> $hash_rej{$a}{count} || $a cmp $b } keys %hash_rej) {
  284. $msg_total += $hash_rej{$key}{count};
  285. $msg_rejected += $hash_rej{$key}{count};
  286. foreach my $key1 (keys %{ $hash_rej{$key} }) {
  287. lprint "Rejected: $key = $key1: $hash_rej{$key}{$key1}\n";
  288. } lprint "-------\n";
  289. }
  290. foreach my $key ( sort { $hash_snt{$b}{count} <=> $hash_snt{$a}{count} || $a cmp $b } keys %hash_snt) {
  291. $msg_total += $hash_snt{$key}{count};
  292. $msg_size += $hash_snt{$key}{size};
  293. $msg_in_size += $hash_snt{$key}{in_size};
  294. $msg_out_size += $hash_snt{$key}{out_size};
  295. $msg_relay_size += $hash_snt{$key}{relay_size};
  296. $msg_inbound += $hash_snt{$key}{count} if $hash_snt{$key}{mailer} =~ /local/i;
  297. $msg_outbound += $hash_snt{$key}{count} if $hash_snt{$key}{mailer} =~ /esmtp/i;
  298. $msg_relay += $hash_snt{$key}{count} if $hash_snt{$key}{mailer} =~ /relay/i;
  299. if ( $hash_snt{$key}{mailer} =~ /local|esmtp|relay/i ) {
  300. $top_sender{$hash_snt{$key}{from}} +=1;
  301. $top_recv{$hash_snt{$key}{to}} +=1;
  302. $top_rsize{$hash_snt{$key}{to}} += int($hash_snt{$key}{size}/1024);
  303. $top_ssize{$hash_snt{$key}{from}} += int($hash_snt{$key}{size}/1024);
  304. }
  305. foreach my $key1 (keys %{ $hash_snt{$key} }) {
  306. lprint "Sent: $key = $key1: $hash_snt{$key}{$key1}\n";
  307. }lprint "-------\n";
  308. }
  309. $msg_size = int($msg_size/1024);
  310. $msg_in_size = int($msg_in_size/1024);
  311. $msg_out_size = int($msg_out_size/1024);
  312. $msg_relay_size = int($msg_relay_size/1024);
  313. #-- CGI Part -------------------------
  314. #-- Locale Settings
  315. my $LOCALE = "de_DE.ISO8859-1";
  316. setlocale(LC_CTYPE, "$LOCALE");
  317. my $Q = new CGI;
  318. &menu1;
  319. exit;
  320. {
  321. end_script:
  322. print $OUT $Q->end_html;
  323. exit;
  324. }
  325. #-- SUBS
  326. sub lprint {
  327. $DEBUG && print $OUT shift() . "<br>";
  328. }
  329. sub menu1 {
  330. #-- Styles
  331. my $STYLE_1 =<<"EOF_STYLE_1";
  332. A{
  333. color: red;
  334. font-family: Avantgarde, Verdana, Arial;
  335. font-variant: small-caps;
  336. letter-spacing: 0.2em;
  337. font-style: normal;
  338. font-weight: bold;
  339. text-decoration: none;
  340. }
  341. HTML {
  342. font-size: 10px;
  343. color: #F3F0E0;
  344. font-family: Verdana, Arial, Helvetica, sans-serif;
  345. font-style: normal;
  346. font-variant: normal;
  347. text-decoration: none;
  348. background-color: #707070;
  349. }
  350. .hr {
  351. color:#F3F0E0;
  352. background-color:;
  353. border:1px solid #F3F0E0;
  354. height: 0pt;
  355. }
  356. .m0 {
  357. border-width: 1px;
  358. border-style: solid;
  359. border-color: #F3F0E0;
  360. border-spacing: 2px;
  361. empty-cells:hide;
  362. padding: 0px;
  363. white-space:pre;
  364. font: bold 14px Verdana;
  365. color: #F3F0E0;
  366. margin: 0px;
  367. background-color: #808080;
  368. }
  369. .m0 table {
  370. border-width: 1px;
  371. border-style: solid;
  372. border-color: #F3F0E0;
  373. border-spacing: 1px;
  374. empty-cells:hide;
  375. padding: 0px;
  376. white-space:pre;
  377. font: bold 14px Verdana;
  378. color: #F3F0E0;
  379. margin: 0px;
  380. background-color: #808080;
  381. }
  382. .m0 td {
  383. border-width: 0px;
  384. border-style: solid;
  385. border-color: #F3F0E0;
  386. border-spacing: 0px;
  387. padding: 3px;
  388. white-space:pre;
  389. font: bold 14px Verdana;
  390. color: #F3F0E0;
  391. margin: 0px;
  392. background-color: #404040;
  393. }
  394. .m0 th {
  395. border-spacing: 1px;
  396. font: normal 16px Avantgarde, Verdana, Arial;
  397. font-variant:small-caps;
  398. letter-spacing:0.2em;
  399. padding: 5px;
  400. white-space:pre;
  401. color: #F3F0E0;
  402. margin: 0px;
  403. background-color: #808080;
  404. }
  405. .m0 tr {
  406. border: 0px;
  407. margin: 0px;
  408. padding: 0px;
  409. background-color: #808080;
  410. }
  411. .m1 {
  412. border-width: 1px;
  413. border-style: solid;
  414. border-color: #F3F0E0;
  415. border-spacing: 2px;
  416. empty-cells:hide;
  417. padding: 1px;
  418. white-space:pre;
  419. font: bold 12px Verdana;
  420. color: #F3F0E0;
  421. margin: 0px;
  422. background-color: #808080;
  423. }
  424. .m1 table {
  425. border-width: 1px;
  426. border-style: solid;
  427. border-color: #F3F0E0;
  428. border-spacing: 1px;
  429. empty-cells:hide;
  430. padding: 1px;
  431. white-space:pre;
  432. font: bold 12px Verdana;
  433. color: #F3F0E0;
  434. margin: 0px;
  435. background-color: #808080;
  436. }
  437. .m1 td {
  438. border-width: 0px;
  439. border-style: solid;
  440. border-color: #F3F0E0;
  441. border-spacing: 0px;
  442. padding: 3px;
  443. white-space:pre;
  444. font: bold 12px Verdana;
  445. color: #F3F0E0;
  446. margin: 0px;
  447. background-color: #404040;
  448. }
  449. .m1 th {
  450. border-spacing: 1px;
  451. padding: 5px;
  452. white-space:pre;
  453. font: normal 16px Avantgarde, Verdana, Arial;
  454. font-variant:small-caps;
  455. letter-spacing:0.2em;
  456. color: #F3F0E0;
  457. margin: 0px;
  458. background-color: #808080;
  459. }
  460. .m1 tr {
  461. border: 0px;
  462. margin: 0px;
  463. padding: 0px;
  464. background-color: #808080;
  465. }
  466. .trline {
  467. border: 0px;
  468. margin: 0px;
  469. padding: 0px;
  470. background-color: #808080;
  471. height: 2px;
  472. font-size: 2px;
  473. }
  474. #graph1 {
  475. background-color: #404040;
  476. height: 100%;
  477. border: 0px;
  478. table-layout:auto;
  479. padding: 0px;
  480. margin: 3px;
  481. border-collapse:collapse;
  482. vertical-align:middle;
  483. }
  484. #graph1 tr {
  485. background-color: #404040;
  486. height: 50px;
  487. border: 0px;
  488. padding: 0px;
  489. }
  490. #graph1 td {
  491. border: 0px;
  492. margin: px;
  493. padding: 0px;
  494. text-align: left;
  495. }
  496. #graph1 .go {
  497. border-width: 1px 1px 0px 1px;
  498. border-style: solid;
  499. border-color: black;
  500. padding: 2px;
  501. padding-left: 0px;
  502. }
  503. #graph1 .gm {
  504. border-width: 0px 1px 0px 1px;
  505. border-style: solid;
  506. border-color: black;
  507. padding: 2px;
  508. padding-left: 0px;
  509. }
  510. #graph1 .gu {
  511. border-width: 0px 1px 1px 1px;
  512. border-style: solid;
  513. border-color: black;
  514. padding: 2px;
  515. padding-left: 0px;
  516. }
  517. div.pc {
  518. border: 0px;
  519. width: 100%;
  520. margin: 0px;
  521. padding: 0px;
  522. float: left;
  523. background: transparent;
  524. vertical-align: middle;
  525. }
  526. div.pc > div {
  527. background-color: red;
  528. height: 20px;
  529. vertical-align: middle;
  530. text-align: right;
  531. border-width: 1px 1px 1px 1px;
  532. border-style: solid;
  533. border-color: black;
  534. }
  535. EOF_STYLE_1
  536. my $p_title = "Yasma - Sendmail Logfile Analyzer";
  537. #print $OUT $Q->header( -type => 'text/html' );
  538. print $OUT $Q->start_html( -title => "$p_title",
  539. -head => [ meta( { -http_equiv => 'Content-Type',
  540. -content => 'text/html; charset=iso-8859-1'}),
  541. meta( { -http_equiv => 'content-language',
  542. -content => 'de'}) ],
  543. -author => "sigi-at-ZweierNet-dot-ch",
  544. -style => {-code => "$STYLE_1"} );
  545. print $OUT qq(<p><br><font style="font-family: Avantgarde, Verdana, Arial; font-size: 380%;font-variant:small-caps;font-weight:500;letter-spacing:0.2em;">Yasma - </font><font style="font-family: Avantgarde, Verdana, Arial; font-size: 220%;font-variant:small-caps;letter-spacing:0.2em;"> Yet Another Sendmail Logfile Analyzer</font><b>);
  546. print $OUT qq(<p style="text-align:right;font-family: Avantgarde, Verdana, Arial; font-size: 100%;font-variant:small-caps;letter-spacing:0.3em;font-weight:500;"> Free <a href="http://pss.zweiernet.ch/index.html?f_down.html">Yasma</a> $VERSION Designed by <a href="http://PSS.ZweierNet.ch">PSS</a></p>);
  547. print $OUT qq(<br><p style="font-family: Verdana, Arial; font-size: 150%;font-variant:small-caps;letter-spacing:0.1em;">Report Generated at );
  548. print $OUT scalar localtime();
  549. print $OUT qq(</p><p><br><p>);
  550. &print_totals;
  551. &print_avg;
  552. &print_tops;
  553. print $OUT qq(<p><br><p style="text-align:right;font-family: Avantgarde, Verdana, Arial; font-size: 100%;font-variant:small-caps;letter-spacing:0.3em;font-weight:500;"> Free <a href="http://pss.zweiernet.ch/index.html?f_down.html">Yasma</a> $VERSION Designed by <a href="http://PSS.ZweierNet.ch">PSS</a></p><br>);
  554. goto end_script;
  555. }
  556. sub print_totals {
  557. print $OUT qq(<table class="m1" width=90%>);
  558. print $OUT qq(<tr><th colspan=3>Overview of Period <b>);
  559. printf("%d.%d.%d %02d:%02d - %d.%d.%d %02d:%02d", $a1,$a2,$a3,$a4,$a5, $e1,$e2,$e3,$e4,$e5);
  560. $std_period > 24 ? print $OUT qq!</b> ($day_period days)</th></tr>!
  561. : print $OUT qq!</b> ($std_period hours)</th></tr>!;
  562. print $OUT qq(<tr><td style="border-bottom-width:2px;border-bottom-color: #808080;">Overall Processed Messages</td><td style="border-bottom-width:2px;border-bottom-color: #808080;">$msg_total</td><td width=30% rowspan=12 align=right>);
  563. &make_chart;
  564. print $OUT qq(</td></tr>);
  565. print $OUT qq(<tr><td>Total Delivered Messages</td><td>);
  566. print $OUT $msg_outbound + $msg_inbound;
  567. print $OUT qq(</td></tr>);
  568. print $OUT qq(<tr><td>&nbsp;&nbsp;&nbsp;&nbsp; Outbound</td><td>$msg_outbound</td></tr>);
  569. print $OUT qq(<tr><td>&nbsp;&nbsp;&nbsp;&nbsp; Inbound</td><td>$msg_inbound</td></tr>);
  570. print $OUT qq(<tr><td style="border-bottom-width:2px;border-bottom-color: #808080;">&nbsp;&nbsp;&nbsp;&nbsp; Relay (of it)</td><td style="border-bottom-width:2px;border-bottom-color: #808080;">$msg_relay</td></tr>);
  571. print $OUT qq(<tr><td>Total Waste Messages</td><td>);
  572. print $OUT ($msg_rejected + $msg_deferred);
  573. print $OUT qq(</td></tr>);
  574. print $OUT qq(<tr><td>&nbsp;&nbsp;&nbsp;&nbsp; Deferred Messages</td><td>$msg_deferred</td></tr>);
  575. print $OUT qq(<tr><td style="border-bottom-width:2px;border-bottom-color: #808080;">&nbsp;&nbsp;&nbsp;&nbsp; Rejected Messages</td><td style="border-bottom-width:2px;border-bottom-color: #808080;">$msg_rejected</td></tr>);
  576. print $OUT qq(<tr><td style="border-bottom-width:2px;border-bottom-color: #808080;">Ratio Delivered : Waste Messages<div class="font-size:100%;"></td><td style="border-bottom-width:2px;border-bottom-color: #808080;">);
  577. print $OUT round(eval { (($msg_outbound + $msg_inbound) * 100) / $msg_total } or 0);
  578. print $OUT qq( % : );
  579. print $OUT round(eval { (($msg_rejected + $msg_deferred) * 100) / $msg_total } or 0);
  580. print $OUT qq( %</td></tr>);
  581. print $OUT qq(<tr><td>Total Size of Delivered Messages</td><td>);
  582. print $OUT fmt_kb($msg_size);
  583. print $OUT qq( Kb</td></tr>);
  584. print $OUT qq(<tr><td>&nbsp;&nbsp;&nbsp;&nbsp; Outbound</td><td>);
  585. print $OUT fmt_kb($msg_out_size);
  586. print $OUT qq( Kb</td></tr>);
  587. print $OUT qq(<tr><td>&nbsp;&nbsp;&nbsp;&nbsp; Inbound</td><td>);
  588. print $OUT fmt_kb($msg_in_size);
  589. print $OUT qq( Kb</td></tr>);
  590. print $OUT qq(</table>);
  591. }
  592. sub print_tops {
  593. print $OUT qq(<p><br><p><br>);
  594. print $OUT qq(<table class="m1" width=60%>);
  595. print $OUT qq(<tr><th colspan=2>Top Envelope Sender</th></tr>);
  596. foreach my $adr( sort { $top_sender{$b} <=> $top_sender{$a} || $a cmp $b } keys %top_sender ) {
  597. print $OUT qq(<tr><td>$top_sender{$adr}</td><td width=85%>$adr</td></tr>);
  598. last if $max_top_snt-- == 1;
  599. }
  600. print $OUT qq(</table>);
  601. print $OUT qq(<p><br><p>);
  602. print $OUT qq(<table class="m1" width=60%>);
  603. print $OUT qq(<tr><th colspan=2>Top Envelope Recipients</th></tr>);
  604. foreach my $adr( sort { $top_recv{$b} <=> $top_recv{$a} || $a cmp $b } keys %top_recv ) {
  605. print $OUT qq(<tr><td>$top_recv{$adr}</td><td width=85%>$adr</td></tr>);
  606. last if $max_top_rcv-- == 1;
  607. }
  608. print $OUT qq(</table>);
  609. print $OUT qq(<p><br><p>);
  610. print $OUT qq(<table class="m1" width=60%>);
  611. print $OUT qq(<tr><th colspan=2>Top Senders Message Size (in Kbyte)</th></tr>);
  612. foreach my $adr( sort { $top_ssize{$b} <=> $top_ssize{$a} || $a cmp $b } keys %top_ssize ) {
  613. print $OUT qq(<tr><td>);
  614. print $OUT fmt_kb($top_ssize{$adr});
  615. print $OUT qq(</td><td width=85%>$adr</td></tr>);
  616. last if $max_top_siz-- == 1;
  617. }
  618. print $OUT qq(</table>);
  619. print $OUT qq(<p><br><p><br>);
  620. print $OUT qq(<table class="m1" width=60%>);
  621. print $OUT qq(<tr><th colspan=2>Top Recipients Message Size (in Kbyte)</th></tr>);
  622. foreach my $adr( sort { $top_rsize{$b} <=> $top_rsize{$a} || $a cmp $b } keys %top_rsize ) {
  623. print $OUT qq(<tr><td>);
  624. print $OUT fmt_kb($top_rsize{$adr});
  625. print $OUT qq(</td><td width=85%>$adr</td></tr>);
  626. last if $max_top_riz-- == 1;
  627. }
  628. print $OUT qq(</table>);
  629. print $OUT qq(<p><br><p><br>);
  630. print $OUT qq(<table class="m1" width=80%>);
  631. print $OUT qq(<tr><th colspan=2>Top Deferrer</th></tr>);
  632. foreach my $key ( sort { $hash_def{$b}{count} <=> $hash_def{$a}{count} || $a cmp $b } keys %hash_def) {
  633. if ( exists $hash_def{$key}{notify} ) {
  634. print $OUT qq(<tr><td>$hash_def{$key}{count}<br> <br> </td><td width=85%>$hash_def{$key}{ctladdr}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;To: $hash_def{$key}{to}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Reason: $hash_def{$key}{status}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;==> Solved with: $hash_def{$key}{notify}</td></tr>);
  635. } else {
  636. print $OUT qq(<tr><td>$hash_def{$key}{count}<br> <br> </td><td width=85%>$hash_def{$key}{ctladdr}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;To: $hash_def{$key}{to}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Reason: $hash_def{$key}{status}</td></tr>);
  637. }
  638. last if $max_top_def-- == 1;
  639. }
  640. print $OUT qq(</table>);
  641. print $OUT qq(<p><br><p>);
  642. print $OUT qq(<table class="m1" width=80%>);
  643. print $OUT qq(<tr><th colspan=2>Top Rejects</th></tr>);
  644. foreach my $key ( sort { $hash_rej{$b}{count} <=> $hash_rej{$a}{count} || $a cmp $b } keys %hash_rej) {
  645. print $OUT qq(<tr><td width=15%>$hash_rej{$key}{count}<br> </td><td>$key<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Relay: $hash_rej{$key}{relay}</td></tr>);
  646. last if $max_top_rej-- == 1;
  647. }
  648. print $OUT qq(</table>);
  649. my $GI;
  650. $geoip_dbase && ( $GI = Geo::IP::PurePerl->open($geoip_dbase) );
  651. print $OUT qq(<p><br><p>);
  652. print $OUT qq(<table class="m1" width=80%>);
  653. print $OUT qq(<tr><th colspan=4>Top DSN Messages and Supposed Spammers/Abused Addresses</th></tr>);
  654. my $stmp = $max_top_ssp;
  655. foreach my $key1 ( sort { $hash_ssp{$b}{count} <=> $hash_ssp{$a}{count} || $a cmp $b } keys %hash_ssp ) {
  656. my $scnt = $stmp;
  657. my $fk = "($hash_ssp{$key1}{dsn}) $key1";
  658. my $fkc = $hash_ssp{$key1}{count};
  659. my %tmph = ();
  660. foreach my $x ( keys %{ $hash_ssp{$key1} } ) {
  661. next if $x eq "count" or $x eq "dsn";
  662. $tmph{$x} = "$hash_ssp{$key1}{$x}{count}";
  663. }
  664. foreach my $key ( sort { $tmph{$b} <=> $tmph{$a} || $a cmp $b } keys %tmph ) {
  665. my $land = "";
  666. if ($key =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/ ) { $geoip_dbase && ($land = $GI->country_code_by_addr($key)); }
  667. my $keyl = $key;
  668. if ($keyl =~ s/.+\@(.*)/$1/ ) { $geoip_dbase && ($land = $GI->country_code_by_name($keyl)); }
  669. my $keyu = $key;
  670. $keyu =~ s/\b[a-z0-9\.\-_\+]+(\@[a-z0-9\.\-_\+]+)\b/$1/gi if $HIDE_USERS;
  671. print $OUT qq(<tr><td>$fkc</td><td width=30%>$fk</td><td align=left>$tmph{$key} </td><td>$keyu &nbsp;&nbsp; );
  672. $geoip_dbase && (print $OUT qq([$land]));
  673. print $OUT qq(</td></tr>);
  674. $fk = " ";
  675. $fkc = " ";
  676. last if $scnt-- == 1;
  677. }
  678. last if $max_top_ssp-- == 1;
  679. }
  680. print $OUT qq(</table>);
  681. print $OUT qq(<p><br><p>);
  682. print $OUT qq(<table class="m1" width=60%>);
  683. print $OUT qq(<tr><th colspan=2>Top Status Messages</th></tr>);
  684. foreach my $key( sort { $hash_sts{$b}{count} <=> $hash_sts{$a}{count} || $a cmp $b } keys %hash_sts ) {
  685. print $OUT qq(<tr><td>$hash_sts{$key}{count}</td><td width=85%>$key</td></tr>);
  686. last if $max_top_sts-- == 1;
  687. }
  688. print $OUT qq(</table>);
  689. print $OUT qq(<p><br><p>);
  690. print $OUT qq(<table class="m1" width=60%>);
  691. print $OUT qq(<tr><th colspan=2>Top Relay Hosts</th></tr>);
  692. foreach my $key( sort { $hash_rel{$b}{count} <=> $hash_rel{$a}{count} || $a cmp $b } keys %hash_rel ) {
  693. print $OUT qq(<tr><td>$hash_rel{$key}{count}</td><td width=85%>$key</td></tr>);
  694. last if $max_top_rel-- == 1;
  695. }
  696. print $OUT qq(</table>);
  697. print $OUT qq(<p><br><p>);
  698. print $OUT qq(<table class="m1" width=60%>);
  699. print $OUT qq(<tr><th colspan=2>Top Mailer</th></tr>);
  700. foreach my $key( sort { $hash_mlr{$b}{count} <=> $hash_mlr{$a}{count} || $a cmp $b } keys %hash_mlr ) {
  701. print $OUT qq(<tr><td>$hash_mlr{$key}{count}</td><td width=85%>$key</td></tr>);
  702. last if $max_top_mlr-- == 1;
  703. }
  704. print $OUT qq(</table>);
  705. print $OUT qq(<p><br><p>);
  706. print $OUT qq(<table class="m1" width=60%>);
  707. print $OUT qq(<tr><th colspan=2>Top Mailer Hosts Processed</th></tr>);
  708. foreach my $key( sort { $hash_hst{$b}{count} <=> $hash_hst{$a}{count} || $a cmp $b } keys %hash_hst ) {
  709. print $OUT qq(<tr><td>$hash_hst{$key}{count}</td><td width=85%>$key</td></tr>);
  710. last if $max_top_hst-- == 1;
  711. }
  712. print $OUT qq(</table>);
  713. }
  714. sub print_avg {
  715. print $OUT qq(<p><br><p>);
  716. print $OUT qq(<table class="m1" width=90%>);
  717. print $OUT qq(<tr><th colspan=4>Averages of Period <b>);
  718. printf("%d.%d.%d %02d:%02d - %d.%d.%d %02d:%02d", $a1,$a2,$a3,$a4,$a5, $e1,$e2,$e3,$e4,$e5);
  719. $std_period > 24 ? print $OUT qq!</b> ($day_period days)</th></tr>!
  720. : print $OUT qq!</b> ($std_period hours)</th></tr>!;
  721. print $OUT qq(<tr><td>Overall Processed/Day $estim_day</td><td style="border-right-width:2px;border-right-color: #808080;">);
  722. print $OUT round2(eval { $msg_total / ($std_period / 24) } or 0 );
  723. print $OUT qq(</td>);
  724. print $OUT qq(<td>Total Delivered/Day $estim_day</td><td>);
  725. print $OUT round2(eval {($msg_outbound + $msg_inbound) / ($std_period / 24) } or 0);
  726. print $OUT qq(</td></tr>);
  727. print $OUT qq(<tr><td>Overall Processed/Hour $estim_std</td><td style="border-right-width:2px;border-right-color: #808080;">);
  728. print $OUT round2(eval { $msg_total / $std_period } or 0);
  729. print $OUT qq(</td>);
  730. print $OUT qq(<td>Total Delivered/Hour $estim_std</td><td>);
  731. print $OUT round2(eval {($msg_outbound + $msg_inbound) / $std_period } or 0);
  732. print $OUT qq(</td></tr>);
  733. print $OUT qq(<tr><td style="border-bottom-width:2px;border-bottom-color: #808080;">Overall Processed/Min $estim_min</td><td style="border-bottom-width:2px;border-bottom-color: #808080;border-right-width:2px;border-right-color: #808080;">);
  734. print $OUT round2(eval { $msg_total / ($std_period * 60) } or 0 );
  735. print $OUT qq(</td>);
  736. print $OUT qq(<td style="border-bottom-width:2px;border-bottom-color: #808080;">Total Delivered/Min $estim_min</td><td style="border-bottom-width:2px;border-bottom-color: #808080;">);
  737. print $OUT round2(eval {($msg_outbound + $msg_inbound) / ($std_period * 60) } or 0);
  738. print $OUT qq(</td></tr>);
  739. print $OUT qq(<tr><td>Inbound Delivered/Day $estim_day</td><td style="border-right-width:2px;border-right-color: #808080;">);
  740. print $OUT round2(eval {$msg_inbound / ($std_period /24) } or 0 );
  741. print $OUT qq(</td>);
  742. print $OUT qq(<td>Outbound Delivered/Day $estim_day</td><td>);
  743. print $OUT round2(eval {$msg_outbound / ($std_period /24) } or 0);
  744. print $OUT qq(</td></tr>);
  745. print $OUT qq(<tr><td>Inbound Delivered/Hour $estim_std</td><td style="border-right-width:2px;border-right-color: #808080;">);
  746. print $OUT round2(eval {$msg_inbound / $std_period } or 0 );
  747. print $OUT qq(</td>);
  748. print $OUT qq(<td>Outbound Delivered/Hour $estim_std</td><td>);
  749. print $OUT round2(eval {$msg_outbound / $std_period } or 0);
  750. print $OUT qq(</td></tr>);
  751. print $OUT qq(<tr><td style="border-bottom-width:2px;border-bottom-color: #808080;">Inbound Delivered/Min $estim_min</td><td style="border-bottom-width:2px;border-bottom-color: #808080;border-right-width:2px;border-right-color: #808080;">);
  752. print $OUT round2(eval {$msg_inbound / ($std_period * 60) } or 0 );
  753. print $OUT qq(</td>);
  754. print $OUT qq(<td style="border-bottom-width:2px;border-bottom-color: #808080;">Outbound Delivered/Min $estim_min</td><td style="border-bottom-width:2px;border-bottom-color: #808080;">);
  755. print $OUT round2(eval {$msg_outbound / ($std_period * 60) } or 0);
  756. print $OUT qq(</td></tr>);
  757. print $OUT qq(<tr><td>Rejected Messages/Day $estim_day</td><td style="border-right-width:2px;border-right-color: #808080;">);
  758. print $OUT round2(eval {$msg_rejected / ($std_period /24) } or 0 );
  759. print $OUT qq(</td>);
  760. print $OUT qq(<td>Deferred Messages/Day $estim_day</td><td>);
  761. print $OUT round2(eval {$msg_deferred / ($std_period /24) } or 0);
  762. print $OUT qq(</td></tr>);
  763. print $OUT qq(<tr><td>Rejected Messages/Hour $estim_std</td><td style="border-right-width:2px;border-right-color: #808080;">);
  764. print $OUT round2(eval {$msg_rejected / $std_period } or 0);
  765. print $OUT qq(</td>);
  766. print $OUT qq(<td>Deferred Messages/Hour $estim_std</td><td>);
  767. print $OUT round2(eval {$msg_deferred / $std_period } or 0);
  768. print $OUT qq(</td></tr>);
  769. print $OUT qq(<tr><td style="border-bottom-width:2px;border-bottom-color: #808080;">Rejected Messages/Min $estim_min</td><td style="border-bottom-width:2px;border-bottom-color: #808080;border-right-width:2px;border-right-color: #808080;">);
  770. print $OUT round2(eval {$msg_rejected / ($std_period * 60) } or 0 );
  771. print $OUT qq(</td>);
  772. print $OUT qq(<td style="border-bottom-width:2px;border-bottom-color: #808080;">Deferred Messages/Min $estim_min</td><td style="border-bottom-width:2px;border-bottom-color: #808080;">);
  773. print $OUT round2(eval {$msg_deferred / ($std_period * 60) } or 0);
  774. print $OUT qq(</td></tr>);
  775. print $OUT qq(<tr><td>Average Size of Delivered Messages</td><td style="border-right-width:2px;border-right-color: #808080;">);
  776. print $OUT fmt_kb(round(eval {$msg_size / ($msg_outbound + $msg_inbound) } or 0));
  777. print $OUT qq( Kb</td>);
  778. print $OUT qq(<td> </td><td>);
  779. #print $OUT round2($msg_deferred / ($std_period /24));
  780. print $OUT qq( </td></tr>);
  781. print $OUT qq(<tr><td>Average Size of Inbound Messages</td><td style="border-right-width:2px;border-right-color: #808080;">);
  782. print $OUT fmt_kb(round(eval {$msg_in_size / $msg_inbound } or 0));
  783. print $OUT qq( Kb</td>);
  784. print $OUT qq(<td>Average Size of Outbound Messages</td><td>);
  785. print $OUT fmt_kb(round(eval {$msg_out_size / $msg_outbound } or 0));
  786. print $OUT qq( Kb</td></tr>);
  787. print $OUT qq(</table>);
  788. }
  789. sub make_chart {
  790. # 400x250
  791. my $max = 0;
  792. $msg_deferred > $max && ($max = $msg_deferred);
  793. $msg_rejected > $max && ($max = $msg_rejected);
  794. $msg_inbound > $max && ($max = $msg_inbound);
  795. $msg_outbound > $max && ($max = $msg_outbound);
  796. my $wde = round(eval { ($msg_deferred * 100) / $max } or 0);
  797. my $wre = round(eval { ($msg_rejected * 100) / $max } or 0);
  798. my $wib = round(eval { ($msg_inbound * 100) / $max } or 0);
  799. my $wob = round(eval { ($msg_outbound * 100) / $max } or 0);
  800. print $OUT <<"EOFHTML";
  801. <table id="graph1" border=0 width="400" height="250" cellspacing="0" cellpadding="0">
  802. <tr>
  803. <td width="60px">Deferred </td>
  804. <td class="go"><div class="pc" style="width: 100%"><div style="width: ${wde}%"> $msg_deferred </div></div></td>
  805. </tr>
  806. <tr>
  807. <td width="60px">Rejected </td>
  808. <td class="gm"><div class="pc" style="width: 100%"><div style="width: ${wre}%"> $msg_rejected </div></div></td>
  809. </tr>
  810. <tr>
  811. <td width="60px">Inbound </td>
  812. <td class="gm"><div class="pc" style="width: 100%"><div style="width: ${wib}%"> $msg_inbound </div></div></td>
  813. </tr>
  814. <tr>
  815. <td width="60px">Outbound </td>
  816. <td class="gu"><div class="pc" style="width: 100%"><div style="width: ${wob}%"> $msg_outbound </div></div></td>
  817. </tr>
  818. </table>
  819. EOFHTML
  820. return;
  821. }
  822. sub round {
  823. return int( shift() + .5);
  824. }
  825. sub round2 {
  826. return int( shift() * 100 + .5) / 100;
  827. }
  828. sub fmt_kb {
  829. my $x = shift;
  830. $x =~ s/(\d{1,3})(?=(\d{3})+$)/$1'/g;
  831. return $x;
  832. }
  833. sub read_config {
  834. open( CONF, "$conf_file" ) or die "Configfile '$conf_file' Error: $!\n";
  835. while ( my $line = <CONF> ) {
  836. next if $line =~ /^(#|\s+)/;
  837. CS: {
  838. $line =~ /^HIDE_USERS\s*=\s*(.*)/i && do {
  839. $HIDE_USERS = TRUE if $1 =~ m/true/i;
  840. last CS;
  841. };
  842. $line =~ /^DEBUG\s*=\s*(.*)/i && do {
  843. $DEBUG = TRUE if $1 =~ m/true/i;
  844. last CS;
  845. };
  846. $line =~ /^out_file\s*=\s*(.*)/i && do {
  847. $out_file = $1 if $1;
  848. last CS;
  849. };
  850. $line =~ /^geoip_dbase\s*=\s*(.*)/i && do {
  851. $geoip_dbase = $1 if $1;
  852. last CS;
  853. };
  854. $line =~ /^max_top_snt\s*=\s*(.*)/i && do {
  855. $max_top_snt = $1;
  856. last CS;
  857. };
  858. $line =~ /^max_top_rcv\s*=\s*(.*)/i && do {
  859. $max_top_rcv = $1;
  860. last CS;
  861. };
  862. $line =~ /^max_top_siz\s*=\s*(.*)/i && do {
  863. $max_top_siz = $1;
  864. last CS;
  865. };
  866. $line =~ /^max_top_riz\s*=\s*(.*)/i && do {
  867. $max_top_riz = $1;
  868. last CS;
  869. };
  870. $line =~ /^max_top_def\s*=\s*(.*)/i && do {
  871. $max_top_def = $1;
  872. last CS;
  873. };
  874. $line =~ /^max_top_rej\s*=\s*(.*)/i && do {
  875. $max_top_rej = $1;
  876. last CS;
  877. };
  878. $line =~ /^max_top_ssp\s*=\s*(.*)/i && do {
  879. $max_top_ssp = $1;
  880. last CS;
  881. };
  882. $line =~ /^max_top_sts\s*=\s*(.*)/i && do {
  883. $max_top_sts = $1;
  884. last CS;
  885. };
  886. $line =~ /^max_top_rel\s*=\s*(.*)/i && do {
  887. $max_top_rel = $1;
  888. last CS;
  889. };
  890. $line =~ /^max_top_mlr\s*=\s*(.*)/i && do {
  891. $max_top_mlr = $1;
  892. last CS;
  893. };
  894. $line =~ /^max_top_hst\s*=\s*(.*)/i && do {
  895. $max_top_hst = $1;
  896. last CS;
  897. };
  898. }
  899. }
  900. close CONF;
  901. }