#!/usr/bin/perl -T
#########################################################################################
# listsessions.pl
# Version 3.0.0
#
# Copyright 1997, 1998, 2004 Neil Harkins, William R. Thomas, Harlann Stenn,
# William W. Kimball Jr.
#
#      This file is part of popauth.
#
#      popauth is free software; you can redistribute it and/or modify
#      it under the terms of the GNU General Public License as published by
#      the Free Software Foundation; either version 2 of the License, or
#      (at your option) any later version.
#
#      popauth is distributed in the hope that it will be useful,
#      but WITHOUT ANY WARRANTY; without even the implied warranty of
#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#      GNU General Public License for more details.
#
#      You should have received a copy of the GNU General Public License
#      along with popauth; if not, write to the Free Software
#      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# This program generates an HTML report that lists all open POP-authorized relay
# sessions.  Be sure that $path_popauthspool accurately reflects the location of the IP
# authorization files that popauth outputs.
#
# Created by:  William W. Kimball Jr. <bkimball1@yahoo.com>
#########################################################################################
# vi: tabstop=3

# Pragmas
use warnings;
use strict;
use diagnostics;

my $now               = time();
my $now_nice          = &tstamp($now);
my $path_postfix      = "/etc/postfix/";
my $path_popauthspool = "/var/spool/popauth/authenticated/";
my $input             = "";
my $ip                = "";	# IP Address from which the user connects.
my $open_dt           = $now;	# Date-Time when they opened their POP session.
my $last_dt           = $now;	# Last Date-Time they refreshed their open POP session (last time they checked for new mail).
my $user              = "";
my $checks            = 0;
my $spread            = 0;
my $nice_spread       = "";
my $nice_open_dt      = "";
my $nice_last_dt      = "";
my $frequency         = 0.0;
my $nice_frequency    = "";
my $rownumber         = 0;
my $session_count     = 0;
my $nice_last_secs    = 0;
my @fields;
my @session_list;

# Open the report output stream.
print("Content-type: text/html\n\n");
print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
print("<html>\n");
print("<head>\n");
print("\t<title>Open POP Sessions Report For $now_nice</title>\n");
print("\t<meta http-equiv=\"content-type\" content=\"text/html; charset=iso-8859-1\">\n");
print("\t<meta http-equiv=\"content-language\" content=\"en-us\">\n");
print("\t<meta http-equiv=\"content-style-type\" content=\"text/css\">\n");
print("\t<meta http-equiv=\"Refresh\" content=\"60\">\n");
print("\t<meta name=\"robots\" content=\"noindex,nofollow\">\n");
print("\t<link rel=\"stylesheet\" href=\"/css/listreport.css\" media=\"screen\" type=\"text/css\">\n");
print("\t<link rel=\"stylesheet\" href=\"/css/printable.css\" media=\"print\" type=\"text/css\">\n");
print("</head>\n\n");
print("<body>\n");

# Get all filenames (IP addresses) to be added to authorization file.
opendir(DIR, $path_popauthspool);
@session_list = grep !/^\.\.?$/, readdir(DIR);
closedir(DIR);
$session_count = scalar @session_list;

# Open the repeat_list queue file.  First, make sure such a file exists...
if (0 < $session_count) {
	print("<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">\n");
	print("\t<tr>\n");
	print("\t\t<th>#</th>\n");
	print("\t\t<th colspan=\"6\">IP Address</th>\n");
	print("\t</tr>\n");
	print("\t<tr>\n");
	print("\t\t<th>&nbsp;</th>\n");
	print("\t\t<th>User</th>\n");
	print("\t\t<th>Hits</th>\n");
	print("\t\t<th>Hit Rate</th>\n");
	print("\t\t<th>Session Opened</th>\n");
	print("\t\t<th>Last Checked</th>\n");
	print("\t</tr>\n");

	foreach $ip (@session_list) {
		if($ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
			++$rownumber;

			if (open(SESSION, "< " . $path_popauthspool . $ip)) {
				print("\t<tr>\n");
				print("\t\t<td>$rownumber</td>\n");
				print("\t\t<td colspan=\"6\"><b>$ip</b></td>\n");
				print("\t</tr>\n");

				while ($input = <SESSION>) {
					chomp($input);
					@fields  = split(/\t/, $input);
					$user    = $fields[0];
					$open_dt = $fields[1];
					$last_dt = $fields[2];
					$checks  = $fields[3];
					$spread  = $last_dt - $open_dt;
					$frequency = $spread / $checks;
					$nice_spread  = pretty_seconds($spread);
					$nice_open_dt = &tstamp($open_dt);
					$nice_last_dt = &tstamp($last_dt);
					$nice_frequency = pretty_seconds($frequency);
					$nice_last_secs = pretty_seconds($now - $last_dt);

					print("\t<tr class=\"oddrow\">\n");
					print("\t\t<td>&nbsp;</td>\n");
					print("\t\t<td><a href=\"mailto:$user\">$user</a></td>\n");
					print("\t\t<td>$checks</td>\n");
					print("\t\t<td>$nice_frequency</td>\n");
					print("\t\t<td>$nice_open_dt (<b>$nice_spread</b> old)</td>\n");
					print("\t\t<td>$nice_last_dt ($nice_last_secs ago)</td>\n");
					print("\t</tr>\n");
				}

				close(SESSION);
			}
		}
	}

	print("</table>\n");
}
else {
	print("<p>The $path_popauthspool spool contains no open sessions. Please try again later.</p>\n");
}

# Close the HTML report.
print("</body>\n");
print("</html>\n");

exit(0);

#########################################################################################
# tstamp
#
# Returns a formatted date/time stamp.
#
# Receives:
#   OPTIONAL:  A date-time value to format.  time() is used if this is not provided.
# Returns:
#   A formatted version of the date-time value.
#########################################################################################
sub tstamp {
	my $datetime = time();

	# Read an arbitrary time value from the argument list, if provided.
	if (@_ > 0) {
		$datetime = $_[0];
	}

	use POSIX qw(strftime);
	return(POSIX::strftime("%b %d %H:%M:%S", localtime($datetime)));
}

#########################################################################################
# pretty_seconds
#
# Returns a formatted count of seconds parsed into weeks, days, hours, minutes, and
# remaining seconds.
#
# Receives:
#   A number of seconds to format.
# Returns:
#   A formatted version of the number of seconds in "Xw Xd Xh Xm Xs" format.
#########################################################################################
sub pretty_seconds {
	my $bigseconds = $_[0];
	my $weeks = 0;
	my $days = 0;
	my $hours = 0;
	my $minutes = 0;
	my $seconds = 0;
	my $pretty = "";

	$weeks   = int($bigseconds / (7 * 24 * 60 * 60));
	$seconds = int($bigseconds % (7 * 24 * 60 * 60));
	$days    = int($seconds / (24 * 60 * 60));
	$seconds = int($seconds % (24 * 60 * 60));
	$hours   = int($seconds / (60 * 60));
	$seconds = int($seconds % (60 * 60));
	$minutes = int($seconds / 60);
	$seconds = int($seconds % 60);

	$pretty = (($weeks > 0) ? $weeks . "w " : "") .
				 ((($weeks > 0) || ($days > 0)) ? $days . "d " : "") .
				 ((($weeks > 0) || ($days > 0) || ($hours > 0)) ? $hours . "h " : "") .
				 ((($weeks > 0) || ($days > 0) || ($hours > 0) || ($minutes > 0)) ? $minutes . "m " : "") .
				 $seconds . "s";

	return($pretty);
}
