#!/usr/bin/perl

# cpanel10 - /usr/local/cpanel/Cpanel/cPAddons.pm  Copyright(c) 2005 cPanel, Inc.
#                                                           All rights Reserved.
#                                         copyright@cpanel.net http://cpanel.net
# This code is subject to the cpanel license. Unauthorized copying is prohibited

use strict;
use Storable;

BEGIN { push @INC, '/usr/local/cpanel', '/usr/local/cpanel/whostmgr/docroot/cgi', '/usr/local/cpanel/cpaddons' }

use Cpanel;
use Cpanel::cPAddons;
use whmlib;
use cPAddonsConf;

use CGI;

my $html = -t STDIN ? 0 : 1;

defheader("cPAddon Scripts Client Install Manager") if $html;

my $user = CGI::param('user');

opendir USR, '/var/cpanel/users' or die "Could not open users dir: $!";
my @USERS = grep !/^\.+$/, readdir USR;
closedir USR;

my $back = '';
my $multi = 0;
if(CGI::param('action')) {
    my $xuser = CGI::param('user');
    my $xshow = CGI::param('show');
    my $xinst = CGI::param('inst');
    my $dispuser = defined $xuser ? "user=$xuser&" : '';
    $back = qq(<p align="center">[<a href="$ENV{SCRIPT_NAME}?${dispuser}show=$xshow">Back</a>]</p>\n);
    if( CGI::param('action') eq 'up' ) {
        upgrade($xuser, $xinst, $back);
        exit;
    } elsif( CGI::param('action') eq 'un' ) {
        uninstall($xuser, $xinst, $back);
        exit;
    } elsif( CGI::param('action') eq 'upgradeall' ) {
        print "<b>Upgrading all installs ";
        print $xuser ? "for $xuser</b><br />" : "serverwide</b><br />";
        $multi = 1;
    } elsif( CGI::param('action') eq 'uninstallnonwhm' ) {
        print "<b>Uninstalling all installs of addons not installed via WHM ";
        print $xuser ? "for $xuser</b><br />" : "serverwide</b><br />";
        if(!CGI::param('verified')) {
            print qq(<p><b>Are you sure you want to uninstall this?</b></p>\n<a href="$ENV{SCRIPT_NAME}?action=uninstallnonwhm&user=$xuser&show=$xshow&verified=1">Yes I am sure I want to do this.</a>\n$_[2]);
            exit;
        }
        $multi = 1;
    }
}

if(!defined $user && !-t STDIN) {
    my $opts;
    for(sort @USERS) {
        $opts .= qq(              <option name="$_">$_</option>\n);
    }
    print <<FORM;
        <form action="$ENV{SCRIPT_NAME}" method="post">
           Show
           <select name="show">
              <option value="up" selected>All Installs that need updated</option>
              <option value="in">All Installs that are no longer installed in WHM</option>
              <option value="">Every Install</option>
           </select>
           for
           <select name="user">
              <option value="">All Users</option>
$opts
           </select>
           <input type="submit" value="Manage" />
        </form>
        <form action="$ENV{SCRIPT_NAME}" method="post">
           <select name="action">
              <option value="upgradeall" selected>Upgrade all installs that need it</option>
              <option value="uninstallnonwhm">Uninstall all Installs that are no longer installed in WHM</option>
           </select>
           for
           <select name="user">
              <option value="">All Users</option>
$opts
           </select>
           <input type="submit" value="Go" />
        </form>
FORM
    exit;
}

$user = $ARGV[0] || '' if !$user;

my $dump = CGI::param('dumpreg');
if($dump && $user) {
    use Data::Dumper;
    my $cp = Cpanel->new();
    $cp->initcp($user);
    print "<b>Registry Info for $Cpanel::homedir/.cpaddons/$dump</b><pre>\n";
    print Data::Dumper::Dumper Storable::retrieve("$Cpanel::homedir/.cpaddons/$dump");
    print "</pre>\n";
    exit;
}

my $show = CGI::param('show') | '';

