#!/usr/bin/perl


# Includes --------------------------------------------------------------------

# Common stuff:

# Yell at me.
use strict;
use warnings;

# Database
use DBI;

# Email
use Email::MIME;
use Email::Sender::Simple qw(sendmail);

use POSIX qw(floor);

# Not so common stuff.
use IPC::System::Simple qw(capture); # We use IPC::System::Simple's capture
                                    # function instead of backticks. It
                                    # properly sanitizes arguments and does
                                    # proper error checking.


# Stuff you should configure --------------------------------------------------

my $mailfrom = '[email protected]';
my $mailto = '[email protected]';
my $servername = 'supercoolserver';

# Debug -----------------------------------------------------------------------

use Data::Dumper;

# Enable backtraces via Carp. Comment out this section if not needed.
# When enabled, the standard perl die() outputs a backtrace, which is much more
# useful than the standard die-message-only behavior.

use Carp 'verbose';
$SIG{ __DIE__ } = sub { Carp::confess( @_ ) };

# Globals ---------------------------------------------------------------------

my $dbh;
my $interactive;
my $self=$0;

# Subroutines -----------------------------------------------------------------

# Connects to the plesk database.
sub connect_to_db()
{
 my $db_password = capture('/bin/cat',qw(/etc/psa/.psa.shadow));
 chomp($db_password);
 $dbh = DBI->connect(
   'DBI:mysql:database=psa;host=localhost', #connection string
   'admin',            # username
   $db_password,       # password
   {'RaiseError' => 1} # options
 );
}

# Show usage
sub show_help()
{
 print "Usage: $self [options]\n\n";
 print "-i\tInteractive - Output in shell instead of email.\n";
 print "-h\tHelp - Display program help (this text).\n";
}

# Entry point -----------------------------------------------------------------

# Defaults
$interactive = 0;

# Parse commandline args
my $argc = $#ARGV;
for (my $argn = 0 ; $argn <= $argc ; $argn++)
{
 my $opt = $ARGV[$argn];
 if ($opt eq '-i')
 {
   $argn++;
   $interactive = 1;
 }
 else
 {
   show_help();
   exit 1;
 }
}

connect_to_db();

# Get results from db.
my $rs = $dbh->prepare('

 SELECT

   domains.name AS `domain`,
   domains.real_size AS `total`,
   Limits.value AS `allowed`,
   0 + disk_usage.httpdocs + disk_usage.httpsdocs + disk_usage.subdomains + disk_usage.web_users + disk_usage.webapps AS `web`,
   0 + disk_usage.mailboxes + disk_usage.maillists AS `mail`,
   0 + disk_usage.dbases AS `databases`,
   0 + disk_usage.logs AS `logs`,
   0 + disk_usage.anonftp + disk_usage.domaindumps + disk_usage.configs + disk_usage.chroot AS `other`

 FROM

   disk_usage

 INNER JOIN domains ON domains.id=disk_usage.dom_id
 INNER JOIN Limits ON Limits.id=domains.limits_id

 WHERE

   domains.overuse=true AND
   Limits.limit_name="disk_space"

 ORDER BY

   domains.real_size DESC

');
$rs->execute();

# Prepare table headers and stuff
my $num_processed = 0;
my $result_text = "Overuse data, all values in megabytes.\n\n";
my $colformat = "%49s | %-10s | %-11s | %-8s| %-8s | %-9s | %-8s | %-8s\n";
$result_text .= sprintf($colformat,'Domain','Total use','Allowed use','Website','Mail','Databases','Logs','Other');
$result_text .= "--------------------------------------------------+------------+-------------+---------+----------+-----------+----------+----------\n";

# Get results.
my $have_results = 0;
while (my $row = $rs->fetchrow_hashref())
{
 $have_results = 1;
 my $domain = $row->{'domain'};
 my $total_usage = floor($row->{'total'} / (1024**2));
 my $allowed_usage = floor($row->{'allowed'} / (1024**2));
 my $web_usage = floor($row->{'web'} / (1024**2));
 my $mail_usage = floor($row->{'mail'} / (1024**2));
 my $db_usage = floor($row->{'databases'} / (1024**2));
 my $log_usage = floor($row->{'logs'} / (1024**2));
 my $other_usage = floor($row->{'other'} / (1024**2));
 if ($allowed_usage == -1)
 {
   $allowed_usage = 'unlimited';
 }
 $result_text .= sprintf($colformat,$domain,$total_usage,$allowed_usage,$web_usage,$mail_usage,$db_usage,$log_usage,$other_usage);
}
$rs->finish;
$dbh->disconnect;

# If no results, exit now.
if ($have_results == 0)
{
 exit 0;
}

# In interactive mode, show results in shell,
# otherwise email results.
if ($interactive == 1)
{
 print "$result_text\n";
}
else
{
 my $message = Email::MIME->create(
   header_str => [
     From => $mailfrom,
     To   => $mailto,
     Subject => 'Overuse report ' . $servername
   ],
   attributes => {
     encoding => 'quoted-printable',
     charset => 'ISO-8859-1'
   },
   body_str => $result_text
 );
 sendmail($message);
}
exit 0;