MOON
Server: Apache
System: Linux server1.studioinfinity.com.br 2.6.32-954.3.5.lve1.4.90.el6.x86_64 #1 SMP Tue Feb 21 12:26:30 UTC 2023 x86_64
User: artinside (517)
PHP: 7.4.33
Disabled: exec,passthru,shell_exec,system
Upload Files
File: //usr/local/share/perl5/Cpanel/TaskQueue/Task.pm
package Cpanel::TaskQueue::Task;

use strict;

#use warnings;

our $VERSION = 0.307;

# Namespace for the ids created by this class.
my $task_uuid = "TaskQueue-Task";

# These methods are intended to help document the importance of the message and to supply 'seam' that
#   could be used to modify the logging behavior of the TaskQueue.
sub _throw {
    my $class = shift;
    die @_;
}

# Not using _warn or _info, so don't define them.

sub new {
    my ( $class, $args ) = @_;

    $class->_throw('Missing arguments')                  unless defined $args;
    $class->_throw('Args parameter must be a hash ref.') unless 'HASH' eq ref $args;
    $class->_throw('Missing command string.')            unless exists $args->{cmd} and $args->{cmd} =~ /\S/;
    $class->_throw('Invalid Namespace UUID.') if exists $args->{nsid} and !_is_valid_ns( $args->{nsid} );
    $class->_throw('Invalid id.') unless _is_pos_int( $args->{id} );

    my $uuid = _make_name_based_uuid(
        exists $args->{nsid} ? $args->{nsid} : $task_uuid,
        $args->{id}
    );

    my $timeout = -1;
    if ( exists $args->{timeout} ) {
        $timeout = $args->{timeout};
        $class->_throw('Invalid child timeout.') unless _is_pos_int($timeout);
    }
    my $retries = 1;
    if ( exists $args->{retries} ) {
        $retries = $args->{retries};
        $class->_throw('Invalid value for retries.') unless _is_pos_int($retries);
    }
    my $userdata = {};
    if ( exists $args->{userdata} ) {
        $class->_verify_userdata_arg( $args->{userdata} );
        $userdata = { %{ $args->{userdata} } };
    }

    my ( $command, $argstring ) = split( /\s+/, $args->{cmd}, 2 );
    $argstring = '' unless defined $argstring;

    # recognizes simple args, quoted args, and quoted args with escaped quotes.
    my @args = ( $argstring =~ m/('(?: \\' | [^'] )*' | "(?: \\" | [^"] )*" | \S+ )/xg );
    foreach my $arg (@args) {

        # remove quotes and escapes.
        $arg =~ s/^['"]|["']$//g;
        $arg =~ s/\\(['"])/$1/g;
    }

    return bless {
        _command       => $command,
        _argstring     => $argstring,
        _args          => \@args,
        _timestamp     => time,
        _uuid          => $uuid,
        _child_timeout => $timeout,
        _started       => undef,
        _pid           => undef,
        _retries       => $retries,
        _userdata      => $userdata,
    }, $class;
}

# Make a copy of the task description.
# Makes a one-level deep copy of the hash. If this structure is ever extended
# to support more complex attributes, this method will need to change.
#
# Returns the clone.
sub clone {
    my $self = shift;

    my $new = bless { %{$self} }, __PACKAGE__;

    # Don't add lexical in for, changing in place.
    foreach ( grep { ref $_ } values %{$new} ) {
        if ( 'ARRAY' eq ref $_ ) {
            $_ = [ @{$_} ];
        }
    }
    return $new;
}

# Make a copy of the task description with changes.
# Makes a one-level deep copy of the hash. If this structure is ever extended
# to support more complex attributes, this method will need to change.
#
# Returns the modified clone.
sub mutate {
    my $self  = shift;
    my %parms = %{ shift() };

    my $new = $self->clone();

    if ( exists $parms{timeout} ) {
        $self->_throw('Invalid child timeout.') unless _is_pos_int( $parms{timeout} );
        $new->{_child_timeout} = $parms{timeout};
    }
    if ( exists $parms{retries} ) {
        $self->_throw('Invalid value for retries.') unless _is_pos_int( $parms{retries} );
        $new->{_retries} = $parms{retries};
    }
    if ( exists $parms{userdata} ) {
        $self->_verify_userdata_arg( $parms{userdata} );
        while ( my ( $k, $v ) = each %{ $parms{userdata} } ) {
            $new->{_userdata}->{$k} = $v;
        }
    }

    return $new;
}

# Accessors
sub command           { return $_[0]->{_command} }
sub full_command      { return "$_[0]->{_command} $_[0]->{_argstring}"; }
sub argstring         { return $_[0]->{_argstring} }
sub args              { return @{ $_[0]->{_args} }; }
sub timestamp         { return $_[0]->{_timestamp} }
sub uuid              { return $_[0]->{_uuid} }
sub child_timeout     { return $_[0]->{_child_timeout} }
sub started           { return $_[0]->{_started} }
sub pid               { return $_[0]->{_pid} }
sub retries_remaining { return $_[0]->{_retries} }

sub get_userdata {
    my $self = shift;
    my $key  = shift;
    $self->_throw('No userdata key specified') unless defined $key;
    return unless exists $self->{_userdata}->{$key};
    return $self->{_userdata}->{$key};
}

sub get_arg {
    my ( $self, $index ) = @_;
    return $self->{_args}->[$index];
}

sub set_pid { $_[0]->{_pid}     = $_[1]; return; }
sub begin   { $_[0]->{_started} = time;  return; }

sub decrement_retries {
    my $self = shift;
    return unless $self->{_retries};
    $self->{_retries}--;
    return;
}

# Utility methods

# Create a UUID from the supplied namespace and name.
# Based on code in RFC 4122, verified against Data::UUID
sub _make_name_based_uuid {
    my ( $nsid, $name ) = @_;

    return sprintf( 'TQ:%s:%s', $nsid, $name );
}

#
# Returns true if the supplied parameter is a positive integer.
sub _is_pos_int {
    my $val = shift;
    return unless defined $val;
    return unless $val =~ /^\d+$/;
    return $val > 0;
}

sub _is_valid_ns {
    my $val = shift;
    return defined $val && length $val && $val !~ /:/;
}

sub is_valid_taskid {
    my $val = shift;
    return defined $val && $val =~ /^TQ:[^:]+:\d+$/;
}

sub _verify_userdata_arg {
    my $class = shift;
    my $arg   = shift;
    $class->_throw('Expected a hash reference for userdata value.') unless 'HASH' eq ref $arg;
    my @bad_keys;
    while ( my ( $k, $v ) = each %{$arg} ) {
        push @bad_keys, $k if ref $v;
    }
    if (@bad_keys) {
        @bad_keys = sort @bad_keys;
        $class->_throw("Reference values not allowed as userdata. Keys containing references: @bad_keys");
    }
    return;
}

1;    # Magic true value required at the end of the module