if(grep /^\Q$user\E$/, @USERS) {
    @USERS = ();
    $USERS[0] = $user;
    if($html) {
        print qq(<p><a href="$ENV{SCRIPT_NAME}?show=$show&user=">View All Users</a></p>\n);
    }
}

if($html) {
    print qq(<p><b><a href="$ENV{SCRIPT_NAME}?">Main Page</a></b></p>\n); # the  "?" is not a mistake
    if($show eq 'up' || $show eq 'in') {
        print qq(<p><a href="$ENV{SCRIPT_NAME}?show=&user=$user">Show All Installs</a></p>\n);
        print qq(<p><a href="$ENV{SCRIPT_NAME}?show=up&user=$user">Show All Installs that need updated</a></p>\n) if $show ne 'up';
        print qq(<p><a href="$ENV{SCRIPT_NAME}?show=in&user=$user">Show All Installs that are no longer installed in WHM</a></p>\n) if $show ne 'in';
    } else {
        $show = '';
        print <<SHW;
            <p><a href="$ENV{SCRIPT_NAME}?show=up&user=$user">Show All Installs that need updated</a></p>
            <p><a href="$ENV{SCRIPT_NAME}?show=in&user=$user">Show All Installs that are no longer installed in WHM</a></p>
SHW
    }
}
print $html ? qq(<table>\n<tr class="scellheader"><td>User</td><td>Addon</td><td>Latest</td><td>Version</td><td><a href="/cgi/cpaddons.pl">Currently installed in WHM</a></tr>) : '' if !$multi;
my $tdshade = 'tdshade2';

my %cpaddoninfo;
my %installedx = %cPAddonsConf::inst;
my $notify     = defined $ARGV[0] && $ARGV[0] eq '--notify' ? 1 : 0;

