HEX
Server: Apache
System: Linux vps.rockyroadprinting.net 4.18.0 #1 SMP Mon Sep 30 15:36:27 MSK 2024 x86_64
User: rockyroadprintin (1011)
PHP: 8.2.29
Disabled: exec,passthru,shell_exec,system
Upload Files
File: //dev/shm/rctmp
ggsession="$$"
#!/bin/bash
#Global Variables
version="1.5a \"GGVPS Troubleautomagic - Support Dev Edition\""
G="\e[30;48;5;82m"
CYAN="$(tput setaf 6)"
M="$(tput setaf 5)"
B="\e[48;5;196m"
CLEAR="\033[0m"
NC=$(tput sgr0)

if [[ -f mrun ]]; then 
alias ggexit="kill -1 $$"
rm -rf mrun
else
alias ggexit="kill -1 $ggsession"
fi

PATH=$PATH:/scripts/

#Setting Hostname Variables
if [[ -f /usr/bin/hostname ]];then
	HOSTNAMEBIN=/usr/bin/hostname
elif [[ -f /bin/hostname ]];then
	HOSTNAMEBIN=/bin/hostname
else
	HOSTNAMEBIN=hostname
fi

#Set Variables for node/container
vzCTID=`awk '{print $1}' /proc/vz/veinfo`
#vzNODE=`traceroute -T -N1 -m1 -q1 -w0 8.8.8.8|grep -v traceroute|head -n1|tail -n1|awk '{print $2}'| awk -F'.' '{print $1}'`

OS=$(rpm -E %{rhel})

#PS1 Fix for Dual Bash
PS1="[\u@\h \W]\$ "

#Display/CTA Functions
function good() {
GREEN='\033[0;32m'
echo -e  "${GREEN}\xE2\x9C\x94 $1${NC} "
}

function good2() {
echo "$G $1 $CLEAR"
}

function bad() {
RED='\033[0;31m'
echo -e "${RED}X $1${NC}"
}

function bad2() {
echo "$B $1 $CLEAR"
}

function SOUT(){
printf "[$1]\n"
printf "$2\n"
}

#Script Functions
alias sushell='whmapi1 modifyacct user=$(stat -c %U .) HASSHELL=1 && su $(stat -c %U .)'
alias summary='wget -O summary.php https://dl.websitehostserver.net/vps-files/summary.txt;php summary.php'
alias ll='ls -lAh --color'
alias ls='ls --color'
alias fixlicense='/usr/local/cpanel/cpkeyclt'
alias exit='echo "You must use ggexit to close this session."'
alias logout='echo "You must use ggexit to close this session."'
alias install-softaculous='curl https://dl.websitehostserver.net/vps-files/softaculous_install.sh.txt | bash'
alias exim-security="cat /etc/exim.conf | grep -E 'openssl_options|tls_require_ciphers'"

function enable-root(){
sed -i s/"PasswordAuthentication no"/"PasswordAuthentication yes"/g /etc/ssh/sshd_config
sed -i s/"PermitRootLogin without-password"/"PermitRootLogin yes"/g /etc/ssh/sshd_config
service sshd restart
echo "Root access has been enabled."
}

function disable-root(){
sed -i s/"PasswordAuthentication yes"/"PasswordAuthentication no"/g /etc/ssh/sshd_config
sed -i s/"PermitRootLogin yes"/"PermitRootLogin without-password"/g /etc/ssh/sshd_config
service sshd restart
echo "Root access has been disabled."
}

#### TOPS Req. Functions #####
    # Function to show the biggest files and directories
    show_biggest() {
        echo "Top $1 biggest $2 in $3:"
        du -ah --threshold=100M --max-depth=1 "$3" | sort -rh | head -n $1 | awk '{printf "%-50s %s\n", $2, $1}'
        echo ""
    }

    # Function to display usage information
    display_usage() {
        echo "Usage: tops [number_of_files] -d <directory>"
        echo "Options:"
        echo "  -h     Display usage information"
        echo "  -d     Specify the directory to view the largest files/directories"
    }
##############################


