#!/usr/local/cpanel/3rdparty/bin/perl

# cpanel - autofixer2/clean_92_cruft               Copyright 2021 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

package autofixer2::clean_92_cruft;

use strict;
use warnings;
use v5.30;

use Carp            ();
use Errno           ();
use Cpanel::Version ();

use Try::Tiny;

use feature 'signatures';
no warnings 'experimental::signatures';

use constant {
    MIN_VER => 92,
};

exit __PACKAGE__->new( { 'argv' => \@ARGV } )->run() unless caller();

sub new ( $class, $opts = {} ) {
    Carp::croak 'opts is not a hash ref!' unless ref $opts eq 'HASH';
    Carp::croak 'argv option is not an array ref!' if exists $opts->{'argv'} && ref $opts->{'argv'} ne 'ARRAY';
    return bless $opts, $class;
}

sub run ($self) {

    # All returns here are exit() values.
    return 0 if int( Cpanel::Version::get_short_release_number() ) < MIN_VER;
    return 0 if $self->is_sandbox();
    $self->clean_ulc_cruft();
    return 0;
}

sub clean_ulc_cruft ($self) {
    foreach my $path ( $self->ulc_cruft()->@* ) {
        $self->remove_cruft($path);
    }
    return 1;
}

sub error ( $self, $msg ) {
    chomp $msg;
    print STDERR "[ERROR] $msg\n";
    return;
}

sub debug ( $self, $msg ) {
    return unless $self->{'_debug'} //= grep { $_ eq '--debug' } $self->{'argv'}->@*;
    chomp $msg;
    print STDERR "[DEBUG] $msg\n";
    return;
}

sub remove_cruft ( $self, $path ) {
    try {
        use autodie;
        lstat $path;
        if ( -f _ ) {
            $self->debug("unlink “$path”");
            unlink $path;
        }
        elsif ( -d _ ) {
            $self->debug("rmdir “$path”");
            rmdir $path;
        }
        elsif ( -e _ ) {
            $self->debug( "“$path” is neither file or directory:\n" . qx{ namei -lx $path } );
        }
    }
    catch {
        # We only need to remove empty directories, so ignore rmdir ENOTEMPTY.
        if ( try { $_->isa('autodie::exception') } && !( $_->matches('rmdir') && $_->errno() == Errno::ENOTEMPTY() ) ) {
            $self->error($_);
        }
    };
    return;
}

sub basedir ($self) {
    return '/usr/local/cpanel';
}

sub ulc_cruft ($self) {

    # See CPANEL-36468 and CPANEL-36548
    # Includes dirs which may become empty after cruft files are removed.
    # The reverse sort orders child nodes before parents so empty directories will be removed.
    return [
        reverse sort map { $self->basedir() . q{/} . $_ }
          qw(
          Cpanel/API/Mysql
          Cpanel/API/Mysql/Mysql-update_privileges.openapi.yaml
          Cpanel/API/Postgresql
          Cpanel/API/Postgresql/Postgresql-update_privileges.openapi.yaml
          Cpanel/CPAN/overload/__Digest
          Cpanel/CPAN/overload/__Digest/Digest
          Cpanel/CPAN/overload/__Digest/Digest/base.pm
          Cpanel/ContactInfo/Challenge
          Cpanel/ContactInfo/Challenge/ContactObj.pm
          Cpanel/ContactInfo/Challenge/Fake
          Cpanel/ContactInfo/Challenge/Fake/Email.pm
          Cpanel/ContactInfo/Challenge/Lookup
          Cpanel/ContactInfo/Challenge/Lookup/Cpanel.pm
          Cpanel/ContactInfo/Challenge/Lookup/Fake.pm
          Cpanel/ContactInfo/Challenge/Lookup/Sub.pm
          Cpanel/ContactInfo/Challenge/Lookup/Util
          Cpanel/ContactInfo/Challenge/Lookup/Util/CustInfo.pm
          Cpanel/ContactInfo/Challenge/Obscure
          Cpanel/ContactInfo/Challenge/Obscure/Email.pm
          Cpanel/ContactInfo/Challenge/Salt.pm
          Cpanel/CpKeyClt
          Cpanel/CpKeyClt/Change.pm
          Cpanel/CpKeyClt/EnvType.pm
          Cpanel/CpKeyClt/SysId
          Cpanel/CpKeyClt/SysId.pm
          Cpanel/CpKeyClt/SysId/Generate.pm
          Cpanel/IO/Interface
          Cpanel/IO/Interface/List.pm
          Cpanel/LicenseAuthn
          Cpanel/LicenseAuthn/Write.pm
          Whostmgr/SSL
          Whostmgr/SSL/Hosts.pm
          autofixer2
          autofixer2/README
          cgi-priv/get_local.cgi.pl
          libexec/tailwatch/tailwatchd.pl
          )
    ];
}

sub is_sandbox ($self) {
    return -e '/var/cpanel/dev_sandbox';
}

1;