for my $usr (sort @USERS) {
    my $cp = Cpanel->new();

    $cp->initcp($usr);
    next if $Cpanel::user ne $usr;
    next if !-d "$Cpanel::homedir/.cpaddons/";
    my $needsupdated = '';

    if(opendir REG, "$Cpanel::homedir/.cpaddons/") {
        my @installed = grep /\.\d+$/, readdir REG;
        close REG;
        for my $reg(sort @installed) {
            my ($base) = $reg =~ m/(.*)\.\d+$/;
            if(open STR, "$Cpanel::homedir/.cpaddons/$reg") {
                my $regst = Storable::fd_retrieve(\*STR);
                close STR;
                my $vers = $regst->{version} || 'registry did not contain version';
                $cpaddoninfo{$usr}->{$base}->{$reg} = $vers;
                $needsupdated .= "cPAddon $reg is v$vers and the latest available is v$installedx{$base}->{version}\n" if $installedx{$base}->{version} ne $vers;
            } else {
                $needsupdated .= "cPAddon $reg could not be checked: $!\n";
                $cpaddoninfo{$usr}->{$base}->{$reg} = 'Could not determine version';
            }
            if($html) {
                my $upgrade = '';
                my $uninstall = '';
                my $latest = $installedx{$base}->{version};
                eval "use $base;";
                if(!$@) {
                    no strict 'refs';
                    my $hr = ${"$base\:\:meta_info"} || {};
                    $latest = $hr->{version} || 'Could not determine latest version';
                }  else {
                    $latest .= " Module Error <!-- $@ -->";
                }
                my $dontprint = 0;
                my $img = $cPAddonsConf::inst{$base}->{version} && $base ? 'green' : 'red';
                if($img eq 'green' && $latest =~ m/Module Error/) {
                    $img = 'yellow';
                }
                my $col = $latest eq $cpaddoninfo{$usr}->{$base}->{$reg} ? '00aa00' : 'FF0000';
                if($show eq 'in') {
                    $dontprint = 1 if $installedx{$base}->{'version'};
                }
                if($show eq 'up') {
                    $dontprint = 1 if $latest eq $cpaddoninfo{$usr}->{$base}->{$reg}; # && $img ne 'red';
                }
                if(!$dontprint) {
                    unless($latest =~ m/Module Error/ || $cpaddoninfo{$usr}->{$base}->{$reg} =~ m/^registry did/) {
                        my ($v, $c, $n) = split /\:\:/, $base;
                        $uninstall = qq( (<a href="$ENV{SCRIPT_NAME}?action=un&user=$usr&inst=$reg&show=$show">uninstall</a>)) unless $img eq 'yellow';
                        $upgrade = qq( (<a href="$ENV{SCRIPT_NAME}?action=up&user=$usr&inst=$reg&show=$show">upgrade</a>))
                          if $latest ne $cpaddoninfo{$usr}->{$base}->{$reg} && $img ne 'yellow' && -d "/usr/local/cpanel/cpaddons/$v/$c/$n/";
                    }
                    if( CGI::param('action') eq 'upgradeall' ) {
                        upgrade($usr, $reg, '<hr />') if $upgrade;
                    } elsif( CGI::param('action') eq 'uninstallnonwhm' ) {
                        uninstall($usr, $reg, '<hr />') if $uninstall && $img eq 'red';
                    } else {
                        $tdshade = $tdshade eq 'tdshade2' ? 'tdshade1' : 'tdshade2';
                        print qq(<tr class="$tdshade"><td><a href="$ENV{SCRIPT_NAME}?show=$show&user=$usr">$usr</a></td><td><a target="_blank" href="$ENV{SCRIPT_NAME}?dumpreg=$reg&user=$usr">$reg</a></td><td>$latest</td><td><font color=#$col>$cpaddoninfo{$usr}->{$base}->{$reg}</font>$upgrade<td><img src="/$img\-status.gif" />$uninstall</td></tr>\n);
                    }
                }
            } else {
                my $inst = exists $installedx{$base} ? '' : '[not in WHM list]';
                print "$usr $reg Current: $installedx{$base}->{version} Installed: $cpaddoninfo{$usr}->{$base}->{$reg} $inst\n" if !$notify;
            }
        }
        if($needsupdated && !$html && -e "$Cpanel::homedir/.cpaddons_notify" && $notify) {
            open SENDMAIL, '|/usr/sbin/sendmail -t';
            print SENDMAIL "To: $Cpanel::USERDATA{'contact_email'}\n";
            print SENDMAIL "From: root\n";
            print SENDMAIL "Subject: You Have Addon CGI Script Installs That Need Upgraded)\n\n";
            print SENDMAIL "Hello $usr,\nBelow is a list of your addon cgis that need updated.\n";
            print SENDMAIL "Please login to cPanel and update them right away.\n";
            print SENDMAIL "Please contact your host if you have any questions.\n\n$needsupdated\n";
            close SENDMAIL;
        }
    } else {
       warn "Could not open registry dir for $_: $!";
    }
}

print $html ? "</table>" : '' if !$multi;
print $html ? $back : '' if $multi;

#### funkshuns ##

sub upgrade { domainpgasuser('Upgrading', 'upgrade', @_) }

sub uninstall {
    if(CGI::param('verified')) {
        domainpgasuser('Uninstalling', 'uninstall', @_);
    } else {
        print qq(<p><b>Are you sure you want to uninstall this?</b></p>\n<a href="$ENV{SCRIPT_NAME}?action=un&user=$_[0]&inst=$_[1]&show=$show&verified=1">Yes I am sure I want to do this.</a>\n$_[2]);
    }
}

sub domainpgasuser {
    my($label, $akshn, $u, $r, $back) = @_;
    my ($addon) = $r =~ m/^(.*)\.\d+$/;
    my %input = (asuser => $u, action => $akshn, workinginstall => $r, addon => $addon);
    print "$label $u $r installation here...<br />\n";
    local $ENV{CPASUSER} = $u;
    local $ENV{CPNONAVFORPARENT} = 1;
    Cpanel::cPAddons::cPAddons_mainpg(\%input);
    print "<br />\n$back\n";
}