tops() {
# Script Name: top.sh
# Author: Keith M
# Description: A script to display the top largest files and directories in a specified directory.
# Usage: tops [number_of_files] -d <directory>
# Version: 0.2
# Options:
#   -h     Display usage information
#   -d     Specify the directory to view the largest files/directories

#exit hack by Catie
do_nothing=false

    # Check if the -h flag is used for usage information
    if [ "$1" == "-h" ]; then
        display_usage
        do_nothing=true
    fi

    if [ "$do_nothing" == false ]; then
        # Check if the -d flag is used
        if [ "${1:0:2}" == "-d" ]; then
            if [ -z "$2" ]; then
                display_usage
                do_nothing=true
            fi
            directory="$2"
            num_files=10
            show_biggest "$num_files" "files and directories" "$directory"
            do_nothing=true
        fi
    fi

    if [ "$do_nothing" == false ]; then
        # Check if the number of files is provided
        if [ "$#" -ge 1 ] && [ "$1" -gt 0 ]; then
            num_files="$1"
            shift # Remove the first argument (number_of_files) from the arguments list
        else
            num_files=10
        fi

        # Check if the -d flag is used and a directory is provided
        if [ "$#" -ge 2 ] && [ "$1" == "-d" ]; then
            if [ -z "$2" ]; then
                display_usage
                do_nothing=true
            fi
            if [ "$do_nothing" == false ]; then
                directory="$2"
                show_biggest "$num_files" "files and directories" "$directory"
            fi
        else
            # Show the top number of files in the /home/ and /backup/ directories
            for user_dir in /home/*; do
                if [ -d "$user_dir" ] && [ "$(basename "$user_dir")" != "virtfs" ] && [ "$(basename "$user_dir")" != "csf" ]; then
                    show_biggest "$num_files" "files and directories" "$user_dir"
                fi
            done

            # Show the top number of files in the /backup/ directory
            show_biggest "$num_files" "files and directories" "/backup/"
        fi
    fi
}


function ec(){
# Pass all arguments to the Perl script using command substitution
  perl_result="$(perl - "$@" <<'EOF'
#################################################################
# ecpp_3.pl - Updated by RJ
# Utility to parse and generate statistics from mail logs.
#
#################################################################


my $version = "20230512";

use strict;
use warnings;
use Time::Local;
use Time::localtime;
use POSIX qw(strftime);
use File::stat;
use Getopt::Long;
use IO::Uncompress::Gunzip;
use FileHandle;

sub usage;
sub findmailcreation;
sub populatedomainmap;
sub populateownermap;
sub getsearchusers;
sub getfixedlogins;
sub mailcount;
sub eximlogstart;
sub processeximlogs;
sub recordsample;
sub addemail;
sub parseeximline;
sub commify;
sub printtotals;
sub formatsample;
sub printsamples;
sub printhourly;
sub printsendaddr;
sub printsendlog;
sub printcwd;
sub printsubs;
sub printrecaddr;
sub printexim;
sub printtimerange;
sub maillogstart;
sub processmaillogs;
sub parsemailline;
sub pseudoui;
sub get_homedir;

$| = 1; #turn on autoflush of stdout (allows progress code to work correctly)

# begin maincode

print "ecpp_2.pl - Version: $version \n\n";

my $starthours = 48;
my $endhours = 0;
my $days = 0;

my $resellermode = 0;
my $findemailcreate = 0;
my $imappopips = 1;
my $tos = 0;
my $terse = 1;
my $lowmem = 0; # skip recording of recipient/topic/sender info for memory/cpu constrained servers

# grab the timezone offset, so that we can make timegm work right (it's much faster than timelocal)

my @time = CORE::localtime(time);
my $offset = timegm(@time) - timelocal(@time);

# grab command line options

GetOptions ('shours|s|hours|h=i' => \$starthours,
            'ehours|e=i' => \$endhours,
            'days|d=i' => \$days,
            'reseller|r' => \$resellermode,
            'create|c' => \$findemailcreate,
            'ips|i=i' => \$imappopips,
            'terse|t=i' => \$terse,
            'lowmem|l|fast|f' => \$lowmem);

if (!exists $ARGV[0]) { #quick check to make sure we have an argument
    usage();
} elsif ($findemailcreate) {
    findmailcreation($ARGV[0]);
} else {
    mailcount($ARGV[0], $starthours, $endhours, $days, $resellermode, $imappopips, $tos);
}

exit 0;

# end maincode

sub usage {
print <<EOU;
No argument provided.

Default usage, assumes you wish to parse the last 48 hours of logs:

   # ec <username>
   # ec <domain>

Parse the last <hours> hours worth of logs:

   # ec -h <hours> <user or domain>
   # ec --hours=<hours> <user or doman>

Parse between the last <start hours> and <end hours> marks:

   # ec -s <start hours> -e <end hours> <user or doman>
   # ec --shours=<start hours> --ehours=<end hours> <user or doman>

Parse for the last <days> day period:

   # ec -d <days>
   # ec --days=<days>

Search across all users for a reseller:

   # ec --reseller <reseller account>
   # ec -r <reseller account>

Search for the log excerpt and creation time of an email address:

   # ec -c <email address>

Some example use cases:

   # ec teammast
   # ec --hours=48 teammast
   # ec -s 48 -e 24 teammast
   # ec -h 48 -r mrowner
   # ec -c alex\@rugbysuccess.com

EOU
}

sub findmailcreation {
    my $emailaddress = $_[0];
    my $cparchlogp = "/usr/local/cpanel/logs/archive";
    my @cplogs= ("/usr/local/cpanel/logs/access_log");

    my ($emailuser, $emaildomain) = ($emailaddress =~ /^([^@]*)[\+@](.*)$/);

    if ($emailuser && $emaildomain) {
        print "Finding the creation time of: $emailaddress\n";
        print "User: $emailuser\n";
        print "Domain: $emaildomain\n\n";

        # add archived cpanel logs to list

        opendir(my $archivedh, $cparchlogp);

        while(my $file = readdir($archivedh)) {
            if ($file =~ /access_log-.*?\.gz/) {
                push (@cplogs, "$cparchlogp/$file");
            }
        }

        closedir($archivedh);

        @cplogs = sort { stat($b)->mtime <=> stat($a)->mtime } @cplogs;

        # search through logs for creation

        my $createrex = "addpop&email=$emailuser&password=__HIDDEN__&quota=[^&]*&domain=$emaildomain&";
        my $found = 0;

        foreach my $file (@cplogs) {
            print "Processing: $file\n";

            my $progress = -1;
            my $filesize = stat($file)->size;

            my $fh = new FileHandle;
            $fh->open("<$file");

            my $fhp;

            if ($file =~ /^.*?\.gz$/) {
                $fhp = new IO::Uncompress::Gunzip $fh;
            } else {
                $fhp = $fh;
            }

            my $istty = (-t STDOUT);

            while(my $line = <$fhp>) {
                if($line =~ /$createrex/) {
                    print "\nCreation of email address found: \n\n$line";

                    $found = 1;
                    last;
                }

                if (int((tell($fh) / $filesize) * 100 ) > $progress){ #prevent a billion slow i/o calls
                    $progress = int((tell($fh) / $filesize) * 100 );

                    if ($istty) {
                        print "\r               \rProgress: $progress%"; #replace prev line with new progress
                    } else {
                        if (($progress == 0) || ($progress % 10 == 0)) {
                            print "$progress%";
                        } else {
                            print ".";
                        }
                    }
                }
            }

            $fh->close();

            print "\n";

            if ($found) {
                last;
            }
        }



    } else {
        print "Invalid email address provided.\n";
    }
}

# populate user2domain and domain2user maps

sub populatedomainmap {
    my $userpath = "/etc/userdomains";

    my %user2domain = (); # hash of arrays for user -> domains map
    my %domain2user = (); # hash for domain -> user map

    open (USERDOMAINS, $userpath) or die;

    while (my $line = <USERDOMAINS>) {
        chomp($line); # Kill trailing whitespace/newline
        my @temp = split(": ", $line); # userdomains format is "domain.com: user"

        $domain2user{ $temp[0] } = $temp[1];
        push @{ $user2domain{ $temp[1]} }, $temp[0];
    }

    close (USERDOMAINS);

    return (\%user2domain, \%domain2user);
}

sub populateownermap {
    my %owner2user = (); # hash for owner -> user map
    my $tuopath = "/etc/trueuserowners";

    open (TUOWNER, $tuopath) or die;

    while (my $line = <TUOWNER>) {
        chomp($line); # Kill trailing whitespace/newline

        if ($line =~ /^.*?:\s.*?$/) {
            my @temp = split(": ", $line); # trueuserowners format is "user: owner"

            push @{ $owner2user{ $temp[1]} }, $temp[0];
        }
    }

    close (TUOWNER);

    return %owner2user;
}

sub getsearchusers {
    my ($baseowner, $reseller, $user2domain_r) = @_;
    my @searchusers;

    # if reseller mode was specified, add sub-accounts to checklist, otherwise just add the user

    if ($baseowner eq "root") { # if we are root, add all the users to the list
        print "Entire Server Mode.\n";

        for my $user (keys %{$user2domain_r}) {
            push (@searchusers, $user);
        }
    } elsif ($reseller) {
        print "Reseller Mode.\n";

        my %owner2user = populateownermap();

        if (!(exists $owner2user{$baseowner})) {
            print "$baseowner does not appear to be a reseller.\n";
        } else {
            foreach (@{$owner2user{$baseowner}}) {
                push(@searchusers, $_);
            }
        }
    } else {
        print "Single User Mode.\n";

        push (@searchusers, $baseowner);
    }

    return @searchusers;
}

sub getfixedlogins {
    my ($sur, $u2sr) = @_;

    my @searchusers = @{$sur};
    my %user2domain = %{$u2sr};

    my %fixedloginsh;

    foreach my $user (@searchusers) {
        $fixedloginsh{$user} = undef;

        print "\nEmail accounts per domain owned by $user:\n";

        foreach my $domain (@{$user2domain{$user}}) {
            my $count = 0;

            if(open(SHADOW, "< ".get_homedir($user)."/etc/$domain/shadow")) {
                while (<SHADOW>) {
                    $count++;
                }

                close(SHADOW);
            }

            print "\t$domain: $count\n";

            $fixedloginsh{$domain} = undef;
        }
    }

    return \%fixedloginsh;
}

sub mailcount {
    my ($arg, $starthours, $endhours, $days, $reseller, $imappopips, $tos) = @_;

    # check to see if the argument were were provided us a user or domain

    my $baseowner;

    my ($user2domainr, $domain2userr) = populatedomainmap();
    my %user2domain = %{$user2domainr};
    my %domain2user = %{$domain2userr};

    $arg = lc($arg);

    if (exists ($user2domain{$arg}) || ($arg eq "root")) {
        $baseowner = $arg;

        print "$arg is a USER.\n";
    } elsif (exists $domain2user{$arg}) {
        $baseowner = $domain2user{$arg};

        print "$arg is a DOMAIN.\n";
        print "$arg is owned by USER $domain2user{$arg}\n";
    } else {
        print "$arg appears to be nothing useful, quitting.\n";
        return;
    }

    if ($days) {
        $starthours = ($days * 24);
        $endhours = 0;
    }

    if ($endhours > $starthours) { #sanity check
        print "Invalid time range, ends before it starts. Assuming you were confused, swapping.\n";

        ($starthours, $endhours) = ($endhours, $starthours);
    }

    my $currentTime =  time;
    my $endTime = $currentTime - ($endhours * 3600);
    my $startTime = $currentTime - ($starthours * 3600);


    my @searchusers = getsearchusers($baseowner, $reseller, \%user2domain);
    my $fixedlogins_r = getfixedlogins(\@searchusers, \%user2domain);

    print "\n";

    my %ipaddr; # ip addresses logging in via POP/IMAP

    if ($imappopips) {
        my ($ipaddr_r) = processmaillogs(\@searchusers, $fixedlogins_r, $startTime, $endTime);
        %ipaddr = %{$ipaddr_r};
    }

    my ($totec_r, $trec_r, $fsp_r, $lsp_r, $cnt_r, $raddr_r, $slog_r, $saddr_r, $mid_r, $bcnt_r, $bcnt_h_r,
        $cwd_r, $sub_r, $usercnt_r, $userraddr_r, $bcnt_rec_r)
        = processeximlogs(\@searchusers, $fixedlogins_r, \%ipaddr, $startTime, $endTime);

    my $totec = ${$totec_r}; # total email count
    my $trec = ${$trec_r}; # true email count (multiple recipients separated)
    my @fsp = @{$fsp_r}; # first samples
    my @lsp = @{$lsp_r}; # last samples
    my %cnt = %{$cnt_r}; # per user count
    my %raddr = %{$raddr_r}; # receiving addresses
    my %slog = %{$slog_r}; # sender logins
    my %saddr = %{$saddr_r}; # sender addresses
    my %mid = %{$mid_r};

    my %cwd = %{$cwd_r}; # current working directories
    my %sub = %{$sub_r}; # subjects
    my %usercnt = %{$usercnt_r}; # per user count
    my %userraddr = %{$userraddr_r}; #per user count recipients

    my %bcnt = %{$bcnt_r};
    my %bcnt_h = %{$bcnt_h_r};
    my %bcnt_rec = %{$bcnt_rec_r};


    print "\n"; print '-' x25 . "\n\n";

    pseudoui($baseowner); print "\n";

    print '-' x25 . "\n\n";

    printtimerange($startTime, $endTime);
    printtotals($trec, \%raddr, \%bcnt, \%bcnt_rec);
    printhourly(\%cnt, \%bcnt_h, \%usercnt, \%slog, \%userraddr);

    unless($lowmem) {
        printsendaddr(\%saddr);
        printsendlog(\%slog);
    }

    printcwd(\%cwd);

    unless($lowmem) {
        printrecaddr(\%raddr);
        printsubs(\%sub);
    }

    printsamples(\@fsp, \@lsp);
    printexim(\%saddr);
}

sub eximlogstart {
    my ($file) = @_;

    my $fh = new FileHandle;
    $fh->open("<$file");

    my $fhp;

    if ($file =~ /^.*?\.gz$/) {
        $fhp = new IO::Uncompress::Gunzip $fh;
    } else {
        $fhp = $fh;
    }

    my $time;

    while(my $line = <$fhp>) {
        if ($line =~ /(\d{4})\-(\d{2})\-(\d{2})\s(\d{2}):(\d{2}):(\d{2})\s/) {
            $time = timelocal($6, $5, $4, $3, $2 - 1, $1);
            last;
        }
    }

    $fh->close();

    return $time;
}

sub processeximlogs {
    my ($searchusers_r, $fixedlogins_r, $ipaddr, $startTime, $endTime) = @_;
    my @searchusers = @{$searchusers_r};

    # specify logs to search

    my @eximlogs = @{findlogs('/var/log', 'exim_mainlog((-\d{8})|(\.\d))?(\.gz)?')};

    # setup hashes, arrays, and variables for collected data

    my $totec = 0; # total email count
    my $trec = 0; # true email count (multiple recipients separated)
    my @fsp; # first samples
    my @lsp; # last samples
    my %cnt; # per user count
    my %raddr; # receiving addresses
    my %slog; # sender logins
    my %saddr; # sender addresses
    my %mid; # exim mail ids
    my %cwd; # current working directories
    my %sub; # subjects
    my %usercnt; #per user count
    my %userraddr; #per user count recipients
    my %m_rec; #per id recipients

    my %bcnt; # bounces
    my %bcnt_h; # hourly bounces
    my %bcnt_rec; # bounced recipients


    foreach my $file (@eximlogs) {
        if (my $eximt = eximlogstart($file)) {
            print "Processing '$file'.\n";

            # makes sure the log contains the time we want to check

            if ($startTime < $eximt) {
                print "Start time pre-dates log, ";

                if ($endTime < $eximt) {
                    print "checking next log.\n";
                    next;
                } else {
                    print "but end time is present, checking anyways.\n";
                }
            }

            # open file and parse lines

            my $progress = -1;
            my $filesize;

            # this is totally a hack, but way faster than the pure perl way of doing it

            my $fh;

            if ($file =~ /^.*?\.gz$/) {
                open($fh, "-|", "zcat " . $file);
                my $gziplist=`gzip -l $file`;
                $gziplist=~/.\n\s*\d*\s*(\d*)/;
                $filesize=$1;
            } else {
                $fh = FileHandle->new("<$file");
                $filesize = stat($file)->size
            }

            my $istty = (-t STDOUT);
            my $pos = 0;

            while (my $line = <$fh>) {
                parseeximline(\$line, $startTime, $endTime, $fixedlogins_r, $ipaddr, \$totec, \$trec, \@fsp, \@lsp, \%cnt, \%raddr, \%slog,
                              \%saddr, \%mid, \%bcnt, \%bcnt_h, \%cwd, \%sub, \%usercnt, \%userraddr, \%m_rec, \%bcnt_rec);

                $pos += length($line);
                my $new_progress = int(($pos / $filesize) * 100);

                if ($new_progress > $progress){ #prevent a billion slow i/o calls
                    $progress = $new_progress;

                    if ($istty) {
                        print "\r               \rProgress: $progress%"; #replace prev line with new progress
                    } else {
                        if (($progress == 0) || ($progress % 10 == 0)) {
                            print "$progress%";
                        } else {
                            print ".";
                        }
                    }
                }
            }

            $fh->close();

            print "\n";

            if ($startTime >= $eximt) {
                last; # start time is in current log, we are done checking
            }
        }
    }

    return (\$totec, \$trec, \@fsp, \@lsp, \%cnt, \%raddr, \%slog, \%saddr, \%mid, \%bcnt, \%bcnt_h,
            \%cwd, \%sub, \%usercnt, \%userraddr, \%bcnt_rec);
}

sub findlogs {
    my ($directory, $rex) = @_;
    my @files;

    opendir(my $dh, $directory);

    while(my $file = readdir($dh)) {
        if ($file =~ /$rex/) {
            push (@files, $directory.'/'.$file);
        }
    }

    closedir($dh);

    @files = sort {stat($b)->mtime <=> stat($a)->mtime} @files;
    return \@files;
}

sub recordsample {
    my ($fsp_r, $lsp_r, $time, $line_r) = @_;

        my @sample = ($time, $line_r);

    if ((scalar @{$fsp_r}) <= 0){
        push @{$fsp_r}, \@sample;
    } else {
        if ($time <= ${${$fsp_r}[0]}[0]) {
            unshift @{$fsp_r}, \@sample;
        } elsif ($time >= ${${$fsp_r}[-1]}[0]) {
            push @{$fsp_r}, \@sample;
        } else {
            for (my $i = 0; $i < (scalar @{$fsp_r}); $i++) {
                if ($time <= ${${$fsp_r}[$i]}[0]) {
                    splice (@{$fsp_r}, $i, 0, \@sample);
                    last;
                }
            }
        }

        if ((scalar @{$fsp_r}) > 5){
            pop @{$fsp_r};
        }
    }

    if ((scalar @{$lsp_r}) <= 0){
        push @{$lsp_r}, \@sample;
    } else {
        if ($time <= ${${$lsp_r}[0]}[0]) {
            unshift @{$lsp_r}, \@sample;
        } elsif ($time >= ${${$fsp_r}[-1]}[0]) {
            push @{$lsp_r}, \@sample;
        } else {
            for (my $i = 0; $i < (scalar @{$lsp_r}); $i++) {
                if ($time <= ${${$lsp_r}[$i]}[0]) {
                    splice (@{$lsp_r}, $i, 0, \@sample);
                    last;
                }
            }
        }

        if ((scalar @{$lsp_r}) > 5){
            shift @{$lsp_r};
        }
    }
}

sub addemail {
    my ($line_r, $time, $user, $sender, $totec_r, $trec_r, $fsp_r, $lsp_r, $cnt_r, $raddr_r, $slog_r,
        $saddr_r, $mid_r, $id, $sub_r, $usercnt_r, $userraddr_r, $m_rec_r) = @_;

    recordsample($fsp_r, $lsp_r, $time, $line_r);

    ${$line_r} =~ /^(.*(?:(?:from\s<[^>]*>)|(?:T=\"[^\"]*\"))\sfor\s)(.*)$/;
    my @emails = split(/\s/, $2);;

    foreach (@emails) {
        unless($lowmem) {
            ${$raddr_r}{$_} += 1;
        }

        ${$userraddr_r}{$user}{$_} += 1;
        push (@{$m_rec_r->{$id}}, $_);
    }

    ${$cnt_r}{strftime("%Y-%m-%d", CORE::localtime($time))}{localtime($time)->hour} += @emails;
    ${$usercnt_r}{$user}{strftime("%Y-%m-%d", CORE::localtime($time))}{localtime($time)->hour} += @emails;
    ${$trec_r} += @emails;
    ${$slog_r}{$user} += @emails;

    unless($lowmem) {
        if ($sender eq "<>") {
            ${$saddr_r}{"Blank Sender"} += @emails;
        } else {
            ${$saddr_r}{$sender} += @emails;
        }
    }

    ${$totec_r}++;

    push (@{${$mid_r}{$id}}, strftime("%Y-%m-%d", CORE::localtime($time)));
    push (@{${$mid_r}{$id}}, localtime($time)->hour);

    unless($lowmem) {
        if (${$line_r} =~ /(T=\".*?(?<!\\)\"\s)/) {
            ${$sub_r}{$1} += @emails;
        } else {
            ${$sub_r}{'Blank Subject'} += @emails;
        }
    }
}

sub addbounce {
    my ($line_r, $id, $bounceid, $bcnt_r, $bcnt_h_r, $mid_r, , $m_rec_r, $bcnt_rec_r) = @_;

    ${$bcnt_r}{$id}++;
    ${$bcnt_h_r}{${$mid_r}{$bounceid}[0]}{${$mid_r}{$bounceid}[1]}++;
    map {$bcnt_rec_r->{$_}++} @{$m_rec_r->{$bounceid}};
}

sub parseeximline {
    my ($line_r, $startt, $endt, $flh_r, $ipaddr, $totec_r, $trec_r, $fsp_r, $lsp_r, $cnt_r, $raddr_r, $slog_r,
        $saddr_r, $mid_r, $bcnt_r, $bcnt_h_r, $cwd_r, $sub_r, $usercnt_r, $userraddr_r, $m_rec_r, $bcnt_rec_r) = @_;

    if (${$line_r} =~ /<=/) { # is this an outbound email?
        if (${$line_r} =~ /^(\d{4})\-(\d{2})\-(\d{2})\s(\d{2}):(\d{2}):(\d{2})\s(\[\d{1,8}\]\s)?(\w{6}\-\w{6}\-\w{2})\s<=\s/gc) { # grab time and id
            my $time = timegm($6, $5, $4, $3, $2 - 1, $1) - $offset;

            my $id = $8;

            if(($time >= $startt) & ($time <= $endt)) { # only count within the specified time range
                if (${$line_r} =~ /\G((?:[^\s]*[\+@][^\s]*)|(?:<>))\s/gc) { # do we have a sender?
                    my $sender = $1;

                    if (${$line_r} =~ /\G(H=([^\s]*\s)?((\([^\(]*\)\s)?\[([^\]]*)\]))(:\d{1,5})?\s/gc) { # is this a remote user?
                        my $helo = $1;
                        my $ip = $5;

                        if (${$line_r} =~ /(A=(fixed|courier|dovecot)_(login|plain):(([^\+@%:\s]*)|([^\+@%:\s]*[\+@%:]([^\+@%:\s]*))))\s/) { # do we have a valid authenticator?
                            my $auth = $1;
                            my $euser;

                            if ($5) {
                                $euser = $5;
                            } elsif ($7) {
                                $euser = $7;
                            } else {
                                return;
                            }

                            if (exists ${$flh_r}{$euser}) {
                                addemail($line_r, $time, $auth, $sender, $totec_r, $trec_r, $fsp_r, $lsp_r, $cnt_r, $raddr_r, $slog_r,
                                         $saddr_r, $mid_r, $id, $sub_r, $usercnt_r, $userraddr_r, $m_rec_r);
                                return;
                            } else {
                                return;
                            }
                        } else { # ipaddress tracking for imap/pop users goes here
                            if (exists ${$ipaddr}{$ip}) {
                                addemail($line_r, $time, $helo, $sender, $totec_r, $trec_r, $fsp_r, $lsp_r, $cnt_r, $raddr_r, $slog_r,
                                         $saddr_r, $mid_r, $id, $sub_r, $usercnt_r, $userraddr_r, $m_rec_r);
                                return;
                            } elsif ($sender =~ /^(.*?)-bounces[\+@](.*?)$/) { # were we sent from a bounce address?
                                my $blist = $1;
                                my $bdomain = $2;

                                if (exists ${$flh_r}{$bdomain}) { # did the domain belong the the user?
                                    if (${$line_r} =~ /id=mailman/) { # did the email belong to mailman?
                                        addemail($line_r, $time, "Mailman:$blist\@$bdomain", $sender, $totec_r, $trec_r, $fsp_r, $lsp_r, $cnt_r, $raddr_r, $slog_r,
                                                 $saddr_r, $mid_r, $id, $sub_r, $usercnt_r, $userraddr_r, $m_rec_r);
                                        return;
                                    } elsif ($ip eq "127.0.0.1") { # are we a local email, if so, and we have a "bounces" address, we are probably mailman
                                        addemail($line_r, $time, "Mailman:$blist\@$bdomain", $sender, $totec_r, $trec_r, $fsp_r, $lsp_r, $cnt_r, $raddr_r, $slog_r,
                                                 $saddr_r, $mid_r, $id, $sub_r, $usercnt_r, $userraddr_r, $m_rec_r);
                                    }
                                    else {
                                        return;
                                    }
                                } elsif($blist eq "mailman") {
                                    if (${$line_r} =~ /T="([^\s]*)\s.*?\s([^\s]*)"/) { # catch generic mailman reminder messages
                                        my $mdomains = $1;
                                        my $mdomaine = $2;

                                        if (exists ${$flh_r}{$mdomains}) { # does it belong to a domain we own?
                                            addemail($line_r, $time, "Generic Mailman Reminder:$mdomains", $sender, $totec_r, $trec_r, $fsp_r, $lsp_r, $cnt_r, $raddr_r, $slog_r,
                                                 $saddr_r, $mid_r, $id, $sub_r, $usercnt_r, $userraddr_r, $m_rec_r);
                                        } elsif (exists ${$flh_r}{$mdomaine}) {
                                            addemail($line_r, $time, "Generic Mailman Reminder:$mdomaine", $sender, $totec_r, $trec_r, $fsp_r, $lsp_r, $cnt_r, $raddr_r, $slog_r,
                                                 $saddr_r, $mid_r, $id, $sub_r, $usercnt_r, $userraddr_r, $m_rec_r);
                                        } else {
                                            return;
                                        }
                                    } else {
                                        return;
                                    }
                                } else {
                                    return;
                                }
                            } else {
                                return;
                            }
                        }
                    } elsif (${$line_r} =~ /\G(U=([^\s]*))\s/gc) { # is this a local user?
                        my $euser = $2;
                        my $login = $1;

                        if (exists ${$flh_r}{$euser}) {
                            if (${$line_r} =~ /id=[^\s]*squirrel@/) {
                                addemail($line_r, $time, 'Webmail', $sender, $totec_r, $trec_r, $fsp_r, $lsp_r, $cnt_r, $raddr_r, $slog_r,
                                         $saddr_r, $mid_r, $id, $sub_r, $usercnt_r, $userraddr_r, $m_rec_r);
                            } else {
                                addemail($line_r, $time, $login, $sender, $totec_r, $trec_r, $fsp_r, $lsp_r, $cnt_r, $raddr_r, $slog_r,
                                         $saddr_r, $mid_r, $id, $sub_r, $usercnt_r, $userraddr_r, $m_rec_r);
                            }
                            return;
                        } else {
                            return;
                        }

                    } elsif (${$line_r} =~ /\GR=(\w{6}\-\w{6}\-\w{2})\s/gc) { # is this a returned mail?
                        my $bounceid = $1;

                        if (exists ${$mid_r}{$bounceid}) { # is it one that we sent?
                            addbounce($line_r, $id, $bounceid, $bcnt_r, $bcnt_h_r, $mid_r, $m_rec_r, $bcnt_rec_r);
                            return;
                        } else {
                            return;
                        }
                    }
                }
            }
        }
    } elsif (${$line_r} =~ /cwd=/) { # is this a cwd line?
        if (${$line_r} =~ /^(\d{4})\-(\d{2})\-(\d{2})\s(\d{2}):(\d{2}):(\d{2})\scwd=(\/home\d?\/([^\/\s]*)([^\s]*)?)\s/gc) { # grab time and path
            my $time = timegm($6, $5, $4, $3, $2 - 1, $1) - $offset;

            my $cwdp = $7;
            my $cuser = $8;

            if(($time >= $startt) & ($time <= $endt)) { # only count within the specified time range
                if (exists ${$flh_r}{$cuser}) {
                    ${$cwd_r}{$cwdp}++;
                } else {
                    return;
                }
            }
        }
    }
}

sub commify { #commify (add commas to a number in a string)
    my $text = reverse $_[0];
    $text =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g;
    return scalar reverse $text
}

sub printtotals {
    my ($trec, $raddr_r, $bcnt_r, $bcnt_rec_r) = @_;

    my $percent = 0;

    if ($trec > 0) {
        $percent = (scalar(keys %{$bcnt_r})/$trec)*100;
    }

    print "User sent approximately ".commify($trec)." messages to ".commify(scalar(keys %{$raddr_r}))." unique recipients.\n";
    print "There were ".scalar(keys %{$bcnt_r})." bounces on ".scalar(keys %{$bcnt_rec_r})." unique addresses, ".int($percent)." percent of the emails sent.\n\n";
}

sub formatsample {
    my ($sample) = @_;
    my $fsample;

    if ($sample =~ /^(.*(?:(?:from\s<[^>]*>)|(?:T=\"[^\"]*\"))\sfor\s)(.*)$/)  {
        my @emails = split(/\s/, $2);

        if (@emails > 5) {
            $fsample = $1;

            my $i = 0;
            while ($i < 5) {
                $fsample = $fsample."$emails[$i] ";
                $i++;
            }
            $fsample = $fsample."... ".(@emails - 5)." additional email addresses removed.\n";
        } else {
            $fsample = $sample;
        }
    } else {
        $fsample = $sample;
    }

    return $fsample;
}

sub printsamples {
    my ($fsp_r, $lsp_r) = @_;

    print "Selected email samples:\n";
    print "-----------------------\n\n";

    print "First 5 Entries:\n\n";
    foreach my $samp_r (@{$fsp_r}) {
        my $samp = ${${$samp_r}[1]};
        print formatsample($samp);
    }
    print "\n";

    print "Last 5 Entries:\n\n";
    foreach my $samp_r (@{$lsp_r}) {
        my $samp = ${${$samp_r}[1]};
        print formatsample($samp);
    }
    print "\n";
}

sub pnbs {
    my ($text, $size) = @_;

    # return padleft($text, $size, "\xc2\xa0");  # unicode non breaking space
    return padleft($text, $size, ' ');  # normal space
}

sub padleft {
    my ($text, $size, $fill) = @_;

    if (($size - length($text)) <= 0) {
        return $text;
    } else {
        return ($fill x ($size - length($text))).$text;
    }
}

sub printhourly {
    my ($cnt_r, $bcnt_h_r, $usercnt_r, $slog_r, $userraddr_r) = @_;
    my $indthresh = 500; # threshold for displaying domain count

    print "Hourly mail volume for the entire account:\n\n";

    for my $d (sort {$a cmp $b} keys %{$cnt_r}) { #print numbers of emails sent, grouped into days and hours
        print "$d\n";
        print "-" x30 . "\n";

        print pnbs("Hour",4).pnbs("Volume",10).pnbs("Bounces",10).pnbs("%",6)."\n";

        print "-" x30 . "\n";

        for my $h (sort {$a <=> $b} keys %{${$cnt_r}{$d}}) {
            my $chour = ${$cnt_r}{$d}{$h};
            my $cbounce = 0;

            if (exists ${$bcnt_h_r}{$d}{$h}) {
                $cbounce = ${$bcnt_h_r}{$d}{$h};
            }

            my $percent;

            if ($chour <= 0) {
                $percent = 100;
            } else {
                $percent = ($cbounce/$chour)*100;
            }

            print pnbs($h,4).pnbs(commify($chour),10).pnbs(commify($cbounce),10).pnbs(int($percent),6)."\n";
        }

        print "\n";
    }

    my %udomains;
    my %udomainrecs;

    for my $u (keys %{$usercnt_r}) {
        my $udomain;

        if ($u =~ /(^.*?[\+@](.*?)$)/) {
            $udomain = $2;
        } elsif ($u =~ /(^U=(.*?)$)/) {
            $udomain = $1;
        } else {
            next; # this really shouldnt ever happen, but we should capture it anyways
        }

        for my $d (keys %{${$usercnt_r}{$u}}) {
            for my $h (keys %{${$usercnt_r}{$u}{$d}}) {
                $udomains{$udomain}{$d}{$h} += ${$usercnt_r}{$u}{$d}{$h};
            }
        }

        for my $r (keys %{${$userraddr_r}{$u}}) {
            $udomainrecs{$udomain}{$r} = ${$userraddr_r}{$u}{$r};
        }
    }

    if (scalar keys %udomains > 1) { # don't bother with the excess hourly display if there is only one user sending mail
        for my $u (sort {$udomains{$a} <=> $udomains{$b}} keys %udomains) {
            my $total = 0;

            for my $d (keys %{$udomains{$u}}) { # total up emails sent
                for my $h (keys %{$udomains{$u}{$d}}) {
                    $total += $udomains{$u}{$d}{$h};
                }
            }

            if ($total > $indthresh) { # if the account has sent more than the threshold
                print "\nThe '$u' account/domain was detected as sending large amounts of email.\n";
                print "The account/domain sent ".commify($total)." emails to ".commify((scalar (keys %{$udomainrecs{$u}})))." unique recipients. Displaying hourly mail:\n\n";

                for my $d (sort {$a cmp $b} keys %{$udomains{$u}}) { #print numbers of emails sent, grouped into days and hours
                    print "$d\n";
                    print "-" x14 . "\n";

                    print pnbs("Hour",4).pnbs("Volume",10)."\n";

                    print "-" x14 . "\n";

                    for my $h (sort {$a <=> $b} keys %{$udomains{$u}{$d}}) {
                        print pnbs($h,4).pnbs(commify($udomains{$u}{$d}{$h}),10)."\n";
                    }

                    print "\n";
                }
            }
        }
    }
}

sub printsendaddr {
    my ($saddr_r) = @_;

    if (%{$saddr_r}) { #only print out email addresses if there are any (there should be)
        print "Email addresses sent from:\n";
        print "--------------------------\n";

        my @s = sort {int (${$saddr_r}{$b}) <=> int(${$saddr_r}{$a})} keys %{$saddr_r};

        if ($terse && (scalar(@s) > 15)) { # trim long displays
            for (my $i = 0; $i < 15; $i++) {
                my $c = shift @s;
                print "$c: " . commify(${$saddr_r}{$c}) . "\n";
            }

            print "\nThere were ".scalar(@s)." additional sender addresses trimmed.\n";
        } else {
            for my $c (@s) {
                print "$c: " . commify(${$saddr_r}{$c}) . "\n";
            }
        }

        print "\n";
    }
}

sub printsendlog {
    my ($slog_r) = @_;

    if (%{$slog_r}) { #only print out logins if there are any
        print "Logins used to send mail:\n";
        print "-------------------------\n";

        my @l = sort {int (${$slog_r}{$b}) <=> int(${$slog_r}{$a})} keys %{$slog_r};

        if ($terse && (scalar(@l) > 15)) { # trim long displays
            my %new_slog;

            for my $c (@l) { # collapse randomized HELO strings
                if ($c =~ /(H=([^\s]*\s)?((\([^\(]*\)\s)?\[([^\]]*)\]))(:\d{1,5})?/) {
                    $new_slog{"H=(...) [$5]"} += ${$slog_r}{$c};
                } else {
                    $new_slog{$c} += ${$slog_r}{$c};
                }
            }

            @l = sort {int ($new_slog{$b}) <=> int($new_slog{$a})} keys %new_slog;

            if (scalar(@l) > 15) { # trim long displays
                for (my $i = 0; $i < 15; $i++) {
                    my $c = shift @l;
                    print "$c: " . commify($new_slog{$c}) . "\n";
                }

                print "\nThere were ".scalar(@l)." additional logins trimmed.\n";
            } else {
                for my $c (@l) {
                    print "$c: " . commify($new_slog{$c}) . "\n";
                }
            }
        } else {
            for my $c (@l) {
                print "$c: " . commify(${$slog_r}{$c}) . "\n";
            }
        }

        print "\n";
    }
}

sub printcwd {
    my ($cwd_r) = @_;

    if (%{$cwd_r}) { #only print out cwd stats if there are any
        print "Current working directories:\n";
        print "----------------------------\n";

        for my $c (sort {int (${$cwd_r}{$b}) <=> int(${$cwd_r}{$a})} keys %{$cwd_r}) {
            print "$c: " . commify(${$cwd_r}{$c}) . "\n";
        }

        print "\n";
    }
}

sub printsubs {
    my ($subs_r) = @_;

    if (%{$subs_r}) { #only print out subjects if there are any (there should be)
        print "Top subjects:\n";
        print "-------------\n";

        # sort subjects

        my @subss = sort {int (${$subs_r}{$b}) <=> int(${$subs_r}{$a})} keys %{$subs_r};

        if (scalar @subss <= 10) {
            foreach my $sub (@subss) {
                print "$sub: ${$subs_r}{$sub}\n";
            }
        } else {
            for (my $i = 0; $i < 10; $i++) {
                    print "$subss[$i]: ${$subs_r}{$subss[$i]}\n";
            }
        }

        print "\n";

        print "Total number of discrete subjects: " . scalar keys(%{$subs_r}) . "\n\n";
    }
}

sub printrecaddr {
    my ($raddr_r) = @_;

    if (%{$raddr_r}) { #only print out email addresses if there are any (there should be)
        my @k = sort {int (${$raddr_r}{$b}) <=> int(${$raddr_r}{$a})} keys %{$raddr_r};

        print "Random recipient addresses:\n";
        print "---------------------------\n";

        if (scalar @k <= 10) {
            foreach my $addr (@k) {
                print "$addr\n";
            }
        } else {
            for (my $i = 0; $i < 10; $i++) {
                    print $k[rand @k] . "\n";
            }
        }

        print "\n";

        print "Top recipients:\n";
        print "---------------\n";

        if (scalar @k <= 10) {
            foreach my $addr (@k) {
                print "$addr: ${$raddr_r}{$addr}\n";
            }
        } else {
            for (my $i = 0; $i < 10; $i++) {
                    print "$k[$i]: ${$raddr_r}{$k[$i]}\n";
            }
        }

        print "\n";
    }
}

sub printexim {
    my ($saddr_r) = @_;

    my @queue = `exim -bpr`;
    my $queuemails = 0;

    foreach (@queue) {
        $_ =~ s/^\s+|\s+$//g; # kill whitespace and newlines
        if (exists ${$saddr_r}{$_}) {
            $queuemails++;
        }
    }

    print "Emails currently in queue:\n";
    print "--------------------------\n";
    print "User: $queuemails, Total: ";

    print `exim -bpc`;
    print "\n";
}

sub printtimerange {
    my ($startTime, $endTime) = @_;

    my @monthsArr = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
    my ($psec,$pmin,$phour,$pday,$pmon,$pyear) = CORE::localtime($startTime);
    my ($sec,$min,$hour,$day,$mon,$year) = CORE::localtime($endTime);

    printf "Mail Log Parsed from $monthsArr[$pmon] $pday, %d %02d:%02d:%02d to $monthsArr[$mon] $day, %d %02d:%02d:%02d\n\n", ($pyear + 1900), $phour, $pmin, $psec, ($year + 1900), $hour, $min, $sec;
}

sub maillogstart {
    my ($file) = @_;
    my %monthsRev = ("Jan"=>1, "Feb"=>2, "Mar"=>3, "Apr"=>4, "May"=>5, "Jun"=>6, "Jul"=>7, "Aug"=>8, "Sep"=>9, "Oct"=>10, "Nov"=>11, "Dec"=>12);

    my $fh = new FileHandle;
    $fh->open("<$file");

    my $fhp;

    if ($file =~ /^.*?\.gz$/) {
        $fhp = new IO::Uncompress::Gunzip $fh;
    } else {
        $fhp = $fh;
    }

    my $time;

    while(my $line = <$fhp>) {
        if ($line =~ /((\w{3})\s{1,2}(\d{1,2})\s(\d{2}):(\d{2}):(\d{2}))/) {
            $time = timelocal($6, $5, $4, $3, $monthsRev{$2} - 1, localtime->year() + 1900);
            last;
        }
    }

    $fh->close();

    return $time;
}

sub processmaillogs {
    my ($searchusers_r, $fixedlogins_r, $startTime, $endTime) = @_;
    my @searchusers = @{$searchusers_r};

    my %monthsRev = ("Jan"=>1, "Feb"=>2, "Mar"=>3, "Apr"=>4, "May"=>5, "Jun"=>6, "Jul"=>7, "Aug"=>8, "Sep"=>9, "Oct"=>10, "Nov"=>11, "Dec"=>12);
    my $year = localtime->year() + 1900;

    # specify logs to search

    my @maillogs = @{findlogs('/var/log', 'maillog((-\d{8})|(\.\d))?(\.gz)?')};

    # setup hashes, arrays, and variables for collected data

    my %ipaddr; # ip addresses logging in via POP/IMAP

    # grab the server's own ip address

    my $myip = `hostname -i`;
    chomp($myip);

    foreach my $file (@maillogs) {
        if (my $eximt = maillogstart($file)) {
            print "Processing '$file'.\n";

            # makes sure the log contains the time we want to check

            if ($startTime < $eximt) {
                print "Start time pre-dates log, ";

                if ($endTime < $eximt) {
                    print "checking next log.\n";
                    next;
                } else {
                    print "but end time is present, checking anyways.\n";
                }

            }

            # open file and parse lines

            my $progress = -1;
            my $filesize;

            # this is totally a hack, but way faster than the pure perl way of doing it

            my $fh;

            if ($file =~ /^.*?\.gz$/) {
                open($fh, "-|", "zcat " . $file);
                my $gziplist=`gzip -l $file`;
                $gziplist=~/.\n\s*\d*\s*(\d*)/;
                $filesize=$1;
            } else {
                $fh = FileHandle->new("<$file");
                $filesize = stat($file)->size
            }

            my $istty = (-t STDOUT);
            my $pos = 0;

            while (my $line = <$fh>) {
                parsemailline(\$line, $startTime, $endTime, \%monthsRev, $year, $fixedlogins_r, \%ipaddr, $myip);

                $pos += length($line);
                my $new_progress = int(($pos / $filesize) * 100);

                if ($new_progress > $progress){ #prevent a billion slow i/o calls
                    $progress = $new_progress;

                    if ($istty) {
                        print "\r               \rProgress: $progress%"; #replace prev line with new progress
                    } else {
                        if (($progress == 0) || ($progress % 10 == 0)) {
                            print "$progress%";
                        } else {
                            print ".";
                        }
                    }
                }
            }

            $fh->close();

            print "\n";

            if ($startTime >= $eximt) {
                last; # start time is in current log, we are done checking
            }
        }
    }

    return (\%ipaddr);
}

sub parsemailline {
    my ($line_r, $startTime, $endTime, $monthsRev_r, $year, $fixedlogins_r, $ipaddr_r, $myip) = @_;

    if (${$line_r} =~ /((\w{3})\s{1,2}(\d{1,2})\s(\d{2}):(\d{2}):(\d{2})).*?Login: /gc) { # is this a login?
        my $logTime = timegm($6, $5, $4, $3, ${$monthsRev_r}{$2} - 1, $year) - $offset;

        if(($logTime >= $startTime) & ($logTime <= $endTime)) { # only count within the specified time range
            if (${$line_r} =~ /\Guser=<((.*?[\@+])?([^>]*))>.*?rip=([^,]*),/gc) { # do we have a user?
                my $user = $3;
                my $ip = $4;

                if (($ip ne "127.0.0.1") && ($ip ne $myip)) { # ignore localhost entries
                    if (exists ${$fixedlogins_r}{$user}) {
                        ${$ipaddr_r}{$ip}++;
                    }
                }
            }
        }
    }
}

sub pseudoui {
    my ($user) = @_;
    my $cuserpath = "/var/cpanel/users";
    my $netpath = "/etc/sysconfig/network";
    my $hostname = `hostname`;
#    my $hostname;

    my $owner = undef;
    my $domain = undef;

    open(NETWORK, $netpath);
    while(my $line = <NETWORK>) {
        if ($line =~ m/HOSTNAME=([a-z0-9]*)/) {
           $hostname = $1;
            last;
        }
    }
    close(NETWORK);

    if ($user ne "root") {
        open(CUSERS, "$cuserpath/$user");
        while(my $line = <CUSERS>) {
            if ($line =~ m/OWNER=([a-z0-9]*)/) {
                $owner = $1;
                last;
            }
        }
        close(CUSERS);

        open(CUSERS, "$cuserpath/$user");
        while(my $line = <CUSERS>) {
            if ($line =~ m/DNS=(.*?)$/) {
                $domain = $1;
                last;
            }
        }
        close(CUSERS);
    }

    if ($owner) {
        if (!($owner eq "root") && !($owner eq $user)) {
            print "Mail Report: $hostname: $owner($user)\n\n\n";
        } else {
            print "Mail Report: $hostname: $user\n\n\n";
        }
    } else {
        print "Mail Report: $hostname\n\n\n";
    }

    print "   Server: $hostname\n";

    if ($domain) {
        print "   Domain: $domain\n";
    }

    print "     User: $user\n";

    if ($owner) {
        if (!($owner eq "root") && !($owner eq $user)) {
            print "    Owner: $owner\n";
        }
    }
}

sub get_homedir {
    my ($user) = @_;
    my @pwent = getpwnam($user);
    return $pwent[7];
}
EOF
  )"
  
  # Print the Perl script result
  echo "$perl_result" | sed -e 's/T=//g' -e 's/"//g' -e 's/\t//g'
}

function finddiskspace() {
if [ "$(df -h | awk 'FNR == 2 {print $5}' | sed 's/%$//')" -gt "25" ]; then
        echo ""
        echo -n "Warning! Disk space usage is higher than 25%!"
        echo ""
        echo ""
        df -h | awk '$NF=="/"{printf "Disk Usage: %d/%dGB (%s)\n", $3,$2,$5}'
        echo ""
        echo ""
        echo -n "Searching for backups or files larger than 250M on $(hostname -f): "
        echo ""
        echo ""
        echo -n "Backups: "
        echo ""
        echo ""
        du -shc /backup///
        echo ""
        echo ""
        echo -n "File Usage: "
        echo ""
        echo ""
        du -shc $(find /home/ -size +250M -print 2>/dev/null) | grep total
        echo ""
        echo ""
        echo "Total Usage (Files + Backup): " && echo "" && du -shc $(find /home/ /backup -size +250M -print 2>/dev/null)
        echo ""
        echo ""
else
        echo ""
        echo ""
        echo -n "Disk space check is less than 25%"
        echo ""
        echo ""
        df -h | awk '$NF=="/"{printf "Disk Usage: %d/%dGB (%s)\n", $3,$2,$5}'
        echo ""
        echo ""
fi
}


function pass-security(){
username=$(awk -F'@' '{print $1}' <<< $1)
domain=$(awk -F'@' '{print $2}' <<< $1)
cPuser=$(/scripts/whoowns $domain)
enctype="{SHA512-CRYPT}"
hash=$(cat /home/$cPuser/etc/$domain/shadow | grep $username | awk -F':' '{print $2}')
encpass="{SHA512-CRYPT}$hash"
doveadm pw -t $encpass -p $2
}

function listfunctions() {
echo -e "${CYAN}apache-stats		${NC}-- Provides a comprehensive listing of all current Apache Workers across all domains hosted on the VPS.  Useful for troubleshooting limits with MaxRequestWorkers as well as identifying DDoS attack targets."
echo -e "${CYAN}zone		${NC}-- Displays all zone entries for given domain, usage: zone domain.tld"
echo -e "${CYAN}blocks		${NC}-- Displays all blocks in lfd.log for today's date."
echo -e "${CYAN}bots		${NC}-- This function performs a search across all of the domlogs for entries marked for the current date related to bot activity and outputs information useful to determining if perhaps a robots.txt is needed."
echo -e "${CYAN}cfallow		${NC}-- Automatically downloads and adds all of CloudFlare's IPv4 Addresses into CSF."
echo -e "${CYAN}docroot		${NC}-- Usage: docroot domain.tld, provides document root"
echo -e "${CYAN}ddos		${NC}-- DDoS log analyzer, usage: ddog /home/user/accesslogs/log_file"
echo -e "$(bad2 "enable-root		-- CAUTION: This will enable root access over SSH with password authentication.  Advise clients of the pros/cons of this feature before enabling.")"
echo -e "${CYAN}errors		${NC}-- This is an easy to use tool that provides all error output from error_log files for the current day run in public_html for best effectiveness."
echo -e "${CYAN}exim-security		${NC}-- Provides exim security protocols allowed and cipher suite."
echo -e "${CYAN}hack		${NC}-- Searches the domlogs for signs of brute force via xmlrpc.php, wp-login.php, and admin-ajax.php"
echo -e "${CYAN}install-softaculous		${NC}-- Auto-launches Will C.'s Softaculous installation script."
echo -e "${CYAN}findbigdirs		${NC}-- Reports any big directories within /home/*/public_html and /home/*/mail/"
echo -e "${CYAN}fixlicense		${NC}-- Fixes issues with cpanel licensces"
echo -e "${CYAN}ggnull		${NC}-- Usage: ggnull IP_Address, null routes IP Address provided."
echo -e "${CYAN}ggpaste		${NC}-- Provides a URL of the output data, used either in | or >"
echo -e "$(good2 "ggexit		-- Closes the session properly as the utility creates a dual bash session environment.")"
echo -e "${CYAN}lsdomains		${NC}-- Lists all domain names hosted on the VPS."
echo -e "${CYAN}lsforwards		${NC}-- Lists all mail forwarders on the VPS"
echo -e "${CYAN}phpusers		${NC}-- Provides information regarding each cPanel user and which PHP version they are configured to use."
echo -e "${CYAN}robotstxt		${NC}-- Searches throughout all the user public_html for robots.txt and reports directives."
echo -e "$(bad2 "sec-disable		-- CAUTION: This disables Security Questions and MUST be re-enabled once you complete your work.")"
echo -e "${CYAN}sec-enable		${NC}-- CAUTION: Do not enable this unless the client had it enabled previously and you disabled to service the server."
echo -e "${CYAN}summary		${NC}-- This run's the GG Summary Script for quoting server migrations."
echo -e "${CYAN}wpfunctions	${NC}-- This provides a comprehensive list of functions pertaining to WordPress."
}


function spamcheck(){
# Email Report
#By Robert J
echo ""
echo -n "==================EMAIL REPORT====================="
echo ""
echo ""
echo -n "===========$(date)============"
echo ""
echo ""
echo -n "Total emails in exim queue: " && exim -bpc
echo ""
echo -n "Total frozen emails in exim queue: " && exiqgrep -iz | wc -l
echo ""
exim -bp | exiqsumm | egrep -v "\-\-|Volume|^$" | sort -bg | awk '{print "Volume: " $1 " \t Domain: " $5}'
echo ""
echo ""
if [ -d /usr/local/cpanel ];then
echo "Checking for relay entries within LFD log files."
echo ""
echo "$(grep -i relay /var/log/lfd.log)"
echo ""
echo "Checking for high volume dovecot logins for potential compromised accounts."
echo ""
echo "$(grep -Po '(?<=dovecot_(plain|login):)\S*' /var/log/exim_mainlog | sort | uniq -c | sort -n | tail)"
echo ""
echo ""
echo ""
eximstats /var/log/exim_mainlog | head -11 && eximstats /var/log/exim_mainlog | grep -A 5 rejection | sed '/sending/d'
echo ""
echo ""
echo -n "Blacklist Check URL: " && echo -n "https://mxtoolbox.com/SuperTool.aspx?action=blacklist%3A$(hostname -i)"
echo ""
echo ""
echo ""
echo -n "=====EXIM LOG SAMPLES====="
echo ""
echo ""
tail -25 /var/log/exim_mainlog
echo ""
echo ""
else
echo "Checking for relay entries within LFD log files."
echo ""
echo "$(grep -i relay /var/log/lfd.log)"
echo ""
echo "Checking for high volume dovecot logins for potential compromised accounts."
echo ""
echo "$(grep -Po '(?<=dovecot_(plain|login):)\S*' /var/log/exim/main_log | sort | uniq -c | sort -n | tail)"
echo ""
echo ""
eximstats /var/log/exim/main_log | head -11 && eximstats /var/log/exim/main_log | grep -A 5 rejection | sed '/sending/d'
echo ""
echo ""
echo -n "Blacklist Check URL: " && echo -n "https://mxtoolbox.com/SuperTool.aspx?action=blacklist%3A$(hostname -i)"
echo ""
echo ""
echo ""
echo -n "=====EXIM LOG SAMPLES====="
echo ""
echo ""
tail -25 /var/log/exim/main_log
echo ""
echo ""
fi
}


function dspace() {

python2 << END
import os
import subprocess
import shlex
import sys

#paths to check
bpath = '/backup/'
hpath = '/home/'
plist = list()

max = 200

def run(cmd):
    proc=subprocess.Popen(shlex.split(cmd),stdout=subprocess.PIPE)
    out,err=proc.communicate()
    return str(out)

def gsize(num):
    if int(num) > 1024:
    	gbsize = num / float(1024)
        if str(gbsize).count('.') >= 1:
                gb = str(gbsize).split(".")
                size = gb[0] + "." + gb[1][:2] + "G"
    else:
	size = str(num) + "M"
    return size

def filter(input):
	fsize,fname = input.split("\t")
	if fsize >= 1024:
		msize = int(fsize) / 1024
		if msize >= max:
			fname = fname.lstrip()
                        fname = fname.rstrip()
			if fname.count('/') >=4:
				hsize = gsize(msize)
				print hsize + " " + fname
			if fname.count('/') <= 3:
				plist.append(fname)

def list_files(startpath):
    for root, dirs, files in os.walk(startpath):
        level = root.replace(startpath, '').count(os.sep)
        indent = ' ' * 4 * (level)
        tprint = '{}{}/'.format(indent, os.path.basename(root))
	if tprint != '/':
		if tprint != 'virtfs/':
			if os.path.isdir(startpath + tprint):
				filter(run('du -s ' + startpath + tprint))

        subindent = ' ' * 4 * (level + 1)

def chkdir(dir):
	if os.listdir(dir):
        	#print 'Output from ' + dir
        	list_files(dir)
	else:
        	print dir + ' is empty'

def subdir():
	for p in plist:
		chkdir(p)

def bigf():
	print "Listing of files over " + str(max) + "MB"
	for p in plist:
		#print p
		g = run ('find ' + p + ' -type f -size +' + str(max) + '000k -exec ls -lh {} \;')
		#print g
		gsplit = g.split('\n')
		#print str(len(gsplit))
		dl = len(gsplit)
		d = 1
		for r in gsplit:
			if d < dl:
				rsplit = r.split(' ')
				if len(rsplit) > 8:
					c = 0
					for i in rsplit:
						if c == 4:
							lt = i
						if c >= 7:
							lt = lt + " " + i
						c += 1
					print lt
				else:
					print rsplit[4] + " " + rsplit[7]
			d += 1

print "Looking for directories over " + str(max) + "MB"
print "Checking for large directories within " + bpath + " " + hpath
chkdir(bpath)
chkdir(hpath)
subdir()
print ""
bigf()
END
}

function zone(){
awk '$1 ~ /[^;]/' /var/named/$@.db
}

function checkssl(){
certificate=$(echo | openssl s_client -showcerts -servername $1 -connect $1:443 2>/dev/null | openssl x509 -inform pem -noout -text | grep -E 'Issuer|Not After|DNS')
echo "Domains: $(echo "$certificate" | awk -F'DNS:' '{print $2 $3 $4}' | grep '*')"
echo "Issuer: $(echo "$certificate" | awk -F', O=' '{print $2}' | awk -F', CN' '{print $1}')"
echo "Expires: $(echo "$certificate" | awk -F'Not After : ' '{print $2}' | sed -e 's/^[[:space:]]*//' | grep 'GMT')"
}

