package UserapParser;

use strict;
use UserapCommon;
use Digest::MD5 qw(md5 md5_hex md5_base64);

#===============================================================================
#global package variables
my $STATFILE="$DATADIR/tc_dump.xml";
my $USERAPSTAT="$DATADIR/tc_update.xml";

my $NICKS = {};
$NICKS->{$DEFAULT_CLASS}="Default";
my $IPS = {};
my $BANS = {};
my %CACHE = ();
my $FACE_CONF = {};
my $IF_HOUR = {};
#===============================================================================

sub GetIPs ($) {
    my $face = shift;
    my $IPS = {};
    my $tmpbans = {};
    #write ban file for this interface
    open BF, ">$DATADIR/autoban/$face";
    if (open (FI, "$DATADIR/qos-${face}.act")) {
        while (<FI>) {
	    my $lajna = $_;
    	    if (!($lajna =~ /account id*/)) {
        	next;
            } else {
	        chomp($lajna);
    	        my @pole = split (">",$lajna);
                my (undef, $id, undef, $nick) = split ("'", $pole[0]);
	        #print "\n$id - $nick: ";
    	        $NICKS->{"$id"}=md5_base64($nick."-".$id);
		my $tmpips = "";
		my $banned = 0;
                for (my $i = 1;$i < $#pole;$i++) {
	            my (undef, $ip, undef, $ustatus) = split ("'", $pole[$i]);
    	            if ($ustatus =~ /BAN64/ ) {
			$banned = 64;
    	            } elsif ($ustatus =~ /BAN128/ ) {
			$banned = 128;
    	            } elsif ($ustatus =~ /BAN(\d+)k/ ) {
			$banned = $1;
    	            } elsif ($ustatus =~ /BAN(\d+)M/ ) {
			$banned = $1*1124;
			#print "parse $1 $banned";
    	            } elsif ($ustatus =~ /DEPTOR/ ) {
			$banned = 128;			
		    }
		    if ($tmpips eq "") {
			$tmpips = $ip;
		    } else {
			$tmpips = $tmpips.":".$ip;
		    }
		}
        	if ($banned) {
		    print BF "$id $face 32 $banned\n";
            	    #print "      BAN$banned - $id $face\n";
		    $tmpbans->{"$id"}=$banned;
		}
		$IPS->{"$id"}=$tmpips;
		#print "$id: $tmpips\n";
    	    }
	}
	close FI;
    }
    close BF;
    $BANS->{$face} = $tmpbans;
    return $IPS;
}


#load IP and bans
sub GetAutoBans ($) {
    my $face = shift;
    GetIPs($face);
    return $BANS->{$face};
}

# ==========================================================

sub saveConfig  {
    my ($shash, $filen) = @_;
    if (not defined ($filen)) { $filen = "$DATADIR/config.xml" };
    #generuje vystup toho jak je kdo omezen 
    print "   generating stats ... \n";
    open OF, ">$filen";
    print OF "<?xml version='1.0'?>\n";
    print OF "<scriptversion id='$UVERS'/>\n";
    #dump config info
    print OF "<config>\n";
    while (my ($face,$face_cfg) = each (%{$shash})) {
        my $iface = ${$face_cfg}{"iface"};
        if (!$iface || $iface eq "") {
            $iface = $face;
        }
        print OF "<interface name='$face'>\n   ";
        while (my ($varn, $varv) = each (%{$face_cfg})) {
            print OF "<var name='$varn' value='$varv'/>";
        }
        print OF "\n</interface>\n";
    }
    print OF "</config>\n";
    close OF;
}

sub loadConfig {
    my ($filen)=@_;
    if (not defined ($filen)) { $filen = "$DATADIR/config.xml" };
    open IF, "$filen";
    my $return_hash = { };
    while (<IF>) {
	chomp;my $line = $_;
        if ($line =~ /<interface>*/) {
	    #store data in temporary hash
	    my $tmphash = { };
            my (undef, $iname) = split ("'", $line);
	    #print "$iname ==============\n";
            $line = <IF>;chomp($line);
            my @ipole = split(">", $line);
            foreach (@ipole) {
                my (undef, $varn, undef, $varv) = split("'",$_ );
                ${$tmphash}{"$varn"} = $varv;
		#print "   $varn : $varv \n";
            }
            if (!exists ${$tmphash}{iface}) {
                ${$tmphash}{iface} = $iname;
            }
            if (!exists ${$tmphash}{queues}) {
                ${$tmphash}{queues} = $iname;
            }
	    $return_hash->{"$iname"}=$tmphash;
        }
    }
    #return data
    close IF;
    return $return_hash;
}

# ==========================================================

