#!/usr/bin/perl -w
#########################################################################################
#
#   Author:          G.K. Grubert (grubert@physik.uni-greifswald.de)
#   Version:         1.2
#   Last modified:   Jul 2008
#   License:         GPLv2
#
#########################################################################################


use strict;
use warnings;
use Getopt::Std;
use GD::Graph::pie;
use CGI qw(:standard -no_undef_params *table);

# Global variables
use vars qw(@name_master @name_alias $log_1 $log_2 @printer_tmp @user_tmp @info);


# Command Line Options
#########################################################################################

my (%opt,$PAGELOG,$ALIAS,$OUTPATH,$OUTFILE,$use_alias,$help);
getopt("a:f:h:o:p",\%opt);

if (exists $opt{'f'}){$PAGELOG = $opt{f}}
else{$PAGELOG = '/var/log/cups/page_log'}

if (exists $opt{'a'}){$ALIAS = $opt{a}; $use_alias = 1;}
else{$use_alias = 0}

if (exists $opt{'p'}){$OUTPATH = $opt{p}}
else{$OUTPATH = '/tmp'}

if (exists $opt{'o'}){$OUTFILE = $opt{o}}
else{$OUTFILE = '/tmp/pages'}

if (exists $opt{'h'}){$help = 1}
else{$help = 0}

if ($help){
    print "Cups page_log analyzer 1.2 (Jul 2008)
-------------------------------------\n
pagelog_analyzer.pl [-afhop]\n
-h print this help screen
-a alias file for usernames (default: none)
-p outputpath for gif-files (default: /tmp)
-o html-outfile, enter WITHOUT .html!!! (default: /tmp/pages.html)
-f page_log file (default: /var/log/cups/page_log)\n\n";
    exit(0);
}


# Main Program
#########################################################################################

# Test, if aliases have to be used
read_alias($ALIAS) if ($use_alias);

# Read the cups page_log file
read_logfile($PAGELOG,$use_alias);

# Order user output alphabetically
@user_tmp = dummy_sort();

# File output of calculated statistics
print_statistics();

exit(0);


# read alias file
#########################################################################################
sub read_alias{
    my $ALIASFILE = shift;

    # Test of Alias-File
    if (-e $ALIASFILE){}else{print 'No alias file given.'."\n"; exit(0);}

    open(AL,$ALIASFILE);
    while(<AL>){
        my $linedummy = $_;
        my @dummy = split(' ',$linedummy);
        # Infos saved in @dummy
        # [0]   master name
        # [1]   alias name
        push(@name_master,$dummy[0]);
        push(@name_alias,$dummy[1]);
    }
    close(AL);
}# read_alias

# Test, if alias exists for given argument
# Output: new Name
#########################################################################################
sub test_alias{
	my $name = shift;
	my $u_i;
	my $name_final;

	my $found = 0;my $i = 0;
	foreach my $tmp (@name_alias){
		if ($name eq $tmp){
			$found = 1;
			$u_i = $i;
		}
		$i++;
	}
	if ($found){$name_final = $name_master[$u_i]}
	else{$name_final = $name}
	return($name_final);
}# test_alias

# File output of statistics
#########################################################################################
sub print_statistics{
    my ($i,$j);
    my @page_printer;

    # Count printed pages per printer
    $i = 0;
    foreach my $tmp_p (@printer_tmp){
        my $page_total = 0;
        $j = 0;
        foreach my $tmp_u (@user_tmp){
            $page_total += $info[$i][$j];
            $j++;
        }
        $page_printer[$i] = $page_total;
        $i++;
    }

    # Open outfile
    open(OUT,">$OUTFILE.html");

    # Create html-Header
    htmlheader();

    $i = 0;
    foreach my $tmp_p (@printer_tmp){
        print OUT hr;
        print OUT 'Printer '.b($tmp_p).':&nbsp;&nbsp;'.
                  $page_printer[$i].' pages printed on this device',br,br;

        print OUT start_table(),'<tr><td>';
        print OUT start_table(),'<tr>';
        print OUT th({-width=>100,style=>'background-color:#ffffff;'},['']),
                  th({-width=>150},['user']),
                  th({-width=>75},['pages']),
                  th({-width=>75},['%']);

        $j = 0;
        my @yvals=();
        foreach my $tmp_u (@user_tmp){
            my $tmp_percent = $info[$i][$j]/$page_printer[$i]*100;
            $tmp_percent = sprintf("%.2f",$tmp_percent);
            my $style = '';
            $style = 'background-color:#dddddd;' if ($j % 2 != 0);
            print OUT Tr([td(['']).
                          td({-style=>$style},[$tmp_u]).
                          td({-style=>$style,-align=>'right'},[$info[$i][$j]]).
                          td({-style=>$style,-align=>'right'},[$tmp_percent])]);
            push(@yvals,$info[$i][$j]);
            $j++;
        }
        print OUT "</table></td>";

        my $graph = GD::Graph::pie->new();
        my $format = $graph->export_format();
        open(MYGIF,">$OUTPATH/$printer_tmp[$i].gif");
        binmode MYGIF;
        print MYGIF $graph->plot([\@user_tmp,\@yvals])->$format;
        close(MYGIF);
        print OUT td(['&nbsp;&nbsp;&nbsp;'.img({-src=>$printer_tmp[$i].'.gif',-alt=>$printer_tmp[$i]})]);
        print OUT '</tr></table>';
        $i++;
    }
    print OUT "<hr>";
    print OUT span({-class=>'small'},['Report created '.get_current_time().br.
                                      'Script written by G.K. Grubert, Version 1.2, Jul 2008']);

    # Create html-Footer
    end_html();

    # Close Outfile
    close(OUT);
}# print_statistics

