#!/bin/sh
eval 'if [ -x /usr/local/cpanel/3rdparty/bin/perl ]; then exec /usr/local/cpanel/3rdparty/bin/perl -x -- $0 ${1+"$@"}; else exec /usr/bin/perl -x $0 ${1+"$@"}; fi;'
if 0;

#!/usr/bin/perl

BEGIN {
    if(-f '/var/cpanel/cpgs/cPGSLib.pm') {
        print "Found cPGSLib already installed\n";
        push(@INC,'/var/cpanel/cpgs');
    }
    else {
        chomp(my $cwd = `pwd`);
        if(-f "$cwd/cPGSLib.pm") {
            print "Found cPGSLib in install directory\n";
            push(@INC, $cwd);
        } else {
            print "Could not find cPGSLib, good luck!\n";
        }
    }
};

use IPC::Open2;
use cPGSLib;

##### make sure we're running as root

if($< != 0) {
    print "You must be root to install cPGS.\n";
    exit(0);
}

# cleanup
unlink("/var/cpanel/cpgs/ts3_ts3_11239-12473_patch.cpgs");
unlink("/var/cpanel/cpgs/ts3_patch.cpgs");
unlink("/usr/local/cpanel/whostmgr/docroot/cgi/addon_gs.cgi.bak");
system("rm","-rf","/var/cpanel/cpgs/tmp/") if -d "/var/cpanel/cpgs/tmp/";

##### check to see if updates are enabled

if(open(my $cfg_fh,'<','/var/cpanel/cpgs/cpgsd.cfg')) {
    while(<$cfg_fh>) {
        my($var,$val) = split(/\=/,$_,2);
        if($var eq 'disableupdates' && $val == 1) {
            print "Updates are currently disabled, please edit /var/cpanel/cpgs/cpgsd.cfg and set disableupdates=0 to enable.\n";
            close($cfg_fh);
            exit;
        }
    }
    close($cfg_fh);
}

my $orig_umask = umask;
umask(0022);

##### install needed perl mods

system('/scripts/perlinstaller','IO::Socket::SSL','IPC::Run','IO::Pty');

#### make sure these two copies of cpgsd.pl are the same to avoid mismatched version issues

my $inode_one = (stat('/usr/local/cpanel/libexec/cpgsd.pl'))[1];
my $inode_two = (stat('/var/cpanel/cpgsd.pl'))[1];
if( $inode_one != $inode_two ) {
    rename( '/var/cpanel/cpgsd.pl', '/var/cpanel/cpgsd.pl.old' );
    system('ln','-sf','/usr/local/cpanel/libexec/cpgsd.pl','/var/cpanel/cpgsd.pl');
}

print "Installing cPanel/WHM files..\n";
system( 'tar', 'xzf', 'release.tgz', '-C', '/' );

if(! -e '/scripts/postkillacct') {
    system('cp','postkillacct','/scripts/postkillacct');
}

#### handle appconfig registration
if( -e '/usr/local/cpanel/bin/register_appconfig' ) {
    system('/usr/local/cpanel/bin/register_appconfig','appconfig/cpgs.conf');
} else {
    if( ! -e '/var/cpanel/apps' ) {
        mkdir '/var/cpanel/apps';
        chmod 0755, '/var/cpanel/apps';
    }
    system('cp','appconfig/cpgs.conf','/var/cpanel/apps/cpgs.conf');
}

#### create a cpgsd.cfg if none exists ####################################

if ( !-e "/var/cpanel/cpgs/cpgsd.cfg" ) {
    print "Creating /var/cpanel/cpgs/cpgsd.cfg ..\n";

    # get a list of all IPs bound to the server and allow them to talk to cPGSD by default.
    my $boundips;
    my @ifconfig = `ifconfig`;
    foreach my $line(@ifconfig) {
        if($line =~ m/\s*inet\s(\d+)\.(\d+)\.(\d+)\.(\d+)\s+/) { # bsd
            $boundips .= "$1\.$2\.$3\.$4,";
        } elsif ($line =~ m/\s*inet\s+addr\:(\d+)\.(\d+)\.(\d+)\.(\d+)\s+/) { # linux
            $boundips .= "$1\.$2\.$3\.$4,";
        }
    }

    open( my $config_fh, '>', '/var/cpanel/cpgs/cpgsd.cfg' ) or print "Could not write default config to /var/cpanel/cpgs/cpgsd.cfg : $!\n";
    print $config_fh <<EOF;
root=/var/cpanel/
allowedips=$boundips
sslpem=/var/cpanel/cpgs.pem
pkgdir=/home/gameservers/
qstat=/usr/local/bin/qstat
logfile=/var/log/cpgsd.log
port=2092
maxsim=2
waittime=10
quotacheck=1
EOF
    close($config_fh);
}