sub saveUserLimits  {
    #generate xml output of user limits
    my ($shash, $filen) = @_;
    if (not defined ($filen)) { $filen = "$DATADIR/tc_update.xml.tmp" };
    print "   generating stats ... \n";
    open OF, ">$filen";
    print OF "<?xml version='1.0'?>\n";
    print OF "<scriptversion id='$UVERS'/>\n";
		    
    print OF "<userapstats>\n";
    while (my ($uidf,$rcd) = each (%{$shash})) {
        my ($uid, $face) = split(":", $uidf);
        my $nick = $NICKS->{$uid} ? $NICKS->{$uid} : "neznamy";
        print OF "<user id='$uid' face='$face'>$rcd</user>\n";
    }
    print OF "</userapstats>\n";
    close OF;
    `mv $USERAPSTAT.tmp $USERAPSTAT`;
}

sub loadUserLimits {
    #loads user limits
    #returns hash key=id:face value=rate:ceil
    my ($filen) = $_;
    if (not defined ($filen)) { $filen = "$DATADIR/tc_update.xml" };
    open IF, "$filen";
    my $return_hash = { };
    while (<IF>) {
	chomp;
	my $line = $_;
        if ($line =~ /<user /) {
            my ($ids,$dts) = split (">", $line);
            my (undef,$id,undef,$face) = split ("'", $ids);
            my ($dataz) = split ("<", $dts);
            $return_hash->{"$id:$face"}=$dataz;
            #print "$id - $face - $dataz\n";
        }
    }
    return $return_hash;
}									

# ==========================================================

sub parse_qos_cfg {
    my ($FN) = @_;my $tmp_hash = { };
    open IF, "$FN";
    while (<IF>) {
        my $tmp = $_;$tmp =~ s/#.*//; chomp ($tmp);
        if (length($tmp) > 0) {
            my ($rvar, $rvalue) = split ("=", $tmp);
            ${$tmp_hash}{"$rvar"} = $rvalue;
        }
    }
    close IF;
    return $tmp_hash;
}
								
#nacte informace z konfiguraku do hashe
sub getIfacesInfo {
    my $tmp=`ls $QOSDIR/qos-*`;
    $tmp =~ s/$QOSDIR\/qos-//g;
    my @faces = split ('\n', $tmp);
								
    my $def_cfg_ref = parse_qos_cfg("${QOSDIR}/default-qos");
								    
    foreach (@faces) {
        my $tmp_face = $_;
        my $face_cfg_ref = parse_qos_cfg("${QOSDIR}/qos-$tmp_face");
        #kopie defaultniho nastaveni
        my $tmp_cfg_ref = { };
        %{$tmp_cfg_ref} = %{$def_cfg_ref};
        #uplatnime zmeny podle konfigu
        while (my ($fvar, $fval) = each (%{$face_cfg_ref})) {
            ${$tmp_cfg_ref}{"$fvar"} = $fval;
        }
        $FACE_CONF->{"$tmp_face"} = $tmp_cfg_ref;
    }
    return $FACE_CONF;
}

# ==========================================================

sub loadNicks {
    #load nicks from file
    if (open NF, "$DATADIR/nicks.txt") {
	while (<NF>) {
	    chomp;
	    my ($id,$nick) = split(":", $_);
	    $NICKS->{"$id"}=$nick;
	}
	close NF;
    }
    return $NICKS;
}

sub saveNicks ($) { 
    #store nicks to file
    my $snicks = shift;
    $NICKS=$snicks;    
    open NF, ">$DATADIR/nicks.txt";
    while (my ($id,$nick) = each (%{$snicks})) {
	print NF "$id:$nick\n";
    }
    close NF;
}

# ==========================================================