function wpfunctions(){
curl -s https://gist.githubusercontent.com/markjaquith/4487609/raw/a9bd6282620c7dada3cff9e8dee2bdf5cdc6b163/gistfile1.txt | tail -n +2 | head -n -2
echo -e "${M}wpaudit		${NC}-- Provides an audit of a WP install, ran as root within the installation directory includes siteurl, version, and 
summary of plugin and theme based on number of installed, updates pending, and inactive." 
echo -e "${M}wpthemelist	${NC}-- Provides standard output of wp-cli wp theme list, but as root without security risks."
echo -e "${M}wpplugininfo	${NC}-- Provides a brief description of a given plugin, must use the name as provided via wp-cli or WordPress.org."
echo -e "${M}wppluginlist	${NC}-- Provides standard output of wp-cli wp plugin list, but as root without security risks."
echo -e "${M}wpsecurity		${NC}-- Provides a list of any/all installations detected of WordPress installs containing WordFence and WP-Cerber."
}

#WP Plugin info
function wpplugininfo(){
content=$(curl -s https://wordpress.org/plugins/$1/)
length=$(echo "$content" | wc -l)
begin=$(echo "$content" | grep -n '<script type="application/ld+json">' -m 1 | cut -f1 -d:)
string=$(echo "$content" | tail -n $((length - begin + 1)))
end=$(echo "$string" | grep -n '</script>' -m 1 | cut -f1 -d:)
name=$(echo "$string" | head -n $end | grep name | awk -F': "' '{print $2}' | awk -F'",' '{print $1}')
description=$(echo "$string" | head -n $end | grep description | awk -F': "' '{print $2}' | awk -F'",' '{print $1}')
version=$(echo "$string" | head -n $end | grep softwareVersion | awk -F': "' '{print $2}' | awk -F'",' '{print $1}')
modified=$(echo "$string" | head -n $end | grep dateModified | awk -F': "' '{print $2}' | awk -F'",' '{print $1}')
echo $name | sed s/'WordPress.org'//g
echo $description
echo "Version: $version"
echo "Last updated: $(date -d"$modified" +%B" "%d", "%Y)"
}

#WP Plugin List
function wppluginlist(){
cpwd=$(pwd)
runuser -l $(stat -c %U .) -c "cd $cpwd; wp plugin list"
}

#WP Thee List
function wpthemelist(){
cpwd=$(pwd)
runuser -l $(stat -c %U .) -c "cd $cpwd; wp theme list"
}

# Function to create a random admin user
generate_random_string() {
    cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w "${1:-10}" | head -n 1
}

function wpcreateadmin() {
    local wp_url=$(wp option get siteurl --allow-root)
    
    # Generate random username and password
    local username=$(generate_random_string 8)
    local password=$(generate_random_string 12)
    local cpwd=$(pwd)
    
    # Suppress error output temporarily
    exec 3>&2  # Save current stderr to file descriptor 3
    exec 2> /dev/null  # Redirect stderr to /dev/null (suppress errors)

    # Execute the WP-CLI command to create the admin user
    makeuser=$(runuser -l $(stat -c %U .) -c "cd $cpwd && wp user create $username --allow-root '${username}@ggsupport.com' \
        --role=administrator \
        --user_pass='$password' \
        --display_name='GreenGeeks Temporary Admin User' --path='$cpwd'")

    # Restore stderr to its original state
    exec 2>&3  # Restore stderr from file descriptor 3
    exec 3>&-  # Close file descriptor 3 (cleanup)

    # Return username, password, and WordPress login URL
    echo "Username: $username"
    echo "Password: $password"
    echo "WordPress Login URL: ${wp_url}/wp-login.php"

    # Schedule deletion of the user after 30 minutes
    echo "/usr/local/bin/wp user delete $username --path='$cpwd' --yes --allow-root" | at now + 30 minutes
}


#WP Audit
function wpaudit(){ 
cpwd=$(pwd) 
siteurl=$(runuser -l $(stat -c %U .) -c "cd $cpwd; wp option get siteurl")
version=$(runuser -l $(stat -c %U .) -c "cd $cpwd; wp core version")
plugins="$(runuser -l $(stat -c %U .) -c "cd $cpwd; wp plugin list")"
themes="$(runuser -l $(stat -c %U .) -c "cd $cpwd; wp theme list")"
echo "WP siteurl: $siteurl"
echo "WP filepath: $cpwd"
echo "WP version: $version"
echo "WP themes: $(echo "$themes" | tail -n +2 | wc -l) total, $(echo "$themes" | grep available | wc -l) updates, $(echo "$themes" | grep inactive | wc -l) inactive"
echo "WP plugins: $(echo "$plugins" | tail -n +2 | wc -l) total, $(echo "$plugins" | grep available | wc -l) updates, $(echo "$plugins" | grep inactive | wc -l) inactive" 
}

#GGLoop
function ggloop(){
c=0
for i in "$@"
do
c=$((c+1))
if [ $c != 1 ]; then
cmd="$cmd $i"
fi
done

while read p; do
rcmd="$(echo $cmd | sed "s/\%v/$p/g")"
$rcmd
done < $1
}

# ggpaste Utility
# @return $paste_url
function ggpaste() {
    if [ ! -z $2 ]
    then
        curl --header "GGAUTH: ggpaste_259gag235" --form t=$1 --form file=@$2 https://paste.websitehostserver.net
    else
        curl --header "GGAUTH: ggpaste_259gag235" --form t=$1 --form file=@- https://paste.websitehostserver.net
    fi
}

#Null Router
function ggnull(){
route add -host $1 reject
}

#Whitelist CloudFlare
function cfallow(){
IPS=`curl -s https://www.cloudflare.com/ips-v4`

for ip in ${IPS}; do
  csf -a $ip
done

csf -r
}

#Mass CloudFlare
function masscf(){
IPS=`curl -s https://www.cloudflare.com/ips-v4`

for ip in ${IPS}; do
  csf -$1 $ip
done

#csf -r
}

#Get DDoS logs
function ddos() {
domain=$1
echo "Top URLs Requested:"
grep "$(date +%d/%b/%Y)" $domain | awk '{print $7}' | sort | uniq -c | sort -r | awk '$1>100'
echo "Top IP Addresses:"
grep "$(date +%d/%b/%Y)" $domain | awk '{print $1}' | sort | uniq -c | sort -r | awk '$1>100'
echo "Top User Agents:"
grep "$(date +%d/%b/%Y)" $domain | awk -F'"' '{print $6}' | grep -E '^.{50,}$' | sort | uniq -c | sort -r | head -n 10
}


######### RCTMP RIPPED FUNCTIONS NEED TO REWRITE SOME AND DOCUMENT

function hack() {
    D=$(date +%d)
    M=$(date +%b)
    Y=$(date +%Y)
    echo "Checking for xmlrpc.php brute force attacks.."
    echo "$(grep -H $D/$M/$Y /usr/local/apache/domlogs/* 2>/dev/null |grep 'POST /xmlrpc.php'|cut -d: -f1|sort|uniq -c)"
    echo ""
    echo  "Checking for wp-login.php brute force attacks.."
    echo "$(grep -H $D/$M/$Y /usr/local/apache/domlogs/* 2>/dev/null |grep 'POST /wp-login.php'|cut -d: -f1|sort|uniq -c)"
    echo ""
    echo "Checking for admin-ajax.php abuse.."
    echo "$(grep -H $D/$M/$Y /usr/local/apache/domlogs/* 2>/dev/null |grep 'POST /admin-ajax.php'|cut -d: -f1|sort|uniq -c)"
}

function bots() {
    D=$(date +%d)
    M=$(date +%b)
    Y=$(date +%Y)
    echo "Checking for bot traffic.."
    echo "$(grep -H $D/$M/$Y /usr/local/apache/domlogs/* 2>/dev/null |grep 'Bot'|cut -d: -f1|sort|uniq -c)"
}

function blocks() {
    D=$(date +%d)
    M=$(date +%b)
    Y=$(date +%Y)

grep "$M $D" /var/log/lfd.log | grep Blocked
}

function docroot(){ 
grep -E "^${1}: " /etc/userdatadomains|awk -F'==' '{print $5}'
}  

function lsdomains() {	
grep -E "==(addon|main)==" /etc/userdatadomains|cut -d: -f1|sort | xargs -i sh -c 'echo {} " " $(/scripts/whoowns {})'
}

function lsforwards(){
grep "=> .*@.*@.*lookuphost" /var/log/exim_mainlog | awk '{print $6,$5}' |sed 's/(//g;s/)//g;s/<//g;s/>//g'|awk '$2 ~ "@"'| sort | uniq -c | sort -n
}

function findbigdirs() {
if [[ $NCP == 0 ]];then
tmpLIST="/tmp /home/*/public_html /home/*/mail"
else
tmpLIST="/tmp /home/*/public_html"
fi
find $tmpLIST -xdev -printf '%h\n' | sort | uniq -c | awk '$1 >=  800' | sort -k 1 -rn
}

function robotstxt() { 
find /home/ -name robots.txt -type f | xargs grep -n delay | head $(awk -F':' '{print $1 " -n " $2}') | grep -v "#" 
}

function wpsecurity(){
echo "Looking for installations of WP-Cerber"
find /home/ -name wp-cerber -type d
echo ""
echo "Looking for installations of Wordfence"
find /home/ -name wordfence -type d
}


######### END


#Security Questions Functions
function sec-enable() {
case $secpol in
  "N") echo "Security Questions is not setup." ;;
  "1") echo "Security Questions already enabled." ;;
  "0")
   echo "Security Questions have been enabled."
   sed -i 's/SecurityPolicy::SourceIPCheck=0/SecurityPolicy::SourceIPCheck=1/g' /var/cpanel/cpanel.config
   /scripts/restartsrv cpanel
   secpol="1"
  ;;
