#!/usr/bin/perl
# cpanel - autofixer/reset_cpanel_user_files      Copyright(c) 2009 cPanel, Inc.
#                                                           All rights Reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited

BEGIN { unshift @INC, '/usr/local/cpanel'; }

use strict;
use warnings;
use Cpanel::SafeRun::Errors     ();
use Cpanel::Config::LoadConfig  ();
use Cpanel::Config::userdata    ();
use Cpanel::Config::FlushConfig ();

my $log_fh;
my $changes_made = 0;
my $verbose      = 1;

my $warn_only = 0;

# my $warn_only = 1;
# if ( grep { /^--really-fix/ } @ARGV ) {
#     $warn_only = 0;
# }

my $header = '#cPanel -- If you edit this file directly you must run /scripts/updateuserdomains after to rebuild the cache';
my $now    = time();

# Read cpuser directory contents
unless ( -d '/var/cpanel/users' ) {
    die "/var/cpanel/users directory is missing!";
}

opendir( my $users_dh, '/var/cpanel/users' ) || die "Could not open /var/cpanel/users for reading!";
my @users = readdir($users_dh);
closedir $users_dh;

# Check each cpuser file
print "Checking all cpuser files for consistency...\n" if $verbose;
foreach my $user (@users) {
    next if ( $user =~ /^\./ );
    my $cpuser_ref = Cpanel::Config::LoadConfig::loadConfig( '/var/cpanel/users/' . $user );

    my $userdata_ref = Cpanel::Config::userdata::load_userdata($user);
    next unless ( defined $userdata_ref && defined $userdata_ref->{'main_domain'} );

    # TODO: We could do some simple sanity tests like checking for the theme package and MAX settings before comparing the domain counts.

    # Get the list of DNS entries from the userdata file
    my %userdata_dns_items_map = map { $_ => 1 } ( keys %{ $userdata_ref->{'addon_domains'} }, @{ $userdata_ref->{'sub_domains'} }, @{ $userdata_ref->{'parked_domains'} } );

    # Get the list of DNS entries from the cpuser file
    my %cpuser_dns_items_map;
    foreach my $key ( keys %$cpuser_ref ) {
        next unless ( $key =~ /^DNS\d+$/ && $cpuser_ref->{$key} );
        $cpuser_dns_items_map{ $cpuser_ref->{$key} } = 1;
        delete $cpuser_ref->{$key};
    }

    # Compare and fix
    my $userdata_dns_count = scalar keys %userdata_dns_items_map;
    my $cpuser_dns_count   = scalar keys %cpuser_dns_items_map;

    if ( $userdata_dns_count > $cpuser_dns_count ) {
        log_it("$user should have $userdata_dns_count domains listed but has $cpuser_dns_count\n");
        $changes_made = 1;
        my $dns_count = 1;
        foreach my $domain ( keys %userdata_dns_items_map ) {
            $cpuser_ref->{ 'DNS' . ( $dns_count++ ) } = $domain;
        }

        if ( !$warn_only ) {

            # TODO: Should we set defaults on any other cpuser items?
            Cpanel::Config::FlushConfig::flushConfig( "/var/cpanel/users/$user", $cpuser_ref, '=', $header );
        }
    }
}

if ($changes_made) {
    print "\n";
    if ($warn_only) {
        print "A list of users that have inconsistend cpuser information was created at /var/cpanel/logs/cpusers-autofixer.$now\n";
        print "It is highly recommended that you restore these cpuser files from backups.\n";
        print "If it is not possible to do so, run this script again with the --really-fix flag.\n";
    }
    else {
        print "Some users were found in an inconsistent state.\n";
        print "A log of the updated users was created at /var/cpanel/logs/cpusers-autofixer.$now\n";
        print "It is recommended that you review this log and restore these cpuser files from backup\n";
        print "if possible since it is impossible to determine how some settings and limits\n";
        print "were previously configured\n\n";
        print "Running /scripts/updateuserdomains to finish update...\n";

        run_command('/scripts/updateuserdomains');
    }
}
else {
    print "No errors encountered\n" if $verbose;
}

close($log_fh) if ( defined $log_fh );
exit 0;

sub log_it {
    unless ( defined $log_fh ) {
        mkdir( '/var/cpanel/logs', 0700 ) unless ( -d '/var/cpanel/logs' );
        open $log_fh, '>', '/var/cpanel/logs/cpusers-autofixer.' . $now || die "Couldn't open /var/cpanel/logs/cpusers-autofixer.$now for writing: $!";
    }
    print $log_fh @_;
    print @_ if $verbose;
}

sub run_command {
    if ($verbose) {
        system(@_);
    }
    else {
        Cpanel::SafeRun::Errors::saferunallerrors(@_);
    }
}
