#!/usr/bin/perl

# cpanel10 - cpaddons.pl 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;

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

mkdir  '/usr/local/cpanel/cpaddons' if !-d  '/usr/local/cpanel/cpaddons';

use Cpanel;
use Cpanel::HttpRequest;

#use Cpanel::cPAddons;
use whmlib;
eval "use cPAddonsConf;";
if($@) {
    %cPAddonsConf::vend = ();
    %cPAddonsConf::inst = ();
}
use CGI;

my %OwnVend = %cPAddonsConf::vend;
my %Current = %cPAddonsConf::inst;

my %vendors = (
#    FooBar => 'url here',
);
# in config FooBar => 'string to pass to url ???' # how with cpanelsync ??

my $basesyncdir = '/cpanelsync/cpaddons'; # no trailing slash
my $listage = 14400; # 4 hours in seconds
my %Availab;

defheader("cPAddons Script Server Installer/Updater");

require '/scripts/cpsources.pl';
my %CPSRC = loadcpsources();

if( ( (stat '/usr/local/cpanel/cpaddons/cPAddonsAvailable.pm')[9] + $listage) < time() || CGI::param('force') ) {
    Cpanel::HttpRequest->new()->request(
        'host'     => $CPSRC{HTTPUPDATE},
        'url'      => "$basesyncdir/cPAddonsAvailable.pm",
        'destfile' => "/usr/local/cpanel/cpaddons/cPAddonsAvailable.pm"
    );

    for my $vnd (keys %OwnVend) {
        next if !exists $vendors{$vnd} || ! $vnd;
        system '/scripts/cpanelsync', $vendors{$vnd}, "$basesyncdir/cPAddonsAvailable/$vnd.pm", '/usr/local/cpanel/cpaddons/cPAddonsAvailable';
        eval "use cPAddonsAvailable\:\:$vnd;";
        if($@) {
            print "Warning: Vendor List failed to be included: $@<br />Contact $vnd for support.<br />";
        } else {
            no strict 'refs';
            for (keys %{"cPAddonsAvailable\:\:$vnd\:\:list"}) {
                next if $_ !~ m/^\Q$vnd\E\:\:/;
                $Availab{$_} = ${"cPAddonsAvailable\:\:$vnd\:\:list"}{$_};
            }
        }
    }
} else {
    print qq(<p><a href="$ENV{SCRIPT_NAME}?force=1">Refresh List of available Addons</a></p>\n);
}

#eval "use cPAddonsAvailable;";
eval q{require "/usr/local/cpanel/cpaddons/cPAddonsAvailable.pm";};

if($@) {
    print "<p>Sorry - The list of available addons could not be found or fetched!</p> <!-- $@ -->\n";
    exit;
}