#### end cpgsd.cfg creation ###############################################

#### determine auth directory, get keys from there ########################

my $rootd = '/var/cpanel';
open(my $cfg_fh, '<', '/var/cpanel/cpgs/cpgsd.cfg');
while(<$cfg_fh>) {
   if(m/^root=(.*)$/) {
        $rootd = $1;
        last;
   }
}
close($cfg_fh);

my $authd = $root . '/cpgs/auth';
$authd =~ s/\/+/\//g;
if ( ! -d $authd ) { system('mkdir','-p',$authd); }

if ( -f '/root/.cpgskey' && ! -e "$authd/.cpgs_adminkey" && -d $authd ) {
    system('mv','/root/.cpgskey',"$authd/.cpgs_adminkey");
}

if ( open( my $root_key_fh, '<', "$authd/.cpgs_adminkey" ) ) {
    while (<$root_key_fh>) {
        s/(\r|\n)//g;
        if (m/^secret\=(.*)/) {
            $cfgdata{'secretkey'} = $1;
            last;
        }
    }
    close($root_key_fh);
}
chmod oct('0600'), "$authd/.cpgs_adminkey";

#### create the cpgs_query key if needed ##################################

if( ! -f "$authd/.cpgs_querykey") {
    my $q_key = gen_key();
    open(my $qfh,'>',"$authd/.cpgs_querykey");
    print $qfh "secret=$q_key\n";
    close($qfh);
}
chmod oct('0600'), "$authd/.cpgs_querykey";



if(-f "/var/cpanel/cpgs/custom_content/global") {
    my $rem=0;
    open(my $fh,'<','/var/cpanel/cpgs/custom_content/global');
    while(<$fh>) {
        if(/My global edits/i) { $rem = 1; last; }
    }
    close($fh);
    if($rem == 1) { unlink('/var/cpanel/cpgs/custom_content/global'); }
}

print "Creating default reseller config if not already present..\n";

if(! -e '/var/cpanel/gameserv_resellers.cfg') { open(my $file_fh,">>/var/cpanel/gameserv_resellers.cfg"); close($file_fh); }

print "Setting up cron jobs ..\n";

$fnd  = 0;
$fnd2 = 0;
open( my $cron_fh, '<', '/etc/crontab' );
@croncont = (<$cron_fh>);
close($cron_fh);
if ( grep /cpgs_cron/, @croncont ) { $fnd  = 1; }
if ( grep /cpgs_chk/,  @croncont ) { $fnd2 = 1; }

my $bucnt = 0;
my @bulist;

if ( opendir( my $etc_fh, '/etc' ) ) {
    while ( my $file = readdir($etc_fh) ) {
        if ( $file =~ m/^crontab\.\d{10}/ ) {
            $bucnt++;
            push( @bulist, $file );
        }
    }
    closedir($etc_fh);
}
else {
    print "Could not open /etc , terminating update/install : $!\n";
    exit;
}

if ( $bucnt > 4 ) {
    print "Deleting oldest backup file..\n";
    my @sorted = sort(@bulist);
    my $oldest = '/etc/' . shift(@sorted);
    if ( -f $oldest and !-l $oldest ) {
        unlink($oldest);
    }
}

my $loopcnt = 0;

BACKUP:
$loopcnt++;
my $time   = time;
my $backup = "/etc/crontab.$time";

if ( !-e $backup ) {
    print "Backing up /etc/crontab to $backup<br>\n";
    if ( open( my $crontabcopy_fh, '>', $backup ) ) {
        foreach (@croncont) {
            print $crontabcopy_fh $_;
        }
        close($crontabcopy_fh);
    }
    else {
        print "Could not create $backup : $! <br>\n";
    }
}
else {
    if ( $loopcnt < 10 ) {
        sleep 1;
        goto BACKUP;
    }
}

if ( $fnd == 0 ) {
    print "Adding cpgs_cron.pl script to /etc/crontab..<br>\n";
    open( my $cron_fh, '>>', '/etc/crontab' ) or print "Could not open /etc/crontab for writing: $!\n";
    print $cron_fh "*/2 * * * * root /var/cpanel/cpgs/cpgs_cron.pl\n";
    close($cron_fh);
}
if ( $fnd2 == 0 ) {
    print "Adding cpgs_chk script to /etc/crontab..<br>\n";
    open( my $cron_fh, '>>', '/etc/crontab' ) or print "Could not open /etc/crontab for writing: $!\n";
    print $cron_fh "*/5 * * * * root /var/cpanel/cpgs/cpgs_chk 2>&1 >>/var/log/cpgsd.log\n";
    close($cron_fh);
}
if ( $fnd == 1 && $fnd2 == 1 ) {
    print "Crontabs already installed, skipping<br>\n";
}

