Kerala Cyber Warriors
KCW Uploader V1.1

Path : /scripts/
File Upload :
Current File : //scripts/gather_update_logs_setupcrontab

#!/usr/local/cpanel/3rdparty/bin/perl
# cpanel - scripts/gather_update_logs_setupcrontab
#                                               Copyright(c) 2022 cPanel, L.L.C.
#                                                           All rights Reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited

# copying clamav_setupcrontab only because most recent solution is too new:
# CPANEL-33654. So next cron added should use that instead, and this code should
# be replaced with it after some time.
package scripts::gather_update_logs_setupcrontab;

=head1 NAME

gather_update_logs_setupcrontab

=head1 SYNOPSIS

gather_update_logs_setupcrontab [ off --help ]

=head1 DESCRIPTION

This script adds a line to the system cron for the update gatherer script.

The optional argument 'off' will remove the line.

=cut

use lib '/var/cpanel/perl';
use Cpanel::UpdateGatherer::Std;

use parent 'Cpanel::HelpfulScript';

use constant _OPTIONS          => ();
use constant CRONTAB_FILE_PATH => '/etc/cron.d/cpanel-analytics';
use constant { CRONTAB_TYPE_USER => 0, CRONTAB_TYPE_FILE => 1, CRONTAB_TYPE_MAX => 1 };

use Try::Tiny;

use Cpanel::ConfigFiles            ();
use Cpanel::SafeRun::Object        ();
use Cpanel::Autodie                ();
use Cpanel::Transaction::File::Raw ();

__PACKAGE__->new()->run(@ARGV) if !caller;

sub run ( $self, @args ) {
    my $match   = 'gather_update_log_stats';
    my $command = "$Cpanel::ConfigFiles::CPANEL_ROOT/scripts/gather_update_log_stats --logfile /var/cpanel/updatelogs/last --upload > /dev/null 2>&1";
    my $enable  = 1;
    if ( @args && $args[0] =~ m/^off$/i ) {
        $enable = 0;
    }

    # If there is an entry in root's crontab, mark it for deletion.
    my $has_match_root = 0;
    my @crontab_root   = get_crontab_root();
    foreach my $line (@crontab_root) {
        next if $line =~ m/^#/;
        if ( $line =~ m/$match/ ) {
            $has_match_root = 1;
            last;
        }
    }

    # Do the same for the file in /etc/cron.d.
    # FIXME: This is probaby too DRY, but it's also dead simple.
    my $has_match_file = 0;
    my @crontab_file   = get_crontab_file(CRONTAB_FILE_PATH);
    foreach my $line (@crontab_file) {
        next if $line =~ m/^#/;
        if ( $line =~ m/$match/ ) {
            $has_match_file = 1;
            last;
        }
    }

    umask 077;    # See SEC-408.

    my $ex;

    if ($enable) {
        if ( !$has_match_file ) {
            push @crontab_file, generate_crontab_entry( $command, CRONTAB_TYPE_FILE );
            try {
                write_crontab_file(@crontab_file);
            }
            catch {
                $ex = $_;
            };
        }
    }
    else {
        if ($has_match_file) {
            @crontab_file = remove_crontab_entry( $match, @crontab_file );
            try {
                write_crontab_file(@crontab_file);
            }
            catch {
                $ex = $_;
            };
        }
    }

    # Always clean the root crontab entry if things didn't go badly when writing the file.
    if ( $has_match_root && !defined $ex ) {
        @crontab_root = remove_crontab_entry( $match, @crontab_root );
        try {
            write_crontab_root(@crontab_root);
        }
        catch {
            $ex = $_;
        };
    }

    if ($ex) {
        return 0;
    }

    return 1;
}

sub generate_crontab_entry ( $command, $entry_type = CRONTAB_TYPE_USER ) {
    die "no command given"        if !$command;
    die "unrecognized entry type" if ( $entry_type < 0 || $entry_type > CRONTAB_TYPE_MAX );

    my $rt     = int( rand(2.9999999) );
    my $hour   = int( rand(6) );
    my $minute = int( rand(60) );

    # With about 1/3rd probability, choose to run between 21:00 and 23:59 instead of 00:00 to 06:59.
    if ( $rt == 0 ) {
        $hour = ( 24 - int( rand(4) ) );
    }
    if ( $hour == 24 ) {
        $hour = 0;
    }

    my $entry = "$minute $hour * * * ";

    # If this is for a crontab file, add the user name before the command.
    $entry .= "root " if $entry_type == CRONTAB_TYPE_FILE;

    $entry .= $command;

    return $entry;
}

sub remove_crontab_entry ( $match, @crontab ) { return grep( !/$match/, @crontab ) }

sub get_crontab_root {
    my $crontab_sro = Cpanel::SafeRun::Object->new_or_die(
        'program' => '/usr/bin/crontab',
        'args'    => ['-l'],
    );
    my @crontab = split( /\n/, $crontab_sro->stdout() );
    return @crontab;
}

sub get_crontab_file ($path) {
    my @crontab;
    local $/;

    try {
        Cpanel::Autodie::open( my $fh, '<', $path );
        my $contents = <$fh>;
        @crontab = split( /\n/, $contents ) if defined $contents;
        close $fh;
    }
    catch {
        my $ex = $_;
        die $ex unless $ex->error_name() eq 'ENOENT';
    };

    return @crontab;
}

sub write_crontab_root (@crontab) {
    Cpanel::Autodie::open( my $cron_in, '>', '/scripts/.crontab' );
    foreach my $line (@crontab) {
        Cpanel::Autodie::print( $cron_in, $line . "\n" );
    }
    close $cron_in;
    system 'crontab', '/scripts/.crontab';
    unlink '/scripts/.crontab';
    return 1;
}

sub write_crontab_file (@crontab) {
    my $contents = join( "\n", @crontab ) . "\n";
    my $txn      = Cpanel::Transaction::File::Raw->new(
        'path'        => CRONTAB_FILE_PATH,
        'ownership'   => [ 0, 0 ],
        'permissions' => 0600,
    );
    $txn->set_data( \$contents );
    $txn->save_and_close_or_die();
    return 1;
}

1;

-=[ KCW uplo4d3r c0ded by cJ_n4p573r ]=-
Ⓒ2017 ҠЄГѦLѦ СүѣЄГ ЩѦГГіѺГՏ