esac
}

function sec-disable() {
case $secpol in
  "N") echo "Security Questions is not setup." ;;
  "0") echo "Security Questions already disabled." ;;
  "1")
  echo "Security Questions have been disabled, please ensure you re-enable them before finalizing work."
  sed -i 's/SecurityPolicy::SourceIPCheck=1/SecurityPolicy::SourceIPCheck=0/g' /var/cpanel/cpanel.config
  /scripts/restartsrv cpanel
  secpol="0"
  ;;
esac
}
#End Security Question Functions

function apache-stats(){
curl -s 'http://localhost/whm-server-status' | perl -ne 'print "$1\n" if m~<td nowrap>(.*?)</td>.*</td></tr>~ ' | sort | uniq -c | sort -n
}

function phpusers(){
grep php /etc/userdatadomains | awk -F'==' '{print $4 " " $10}' | sort | uniq
defaultphp="$(/usr/local/cpanel/bin/rebuild_phpconf --current|sed 's/^/        /' | sed -n 1p | awk -F':' '{print $2}')"
echo "$(grep inherit /etc/userdatadomains | awk -F'==' '{print $4 " " $10}' | sort | uniq | sed -e "s/inherit/inherit ${defaultphp}/g")"
}

function errors() {
    D=$(date +%d)
    M=$(date +%b)
    Y=$(date +%Y)

find . -name error_log | xargs grep $D-$M-$Y
}


