#!/local/bin/perl
#          ^^^^perl5 :-)
# 
#
# Written by: Ove Ruben R Olsen (ruben@uib.no) 
#
# Based on an idea by:    kmk@cc.tut.fi
# English translation by: espena@ifi.uio.no
#
# Read the manual page for further info.
#
# Thanks to Espen for some good ideas and heavy bug reporting.
#
# Usage: stat -h  
#
################################################################################
#
# Copyright (c) Ove Ruben R Olsen (Gnarfer from hell)
#
# Permission to use, copy, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation.
# This also apply your own incarnations of any or all of this code.
# If you use portions of this code, you MUST include a apropriate notice
# where you "stole" it from.
#
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
# Email:  Ruben@uib.no 
#
#
# This work is free software, but if you find it usefull I would appreciate
# if you donated aprox 10 USD to your country's cancer research.
#
#
# This work is entierly dedicated to Kari L|nningen
#
################################################################################
# Alter this lines to suit your site.
#

$IRCDIR  = "/local/irc" ;		# Your IRC directory
$logfile = "$IRCDIR/userlog" ;		# Your userlogfil.
$ddfil   = "$IRCDIR/ircstat.idf" ;	# Your domain description file.


#
# There is no need going beyond this line unless you are very eager to
# debug and destroy this work :-)
################################################################################
################################################################################

$linjer  = 250 ;
$ucount  = 1000 ;
$min     = 60 ;  
$bit     = 0 ;
$stille  = 0 ;
$status  = 'tudi' ;
$sok     = '' ;
$eks     = '' ;
$trans   = '' ;
$Date    = " Sat Jan 21 00:52:29 GMT 1995."; 
$Version = "2.70-200" ;
$ZCAT    = "zcat" ;
$GZIP    = "gzip -cd";
# Og noen av disse burde erstattes med $#blah osv i koden.
$aatte = $fire = $fem  = 0 ;
$seks = $syv  = 1 ;
$firstdate = 991231235959;   # 31.12.1999 23:59:59
$date = 0 ;
$UseGrp = 0;
$Slow = 0 ;
$Para = "";
%mnd = ( 'Jan', "01" , 'Feb', "02" , 'Mar', "03" , 'Apr', "04" ,
	 'May', "05" , 'Jun', "06" , 'Jul', "07" , 'Aug', "08" ,
	 'Sep', "09" , 'Oct', "10" , 'Nov', "11" , 'Dec', "12" ) ;