sub saveStats {
    #save user stats
    #input <if_hour_hash>,<if_total_hash>,<if_last_hash>,<sum_hour_hash>,<sum_total_hash>
    #   <sysclass_hash>,[filename for save file]
    my ($if_hour,$if_total,$if_last,$sum_hour,$sum_total,$sysclass,$filen) = @_;
    if (not defined ($filen)) { $filen = "$DATADIR/tc_dump.xml" };
    open OF, ">$DATADIR/tc_dump-$$.tmp";
    print "   saving stats to $filen";

    #dump general info
    print OF "<tc_dump>\n";
    print OF "<general>\n";
    print OF "  <scriptversion id='$UVERS'/>\n";
    print OF "  <created stamp='".time."'/>\n";
    print OF "</general>\n";
    #dump prirustky na interfejsech
    print OF "<interfacehourdata>\n";
    while (my ($face,$users) = each (%{$if_hour})) {
        while (my ($uid,$send) = each (%{$users})) {
            print OF "  <user id='$uid' face='$face'>$send</user>\n";
        }
    }
    print OF "</interfacehourdata>\n";
									    
    #dump total na interfacech
    print OF "<interfacesumdata>\n";
    while (my ($face,$users) = each (%{$if_total})) {
        while (my ($uid,$send) = each (%{$users})) {
    	    print OF "      <user id='$uid' face='$face'>$send</user>\n";
	}
    }
    print OF "</interfacesumdata>\n";

    #dump nejnovejsich prirustku
    print OF "<interfacelastdata>\n";
    while (my ($uface,$send) = each (%{$if_last})) {
        my ($uid,$face)=split(":", $uface);
        print OF "      <user id='$uid' face='$face'>$send</user>\n";
    }
    print OF "</interfacelastdata>\n";

    #dump celkove prirustky
    print OF "<userhourdata>\n";
    while (my ($uid,$send) = each (%{$sum_hour})) {
        print OF "      <user id='$uid'>$send</user>\n";
    }
    print OF "</userhourdata>\n";

    #dump celkovy total
    print OF "<usersumdata>\n";
    while (my ($uid,$send) = each (%{$sum_total})) {
        print OF "      <user id='$uid'>$send</user>\n";
    }
    print OF "</usersumdata>\n";

    #dump system classes
    print OF "<systemclasses>\n";
    while (my ($face,$fdata) = each (%{$sysclass})) {
        while (my ($uid,$data) = each (%{$fdata})) {
    	    print OF "      <class dev='$face' id='$uid' rate='".${$data}{"crate"}."' ceil='".${$data}{"cceil"}."' currate='".${$data}{"rrate"}."' send='".${$data}{"send"}."' drop='".${$data}{"drop"}."'/>\n";
	}
    }
    print OF "</systemclasses>\n";
    print OF "</tc_dump>\n";

    close OF;
    system("mv $DATADIR/tc_dump-$$.tmp $filen");
    print ".\n";
}

sub load_general_data {
    print " config";
    my ($ff)=@_;
    my $line = <$ff>;chomp($line);
    my $ts = 0;
    while ($line && $line ne "</general>") {
        #print OF "$line <br>\n";
	if ($line =~ /created/ ) {
	    (undef, $ts) = split("\'", $line);
	    print "timestamp: $ts\n";
	}
        $line = <$ff>;chomp($line);
    }
    return $ts;
}

sub load_interface_hour_data {
    #hour back traffic on interfaces
    print " if_hour";
    my ($ff)=@_;
    my $tmpdata = {};
    my $line = <$ff>;
    while ($line && (!($line =~ /<\/interfacehourdata>/))) {
        if ($line =~ /<user/) {
            my ($ids,$dts) = split (">", $line);
            my (undef,$id, undef, $face) = split ("'", $ids);
            my ($send) = split ("<", $dts);
	    if (!exists $tmpdata->{$face}) {
		$tmpdata->{$face} = {};
	    }
            $tmpdata->{$face}->{$id}= $send;
            #print "$id:$face - $send\n";
        }
        $line = <$ff>;
    }
    return $tmpdata;
}

sub load_interface_last_data {
    #last measured traffic on interfaces
    print " if_last";
    my ($ff)=@_;
    my $tmpdata = {};
    my $line = <$ff>;
    while ($line && (!($line =~ /<\/interfacelastdata>/))) {
        if ($line =~ /<user/) {
            my ($ids,$dts) = split (">", $line);
            my (undef,$id, undef, $face) = split ("'", $ids);
            my ($send) = split ("<", $dts);
            $tmpdata->{"$id:$face"}= $send;
            #print "$id:$face - $send\n";
        }
        $line = <$ff>;
    }
    return $tmpdata;
}

sub load_interface_sum_data {
    #traffic on interfaces
    print " if_total";
    my ($ff)=@_;
    my $tmpdata = {};
    my $line = <$ff>;
    while ($line && (!($line =~ /<\/interfacesumdata>/))) {
        if ($line =~ /<user/) {
            my ($ids,$dts) = split (">", $line);
            my (undef,$id, undef, $face) = split ("'", $ids);
            my ($send) = split ("<", $dts);
	    if (!exists $tmpdata->{$face}) {
		$tmpdata->{$face} = {};
	    }
            $tmpdata->{$face}->{$id}= $send;
            #!!!! $users{"$id"}="1";
            #print "$id:$face - $send\n";
        }
        $line = <$ff>;
    }
    return $tmpdata;
}

sub load_user_hour_data {
    #summary hour traffic on all interfaces
    print " sum_hour";
    my ($ff)=@_;
    my $tmpdata = {};
    my $line = <$ff>;
    while ($line && (!($line =~ /<\/userhourdata>/))) {
        if ($line =~ /<user /) {
            my ($ids,$dts) = split (">", $line);
            my (undef,$id) = split ("'", $ids);
            my ($send) = split ("<", $dts);
            $tmpdata->{$id}= $send;
            #print "$id - $send\n";
        }
        $line = <$ff>;
    }
    return $tmpdata;
}