#Supplemental Functions for getea4php
function phpeol() {
        PHPVer=$1
        PHPVer=$(case $PHPVer in
                "5.2") echo "2011-06-01" ;;
                "5.3") echo "2014-08-14" ;;
                "5.4") echo "2015-09-03" ;;
                "5.5") echo "2016-07-10" ;;
                "5.6") echo "2018-12-31" ;;
                "7.0") echo "2018-12-03" ;;
                "7.1") echo "2019-12-01" ;;
                "7.2") echo "2020-11-30" ;;
                "7.3") echo "2021-12-06" ;;
                "7.4") echo "2022-11-28" ;;
                "8.0") echo "2023-11-26" ;;
                "8.1") echo "2024-11-25" ;;
                *) echo $PHPVer ;;
        esac)
        echo $PHPVer
}

function datecheck() {
        CDate=$1
        D=$(date +%d)
        M=$(date +%m)
        Y=$(date +%Y)
        TDate="$Y-$M-$D"

        if [[ "$CDate" > "$TDate" ]]; then
                GREEN='\033[0;32m'
                NC='\033[0m'
                echo -e "${GREEN}${CDate}${NC}"
        else
                RED='\033[0;31m'
                NC='\033[0m'
                echo -e "${RED}${CDate}${NC}"
        fi
}
#End Supplemental Functions