while ($i = shift) {
  $bit = 1 ,next if ("-b" eq $i)  ;  
  $stille = 1, next if ("-s" eq $i) ;
  $min = shift, next if ("-d" eq $i);
  $Para = shift, next if ("-P" eq $i);
  $ddfil = shift, next if ("-D" eq $i) ;
  $ucount = shift, next if ("-c" eq $i) ;
  $linjer = shift, next if ("-n" eq $i ) ;
  $eks = shift, next if ("-u" eq $i) ;
  $sok .= 'V', next if ("-V" eq $i) ;
  $status = shift, next if ("-r" eq $i) ;
  $UseGrp = 1, next if ("-g" eq $i) ;
  $UseGrp = 2, next if ("-G" eq $i) ;
  $trans = shift, next if ("-t" eq $i) ;
  $Slow = 1, next if ("-S" eq $i);
  $sok = 'I', next if ("-I" eq $i);
  $sok = 'X', next if ("-X" eq $i);
  push (@logfil,$i), next if ($i !~ /^\-/) ;
  push (@logfil,shift(ARGV)), next if ("-l" eq $i)  ;

  if ("-e" eq $i) {
    $estreng = shift ;
    $sok .= 'e' ;
    next ;

  } elsif ("-m" eq $i) {
    $a = shift ;
    if ($a =~ /^-/) {
      unshift(@ARGV,$a) ;
      $a = 0 ;
    } 
    $estreng = (localtime(time))[4] + 1 - $a ;
    $a = 1 if ($a < 0); $a = 12 if ($a > 12);
    foreach (keys %mnd) { $estreng = $_, last if ($estreng == $mnd{$_}); }
    $sok .= 'e';
    next ;

  } elsif ("-v" eq $i) {
    $vstreng = shift ;
    $sok .= 'v' ;
    next ;


  } elsif ( ("-p" eq $i) || ("-x" eq $i) ){
    $a = shift ;
    if ($a eq "m") {
      $a  = shift ;
      $e  = shift ;
      $fra = join ("",$a,$e,"01") ;
      $til = join ("",$a,$e,"31") ;
    } else {
      unshift(@ARGV,$a) ;
      for $e (1..2) {
	$a = shift ;
	($1,$2,$3) = split (/\./,$a);
	@_[$e] = join ("",$3,$2,$1);
      }
      $fra = @_[1] ;
      $til = @_[2];
    }
    $sok .= 'p' if ("-p" eq $i) ;
    $sok = 'x' if ("-x" eq $i) ;
    next ;

  } elsif ($i =~ /^-o$|^-O$/) {
    $Ofil = shift ;
    die "\n$Ofil does allready exist.\n" if (($i eq "-o") && (-e  $Ofil)) ;
    open(OUTPUT,"> $Ofil") || die "\nCannot open $Ofil\n";
    select (OUTPUT); $| = 1 ;
    next;

  } elsif ("-i" eq $i) {
    push (@logfil,shift(ARGV)) ;
    $ofil = shift ;
    die "$ofil does allready exist.\n" if (-e  $ofil) ;
    open(OFIL,">>$ofil") || die "\nCannot open $ofil\n";
    $sok = 'i' ;
    next ;


  } elsif ("-h" eq $i) {
    print (STDERR <<SLUTT);

Usage: stat [options] [logfile] ... [logfile]
 Options:
   -b                 Use bitbucket on unknown domains.
   -c <count>         Display only c number of users under User Information.
   -d <delta>         Group users with delta seconds connect time or less.
   -D <IDFile>        Uses IDFile as an alternative Ircstat Description file.
   -e <string>        Report with matching string occurences.
   -g                 Use grouped domains.
   -G                 As -g but put users into grouped domains also.
   -h                 This help.
   -i <ifile> <ofile> Extract correct formated lines in ifile, append to ofile.
   -I                 Integrity check of the userlogfile.
   -l <logfile>       Uses logfile instead of default logfile.
   -m [n]             Stat this month. If n is present, stat (this month - n).
   -o <outputfile>    Uses outputfile instead of sending the results to stdout.
		      Will check if outputfile exist.
   -O <outputfile>    Sames as -o, but with no checking.
   -n <count>         Show progress for every n counted lines.

SLUTT
    print STDERR "Press Enter to continue" ; $a = <> ;
    print (STDERR <<SLUTT);
   
   -P ad              Paranoid ident parsing. Always, Different.
   -p <date1> <date2> Report for dates between date1 and date2.
      m <year> <mnt>  Report for month 'mnt' and year.
   -r tdDuUi          Report type: Total, Domain, Users, Introduction.
   -s                 Run silently.
   -t du              Translations. Domains, users.
   -u tu              Use user exceptions: Total, Users.
   -v <string>        Report with NON matching string occurences.
   -V                 Return the version of this program.        
   -x <date1> <date2> Extract dates between date1 and date2 to stdout.
      m <year> <mnt>  Report for month 'mnt' and year.
   -X                 Extract correctly formated lines from the input.

 Logfiles:
   Logfiles is for the lazy ones who do not want to use the -l option.

SLUTT
  exit ;
  }
}

push (@logfil,$logfile) unless @logfil;

if (! $stille) {
   print STDERR "\nThis is IRCSTAT version $Version - $Date.\n",
         "Written by Ove Ruben R Olsen - Copyright (C) 1991-1995.\n\n" ; 
   exit if ($sok =~ /V/);
   print STDERR "Using:     $ddfil as IDF file.\n" ;
   foreach (@logfil) { print STDERR "           $_ as logfile.\n" ; }
   $Ofil = STDOUT unless $Ofil;
   print STDERR "           $Ofil as outputchannel.\n\n",
        "Status:    So:$sok St:$status T:$trans B:$bit U:$ucount " ,
         "u:$eks D:$min L:$linjer\n\n";
}

