#!/usr/local/cpanel/3rdparty/bin/perl
# cpanel - autofixer2/fix-exponent-cpusers           Copyright 2018 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;
use warnings;

use Cpanel::Config::CpUserGuard ();
use Cpanel::Config::Users       ();
use Whostmgr::ACLS              ();
use Whostmgr::Func              ();
use Whostmgr::Packages          ();

exit main() unless caller;

sub fix_package {
    my ($data) = @_;

    my $changed = 0;
    foreach my $key (qw/BWLIMIT QUOTA/) {
        if ( length $data->{$key} && $data->{$key} ne 'unlimited' && $data->{$key} !~ /\A\d{1,15}\z/ ) {
            $data->{$key} = Whostmgr::Func::unlimitedint( $data->{$key}, sub { int shift } );
            $changed = 1;
        }
    }
    return $changed;
}

sub check_packages {
    print "Fixing packages...\n";
    my $pkgs = Whostmgr::Packages::fetch_package_list();
    foreach my $pkg ( sort keys %$pkgs ) {
        next if $pkg eq 'default';

        print "\t$pkg...";
        my $changed = fix_package( $pkgs->{$pkg} );
        my ( $result, $error );
        if ($changed) {

            # We apply a trick here: if the values are in uppercase,
            # Whostmgr::Package thinks them to be in bytes and tries to
            # transform them, but if they're in lowercase, it doesn't.  Since we
            # want to make the minimum transformations necessary (and certainly
            # don't want to decrease these values by a factor of 1048576), we
            # force the values to lowercase.
            my $data = { map { lc $_ => $pkgs->{$pkg}{$_} } keys %{ $pkgs->{$pkg} } };
            ( $result, $error ) = Whostmgr::Packages::_editpkg( %$data, pkgname => $pkg );
        }
        my $msg = $changed ? $result ? 'ok (fixed)' : "failed ($error)" : 'unchanged';
        print "$msg\n";
    }
    return 1;
}

sub fix_user {
    my ($data) = @_;

    my $changed = 0;
    foreach my $key (qw/BWLIMIT/) {

        # If we were able to serialize the data into the file correctly, then we
        # can clearly handle reading the data from the file correctly.  Be less
        # strict about forcing very large values to unlimited.
        if ( length $data->{$key} && $data->{$key} ne 'unlimited' && $data->{$key} !~ /\A\d+\z/ ) {
            $data->{$key} = Whostmgr::Func::unlimitedint( $data->{$key} );
            $changed = 1;
        }
    }
    return $changed;
}

sub check_users {
    print "Fixing users...\n";
    my @users = Cpanel::Config::Users::getcpusers();
    foreach my $user ( sort @users ) {
        print "\t$user...";
        my $guard   = Cpanel::Config::CpUserGuard->new($user);
        my $changed = fix_user( $guard->{'data'} );
        my $result  = $changed ? $guard->save : $guard->abort;
        my $msg     = $changed ? $result ? 'ok (fixed)' : "failed" : 'unchanged';
        print "$msg\n";
    }
    return 1;
}

sub main {
    local $ENV{'REMOTE_USER'} = 'root';
    Whostmgr::ACLS::init_acls();

    # We fix users first; otherwise, the correct values may not be saved.
    check_users();
    check_packages();
    return 0;
}
