#!/usr/bin/bash
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

use experimental 'smartmatch';
use strict;
use Getopt::Std;

my %opts = ();
my $original_files_dir = '/usr/local/cpanel/base/3rdparty/cloudlinux/original/';
getopts( 'iud',\%opts );

unless ( $> == 0 ) {
    warn "The program should be started under root privileges only!\n";
    exit(0);
}

my $theme_location = '/usr/local/cpanel/base/frontend';

my %symlinks = (
);

my @data = (
    {
        src => q#/usr/share/l.v.e-manager/cpanel/cgi/CloudLinux.cgi#,
        dst => q#/usr/local/cpanel/whostmgr/docroot/cgi/CloudLinux.cgi#,
        bcp => 1,
        check_orig => 1,
    },
# substitution for lveversion.cgi which is obsolete
    {
        src => q#/usr/share/l.v.e-manager/cpanel/resource_usage/LVEInfo.pm#,
        dst => q#/usr/local/cpanel/Cpanel/LVEInfo.pm#,
        bcp => 1,
        check_orig => 0,
    },
    {
        src => q#/usr/share/l.v.e-manager/cpanel/lveversion/cl-selector.cgi#,
        dst => q#/usr/local/cpanel/base/3rdparty/cloudlinux/cl-selector.cgi#,
    },
    {
        src => q#/usr/share/l.v.e-manager/cpanel/lveversion/cloudlinux-selector.cgi#,
        dst => q#/usr/local/cpanel/base/3rdparty/cloudlinux/cloudlinux-selector.cgi#,
    },

# javascript moved from lveselect.html to separate files
    {
        src => q#/usr/share/l.v.e-manager/commons/js/cl-message-handler.js#,
        dst => q#/usr/local/cpanel/base/3rdparty/cloudlinux/cl-message-handler.js#,
    },
    {
        src => q#/usr/share/l.v.e-manager/commons/js/alt-selector.js#,
        dst => q#/usr/local/cpanel/base/3rdparty/cloudlinux/alt-selector.js#,
    },
    {
        src => q#/usr/share/l.v.e-manager/commons/js/alt-ruby-selector.js#,
        dst => q#/usr/local/cpanel/base/3rdparty/cloudlinux/alt-ruby-selector.js#,
    },
    {
        src => q#/usr/share/l.v.e-manager/commons/js/jquery/#,
        dst => q#/usr/local/cpanel/base/3rdparty/cloudlinux/#,
    },
    {
        src => q#/usr/share/l.v.e-manager/commons/js/images/#,
        dst => q#/usr/local/cpanel/base/3rdparty/cloudlinux/#,
    },
# for new LVEManager plugin with SPA
    {
        src => q#/usr/share/l.v.e-manager/cpanel/spa/assets/#,
        dst => q#/usr/local/cpanel/whostmgr/docroot/3rdparty/cloudlinux/#,
    },
    {
        src => q#/usr/share/l.v.e-manager/cpanel/configs/LveManager/META.pm#,
        dst => q#/usr/local/cpanel/Cpanel/Config/ConfigObj/Driver/LveManager/META.pm#,
    },
    {
        src => q#/usr/share/l.v.e-manager/cpanel/configs/LveManager.pm#,
        dst => q#/usr/local/cpanel/Cpanel/Config/ConfigObj/Driver/LveManager.pm#,
    },
);

my @theme_data = (
    # resource usage
    {
        src => q#/usr/share/l.v.e-manager/cpanel/resource_usage/resource_usage.live.pl#,
        dst => q#resource_usage/resource_usage.live.pl#,
    },
    # selectors
    {
        src => q#/usr/share/l.v.e-manager/cpanel/lveversion/ruby-selector.html.tt#,
        dst => q#lveversion/ruby-selector.html.tt#,
    },
    {
        src => q#/usr/share/l.v.e-manager/cpanel/lveversion/ruby-selector.tmpl#,
        dst => q#lveversion/ruby-selector.tmpl#,
    },
    {
        src => q#/usr/share/l.v.e-manager/cpanel/lveversion/python-selector.html.tt#,
        dst => q#lveversion/python-selector.html.tt#,
    },
    {
        src => q#/usr/share/l.v.e-manager/cpanel/lveversion/nodejs-selector.html.tt#,
        dst => q#lveversion/nodejs-selector.html.tt#,
    },
    {
        src => q#/usr/share/l.v.e-manager/cpanel/lveversion/php_selector.live.pl#,
        dst => q#lveversion/php_selector.live.pl#,
    },
    {
        src => q#/usr/share/l.v.e-manager/cpanel/lveversion/ruby-selector-check.tmpl#,
        dst => q#lveversion/ruby-selector-check.tmpl#,
    },
    {
        src => q#/usr/share/l.v.e-manager/cpanel/wpos/wpos.live.pl#,
        dst => q#lveversion/wpos.live.pl#,
    },
);