# Sort users alphabetically
#########################################################################################
sub dummy_sort {
	my @user_copy;
	my @info_copy;

	# Copy user list
	foreach my $tmp (@user_tmp){push(@user_copy,$tmp)}

	# Copy page array
	my $p = 0;
	foreach my $tmp_p (@printer_tmp){
		my $i=0;
		foreach my $tmp_u (@user_tmp){
			if ($info[$p][$i]){$info_copy[$p][$i] = $info[$p][$i]}
            else{$info_copy[$p][$i] = 0}
			$i++;
		}
		$p++;
	}

	# Sort user list (original)
	my @user_tmp = sort(@user_copy);

	# Sort printed pages to new list position (for each printer)
	$p = 0;
	foreach my $tmp_p (@printer_tmp){
		my $j = 0;
		foreach my $u_new (@user_tmp){
			my $i = 0;
			foreach my $u_old (@user_copy){
                $info[$p][$j] = $info_copy[$p][$i] if ($u_old eq $u_new);
				$i++;
			}
			$j++;	
		}
		$p++;
	}
	return(@user_tmp);
}# dummy_sort

# Create the page statistics
#########################################################################################
sub create_statistics{
	my $printer = shift;
    my $user = shift;
    my $pages = shift;

	my $p_i = -1;
	my $u_i = -1;

	# Find printer in printer list and find the index number
	my $i = 0;
	foreach my $tmp (@printer_tmp){
		$p_i = $i if ($tmp eq $printer);
		$i++;
	}

	# Find user in user list and find the index number
	$i = 0;
	foreach my $tmp (@user_tmp){
		$u_i = $i if ($tmp eq $user);
		$i++;
	}

	# Test index numbers (has to be greater zero)
	if (($p_i < 0) or ($u_i < 0)){
		print 'ERROR in Array-Index'."\n";
		exit(0);
	}

	# Add new pages to previous page counter
    $info[$p_i][$u_i] = 0 if(!$info[$p_i][$u_i]);
	$pages = $info[$p_i][$u_i] + $pages;
	# Set new page counter
	$info[$p_i][$u_i] = $pages;
}# create_statistics

# Read the cups page_log file
#########################################################################################
sub read_logfile{
    my $PAGELOGFILE = shift;
    my $use_alias = shift;

    # Test of logfile
    if (-e $PAGELOGFILE){
        my $size = -s $PAGELOGFILE;
        if ($size == 0){print 'page_log file empty.'."\n"; exit(0);}
    }
    else{print 'page_log file not found.'."\n"; exit(0);}

    my $i = 0;
    open(IN,$PAGELOGFILE);
    while(<IN>){
        my $linedummy = $_;
        my @dummy = split(' ',$linedummy);
        # Data stored in @dummy
        # [0]   printer
        # [1]   user
        # [2]   job-id
        # [3]   date
        # [4]   time-different to GMT
        # [5]   page
        # [6]   how many copies

        # Set first and last date of the logfile
        $log_1 = $dummy[3].$dummy[4] if ($i == 0);
        $log_2 = $dummy[3].$dummy[4];

        # Convert usernames in small letters
        $dummy[1] = lc($dummy[1]);

        # Test user alias
        $dummy[1] = test_alias($dummy[1]) if ($use_alias);

        # Modify printer and user list
        build_array($dummy[0],'p');
        build_array($dummy[1],'u');

        # Add data to statistics
        create_statistics($dummy[0],$dummy[1],$dummy[6]);
        $i++;
    }
    close(IN);
}# read_logfile

# Create/modify printer/user list
#########################################################################################
sub build_array{
    my $testvalue = shift;
    my $which = shift;

    # Which defines, which List to use
    # p: Printer
    # u: User
    my $found = 0;
    if ($which eq 'p'){
        foreach my $tmp (@printer_tmp){$found = 1 if ($testvalue eq $tmp)}
        push(@printer_tmp,$testvalue) if (!$found);
    }
    if ($which eq 'u'){
        foreach my $tmp (@user_tmp){$found = 1 if ($testvalue eq $tmp)}
        push(@user_tmp,$testvalue) if (!$found);
    }
}
# End built_array
#########################################################################################

# Create html header
#########################################################################################
sub htmlheader{
	print OUT start_html(-title=>'Printing Statistics',
                         -style=>{'src'=>'/usr/share/cups-pagelog-analyzer/main.css'}),
              p({-class=>'title'},['Printing Statistics'.br.$log_1.'-'.$log_2]);
}# htmlheader

# Get the actual Time and Date
#########################################################################################
sub get_current_time {
	# Get the all the values for current time
	my ($Second,$Minute,$Hour,$Day,$Month,$Year,$WeekDay,$DayOfYear,$IsDST) = localtime(time);

	# Fix Time-Output
	my $RealMonth = $Month+1; # Months of the year are not zero-based
	if ($RealMonth < 10){
		# add a leading zero to one-digit months
		$RealMonth = '0'.$RealMonth; 
	}
	if ($Day < 10){
		$Day = '0'.$Day; # add a leading zero to one-digit days
	}
	my $Fixed_Year = $Year+1900;
	if ($Hour < 10){
		$Hour = '0'.$Hour; # add a leading zero to one-digit hours
	}
	if ($Minute < 10){
		# add a leading zero to one-digit minutes
		$Minute = '0'.$Minute; 
	}
	if ($Second < 10){
		# add a leading zero to one-digit seconds
		$Second = '0'.$Second; 
	}

	# Create new Time/Date-String
	my $current_time = "$Fixed_Year-$RealMonth-$Day, $Hour:$Minute:$Second";
    return($current_time);
}# get_current_time