if ($sok =~ /I/) { 
  foreach (@logfil) { &Integritet($_) ; }
  exit ;
}

if ($sok =~ /X/) { 
  foreach (@logfil) { &Integritet($_) ; }
  exit ;
}

open (FIL, $ddfil) || warn "\nCannot open IDF file $ddfil.\n";
while (<FIL>) {
  &IDF() ;
}


if ( ! $stille) {
  print STDERR "Read in: ", &SPCs($fire,3), "$fire Domain translations.\n" ,
               &SPCs($seks,12), "$seks Domain informations.\n" ,
               &SPCs($syv,12), "$syv User translations.\n" ,
               &SPCs($aatte,12), "$aatte User exceptions.\n" ,
               &SPCs($fem,12), "$fem User information lines.\n\n" ;
}

if ($status eq "i" ) { while (<FIL>) { print $_ ; } exit ;}



exit if ($sok eq 'i' ) ;

foreach (@logfil) { &LOG ($_) ; }



exit if ($sok =~ /x/) ;

die "No data availible to make a report.\n"  if (! $total) ;

exit if ($sok eq 'i' ) ;


$virkC = $indivC = $domC = 0 ;
foreach ( keys %domains) { $domC ++ ; };
foreach ( keys %virkelig) { $virkC ++ ; };
foreach ( keys %indic) { 
  $indivC ++ ;   # Numer of users total.
  ($j,$ho) = split (/@/,$_,2);
  $individom{$ho} ++ ; # Numer of users inside a domain.
} ;

# Adding groupinfo
if ($UseGrp != 0 ) {
  foreach (keys %subgrp) {
    $s = $subgrp{$_};
    $grps{$s} = join (" ",$grps{$s},$_);
  }

  foreach (keys %grptime) {
    $domains{"\001$_"} = $grptime{$_} ;
    $domainc{"\001$_"} = $grpcount{$_} ;
    foreach $gr ( split(/\s+/,$grps{$_}) ) {
      # next if ($gr =~ /^\s+$|^$/);
      $SubDom{$gr} = $domains{$gr} ;
      $SubDomC{$gr} = $domainc{$gr} ;
      $SubDomI{$gr} = $individom{$gr};
      $individom{"\001$_"} += $individom{$gr};
      delete $domains{$gr} ;
      delete $domainc{$gr} ;
      delete $individom{$gr};
    }
  }

}


@_ = localtime(time); @_[4] ++ ;
chop ($a = `hostname`) ; 
chop ($b = `domainname`)  ; 
$a = "$a.$b" ;

$a =~ tr/a-z/A-Z/ ;

if ($status !~ /D|U/) {

  print   "\nSTATISTICS FOR IRC SERVER $a @_[3]/@_[4] @_[5]" ,  
	  "  @_[2]:@_[1]:@_[0]\n";
  if ($status =~ /i/) { while (<FIL>) { print $_ ; } }
  print "\nLog started: $Fday ", &DateStr($firstdate),
        "\nLog ended:   $Lday ", &DateStr($date), "\n\n";
} 

if ($status =~ /t/) {

  print "\nTOTAL INFORMATION\n^^^^^^^^^^^^^^^^^\n";
  $a = $sessions ;       $b = $domC ;
  $c = $indivC ;     $d = $virkC ;
  foreach (values %ParaUkj) {$Ukjente += $_};
  foreach (values %ParaLik) {$Like += $_};
  foreach (values %ParaUlik) {$Ulike += $_};
  $Ukjente = $Ukjente / 2 ; $Like = $Like / 2 ; $Ulike = $Ulike / 2 ;
  print "Total served time:                  " , &skriv ($total)  ,
        "\nNumber of sessions:                 ",  &SPCs($a,4), $a ,
       "\nNumber of different domains:        ",  &SPCs($b,4), $b ,
       "\nNumber of different users:          ",  &SPCs($c,4), $c ,
       "\nNumber of different machines:       ",  &SPCs($d,4), $d ,
       "\n\nNumber of \"unknown\" ident replies:  ",
		     &SPCs($Ukjente,4), $Ukjente,
       "\nNumber of \"correct\" ident replies:  ", &SPCs($Like,4), $Like,
       "\nNumber of \"incorrect\" ident replies:", &SPCs($Ulike,4), $Ulike,
  "\n\n\n";



}  # Status = t 


