2929# 1.2 support for mod_logio
3030# 1.3 various contributed bugfixes
3131# 1.4 automatically creates two levels of subdirs.
32+ # 1.4p1 implemented anonymization of ipv4 and ipv6
33+ # 1.4p2 implemented anonymization in error log part
34+ # 1.4p3 implemented stronger anonymization
35+ # 1.4p4 implemented re-opening on externally rotated error.log
36+ # 1.4p5 backported old ISPConfig changes (improved DBI error handling, naming)
3237#
3338#
3439# TODO:
@@ -39,7 +44,7 @@ package vlogger;
3944
4045$ENV {PATH } = " /bin:/usr/bin" ;
4146
42- my $VERSION = " 1.3 " ;
47+ my $VERSION = " 1.4p5 " ; # modified for ISPConfig
4348
4449=head1 NAME
4550
@@ -112,6 +117,9 @@ or "%m%d%Y-error.log". When using the -r option, the default becomes
112117-p
113118 Privacy mode (delete last octet of ipv4 or last 4 sections of ipv6)
114119
120+ -P
121+ Extended privacy mode (delete 2 octets ipv4 or 5 sections ipv6)
122+
115123-h
116124 Displays help.
117125
@@ -156,7 +164,7 @@ use File::Basename;
156164
157165# get command line options
158166our %OPTS ;
159- getopts( ' f:t:s:hu:g:aeipvr :d:' , \%OPTS );
167+ getopts( ' f:t:s:hu:g:aeinpPvr :d:' , \%OPTS );
160168
161169# print out version
162170if ( $OPTS {' v' } ) {
@@ -176,9 +184,9 @@ if ( $OPTS{'h'} || !$ARGV[0] ) {
176184# log directory
177185my $LOGDIR ;
178186if ( $ARGV [0] ) {
179- if ( !-d $ARGV [0] ) {
187+ if ( !-d $ARGV [0] || -l $ARGV [0] ) {
180188 print STDERR
181- " [vlogger] target directory $ARGV [0] does not exist - exiting.\n\n " ;
189+ " [vlogger] target directory $ARGV [0] does not exist or is a symlink - exiting.\n\n " ;
182190 exit ;
183191 }
184192 $LOGDIR = $ARGV [0];
@@ -258,9 +266,14 @@ if ( $OPTS{'d'} ) {
258266 }
259267
260268 # test the connection
261- my $dbh = DBI-> connect ( $DBI_DSN , $DBI_USER , $DBI_PASS )
262- or die " DBI Error: $! " ;
263- $dbh -> disconnect;
269+ eval {
270+ my $dbh = DBI-> connect ( $DBI_DSN , $DBI_USER , $DBI_PASS )
271+ or die " DBI Error: $! " ;
272+ $dbh -> disconnect;
273+ };
274+ if ($@ ) {
275+ print " MySQL Connection problem\n " ;
276+ }
264277
265278 # SIGALRM dumps the tracker hash
266279 $SIG {ALRM } = \&dump_tracker;
@@ -317,7 +330,7 @@ if ( $OPTS{'s'} ) {
317330
318331# chroot to the logdir
319332chdir ($LOGDIR );
320- chroot (" ." );
333+ # chroot("."); #we better do not chroot as DBI requires to load a module on the fly -> error!
321334
322335my %logs = ();
323336my %tracker = ();
@@ -367,6 +380,25 @@ if ( $OPTS{'e'} ) {
367380 $LASTWRITE = time ();
368381 }
369382
383+ # my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
384+ # $atime,$mtime,$ctime,$blksize,$blocks)
385+ # = stat(time2str( $TEMPLATE, time() ));
386+ my @fstat = ELOG-> stat ();
387+ my $nlinks = $fstat [3];
388+ if ($nlinks < 1) {
389+ close ELOG;
390+ open ELOG, " >>" . time2str( $TEMPLATE , time () )
391+ or die ( " can't open $LOGDIR /" . time2str( $TEMPLATE , time () ) );
392+ }
393+
394+ if ( $OPTS {' P' } ) {
395+ $log_line =~ s / ^(.*?\[ client\s +\d +\.\d +)\.\d +\.\d +((?::\d +)?\]\s +.*)/ $1 .0.0$2 / g ;
396+ $log_line =~ s / ^(.*?\[ client\s +[a-f0-9]*:[a-f0-9]*:[a-f0-9]*)(?::[a-f0-9]*){2,5}((?::\d +)?\]\s +.*)/ $1 ::0$2 / g ;
397+ } elsif ( $OPTS {' p' } ) {
398+ $log_line =~ s / ^(.*?\[ client\s +\d +\.\d +\.\d +)\.\d +((?::\d +)?\]\s +.*)/ $1 .0$2 / g ;
399+ $log_line =~ s / ^(.*?\[ client\s +[a-f0-9]*:[a-f0-9]*:[a-f0-9]*:[a-f0-9]*)(?::[a-f0-9]*){1,4}((?::\d +)?\]\s +.*)/ $1 ::0$2 / g ;
400+ }
401+
370402 # we dont need to do any other parsing at all, so write the line.
371403 print ELOG $log_line ;
372404 }
@@ -379,10 +411,13 @@ else {
379411 while ( my $log_line = <STDIN > ) {
380412
381413
382- if ( $OPTS {' p' } ) {
383- $log_line =~ s / ^(\S *\s +\d +\.\d +\.\d +)\.\d +(\s +.*)/ $1 .0$2 / ;
384- $log_line =~ s / ^(\S *\s +[a-f0-9]*:[a-f0-9]*:[a-f0-9]*:[a-f0-9]*)(?::[a-f0-9]*){1,4}(\s +.*)/ $1 ::0$2 / ;
385- }
414+ if ( $OPTS {' P' } ) {
415+ $log_line =~ s / ^(\S *\s +\d +\.\d +)\.\d +\.\d +(\s +.*)/ $1 .0.0$2 / g ;
416+ $log_line =~ s / ^(\S *\s +[a-f0-9]*:[a-f0-9]*:[a-f0-9]*)(?::[a-f0-9]*){2,5}(\s +.*)/ $1 ::0$2 / g ;
417+ } elsif ($OPTS {' p' }) {
418+ $log_line =~ s / ^(\S *\s +\d +\.\d +\.\d +)\.\d +(\s +.*)/ $1 .0$2 / g ;
419+ $log_line =~ s / ^(\S *\s +[a-f0-9]*:[a-f0-9]*:[a-f0-9]*:[a-f0-9]*)(?::[a-f0-9]*){1,4}(\s +.*)/ $1 ::0$2 / g ;
420+ }
386421
387422 # parse out the first word (the vhost)
388423 my @this_line = split ( / \s / , $log_line );
@@ -392,6 +427,7 @@ else {
392427 if ( $vhost =~ m #[/\\ ] # ) { $vhost = " default" }
393428 $vhost =~ / (.*)/o ;
394429 $vhost = $1 ;
430+ $vhost = ' default' unless $vhost ;
395431
396432 if ( $OPTS {' i' } ) {
397433 $reqsize = $this_line [1] + $this_line [2];
@@ -439,6 +475,11 @@ else {
439475 make_path($filepath )
440476 or die ( " can't mkdir $filepath " );
441477 }
478+
479+ # Dont log to symlinks
480+ if ( -l " ${vhost} /" .time2str( $TEMPLATE , time () ) ) {
481+ die (" Log target is a symlink: $LOGDIR /${vhost} /" .time2str( $TEMPLATE , time () ));
482+ }
442483
443484 # open the file using the template
444485 open $vhost , " >>" .$filename
@@ -520,32 +561,38 @@ sub open_errorlog {
520561
521562# sub to update the database with the tracker data
522563sub dump_tracker {
564+ eval {
523565 if ( keys (%tracker ) > 0 ) {
524566 my $dbh = DBI-> connect ( $DBI_DSN , $DBI_USER , $DBI_PASS )
525567 or warn " DBI Error: $! " ;
526568 foreach my $key ( keys (%tracker ) ) {
527- my $ts = time2str( " %m%d%Y " , time () );
569+ my $ts = time2str( " %Y - %m - %d " , time () );
528570 my $sth =
529- $dbh -> prepare( " select * from wwwusage where vhost ='" . $key
530- . " ' and ldate ='" . $ts . " '" );
571+ $dbh -> prepare( " select * from web_traffic where hostname ='" . $key
572+ . " ' and traffic_date ='" . $ts . " '" );
531573 $sth -> execute;
532574 if ( $sth -> rows ) {
533575 my $query =
534- " update wwwusage set bytes=bytes +"
576+ " update web_traffic set traffic_bytes=traffic_bytes +"
535577 . $tracker {$key }
536- . " where vhost ='" . $key
537- . " ' and ldate ='" . $ts . " '" ;
578+ . " where hostname ='" . $key
579+ . " ' and traffic_date ='" . $ts . " '" ;
538580 $dbh -> do($query );
539581 }
540582 else {
541- my $query = " insert into wwwusage (vhost, ldate, bytes ) values ('$key ', '$ts ', '$tracker {$key }')" ;
583+ my $query = " insert into web_traffic (hostname, traffic_date, traffic_bytes ) values ('$key ', '$ts ', '$tracker {$key }')" ;
542584 $dbh -> do($query );
543585 }
544586 }
545587 $dbh -> disconnect;
546588 %tracker = ();
547589 }
548590 alarm $DBI_DUMP ;
591+ };
592+
593+ if ($@ ) {
594+ print " Unable to store vlogger data in database\n " ;
595+ }
549596}
550597
551598# print usage info
@@ -565,6 +612,8 @@ sub usage {
565612 print " -d CONFIG use DBI usage tracker (see perldoc vlogger)\n " ;
566613 print " -p Privacy mode (delete last octet of ipv4 or\n " ;
567614 print " last 4 sections of ipv6)\n " ;
615+ print " -P Extended privacy mode (delete 2 octets ipv4\n " ;
616+ print " or last 5 sections of ipv6\n " ;
568617 print " -i extract mod_logio instead of filesize\n " ;
569618 print " -h display this help\n " ;
570619 print " -v output version information\n\n " ;
0 commit comments