my %original_files = (
    'CloudLinux.cgi' => {
        src => q#/usr/local/cpanel/whostmgr/docroot/cgi/CloudLinux.cgi#,
    },
    'lvechart.cgi' => {
        src => q#/usr/local/cpanel/base/3rdparty/lvechart.cgi#,
    },
    'LVEInfo.pm' => {
        src => q#/usr/local/cpanel/Cpanel/LVEInfo.pm#,
    },
    'resourceusage.auto.tmpl' => {
        src => q#/usr/local/cpanel/base/frontend/paper_lantern/stats/resourceusage.auto.tmpl#,
        dst => q#stats/resourceusage.auto.tmpl#,
        link => q#stats/resourceusage.html#,
        theme => 1,
        themes => ['paper_lantern'],

    },
    'resourceusagedetails.auto.tmpl' => {
        src => q#/usr/local/cpanel/base/frontend/paper_lantern/stats/resourceusagedetails.auto.tmpl#,
        dst => q#stats/resourceusagedetails.auto.tmpl#,
        link => q#stats/resourceusagedetails.html#,
        theme => 1,
        themes => ['paper_lantern'],
    },
);

if ( $opts{i} or $opts{u} ) {
    backup_original_files();

    for my $i ( @data ) {
        if ( -e $i->{src} ) {
            if ( $i->{bcp} ) {
                make_backup( $i->{dst}, 0, $i->{check_orig} ? 1 : 0 );
            }
            else {
                unlink $i->{dst} if -e $i->{dst};
            }
            check_dir( $i->{dst} );
            system( "/bin/cp", "-Rf", $i->{src}, $i->{dst} );
            if ($symlinks{$i->{dst}} && ! -e $symlinks{$i->{dst}}) {
                # create symlinks for .min.js files
                system("/bin/ln", "-s", $i->{dst}, $symlinks{$i->{dst}});
            }
        }
    }
    if(! -e "/usr/local/cpanel/base/3rdparty/cloudlinux/assets") {
        system("/bin/ln", "-s", "/usr/local/cpanel/whostmgr/docroot/3rdparty/cloudlinux/assets",
               "/usr/local/cpanel/base/3rdparty/cloudlinux/assets");
    }

    # reset dynamical items cache
    system("/bin/rm", "-f", '/var/cpanel/dynamicaclitems.cache');

    for my $theme ( @{ get_themes_list() } ) {
        for my $i ( @theme_data ) {
            my $path_src = $i->{src};
            if ( -e $path_src ) {
                my $path_dst = $theme . '/' . $i->{dst};
                unlink $path_dst if -e $path_dst;
                check_dir($path_dst);
                system( "/bin/cp", "-Rf", $path_src, $path_dst );
            }
        }
        if ( $opts{u} ) {
            unpatch_index($theme);
        }
        patch_index($theme);
        check_dynamicui($theme);
    }
    install_locales();
    update_rvskin();
    process_obsoletes();
}
elsif ( $opts{d} ) {
    for my $i ( @data ) {

        if ($symlinks{$i->{dst}} && -e $symlinks{$i->{dst}}) {
            # create symlinks for .min.js files
            system("/bin/rm", "-f", $symlinks{$i->{dst}});
        }

        if ( -f $i->{dst} ) {
            system( "/bin/rm", "-Rf", $i->{dst}) if -e $i->{dst};
            my $bcp = $i->{dst} . '.saved';
            my $orig = $i->{dst} . '.orig';
            if ( -e $orig ) {
                system( "/bin/mv", $orig, $i->{dst} );
                unlink $bcp if -e $bcp;
            }
            elsif ( -e $bcp ) {
                system( "/bin/mv", $bcp, $i->{dst} );
            }
        } else {
            my $dst = $i->{dst}.(split(/\//, $i->{src}))[-1];
            system( "/bin/rm", "-Rf", $dst) if -e $dst;
        }
    }
    for my $theme ( @{ get_themes_list() } ) {
        for my $item ( @theme_data ) {
            my $path = $theme . '/' . $item->{dst};
            system( "/bin/rm", "-Rf", $path) if -e $path;
        }
        unpatch_index($theme);
    }
    update_rvskin();
    restore_original_files();
}

sub check_dynamicui {
    my ( $path ) = @_;
    my $dynamicui_path = q#/usr/local/cpanel/base/frontend/paper_lantern/dynamicui#;
    my $dynamicui_conf = q#/usr/local/cpanel/base/frontend/paper_lantern/dynamicui.conf#;
    my $d_path = join( q{/}, $path, 'dynamicui' );
    unless ( -e join( q{/}, $path, 'dynamicui.conf' ) ) {
        system( '/bin/cp', $dynamicui_conf, $path );
    }
    return unless -d $dynamicui_path;
    opendir my $dyn_x3, $dynamicui_path or return;
    mkdir $d_path unless -d $d_path;
    for my $d ( readdir $dyn_x3 ) {
        next if $d eq '.' or $d eq '..';
        next unless $d =~ /(?:enduserlve|lvephpsel)/i;
        my $item_path = join( q{/}, $dynamicui_path, $d );
        my @params = ( '/bin/cp', $item_path, $d_path );
        system( @params ) unless -e join( q{/}, $d_path, $d );
    }
    closedir $dyn_x3;
}

sub update_rvskin {
    system( '/root/rvadmin/autoupdatewhmaddon.pl' ) if -x '/root/rvadmin/autoupdatewhmaddon.pl';
}

sub process_obsoletes {
    my @deletes = (
        '/usr/local/cpanel/base/3rdparty/lveversion.cgi',
        '/usr/local/cpanel/base/frontend/x3/lveversion/lveselect.tmpl',
        '/usr/local/cpanel/base/3rdparty/lvechart.cgi',
        '/usr/local/cpanel/base/3rdparty/lvechart.cgi.saved',
    );
    for my $i ( @deletes ) {
        unlink $i if -e $i;
    }
}

sub get_themes_list {
    my @dirs;
    return [] unless -d $theme_location;
    opendir my $dir, $theme_location or return [];
    for my $d ( readdir $dir ) {
        next if $d eq '.' or $d eq '..';
        my $path = $theme_location . '/' . $d;
        next if -l $path;
        next unless -d $path;
        push @dirs, $path;
    }
    closedir $dir;
    return \@dirs;
}

sub check_dir {
    my ( $path ) = @_;
    my $dirpath = substr( $path, 0, rindex( $path, '/' ) );
    system("/bin/mkdir", "-p", $dirpath) unless -d $dirpath;
}

sub make_backup {
    my ( $path, $to_copy, $check_orig ) = @_;
    return unless -e $path;
    my $bcp;
    if ( $check_orig and detect_orig( $path ) ) {
        $bcp = $path . '.orig';
    }
    else {
        $bcp = $path . '.saved';
        unlink $bcp if -e $bcp;
    }
    if ( $to_copy ) {
        system( "/bin/cp", $path, $bcp );
    }
    else {
        system( "/bin/mv", $path, $bcp );
    }
}

sub detect_orig {
    my ( $path ) = @_;
    return 0 unless -e $path;
    open my $f, '<', $path or return 0;
    my ( $str_count, $str_limit ) = ( 0, 30 );
    while ( my $line = <$f> ) {
        last if $str_count > $str_limit;
        if ( index( $line, '#WHMADDON:lvemanager:CloudLinux Manager' ) >= 0 ) {
            # This is the cPanel original file
            return 1;
        }
        $str_count++;
    }
    close $f;
    return 0;
}

sub patch_index {
    my ( $theme_path ) = @_;
    my $path = $theme_path . '/branding/index.html';
    return unless -e $path;

    my ( $pc, $ll, $op ) = ( # percent_key, lve_limits, other_params
        q#,pc) display=#,
        q#lvecpu|lvemem|lvepmem|lvemep|lveproc|lveiop|lveiops|lvequota#,
        q#<cpanelif !$hascloudlinux || 1>#,
    );
    my $search_pattern = qr/
                        ( \n \s* \<cpanelif\s\$hascloudlinux\>)
                            (?= \s+ <\?\s?cp\sStatsBar::stat )
                                ( .+? ,max ) .*?
                                ( ,percent[)]\s*display=lvecpu[|]lvemem[|]lvemep[|]diskusage[|]filesusage[|]bandwidthusage) .*?
                                ( ,infinitylang .+? \<\/cpanelif\> \s*? )
                            \n
                    /sx;

    my $second_pattern = qr/(\<cpanelif\s!\$hascloudlinux\>)/s;

    # read current template content
    open my $i, '<', $path or return;
    my $data = do { local $/; <$i> };
    close $i;

    # change template
    $data =~ s/$search_pattern/$1$2$pc$ll$4\n/;
    $data =~ s/$second_pattern/$op/;

    # save new template content
    open my $o, '>', $path or return;
    print $o $data;
    close $o;
}

sub unpatch_index {
    my ( $theme_path ) = @_;
    my $path = $theme_path . '/branding/index.html';
    my $saved = $theme_path . '/branding/index.saved';
    my $orig = $theme_path . '/branding/index.orig';
    unlink $saved if -e $saved;
    unlink $orig if -e $orig;
    return unless -e $path;

    my ($old_ps, $ps, $oc) = ( # old_param_string, param_string, original_conditions
        q#lvecpu|lvemem|lvemep|#,
        q#rowtype,item,count,max,percent) display=lvecpu|lvemem|lvemep|diskusage|filesusage|bandwidthusage,#,
        q#<cpanelif !$hascloudlinux>#,
    );

    my $search_pattern = qr/(rowtype,item,count,max,pc[)] display=.+?,)/s;
    my $second_pattern = qr/\<cpanelif\s*!\$hascloudlinux\s*[|][|]\s*1\>/s;
    my $old_search_pattern = qr/
                            ( \n \s* \<cpanelif\s\$hascloudlinux ) .+? \>
                                (?= \s+ <\?\s?cp\sStatsBar::stat )
                                    ( .+? display= ) .*?
                                    ( diskusage .+? \<\/cpanelif\> \s*? )
                            (?:\1 .+? \> \2 .*? \3)?
                            \1 .+? \> \2 .*? \3 \n
                        /sx;

    # read current template content
    open my $i, '<', $path or return;
    my $data = do { local $/; <$i> };
    close $i;

    # restore old template changes
    $data =~ s/$old_search_pattern/$1>$2$old_ps$3\n/;
    # restore new template changes
    $data =~ s/$search_pattern/$ps/;
    $data =~ s/$second_pattern/$oc/;

    # save new template content
    open my $o, '>', $path or return;
    print $o $data;
    close $o;
}