if ($status =~ /d/i) {
  if ($status =~ /d/) {
  print  <<SLUTT;

DOMAIN INFORMATION
^^^^^^^^^^^^^^^^^^
(f) = indicates a far-away domain net-vice.
(n) = indicates a close domain net-vice.
Unk = Unknown identd replies.
Inc = Incorrect identd replies (eg. fakes).
Cor = Correct idented replies (username matches identd reply).

                                                                  Ident replies
Num  Domain name        Users  Logins  Connection time  Percent   Unk  Inc  Cor 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SLUTT
}

  $teller = 0 ;
  foreach ( sort { $domains{$b} <=> $domains{$a} ;} keys %domains ) {
    $teller ++ ;

    
    if ( ($_ =~ /^\001/) && ($UseGrp != 0)) {
      $host = $_; $host =~ s/\001//;
      &Hinfo();

      foreach $gr ( split(/\s+/,$grps{$host}) ) {
        next if ($gr =~ /^\s+$|^$/);
	&HinfoG (" ", "    $gr" , $SubDomI{$gr} ,$SubDomC{$gr}, 
	      $SubDom{$gr} , &Precent($SubDom{$gr},$domains{$_}));
	$domains{$gr} = $SubDom{$gr} ;
      }
      next ;
    }
		      
    &Hinfo ();
  }


  print "\n\n";
  foreach ( sort { $domains{$b} <=> $domains{$a} ;} keys %domains ) {
    next if ( ($_ =~ /^\001/) && ($UseGrp != 0)) ;
    $a = $in{$_} || "- Not defined in the $ddfil file." ;
    print   $_, &SPCs($_,15), $a , "\n" ; 
  }

}   # status = d




if ($status =~ /u/i) {

  if ($status =~ /u/) {
  print   "\n\nINDIVIDUAL USER INFORMATION\n" .
	  "^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n\n";

  foreach (@ui) { print $_,"\n";  ; }

  print " 

Unk = Unknown identd replies.
Inc = Incorrect identd replies (eg. fakes).
Cor = Correct idented replies (username matches identd reply).

                                                               Ident replies
Num  Username                     Logins    Connection time    Unk  Inc  Cor 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
";
  }

  $a = $total = $teller = $j = 0 ;
  $delta = $min * 60 ;

  if ($UseGrp == 2) {
    foreach (keys %indiv) {
      ($user,$host) = split (/@/,$_);
      if ($subgrp{$host}) {
	$s = join ("@",$user,$subgrp{$host});
	$indiv{$s} += $indiv{$_} ;
	$indic{$s} += $indic{$_};
	delete $indiv{$_} ; delete $indic{$_} ;
      }
    }
  } 

  foreach ( sort { $indiv{$b} <=> $indiv{$a} ;} keys %indiv ) {
    $teller ++ ;
    next if (($ue{$_} == 1) && ($eks =~ /u/)) ;
    exit if ($teller == $ucount);
    

    if ($indiv{$_} < $delta) {
      $a += $indic{$_} ;
      $j ++ ;
      $total += $indiv{$_} ;
      next ;
    }

    if ($status =~ /u/) {
      printf ("%3s  %-28s %6s  %s   %4s %4s %4s\n",
             $teller ,  $_, $indic{$_}, &skriv ($indiv{$_}),
            $ParaUkj{$_}, $ParaUlik{$_}, $ParaLik{$_});
    } 
    if ($status =~ /U/) {
      print join (":",$teller ,  $_, $indic{$_}, &skriv ($indiv{$_}),
            $ParaUkj{$_}, $ParaUlik{$_}, $ParaLik{$_});
    }
  }

  exit unless $j ;
  exit if ($status =~/U/) ;
  print   "\n" ;
  $delta = "users with less than $min min. logintime" ;
  print   &SPCs($j,2) ,$j , "  " ;
  print   $delta ,  &SPCs($delta,40) ;
  print   &SPCs($a,4) , $a , "  ",
  &skriv ($total);
  print   "\n" ;

}  # Status = u 

