00000005
     �_’I|¥‰ÓMjqØ‚¦ð¬÷À¿      File not found.
  "   ˆl–Ü4ý()¨‰P@ŠëŒ¿q¶”Å£Âƒh¹ÁÀ      unsupported
  #   ˆl–Ðz¾”Jj"TÒ�zàœ¸”Å£Ã„î¶ßÂÁ ?÷     #!/usr/local/cpanel/3rdparty/bin/perl

# cpanel - scripts/cpuser_port_authority           Copyright 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

use strict;
use warnings;

package scripts::cpuser_port_authority;

use Cpanel::JSON                    ();
use Cpanel::Transaction::File::JSON ();
use Cpanel::Config::LoadUserDomains ();
use Cpanel::Debug                   ();
use Cpanel::Validate::Username      ();
use Cpanel::FileUtils::Write        ();
use Cpanel::PwCache                 ();

our $port_authority_conf = "/etc/cpanel/cpuser_port_authority.json";

my $cmds = {
    give => {
        code     => \&give,
        clue     => "give <user> <number of ports> [--service=my_app]",
        abstract => 'Give a user 1 or more ports.',
        help     => "Give a user 1 or more ports, that only they can run a service on.\n  --service=<NAME>  this will tie a service name, as appropriate for scripts/cpuser_service_manager, to the ports for reference",
    },
    take => {
        code     => \&take,
        clue     => "take <user> <port-number> [<port-number> <port-number> â€¦]",
        abstract => "Take 1 or more ports from a user.",
        help     => "Take 1 or more ports from a user. Errors out completely if any of the given ports do not belong to them.",
    },
    list => {
        code     => \&list,
        clue     => "list [<user>]",
        abstract => "List port assignment information.",
        help     => "List port assignment information. If given a user it lists only that userâ€™s information. The output is in human friendly JSON format.",
    },
    fw => {
        code     => \&fw,
        clue     => "fw",
        abstract => "Setup Firewall",
        help     => "Setup the firewall rules to match the configured port assignments",
    },
    user => {
        code     => \&user,
        clue     => "user (remove|change) <user> [<new_user>]",
        abstract => "Operate on a given userâ€™s port assignments",
        help     => "Remove all ports owned by the given user. Change port ownership from <user> to <new_user>.",
    },
};

my $hint_blurb = "Usage: `$0 {command} â€¦`.\n\tThis tool supports the following commands:";
my $opts       = {
    'help:pre_hint'  => $hint_blurb,
    'help:pre_help'  => "Various user-assigned-port related admin utilities\n\n$hint_blurb",
    default_commands => "help",
    alias            => { free => "take", firewall => "fw" },
};

run(@ARGV) if !caller;

sub run {
    my (@argv) = @_;
    die "This script should only be called as root\n" if $> != 0;

    local $ENV{TERM} = $ENV{TERM} || "xterm-256color";    # non-CLI modulino avoid needless: Cannot find termcap: TERM not set at â€¦/Term/ReadLine.pm line 373.
    require App::CmdDispatch;
    import App::CmdDispatch;

    # need to have App::CmdDispatch do this automatically see CPANEL-22328
    if ( @argv && grep { defined && m/\A\-\-help\z/ } @argv ) {
        App::CmdDispatch->new( $cmds, $opts )->help();
        exit(0);
    }

    my $orig_command_hint = \&App::CmdDispatch::command_hint;
    no warnings "redefine";
    local *App::CmdDispatch::command_hint = sub {
        $orig_command_hint->(@_);
        exit(1);
    };
    no warnings 'once';
    require App::CmdDispatch::IO;
    local *App::CmdDispatch::IO::print = sub {
        shift;
        if ( ref($@) && $@ =~ m/^App::CmdDispatch::Exception/ ) {
            CORE::print STDERR @_;
            return;
        }
        CORE::print(@_);
        return;
    };
    local *App::CmdDispatch::MinimalIO::print = \&App::CmdDispatch::IO::print;
    use warnings 'once';

    # ^^^ /need to have App::CmdDispatch do this automatically see CPANEL-22328

    if ( $ARGV[0] && $ARGV