sub install_locales {
    my $src = q#/usr/share/l.v.e-manager/cpanel/locales#;
    my $dst = q#/var/cpanel/locale.local#;
    if ( -d $src ) {
        chdir $src;
        for my $file ( glob('*.yaml') ) {
            if ( -e "$dst/$file" && `/usr/bin/diff -q $dst/$file $src/$file` ) {
                # update only different files
                system("/usr/share/l.v.e-manager/cpanel/utils/merge_locales.py", "$src/$file", "$dst/$file", "$dst/$file");
            } else {
                system('/bin/cp', '-f', $file, $dst);
            }
        }
        system('/usr/local/cpanel/bin/build_locale_databases');
    }
}

sub detect_new_template_style{
    my ( $theme_path ) = @_;
    return (-e $theme_path . '/_assets/master.html.tt')
}

sub backup_original_files {
    if (!-d $original_files_dir) {
        system('/bin/mkdir', '-p', $original_files_dir);
        system('/bin/cp', '-rf', '/usr/share/l.v.e-manager/cpanel/original/.', $original_files_dir);
    } else {
        return;
    }
}

sub restore_original_files {
    return if(!-d $original_files_dir);

    my $src;

    for my $file (keys %original_files) {
        $src = $original_files_dir . $file;
        if(-e $src) {
            if($original_files{$file}{'theme'}) {
                for my $theme ( @{ get_themes_list() } ) {
                    my $path_dst = $theme . '/' . $original_files{$file}{'dst'};
                    my @tmp = split('/', $theme);
                    my $cur_theme = $tmp[@tmp-1];

                    if(grep {$cur_theme eq $_} @{$original_files{$file}{'themes'}}) {
                        system('/bin/cp', '-f', $src, $path_dst);
                        if($original_files{$file}{'link'}) {
                            system('/bin/ln', '-fs', $path_dst, $theme . '/' . $original_files{$file}{'link'})
                        }
                    }

                    if($cur_theme !~ $original_files{$file}{'exclude_themes'}) {
                        system('/bin/cp', '-f', $src, $path_dst);
                    }

                    patch_index($theme);
                    check_dynamicui($theme);
                }
            } else {
                system('/bin/cp', '-f', $src, $original_files{$file}{'src'}) if(-f $src);
            }
        }
    }
}