exit ;   # Just in case ...


################################################################################
sub Hinfo {
    if ($status =~ /d/) {
      # $ParaUkj{$_}  = 0 if ($ParaUkj{$_} eq "" );
      # $ParaUlik{$_} = 0 if ( $ParaUlik{$_} eq "" );
      # $ParaLik{$_}  = 0 if ( $ParaLik{$_} eq ""  );
      printf("%3s %-21s %3s %6s %s   %6s  %4s %4s %4s\n",
            $teller, "$_ ($farnear{$_})" , $individom{$_} , $domainc{$_} ,
            &skriv($domains{$_}),&Precent($domains{$_},$total) ,
            $ParaUkj{$_}, $ParaUlik{$_}, $ParaLik{$_}
	    )  ;
    } elsif ($status =~ /D/) {
      print join (":", $teller, $_ , $individom{$_} , $domainc{$_} ,
            &skriv($domains{$_}),&Precent($domains{$_},$total) ,
            $ParaUkj{$_}, $ParaUlik{$_}, $ParaLik{$_},"\n");
    }
}
################################################################################


sub HinfoG {  # Print a line at the hostinfo in groups
  if ($status =~ /d/) {
    print &SPCs(@_[0],2) ,@_[0] , "  " ,		# Counter.
	  @_[1], &SPCs(@_[1],29), "[",			# Hostname.
	  &SPCs(@_[2],3), @_[2],			# num of users.
	  &SPCs(@_[3],8) ,@_[3],			# num of logins.
	  "   " , &skriv (@_[4]) ; 			# time logged in.
    print "   ", &SPCs(@_[5],4), @_[5] ," ]\n" ;	# % tid log in.
  } elsif ($status =~ /D/) {
    print join (":",@_[0],"\n");
  }
}


################################################################################
sub DateStr {
  # 99123186399 = 31.12.1999
  # Tue Jul  6 01:39:27 1993
  ($c,$a,$b,$dt,$dm,$ds) = unpack ("a2 a2 a2 a2 a2 a2",@_[0]);
  foreach (keys %mnd) {
    $a = $_, last if ($mnd{$_} eq $a); 
  }
  "$a $b $dt:$dm:$ds 19$c" ;
}


################################################################################
sub Precent {
  $a = (@_[0] * 100) / @_[1] ;
  if ($a > 0.01) {
    ($a,$j) = split (/\./,$a) ;
    join (".",$a, unpack ("a2",$j)) ; 
  } else {
    "0.00" ;
  } 
}

################################################################################

# sub bynumber { $a <=> $b; } 
################################################################################

sub skriv {
    local ($a,$b,$c,$d) ;
    $a = @_[0] % 60;
    $b = (@_[0] % 3600) / 60;
    $c = (@_[0] % (24*3600)) / 3600;
    $d = @_[0] / (24 * 3600);
    sprintf   ("%3d ds + %02d:%02d:%02d", $d, $c, $b, $a);
}

################################################################################
sub SPCs {
  " " x ( @_[1] - length (@_[0] ) + 1 ) ;
}

################################################################################

