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)
3237#
3338#
3439# TODO:
@@ -39,7 +44,9 @@ package vlogger;
3944
4045$ENV {PATH } = " /bin:/usr/bin" ;
4146
42- my $VERSION = " 1.3" ;
47+ my $VERSION = " 1.4p5" ; # modified for ISPConfig
48+
49+ use Data::Dumper;
4350
4451=head1 NAME
4552
@@ -112,6 +119,9 @@ or "%m%d%Y-error.log". When using the -r option, the default becomes
112119-p
113120 Privacy mode (delete last octet of ipv4 or last 4 sections of ipv6)
114121
122+ -P
123+ Extended privacy mode (delete 2 octets ipv4 or 5 sections ipv6)
124+
115125-h
116126 Displays help.
117127
@@ -156,7 +166,7 @@ use File::Basename;
156166
157167# get command line options
158168our %OPTS ;
159- getopts( ' f:t:s:hu:g:aeipvr :d:' , \%OPTS );
169+ getopts( ' f:t:s:hu:g:aeinpPvr :d:' , \%OPTS );
160170
161171# print out version
162172if ( $OPTS {' v' } ) {
@@ -176,9 +186,9 @@ if ( $OPTS{'h'} || !$ARGV[0] ) {
176186# log directory
177187my $LOGDIR ;
178188if ( $ARGV [0] ) {
179- if ( !-d $ARGV [0] ) {
189+ if ( !-d $ARGV [0] || -l $ARGV [0] ) {
180190 print STDERR
181- " [vlogger] target directory $ARGV [0] does not exist - exiting.\n\n " ;
191+ " [vlogger] target directory $ARGV [0] does not exist or is a symlink - exiting.\n\n " ;
182192 exit ;
183193 }
184194 $LOGDIR = $ARGV [0];
@@ -258,9 +268,14 @@ if ( $OPTS{'d'} ) {
258268 }
259269
260270 # test the connection
261- my $dbh = DBI-> connect ( $DBI_DSN , $DBI_USER , $DBI_PASS )
262- or die " DBI Error: $! " ;
263- $dbh -> disconnect;
271+ eval {
272+ my $dbh = DBI-> connect ( $DBI_DSN , $DBI_USER , $DBI_PASS )
273+ or die " DBI Error: $! " ;
274+ $dbh -> disconnect;
275+ };
276+ if ($@ ) {
277+ print " MySQL Connection problem\n " ;
278+ }
264279
265280 # SIGALRM dumps the tracker hash
266281 $SIG {ALRM } = \&dump_tracker;
@@ -317,7 +332,7 @@ if ( $OPTS{'s'} ) {
317332
318333# chroot to the logdir
319334chdir ($LOGDIR );
320- chroot (" ." );
335+ # chroot("."); #we better do not chroot as DBI requires to load a module on the fly -> error!
321336
322337my %logs = ();
323338my %tracker = ();
@@ -367,6 +382,25 @@ if ( $OPTS{'e'} ) {
367382 $LASTWRITE = time ();
368383 }
369384
385+ # my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
386+ # $atime,$mtime,$ctime,$blksize,$blocks)
387+ # = stat(time2str( $TEMPLATE, time() ));
388+ my @fstat = ELOG-> stat ();
389+ my $nlinks = $fstat [3];
390+ if ($nlinks < 1) {
391+ close ELOG;
392+ open ELOG, " >>" . time2str( $TEMPLATE , time () )
393+ or die ( " can't open $LOGDIR /" . time2str( $TEMPLATE , time () ) );
394+ }
395+
396+ if ( $OPTS {' P' } ) {
397+ $log_line =~ s / ^(.*?\[ client\s +\d +\.\d +)\.\d +\.\d +((?::\d +)?\]\s +.*)/ $1 .0.0$2 / g ;
398+ $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 ;
399+ } elsif ( $OPTS {' p' } ) {
400+ $log_line =~ s / ^(.*?\[ client\s +\d +\.\d +\.\d +)\.\d +((?::\d +)?\]\s +.*)/ $1 .0$2 / g ;
401+ $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 ;
402+ }
403+
370404 # we dont need to do any other parsing at all, so write the line.
371405 print ELOG $log_line ;
372406 }
@@ -379,10 +413,13 @@ else {
379413 while ( my $log_line = <STDIN > ) {
380414
381415
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- }
416+ if ( $OPTS {' P' } ) {
417+ $log_line =~ s / ^(\S *\s +\d +\.\d +)\.\d +\.\d +(\s +.*)/ $1 .0.0$2 / g ;
418+ $log_line =~ s / ^(\S *\s +[a-f0-9]*:[a-f0-9]*:[a-f0-9]*)(?::[a-f0-9]*){2,5}(\s +.*)/ $1 ::0$2 / g ;
419+ } elsif ($OPTS {' p' }) {
420+ $log_line =~ s / ^(\S *\s +\d +\.\d +\.\d +)\.\d +(\s +.*)/ $1 .0$2 / g ;
421+ $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 ;
422+ }
386423
387424 # parse out the first word (the vhost)
388425 my @this_line = split ( / \s / , $log_line );
@@ -392,6 +429,7 @@ else {
392429 if ( $vhost =~ m #[/\\ ] # ) { $vhost = " default" }
393430 $vhost =~ / (.*)/o ;
394431 $vhost = $1 ;
432+ $vhost = ' default' unless $vhost ;
395433
396434 if ( $OPTS {' i' } ) {
397435 $reqsize = $this_line [1] + $this_line [2];
@@ -439,6 +477,11 @@ else {
439477 make_path($filepath )
440478 or die ( " can't mkdir $filepath " );
441479 }
480+
481+ # Dont log to symlinks
482+ if ( -l " ${vhost} /" .time2str( $TEMPLATE , time () ) ) {
483+ die (" Log target is a symlink: $LOGDIR /${vhost} /" .time2str( $TEMPLATE , time () ));
484+ }
442485
443486 # open the file using the template
444487 open $vhost , " >>" .$filename
@@ -520,6 +563,7 @@ sub open_errorlog {
520563
521564# sub to update the database with the tracker data
522565sub dump_tracker {
566+ eval {
523567 if ( keys (%tracker ) > 0 ) {
524568 my $dbh = DBI-> connect ( $DBI_DSN , $DBI_USER , $DBI_PASS )
525569 or warn " DBI Error: $! " ;
@@ -546,6 +590,11 @@ sub dump_tracker {
546590 %tracker = ();
547591 }
548592 alarm $DBI_DUMP ;
593+ };
594+
595+ if ($@ ) {
596+ print " Unable to store vlogger data in database\n " ;
597+ }
549598}
550599
551600# print usage info
@@ -565,6 +614,8 @@ sub usage {
565614 print " -d CONFIG use DBI usage tracker (see perldoc vlogger)\n " ;
566615 print " -p Privacy mode (delete last octet of ipv4 or\n " ;
567616 print " last 4 sections of ipv6)\n " ;
617+ print " -P Extended privacy mode (delete 2 octets ipv4\n " ;
618+ print " or last 5 sections of ipv6\n " ;
568619 print " -i extract mod_logio instead of filesize\n " ;
569620 print " -h display this help\n " ;
570621 print " -v output version information\n\n " ;
0 commit comments