function getea4php() {
        phpcount=$(/usr/local/cpanel/bin/rebuild_phpconf --current|sed 's/^/        /' |  wc -l)
        for (( c=1; c<=$phpcount; c++))
        do
	if [[ $c == 1 ]]; then
                /usr/local/cpanel/bin/rebuild_phpconf --current|sed 's/^/        /' | sed -n 1p
        else
            	vstr=$(/usr/local/cpanel/bin/rebuild_phpconf --current|sed 's/^/        /' | sed -n $c"p")
                vver=$(/usr/local/cpanel/bin/rebuild_phpconf --current|sed 's/^/        /' | awk -F'ea-php' '{print $2}' | awk '{print $1}' | sed -n $c"p")
                v1=${vver:0:1}
                v2=${vver:1:1}
                vc="$v1.$v2"
                veol=$(phpeol $vc)
                chkeol=$(datecheck $veol)
                echo -e ' \t '$vstr $chkeol
        fi
	done
}

function chksvc() {
case $OS in
  [7-8])
  httpd="$(service httpd status 2>&1 | awk '$1=="Active:"{print $2}')"
  if [[ $httpd = *"inactive" ]]; then
  bad "Apache (httpd) is down."
  else
  UPTIME=$(systemctl status httpd.service | grep Active | awk -F';' '{print $2}')
  good "Apache (httpd) is up since$UPTIME"
  fi

  mysqld="$(service mysqld status 2>&1 | awk '$1=="Active:"{print $2}')"
        if [[ $mysqld = *"inactive" ]]; then
        bad "MySQL (mysqld) is down."
	      else
	      UPTIME=$(systemctl status mysqld.service | grep Active | awk -F';' '{print $2}')
	      good "MySQL (mysqld) is up since$UPTIME"
        fi

  DNS=$(grep local_nameserver_type /var/cpanel/cpanel.config | awk -F'=' '{print $2}')
  case $DNS in
    'bind')
    named="$(service named status 2>&1 | awk '$1=="Active:"{print $2}')"
    if [[ $named = *"inactive" ]]; then
    bad "NAMED (named) is down."
    else
    UPTIME=$(systemctl status named.service | grep Active | awk -F';' '{print $2}')
    good "NAMED (named) is up since$UPTIME"
    fi
    ;;
    'powerdns')
    powerdns="$(service pdns status 2>&1 | awk '$1=="Active:"{print $2}')"
    if [[ $powerdns = *"inactive" ]]; then
    bad "POWERDNS (pdns) is down."
    else
    UPTIME=$(systemctl status pdns.service | grep Active | awk -F';' '{print $2}')
    good "POWERDNS (pdns) is up since$UPTIME"
    fi
    ;;
  esac