sub IDF {
  next if ($_ =~ '^$');
  next if ($_ =~ '^#') ;
  # &intro (@_[0]) if ($_ =~ '^intro');
  last if ($_ =~ '^intro');
  chop;
  ($a,$b) = split (/ /,$_,2);

  # First level of confusion

  if ($a eq 'include') {
    if ($i == 1) {
      print STDERR "\nMax include level is 1.\n" unless $stille ; 
      next  ;
    }
    $i = 1 ;
    open (IFIL, $b) || warn "\nCannot include IDF file $b.\n";
    while (<IFIL>) {
      &IDF() ;
    }
    close (IFIL);
    $i = 0 ;

  } elsif ($a eq 'ui') {
    $fem ++ ;
    push (@ui,$b) ;
    next ;

  } elsif ($a eq 'dg') {
    $dgCount ++ ;
    @mld = split (/\s+/,$b);
    $grp = shift (@mld);
    $j = join (" ", @mld);
    $grps{$grp} =  join (" ",$j,$grps{$grp});
    $grptime{$grp} = 0 ;
    $grpcount{$grp} = 0 ;
    foreach $gr (@mld) {
      $subgrp{$gr} = $grp;
    }

    next;
  }

  # Next level of confusion...

  ($b,$c) = split (/\s+/,$b,2) ; 

  if ($a eq 'ue') {
    $ue{$b} = 1 ;
    $aatte ++ ;
    next ;

  } elsif ($a eq 'di') {
    $in{$b} = $c  ;
    $seks ++ ;
    next ;

  } elsif ($a eq 'fg') {
    $fg{$b} = $c ;
    $fgCount ++ ;
    $grptime{$c} = 0 ;
    $grpcount{$c} = 0 ;
    next;

  } elsif ($a eq 'ut') {
    $ut{$b} = $c  ;
    $syv ++ ;
    next ;

  } elsif ($a eq 'dt') {
    $dt[$fire] = $b ;
    ($c,$junk) = split (/\s+/,$c,2);
    $tr[$fire] = $c ;
    $junk = "far" if ($junk eq "");
    $farnear{$c} = unpack("a1",$junk);
    $fire ++ ;
    next ;
  }

  print STDERR "\nBullshit found while parsing IDF file @_[0] line $.\n" 
    unless $stille ; 
}

################################################################################
sub Integritet {
  $ofil = @_[0];
  if (! (-e $ofil && -R $ofil ))  {
     print STDERR "Cannot open userlog file: $ofil\n";
     return  ;
  }
  $ofil = "$ZCAT $ofil |" if ($ofile =~ /.Z$/);
  $ofil = "$GZIP $ofil |" if ($ofile =~ /.gz$|.z$/);
  open(FILEN, $ofil); 
  while (<FILEN>) {
    if (/^$/) { print "Open line: $ofil line $. \n" ; next ;}
    if (/^... ...\s*\d+ \d\d:\d\d:\d\d \d+ \(\s*\d+:\d\d:\d\d\): .+@.+$/) {
      print if ($sok =~ /X/) ;
      next ;
    }
    print "Bullshit in line $., file: $ofil  ->\n   $_\n" ;
  }
  print STDERR "$. lines checked in $ofil\n" ;

}

################################################################################