%Availab = (%Availab, %cPAddonsAvailable::list);
#    'cPanel::Test::Install' => {
#        VERSION => '0.1',
#       version => '1.4',
#   },
if(CGI::param('action') eq 'upvend') {
    print "Update vendor config here";
} elsif(CGI::param('action') eq 'rmpm') {
    my $mod = CGI::param('mod');
    if($mod !~ m/^\w+\:\:\w+\:\:\w+$/) {
        print "Invalid addon, Are you trying to be sneaky?";
        exit;
    }
    $mod =~ s/\:\:/\//g;
    $mod = "/usr/local/cpanel/cpaddons/$mod";
    my $back = qq(<p>[<a href="$ENV{SCRIPT_NAME}?">Back</a>]</p>\n);
    if(!-d "$mod/") {
        if(-e "$mod.pm") {
            if(unlink "$mod.pm") {
                print ".pm removed! $back";
            } else {
                print ".pm could not be removed: $! $back";
            }
        } else {
            print "That .pm is already gone. $back";
        }
    } else {
        print "This is still installed, .pm not removed. $back";
    }
} elsif(CGI::param('action') eq 'update') {
    print "Updating Local Addons Database...<br /><br />";
    system '/scripts/cpanelsync', $CPSRC{HTTPUPDATE}, "$basesyncdir/cPAddonsMD5", '/usr/local/cpanel/cpaddons/cPAddonsMD5';
    for my $vnd (keys %OwnVend) {
        next if !exists $vendors{$vnd} || ! $vnd;
        system '/scripts/cpanelsync', $vendors{$vnd}, "$basesyncdir/cPAddonsMD5/$vnd.pm", '/usr/local/cpanel/cpaddons/cPAddonsMD5';
        eval "use cPAddonsMD5\:\:$vnd;";
    }
    my $keyval = '';
    print "<br />\n";
    for my $amod (sort keys %Availab) {
        if( CGI::param($amod) ) {
            if($Current{$amod}->{VERSION} ne $Availab{$amod}->{VERSION} || CGI::param('force')) {
                print "<p><b>Installing $amod...</b></p>\n";
                my($v, $c, $n) = split /\:\:/, $amod;
                my $url = $v eq 'cPanel' ? $CPSRC{HTTPUPDATE} : $vendors{$v};
                if(!$url) {
                    print "Could not determine url for $amod. Contact $v for support.<br />\n";
                    next;
                }
                mkdir "/usr/local/cpanel/cpaddons/$v/";
                mkdir "/usr/local/cpanel/cpaddons/$v/$c/";
                system '/scripts/cpanelsync', $url, "$basesyncdir/$v/$c/$n", "/usr/local/cpanel/cpaddons/$v/$c/$n";
                Cpanel::HttpRequest->new()->request(
                    'host' => $url,
                    'url'  => "$basesyncdir/$v/$c/$n.pm",
                    'destfile' => "/usr/local/cpanel/cpaddons/$v/$c/$n.pm"
                );
            }
            $keyval .= qq(   '$amod' => { version => '$Availab{$amod}->{version}', VERSION => '$Availab{$amod}->{VERSION}' },\n);
        } else {
            if($Current{$amod}->{VERSION} || CGI::param('force')) {
                print "<p><b>Uninstalling  $amod...</b></p>\n";
                chdir '/usr/local/cpanel/cpaddons' or die "Uninstall - Could not go into addons dir: $!";
                my($v, $c, $n) = split /\:\:/, $amod;
                chdir "$v/$c" or die $! if -d "$v/$c";
                system('rm', '-rf', $n);
                if(!-d $n) {
                    print "$n removed ok...<br />\n";
                    # unlink "$n.pm" or print "$n.pm not removed: $!<br />\n";# leave module there so uninstalls can be done
                } else {
                    print "Error: $amod could not be removed!<br />\n";
                }
            }
            $keyval .= qq(   '$amod' => { version => 0, VERSION => 0 },\n);
        }
    }
    if(open CONF, '>', '/usr/local/cpanel/cpaddons/cPAddonsConf.pm') {
        my $vendx;
        for(keys %OwnVend) {
            $vendx = "\n" if !$vendx;
            $vendx .= qq(   '$_' => '$OwnVend{$_}',\n);
        }
        my $cont = join '', <DATA>;
        $cont =~ s/\[\% keyval \%\]/$keyval/;
        $cont =~ s/\[\% vendor \%\]/$vendx/;
        print CONF $cont;
        close CONF;
    } else {
        print "Could not write to config file: $!";
    }
    print qq(<p align="center">[<a href="$ENV{SCRIPT_NAME}?">Back</a>]</p>\n);
} else {
    print qq(<form action="$ENV{SCRIPT_NAME}" method="post">\n<input type="hidden" name="action" value="update" />\n);
    print qq(Force/Refresh installs/updates/uninstalls even if not needed <input type="checkbox" name="force" value="1" /><br /><br />\n);
    my $do_pm_warn = 0;
    for(sort keys %Availab) {
        my $checked = $Current{$_}->{VERSION} ? ' checked' : '';
        my ($vend, $cat, $name) = split /\:\:/, $_;
        my $unpmfile = !-d "/usr/local/cpanel/cpaddons/$vend/$cat/$name/"
                       && -e "/usr/local/cpanel/cpaddons/$vend/$cat/$name.pm"
                       ? qq( <a href="$ENV{SCRIPT_NAME}?action=rmpm&mod=$_">Remove .pm</a>**) : '';
        $do_pm_warn++ if $unpmfile;
        $cat =~ s/\_/ /g;
        $name =~ s/\_/ /g;

        print qq(<input type="checkbox"$checked name="$_" value="1" /> $vend : $cat : $name ($Availab{$_}->{version})$unpmfile<br />\n);
    }
    print qq(<input type="submit" value="Update Addon Config" /></form>\n);
    print qq(<p><b>** You should only remove the .pm file for an uninstalled cPAddon if you've <a target="_blank" href="/cgi/cpaddons_report.pl">uninstalled all installs</a> of it first or you will end up with users that have installations that are not removeable until you reinstall the module here.</b></p>\n) if $do_pm_warn;

    if(%vendors) {
        print "<hr /><p>Manage 3rd party vendors</p>\n";
        print "Form here(action=upvend): name: [config] (empty = off)";
    }
}


__END__
# 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
package cPAddonsConf;

our %inst = (
[% keyval %]);

our %vend = ([% vendor %]);

1;