# Get updated crontab
open( my $cron_fh, '<', '/etc/crontab' );
@croncont = (<$cron_fh>);
close($cron_fh);

if ( open( my $crontab_fh, '>', '/etc/crontab' ) ) {
    foreach my $line (@croncont) {
        if ( $line =~ m/(.*)cpgs_cron/ ) {
            if ( $1 =~ m/^\#/ ) {
                print $crontab_fh "\#*/2 * * * * root /var/cpanel/cpgs/cpgs_cron.pl\n";
            }
            else {
                print $crontab_fh "*/2 * * * * root /var/cpanel/cpgs/cpgs_cron.pl\n";
            }
        }
        elsif ( $line =~ m/(.*)cpgs_chk/ ) {
            if ( $1 =~ m/^\#/ ) {
                print $crontab_fh "\#*/5 * * * * root /var/cpanel/cpgs/cpgs_chk 2>&1 >>/var/log/cpgsd.log\n";
            }
            else {
                print $crontab_fh "*/5 * * * * root /var/cpanel/cpgs/cpgs_chk 2>&1 >>/var/log/cpgsd.log\n";
            }
        }
        else {
            print $crontab_fh $line;
        }
    }
    close($crontab_fh);
}
else {
    print "Could not write to /etc/crontab : $! <br>\n";
}

chmod oct('0700'), '/var/cpanel/cpgs/cpgs_cron.pl';
chmod oct('0700'), '/var/cpanel/cpgs/cpgs_chk';
chmod oct('0700'), '/var/cpanel/cpgsd.pl';

# fix for bug in whm that doesn't register in plugins, showing no link in WHM
unlink '/var/cpanel/pluginscache.cache';
unlink '/var/cpanel/pluginscache.yaml';

if ( -x "/usr/local/cpanel/bin/register_cpanelplugin" ) {
    print "Registering plugin with cPanel..\n";
    `/usr/local/cpanel/bin/register_cpanelplugin cpgs.cpanelplugin`;
}

print "Installing language file entries..\n";

`mkdir -p /usr/local/cpanel/modules-install/cpgs/lang`;
`cp -f lang/english lang/english-utf8 /usr/local/cpanel/modules-install/cpgs/lang/`;
`/usr/local/cpanel/bin/build_locale_databases --clean` if -x '/usr/local/cpanel/bin/build_locale_databases';
`/usr/local/cpanel/bin/rebuild_sprites`;

my $qvl = 0;

if ( open( F, '<', '/usr/local/bin/qstat' ) ) {
    while (<F>) {
        if (/cpgs-0.7.0/) {
            $qvl = 0;
            print "qstat is installed and up to date..\n";
            last;
        }
        else {
            $qvl = 1;
        }
    }
    close(F);
}
else {
    $qvl = 1;
}

if ( $qvl == 1 ) {
    print "Installing qstat..\n";
    if ( -e "qstat2.tgz" ) { unlink "qstat2.tgz"; }
    `wget -q http://cpgs.cpanel.net/qstat2.tgz`;
    `tar xzf qstat2.tgz`;
    chdir("qstat2");
    `rm -rf autom4te.cache`;
    `sh autogen.sh`;
    `./configure`;
    `make`;
    `make install`;
    `make clean`;
}

if(-f '/var/cpanel/cpgs.pem') {
    rename('/var/cpanel/cpgs.pem','/var/cpanel/cpgs/cpgs.pem');
}

if(!-e '/var/cpanel/cpgs/cpgs.pem') {
open2(\*CERT,\*SSL,"openssl req -new -x509 -nodes -days 999 -keyout /var/cpanel/cpgs/cpgs.pem -out /var/cpanel/cpgs/cpgs.pem 2>\&1 >/dev/null");
print SSL<<EOF;
GS
cPGS
cPGS
cPGS
cPGS
cPGS
cPGS
EOF
}

if(open(my $alertcfg,'<','/var/cpanel/cpgs/alert.cfg')) {
    while(<$alertcfg>) {
        if(m/darren\@cpanel/) {
            close($alertcfg);
            unlink '/var/cpanel/cpgs/alert.cfg';
            last;
        }
    }
}

print "Linking theme support..\n";
symlink( '/usr/local/cpanel/base/frontend/x3/gameserv/', '/usr/local/cpanel/base/frontend/x3mail/gameserv' );

my $xdir = '/usr/local/cpanel/base/frontend/x';
my $rm_x = 1; # remove old "x" dir by default

if( -d $xdir ) {
    if(opendir(my $x_dir_fh, $xdir)) {
        while(my $f = readdir($x_dir_fh)) {
            if( $f =~ m/^\.+$/) { next; }
            if( $f !~ m/gameserv/) { # if we find a file or dir that is not cPGS related, set the rm flag to 0
                print "Detected a non-cPGS file here [$f], not removing.\n";
                $rm_x = 0;
                last;
            }
        }
        closedir($x_dir_fh);
    }
    if($rm_x == 1) {
        print "Removing deprecated \"x\" theme support\n";
        system('rm','-rf', $xdir);
    }
}