;;
'6')
if [[ -n $(ps aux | grep mysql | grep -v grep) ]] ; then good "MySQL is UP!"; else bad "MySQL is DOWN!"; fi
if [[ -n $(ps aux | grep httpd | grep -v grep) ]] ; then good "Apache is UP!"; else bad "Apache is DOWN!"; fi
if [[ -n $(ps aux | grep named | grep -v grep) ]] ; then good "NAMED is UP!"; else bad "NAMED is DOWN!"; fi
;;
esac
}

#Begin Summary Output
#Script Version Data
SOUT "GreenGeeks MVM System Status Version: $version" "Container: $vzCTID"

#Check Operating System
case $OS in
  '5')  SOUT "Operating System" "$(bad "$(cat /etc/redhat-release)")" ;;
  '6')  SOUT "Operating System" "$(bad "$(cat /etc/redhat-release)")" ;;
  [7-8])  SOUT "Operating System" "$(good "$(cat /etc/redhat-release)")" ;;
esac

#Check Hostname for formatting, DNS, etc.
if [[ `${HOSTNAMEBIN}|grep -c '.'` -lt 1 ]];then
hname="$B ${HOSTNAME} Invalid Hostname $CLEAR"
else
        htest="$(dig +noall +answer ${HOSTNAME} @8.8.8.8)"
        if [[ ! -n $htest ]];then
        hname="$B ${HOSTNAME} DNS Not Setup $CLEAR"
        fi