sub load_user_sum_data {
    #summary data on all interfaces
    print " sum_total";
    my ($ff) = @_;
    my $tmpdata = {};
    my $line = <$ff>;
    while ($line && (!($line =~ /<\/usersumdata>/))) {
        if ($line =~ /<user /) {
            my ($ids,$dts) = split (">", $line);
            my (undef,$id) = split ("'", $ids);
            my ($send) = split ("<", $dts);
            $tmpdata->{"$id"}= $send;
            #print "$id - $send\n";
        }
        $line = <$ff>;
    }
    return $tmpdata;
}

sub load_system_classes_data {
    #load system classes data
    print " system";
    my ($ff) = @_;
    my $tmpdata = {};
    my $line = <$ff>;
    while ($line && (!($line =~ /<\/systemclasses>/))) {
        if ($line =~ /<class/) {
            my (undef,$device, undef, $class,undef,$rate,undef,$ceil,undef,$crate,undef,$send,undef,$drop) =
	    split ("'", $line);
	    if (!exists $tmpdata->{$device}) {
		$tmpdata->{$device} = {};
	    }
            $tmpdata->{$device}->{$class} = {};
            $tmpdata->{$device}->{$class}->{crate} = $rate;
            $tmpdata->{$device}->{$class}->{cceil} = $ceil;
            $tmpdata->{$device}->{$class}->{rrate} = $crate;
            $tmpdata->{$device}->{$class}->{"send"} = $send;
            $tmpdata->{$device}->{$class}->{drop} = $drop;
            #print $class.$device.$system_data{"$class:$device"}."\n";
        }
        $line = <$ff>;
    }
    return $tmpdata;
}

sub loadStats {
    #load user stats
    #output (<if_hour_hash>,<if_total_hash>,<if_last_hash>,<sum_hour_hash>,<sum_total_hash>
    #   <sysclass_hash>,<timestamp>)
    #input [filename for save file]
    my ($filen) = @_;
    my $if_hour={};my $if_total={};my $if_last={};
    my $sum_hour={};my $sum_total={};my $sysclass={};
    my $fts;
    if (not defined ($filen)) { $filen = "$DATADIR/tc_dump.xml" };
    open IF, $filen;
    my $line = <IF>;
    chomp ($line);
    if ($line eq "<tc_dump>") {
	while (<IF>) {
            $line = $_;
	    chomp($line);
	    if ($line eq "<general>") {
	        $fts = load_general_data(\*IF);
	    } elsif ($line eq "<interfacehourdata>") {
	        $if_hour = load_interface_hour_data(\*IF);
	    } elsif ($line eq "<interfacesumdata>") {
	        $if_total = load_interface_sum_data(\*IF);
	    } elsif ($line eq "<userhourdata>") {
	        $sum_hour = load_user_hour_data(\*IF);
	    } elsif ($line eq "<usersumdata>") {
	        $sum_total = load_user_sum_data(\*IF);
	    } elsif ($line eq "<interfacelastdata>") {
	        $if_last = load_interface_last_data(\*IF);
	    } elsif ($line eq "<systemclasses>") {
	        $sysclass = load_system_classes_data(\*IF);
	    } elsif ($line eq "</tc_dump>") {
	        print ".\n";
	    } else  {
	        print "ERROR PARSING STATS !!!\n";
	    }
	}
    } else {
	print "ERROR invalid file !!!\n";
    }
    close IF;
    return ($if_hour,$if_total,$if_last,$sum_hour,$sum_total,$sysclass,$fts);
}

# ==========================================================

sub LoadInterfacesHourData {
    #nactem kolik toho ma kterej user za hodinu
    open IF, "$STATFILE";
    while (<IF>) {
        my $lajna = $_;
        if ($lajna =~ /<interfacehourdata>/) {
            $lajna = <IF>;
            while ($lajna && !($lajna =~ /<\/interfacehourdata>/)) {
                my ($idc, $sc) = split (">", $lajna);
                my (undef, $id, undef, $mface) = split ("'", $idc);
                my ($send) = split ("<", $sc);
                $lajna = <IF>;
		#print "$mface $id $send\n";
		if (exists ($IF_HOUR->{$mface})) {
		    $IF_HOUR->{$mface}->{$id} = $send;
		} else {
		    $IF_HOUR->{$mface} = {};
		    $IF_HOUR->{$mface}->{$id} = $send;
		}
            }
        }
    }
    close IF;
}

sub GetInterfacesHourData ($) {
    my $face = shift;
    return $IF_HOUR->{$face};
}



1;