umask($orig_umask);
symlink( '/usr/local/cpanel/libexec/cpgsd.pl', '/var/cpanel/cpgsd.pl' );

print "Updating remote servers..\n";
my %remservs;
if ( open( my $remsrvs, '<', '/var/cpanel/gameserv_rem.cfg' ) ) {
    while (<$remsrvs>) {
        my ( $combo, $ips ) = split( /\|/, $_, 2 );
        if ( $combo =~ s/\_servip$// ) {
            my ( $user, $game, $srvn ) = split( /\_/, $combo, 3 );
            my (@ips) = split( /\,/, $ips );
            foreach my $ip (@ips) {
                chomp($ip);
                if ( $ip eq '127.0.0.1' ) {
                    next;
                }
                $remservs{$ip} = 1;
            }
        }
    }
}

foreach my $ip ( keys %remservs ) {
    print "Updating $ip.. \n";
    set_quotacheck($ip);
    remotecmd($ip,'updateself');
}

mkdir '/var/cpanel/cpgs/tmp';

if( ! -d '/var/cpanel/cpgs/cfg/ugs' ) {
    print "Converting <0.9.2 configuration files to current format..\n";
    system("/var/cpanel/cpgs/misc/config_convert.pl");
}

print "cPGS installation complete.<br>Starting cPGSD..\n";

exec("/usr/local/cpanel/libexec/cpgsd.pl");

exit(0);

#######################################################################################
# subs
#######################################################################################

sub remotecmd {

    my ($remip,$cmd) = @_; # we take a $cmd arg, but the function only really works if it's 'updateself'. Might be modded in the future.

    if( open( my $cfg_fh, '<', '/var/cpanel/cpgs/cpgsd.cfg' )) {
        while (<$cfg_fh>) {
            s/(\r|\n)//g;
            my ( $var, $val ) = split( /\=/, $_, 2 );
            if    ( $var eq 'secret' ) { $secretkey = $val; }
            elsif ( $var eq 'port' )   { $port      = $val; }
            elsif ( $var eq 'sslpem' ) { $sslpem    = $val; }
        }
        close($cfg_fh);
    } else {
         print "Could not open config file /var/cpanel/cpgs/cpgsd.cfg : $!\n";
         return;
    }
    if ( -f '/var/cpanel/cpgs/auth/.cpgs_adminkey' ) {
        open( my $keyf, '<', '/var/cpanel/cpgs/auth/.cpgs_adminkey' );
        $secretkey = <$keyf>;
        close($keyf);
        $secretkey =~ s/^secret\=//;
        chomp($secretkey);
    }

    my %meta;
    $meta{'user'} = 'root';
    $meta{'secretkey'} = $secretkey;
    $meta{'remuser'}   = 'cpgs_admin';
    $meta{'command'}   = $cmd;
    $meta{'remip'}     = $remip;
    my $rp = cPGSLib::sendssl( \%meta, \%data );
    if ( $$rp{'retcode'} == 0 ) {
        print "Waiting 5 seconds for cPGSD to restart..\n";
        for(my $i = 0; $i < 5; $i++) {
            sleep(1);
            print '.';
        }
        $meta{'command'} = 'getversion';
        my $rp = cPGSLib::sendssl( \%meta, \%data );
        if ( $$rp{'retcode'} == 0 ) {
            print "cPGSD \@ $remip is now running version $$rp{'version'}\-$$rp{'subversion'}\n";
        }
        else {
            print "Problem getting version on $remip: $$rp{'errmsg'}\n";
        }
    } else {
        print "Problem updating cPGS on $remip: $$rp{'errmsg'}\n";
    }
}

sub set_quotacheck {
        my ($ipval) = @_;
        my %meta;
        my %data;

        $meta{'remip'}   = $ipval;
        $meta{'remuser'} = 'cpgs_admin';
        $meta{'command'} = 'saveConfig';

        $data{'config'}{'quotacheck'} = 1;

        my $rp = cPGSLib::sendssl( \%meta, \%data );
        if ( $$rp{'retcode'} == 0 ) {
            print "Enabled quotacheck\n";
        }
        else {
            print $$rp{'errmsg'};
        }
}

sub gen_key {
    # generate a secret key
    my $secretkey;
    my @chars = split( /\s+/, "a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 ! @ # $ % ^ & * ( ) _ + - = [ ] { } , < . > / ? ; : ' \"" );
    srand;
    for ( my $i = 0; $i <= 20; $i++ ) {
        my $rand = int( rand 32 );
        $secretkey .= $chars[$rand];
    }
    return($secretkey);
}