fi
if [[ -z $hname ]];then
hname="$G ${HOSTNAME} $CLEAR"
fi
SOUT "Hostname" "$hname"

#get Primary IP address
SOUT "Primary IP" $(hostname -i)

#cPanel Version Check
CPVER="$(cat /usr/local/cpanel/version)"
CPV="$(awk -F . '{print $2}' /usr/local/cpanel/version)"
case $CPV in
 [4-6][0-9]) SOUT "cPanel Version" "$(bad2 $CPVER)" ;;
 7[0-3]) SOUT "cPanel Version" "$(bad2 $CPVER)" ;;
 7[4-9]) SOUT "cPanel Version" "$(bad $CPVER)" ;;
 [8-9][0-9]) SOUT "cPanel Version" "$(good $CPVER)" ;;
esac

#EasyApache Version Check
cpeaver=`/usr/local/apache/bin/httpd -v|grep Easy|awk '{print $2}'|sed 's/v//'|awk -F. '{print $1}'`
	if [[ ${cpeaver} -ne 3 ]]; then
		cpeaver=4
	fi
				
	case ${cpeaver} in
		4)
		SOUT "EasyApache" "$(good 'Version 4')"
		getea4php
		;;
		3)
		SOUT "EasyApache" "$(bad 'Version 3')"
    EA3PHP=$(php -v | head -n 1 | awk '{print $2}' | awk -F'.' '{print $1"."$2}')
    EA3PHPEOL=$(phpeol $EA3PHP)
    echo -e 'PHP '$EA3PHP $(datecheck $EA3PHPEOL)
		;;
		esac

#Database Version Check

      DB="$(mysql --version | awk '{print $1 " " $5}'| sed 's/.$//')"
      DBV="$(echo $DB | awk '{print $2}' | awk -F'.' '{print $1"."$2}')"
      case $DBV in
      #mysql checks
        '5.'[0-5]) SOUT "Database" "$(bad "$DB")" ;;
        '5.'[6-7]) SOUT "Database" "$(good "$DB")" ;;
        '8.'[0-9]) SOUT "Database" "$(good "$DB")" ;;
      #mariadb checks
        '10.'[0-2]) SOUT "Database" "$(bad "$DB")" ;;
        '10.'[3-9]) SOUT "Database" "$(good "$DB")" ;
      esac

#Check Backup Status
backup=$(grep BACKUPENABLE /var/cpanel/backups/config | awk -F"BACKUPENABLE: " '{print $2}' | tr -d \'\")
      if [ "$backup" = "no" ];then
        SOUT "Backups" "$B Backups are not enabled. $CLEAR"
        else
        SOUT "Backups" "$G Backups are enabled. $CLEAR"
      fi 

#Get Server Stats
SOUT "Service Status" "$(chksvc)"

#disk percentage check
DU=`df -h | head -n 2 | tail -n 1 | awk {'print $5'}`
DT=`df -h | head -n 2 | tail -n 1 | awk {'print $2'}`

case $DU in
  [0-9]'%') DISK="$(good2 "$DU of $DT")" ;;
  [0-4][0-9]'%') DISK="$(good2 "$DU of $DT")" ;;
  [5-6][0-9]'%') DISK="$(good "$DU of $DT")" ;;
  [7-8][0-9]'%') DISK="$(bad "$DU of $DT")" ;;
  [9][0-9]'%') DISK="$(bad2 "$DU of $DT")" ;;
  100'%') DISK="$(bad2 "$DU of $DT")" ;;
esac

#memory percentage check
case $OS in
'6')
getmem=`vmstat -s | egrep -v '(swap|cpu|pages|boot|forks|interrupt|switches)'`
gt=$(echo $getmem | awk '{print $1 / 1024}')
gts="$(echo "${gt}MB")"
ga=$(echo $getmem | awk '{print $7 / 1024}' | awk -F'.' '{print $1}')
mp=$((100*$ga/$gt))
;;
[7-8])
getmem=`vmstat -s | egrep -v '(swap|cpu|pages|boot|forks|interrupt|switches)'`
gt=$(echo $getmem | awk '{print $1 / 1024}')
gts="$(echo "${gt}MB")"
ga=$(echo $getmem | awk '{print $9 / 1024}' | awk -F'.' '{print $1}')
mp=$((100*$ga/$gt))
;;
esac

case $mp in
  [0-9]) MEMORY="$(good2 "$mp% of $gts")" ;;
  [0-4][0-9]) MEMORY="$(good2 "$mp% of $gts")" ;;
  [5-6][0-9]) MEMORY="$(good "$mp% of $gts")" ;;
  [7-8][0-9]) MEMORY="$(bad "$mp% of $gts")" ;;
  [9][0-9]) MEMORY="$(bad2 "$mp% of $gts")" ;;
  100) MEMORY="$(bad2 "$mp% of $gts")" ;;
esac

#CPU check
load="$(uptime | awk -F'average:' '{print $2}' | sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//')"
SOUT "Server Health" "Disk Usage\t\tMemory\t\t\tLoad"
tload="$(echo $load | awk -F'.' '{print $1}')"

case $tload in
     [0-1]) DLOAD="$(good2 "$load")" ;;
     [2-3]) DLOAD="$(bad "$load")" ;;
     [4-9]) DLOAD="$(bad2 "$load")" ;;
[1-9][0-9]) DLOAD="$(bad2 "$load")" ;;
esac

echo -e "$DISK\t\t$MEMORY\t\t$DLOAD"

#exim check
queueFAIL=100
mailQUEUE=`exim -bpc`
				if [[ $mailQUEUE -gt $queueFAIL ]]; then
					SOUT "Exim Check" "$(bad2 "Messages in queue: $mailQUEUE")"
                else
                    SOUT "Exim Check" "$(good "Messages in queue: $mailQUEUE")"
				fi
unset mailQUEUE

securitycheck="$(grep SecurityPolicy::SourceIPCheck /var/cpanel/cpanel.config)"
if [[ ! -n $securitycheck ]]; then
SOUT "Security Check" "$(bad "Not Found")"
secpol="N"
else
  case $securitycheck in
   "SecurityPolicy::SourceIPCheck=0") SOUT "Security Check" "$(bad "Disabled")"; secpol="0" ;;
   "SecurityPolicy::SourceIPCheck=1") SOUT "Security Check" "$(good "Enabled")"; secpol="1" ;;
  esac
fi