sub LOG {
  $ofil = @_[0];
  if (! (-e $ofil && -R $ofil ))  {
     print STDERR "Cannot open userlog file: $ofil\n";
     return  ;
  }
  $ofil = "$ZCAT $ofil |" if ($ofil =~ /.Z$/);
  $ofil = "$GZIP $ofil |" if ($ofil =~ /.gz$|.z$/);
  open(FILEN, $ofil) ; 
  print STDERR "Processing @_[0]: " unless $stille ;

  while (<FILEN>) {
    next if (/^$/) ;

    if ($sok =~ /e/ ) {
      next if ($_ !~ /$estreng/io) ;
    }

    if ($sok =~ /v/ ) {
      next if ($_ =~ /$vstreng/io) ;
    }
    chop;
    if ($sok eq 'i') {
      print OFIL $_,"\n" ;
      next ;
    }

    ($dd,$a,$b, $dt,$j,$dm,$j,$ds, $c,$j,$ti,$j,$mi,$j,$se,$j,$UatH) =
    unpack("a4 A4 a2 a3 a1 a2 a1 a2 a5 a2 a3 a1 a2 a1 a2 a3 A50",$_);
    #       dd a  b  dt    dm    ds c     ti    mi    se    Uat 
    
    ($UatH,$ident) = split (/\s+/,$UatH,2);
    $ident =~ tr/\[\]//d;

    #  a = month     dd = Day
    #  b = date      dt = Hour
    #  c = year      dm = Min
    #  j = junk      ds = Sec 

    
    $a = $mnd{$a} ;
    $b = "0$b"  if ($b < 10 ) ;
    $c -= 1900 ;
    $dt =~ s/ //; 
    $b =~ s/ //;
    $j = "$c$a$b$dt$dm$ds";

    if ($j > $date) {
      $date = $j;
      $Lday = $dd ;
    }
    if ( $j < $firstdate ) {
      $firstdate = $j ;
      $Fday = $dd ;
    }

    if ( ($sok =~ /p/ ) || ($sok =~ /x/ )) {
      $tid = join ("",$c,$a,$b) ;
      next if ! ( ($tid >= $fra) && ($tid <= $til) ) ;
      if ($sok =~ /x/) {
	print $_, "\n" ;
	next ;
      }
    }

    $secs = ($ti * 3600) + ($mi * 60) + $se;
    $total += $secs;
    $sessions++;

    ($user,$ho) = split (/@/,$UatH,2) ;
    $real = $user ;
    # $user =~ s/^~//; 	# Trim av eventuel ~ p} starten av brukernavn
    $user =~ tr/~//d;	# tr skal v{re kjappere enn s. Tviler p} at det
			# finnes brukerid med tilde i seg. Den tid, den
			# sorg.

    $parateller = 3 if ($ident ne $user); 
    $parateller = 1 if ($ident eq "unknown"); 
    $parateller = 2 if ($ident eq $user); 
     # print "ID $ident -> $parateller\n";

    if ($Para eq "a") { 
      $user = $ident if ($ident ne "unknown"); 
    } elsif ($Para eq "d") { 
      $user = $ident if ( ($ident ne "unknown") && ($ident ne $user)); 
    }

    $us = $ho ;

    $virkelig{$us} += 1;


    if (! $stille ) {
      print STDERR "$sessions " if ( $sessions % $linjer  ==  0 )  ;
    }
    $host = '' ;

    # Dette er n|kkelen til hastighet:
    if (!($host=$domaintrans{$ho})) {
	for $s (0..$#dt)  {
	      $host = $tr[$s], last if ($ho =~ /$dt[$s]/i) ;
#
# Her brukes den ber|mmelige @dt
#
	}
#	warn "Ny cache entry: $ho -> $host\n";
	$domaintrans{$ho}=$host;
    }
#     else {
#	warn "Cache hit!\n";
#    }
    # Det var alt

    if ($bit) {
      if ($host eq '') {
	$host = "BITBUCKET"  ;
	$user = "BITBUCKET" ;
      }
    } else {
      $host = $ho if ($host eq '') ; 
    }

    # $host =~ s/\s+$//g ;
    $host =~ tr/ //d ;

    $host = $ho if ($trans =~ /d/) ;


    $UatH = join ("@",$user,$host);

    if ($trans !~ /u/ ) {
      if ($ut{$UatH}) {
	$UatH = $ut{$UatH} ;
	($user,$host) = split (/@/,$UatH);
      }
    }

    next if (($ue{$UatH} == 1) && ($eks =~ /t/)) ;


    if ($UseGrp != 0) {
      foreach $s (keys %fg) { 
	if ($host =~ /$s/)  {
	  $subgrp{$host} = $fg{$s};
	  last ;
	}
      }
    }



    $indiv{$UatH} += $secs ;
    $indic{$UatH} += 1;
    
    $domains{$host} += $secs;
    $domainc{$host} += 1 ;

    $ParaUkj{$UatH} ++ if ($parateller == 1) ;
    $ParaLik{$UatH} ++ if ($parateller == 2);
    $ParaUlik{$UatH} ++ if ($parateller == 3);
    $ParaUkj{$host} ++ if ($parateller == 1) ;
    $ParaLik{$host} ++ if ($parateller == 2);
    $ParaUlik{$host} ++ if ($parateller == 3);

    if ($UseGrp != 0) {
      if ($subgrp{$host}) {
	$gr = $subgrp{$host} ;
	$grptime{$gr} += $secs; 
	$grpcount{$gr} ++ ;
      }
    }


  }
  print STDERR "\n"; 
}
