} if $position eq 'begin'; return '
' if $position eq 'end'; return ''; } else { return ''; # e.g. $lh->context_is_plain() } } sub cpanel_get_3rdparty_lang { my ( $lh, $_3rdparty ) = @_; require Cpanel::Locale::Utils::3rdparty; return Cpanel::Locale::Utils::3rdparty::get_app_setting( $lh, $_3rdparty ) || Cpanel::Locale::Utils::3rdparty::get_3rdparty_lang( $lh, $_3rdparty ) || $lh->get_language_tag() || 'en'; } sub cpanel_is_valid_locale { my ( $lh, $locale ) = @_; my %valid_locales = map { $_ => 1 } ( qw(en en_us i_default), $lh->list_available_locales ); return $valid_locales{$locale} ? 1 : 0; } sub cpanel_get_3rdparty_list { my ($lh) = @_; require Cpanel::Locale::Utils::3rdparty; return Cpanel::Locale::Utils::3rdparty::get_3rdparty_list($lh); } sub cpanel_get_lex_path { my ( $lh, $path, $rv ) = @_; return if !defined $path || $path eq '' || substr( $path, -3 ) ne '.js'; require Cpanel::JS::Variations; my $query = $path; $query = Cpanel::JS::Variations::get_base_file( $query, '-%s.js' ); if ( defined $rv && index( $rv, '%s' ) == -1 ) { substr( $rv, -3, 3, '-%s.js' ); } my $asset_path = $lh->get_asset_file( $query, $rv ); return $asset_path if $asset_path && substr( $asset_path, -3 ) eq '.js' && index( $asset_path, '-' ) > -1; # Only return a value if there is a localized js file here return; } sub tag_is_default_locale { my $tag = $_[1] || $_[0]->get_language_tag(); return 1 if $tag eq 'en' || $tag eq 'en_us' || $tag eq 'i_default'; return; } sub get_cdb_file_path { my ( $lh, $core ) = @_; my $class = $core ? $lh->get_base_class() : $lh->get_language_class(); no strict 'refs'; return $class eq 'Cpanel::Locale::en' || $class eq 'Cpanel::Locale::en_us' || $class eq 'Cpanel::Locale::i_default' ? $Cpanel::Locale::CDB_File_Path : ${ $class . '::CDB_File_Path' }; } sub _slurp_small_file_if_exists_no_exception { my ($path) = @_; local ( $!, $^E ); open my $rfh, '<', $path or do { if ( $! != _ENOENT() ) { warn "open($path): $!"; } return undef; }; read $rfh, my $buf, 8192 or do { warn "read($path): $!"; }; return $buf; } my $_server_locale_file_contents; sub get_server_locale { if ( exists $ENV{'CPANEL_SERVER_LOCALE'} ) { return $ENV{'CPANEL_SERVER_LOCALE'} if $ENV{'CPANEL_SERVER_LOCALE'} !~ tr{A-Za-z0-9_-}{}c; return undef; } if (%main::CPCONF) { return $main::CPCONF{'server_locale'} if exists $main::CPCONF{'server_locale'}; } return ( $_server_locale_file_contents //= ( _slurp_small_file_if_exists_no_exception($SERVER_LOCALE_FILE) || '' ) ); } sub _clear_cache { $_server_locale_file_contents = undef; return; } sub get_locale_for_user_cpanel { if (%main::CPCONF) { return $main::CPCONF{'cpanel_locale'} if exists $main::CPCONF{'cpanel_locale'}; return $main::CPCONF{'server_locale'} if exists $main::CPCONF{'server_locale'}; } require Cpanel::Config::LoadCpConf; my $cpconf = Cpanel::Config::LoadCpConf::loadcpconf_not_copy(); # safe since we do not modify cpconf return $cpconf->{'cpanel_locale'} if $cpconf->{'cpanel_locale'}; # will not be autovivified, 0 and "" are invalid, if the value is invalid they will get 'en' return $cpconf->{'server_locale'} if $cpconf->{'server_locale'}; # will not be autovivified, 0 and "" are invalid, if the value is invalid they will get 'en' return; } sub cpanel_reinit_lexicon { my ($lh) = @_; $lh->cpanel_detach_lexicon(); $lh->cpanel_attach_lexicon(); } my $detach_locale_lex; sub cpanel_detach_lexicon { my ($lh) = @_; my $locale = $lh->get_language_tag(); no strict 'refs'; undef $Cpanel::Locale::CDB_File_Path; if ( $locale ne 'en' && $locale ne 'en_us' && $locale ne 'i_default' ) { $detach_locale_lex = ${ 'Cpanel::Locale::' . $locale . '::CDB_File_Path' }; undef ${ 'Cpanel::Locale::' . $locale . '::CDB_File_Path' }; } untie( %{ 'Cpanel::Locale::' . $locale . '::Lexicon' } ); untie %Cpanel::Locale::Lexicon; } sub cpanel_attach_lexicon { my ($lh) = @_; my $locale = $lh->get_language_tag(); $Cpanel::Locale::CDB_File_Path = Cpanel::Locale::Utils::init_lexicon( 'en', \%Cpanel::Locale::Lexicon, \$Cpanel::Locale::VERSION, \$Cpanel::Locale::Encoding ); _make_alias_if_needed($locale); no strict 'refs'; if ( defined $detach_locale_lex ) { ${ 'Cpanel::Locale::' . $locale . '::CDB_File_Path' } = $detach_locale_lex; } else { ${ 'Cpanel::Locale::' . $locale . '::CDB_File_Path' } = $Cpanel::Locale::CDB_File_Path; } my $file_path = $lh->get_cdb_file_path(); return if !$file_path; return Cpanel::Locale::Utils::get_readonly_tie( $lh->get_cdb_file_path(), \%{ 'Cpanel::Locale::' . $locale . '::Lexicon' } ); } sub is_rtl { my ($lh) = @_; return 'right-to-left' eq $lh->get_language_tag_character_orientation() ? 1 : 0; } sub get_language_tag_character_orientation { if ( my $direction = $known_locales_character_orientation{ $_[1] || $_[0]->{'fallback_locale'} || $_[0]->get_language_tag() } ) { return 'right-to-left' if $direction == $RTL; return 'left-to-right'; } $_[0]->SUPER::get_language_tag_character_orientation( @_[ 1 .. $#_ ] ); } my $menu_ar; sub get_locale_menu_arrayref { return $menu_ar if $menu_ar; require Cpanel::Locale::Utils::Display; $menu_ar = [ Cpanel::Locale::Utils::Display::get_locale_menu_hashref(@_) ]; # always array context to get all structs, properly uses other args besides object return $menu_ar; } my $non_existent; sub get_non_existent_locale_menu_arrayref { return $non_existent if $non_existent; require Cpanel::Locale::Utils::Display; $non_existent = [ Cpanel::Locale::Utils::Display::get_non_existent_locale_menu_hashref(@_) ]; # always array context to get all structs, properly uses other args besides object return $non_existent; } sub _api1_maketext { require Cpanel::Locale::Utils::Api1; goto \&Cpanel::Locale::Utils::Api1::_api1_maketext; ## no extract maketext } our $api1 = { 'maketext' => { ## no extract maketext 'function' => \&_api1_maketext, ## no extract maketext 'internal' => 1, 'legacy_function' => 2, 'modify' => 'inherit', }, }; sub current_year { return (localtime)[5] + 1900; # we override datetime() so we can't use the internal current_year() } sub local_datetime { my ( $lh, $epoch, $format ) = @_; my $timezone = $ENV{'TZ'} // do { require Cpanel::Timezones; Cpanel::Timezones::calculate_TZ_env(); }; return $lh->datetime( $epoch, $format, $timezone ); } sub datetime { my ( $lh, $epoch, $format, $timezone ) = @_; require Cpanel::Locale::Utils::DateTime; if ( $epoch && $epoch =~ tr<0-9><>c ) { require # do not include it in updatenow.static Cpanel::Validate::Time; Cpanel::Validate::Time::iso_or_die($epoch); require Cpanel::Time::ISO; $epoch = Cpanel::Time::ISO::iso2unix($epoch); } return Cpanel::Locale::Utils::DateTime::datetime( $lh, $epoch, $format, $timezone ); } sub get_lookup_hash_of_multi_epoch_datetime { my ( $lh, $epochs_ar, $format, $timezone ) = @_; require Cpanel::Locale::Utils::DateTime; return Cpanel::Locale::Utils::DateTime::get_lookup_hash_of_multi_epoch_datetime( $lh, $epochs_ar, $format, $timezone ); } sub get_locale_name_or_nothing { my ( $locale, $name, $in_locale_tongue ) = @_; $name ||= $locale->get_language_tag(); if ( index( $name, 'i_' ) == 0 ) { require Cpanel::DataStore; my $i_locales_path = Cpanel::Locale::Utils::Paths::get_i_locales_config_path(); my $i_conf = Cpanel::DataStore::fetch_ref("$i_locales_path/$name.yaml"); return $i_conf->{'display_name'} if $i_conf->{'display_name'}; } else { my $real = $locale->get_language_tag_name( $name, $in_locale_tongue ); return $real if $real; } return; } sub get_locale_name_or_tag { return $_[0]->get_locale_name_or_nothing( $_[1], $_[2] ) || $_[1] || $_[0]->get_language_tag(); } *get_locale_name = *get_locale_name_or_tag; # for shorter BN sub get_user_locale { return $Cpanel::CPDATA{'LOCALE'} if $Cpanel::CPDATA{'LOCALE'}; require Cpanel::Locale::Utils::User; # probably a no-op but just in case since its loading is conditional return Cpanel::Locale::Utils::User::get_user_locale(); } sub get_user_locale_name { require Cpanel::Locale::Utils::User; # probably a no-op but just in case since its loading is conditional return $_[0]->get_locale_name_or_tag( Cpanel::Locale::Utils::User::get_user_locale( $_[1] ) ); } sub set_user_locale { my ( $locale, $country_code ) = @_; if ($country_code) { my $language_name = $locale->lang_names_hashref(); if ( exists $language_name->{$country_code} ) { require Cpanel::Locale::Utils::Legacy; require Cpanel::Locale::Utils::User::Modify; my $language = Cpanel::Locale::Utils::Legacy::get_best_guess_of_legacy_from_locale($country_code); if ( Cpanel::Locale::Utils::User::Modify::save_user_locale( $country_code, $language, $Cpanel::user ) ) { return 1; } } } die Cpanel::Exception::create_raw( "Empty", $locale->maketext("Unable to set locale, please specify a valid country code.") ); } sub get_locales { my $locale = shift; my @listing; my ( $names, $local_names ) = $locale->lang_names_hashref(); foreach ( keys %{$names} ) { push @listing, { locale => $_, name => $names->{$_}, local_name => $local_names->{$_}, direction => ( !defined $known_locales_character_orientation{$_} || $known_locales_character_orientation{$_} == $LTR ) ? 'ltr' : 'rtl' }; } return \@listing; } my $api2_lh; sub api2_get_user_locale { $api2_lh ||= Cpanel::Locale->get_handle(); return ( { 'locale' => $api2_lh->get_user_locale() } ); } sub api2_get_user_locale_name { $api2_lh ||= Cpanel::Locale->get_handle(); return ( { 'name' => $api2_lh->get_user_locale_name() } ); } sub api2_get_locale_name { $api2_lh ||= Cpanel::Locale->get_handle(); my $tag = ( scalar @_ > 2 ) ? {@_}->{'locale'} : $_[1]; return ( { 'name' => $api2_lh->get_locale_name_or_tag($tag) } ); } sub api2_get_encoding { $api2_lh ||= Cpanel::Locale->get_handle(); return ( { 'encoding' => $api2_lh->encoding() } ); } sub api2_numf { my %args = @_; $api2_lh ||= Cpanel::Locale->get_handle(); return ( { 'numf' => $api2_lh->numf( $args{number}, $args{max_decimal_places} ) } ); } sub api2_get_html_dir_attr { $api2_lh ||= Cpanel::Locale->get_handle(); return ( { 'dir' => $api2_lh->get_html_dir_attr() } ); } my $allow_demo = { allow_demo => 1 }; our %API = ( get_locale_name => $allow_demo, get_encoding => $allow_demo, get_html_dir_attr => $allow_demo, get_user_locale => $allow_demo, get_user_locale_name => $allow_demo, numf => $allow_demo, ); sub api2 { my ($func) = @_; return { %{ $API{$func} } } if $API{$func}; return; } my $global_lh; sub lh { return ( $global_lh ||= Cpanel::Locale->get_handle() ); } sub import { my ( $package, @args ) = @_; my ($namespace) = caller; if ( @args == 1 && $args[0] eq 'lh' ) { no strict 'refs'; ## no critic(ProhibitNoStrict) my $exported_name = "${namespace}::lh"; *$exported_name = \*lh; } } sub _load_carp { if ( !$INC{'Cpanel/Carp.pm'} ) { local $@; eval 'require Cpanel::Carp; 1;' or die $@; # hide from perlcc } return; } sub user_feedback_text_for_more_locales { require Cpanel::Version; my $locale = Cpanel::Locale->get_handle(); my $version = Cpanel::Version::get_version_full(); my $survey_url = 'https://surveys.webpros.com/to/xGTiJG4X?utm_source=cpanel-changelanguage&cpanel_productversion=' . $version; return $locale->maketext( "Don’t see your language of choice? Take our [output,url,_1,Language Support Feedback Survey,class,externalLink,target,Language Survey] to let us know your preferences.", $survey_url ); } 1; } # --- END Cpanel/Locale.pm { # --- BEGIN Cpanel/Exception/Collection.pm package Cpanel::Exception::Collection; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 my $EXCEPTION_SEPARATOR = "\n"; sub _LINE_HEADER { my ($num) = @_; return Cpanel::LocaleString->new( 'Error #[numf,_1]:', $num ); } sub _default_phrase { my ($self) = @_; my $excs_ar = $self->get('exceptions') or do { die ref($self) . ' instances must have “exceptions”!'; }; if ( !@$excs_ar ) { die "Must have at least 1 exception (or why do you need a “collection”?)"; } return Cpanel::LocaleString->new( '[quant,_1,error,errors] occurred:', scalar @$excs_ar, ); } sub to_en_string { my ($self) = @_; return $self->_stringify_specific('to_en_string'); } sub to_en_string_no_id { my ($self) = @_; return $self->_stringify_specific('to_en_string_no_id'); } sub to_locale_string { my ($self) = @_; return $self->_stringify_specific('to_locale_string'); } sub to_locale_string_no_id { my ($self) = @_; return $self->_stringify_specific('to_locale_string_no_id'); } my %LINE_HEADER_TRANSLATOR = qw( to_en_string makethis_base to_locale_string makevar to_en_string_no_id makethis_base to_locale_string_no_id makevar ); sub _stringify_specific { my ( $self, $method ) = @_; my $exceptions_ar = $self->get('exceptions'); my @lines = map { UNIVERSAL::isa( $_, 'Cpanel::Exception' ) ? $_->$method() : $_ } @$exceptions_ar; my $translator_name = $LINE_HEADER_TRANSLATOR{$method} or do { die "Invalid method: $method"; }; local $@; for my $l ( 0 .. $#lines ) { my $this_header = _locale()->$translator_name( _LINE_HEADER( 1 + $l )->to_list() ); substr( $lines[$l], 0, 0, $EXCEPTION_SEPARATOR . "$this_header " ); } return $self->can("SUPER::$method")->($self) . join q<>, @lines; } my $locale; sub _locale { require Cpanel::Locale; return $locale ||= Cpanel::Locale->get_handle(); } 1; } # --- END Cpanel/Exception/Collection.pm { # --- BEGIN Cpanel/Exception/CommandAlreadyRunning.pm package Cpanel::Exception::CommandAlreadyRunning; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( $self->get('file') ) { return Cpanel::LocaleString->new( 'The command already has an active [asis,PIDFile] at “[_1]” and is running with the process [asis,ID]: [_2]', $self->get('file'), $self->get('pid'), ); } else { return Cpanel::LocaleString->new( 'The command is already running with the process [asis,ID]: [_1]', $self->get('pid'), ); } } sub _spew { my ($self) = @_; if ($^S) { return $self->SUPER::_spew(); } return $self->get_string_no_id() . "\n"; } 1; } # --- END Cpanel/Exception/CommandAlreadyRunning.pm { # --- BEGIN Cpanel/Exception/ConnectionFailed.pm package Cpanel::Exception::ConnectionFailed; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/ConnectionFailed.pm { # --- BEGIN Cpanel/Exception/ContextError.pm package Cpanel::Exception::ContextError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/ContextError.pm { # --- BEGIN Cpanel/Exception/Database/SchemaOutdated.pm package Cpanel::Exception::Database::SchemaOutdated; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/Database/SchemaOutdated.pm { # --- BEGIN Cpanel/Exception/Database/DatabaseCreationFailed.pm package Cpanel::Exception::Database::DatabaseCreationFailed; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to create the database “[_1]” because of an error: [_2]', @{ $self->{'_metadata'} }{qw(database error)}, ); } 1; } # --- END Cpanel/Exception/Database/DatabaseCreationFailed.pm { # --- BEGIN Cpanel/Exception/Database/DatabaseMissing.pm package Cpanel::Exception::Database::DatabaseMissing; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( $self->get('engine') eq 'mysql' ) { return Cpanel::LocaleString->new( 'Although the system’s database map includes a MySQL database named “[_1]”, the MySQL server reported that no database with this name exists. Contact your system administrator.', $self->get('name') ); } elsif ( $self->get('engine') eq 'postgresql' ) { return Cpanel::LocaleString->new( 'Although the system’s database map includes a PostgreSQL database named “[_1]”, the PostgreSQL server reported that no database with this name exists. Contact your system administrator.', $self->get('name') ); } die "Unknown DB engine: " . $self->get('engine'); } 1; } # --- END Cpanel/Exception/Database/DatabaseMissing.pm { # --- BEGIN Cpanel/Exception/Database/Error.pm package Cpanel::Exception::Database::Error; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LoadModule (); # perlpkg line 211 # use Cpanel::LocaleString (); # perlpkg line 211 my %ERRCODE_MODULE = qw( mysql Cpanel::Mysql::Error Pg Cpanel::Postgres::Error SQLite Cpanel::DBI::SQLite::Error ); my %ERRCODE_IS_AT = qw( mysql error_code Pg state SQLite error_code ); my %SQL_DBMS_NAME = qw( mysql MySQL Pg PostgreSQL SQLite SQLite ); sub failure_is { my ( $self, $name ) = @_; my $driver = $self->get("dbi_driver"); my $module = $ERRCODE_MODULE{$driver}; die "Wrong driver? ($driver)" if !length $module; Cpanel::LoadModule::load_perl_module($module); my $cr = $module->can($name) or die "Invalid: $module\::$name"; my $this_code = $self->_err_code(); die "No code??" if !length $this_code; return $cr->() eq $this_code ? 1 : 0; } sub _err_code { my ($self) = @_; my $driver = $self->get("dbi_driver"); my $code = $self->get( $ERRCODE_IS_AT{$driver} ); return $code; } sub _err_code_for_display { my ($self) = @_; my $err_name; my $err_code = $self->_err_code(); my $driver = $self->get("dbi_driver"); if ($err_code) { my $module = $ERRCODE_MODULE{$driver}; Cpanel::LoadModule::load_perl_module($module); my $get_name_cr = $module->can('get_name_for_error') or die "$module has no get_name_for_error()!"; $err_name = $get_name_cr->($err_code); } return $err_name || $err_code; } sub _err_message_for_display { my ($self) = @_; return $self->get('error_string') || $self->get('message') || 'Unknown'; } sub _locale_string_with_dbname { return Cpanel::LocaleString->new('The system received an error from the “[_1]” database “[_2]”: [_3]'); } sub _locale_string_without_dbname { return Cpanel::LocaleString->new('The system received an error from “[_1]”: [_2]'); } sub _default_phrase { my ($self) = @_; my $err_msg = $self->_err_message_for_display(); my $err_name = $self->_err_code_for_display(); $err_msg = "$err_name ($err_msg)" if $err_name; my $dbname = $self->get('database'); my $dbms_name = $SQL_DBMS_NAME{ $self->get('dbi_driver') }; if ($dbname) { return $self->_locale_string_with_dbname()->clone_with_args( $dbms_name, $dbname, $err_msg ); } return $self->_locale_string_without_dbname()->clone_with_args( $dbms_name, $err_msg ); } 1; } # --- END Cpanel/Exception/Database/Error.pm { # --- BEGIN Cpanel/Exception/Database/ServerTime.pm package Cpanel::Exception::Database::ServerTime; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new('The server time and the [asis,MySQL]® time are different.'); } 1; } # --- END Cpanel/Exception/Database/ServerTime.pm { # --- BEGIN Cpanel/Exception/Database/TableCorruption.pm package Cpanel::Exception::Database::TableCorruption; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; my $reason_hr = $self->{'_metadata'}{'table_error'}; my @tables_disp = map { "$_ ($reason_hr->{$_})" } sort keys %$reason_hr; return Cpanel::LocaleString->new( 'The system detected corruption in the following [numerate,_1,table,tables]: [list_and,_2]', ( scalar @tables_disp ), \@tables_disp, ); } 1; } # --- END Cpanel/Exception/Database/TableCorruption.pm { # --- BEGIN Cpanel/Exception/Database/TableCreationFailed.pm package Cpanel::Exception::Database::TableCreationFailed; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to create the table “[_1]” in the database “[_2]” because of an error: [_3]', @{ $self->{'_metadata'} }{qw(table database error)}, ); } 1; } # --- END Cpanel/Exception/Database/TableCreationFailed.pm { # --- BEGIN Cpanel/Exception/Database/TableInsertionFailed.pm package Cpanel::Exception::Database::TableInsertionFailed; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to insert into the table “[_1]” of the database “[_2]” because of an error: [_3]', @{ $self->{'_metadata'} }{qw(table database error)}, ); } 1; } # --- END Cpanel/Exception/Database/TableInsertionFailed.pm { # --- BEGIN Cpanel/Exception/Database/UserMissing.pm package Cpanel::Exception::Database::UserMissing; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( $self->get('engine') eq 'mysql' ) { return Cpanel::LocaleString->new( 'Although the system’s database map includes a MySQL user named “[_1]”, the MySQL server reported that no user with this name exists. Contact your system administrator.', $self->get('name') ); } elsif ( $self->get('engine') eq 'postgresql' ) { return Cpanel::LocaleString->new( 'Although the system’s database map includes a PostgreSQL user named “[_1]”, the PostgreSQL server reported that no user with this name exists. Contact your system administrator.', $self->get('name') ); } die "Unknown DB engine: " . $self->get('engine'); } 1; } # --- END Cpanel/Exception/Database/UserMissing.pm { # --- BEGIN Cpanel/Exception/Database/CpuserNotInMap.pm package Cpanel::Exception::Database::CpuserNotInMap; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The [asis,cPanel] user “[_1]” does not exist in the database map.', $self->get('name'), ); } 1; } # --- END Cpanel/Exception/Database/CpuserNotInMap.pm { # --- BEGIN Cpanel/Exception/Database/DatabaseCreationInProgress.pm package Cpanel::Exception::Database::DatabaseCreationInProgress; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system cannot open the database “[_1]” because another process has created it but has not yet completed its initialization.', @{ $self->{'_metadata'} }{qw(database)}, ); } 1; } # --- END Cpanel/Exception/Database/DatabaseCreationInProgress.pm { # --- BEGIN Cpanel/Exception/Database/DatabaseNotFound.pm package Cpanel::Exception::Database::DatabaseNotFound; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( length $self->get('cpuser') ) { my @mt_args = map { $self->get($_) } qw(cpuser name); if ( $self->get('engine') eq 'mysql' ) { return Cpanel::LocaleString->new( 'The system user “[_1]” does not control a MySQL database named “[_2]”.', @mt_args ); } elsif ( $self->get('engine') eq 'postgresql' ) { return Cpanel::LocaleString->new( 'The system user “[_1]” does not control a PostgreSQL database named “[_2]”.', @mt_args ); } } else { my @mt_args = ( $self->get('name') ); if ( $self->get('engine') eq 'mysql' ) { return Cpanel::LocaleString->new( 'You do not control a MySQL database named “[_1]”.', @mt_args ); } elsif ( $self->get('engine') eq 'postgresql' ) { return Cpanel::LocaleString->new( 'You do not control a PostgreSQL database named “[_1]”.', @mt_args ); } } die "Unknown DB engine: " . $self->get('engine'); } 1; } # --- END Cpanel/Exception/Database/DatabaseNotFound.pm { # --- BEGIN Cpanel/Exception/Database/UserNotFound.pm package Cpanel::Exception::Database::UserNotFound; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( length $self->get('cpuser') ) { my @mt_args = map { $self->get($_) } qw(cpuser name); if ( $self->get('engine') eq 'mysql' ) { return Cpanel::LocaleString->new( 'The system user “[_1]” does not control a MySQL user named “[_2]”.', @mt_args ); } elsif ( $self->get('engine') eq 'postgresql' ) { return Cpanel::LocaleString->new( 'The system user “[_1]” does not control a PostgreSQL user named “[_2]”.', @mt_args ); } } else { my @mt_args = ( $self->get('name') ); if ( $self->get('engine') eq 'mysql' ) { return Cpanel::LocaleString->new( 'You do not control a MySQL user named “[_1]”.', @mt_args ); } elsif ( $self->get('engine') eq 'postgresql' ) { return Cpanel::LocaleString->new( 'You do not control a PostgreSQL user named “[_1]”.', @mt_args ); } } die "Unknown DB engine: " . $self->get('engine'); } 1; } # --- END Cpanel/Exception/Database/UserNotFound.pm { # --- BEGIN Cpanel/Exception/EntryAlreadyExists.pm package Cpanel::Exception::EntryAlreadyExists; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/EntryAlreadyExists.pm { # --- BEGIN Cpanel/Exception/DnsEntryAlreadyExists.pm package Cpanel::Exception::DnsEntryAlreadyExists; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::EntryAlreadyExists (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::EntryAlreadyExists); } 1; } # --- END Cpanel/Exception/DnsEntryAlreadyExists.pm { # --- BEGIN Cpanel/Exception/DomainAlreadyExists.pm package Cpanel::Exception::DomainAlreadyExists; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/DomainAlreadyExists.pm { # --- BEGIN Cpanel/Exception/DomainDoesNotExist.pm package Cpanel::Exception::DomainDoesNotExist; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'This system does not have a domain named “[_1]”.', $self->get('name'), ); } 1; 1; } # --- END Cpanel/Exception/DomainDoesNotExist.pm { # --- BEGIN Cpanel/Exception/DomainHasUnknownNameservers.pm package Cpanel::Exception::DomainHasUnknownNameservers; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/DomainHasUnknownNameservers.pm { # --- BEGIN Cpanel/Exception/DomainNameNotAllowed.pm package Cpanel::Exception::DomainNameNotAllowed; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; my ( $given, $why ) = map { $self->get($_) } qw(given why); if ( length $why ) { return Cpanel::LocaleString->new( 'The system cannot accept “[_1]” as a domain name ([_2]).', $given, $why, ); } return Cpanel::LocaleString->new( 'The system cannot accept “[_1]” as a domain name.', $given, ); } 1; } # --- END Cpanel/Exception/DomainNameNotAllowed.pm { # --- BEGIN Cpanel/Exception/DomainNameNotRfcCompliant.pm package Cpanel::Exception::DomainNameNotRfcCompliant; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 my $RFC_1035_URL = 'http://tools.ietf.org/html/rfc1035'; sub _default_phrase { my ($self) = @_; my ( $given, $why ) = map { $self->get($_) } qw(given why); if ( length $why ) { return Cpanel::LocaleString->new( '“[_1]” is not a valid domain name per [output,url,_2,RFC 1035] ([_3]).', $given, $RFC_1035_URL, $why, ); } return Cpanel::LocaleString->new( '“[_1]” is not a valid domain name per [output,url,_2,RFC 1035].', $given, $RFC_1035_URL, ); } 1; } # --- END Cpanel/Exception/DomainNameNotRfcCompliant.pm { # --- BEGIN Cpanel/Exception/DomainNotRegistered.pm package Cpanel::Exception::DomainNotRegistered; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/DomainNotRegistered.pm { # --- BEGIN Cpanel/Exception/DomainOwnership.pm package Cpanel::Exception::DomainOwnership; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/DomainOwnership.pm { # --- BEGIN Cpanel/Exception/Email/AccountNotFound.pm package Cpanel::Exception::Email::AccountNotFound; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'You do not have an email account named “[_1]”.', $self->get('name'), ); } 1; } # --- END Cpanel/Exception/Email/AccountNotFound.pm { # --- BEGIN Cpanel/Exception/InvalidParameter.pm package Cpanel::Exception::InvalidParameter; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/InvalidParameter.pm { # --- BEGIN Cpanel/Exception/Empty.pm package Cpanel::Exception::Empty; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::InvalidParameter (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::InvalidParameter); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( length $self->{'_metadata'}{'name'} ) { return Cpanel::LocaleString->new( 'The value of “[_1]” may not be empty.', $self->{'_metadata'}{'name'}, ); } return Cpanel::LocaleString->new('This value may not be empty.'); } 1; } # --- END Cpanel/Exception/Empty.pm { # --- BEGIN Cpanel/Exception/EntryDoesNotExist.pm package Cpanel::Exception::EntryDoesNotExist; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/EntryDoesNotExist.pm { # --- BEGIN Cpanel/Exception/FeatureNotEnabled.pm package Cpanel::Exception::FeatureNotEnabled; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'You do not have the feature “[_1]”.', $self->get('feature_name'), ); } 1; } # --- END Cpanel/Exception/FeatureNotEnabled.pm { # --- BEGIN Cpanel/Exception/FeaturesNotEnabled.pm package Cpanel::Exception::FeaturesNotEnabled; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; my $match = $self->get('match') // 'all'; return Cpanel::LocaleString->new( 'You do not have the [numerate,_1,feature,features] [list_and_quoted,_2].', scalar @{ $self->get('feature_names') }, $self->get('feature_names'), ) if $match eq 'all'; return Cpanel::LocaleString->new( 'You do not have the [numerate,_1,feature,features] [list_or_quoted,_2].', scalar @{ $self->get('feature_names') }, $self->get('feature_names'), ); } 1; } # --- END Cpanel/Exception/FeaturesNotEnabled.pm { # --- BEGIN Cpanel/Exception/ForbiddenInDemoMode.pm package Cpanel::Exception::ForbiddenInDemoMode; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new('This functionality is not available in demo mode.'); } 1; } # --- END Cpanel/Exception/ForbiddenInDemoMode.pm { # --- BEGIN Cpanel/Exception/FunctionNotImplemented.pm package Cpanel::Exception::FunctionNotImplemented; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The function “[_1]” has not been implemented. Override this function in a subclass.', $self->{'_metadata'}{'name'}, ); } 1; } # --- END Cpanel/Exception/FunctionNotImplemented.pm { # --- BEGIN Cpanel/URI/Password.pm package Cpanel::URI::Password; use cPstrict; no warnings 'once'; # use Cpanel::LoadModule (); # perlpkg line 211 my $HIDDEN_STR = '__HIDDEN__'; sub strip_password ($url) { return unless defined $url; Cpanel::LoadModule::load_perl_module('URI::Split'); my ( $scheme, $auth, $path, $query, $frag ) = URI::Split::uri_split($url); if ( length $auth && $auth =~ s[(?<=:).+(?=@)][$HIDDEN_STR] ) { return URI::Split::uri_join( $scheme, $auth, $path, $query, $frag ); } return $url; } sub get_password ($url) { return unless defined $url; Cpanel::LoadModule::load_perl_module('URI::Split'); my ( undef, $auth ) = URI::Split::uri_split($url); return unless defined $auth; $auth =~ m[(?<=:)(.+)(?=@)]; return $1; } 1; } # --- END Cpanel/URI/Password.pm { # --- BEGIN Cpanel/Exception/Base/HasUrl.pm package Cpanel::Exception::Base::HasUrl; use strict; use warnings; no warnings 'once'; our $_STACK_TRACE_SUBSTITUTION = '__CPANEL_URLPW_HIDDEN__'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::URI::Password (); # perlpkg line 211 sub get_url_without_password { my ($self) = @_; my $url = $self->get('url'); return undef unless defined $url; return Cpanel::URI::Password::strip_password($url); } sub longmess { my ($self) = @_; my $mess = $self->SUPER::longmess(); my $url = $self->get('url'); if ( defined $url && ( my $passwd = Cpanel::URI::Password::get_password($url) ) ) { $mess =~ s<\Q$passwd\E><$_STACK_TRACE_SUBSTITUTION>g; } return $mess; } 1; } # --- END Cpanel/Exception/Base/HasUrl.pm { # --- BEGIN Cpanel/Exception/HTTP.pm package Cpanel::Exception::HTTP; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/HTTP.pm { # --- BEGIN Cpanel/Exception/HTTP/Network.pm package Cpanel::Exception::HTTP::Network; use strict; use warnings; no warnings 'once'; # use Cpanel::Exception::Base::HasUrl (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::Base::HasUrl); } # use Cpanel::Exception::HTTP (); # perlpkg line 238 BEGIN { push @ISA, qw(Cpanel::Exception::HTTP); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to send an [output,abbr,HTTP,Hypertext Transfer Protocol] “[_1]” request to “[_2]” because of an error: [_3]', $self->get('method'), $self->get_url_without_password(), $self->get('error'), ); } 1; } # --- END Cpanel/Exception/HTTP/Network.pm { # --- BEGIN Cpanel/Exception/HTTP/Server.pm package Cpanel::Exception::HTTP::Server; use strict; use warnings; no warnings 'once'; # use Cpanel::Exception::Base::HasUrl (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::Base::HasUrl); } # use Cpanel::Exception::HTTP (); # perlpkg line 238 BEGIN { push @ISA, qw(Cpanel::Exception::HTTP); } # use Cpanel::LocaleString (); # perlpkg line 211 our $MAX_LENGTH_FOR_JSON = 512; our $MAX_LENGTH_FOR_599 = 128; our $MAX_LENGTH_FOR_OTHER = 32; sub _default_phrase { my ($self) = @_; my $max_length = $MAX_LENGTH_FOR_OTHER; if ( '599' eq $self->get('status') ) { $max_length = $MAX_LENGTH_FOR_599; } elsif ( ( $self->get('content_type') || '' ) =~ m{^application/json\b} ) { $max_length = $MAX_LENGTH_FOR_JSON; } my $short_content = $self->get('content'); if ( length $short_content > $max_length ) { $short_content = substr( $short_content, 0, $max_length - 1 ) . '…'; } return Cpanel::LocaleString->new( 'The response to the [output,abbr,HTTP,Hypertext Transfer Protocol] “[_1]” request from “[_2]” indicated an error ([_3], [_4]): [_5]', $self->get('method'), $self->get_url_without_password(), $self->get('status'), $self->get('reason'), $short_content, ); } sub method { return shift()->get('method') } sub content { return shift()->get('content') } sub url { return shift()->get('url') } sub status { return shift()->get('status') } sub reason { return shift()->get('reason') } sub headers { return shift()->get('headers') } 1; } # --- END Cpanel/Exception/HTTP/Server.pm { # --- BEGIN Cpanel/Exception/InvalidCharacters.pm package Cpanel::Exception::InvalidCharacters; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::InvalidParameter (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::InvalidParameter); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; my $invalid_ar = $self->{'_metadata'}{'invalid_characters'}; if ( @$invalid_ar == 1 ) { return Cpanel::LocaleString->new( 'This value may not contain the character “[_1]”.', $invalid_ar->[0], ); } return Cpanel::LocaleString->new( 'This value may not contain any of the following [quant,_1,character,characters]: [join, ,_2]', scalar(@$invalid_ar), $invalid_ar, ); } sub get_invalid_characters { my ($self) = @_; return [ @{ $self->{'_metadata'}{'invalid_characters'} } ]; } 1; } # --- END Cpanel/Exception/InvalidCharacters.pm { # --- BEGIN Cpanel/Exception/InvalidParameters.pm package Cpanel::Exception::InvalidParameters; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/InvalidParameters.pm { # --- BEGIN Cpanel/Exception/InvalidUsername.pm package Cpanel::Exception::InvalidUsername; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( '“[_1]” is not a valid username on this system.', $self->get('value'), ); } 1; } # --- END Cpanel/Exception/InvalidUsername.pm { # --- BEGIN Cpanel/Exception/ErrnoBase.pm package Cpanel::Exception::ErrnoBase; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::Errno (); # perlpkg line 211 # use Cpanel::Exception (); # perlpkg line 211 sub error_name { my ($self) = @_; return Cpanel::Errno::get_name_for_errno_number( 0 + $self->get('error') ); } sub _default_phrase { die Cpanel::Exception::create( 'AbstractClass', [__PACKAGE__] ); } 1; } # --- END Cpanel/Exception/ErrnoBase.pm { # --- BEGIN Cpanel/Exception/IOError.pm package Cpanel::Exception::IOError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::ErrnoBase (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::ErrnoBase); } sub error { my ($self) = @_; return $self->{'_metadata'}{'error'}; } sub _default_phrase { die 'Unimplemented' } 1; } # --- END Cpanel/Exception/IOError.pm { # --- BEGIN Cpanel/Exception/IO/CloseError.pm package Cpanel::Exception::IO::CloseError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( my $filename = $self->get('filename') ) { return Cpanel::LocaleString->new( 'The system failed to close a file handle for “[_1]” because of the following error: [_2]', $filename, $self->get('error'), ); } return Cpanel::LocaleString->new( 'The system failed to close a file handle because of an error: [_1]', $self->get('error'), ); } 1; } # --- END Cpanel/Exception/IO/CloseError.pm { # --- BEGIN Cpanel/Exception/IO/ChdirError.pm package Cpanel::Exception::IO::ChdirError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( length $self->get('path') ) { return Cpanel::LocaleString->new( 'The system failed to change a process’s current directory to “[_1]” because of an error: [_2]', $self->get('path'), $self->get('error'), ); } return Cpanel::LocaleString->new( 'The system failed to change a process’s current directory because of an error: [_1]', $self->get('error'), ); } 1; } # --- END Cpanel/Exception/IO/ChdirError.pm { # --- BEGIN Cpanel/Exception/IO/ChownError.pm package Cpanel::Exception::IO::ChownError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; my ( $uid, $gid, $path, $error, $immutable, $append_only ) = @{ $self->{'_metadata'} }{qw(uid gid path error immutable append_only)}; $path = [$path] if length($path) && !ref $path; if ( $uid == -1 ) { die "Huh? UID and GID were both -1 .. ?" if $gid == -1; if ($path) { my @args = ( $gid, $path, $error, ); if ($immutable) { return Cpanel::LocaleString->new( 'The system failed to set the group ID to “[_1]” on the immutable (+i) file [list_and_quoted,_2] because of an error: [_3]', @args ); } elsif ($append_only) { return Cpanel::LocaleString->new( 'The system failed to set the group ID to “[_1]” on the append-only (+a) file [list_and_quoted,_2] because of an error: [_3]', @args ); } return Cpanel::LocaleString->new( 'The system failed to set the group ID to “[_1]” on [list_and_quoted,_2] because of an error: [_3]', @args ); } my @args = ( $gid, $error, ); if ($immutable) { return Cpanel::LocaleString->new( 'The system failed to set the group ID to “[_1]” on one or more immutable (+i) filesystem nodes because of an error: [_2]', @args ); } elsif ($append_only) { return Cpanel::LocaleString->new( 'The system failed to set the group ID to “[_1]” on one or more append-only (+a) filesystem nodes because of an error: [_2]', @args ); } return Cpanel::LocaleString->new( 'The system failed to set the group ID to “[_1]” on one or more filesystem nodes because of an error: [_2]', @args ); } if ( $gid == -1 ) { if ($path) { my @args = ( $uid, $path, $error, ); if ($immutable) { return Cpanel::LocaleString->new( 'The system failed to set the user ID to “[_1]” on the immutable (+i) file [list_and_quoted,_2] because of an error: [_3]', @args ); } elsif ($append_only) { return Cpanel::LocaleString->new( 'The system failed to set the user ID to “[_1]” on the append-only (+a) file [list_and_quoted,_2] because of an error: [_3]', @args ); } return Cpanel::LocaleString->new( 'The system failed to set the user ID to “[_1]” on [list_and_quoted,_2] because of an error: [_3]', @args ); } my @args = ( $uid, $error, ); if ($immutable) { return Cpanel::LocaleString->new( 'The system failed to set the user ID to “[_1]” on one or more immutable (+i) filesystem nodes because of an error: [_2]', @args ); } elsif ($append_only) { return Cpanel::LocaleString->new( 'The system failed to set the user ID to “[_1]” on one or more append-only (+a) filesystem nodes because of an error: [_2]', @args ); } return Cpanel::LocaleString->new( 'The system failed to set the user ID to “[_1]” on one or more filesystem nodes because of an error: [_2]', @args ); } if ($path) { my @args = ( $uid, $gid, $path, $error, ); if ($immutable) { return Cpanel::LocaleString->new( 'The system failed to set the user ID to “[_1]” and the group ID to “[_2]” on the immutable (+i) file [list_and_quoted,_3] because of an error: [_4]', @args ); } elsif ($append_only) { return Cpanel::LocaleString->new( 'The system failed to set the user ID to “[_1]” and the group ID to “[_2]” on the append-only (+a) file [list_and_quoted,_3] because of an error: [_4]', @args ); } return Cpanel::LocaleString->new( 'The system failed to set the user ID to “[_1]” and the group ID to “[_2]” on [list_and_quoted,_3] because of an error: [_4]', @args ); } my @args = ( $uid, $gid, $error, ); if ($immutable) { return Cpanel::LocaleString->new( 'The system failed to set the user ID to “[_1]” and the group ID to “[_2]” on one or more immutable (+i) filesystem nodes because of an error: [_3]', @args ); } elsif ($append_only) { return Cpanel::LocaleString->new( 'The system failed to set the user ID to “[_1]” and the group ID to “[_2]” on one or more append-only (+a) filesystem nodes because of an error: [_3]', @args ); } return Cpanel::LocaleString->new( 'The system failed to set the user ID to “[_1]” and the group ID to “[_2]” on one or more filesystem nodes because of an error: [_3]', @args ); } 1; } # --- END Cpanel/Exception/IO/ChownError.pm { # --- BEGIN Cpanel/Exception/IO/ChrootError.pm package Cpanel::Exception::IO::ChrootError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( length $self->get('path') ) { return Cpanel::LocaleString->new( 'The system failed to change the root directory to “[_1]” because of an error: [_2]', $self->get('path'), $self->get('error'), ); } return Cpanel::LocaleString->new( 'The system failed to change the root directory because of an error: [_1]', $self->get('error'), ); } 1; } # --- END Cpanel/Exception/IO/ChrootError.pm { # --- BEGIN Cpanel/Exception/IO/DirectoryCloseError.pm package Cpanel::Exception::IO::DirectoryCloseError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( $self->get('path') ) { return Cpanel::LocaleString->new( 'The system failed to close the directory “[_1]” because of an error: [_2]', $self->get('path'), $self->get('error'), ); } return Cpanel::LocaleString->new( 'The system failed to close a directory because of an error: [_1]', $self->get('error'), ); } 1; } # --- END Cpanel/Exception/IO/DirectoryCloseError.pm { # --- BEGIN Cpanel/Exception/IO/DirectoryCreateError.pm package Cpanel::Exception::IO::DirectoryCreateError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to create the directory “[_1]” because of an error: [_2]', @{ $self->{'_metadata'} }{qw(path error)}, ); } 1; } # --- END Cpanel/Exception/IO/DirectoryCreateError.pm { # --- BEGIN Cpanel/Exception/IO/DirectoryDeleteError.pm package Cpanel::Exception::IO::DirectoryDeleteError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to delete the directory “[_1]” because of an error: [_2]', $self->get('path'), $self->get('error'), ); } 1; } # --- END Cpanel/Exception/IO/DirectoryDeleteError.pm { # --- BEGIN Cpanel/Exception/IO/DirectoryOpenError.pm package Cpanel::Exception::IO::DirectoryOpenError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to open the directory “[_1]” because of an error: [_2]', @{ $self->{'_metadata'} }{qw(path error)}, ); } 1; } # --- END Cpanel/Exception/IO/DirectoryOpenError.pm { # --- BEGIN Cpanel/Exception/IO/DirectoryReadError.pm package Cpanel::Exception::IO::DirectoryReadError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to read the directory “[_1]” because of an error: [_2]', @{ $self->{'_metadata'} }{qw(path error)}, ); } 1; } # --- END Cpanel/Exception/IO/DirectoryReadError.pm { # --- BEGIN Cpanel/Exception/IO/DirectoryRewindError.pm package Cpanel::Exception::IO::DirectoryRewindError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( $self->get('path') ) { return Cpanel::LocaleString->new( 'The system failed to rewind its handle for the directory “[_1]” because of an error: [_2]', $self->get('path'), $self->get('error'), ); } return Cpanel::LocaleString->new( 'The system failed to rewind a directory handle because of an error: [_1]', $self->get('error'), ); } 1; } # --- END Cpanel/Exception/IO/DirectoryRewindError.pm { # --- BEGIN Cpanel/Exception/IO/ExecError.pm package Cpanel::Exception::IO::ExecError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; die 'Need “error”!' if !$self->get('error'); if ( $self->get('path') ) { return Cpanel::LocaleString->new( 'The system failed to execute the program “[_1]” because of an error: [_2]', $self->get('path'), $self->get('error'), ); } return Cpanel::LocaleString->new( 'The system failed to execute an unknown program because of an error: [_1]', $self->get('error'), ); } 1; } # --- END Cpanel/Exception/IO/ExecError.pm { # --- BEGIN Cpanel/Exception/IO/FcntlError.pm package Cpanel::Exception::IO::FcntlError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to manipulate a file descriptor because of an error: [_1]', $self->get('error'), ); } 1; } # --- END Cpanel/Exception/IO/FcntlError.pm { # --- BEGIN Cpanel/Exception/IO/FileCloseError.pm package Cpanel::Exception::IO::FileCloseError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( $self->get('path') ) { return Cpanel::LocaleString->new( 'The system failed to close the file “[_1]” because of an error: [_2]', @{ $self->{'_metadata'} }{qw( path error )}, ); } return Cpanel::LocaleString->new( 'The system failed to close an unknown file because of an error: [_1]', $self->get('error'), ); } 1; } # --- END Cpanel/Exception/IO/FileCloseError.pm { # --- BEGIN Cpanel/Exception/IO/FileCopyError.pm package Cpanel::Exception::IO::FileCopyError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( $self->{'_metadata'}{'error'} ) { return Cpanel::LocaleString->new( 'The system failed to copy the file “[_1]” to “[_2]” because of an error: “[_3]”.', @{ $self->{'_metadata'} }{qw( source destination error )}, ); } else { return Cpanel::LocaleString->new( 'The system failed to copy the file “[_1]” to “[_2]” because of an error.', @{ $self->{'_metadata'} }{qw( source destination )}, ); } } 1; } # --- END Cpanel/Exception/IO/FileCopyError.pm { # --- BEGIN Cpanel/Exception/IO/FileNotFound.pm package Cpanel::Exception::IO::FileNotFound; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system cannot find a file named “[_1]”.', $self->{'_metadata'}{'path'}, ); } 1; } # --- END Cpanel/Exception/IO/FileNotFound.pm { # --- BEGIN Cpanel/Exception/IO/FileOpenError.pm package Cpanel::Exception::IO::FileOpenError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; my ( $mode, $immutable, $append_only ) = @{ $self->{'_metadata'} }{qw(mode immutable append_only)}; if ( length($mode) && ( $mode =~ m<\A[0-9]+]\z> ) ) { return $self->_default_phrase_for_sysopen(); ## no extract maketext } my $for_reading = $mode && ( $mode =~ tr{<+}{} ); my $for_writing = $mode && ( $mode =~ tr{>+}{} ); my @args = @{ $self->{'_metadata'} }{qw(path error)}; if ($for_reading) { if ($for_writing) { if ($immutable) { return Cpanel::LocaleString->new( 'The system failed to open the immutable (+i) file “[_1]” for reading and writing because of an error: [_2]', @args ); } elsif ($append_only) { return Cpanel::LocaleString->new( 'The system failed to open the append-only (+a) file “[_1]” for reading and writing because of an error: [_2]', @args ); } else { return Cpanel::LocaleString->new( 'The system failed to open the file “[_1]” for reading and writing because of an error: [_2]', @args ); } } elsif ($immutable) { return Cpanel::LocaleString->new( 'The system failed to open the immutable (+i) file “[_1]” for reading because of an error: [_2]', @args ); } elsif ($append_only) { return Cpanel::LocaleString->new( 'The system failed to open the append-only (+a) file “[_1]” for reading because of an error: [_2]', @args ); } return Cpanel::LocaleString->new( 'The system failed to open the file “[_1]” for reading because of an error: [_2]', @args ); } elsif ($for_writing) { if ($immutable) { return Cpanel::LocaleString->new( 'The system failed to open the immutable (+i) file “[_1]” for writing because of an error: [_2]', @args ); } elsif ($append_only) { return Cpanel::LocaleString->new( 'The system failed to open the append-only (+a) file “[_1]” for writing because of an error: [_2]', @args ); } return Cpanel::LocaleString->new( 'The system failed to open the file “[_1]” for writing because of an error: [_2]', @args ); } elsif ($immutable) { return Cpanel::LocaleString->new( 'The system failed to open the immutable (+i) file “[_1]” because of an error: [_2]', @args ); } elsif ($append_only) { return Cpanel::LocaleString->new( 'The system failed to open the append-only (+a) file “[_1]” because of an error: [_2]', @args ); } return Cpanel::LocaleString->new( 'The system failed to open the file “[_1]” because of an error: [_2]', @args ); } sub _default_phrase_for_sysopen { my ($self) = @_; my ( $path, $error, $mode, $permissions, $immutable, $append_only ) = @{ $self->{'_metadata'} }{qw(path error mode permissions immutable append_only)}; my @flags; while ( my ( $key, $val ) = each %Cpanel::Fcntl::Constants:: ) { next if substr( $key, 0, 2 ) ne 'O_'; next if ref $val ne 'SCALAR'; push @flags, $key if $mode & $$val; } if ( length($permissions) ) { my $octal_permissions = sprintf( '%04o', $permissions ); my @args = ( $path, $octal_permissions, [ sort @flags ], $error, ); if ($immutable) { return Cpanel::LocaleString->new( 'The system failed to open the immutable (+i) file “[_1]” with permissions “[_2]” and flags [list_and_quoted,_3] because of an error: [_4]', @args ); } elsif ($append_only) { return Cpanel::LocaleString->new( 'The system failed to open the append-only (+a) file “[_1]” with permissions “[_2]” and flags [list_and_quoted,_3] because of an error: [_4]', @args ); } return Cpanel::LocaleString->new( 'The system failed to open the file “[_1]” with permissions “[_2]” and flags [list_and_quoted,_3] because of an error: [_4]', @args ); } my @args = ( $path, [ sort @flags ], $error, ); if ($immutable) { return Cpanel::LocaleString->new( 'The system failed to open the immutable (+i) file “[_1]” with flags [list_and_quoted,_2] because of an error: [_3]', @args ); } elsif ($append_only) { return Cpanel::LocaleString->new( 'The system failed to open the append-only (+a) file “[_1]” with flags [list_and_quoted,_2] because of an error: [_3]', @args ); } return Cpanel::LocaleString->new( 'The system failed to open the file “[_1]” with flags [list_and_quoted,_2] because of an error: [_3]', @args ); } 1; } # --- END Cpanel/Exception/IO/FileOpenError.pm { # --- BEGIN Cpanel/Exception/IO/ReadError.pm package Cpanel::Exception::IO::ReadError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; die "Need “error”!" if !$self->get('error'); if ( defined $self->get('length') ) { if ( $self->get('path') ) { return Cpanel::LocaleString->new( 'The system failed to read up to [format_bytes,_1] from “[_2]” because of an error: [_3]', $self->get('length'), $self->get('path'), $self->get('error'), ); } return Cpanel::LocaleString->new( 'The system failed to read up to [format_bytes,_1] from a file handle because of an error: [_2]', $self->get('length'), $self->get('error'), ); } if ( $self->get('path') ) { return Cpanel::LocaleString->new( 'The system failed to read from “[_1]” because of an error: [_2]', $self->get('path'), $self->get('error'), ); } return Cpanel::LocaleString->new( 'The system failed to read from a file handle because of an error: [_1]', $self->get('error'), ); } 1; } # --- END Cpanel/Exception/IO/ReadError.pm { # --- BEGIN Cpanel/Exception/IO/FileReadError.pm package Cpanel::Exception::IO::FileReadError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IO::ReadError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IO::ReadError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( $self->get('path') ) { return Cpanel::LocaleString->new( 'The system failed to read from the file “[_1]” because of an error: [_2]', @{ $self->{'_metadata'} }{qw( path error )}, ); } return Cpanel::LocaleString->new( 'The system failed to read from an unknown file because of an error: [_1]', $self->get('error'), ); } 1; } # --- END Cpanel/Exception/IO/FileReadError.pm { # --- BEGIN Cpanel/Exception/IO/FileSeekError.pm package Cpanel::Exception::IO::FileSeekError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::Fcntl::Constants (); # perlpkg line 211 # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; my ( $path, $position, $whence, $error ) = @{ $self->{'_metadata'} }{qw( path position whence error )}; my $path_is_a_path_not_a_filehandle = length $path && !ref $path; if ( $whence == $Cpanel::Fcntl::Constants::SEEK_SET ) { if ($position) { if ($path_is_a_path_not_a_filehandle) { return Cpanel::LocaleString->new( 'The system failed to move the pointer for the file “[_1]” to [quant,_2,byte,bytes] after the beginning because of an error: [_3]', $path, $position, $error ); } else { return Cpanel::LocaleString->new( 'The system failed to move the pointer for a file to [quant,_1,byte,bytes] after the beginning because of an error: [_2]', $position, $error ); } } elsif ($path_is_a_path_not_a_filehandle) { return Cpanel::LocaleString->new( 'The system failed to move the pointer for the file “[_1]” to the beginning because of an error: [_2]', $path, $error, ); } return Cpanel::LocaleString->new( 'The system failed to move the pointer for a file to the beginning because of an error: [_1]', $error, ); } elsif ( $whence == $Cpanel::Fcntl::Constants::SEEK_CUR ) { if ( $position >= 0 ) { if ($path_is_a_path_not_a_filehandle) { return Cpanel::LocaleString->new( 'The system failed to advance the pointer for the file “[_1]” by [quant,_2,byte,bytes] because of an error: [_3]', $path, $position, $error ); } else { return Cpanel::LocaleString->new( 'The system failed to advance the pointer for a file by [quant,_1,byte,bytes] because of an error: [_2]', $position, $error ); } } elsif ($path_is_a_path_not_a_filehandle) { return Cpanel::LocaleString->new( 'The system failed to move the pointer for the file “[_1]” back by [quant,_2,byte,bytes] because of an error: [_3]', $path, -$position, $error ); } return Cpanel::LocaleString->new( 'The system failed to move the pointer for a file back by [quant,_1,byte,bytes] because of an error: [_2]', -$position, $error ); } elsif ( $whence == $Cpanel::Fcntl::Constants::SEEK_END ) { if ($position) { if ($path_is_a_path_not_a_filehandle) { return Cpanel::LocaleString->new( 'The system failed to move the pointer for the file “[_1]” to [quant,_2,byte,bytes] before the end because of an error: [_3]', $path, -$position, $error ); } else { return Cpanel::LocaleString->new( 'The system failed to move the pointer for a file to [quant,_1,byte,bytes] before the end because of an error: [_2]', -$position, $error ); } } elsif ($path_is_a_path_not_a_filehandle) { return Cpanel::LocaleString->new( 'The system failed to move the pointer for the file “[_1]” to the end because of an error: [_2]', $path, $error, ); } return Cpanel::LocaleString->new( 'The system failed to move the pointer for a file to the end because of an error: [_1]', $error, ); } return Cpanel::LocaleString->new( 'The arguments to [asis,seek()] (“[_1]”, “[_2]”, “[_3]”) are invalid: [_4]', $path, $position, $whence, $error, ); } 1; } # --- END Cpanel/Exception/IO/FileSeekError.pm { # --- BEGIN Cpanel/Exception/IO/FileTruncateError.pm package Cpanel::Exception::IO::FileTruncateError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( $self->get('path') ) { return Cpanel::LocaleString->new( 'The system failed to truncate the file “[_1]” because of an error: [_2]', $self->get('path'), $self->get('error'), ); } return Cpanel::LocaleString->new( 'The system failed to truncate a file because of an error: [_1]', $self->get('error'), ); } 1; } # --- END Cpanel/Exception/IO/FileTruncateError.pm { # --- BEGIN Cpanel/Exception/IO/WriteError.pm package Cpanel::Exception::IO::WriteError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to write [format_bytes,_1] to a file handle because of an error: [_2]', $self->get('length'), $self->get('error'), ); } 1; } # --- END Cpanel/Exception/IO/WriteError.pm { # --- BEGIN Cpanel/Exception/IO/FileWriteError.pm package Cpanel::Exception::IO::FileWriteError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IO::WriteError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IO::WriteError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to write to the file “[_1]” because of an error: [_2]', @{ $self->{'_metadata'} }{qw(path error)}, ); } 1; } # --- END Cpanel/Exception/IO/FileWriteError.pm { # --- BEGIN Cpanel/Exception/IO/FlockError.pm package Cpanel::Exception::IO::FlockError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::Fcntl::Constants (); # perlpkg line 211 # use Cpanel::LocaleString (); # perlpkg line 211 use constant FLAG_ORDER => qw( LOCK_SH LOCK_EX LOCK_UN LOCK_NB ); sub _default_phrase { my ($self) = @_; my $op = $self->get('operation'); my @flags = _op_to_flags($op); if ( $op & $Cpanel::Fcntl::Constants::LOCK_UN ) { if ( $self->get('path') ) { return Cpanel::LocaleString->new( 'The system failed to unlock ([join,~, ,_1]) the file “[_2]” because of an error: [_3]', \@flags, $self->get('path'), $self->get('error'), ); } return Cpanel::LocaleString->new( 'The system failed to unlock ([join,~, ,_1]) an unknown file because of an error: [_2]', \@flags, $self->get('error'), ); } if ( $self->get('path') ) { return Cpanel::LocaleString->new( 'The system failed to lock ([join,~, ,_1]) the file “[_2]” because of an error: [_3]', \@flags, $self->get('path'), $self->get('error'), ); } return Cpanel::LocaleString->new( 'The system failed to lock ([join,~, ,_1]) an unknown file because of an error: [_2]', \@flags, $self->get('error'), ); } sub _op_to_flags { my ($op) = @_; return grep { $op & ${ *{ $Cpanel::Fcntl::Constants::{$_} }{'SCALAR'} } } FLAG_ORDER(); } 1; } # --- END Cpanel/Exception/IO/FlockError.pm { # --- BEGIN Cpanel/Exception/IO/ForkError.pm package Cpanel::Exception::IO::ForkError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to fork a new process because of an error: [_1]', $self->{'_metadata'}{'error'}, ); } 1; } # --- END Cpanel/Exception/IO/ForkError.pm { # --- BEGIN Cpanel/Exception/IO/LinkError.pm package Cpanel::Exception::IO::LinkError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to create a hard link “[_1]” to “[_2]” because of an error: [_3]', ( map { $self->get($_) } qw( newpath oldpath error ) ), ); } 1; } # --- END Cpanel/Exception/IO/LinkError.pm { # --- BEGIN Cpanel/Exception/IO/RenameError.pm package Cpanel::Exception::IO::RenameError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to rename “[_1]” to “[_2]” because of an error: [_3]', @{ $self->{'_metadata'} }{qw( oldpath newpath error )}, ); } 1; } # --- END Cpanel/Exception/IO/RenameError.pm { # --- BEGIN Cpanel/Exception/IO/SelectError.pm package Cpanel::Exception::IO::SelectError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to multiplex filehandles because of an error: [_1]', $self->get('error'), ); } 1; } # --- END Cpanel/Exception/IO/SelectError.pm { # --- BEGIN Cpanel/Exception/IO/SocketOpenError.pm package Cpanel::Exception::IO::SocketOpenError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } use Socket (); # use Cpanel::LocaleString (); # perlpkg line 211 our @_domains_to_check = qw( AF_UNIX AF_INET AF_INET6 AF_X25 AF_APPLETALK ); our @_types_to_check = qw( SOCK_STREAM SOCK_DGRAM SOCK_SEQPACKET SOCK_RAW SOCK_RDM ); sub _default_phrase { my ($self) = @_; my ( $domain, $type, $protocol, $error ) = map { $self->get($_) } qw( domain type protocol error ); return Cpanel::LocaleString->new( 'The system failed to open a socket of domain “[_1]” and type “[_2]” using the “[_3]” protocol because of an error: [_4]', $self->_get_human_DOMAIN($domain), $self->_get_human_TYPE($type), $self->_get_human_PROTOCOL($protocol), $error, ); } sub _get_human_DOMAIN { my ( $self, $value ) = @_; if ( _is_whole_number($value) ) { return _check_value_against_socket_masks( $value, \@_domains_to_check ); } return $value; #unrecognized } sub _get_human_TYPE { my ( $self, $value ) = @_; if ( _is_whole_number($value) ) { return _check_value_against_socket_masks( $value, \@_types_to_check ); } return $value; #unrecognized } sub _get_human_PROTOCOL { my ( $self, $value ) = @_; return ( getprotobynumber $value )[0] || $value; } sub _check_value_against_socket_masks { my ( $value, $masks_ar ) = @_; for my $checking (@$masks_ar) { my $mask = Socket->can($checking)->(); return $checking if ( $value & $mask ) == $mask; } return $value; } sub _is_whole_number { my ($value) = @_; return length($value) && $value =~ m<\A[0-9]+\z>; } 1; } # --- END Cpanel/Exception/IO/SocketOpenError.pm { # --- BEGIN Cpanel/Exception/IO/SocketWriteError.pm package Cpanel::Exception::IO::SocketWriteError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/IO/SocketWriteError.pm { # --- BEGIN Cpanel/Exception/IO/StatError.pm package Cpanel::Exception::IO::StatError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( defined $self->get('path') ) { return Cpanel::LocaleString->new( 'The system failed to obtain filesystem information about “[_1]” because of an error: [_2]', ( map { $self->get($_) } qw( path error ) ), ); } return Cpanel::LocaleString->new( 'The system failed to obtain filesystem information about the node that a file handle references because of an error: [_2]', ( map { $self->get($_) } qw( path error ) ), ); } 1; } # --- END Cpanel/Exception/IO/StatError.pm { # --- BEGIN Cpanel/Exception/IO/SymlinkCreateError.pm package Cpanel::Exception::IO::SymlinkCreateError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to create a symbolic link “[_1]” to “[_2]” because of an error: [_3]', ( map { $self->get($_) } qw( newpath oldpath error ) ), ); } 1; } # --- END Cpanel/Exception/IO/SymlinkCreateError.pm { # --- BEGIN Cpanel/Exception/IO/SymlinkReadError.pm package Cpanel::Exception::IO::SymlinkReadError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to read “[_1]” as a symbolic link because of an error: [_2]', $self->get('path'), $self->get('error'), ); } 1; } # --- END Cpanel/Exception/IO/SymlinkReadError.pm { # --- BEGIN Cpanel/Exception/IO/UnlinkError.pm package Cpanel::Exception::IO::UnlinkError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; my $path_ar = $self->get('path'); $path_ar = [$path_ar] if !ref $path_ar; return Cpanel::LocaleString->new( 'The system failed to unlink [list_and_quoted,_1] because of an error: [_2]', $path_ar, $self->get('error'), ); } 1; } # --- END Cpanel/Exception/IO/UnlinkError.pm { # --- BEGIN Cpanel/Socket/Constants.pm package Cpanel::Socket::Constants; use strict; use warnings; no warnings 'once'; our $SO_REUSEADDR = 2; our $AF_UNIX = 1; our $AF_INET = 2; our $PF_INET = 2; our $AF_INET6 = 10; our $PF_INET6 = 10; our $PROTO_IP = 0; our $PROTO_ICMP = 1; our $PROTO_TCP = 6; our $PROTO_UDP = 17; our $IPPROTO_TCP; *IPPROTO_TCP = \$PROTO_TCP; our $SO_PEERCRED = 17; our $SOL_SOCKET = 1; our $SOCK_STREAM = 1; our $SOCK_NONBLOCK = 2048; our $SHUT_RD = 0; our $SHUT_WR = 1; our $SHUT_RDWR = 2; our $MSG_PEEK = 2; our $MSG_NOSIGNAL = 16384; 1; } # --- END Cpanel/Socket/Constants.pm { # --- BEGIN Cpanel/Socket/Micro.pm package Cpanel::Socket::Micro; use strict; # use Cpanel::Context (); # perlpkg line 211 # use Cpanel::Socket::Constants (); # perlpkg line 211 # use Cpanel::Socket::UNIX::Micro (); # perlpkg line 211 my $pack_template_AF_INET = q< s #sin_family n #sin_port - network order a4 #sin_addr >; my $pack_template_AF_INET6 = q< s #sin6_family n #sin6_port - network order L #sin6_flowinfo a16 #sin6_addr L #sin6_scope_id >; sub unpack_sockaddr_of_any_type { my ($packed) = @_; Cpanel::Context::must_be_list(); my $type_constant = unpack( 's', $packed ); my @socket_attrs; if ( $type_constant == $Cpanel::Socket::Constants::AF_UNIX ) { @socket_attrs = Cpanel::Socket::UNIX::Micro::unpack_sockaddr_un($packed); } elsif ( $type_constant == $Cpanel::Socket::Constants::AF_INET ) { @socket_attrs = unpack_sockaddr_in($packed); } elsif ( $type_constant == $Cpanel::Socket::Constants::AF_INET6 ) { @socket_attrs = unpack_sockaddr_in6($packed); } else { die "Unrecognized socket family: $type_constant"; } return ( $type_constant, @socket_attrs ); } sub unpack_sockaddr_in { my ($sockaddr) = @_; Cpanel::Context::must_be_list(); return ( unpack $pack_template_AF_INET, $sockaddr )[ 1, 2 ]; } sub unpack_sockaddr_in6 { my ($sockaddr) = @_; Cpanel::Context::must_be_list(); return ( unpack $pack_template_AF_INET6, $sockaddr )[ 1, 3, 2, 4 ]; } sub inet_ntoa { my ($binary) = @_; return join '.', unpack 'C4', $binary; } sub inet6_ntoa { my ($binary) = @_; my @doubles = unpack 'n8', $binary; my %zeroes; my @zero_sequences; for my $d ( 0 .. $#doubles ) { next if $doubles[$d] > 0; if ( defined $zeroes{ $d - 1 } ) { $zeroes{$d} = $zeroes{ $d - 1 }; #assign scalar ref ++$zeroes{$d}->{'length'}; } else { $zeroes{$d} = { start => $d, length => 1 }; push @zero_sequences, $zeroes{$d}; } } if (@zero_sequences) { my $biggest_seq = ( sort { $b->{'length'} <=> $a->{'length'} || $a->{'start'} <=> $b->{'start'} } @zero_sequences )[0]; splice( @doubles, $biggest_seq->{'start'}, $biggest_seq->{'length'}, (q<>) x $biggest_seq->{'length'}, ); } my $str = join ':', map { length($_) ? sprintf( '%x', $_ ) : $_ } @doubles; $str =~ s<:::+><::>; return $str; } 1; } # --- END Cpanel/Socket/Micro.pm { # --- BEGIN Cpanel/Exception/IO/SocketConnectError.pm package Cpanel::Exception::IO::SocketConnectError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::ErrnoBase (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::ErrnoBase); } # use Cpanel::LocaleString (); # perlpkg line 211 # use Cpanel::Socket::Constants (); # perlpkg line 211 # use Cpanel::Socket::Micro (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; my $to; my ( $type, @sockdata ) = ( $self->get('type'), $self->get('socket') ); ( $type, @sockdata ) = Cpanel::Socket::Micro::unpack_sockaddr_of_any_type( $self->get('to') ) if !$type && $self->get('to'); if ( $type eq $Cpanel::Socket::Constants::AF_UNIX ) { $to = $sockdata[0]; return Cpanel::LocaleString->new( 'The system failed to connect a [asis,UNIX] domain socket to “[_1]” because of an error: [_2]', $to, $self->get('error'), ); } my $addr; if ( $type eq $Cpanel::Socket::Constants::AF_INET ) { $addr = Cpanel::Socket::Micro::inet_ntoa( $sockdata[1] ); } elsif ( $type eq $Cpanel::Socket::Constants::AF_INET6 ) { $addr = Cpanel::Socket::Micro::inet6_ntoa( $sockdata[1] ); } elsif ( $type eq $Cpanel::Socket::Constants::AF_UNIX ) { $addr = $sockdata[1]; } else { $addr = "unknown address"; } return Cpanel::LocaleString->new( 'The system failed to connect an Internet socket to port “[_1]” of “[_2]” because of an error: [_3]', $sockdata[0], $addr, $self->get('error'), ); } 1; } # --- END Cpanel/Exception/IO/SocketConnectError.pm { # --- BEGIN Cpanel/Exception/IO/ChmodError.pm package Cpanel::Exception::IO::ChmodError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; my ( $path, $error, $permissions, $immutable, $append_only ) = @{ $self->{'_metadata'} }{qw(path error permissions immutable append_only)}; my $print_perms = sprintf( '%04o', $permissions ); @{ $self->{'_metadata'} }{qw(euid egid)} = ( $>, $) ); if ( length $path ) { $path = [$path] if !ref $path; my @args = ( $path, $print_perms, @{ $self->{'_metadata'} }{qw(euid egid)}, $error, ); if ($immutable) { return Cpanel::LocaleString->new( 'The system failed to set the permissions on the immutable (+i) file [list_and_quoted,_1] to “[_2]” (as [asis,EUID]: [_3], [asis,EGID]: [_4]) because of the following error: [_5]', @args ); } elsif ($append_only) { return Cpanel::LocaleString->new( 'The system failed to set the permissions on the append-only (+a) file [list_and_quoted,_1] to “[_2]” (as [asis,EUID]: [_3], [asis,EGID]: [_4]) because of the following error: [_5]', @args ); } return Cpanel::LocaleString->new( 'The system failed to set the permissions on [list_and_quoted,_1] to “[_2]” (as [asis,EUID]: [_3], [asis,EGID]: [_4]) because of the following error: [_5]', @args ); } my @args = ( $print_perms, @{ $self->{'_metadata'} }{qw(euid egid)}, $error, ); if ($immutable) { return Cpanel::LocaleString->new( 'The system failed to set the permissions on one or more immutable (+i) filesystem nodes to “[_1]” (as [asis,EUID]: [_2], [asis,EGID]: [_3]) because of the following error: [_4]', @args ); } elsif ($append_only) { return Cpanel::LocaleString->new( 'The system failed to set the permissions on one or more append-only (+a) inodes to “[_1]” (as [asis,EUID]: [_2], [asis,EGID]: [_3]) because of the following error: [_4]', @args ); } return Cpanel::LocaleString->new( 'The system failed to set the permissions on one or more inodes to “[_1]” (as [asis,EUID]: [_2], [asis,EGID]: [_3]) because of the following error: [_4]', @args ); } 1; } # --- END Cpanel/Exception/IO/ChmodError.pm { # --- BEGIN Cpanel/Exception/IO/FileCreateError.pm package Cpanel::Exception::IO::FileCreateError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; @{ $self->{'_metadata'} }{qw(euid egid)} = ( $>, $) ); if ( defined $self->{'_metadata'}{'permissions'} ) { my $octal_permissions = sprintf( '%04o', $self->{'_metadata'}{'permissions'} ); return Cpanel::LocaleString->new( 'The system failed to create the file “[_1]” with permissions “[_2]” (as [asis,EUID]: [_3], [asis,EGID]: [_4]) because of the following error: [_5]', $self->{'_metadata'}{'path'}, $octal_permissions, @{ $self->{'_metadata'} }{qw(euid egid error)}, ); } return Cpanel::LocaleString->new( 'The system failed to create the file “[_1]” (as [asis,EUID]: [_2], [asis,EGID]: [_3]) because of the following error: [_4]', @{ $self->{'_metadata'} }{qw( path euid egid error )}, ); } 1; } # --- END Cpanel/Exception/IO/FileCreateError.pm { # --- BEGIN Cpanel/Exception/JSONParseError.pm package Cpanel::Exception::JSONParseError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::Caller (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::Caller); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( $self->get('path') && $self->get('dataref') ) { if ( defined ${ $self->get('dataref') } ) { return Cpanel::LocaleString->new( 'The system failed to parse the [asis,JSON] stream data “[_1]” from the file “[_2]” because of an error: [_3]', substr( ${ $self->get('dataref') }, 0, 1024 ), $self->get('path'), $self->get('error'), ); } else { return Cpanel::LocaleString->new( 'The system tried to parse a [asis,JSON] buffer from the file “[_1]”, but the [asis,JSON] parser received no data.', $self->get('path'), ); } } elsif ( $self->get('path') ) { return Cpanel::LocaleString->new( 'The system failed to parse the [asis,JSON] stream from the file “[_1]” because of an error: [_2]', $self->get('path'), $self->get('error'), ); } my $caller_name = $self->_get_caller_name(); if ( $caller_name && $self->get('dataref') ) { if ( defined ${ $self->get('dataref') } ) { return Cpanel::LocaleString->new( 'The system failed to parse the [asis,JSON] stream data “[_1]” for the caller “[_2]” because of an error: [_3]', substr( ${ $self->get('dataref') }, 0, 1024 ), $caller_name, $self->get('error') ); } else { return Cpanel::LocaleString->new( 'The system tried to parse a [asis,JSON] buffer from the caller “[_1]”, but the [asis,JSON] parser received no data.', $caller_name, ); } } elsif ($caller_name) { return Cpanel::LocaleString->new( 'The system failed to parse the [asis,JSON] stream for the caller “[_1]” because of an error: [_2]', $caller_name, $self->get('error') ); } return Cpanel::LocaleString->new( 'The system failed to parse the [asis,JSON] stream: [_1]', $self->get('error'), ); } 1; } # --- END Cpanel/Exception/JSONParseError.pm { # --- BEGIN Cpanel/Exception/MissingMethod.pm package Cpanel::Exception::MissingMethod; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; my ( $method, $pkg ) = map { $self->get($_) } qw(method pkg); return Cpanel::LocaleString->new( 'The “[_1]” method is missing in the “[_2]” class.', $method, $pkg ); } 1; } # --- END Cpanel/Exception/MissingMethod.pm { # --- BEGIN Cpanel/Exception/MissingParameter.pm package Cpanel::Exception::MissingParameter; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::Caller (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::Caller); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; my $caller_name = $self->_get_caller_name(); if ( !$caller_name ) { return Cpanel::LocaleString->new( 'Provide the “[_1]” parameter.', $self->get('name'), ); } return Cpanel::LocaleString->new( 'Provide the “[_1]” parameter for the “[_2]” function.', $self->{'_metadata'}{'name'}, $caller_name ); } 1; } # --- END Cpanel/Exception/MissingParameter.pm { # --- BEGIN Cpanel/Exception/MissingParameters.pm package Cpanel::Exception::MissingParameters; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::MissingParameter (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::MissingParameter); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; my $caller_name = $self->_get_caller_name(); if ( !$caller_name ) { return Cpanel::LocaleString->new( 'Provide the [list_and_quoted,_1] [numerate,_2,parameter,parameters].', $self->get('names'), scalar( @{ $self->get('names') } ), ); } return Cpanel::LocaleString->new( 'Provide the [list_and_quoted,_1] [numerate,_2,parameter,parameters] for the “[_3]” function.', $self->{'_metadata'}{'names'}, scalar( @{ $self->{'_metadata'}{'names'} } ), $caller_name ); } 1; } # --- END Cpanel/Exception/MissingParameters.pm { # --- BEGIN Cpanel/Exception/ModSecurity/DuplicateQueueItem.pm package Cpanel::Exception::ModSecurity::DuplicateQueueItem; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new('The requested action is a duplicate.'); } 1; } # --- END Cpanel/Exception/ModSecurity/DuplicateQueueItem.pm { # --- BEGIN Cpanel/Exception/ModuleLoadError.pm package Cpanel::Exception::ModuleLoadError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to load the module “[_1]” because of an error: [_2]', @{ $self->{'_metadata'} }{qw(module error)}, ); } sub is_not_found { my ($self) = @_; my $err = $self->get('error'); my $path = $self->get('module'); $path =~ s<::>>g; $path .= '.pm'; return ( 0 == index( $err, "Can't locate $path" ) ); } 1; } # --- END Cpanel/Exception/ModuleLoadError.pm { # --- BEGIN Cpanel/Exception/Netlink.pm package Cpanel::Exception::Netlink; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::ErrnoBase (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::ErrnoBase); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'A [asis,Netlink] error occurred: [_1]', $self->get('error'), ); } 1; } # --- END Cpanel/Exception/Netlink.pm { # --- BEGIN Cpanel/Exception/ProcessFailed.pm package Cpanel::Exception::ProcessFailed; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } my $MAX_STREAM_SPEWAGE_SIZE = 10_000; sub _spew { my ($self) = @_; return join( "\n", length( $self->get('stdout') ) ? sprintf( "STDOUT: %s\n", substr( $self->get('stdout'), 0, $MAX_STREAM_SPEWAGE_SIZE ) ) : (), length( $self->get('stderr') ) ? sprintf( "STDERR: %s\n", substr( $self->get('stderr'), 0, $MAX_STREAM_SPEWAGE_SIZE ) ) : (), $self->SUPER::_spew(), ); } 1; } # --- END Cpanel/Exception/ProcessFailed.pm { # --- BEGIN Cpanel/Exception/ProcessFailed/Error.pm package Cpanel::Exception::ProcessFailed::Error; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::ProcessFailed (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::ProcessFailed); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; my ( $error_code, $name, $pid, $stdout, $stderr ) = map { $self->get($_) } qw( error_code process_name pid stdout stderr ); $stderr ||= ''; die "Need “error_code”!" if !length $error_code; if ( length $name ) { if ( length $pid ) { return Cpanel::LocaleString->new( '“[_1]” (process [asis,ID] [_2]) reported error code “[_3]” when it ended: [_4]', $name, $pid, $error_code, $stderr ); } return Cpanel::LocaleString->new( '“[_1]” reported error code “[_2]” when it ended: [_3]', $name, $error_code, $stderr, ); } if ( length $pid ) { return Cpanel::LocaleString->new( 'The subprocess with [asis,ID] “[_1]” reported error code “[_2]” when it ended: [_3]', $pid, $error_code, $stderr, ); } return Cpanel::LocaleString->new( 'A subprocess reported error code “[_1]” when it ended: [_2]', $error_code, $stderr, ); } 1; } # --- END Cpanel/Exception/ProcessFailed/Error.pm { # --- BEGIN Cpanel/Exception/ProcessFailed/Signal.pm package Cpanel::Exception::ProcessFailed::Signal; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::ProcessFailed (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::ProcessFailed); } # use Cpanel::Config::Constants::Perl (); # perlpkg line 211 # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; my ( $sigcode, $name, $pid, $stdout, $stderr ) = map { $self->get($_) } qw( signal_code process_name pid stdout stderr ); $stderr ||= ''; die "Need “signal_code”!" if !length $sigcode; my $signame = $Cpanel::Config::Constants::Perl::SIGNAL_NAME{$sigcode}; if ( length $name ) { if ( length $pid ) { return Cpanel::LocaleString->new( '“[_1]” (process [asis,ID] [_2]) ended prematurely because it received the “[_3]” ([_4]) signal: [_5]', $name, $pid, $signame, $sigcode, $stderr, ); } return Cpanel::LocaleString->new( '“[_1]” ended prematurely because it received the “[_2]” ([_3]) signal: [_4]', $name, $signame, $sigcode, $stderr ); } if ( length $pid ) { return Cpanel::LocaleString->new( 'The subprocess with [asis,ID] “[_1]” ended prematurely because it received the “[_2]” ([_3]) signal: [_4]', $pid, $signame, $sigcode, $stderr ); } return Cpanel::LocaleString->new( 'A subprocess ended prematurely because it received the “[_1]” ([_2]) signal: [_3]', $signame, $sigcode, $stderr ); } sub signal_name { my ($self) = @_; return $Cpanel::Config::Constants::Perl::SIGNAL_NAME{ $self->get('signal_code') }; } 1; } # --- END Cpanel/Exception/ProcessFailed/Signal.pm { # --- BEGIN Cpanel/Exception/ProcessFailed/Timeout.pm package Cpanel::Exception::ProcessFailed::Timeout; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::ProcessFailed (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::ProcessFailed); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; my ( $timeout, $name, $pid ) = map { $self->get($_) } qw( timeout process_name pid ); die "Need “timeout”!" if !defined($timeout); die "“timeout” cannot be negative!" if $timeout < 0; if ( length $name ) { if ( length $pid ) { return Cpanel::LocaleString->new( 'The system aborted the subprocess “[_1]” (process [asis,ID] “[_2]”) because it reached the timeout of [quant,_3,second,seconds].', $name, $pid, $timeout ); } else { return Cpanel::LocaleString->new( 'The system aborted the subprocess “[_1]” because it reached the timeout of [quant,_2,second,seconds].', $name, $timeout ); } } else { if ( length $pid ) { return Cpanel::LocaleString->new( 'The system aborted the subprocess with the [asis,ID] “[_1]” because it reached the timeout of [quant,_2,second,seconds].', $pid, $timeout ); } else { return Cpanel::LocaleString->new( 'The system aborted the subprocess because it reached the timeout of [quant,_1,second,seconds].', $timeout ); } } } 1; } # --- END Cpanel/Exception/ProcessFailed/Timeout.pm { # --- BEGIN Cpanel/Exception/Reserved.pm package Cpanel::Exception::Reserved; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::InvalidParameter (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::InvalidParameter); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( '“[_1]” is a reserved value.', $self->{'_metadata'}{'value'}, ); } 1; } # --- END Cpanel/Exception/Reserved.pm { # --- BEGIN Cpanel/Exception/ReservedSubdomain.pm package Cpanel::Exception::ReservedSubdomain; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/ReservedSubdomain.pm { # --- BEGIN Cpanel/Exception/ResourceLimitReached.pm package Cpanel::Exception::ResourceLimitReached; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/ResourceLimitReached.pm { # --- BEGIN Cpanel/Exception/RootProhibited.pm package Cpanel::Exception::RootProhibited; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { return Cpanel::LocaleString->new('You cannot run this code as [asis,root].'); } 1; } # --- END Cpanel/Exception/RootProhibited.pm { # --- BEGIN Cpanel/Exception/SMTP.pm package Cpanel::Exception::SMTP; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/SMTP.pm { # --- BEGIN Cpanel/Exception/SMTP/FailedRecipient.pm package Cpanel::Exception::SMTP::FailedRecipient; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::SMTP (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::SMTP); } 1; } # --- END Cpanel/Exception/SMTP/FailedRecipient.pm { # --- BEGIN Cpanel/Exception/TempCreateError.pm package Cpanel::Exception::TempCreateError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/TempCreateError.pm { # --- BEGIN Cpanel/Exception/TempFileCreateError.pm package Cpanel::Exception::TempFileCreateError; use strict; use warnings; no warnings 'once'; # use Cpanel::Exception::TempCreateError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::TempCreateError); } # use Cpanel::Exception::ErrnoBase (); # perlpkg line 238 BEGIN { push @ISA, qw(Cpanel::Exception::ErrnoBase); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The system failed to create the temporary file “[_1]” because of an error: [_2]', @{ $self->{'_metadata'} }{qw(path error)}, ); } 1; } # --- END Cpanel/Exception/TempFileCreateError.pm { # --- BEGIN Cpanel/Exception/Timeout.pm package Cpanel::Exception::Timeout; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/Timeout.pm { # --- BEGIN Cpanel/Exception/TooManyBytes.pm package Cpanel::Exception::TooManyBytes; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( $self->get('key') ) { return Cpanel::LocaleString->new( 'The value “[_1]” for “[_2]” is too long by [quant,_3,byte,bytes]. The maximum allowed length is [quant,_4,byte,bytes].', $self->get('value'), $self->get('key'), $self->excess(), $self->{'_metadata'}{'maxlength'}, ); } return Cpanel::LocaleString->new( 'The “[_1]” value exceeds the maximum length by [quant,_2,byte,bytes]. The maximum allowed length is [quant,_3,byte,bytes].', $self->get('value'), $self->excess(), $self->{'_metadata'}{'maxlength'}, ); } sub excess { my ($self) = @_; return length( $self->{'_metadata'}{'value'} ) - $self->{'_metadata'}{'maxlength'}; } 1; } # --- END Cpanel/Exception/TooManyBytes.pm { # --- BEGIN Cpanel/Exception/Unsupported.pm package Cpanel::Exception::Unsupported; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/Unsupported.pm { # --- BEGIN Cpanel/Exception/UserNotFound.pm package Cpanel::Exception::UserNotFound; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'You do not have a user named “[_1]”.', $self->get('name'), ); } 1; } # --- END Cpanel/Exception/UserNotFound.pm { # --- BEGIN Cpanel/Exception/AccessDeniedToAccount.pm package Cpanel::Exception::AccessDeniedToAccount; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The user “[_1]” is not permitted to access the account “[_2]”.', $self->get('user'), $self->get('account') ); } 1; } # --- END Cpanel/Exception/AccessDeniedToAccount.pm { # --- BEGIN Cpanel/Exception/SystemCall.pm package Cpanel::Exception::SystemCall; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::ErrnoBase (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::ErrnoBase); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; if ( my $args_ar = $self->get('arguments') ) { return Cpanel::LocaleString->new( 'The system failed to execute the system call “[_1]” ([_2]) because of an error: [_3]', $self->get('name'), "@$args_ar", $self->get('error'), ); } return Cpanel::LocaleString->new( 'The system failed to execute the system call “[_1]” because of an error: [_2]', $self->get('name'), $self->get('error'), ); } 1; } # --- END Cpanel/Exception/SystemCall.pm { # --- BEGIN Cpanel/Exception/Services/Unknown.pm package Cpanel::Exception::Services::Unknown; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; return Cpanel::LocaleString->new( 'The “[_1]” service is not a known service.', $self->get('service'), ); } 1; } # --- END Cpanel/Exception/Services/Unknown.pm { # --- BEGIN Cpanel/Exception/UserdataLookupFailure.pm package Cpanel::Exception::UserdataLookupFailure; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/UserdataLookupFailure.pm { # --- BEGIN Cpanel/Exception/RemoteMySQL/UnsupportedAuthPlugin.pm package Cpanel::Exception::RemoteMySQL::UnsupportedAuthPlugin; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/RemoteMySQL/UnsupportedAuthPlugin.pm { # --- BEGIN Cpanel/Exception/RemoteMySQL/InsufficientPrivileges.pm package Cpanel::Exception::RemoteMySQL::InsufficientPrivileges; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/RemoteMySQL/InsufficientPrivileges.pm { # --- BEGIN Cpanel/Exception/RecordNotFound.pm package Cpanel::Exception::RecordNotFound; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/RecordNotFound.pm { # --- BEGIN Cpanel/Exception/NameConflict.pm package Cpanel::Exception::NameConflict; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception); } 1; } # --- END Cpanel/Exception/NameConflict.pm { # --- BEGIN Cpanel/Exception/IO/FileLockError.pm package Cpanel::Exception::IO::FileLockError; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Exception::IOError (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Exception::IOError); } # use Cpanel::LocaleString (); # perlpkg line 211 sub _default_phrase { my ($self) = @_; my ( $path, $error, $immutable, $append_only ) = @{ $self->{'_metadata'} }{qw(path error immutable append_only)}; my @args = ( $path, $>, # euid $), # egid $error, ); if ($immutable) { return Cpanel::LocaleString->new( 'The system failed to lock the immutable (+i) file “[_1]” (as [asis,EUID]: [_2], [asis,EGID]: [_3]) because of the following error: [_4]', @args ); } elsif ($append_only) { return Cpanel::LocaleString->new( 'The system failed to lock the append-only (+a) file “[_1]” (as [asis,EUID]: [_2], [asis,EGID]: [_3]) because of the following error: [_4]', @args ); } return Cpanel::LocaleString->new( 'The system failed to lock the file “[_1]” (as [asis,EUID]: [_2], [asis,EGID]: [_3]) because of the following error: [_4]', @args ); } 1; } # --- END Cpanel/Exception/IO/FileLockError.pm { # --- BEGIN Cpanel/Exception/UpdateNow.pm package Cpanel::Exception::UpdateNow; use strict; use warnings; no warnings 'once'; require Cpanel::Exception::AdminBinError; # PPI USE OK -- force load exception modules require Cpanel::Exception::AbstractClass; # PPI USE OK -- force load exception modules require Cpanel::Exception::AttributeNotSet; # PPI USE OK -- force load exception modules require Cpanel::Exception::AttributeReadOnly; # PPI USE OK -- force load exception modules require Cpanel::Exception::System::RequiredRoleDisabled; # PPI USE OK -- force load exception modules require Cpanel::Exception::Caller; # PPI USE OK -- force load exception modules require Cpanel::Exception::Collection; # PPI USE OK -- force load exception modules require Cpanel::Exception::CommandAlreadyRunning; # PPI USE OK -- force load exception modules require Cpanel::Exception::ConnectionFailed; # PPI USE OK -- force load exception modules require Cpanel::Exception::ContextError; # PPI USE OK -- force load exception modules require Cpanel::Exception::Database::SchemaOutdated; # PPI USE OK -- force load exception modules require Cpanel::Exception::Database::DatabaseCreationFailed; # PPI USE OK -- force load exception modules require Cpanel::Exception::Database::DatabaseMissing; # PPI USE OK -- force load exception modules require Cpanel::Exception::Database::Error; # PPI USE OK -- force load exception modules require Cpanel::Exception::Database::ServerTime; # PPI USE OK -- force load exception modules require Cpanel::Exception::Database::TableCorruption; # PPI USE OK -- force load exception modules require Cpanel::Exception::Database::TableCreationFailed; # PPI USE OK -- force load exception modules require Cpanel::Exception::Database::TableInsertionFailed; # PPI USE OK -- force load exception modules require Cpanel::Exception::Database::UserMissing; # PPI USE OK -- force load exception modules require Cpanel::Exception::Database::CpuserNotInMap; # PPI USE OK -- force load exception modules require Cpanel::Exception::Database::DatabaseCreationInProgress; # PPI USE OK -- force load exception modules require Cpanel::Exception::Database::DatabaseNotFound; # PPI USE OK -- force load exception modules require Cpanel::Exception::Database::UserNotFound; # PPI USE OK -- force load exception modules require Cpanel::Exception::DnsEntryAlreadyExists; # PPI USE OK -- force load exception modules require Cpanel::Exception::DomainAlreadyExists; # PPI USE OK -- force load exception modules require Cpanel::Exception::DomainDoesNotExist; # PPI USE OK -- force load exception modules require Cpanel::Exception::DomainHasUnknownNameservers; # PPI USE OK -- force load exception modules require Cpanel::Exception::DomainNameNotAllowed; # PPI USE OK -- force load exception modules require Cpanel::Exception::DomainNameNotRfcCompliant; # PPI USE OK -- force load exception modules require Cpanel::Exception::DomainNotRegistered; # PPI USE OK -- force load exception modules require Cpanel::Exception::DomainOwnership; # PPI USE OK -- force load exception modules require Cpanel::Exception::Email::AccountNotFound; # PPI USE OK -- force load exception modules require Cpanel::Exception::Empty; # PPI USE OK -- force load exception modules require Cpanel::Exception::EntryAlreadyExists; # PPI USE OK -- force load exception modules require Cpanel::Exception::EntryDoesNotExist; # PPI USE OK -- force load exception modules require Cpanel::Exception::FeatureNotEnabled; # PPI USE OK -- force load exception modules require Cpanel::Exception::FeaturesNotEnabled; # PPI USE OK -- force load exception modules require Cpanel::Exception::ForbiddenInDemoMode; # PPI USE OK -- force load exception modules require Cpanel::Exception::FunctionNotImplemented; # PPI USE OK -- force load exception modules require Cpanel::Exception::HTTP::Network; # PPI USE OK -- force load exception modules require Cpanel::Exception::HTTP::Server; # PPI USE OK -- force load exception modules require Cpanel::Exception::HTTP; # PPI USE OK -- force load exception modules require Cpanel::Exception::InvalidCharacters; # PPI USE OK -- force load exception modules require Cpanel::Exception::InvalidParameter; # PPI USE OK -- force load exception modules require Cpanel::Exception::InvalidParameters; # PPI USE OK -- force load exception modules require Cpanel::Exception::InvalidUsername; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::CloseError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::ChdirError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::ChownError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::ChrootError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::DirectoryCloseError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::DirectoryCreateError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::DirectoryDeleteError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::DirectoryOpenError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::DirectoryReadError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::DirectoryRewindError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::ExecError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::FcntlError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::FileCloseError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::FileCopyError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::FileNotFound; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::FileOpenError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::FileReadError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::FileSeekError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::FileTruncateError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::FileWriteError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::FlockError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::ForkError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::LinkError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::RenameError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::SelectError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::SocketOpenError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::SocketWriteError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::StatError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::SymlinkCreateError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::SymlinkReadError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::UnlinkError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::WriteError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::ReadError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::SocketConnectError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::ChmodError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::FileCreateError; # PPI USE OK -- force load exception modules require Cpanel::Exception::IOError; # PPI USE OK -- force load exception modules require Cpanel::Exception::JSONParseError; # PPI USE OK -- force load exception modules require Cpanel::Exception::MissingMethod; # PPI USE OK -- force load exception modules require Cpanel::Exception::MissingParameter; # PPI USE OK -- force load exception modules require Cpanel::Exception::MissingParameters; # PPI USE OK -- force load exception modules require Cpanel::Exception::ModSecurity::DuplicateQueueItem; # PPI USE OK -- force load exception modules require Cpanel::Exception::ModuleLoadError; # PPI USE OK -- force load exception modules require Cpanel::Exception::Netlink; # PPI USE OK -- force load exception modules require Cpanel::Exception::ProcessFailed::Error; # PPI USE OK -- force load exception modules require Cpanel::Exception::ProcessFailed::Signal; # PPI USE OK -- force load exception modules require Cpanel::Exception::ProcessFailed::Timeout; # PPI USE OK -- force load exception modules require Cpanel::Exception::Reserved; # PPI USE OK -- force load exception modules require Cpanel::Exception::ReservedSubdomain; # PPI USE OK -- force load exception modules require Cpanel::Exception::ResourceLimitReached; # PPI USE OK -- force load exception modules require Cpanel::Exception::RootProhibited; # PPI USE OK -- force load exception modules require Cpanel::Exception::SMTP; # PPI USE OK -- force load exception modules require Cpanel::Exception::SMTP::FailedRecipient; # PPI USE OK -- force load exception modules require Cpanel::Exception::TempFileCreateError; # PPI USE OK -- force load exception modules require Cpanel::Exception::Timeout; # PPI USE OK -- force load exception modules require Cpanel::Exception::TooManyBytes; # PPI USE OK -- force load exception modules require Cpanel::Exception::Unsupported; # PPI USE OK -- force load exception modules require Cpanel::Exception::UserNotFound; # PPI USE OK -- force load exception modules require Cpanel::Exception::AccessDeniedToAccount; # PPI USE OK -- force load exception modules require Cpanel::Exception::SystemCall; # PPI USE OK -- force load exception modules require Cpanel::Exception::Services::Unknown; # PPI USE OK -- force load exception modules require Cpanel::Exception::UserdataLookupFailure; # PPI USE OK -- force load exception modules require Cpanel::Exception::RemoteMySQL::UnsupportedAuthPlugin; # PPI USE OK -- force load exception modules require Cpanel::Exception::RemoteMySQL::InsufficientPrivileges; # PPI USE OK -- force load exception modules require Cpanel::Exception::RecordNotFound; # PPI USE OK -- force load exception modules require Cpanel::Exception::NameConflict; # PPI USE OK -- force load exception modules require Cpanel::Exception::IO::FileLockError; # PPI USE OK -- force load exception modules 1; # PPI USE OK -- force load exception modules } # --- END Cpanel/Exception/UpdateNow.pm { # --- BEGIN Cpanel/Locale/Context.pm package Cpanel::Locale::Context; use strict; use warnings; no warnings 'once'; our $DEFAULT_OUTPUT_CONTEXT; 1; } # --- END Cpanel/Locale/Context.pm { # --- BEGIN Cpanel/SafeDir/RM.pm package Cpanel::SafeDir::RM; use strict; use warnings; no warnings 'once'; sub safermdir { ## no critic qw(Subroutines::RequireArgUnpacking) return if !-d $_[0]; return 1 if rmdir( $_[0] ); if ( opendir( my $dh, $_[0] ) ) { while ( my $file = readdir($dh) ) { next if $file eq '.' || $file eq '..'; unlink("$_[0]/$file") or last; } } return 1 if rmdir( $_[0] ); require File::Path; File::Path::rmtree( $_[0] ); if ( !-d $_[0] ) { $? = 0; return 1; } return; } 1; } # --- END Cpanel/SafeDir/RM.pm { # --- BEGIN Cpanel/Config/Sources.pm package Cpanel::Config::Sources; use strict; use warnings; no warnings 'once'; # use Cpanel::Config::LoadConfig (); # perlpkg line 211 use constant MY_IPV4_ENDPOINT => 'https://myip.cpanel.net/v1.0/'; our $cpsources_conf_file = '/etc/cpsources.conf'; sub get_source { my ($want_key) = @_; return unless length $want_key; my $conf = loadcpsources(); return $conf->{$want_key} // ''; } my $load_cpsources_cache; sub set_cache { return $load_cpsources_cache = shift; } sub loadcpsources { if ( !$load_cpsources_cache ) { if ( ${^GLOBAL_PHASE} && ${^GLOBAL_PHASE} eq 'START' && lc($0) ne '-e' ) { die q[FATAL: loadcpsources is called during compile time. You should postpone this call.]; } my $update_default = 'httpupdate.cpanel.net'; my %sources = ( 'NEWS' => 'web.cpanel.net', 'RSYNC' => 'rsync.cpanel.net', 'HTTPUPDATE' => $update_default, 'MYIP' => MY_IPV4_ENDPOINT, # URL to determine a local IP's public IP (1to1 NAT) 'STORE_SERVER_URL' => 'https://store.cpanel.net', 'TICKETS_SERVER_URL' => 'https://account.cpanel.net', 'VERIFY_URL' => 'https://verify.cpanel.net', 'MANAGE2_URL' => 'https://manage2.cpanel.net', ); if ( -e $cpsources_conf_file ) { Cpanel::Config::LoadConfig::loadConfig( $cpsources_conf_file, \%sources ); } foreach my $key ( keys %sources ) { next if ( !defined $sources{$key} ); $sources{$key} =~ s/^\s+//; $sources{$key} =~ s/\s+$//; } $load_cpsources_cache = \%sources; } return wantarray ? %$load_cpsources_cache : $load_cpsources_cache; } 1; } # --- END Cpanel/Config/Sources.pm { # --- BEGIN Cpanel/Crypt/GPG/Settings.pm package Cpanel::Crypt::GPG::Settings; use strict; # use Cpanel::Config::CpConfGuard (); # perlpkg line 211 # use Cpanel::Config::Sources (); # perlpkg line 211 # use Cpanel::Exception (); # perlpkg line 211 our $RELEASE_VALUE = 'Release Keyring Only'; our $DEVELOPMENT_VALUE = 'Release and Development Keyrings'; our $OFF_VALUE = 'Off'; our $OLD_DEVELOPMENT_VALUE = 'Release and Test Keyrings'; our $RELEASE_KEYRINGS = ['release']; our $DEVELOPMENT_KEYRINGS = [ 'release', 'development' ]; our $OFF_KEYRINGS = []; our $SIG_VALIDATION_CPCONF_KEY = 'signature_validation'; sub signature_validation_enabled { my $validation_setting = _load_cpconf_setting($SIG_VALIDATION_CPCONF_KEY); return ( $validation_setting eq $OFF_VALUE ) ? 0 : 1; } sub default_key_categories { my $validation_setting = shift || _load_cpconf_setting($SIG_VALIDATION_CPCONF_KEY); if ( $validation_setting eq $OFF_VALUE ) { return $OFF_KEYRINGS; } elsif ( $validation_setting eq $DEVELOPMENT_VALUE ) { return $DEVELOPMENT_KEYRINGS; } elsif ( $validation_setting eq $RELEASE_VALUE ) { return $RELEASE_KEYRINGS; } else { die Cpanel::Exception->create( 'Invalid signature validation setting: [_1]', [$validation_setting] ); } } sub allowed_digest_algorithms { return ('sha512'); } sub _load_cpconf_setting { my $setting = shift; my $conf = Cpanel::Config::CpConfGuard->new( 'loadcpconf' => 1 )->config_copy; if ( $setting eq $SIG_VALIDATION_CPCONF_KEY ) { return validation_setting_fixup( $conf->{$setting} ); } else { return $conf->{$setting}; } } sub validation_setting_fixup { my $current_setting = shift; if ( defined $current_setting && $current_setting eq $OLD_DEVELOPMENT_VALUE ) { return $DEVELOPMENT_VALUE; } elsif ( !defined $current_setting || $current_setting !~ /^(?:\Q$OFF_VALUE\E|\Q$RELEASE_VALUE\E|\Q$DEVELOPMENT_VALUE\E)$/ ) { return validation_setting_for_configured_mirror(); } return $current_setting; } sub validation_setting_for_configured_mirror { my $mirror = Cpanel::Config::Sources::loadcpsources(); if ( $mirror->{'HTTPUPDATE'} =~ /^(?:.*\.dev|qa-build|next)\.cpanel\.net$/ ) { return $DEVELOPMENT_VALUE; } return $RELEASE_VALUE; } 1; } # --- END Cpanel/Crypt/GPG/Settings.pm { # --- BEGIN Cpanel/Update/Logger.pm package Cpanel::Update::Logger; use strict; use warnings; no warnings 'once'; # use Cpanel::SafeDir::MK (); # perlpkg line 211 # use Cpanel::Time::Local (); # perlpkg line 211 # use Cpanel::FHUtils::Autoflush (); # perlpkg line 211 use File::Basename (); use constant { DEBUG => 0, INFO => 25, WARN => 50, ERROR => 75, FATAL => 100, }; our $VERSION = '1.2'; our $_BACKLOG_TIE_CLASS; sub new { my $class = shift; my $self = shift || {}; ref($self) eq 'HASH' or CORE::die("hashref not passed to new"); bless( $self, $class ); $self->{'stdout'} = 1 if ( !defined $self->{'stdout'} ); $self->{'timestamp'} = 1 if ( !defined $self->{'timestamp'} ); if ( $self->{'to_memory'} ) { $self->{'backlog'} = []; tie @{ $self->{'backlog'} }, $_BACKLOG_TIE_CLASS if $_BACKLOG_TIE_CLASS; } eval { $self->set_logging_level( $self->{'log_level'} ); 1 } or CORE::die("An invalid logging level was passed to new: $self->{'log_level'}"); $self->open_log() if $self->{'logfile'}; if ( exists $self->{'pbar'} and defined $self->{'pbar'} ) { $self->{'pbar'} += 0; $self->update_pbar( $self->{'pbar'} ); } return $self; } sub open_log { my $self = shift or CORE::die(); my $log_file = $self->{'logfile'}; my $logfile_dir = File::Basename::dirname($log_file); my $created_dir = 0; if ( !-d $logfile_dir ) { Cpanel::SafeDir::MK::safemkdir( $logfile_dir, '0700', 2 ); $created_dir = 1; } my $old_umask = umask(0077); # Case 92381: Logs should not be world-readable open( my $fh, '>>', $log_file ) or do { CORE::die("Failed to open '$log_file' for append: $!"); }; umask($old_umask); Cpanel::FHUtils::Autoflush::enable($fh); Cpanel::FHUtils::Autoflush::enable( \*STDOUT ) if $self->{'stdout'}; $self->{'fh'} = $fh; unless ( $self->{brief} ) { print {$fh} '-' x 100 . "\n"; print {$fh} "=> Log opened from $0 ($$) at " . localtime(time) . "\n"; } $self->warning("Had to create directory $logfile_dir before opening log") if ($created_dir); return; } sub close_log { my $self = shift or CORE::die(); return if ( !$self->{'fh'} ); my $fh = $self->{'fh'}; unless ( $self->{brief} ) { print {$fh} "=> Log closed " . localtime(time) . "\n"; } warn("Failed to close file handle for $self->{'logfile'}") if ( !close $fh ); delete $self->{'fh'}; return; } sub DESTROY { my $self = shift or CORE::die("DESTROY called without an object"); $self->close_log if ( $self->{'fh'} ); return; } sub log { my $self = shift or CORE::die("log called as a class"); ref $self eq __PACKAGE__ or CORE::die("log called as a class"); my $msg = shift or return; my $stdout = shift; $stdout = $self->{'stdout'} if ( !defined $stdout ); my $to_memory = $self->{'to_memory'}; my $fh = $self->{'fh'}; foreach my $line ( split( /[\r\n]+/, $msg ) ) { if ( $self->{'timestamp'} ) { substr( $line, 0, 0, '[' . Cpanel::Time::Local::localtime2timestamp() . '] ' ); } chomp $line; print STDOUT "$line\n" if $stdout; print {$fh} "$line\n" if $fh; push @{ $self->{'backlog'} }, "$line" if ($to_memory); } return; } sub _die { my $self = shift or CORE::die(); my $message = shift || ''; $self->log("***** DIE: $message"); return CORE::die( "exit level [die] [pid=$$] ($message) " . join ' ', caller() ); } sub fatal { my $self = shift or CORE::die(); return if ( $self->{'log_level_numeric'} > FATAL ); my $message = shift || ''; $self->log("***** FATAL: $message"); $self->set_need_notify(); return; } sub error { my $self = shift or CORE::die(); return if ( $self->{'log_level_numeric'} > ERROR ); my $message = shift || ''; $self->log("E $message"); return; } sub warning { my $self = shift or CORE::die(); return if ( $self->{'log_level_numeric'} > WARN ); my $message = shift || ''; $self->log("W $message"); return; } sub panic { my $self = shift or CORE::die(); return if ( $self->{'log_level_numeric'} > ERROR ); my $message = shift || ''; $self->log("***** PANIC!"); $self->log("E $message"); $self->log("***** PANIC!"); $self->set_need_notify(); return; } sub info { my $self = shift or CORE::die(); return if ( $self->{'log_level_numeric'} > INFO ); my $message = shift || ''; $self->log(" $message"); return; } sub debug { my $self = shift or CORE::die(); return if ( $self->{'log_level_numeric'} > DEBUG ); my $message = shift || ''; $self->log("D $message"); return; } sub get_logging_level { return shift->{'log_level'} } sub set_logging_level { my $self = shift or CORE::die(); my $log_level = shift; $log_level = 'info' if ( !defined $log_level ); my $old_log_level = $self->get_logging_level(); if ( $log_level =~ m/^fatal/i ) { $self->{'log_level'} = 'fatal'; $self->{'log_level_numeric'} = FATAL; } elsif ( $log_level =~ m/^error/i ) { $self->{'log_level'} = 'error'; $self->{'log_level_numeric'} = ERROR; } elsif ( $log_level =~ m/^warn/i ) { $self->{'log_level'} = 'warning'; $self->{'log_level_numeric'} = WARN; } elsif ( $log_level =~ m/^info/i ) { $self->{'log_level'} = 'info'; $self->{'log_level_numeric'} = INFO; } elsif ( $log_level =~ m/^debug/i ) { $self->{'log_level'} = 'debug'; $self->{'log_level_numeric'} = DEBUG; } else { CORE::die("Unknown logging level '$log_level' passed to set_logging_level"); } return $old_log_level; } sub get_pbar { return shift->{'pbar'} } sub increment_pbar { my $self = shift or CORE::die(); return if ( !exists $self->{'pbar'} ); my $amount = shift || 1; my $new_value = $self->{'pbar'} + $amount; return $self->update_pbar($new_value); } sub update_pbar { my $self = shift or CORE::die(); return if ( !exists $self->{'pbar'} ); my $new_value = shift || 0; if ( $new_value > 100 ) { $self->debug("Pbar set to > 100 ($new_value)"); $new_value = 100; } return if $new_value == $self->{'pbar'}; $self->{'pbar'} = $new_value; $self->info( $new_value . '% complete' ); return; } sub set_need_notify { my $self = shift; ref $self eq __PACKAGE__ or CORE::die("log called as a class"); $self->info("The Administrator will be notified to review this output when this script completes"); return $self->{'need_notify'} = 1; } sub get_need_notify { my $self = shift; ref $self eq __PACKAGE__ or CORE::die("log called as a class"); return $self->{'need_notify'}; } sub get_stored_log { my $self = shift; ref $self eq __PACKAGE__ or CORE::die("log called as a class"); return if ( !$self->{'to_memory'} ); return $self->{'backlog'}; } sub get_next_log_message { my $self = shift; ref $self eq __PACKAGE__ or CORE::die("log called as a class"); return if ( !$self->{'to_memory'} ); return shift @{ $self->{'backlog'} }; } sub success { goto \&info; } sub out { goto \&info; } sub warn { goto \&warning; } sub die { goto \&_die; } 1; } # --- END Cpanel/Update/Logger.pm { # --- BEGIN Cpanel/Config/Merge.pm package Cpanel::Config::Merge; use strict; use warnings; no warnings 'once'; # use Cpanel::Config::LoadConfig (); # perlpkg line 211 # use Cpanel::Config::FlushConfig (); # perlpkg line 211 # use Cpanel::Crypt::GPG::Settings (); # perlpkg line 211 # use Cpanel::Update::Logger (); # perlpkg line 211 sub files { my (%opts) = @_; my $config_defaults_file = $opts{defaults_file} or die q[Missing required 'defaults_file' argument]; # a.k.a. source my $config_file = $opts{config_file} or die q[Missing required 'config_file' argument]; # a.k.a. destination my $logger = $opts{logger} // Cpanel::Update::Logger->new; my $cpanel_config = {}; # hash used to load config in memory Cpanel::Config::LoadConfig::loadConfig( $config_defaults_file, $cpanel_config ); $cpanel_config->{'signature_validation'} = Cpanel::Crypt::GPG::Settings::validation_setting_for_configured_mirror(); if ( -e $config_file ) { $logger->info("Merging custom cpanel.config entries provided by installer with cPanel defaults."); Cpanel::Config::LoadConfig::loadConfig( $config_file, $cpanel_config ); } else { $logger->info("Installing default cpanel.config, located in etc/cpanel.config"); } Cpanel::Config::FlushConfig::flushConfig( $config_file, $cpanel_config, '=', undef, { 'sort' => 1 } ); return 1; } 1; } # --- END Cpanel/Config/Merge.pm { # --- BEGIN Cpanel/Binaries.pm package Cpanel::Binaries; use strict; use warnings; no warnings 'once'; our @_OVERRIDES; our $VERBOSE = 1; # use Cpanel::OS (); # perlpkg line 211 use constant { PERL_MAJOR => 536, PERL_LEGACY_MAJOR => 532, PHP_MAJOR => 84, PHP_LEGACY_MAJOR => 83, THIRD_PARTY => q{/usr/local/cpanel/3rdparty}, }; use constant { THIRD_PARTY_BIN => THIRD_PARTY . q{/bin}, CPANEL_PERL => THIRD_PARTY . q{/perl/} . PERL_MAJOR(), CPANEL_PERL_LEGACY => THIRD_PARTY . q{/perl/} . PERL_LEGACY_MAJOR(), CPANEL_PHP => THIRD_PARTY . q{/php/} . PHP_MAJOR(), CPANEL_PHP_LEGACY => THIRD_PARTY . q{/php/} . PHP_LEGACY_MAJOR(), CPANEL_PHP_UNVERSIONED => THIRD_PARTY . q{/php/unversioned}, SYSTEM_BIN => q{/usr/bin}, SYSTEM_SBIN => q{/usr/sbin}, LOCAL_BIN => q{/usr/local/bin}, }; use constant { CPANEL_PERL_BIN => CPANEL_PERL . q{/bin}, CPANEL_PERL_SBIN => CPANEL_PERL . q{/sbin}, CPANEL_PHP_BIN => CPANEL_PHP . q{/bin}, CPANEL_PHP_LEGACY_BIN => CPANEL_PHP_LEGACY . q{/bin}, }; sub system_bin_locations { return { 'cloudlinux-awp-admin' => SYSTEM_BIN, 'cloudlinux-awp-user' => SYSTEM_BIN, 'identify' => SYSTEM_BIN, 'convert' => SYSTEM_BIN, 'mogrify' => SYSTEM_BIN, 'firewall-cmd' => SYSTEM_BIN, 'firewalld' => SYSTEM_SBIN, 'at' => SYSTEM_BIN, 'atq' => SYSTEM_BIN, 'atrm' => SYSTEM_BIN, 'chattr' => SYSTEM_BIN, 'chmod' => SYSTEM_BIN, 'crontab' => SYSTEM_BIN, 'curl' => SYSTEM_BIN, 'dig' => SYSTEM_BIN, 'doveadm' => SYSTEM_BIN, 'dpkg-query' => SYSTEM_BIN, 'dsync' => SYSTEM_BIN, 'file' => SYSTEM_BIN, 'find' => SYSTEM_BIN, 'gcc' => SYSTEM_BIN, 'getfacl' => SYSTEM_BIN, 'gpg' => SYSTEM_BIN, 'gzip' => SYSTEM_BIN, 'host' => SYSTEM_BIN, 'iconv' => SYSTEM_BIN, 'ionice' => SYSTEM_BIN, 'iostat' => SYSTEM_BIN, 'ipcrm' => SYSTEM_BIN, 'ipcs' => SYSTEM_BIN, 'lsattr' => SYSTEM_BIN, 'lsof' => SYSTEM_BIN, 'make' => SYSTEM_BIN, 'mysql' => SYSTEM_BIN, 'mysql_config' => SYSTEM_BIN, 'mysql_upgrade' => SYSTEM_BIN, 'mysqladmin' => SYSTEM_BIN, 'mysqlcheck' => SYSTEM_BIN, 'mysqldump' => SYSTEM_BIN, 'nano' => SYSTEM_BIN, 'openssl' => SYSTEM_BIN, 'pdns_control' => SYSTEM_BIN, 'pdnsutil' => SYSTEM_BIN, 'perl' => SYSTEM_BIN, 'pigz' => SYSTEM_BIN, 'python3' => SYSTEM_BIN, 'quota' => SYSTEM_BIN, 'repoquery' => SYSTEM_BIN, 'rsync' => SYSTEM_BIN, 'setfacl' => SYSTEM_BIN, 'ssh-keygen' => SYSTEM_BIN, 'ssh-keyscan' => SYSTEM_BIN, 'strace' => SYSTEM_BIN, 'sudo' => SYSTEM_BIN, 'systemctl' => SYSTEM_BIN, 'tail' => SYSTEM_BIN, 'test' => SYSTEM_BIN, 'unzip' => SYSTEM_BIN, 'vim' => SYSTEM_BIN, 'wall' => SYSTEM_BIN, 'xmlwf' => SYSTEM_BIN, 'yum' => SYSTEM_BIN, 'yum-config-manager' => SYSTEM_BIN, 'zip' => SYSTEM_BIN, 'atd' => SYSTEM_SBIN, 'convertquota' => SYSTEM_SBIN, 'edquota' => SYSTEM_SBIN, 'exim' => SYSTEM_SBIN, 'exim_dbmbuild' => SYSTEM_SBIN, 'exim_tidydb' => SYSTEM_SBIN, 'grubby' => SYSTEM_SBIN, 'ifconfig' => SYSTEM_SBIN, 'ip' => SYSTEM_SBIN, 'ip6tables' => SYSTEM_SBIN, 'ip6tables-save' => SYSTEM_SBIN, 'iptables' => SYSTEM_SBIN, 'iptables-save' => SYSTEM_SBIN, 'logrotate' => SYSTEM_SBIN, 'losetup' => SYSTEM_SBIN, 'mysqld' => SYSTEM_SBIN, 'named' => SYSTEM_SBIN, 'nft' => SYSTEM_SBIN, 'nscd' => SYSTEM_SBIN, 'pdns_server' => SYSTEM_SBIN, 'quotacheck' => SYSTEM_SBIN, 'quotaoff' => SYSTEM_SBIN, 'quotaon' => SYSTEM_SBIN, 'repquota' => SYSTEM_SBIN, 'rndc-confgen' => SYSTEM_SBIN, 'rsyslogd' => SYSTEM_SBIN, 'service' => SYSTEM_SBIN, 'sshd' => SYSTEM_SBIN, 'pkill' => SYSTEM_BIN, 'bash' => SYSTEM_BIN, 'cat' => SYSTEM_BIN, 'cp' => SYSTEM_BIN, 'date' => SYSTEM_BIN, 'dd' => SYSTEM_BIN, 'df' => SYSTEM_BIN, 'echo' => SYSTEM_BIN, 'false' => SYSTEM_BIN, 'grep' => SYSTEM_BIN, 'hostname' => SYSTEM_BIN, 'ls' => SYSTEM_BIN, 'mount' => SYSTEM_BIN, 'netstat' => SYSTEM_BIN, 'pwd' => SYSTEM_BIN, 'rm' => SYSTEM_BIN, 'rpm' => SYSTEM_BIN, 'sh' => SYSTEM_BIN, 'su' => SYSTEM_BIN, 'tar' => SYSTEM_BIN, 'true' => SYSTEM_BIN, 'umount' => SYSTEM_BIN, 'unlink' => SYSTEM_BIN, 'zcat' => SYSTEM_BIN, 'rsyslogd' => SYSTEM_SBIN, 'ip6tables' => SYSTEM_SBIN, 'ifconfig' => SYSTEM_SBIN, 'quotaoff' => SYSTEM_SBIN, 'losetup' => SYSTEM_SBIN, 'quotacheck' => SYSTEM_SBIN, 'ip' => SYSTEM_SBIN, 'quotaon' => SYSTEM_SBIN, 'iptables' => SYSTEM_SBIN, 'service' => SYSTEM_SBIN, 'cagefsctl' => SYSTEM_SBIN, }; } sub dynamic_bin_location { my $binary = shift or die 'dynamic_bin_location($binary)'; my %table = Cpanel::OS::binary_locations()->%*; return $table{$binary}; } sub thirdparty_binary_locations { return { %{ _get_thirdparty_binary_locations_static() }, %{ _get_thirdparty_binary_locations_dynamic() }, }; } our %dynamic_vars = ( 'pear' => 1, 'peardev' => 1, 'pecl' => 1, 'phar' => 1, 'php' => 1, 'php-cgi' => 1, 'php-config' => 1, 'phpize' => 1, ); our $cached_cleanup; # Don't do these checks more than once. sub _remove_server_type_specific_binaries { return if $cached_cleanup; return $cached_cleanup = 1; } sub _get_thirdparty_binary_location { my ($binary) = @_; _remove_server_type_specific_binaries(); return ( exists( $dynamic_vars{$binary} ) ) ? _get_thirdparty_binary_locations_dynamic()->{$binary} : _get_thirdparty_binary_locations_static()->{$binary}; } my $php_dir; sub _get_thirdparty_binary_locations_dynamic { if ( !defined($php_dir) ) { $php_dir = Cpanel::Binaries::get_php_3rdparty_dir() . "bin"; } _remove_server_type_specific_binaries(); return { map { $_ => $php_dir } keys(%dynamic_vars) }; } sub _get_thirdparty_binary_locations_static { return { 'spamd' => CPANEL_PERL_BIN, 'spamc' => CPANEL_PERL_BIN, 'spamassassin' => CPANEL_PERL_BIN, 'sa-compile' => CPANEL_PERL_BIN, 'sa-learn' => CPANEL_PERL_BIN, 'sa-update' => CPANEL_PERL_BIN, 'clamd' => THIRD_PARTY_BIN, 'clamdscan' => THIRD_PARTY_BIN, 'freshclam' => THIRD_PARTY_BIN, 'puttygen' => THIRD_PARTY_BIN, 're2c' => THIRD_PARTY_BIN, 'perl' => CPANEL_PERL_BIN, 'perlcc' => CPANEL_PERL_BIN, 'mysqldiff' => CPANEL_PERL_BIN, 'munin-cron' => CPANEL_PERL_BIN, 'munin-node' => CPANEL_PERL_SBIN, 'munin-node-configure' => CPANEL_PERL_SBIN, 'psql' => THIRD_PARTY_BIN, 'pg_dump' => THIRD_PARTY_BIN, 'pg_restore' => THIRD_PARTY_BIN, 'git' => THIRD_PARTY_BIN, 'git-receive-pack' => THIRD_PARTY_BIN, 'git-shell' => THIRD_PARTY_BIN, 'git-upload-archive' => THIRD_PARTY_BIN, 'git-upload-pack' => THIRD_PARTY_BIN, 'wp-toolkit' => LOCAL_BIN, 'imunify360-agent' => SYSTEM_BIN, @_OVERRIDES, }; } sub thirdparty_binary_names { return {}; } sub LOG { my ($msg) = @_; return unless $VERBOSE && defined $msg; print "$msg\n"; return; } sub optional_binaries { return qw/munin-cron munin-node munin-node-configure perlcc/; } sub path { my $binary = shift or return; if ( my $path = _get_thirdparty_binary_location($binary) ) { return $path . '/' . $binary; } my $bin_hash = system_bin_locations(); if ( $bin_hash->{$binary} ) { return $bin_hash->{$binary} . '/' . $binary; } if ( my $dynamic_location = dynamic_bin_location($binary) ) { return $dynamic_location . '/' . $binary; } require Carp; Carp::confess("Unknown binary: '$binary'; possible typo?"); } sub get_prefix { my $binary = shift or return; my $binloc = _get_thirdparty_binary_location($binary); return unless $binloc; $binloc =~ s{/bin$}{}; return $binloc; } sub get_php_version { my %args = @_; my $target_ver = _get_php_ver_only_for_testing('MAJOR'); if ( !-x CPANEL_PHP_BIN . "/php" ) { $target_ver = _get_php_ver_only_for_testing('LEGACY'); } return $target_ver if $args{flat}; return join '.', split( '', $target_ver, 2 ); } sub _get_php_ver_only_for_testing { return $_[0] eq 'MAJOR' ? PHP_MAJOR : PHP_LEGACY_MAJOR; } sub get_php_3rdparty_dir { my $ver = Cpanel::Binaries::get_php_version( 'flat' => 1 ); return THIRD_PARTY . "/php/$ver/"; } sub symlink_into_3rdparty_bin { my $bin_loc_hash = thirdparty_binary_locations(); my $optional = { map { $_ => 1 } optional_binaries() }; my $third_bin = THIRD_PARTY_BIN; my $ok = 1; foreach my $binary ( keys %$bin_loc_hash ) { next if ( $bin_loc_hash->{$binary} eq $third_bin ); next if ( $bin_loc_hash->{$binary} eq SYSTEM_BIN ); my $third_bin_names = thirdparty_binary_names(); my $real_binary = $third_bin_names->{$binary}; $real_binary ||= $binary; my $real_location = $bin_loc_hash->{$binary} . '/' . $real_binary; if ( !-e $real_location ) { LOG("WARNING: Unexpectedly missing $binary") unless $optional->{$binary}; next; } my $third_bin_loc = "$third_bin/$binary"; if ( -e $third_bin_loc || -l $third_bin_loc ) { my $points_to = readlink($third_bin_loc); next if ( $points_to && $points_to eq $real_location ); LOG( "Removing $third_bin_loc, which " . ( $points_to ? "unexpectedly pointed to $points_to" : "was not a symlink" ) ); unlink $third_bin_loc; } LOG("Linking $third_bin_loc -> $real_location"); $ok = 0 unless symlink( $real_location, $third_bin_loc ); } return $ok; } sub binaries_to_symlink_into_system_bin { return [qw/git git-receive-pack git-shell git-upload-archive git-upload-pack/]; } sub symlink_thirdparty_into_system_bin { my $ok = 1; my $to_link_ref = binaries_to_symlink_into_system_bin(); my $bin_loc_hash = thirdparty_binary_locations(); foreach my $binary (@$to_link_ref) { my $third_bin_loc = SYSTEM_BIN . qq{/$binary}; my $real_location = $bin_loc_hash->{$binary} . '/' . $binary; if ( !-e $third_bin_loc && -x $real_location ) { LOG("Linking $third_bin_loc -> $real_location"); $ok = 0 unless symlink( $real_location, $third_bin_loc ); } } return $ok; } 1; } # --- END Cpanel/Binaries.pm { # --- BEGIN Cpanel/Crypt/GPG/Base.pm package Cpanel::Crypt::GPG::Base; use strict; use warnings; no warnings 'once'; # use Cpanel::Binaries (); # perlpkg line 211 # use Cpanel::Exception (); # perlpkg line 211 sub new { my ( $class, $opts_hr ) = @_; $opts_hr = {} if !( $opts_hr && 'HASH' eq ref $opts_hr ); my $bin = _find_gpg_or_die(); my $obj = { 'bin' => $bin, %{$opts_hr}, }; return bless $obj, $class; } sub get_gpg_bin { my $self = shift; return $self->{bin}; } sub _find_gpg_or_die { my $bin = Cpanel::Binaries::path('gpg'); -x $bin or die Cpanel::Exception::create( 'Unsupported', 'Only servers with [asis,GPG] support this module.' ); return $bin; } 1; } # --- END Cpanel/Crypt/GPG/Base.pm { # --- BEGIN Cpanel/Env.pm package Cpanel::Env; use strict; use warnings; no warnings 'once'; our $VERSION = '1.7'; my $SAFE_ENV_VARS; BEGIN { $SAFE_ENV_VARS = q< ALLUSERSPROFILE APPDATA BUNDLE_PATH CLIENTNAME COMMONPROGRAMFILES COMPUTERNAME COMSPEC CPANEL_BASE_INSTALL CPANEL_IS_CRON CPANEL_RPM_LOCKED_IN_PARENT CPBACKUP DEBIAN_FRONTEND DEBIAN_PRIORITY DOCUMENT_ROOT FORCEDCPUPDATE FP_NO_HOST_CHECK HOMEDRIVE HOMEPATH LANG LANGUAGE LC_ALL LC_MESSAGES LC_CTYPE LOGONSERVER NEWWHMUPDATE NOTIFY_SOCKET NUMBER_OF_PROCESSORS OPENSSL_NO_DEFAULT_ZLIB OS PATH PATHEXT PROCESSOR_ARCHITECTURE PROCESSOR_IDENTIFIER PROCESSOR_LEVEL PROCESSOR_REVISION PROGRAMFILES PROMPT PYTHONIOENCODING SERVER_SOFTWARE SESSIONNAME SKIP_DEFERRAL_CHECK SSH_CLIENT SYSTEMDRIVE SYSTEMROOT TEMP TERM TMP UPDATENOW_NO_RETRY UPDATENOW_PRESERVE_FAILED_FILES USERDOMAIN USERNAME USERPROFILE WINDIR >; $SAFE_ENV_VARS =~ tr<\n >< >s; $SAFE_ENV_VARS =~ s<\A\s+><>; } { no warnings 'once'; *cleanenv = *clean_env; } sub clean_env { my %OPTS = @_; my %SAFE_ENV_VARS = map { $_ => undef } split( m{ }, $SAFE_ENV_VARS ); if ( defined $OPTS{'keep'} && ref $OPTS{'keep'} eq 'ARRAY' ) { @SAFE_ENV_VARS{ @{ $OPTS{'keep'} } } = undef; } if ( defined $OPTS{'delete'} && ref $OPTS{'delete'} eq 'ARRAY' ) { delete @SAFE_ENV_VARS{ @{ $OPTS{'delete'} } }; } delete @ENV{ grep { !exists $SAFE_ENV_VARS{$_} } keys %ENV }; if ( $OPTS{'http_purge'} ) { delete @ENV{ 'SERVER_SOFTWARE', 'DOCUMENT_ROOT' }; } return; } sub get_safe_env_vars { return $SAFE_ENV_VARS; } sub get_safe_path { return '/usr/local/jdk/bin:/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/usr/local/bin:/usr/X11R6/bin:/root/bin:/opt/bin'; } sub set_safe_path { return ( $ENV{'PATH'} = get_safe_path() ); } 1; } # --- END Cpanel/Env.pm { # --- BEGIN Cpanel/FHUtils/OS.pm package Cpanel::FHUtils::OS; use strict; use warnings; no warnings 'once'; my $fileno; sub is_os_filehandle { local $@; $fileno = eval { fileno $_[0] }; return ( defined $fileno ) && ( $fileno != -1 ); } 1; } # --- END Cpanel/FHUtils/OS.pm { # --- BEGIN Cpanel/FHUtils/Blocking.pm package Cpanel::FHUtils::Blocking; use strict; use warnings; no warnings 'once'; # use Cpanel::Fcntl::Constants (); # perlpkg line 211 # use Cpanel::Autodie qw(fcntl); # perlpkg line 248 INIT { Cpanel::Autodie->import(qw{fcntl}); } sub set_non_blocking { return Cpanel::Autodie::fcntl( $_[0], $Cpanel::Fcntl::Constants::F_SETFL, _get_fl_flags( $_[0] ) | $Cpanel::Fcntl::Constants::O_NONBLOCK ) && 1; } sub set_blocking { return Cpanel::Autodie::fcntl( $_[0], $Cpanel::Fcntl::Constants::F_SETFL, _get_fl_flags( $_[0] ) & ~$Cpanel::Fcntl::Constants::O_NONBLOCK ) && 1; } sub is_set_to_block { return !( _get_fl_flags( $_[0] ) & $Cpanel::Fcntl::Constants::O_NONBLOCK ) ? 1 : 0; } sub _get_fl_flags { return int Cpanel::Autodie::fcntl( $_[0], $Cpanel::Fcntl::Constants::F_GETFL, 0 ); } 1; } # --- END Cpanel/FHUtils/Blocking.pm { # --- BEGIN Cpanel/IO/Flush.pm package Cpanel::IO::Flush; use strict; use warnings; no warnings 'once'; use constant { _EAGAIN => 11, _EINTR => 4, }; # use Cpanel::Exception (); # perlpkg line 211 use IO::SigGuard (); sub write_all { ##no critic qw( RequireArgUnpacking ) my ( $fh, $timeout ) = @_; # $_[2] = payload local ( $!, $^E ); my $offset = 0; { my $this_time = IO::SigGuard::syswrite( $fh, $_[2], length( $_[2] ), $offset ); if ($this_time) { $offset += $this_time; } elsif ( $! == _EAGAIN() ) { _wait_until_ready( $fh, $timeout ); } else { die Cpanel::Exception::create( 'IO::WriteError', [ error => $!, length => length( $_[2] ) - $offset ] ); } redo if $offset < length( $_[2] ); } return; } sub _wait_until_ready { my ( $fh, $timeout ) = @_; my $win; vec( $win, fileno($fh), 1 ) = 1; my $ready = select( undef, my $wout = $win, undef, $timeout ); if ( $ready == -1 ) { redo if $! == _EINTR(); die Cpanel::Exception::create( 'IO::SelectError', [ error => $! ] ); } elsif ( !$ready ) { die Cpanel::Exception::create_raw( 'Timeout', 'write timeout!' ); } return; } 1; } # --- END Cpanel/IO/Flush.pm { # --- BEGIN Cpanel/ReadMultipleFH.pm package Cpanel::ReadMultipleFH; use strict; use warnings; no warnings 'once'; # use Cpanel::FHUtils::Blocking (); # perlpkg line 211 # use Cpanel::FHUtils::OS (); # perlpkg line 211 # use Cpanel::IO::Flush (); # perlpkg line 211 # use Cpanel::LoadFile::ReadFast (); # perlpkg line 211 my $CHUNK_SIZE = 2 << 16; my $DEFAULT_TIMEOUT = 600; #10 minutes my $DEFAULT_READ_TIMEOUT = 0; sub new { ## no critic qw(Subroutines::ProhibitExcessComplexity) my ( $class, %opts ) = @_; my %fh_buffer; my %output; my @fhs = @{ $opts{'filehandles'} }; my $read_input = ''; my $read_output = ''; my %fhmap; my %is_os_filehandle; for my $fh_buf_ar (@fhs) { if ( UNIVERSAL::isa( $fh_buf_ar, 'GLOB' ) ) { $fh_buf_ar = [$fh_buf_ar]; } elsif ( !UNIVERSAL::isa( $fh_buf_ar, 'ARRAY' ) ) { die 'items in “filehandles” must be either a filehandle or ARRAY'; } my $fh = $fh_buf_ar->[0]; Cpanel::FHUtils::Blocking::set_non_blocking($fh); $fhmap{ fileno($fh) } = $fh; vec( $read_input, fileno($fh), 1 ) = 1; if ( defined $fh_buf_ar->[1] && UNIVERSAL::isa( $fh_buf_ar->[1], 'SCALAR' ) ) { $fh_buffer{$fh} = $fh_buf_ar->[1]; } else { my $buf = q{}; $fh_buffer{$fh} = \$buf; if ( defined $fh_buf_ar->[1] && UNIVERSAL::isa( $fh_buf_ar->[1], 'GLOB' ) ) { $output{$fh} = $fh_buf_ar->[1]; $is_os_filehandle{$fh} = Cpanel::FHUtils::OS::is_os_filehandle( $fh_buf_ar->[1] ); } elsif ( defined $fh_buf_ar->[1] ) { die '2nd value in “filehandles” array member must be undef, SCALAR, or GLOB!'; } } } my $finished; my $self = { _fh_buffer => \%fh_buffer, _finished => 0, }; bless $self, $class; my ( $nfound, $select_time_left, $select_timeout ); my $overall_timeout = defined $opts{'timeout'} ? $opts{'timeout'} : $DEFAULT_TIMEOUT; my $read_timeout = defined $opts{'read_timeout'} ? $opts{'read_timeout'} : $DEFAULT_READ_TIMEOUT; my $has_overall_timeout = $overall_timeout ? 1 : 0; my $overall_time_left = $overall_timeout || undef; READ_LOOP: while ( !$finished && # has not finished ( !$has_overall_timeout || $overall_time_left > 0 ) # has not reached overall timeout ) { $select_timeout = _get_shortest_timeout( $overall_time_left, $read_timeout ); ( $nfound, $select_time_left ) = select( $read_output = $read_input, undef, undef, $select_timeout ); if ( !$nfound ) { $self->{'_timed_out'} = ( $select_timeout == $read_timeout ) ? $read_timeout : $overall_timeout; last; } elsif ( $nfound != -1 ) { # case 47309: If we get -1 it probably means we got interrupted by a signal for my $fileno ( grep { vec( $read_output, $_, 1 ) } keys %fhmap ) { my $fh = $fhmap{$fileno}; Cpanel::LoadFile::ReadFast::read_fast( $fh, ${ $fh_buffer{$fh} }, $CHUNK_SIZE, length ${ $fh_buffer{$fh} } ) or do { delete $fhmap{$fileno}; $finished = !( scalar keys %fhmap ); last READ_LOOP if $finished; vec( $read_input, $fileno, 1 ) = 0; next; }; if ( $output{$fh} ) { my $payload_sr = \substr( ${ $fh_buffer{$fh} }, 0, length ${ $fh_buffer{$fh} }, q<> ); if ( $is_os_filehandle{$fh} ) { Cpanel::IO::Flush::write_all( $output{$fh}, $read_timeout, $$payload_sr ); } else { print { $output{$fh} } $$payload_sr; } } } } $overall_time_left -= ( $select_timeout - $select_time_left ) if $has_overall_timeout; } delete $fh_buffer{$_} for keys %output; %fhmap = (); $self->{'_finished'} = $finished; if ( !$finished && defined $overall_time_left && $overall_time_left <= 0 ) { $self->{'_timed_out'} = $overall_timeout; } return $self; } sub _get_shortest_timeout { my ( $overall_time_left, $read_timeout ) = @_; return undef if ( !$overall_time_left && !$read_timeout ); return $read_timeout if !defined $overall_time_left; return ( !$read_timeout || $overall_time_left <= $read_timeout ) ? $overall_time_left : $read_timeout; } sub get_buffer { return $_[0]->{'_fh_buffer'}{ $_[1] }; } sub did_finish { return $_[0]->{'_finished'} ? 1 : 0; } sub timed_out { return defined $_[0]->{'_timed_out'} ? $_[0]->{'_timed_out'} : 0; } 1; } # --- END Cpanel/ReadMultipleFH.pm { # --- BEGIN Cpanel/ForkAsync.pm package Cpanel::ForkAsync; use strict; use warnings; no warnings 'once'; # use Cpanel::Exception (); # perlpkg line 211 my $DEFAULT_ERROR_CODE = 127; #EKEYEXPIRED our $quiet = 0; our $no_warn = 0; sub do_in_child { my ( $code, @args ) = @_; local ( $!, $^E ); my $pid = fork(); die Cpanel::Exception::create( 'IO::ForkError', [ error => $! ] ) if !defined $pid; if ( !$pid ) { local $@; if ( !eval { $code->(@args); 1 } ) { my $err = $@; my $io_err = 0 + $!; _print($err) unless $quiet; exit( $io_err || $DEFAULT_ERROR_CODE ); } exit 0; } return $pid; } sub do_in_child_quiet { my ( $code, @args ) = @_; local $quiet = 1; return do_in_child( $code, @args ); } sub _print { my ($msg) = @_; warn $msg unless $no_warn; print STDERR $msg; return; } 1; } # --- END Cpanel/ForkAsync.pm { # --- BEGIN Cpanel/SafeRun/Object.pm package Cpanel::SafeRun::Object; use cPstrict; no warnings 'once'; # use parent Cpanel::ChildErrorStringifier (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::ChildErrorStringifier); } BEGIN { eval { require Proc::FastSpawn; }; } use IO::SigGuard (); # use Cpanel::Env (); # perlpkg line 211 # use Cpanel::Exception (); # perlpkg line 211 # use Cpanel::FHUtils::Autoflush (); # perlpkg line 211 # use Cpanel::FHUtils::OS (); # perlpkg line 211 # use Cpanel::ReadMultipleFH (); # perlpkg line 211 # use Cpanel::LoadModule (); # perlpkg line 211 # use Cpanel::LocaleString (); # perlpkg line 211 use constant _ENOENT => 2; my $CHUNK_SIZE = 2 << 16; my $DEFAULT_TIMEOUT = 3600; # 1 hour my $DEFAULT_READ_TIMEOUT = 0; our $SAFEKILL_TIMEOUT = 1; my @_allowed_env_vars_cache; sub new { ## no critic qw(Subroutines::ProhibitExcessComplexity) my ( $class, %OPTS ) = @_; die "No “program”!" if !length $OPTS{'program'}; if ( !defined $OPTS{'timeout'} ) { $OPTS{'timeout'} = $DEFAULT_TIMEOUT; } if ( !defined $OPTS{'read_timeout'} ) { $OPTS{'read_timeout'} = $DEFAULT_READ_TIMEOUT; } if ( $OPTS{'program'} =~ tr{><*?[]`$()|;$\\\r\n\t }{} && !-e $OPTS{'program'} ) { die Cpanel::Exception::create( 'InvalidParameter', 'A value of “[_1]” is invalid for “[_2]” as it does not permit the following characters: “[_3]”', [ $OPTS{'program'}, 'program', '><*?[]`$()|;$\\\\\r\\n\\t' ] ); } my $args_ar = $OPTS{'args'} || []; die "“args” must be an arrayref" if defined $args_ar && ref $args_ar ne 'ARRAY'; die Cpanel::Exception::create( 'InvalidParameter', 'The “[_1]” argument is invalid.', ['logger'] ) if $OPTS{'logger'}; die "Undefined value given as argument! (@$args_ar)" if grep { !defined } @$args_ar; my $pump_stdin_filehandle_into_child; my ( %parent_read_fh, %child_write_fh ); my $merge_output_yn = $OPTS{'stdout'} && $OPTS{'stderr'} && ( $OPTS{'stdout'} eq $OPTS{'stderr'} ); local $!; for my $handle_name (qw(stdout stderr)) { my $custom_fh = $OPTS{$handle_name} && UNIVERSAL::isa( $OPTS{$handle_name}, 'GLOB' ) && $OPTS{$handle_name}; my $dupe_filehandle_will_work = $custom_fh && !tied(*$custom_fh) && ( fileno($custom_fh) > -1 ); if ( !$custom_fh && $OPTS{$handle_name} ) { die "“$handle_name” must be a filehandle or undef, not $OPTS{$handle_name}"; } if ($dupe_filehandle_will_work) { if ( fileno($custom_fh) < 3 ) { open my $copy, '>&', $custom_fh or die "dup($handle_name): $!"; $child_write_fh{$handle_name} = $copy; } else { $child_write_fh{$handle_name} = $custom_fh; } } elsif ( $merge_output_yn && $handle_name eq 'stderr' ) { $parent_read_fh{'stderr'} = $parent_read_fh{'stdout'}; $child_write_fh{'stderr'} = $child_write_fh{'stdout'}; } else { pipe $parent_read_fh{$handle_name}, $child_write_fh{$handle_name} # or die "pipe() failed: $!"; } } my ( $child_reads, $parent_writes ); my $close_child_reads = 0; if ( !defined $OPTS{'stdin'} || !length $OPTS{'stdin'} ) { open $child_reads, '<', '/dev/null' or die "open(<, /dev/null) failed: $!"; $close_child_reads = 1; } elsif ( UNIVERSAL::isa( $OPTS{'stdin'}, 'GLOB' ) ) { my $fileno = fileno $OPTS{'stdin'}; if ( !defined $fileno || $fileno == -1 ) { $pump_stdin_filehandle_into_child = 1; } else { $child_reads = $OPTS{'stdin'}; } } if ( !$child_reads ) { $close_child_reads = 1; pipe( $child_reads, $parent_writes ) or die "pipe() failed: $!"; } my $self = bless { _program => $OPTS{'program'}, _args => $OPTS{'args'} || [], }, $class; local $SIG{'CHLD'} = 'DEFAULT'; my $exec_failed_message = "exec($OPTS{'program'}) failed:"; my $used_fastspawn = 0; if ( $INC{'Proc/FastSpawn.pm'} # may not be available yet due to upcp.static or updatenow.static && !$OPTS{'before_exec'} && !$Cpanel::AccessIds::ReducedPrivileges::PRIVS_REDUCED # PPI NO PARSE - We not ever be set if its not loaded ) { $used_fastspawn = 1; my @env; if ( !$OPTS{'keep_env'} ) { if ( !@_allowed_env_vars_cache ) { @_allowed_env_vars_cache = ( split( m{ }, Cpanel::Env::get_safe_env_vars() ) ); } @env = map { exists $ENV{$_} ? ( $_ . '=' . ( $ENV{$_} // '' ) ) : () } @_allowed_env_vars_cache; } my $user = $OPTS{'user'}; my $homedir = $OPTS{'homedir'}; if ( !$user || !$homedir ) { my ( $pw_user, $pw_homedir ) = ( getpwuid $> )[ 0, 7 ]; $user ||= $pw_user; $homedir ||= $pw_homedir; } die "Invalid EUID: $>" if !$user || !$homedir; push @env, "HOME=$homedir", "USER=$user"; # need to always be set since we start clean and don't have before_exec push @env, "TMP=$homedir/tmp", "TEMP=$homedir/tmp" if !defined $ENV{'TMP'}; $self->{'_child_pid'} = Proc::FastSpawn::spawn_open3( fileno($child_reads), # stdin defined $child_write_fh{'stdout'} ? fileno( $child_write_fh{'stdout'} ) : -1, # stdout defined $child_write_fh{'stderr'} ? fileno( $child_write_fh{'stderr'} ) : -1, # stderr $OPTS{'program'}, # program [ $OPTS{'program'}, @$args_ar ], # args $OPTS{'keep_env'} ? () : \@env # env ); if ( !$self->{_child_pid} ) { $self->{'_CHILD_ERROR'} = $! << 8; $self->{'_exec_failed'} = 1; ${ $self->{'_stdout'} } = ''; ${ $self->{'_stderr'} } .= "$exec_failed_message $!"; } } else { require Cpanel::ForkAsync; $self->{'_child_pid'} = Cpanel::ForkAsync::do_in_child( sub { $SIG{'__DIE__'} = 'DEFAULT'; ## no critic qw(Variables::RequireLocalizedPunctuationVars) -- will never be unset if ( $parent_read_fh{'stdout'} ) { close $parent_read_fh{'stdout'} or die "child close parent stdout failed: $!"; } if ( $parent_read_fh{'stderr'} && !$merge_output_yn ) { close $parent_read_fh{'stderr'} or die "child close parent stderr failed: $!"; } if ($parent_writes) { close $parent_writes or die "close() failed: $!"; } open( *STDIN, '<&=' . fileno $child_reads ) or die "open(STDIN) failed: $!"; ##no critic qw(ProhibitTwoArgOpen) my $fileno_stdout = fileno \*STDOUT; if ( $fileno_stdout != fileno( $child_write_fh{'stdout'} ) ) { if ( $fileno_stdout != 1 ) { close *STDOUT or die "close(STDOUT) failed: $!"; open( *STDOUT, '>>&=1' ) or die "open(STDOUT, '>>&=1') failed: $!"; ##no critic qw(ProhibitTwoArgOpen) } open( *STDOUT, '>>&=' . fileno $child_write_fh{'stdout'} ) or die "open(STDOUT) failed: $!"; ##no critic qw(ProhibitTwoArgOpen) } my $fileno_stderr = fileno \*STDERR; if ( $fileno_stderr != fileno( $child_write_fh{'stderr'} ) ) { if ( $fileno_stderr != 2 ) { close *STDERR or die "close(STDOUT) failed: $!"; open( *STDERR, '>>&=2' ) or die "open(STDERR, '>>&=2') failed: $!"; ##no critic qw(ProhibitTwoArgOpen) } open( *STDERR, '>>&=' . fileno $child_write_fh{'stderr'} ) or die "open(STDERR) failed: $!"; ##no critic qw(ProhibitTwoArgOpen) } if ( !$OPTS{'keep_env'} ) { Cpanel::Env::clean_env(); } if ($Cpanel::AccessIds::ReducedPrivileges::PRIVS_REDUCED) { # PPI NO PARSE -- can't be reduced if the module isn't loaded my $target_euid = "$>"; my $target_egid = ( split( m{ }, "$)" ) )[0]; Cpanel::AccessIds::ReducedPrivileges::_restore_privileges( 0, 0 ); # PPI NO PARSE -- we will never get here if ReducedPrivileges wasn't loaded Cpanel::LoadModule::load_perl_module('Cpanel::Sys::Setsid::Fast') if !$INC{'Cpanel/Sys/Setsid/Fast.pm'}; Cpanel::Sys::Setsid::Fast::fast_setsid(); Cpanel::LoadModule::load_perl_module('Cpanel::AccessIds::SetUids') if !$INC{'Cpanel/AccessIds/SetUids.pm'}; Cpanel::AccessIds::SetUids::setuids( $target_euid, $target_egid ); } if ( $OPTS{'before_exec'} ) { $OPTS{'before_exec'}->(); } my $user = $OPTS{'user'}; my $homedir = $OPTS{'homedir'}; if ( !$user || !$homedir ) { Cpanel::LoadModule::load_perl_module('Cpanel::PwCache') if !$INC{'Cpanel/PwCache.pm'}; my ( $pw_user, $pw_homedir ) = ( Cpanel::PwCache::getpwuid_noshadow($>) )[ 0, 7 ]; $user ||= $pw_user; $homedir ||= $pw_homedir; } die "Invalid EUID: $>" if !$user || !$homedir; $ENV{'HOME'} = $homedir if !defined $ENV{'HOME'}; # always cleared by clean_env, but may be reset in before_exec $ENV{'USER'} = $user if !defined $ENV{'USER'}; # always cleared by clean_env, but may be reset in before_exec $ENV{'TMP'} = "$homedir/tmp" if !defined $ENV{'TMP'}; $ENV{'TEMP'} = "$homedir/tmp" if !defined $ENV{'TEMP'}; exec( $OPTS{'program'}, @$args_ar ) or die "$exec_failed_message $!"; } ); } if ( $OPTS{'after_fork'} ) { $OPTS{'after_fork'}->( $self->{'_child_pid'} ); } if ($close_child_reads) { #only close it if we opened it close $child_reads or die "close() failed: $!"; } if ( $parent_read_fh{'stdout'} ) { close $child_write_fh{'stdout'} or die "close() failed: $!"; } if ( !$merge_output_yn && $parent_read_fh{'stderr'} ) { close $child_write_fh{'stderr'} or die "close() failed: $!"; } if ($parent_writes) { if ( ref $OPTS{'stdin'} eq 'CODE' ) { $OPTS{'stdin'}->($parent_writes); } else { local $SIG{'PIPE'} = 'IGNORE'; Cpanel::FHUtils::Autoflush::enable($parent_writes); if ($pump_stdin_filehandle_into_child) { my $buffer; my $is_os_stdin = Cpanel::FHUtils::OS::is_os_filehandle( $OPTS{'stdin'} ); local $!; if ($is_os_stdin) { while ( IO::SigGuard::sysread( $OPTS{'stdin'}, $buffer, $CHUNK_SIZE ) ) { $self->_write_buffer_to_fh( $buffer, $parent_writes ); } } else { while ( read $OPTS{'stdin'}, $buffer, $CHUNK_SIZE ) { $self->_write_buffer_to_fh( $buffer, $parent_writes ); } } if ($!) { die Cpanel::Exception::create( 'IO::ReadError', 'The system failed to read up to [format_bytes,_1] from the filehandle that contains standard input for the process that is running the command “[_2]”. This failure happened because of an error: [_3]', [ $CHUNK_SIZE, "$OPTS{'program'} @$args_ar", "$!" ] ); } } else { my $to_print_r = ( ref $OPTS{'stdin'} eq 'SCALAR' ) ? $OPTS{'stdin'} : \$OPTS{'stdin'}; if ( length $$to_print_r ) { $self->_write_buffer_to_fh( $$to_print_r, $parent_writes ); } } } close $parent_writes or warn "close() failed: $!"; } my $reader; my $err_obj; my @filehandles = map { $parent_read_fh{$_} ? [ $parent_read_fh{$_}, $OPTS{$_} ] : () } qw( stdout stderr ); if (@filehandles) { local $@; eval { $reader = Cpanel::ReadMultipleFH->new( filehandles => \@filehandles, timeout => $OPTS{'timeout'}, read_timeout => $OPTS{'read_timeout'}, ); }; $err_obj = $@; } if ( $parent_read_fh{'stdout'} ) { close $parent_read_fh{'stdout'} or warn "parent close(stdout) failed: $!"; } if ( $parent_read_fh{'stderr'} && !$merge_output_yn ) { close $parent_read_fh{'stderr'} or warn "parent close(stderr) failed: $!"; } if ($err_obj) { $self->{'_CHILD_ERROR'} = $self->_safe_kill_child(); die $err_obj; } elsif ($reader) { if ( !$reader->did_finish() ) { $self->{'_timed_out_after'} = $reader->timed_out(); $self->{'_CHILD_ERROR'} = $self->_safe_kill_child(); } $self->{"_stdout"} = $parent_read_fh{stdout} && $reader->get_buffer( $parent_read_fh{stdout} ); if ( !$self->{"_stderr"} ) { $self->{"_stderr"} = $parent_read_fh{stderr} && $reader->get_buffer( $parent_read_fh{stderr} ); } } if ( !defined $self->{'_CHILD_ERROR'} ) { local $?; waitpid( $self->{'_child_pid'}, 0 ) if defined $self->{'_child_pid'}; $self->{'_CHILD_ERROR'} = $?; if ( $self->{'_CHILD_ERROR'} ) { $self->{'_exec_failed'} = 1; } } if ( $used_fastspawn && $self->{'_CHILD_ERROR'} == 32512 ) { $self->{'_CHILD_ERROR'} = _ENOENT() << 8; $self->{'_exec_failed'} = 1; ${ $self->{'_stderr'} } .= "$exec_failed_message $!"; } elsif ( !$used_fastspawn && $self->{'_stderr'} && $self->{'_CHILD_ERROR'} && ( $self->{'_CHILD_ERROR'} >> 8 ) == 2 && index( ${ $self->{'_stderr'} }, $exec_failed_message ) > -1 ) { $self->{'_exec_failed'} = 1; } return $self; } sub _write_buffer_to_fh ( $self, $buffer, $fh ) { while ( length $buffer ) { my $wrote = IO::SigGuard::syswrite( $fh, $buffer ) or die $self->_write_error( \$buffer, $! ); substr( $buffer, 0, $wrote, q<> ); } return; } sub new_or_die { my ( $class, @args ) = @_; return $class->new(@args)->die_if_error(); } sub to_exception { my ($self) = @_; if ( $self->timed_out() ) { return Cpanel::Exception::create( 'ProcessFailed::Timeout', [ process_name => $self->program(), ( $self->child_pid() ? ( pid => $self->child_pid() ) : () ), timeout => $self->timed_out(), $self->_extra_error_args_for_die_if_error(), ], ); } return $self->SUPER::to_exception(); } sub _extra_error_args_for_die_if_error { my ($self) = @_; return ( stdout => $self->{'_stdout'} ? $self->stdout() : '', stderr => $self->{'_stderr'} ? $self->stderr() : '', ); } sub _safe_kill_child { my ($self) = @_; Cpanel::LoadModule::load_perl_module('Cpanel::Kill::Single'); return 'Cpanel::Kill::Single'->can('safekill_single_pid')->( $self->{'_child_pid'}, $SAFEKILL_TIMEOUT ); # One second to die } sub stdout_r { if ( !$_[0]->{'_stdout'} ) { Cpanel::LoadModule::load_perl_module('Cpanel::Carp'); die 'Cpanel::Carp'->can('safe_longmess')->("STDOUT output went to filehandle!"); } return $_[0]->{'_stdout'}; } sub _additional_phrases_for_autopsy { if ( $_[0]->timed_out() ) { return Cpanel::LocaleString->new( 'The system aborted the subprocess because it reached the timeout of [quant,_1,second,seconds].', $_[0]->timed_out() ); } return; } sub stdout { return ${ $_[0]->stdout_r() }; } sub stderr_r { if ( !$_[0]->{'_stderr'} ) { Cpanel::LoadModule::load_perl_module('Cpanel::Carp'); die 'Cpanel::Carp'->can('safe_longmess')->("STDERR output went to filehandle!"); } return $_[0]->{'_stderr'}; } sub stderr { return ${ $_[0]->stderr_r() }; } sub child_pid { return $_[0]->{'_child_pid'}; } sub timed_out { return $_[0]->{'_timed_out_after'}; } sub program { return $_[0]->{'_program'}; } sub _program_with_args_str { my $args_ar = $_[0]->{'_args'}; return $_[0]->{'_program'} . ( ( $args_ar && ref $args_ar && scalar @$args_ar ) ? " @$args_ar" : '' ); } sub _ERROR_PHRASE { my ($self) = @_; return Cpanel::LocaleString->new( 'The “[_1]” command (process [_2]) reported error number [_3] when it ended.', $self->_program_with_args_str(), $self->{'_child_pid'}, $self->error_code() ); } sub _SIGNAL_PHRASE { my ($self) = @_; return Cpanel::LocaleString->new( 'The “[_1]” command (process [_2]) ended prematurely because it received the “[_3]” ([_4]) signal.', $self->_program_with_args_str(), $self->{'_child_pid'}, $self->signal_name(), $self->signal_code() ); } sub _write_error { my ( $self, $buffer_sr, $OS_ERROR ) = @_; my @cmd = ( $self->{'_program'}, @{ $self->{'_args'} } ); return Cpanel::Exception::create( 'IO::WriteError', 'The system failed to send [format_bytes,_1] to the process that is running the command “[_2]” because of an error: [_3]', [ length($$buffer_sr), "@cmd", $OS_ERROR ], { length => length($$buffer_sr), error => $OS_ERROR } ); } 1; } # --- END Cpanel/SafeRun/Object.pm { # --- BEGIN Cpanel/Rand/Get.pm package Cpanel::Rand::Get; use strict; # use Cpanel::FHUtils::Blocking (); # perlpkg line 211 # use Cpanel::FHUtils::Tiny (); # perlpkg line 211 our $random_source = '/dev/urandom'; our %entropy_pool; our $getrandom_syscall_is_usable; my $last_entropy_pool_owner = $$; my %TR_CODE_CACHE_NUM_ACCEPTABLE; my %TR_CODE_CACHE_BAD_CHARS; my $DEFAULT_LENGTH = 10; my @DEFAULT_CHARACTERS = ( 0 .. 9, 'A' .. 'Z', 'a' .. 'z', '_', ); my $_default_want_chars_string; # a cache my $DEFAULT_PRELOAD_16TH = 200; my $MAX_READ_ATTEMPTS = 50; my $NUMBER_OF_ASCII_CHARS = 256; my $_EINTR = 4; my $_ENOSYS = 38; my $SYS_GETRANDOM = 318; my $GRND_NONBLOCK = 0x0001; my $srand_initialized = ''; # Used by _assemble_random_data_collection_without_random_device() sub getranddata { ## no critic qw(Subroutines::ProhibitExcessComplexity) my ( $bytes_of_random_data_wanted, $my_chars_ar, $preloadcount ) = @_; use bytes; #will go away when we leave this context my $pid = $$; if ( $last_entropy_pool_owner != $pid ) { %entropy_pool = (); $last_entropy_pool_owner = $pid; } $preloadcount ||= $DEFAULT_PRELOAD_16TH; my $bytes_of_data_to_preload_into_entropy_pool = $preloadcount * 16; if ($bytes_of_random_data_wanted) { if ( $bytes_of_random_data_wanted =~ tr{0-9}{}c ) { require Cpanel::Exception; die Cpanel::Exception::create( 'InvalidParameter', '“[_1]” is not a valid number of bytes.', [$bytes_of_random_data_wanted] ); } } else { $bytes_of_random_data_wanted = $DEFAULT_LENGTH; } my $number_of_acceptable_characters; my $want_chars; if ( !$my_chars_ar ) { $my_chars_ar = \@DEFAULT_CHARACTERS; $want_chars = ( $_default_want_chars_string ||= join( '', @DEFAULT_CHARACTERS ) ); } if ( !ref $my_chars_ar && $my_chars_ar eq 'binary' ) { $number_of_acceptable_characters = $NUMBER_OF_ASCII_CHARS; $want_chars = ''; } else { $number_of_acceptable_characters = scalar @{$my_chars_ar}; if ( $number_of_acceptable_characters < 1 || $number_of_acceptable_characters > $NUMBER_OF_ASCII_CHARS ) { require Cpanel::Exception; die Cpanel::Exception::create( 'InvalidParameter', 'The number of desired characters must be at least 1 and at most 256.' ); } $want_chars ||= join( '', @{$my_chars_ar} ); } $entropy_pool{$want_chars} ||= ''; my $cur_entropy_pool_sr = \$entropy_pool{$want_chars}; my ( $code_ref_to_remove_chars_above_upper_limit, $code_ref_to_translate_acceptable_chars ) = _generate_random_data_code_refs( $want_chars, $my_chars_ar ); my ( $dummy, $failed_read_attempts, $rand_chars, $random_data_remaining, $entropy_pool_remaining ); my $random_data_collected = ''; my ( $rand_fh, $rand_fh_bitmask ); my $random_source_is_usable = 1; while ( length($random_data_collected) < $bytes_of_random_data_wanted ) { READ_FROM_RANDOM_SOURCE: while (1) { $random_data_remaining = $bytes_of_random_data_wanted - length($random_data_collected); last READ_FROM_RANDOM_SOURCE if !$random_source_is_usable; last READ_FROM_RANDOM_SOURCE if ( length($$cur_entropy_pool_sr) + length($random_data_collected) ) >= $bytes_of_random_data_wanted; $entropy_pool_remaining = $bytes_of_data_to_preload_into_entropy_pool - length($$cur_entropy_pool_sr); if ( !defined $getrandom_syscall_is_usable || $getrandom_syscall_is_usable > 0 ) { my $rand_count = $entropy_pool_remaining > $random_data_remaining ? $entropy_pool_remaining : $random_data_remaining; my $getrandom = _getrandom( $rand_count, \$rand_chars ); if ( $getrandom == -1 ) { if ( $! == $_EINTR ) { next READ_FROM_RANDOM_SOURCE; } else { $getrandom_syscall_is_usable = 0; if ( $! != $_ENOSYS ) { warn "getrandom() failed: $! - falling back to $random_source"; } } } else { $getrandom_syscall_is_usable = $getrandom ? 1 : 0; } } if ( !$getrandom_syscall_is_usable ) { if ( !$rand_fh ) { if ( open $rand_fh, '<:stdio', $random_source ) { $random_source_is_usable = -c $rand_fh ? 1 : 0; if ($random_source_is_usable) { Cpanel::FHUtils::Blocking::set_non_blocking($rand_fh); } else { warn "“$random_source” is unusable because it is not a character device!"; } } else { warn "Failed to open($random_source): $!"; $random_source_is_usable = 0; } last READ_FROM_RANDOM_SOURCE if !$random_source_is_usable; } sysread( $rand_fh, $rand_chars, $entropy_pool_remaining > $random_data_remaining ? $entropy_pool_remaining : $random_data_remaining ) or do { if ( ++$failed_read_attempts > $MAX_READ_ATTEMPTS ) { warn "Failed $MAX_READ_ATTEMPTS times to read from “$random_source”! Last failure was: $!"; $random_source_is_usable = 0; last READ_FROM_RANDOM_SOURCE; } $rand_fh_bitmask ||= Cpanel::FHUtils::Tiny::to_bitmask($rand_fh); select( $dummy = $rand_fh_bitmask, undef, undef, 0.0125 ); next READ_FROM_RANDOM_SOURCE; }; } $code_ref_to_remove_chars_above_upper_limit->( \$rand_chars ) if $code_ref_to_remove_chars_above_upper_limit; $code_ref_to_translate_acceptable_chars->( \$rand_chars ) if $code_ref_to_translate_acceptable_chars; $$cur_entropy_pool_sr .= $rand_chars; } if ( length $$cur_entropy_pool_sr ) { $random_data_collected .= substr( $$cur_entropy_pool_sr, 0, $random_data_remaining, '' ); # just take what we need } else { warn "Using slow randomization logic!"; $random_data_collected .= _assemble_random_data_collection_without_random_device( $number_of_acceptable_characters == $NUMBER_OF_ASCII_CHARS ? [ map { chr } 0 .. 255 ] : $my_chars_ar, $bytes_of_random_data_wanted - length($random_data_collected), ); } } close($rand_fh) if ref $rand_fh; return substr( $random_data_collected, 0, $bytes_of_random_data_wanted ); } sub _assemble_random_data_collection_without_random_device { my ( $my_chars_ar, $bytes_of_random_data_wanted ) = @_; my $process_fingerprint = "$>:$<:$):$$"; unless ( $srand_initialized eq $process_fingerprint ) { $srand_initialized = $process_fingerprint; srand(); } my $num_chars = @$my_chars_ar; my $random_data_collected = q<>; $random_data_collected .= $my_chars_ar->[ rand $num_chars ] for ( 1 .. $bytes_of_random_data_wanted ); return $random_data_collected; } sub clear_pool { %entropy_pool = (); return; } sub _generate_random_data_code_refs { my ( $want_chars, $my_chars_ar ) = @_; if ( !ref $my_chars_ar ) { return (); } my ( $code_ref_to_remove_chars_above_upper_limit, $code_ref_to_translate_acceptable_chars ); my $number_of_acceptable_characters = scalar @$my_chars_ar; my ( $last_good_value_hex, $last_good_value ); my $first_bad_value = $NUMBER_OF_ASCII_CHARS - ( $NUMBER_OF_ASCII_CHARS % $number_of_acceptable_characters ); if ( $first_bad_value != $NUMBER_OF_ASCII_CHARS ) { my $first_bad_value_hex = sprintf( '%02x', $first_bad_value ); $last_good_value = $first_bad_value - 1; $last_good_value_hex = sprintf( '%02x', $last_good_value ); $code_ref_to_remove_chars_above_upper_limit = $TR_CODE_CACHE_BAD_CHARS{$first_bad_value_hex} ||= eval 'sub { ${$_[0]} =~ tr/\x' . $first_bad_value_hex . '-\xff//d; }'; ## no critic qw(BuiltinFunctions::ProhibitStringyEval) } else { $last_good_value_hex = 'ff'; $last_good_value = 255; } $code_ref_to_translate_acceptable_chars = $TR_CODE_CACHE_NUM_ACCEPTABLE{$want_chars} ||= eval 'sub { ${$_[0]} =~ tr/\x{0}-\x{' . $last_good_value_hex . '}/' . join( '', map { quotemeta( $my_chars_ar->[ $_ % $number_of_acceptable_characters ] ) } ( 0 .. $last_good_value ) ) . '/; }'; ## no critic qw(BuiltinFunctions::ProhibitStringyEval) return ( $code_ref_to_remove_chars_above_upper_limit, $code_ref_to_translate_acceptable_chars ); } sub _getrandom { my ( $rand_count, $rand_chars_sr ) = @_; return syscall( 0 + $SYS_GETRANDOM, ( $$rand_chars_sr = "\0" x $rand_count ), 0 + $rand_count, 0 + $GRND_NONBLOCK ); } 1; } # --- END Cpanel/Rand/Get.pm { # --- BEGIN Cpanel/Rand.pm package Cpanel::Rand; use strict; use warnings; no warnings 'once'; # use Cpanel::Exception (); # perlpkg line 211 # use Cpanel::Fcntl::Constants (); # perlpkg line 211 # use Cpanel::Hash (); # perlpkg line 211 # use Cpanel::SV (); # perlpkg line 211 my $MAX_TMPFILE_CREATE_ATTEMPTS = 50; use constant WRONLY_CREAT_EXCL => $Cpanel::Fcntl::Constants::O_WRONLY | $Cpanel::Fcntl::Constants::O_CREAT | $Cpanel::Fcntl::Constants::O_EXCL; our ( $DO_OPEN, $SKIP_OPEN, $TYPE_FILE, $TYPE_DIR ) = ( 0, 1, 0, 1 ); sub getranddata { require Cpanel::Rand::Get; goto \&Cpanel::Rand::Get::getranddata; } sub gettmpfile { return get_tmp_file_by_name('/tmp/cpanel.TMP'); } sub gettmpdir { return get_tmp_dir_by_name('/tmp/cpanel.TMP'); } sub api2_getranddata { my %CFG = @_; require Cpanel::Rand::Get; return { 'random' => Cpanel::Rand::Get::getranddata( $CFG{'length'} || 16 ) }; } our %API = ( getranddata => { allow_demo => 1 }, ); sub api2 { my ($func) = @_; return { %{ $API{$func} } } if $API{$func}; return; } sub get_tmp_dir_by_name { my $templatefile = shift; my $suffix = shift || '.work'; return get_tmp_file_by_name( $templatefile, $suffix, $TYPE_DIR, $DO_OPEN ); } sub get_tmp_file_by_name { my $templatefile = shift; my $suffix = shift || '.work'; my $type = shift || $TYPE_FILE; my $open = shift || $DO_OPEN; if ( index( $suffix, '.' ) != 0 ) { substr( $suffix, 0, 0, '.' ); } my $last_error; my $fh; my $randlength = 8; my $maxlength = 255 - $randlength - 1; my $root = $templatefile . $suffix; my (@path) = split( m{/+}, $root ); my $file = substr( pop @path, -$maxlength, $maxlength ); my $tmpfile = join( '/', @path, $file ) . '.' . _rand_trailer($randlength); Cpanel::SV::untaint($tmpfile); local $!; my $attempts = 0; { my $old = umask(0); # Cpanel::Umask was too slow here when creating many zone file while ( ++$attempts < $MAX_TMPFILE_CREATE_ATTEMPTS && ( ( $open != $DO_OPEN && -e $tmpfile ) || ( $open == $DO_OPEN ? ( $type == $TYPE_DIR ? !mkdir( $tmpfile, 0700 ) : !sysopen( $fh, $tmpfile, WRONLY_CREAT_EXCL, 0600 ) ) : 0 ) ) ) { $last_error = $!; my (@path) = split( m{/+}, $root ); my $file = substr( pop @path, -$maxlength, $maxlength ); my $tmpfile = join( '/', @path, $file ) . '.' . _rand_trailer($randlength); Cpanel::SV::untaint($tmpfile); } umask($old); } if ( $attempts == $MAX_TMPFILE_CREATE_ATTEMPTS ) { die Cpanel::Exception::create( 'TempFileCreateError', [ path => $tmpfile, error => $last_error ] ); } return ( $tmpfile, $fh ) if wantarray && $type == $TYPE_FILE; return $tmpfile; # file will close when $fh leaves context } sub _rand_trailer { return substr( sprintf( '%08x', Cpanel::Hash::get_fastest_hash( join( '-', substr( rand, 2 ), $$, time ) ) ), 0, $_[0] ); } 1; } # --- END Cpanel/Rand.pm { # --- BEGIN Cpanel/TempFile.pm package Cpanel::TempFile; use strict; use warnings; no warnings 'once'; # use Cpanel::Rand (); # perlpkg line 211 # use Cpanel::Debug (); # perlpkg line 211 # use Cpanel::SafeDir::MK (); # perlpkg line 211 # use Cpanel::SafeDir::RM (); # perlpkg line 211 # use Cpanel::Fcntl (); # perlpkg line 211 # use Cpanel::Debug (); # perlpkg line 211 # use Cpanel::Destruct (); # perlpkg line 211 use Cwd (); my $DO_OPEN = $Cpanel::Rand::DO_OPEN; my $SKIP_OPEN = $Cpanel::Rand::SKIP_OPEN; my $TYPE_DIR = $Cpanel::Rand::TYPE_DIR; my $TYPE_FILE = $Cpanel::Rand::TYPE_FILE; our $DEFAULT_PATH = '/var/tmp'; my $DEFAULT_SUFFIX = 'tmp'; sub get_safe_tmpfile { return get_safe_tmp_file_or_dir( $Cpanel::Rand::TYPE_FILE, @_ ); } sub get_safe_tmpdir { return get_safe_tmp_file_or_dir( $Cpanel::Rand::TYPE_DIR, @_ ); } sub get_safe_tmp_file_or_dir { ## no critic qw(Subroutines::RequireArgUnpacking) my $file_or_dir = shift; my $homedir = $Cpanel::homedir; if ( !$homedir ) { require Cpanel::PwCache; $homedir = Cpanel::PwCache::gethomedir(); } if ( !-d $homedir . '/tmp' ) { if ( !mkdir( $homedir . '/tmp', 0755 ) ) { Cpanel::Debug::log_warn("Failed to create $homedir/tmp"); return; } } return Cpanel::Rand::get_tmp_file_by_name( $homedir . '/tmp/Cpanel::TempFile', '.tmp', $file_or_dir, @_ ); # audit case 46806 ok } sub new { my ( $what, $opts ) = @_; my $class = ref $what || $what; my $self = {}; bless $self, $class; $self->set_opts($opts); $self->{"needunlink_$$"} = []; return $self; } sub dir { my ( $self, @other_args ) = @_; return $self->_dir_or_file( $TYPE_DIR, @other_args ); } sub file { my ( $self, @other_args ) = @_; return $self->_dir_or_file( $TYPE_FILE, @other_args ); } sub file_in_dir { my ( $self, @other_args ) = @_; my $dir = $self->dir(@other_args); my $opts = pop @other_args || {}; return $self->_dir_or_file( $TYPE_FILE, @other_args, { %$opts, 'path' => $dir } ); } sub file_readwrite { my ( $self, @other_args ) = @_; if ( !wantarray ) { $self->_warn("Calling file_readwrite() in scalar context makes no sense, since you will only get back a filename but no filehandle"); return; } my ( $fname, $fh ) = $self->file(@other_args); close $fh; undef $fh; my $mode = Cpanel::Fcntl::or_flags(qw( O_RDWR O_EXCL )); sysopen( $fh, $fname, $mode, 0600 ) or $self->_die("Could not sysopen $fname: $!\n"); return ( $fname, $fh ); } sub filename_only { my $self = shift; my $die_msg = "You must not call filename_only() to get a unique temp file name not backed by an actual"; $die_msg .= " file on disk. The subroutine is not implemented and with good reason; see case 48668"; $self->_die($die_msg); } sub set_opts { my ( $self, $opts ) = @_; my @valid_keys = qw( suffix prefix path debug mkdirs ); my $err; foreach my $key ( sort keys %{$opts} ) { next if grep { $key eq $_ } @valid_keys; $self->_warn("Disallowing invalid opt '$key' passed in opts hash"); $err = 1; } return if $err; $opts //= {}; $self->{'opts'} //= {}; my @debug; foreach my $k ( sort keys %{$opts} ) { my $v = $opts->{$k} // ''; $self->{'opts'}->{$k} = $v; push @debug, "Set opt $k = $v"; } $Cpanel::Debug::level = $self->{'opts'}->{'debug'} ? 1 : 0; $self->_debug($_) for (@debug); return 1; } sub _get_opt { my ( $self, $name, $opts ) = @_; return $opts->{$name} || $self->{'opts'}->{$name}; } sub _dir_or_file { # Main workhorse of this module my ( $self, $dir_or_file, @other_args ) = @_; my $opts = {}; my $last_arg = $other_args[$#other_args]; if ( ref $last_arg eq "HASH" ) { pop @other_args; $opts = $last_arg; } my $open = $DO_OPEN; my $prefix = $self->_get_opt( 'prefix', $opts ) || ""; if ( length $prefix ) { if ( $prefix =~ m{/} ) { $self->_warn("You must not specify a prefix containing '/' ; instead, use the 'path' option for that purpose"); return; } if ( $prefix =~ m{[^-.\w]} ) { $self->_warn("Bad prefix '$prefix', prefix must contain only '.', '-', and \\w characters"); return; } } my $caller = _callername(); substr $prefix, 0, 0, substr( $caller, length $caller > 40 ? -40 : 0 ) . '__' if $caller; substr $prefix, 0, 0, "$$" . '.'; my $path = $self->_get_opt( 'path', $opts ) || $DEFAULT_PATH; my $suffix = $self->_get_opt( 'suffix', $opts ) || $DEFAULT_SUFFIX; substr $prefix, 0, 0, "$path/"; if ( !-e $path ) { if ( $self->_get_opt( 'mkdirs', $opts ) ) { my @created; if ( Cpanel::SafeDir::MK::safemkdir( $path, undef, undef, \@created ) && -e $path ) { $self->_info("Have created path '$path'"); push @{ $self->{"needunlink_$$"} }, @created; } else { $self->_warn("Non-existent path '$path', could not create"); } } else { $self->_warn("Non-existent path '$path', will not create, because mkdirs option is not set"); } } my ( $fname, $fh ) = Cpanel::Rand::get_tmp_file_by_name( $prefix, $suffix, $dir_or_file, $open ); undef $fname if defined $fname && $fname eq "/dev/null"; $fname = $self->_make_suffix_rightmost( $fname, $suffix ); push @{ $self->{"needunlink_$$"} }, $fname if defined $fname; return ( $fname, $fh ) if wantarray; return $fname; } sub _make_suffix_rightmost { my ( $self, $fname, $suffix ) = @_; if ( defined $fname ) { my $orig = $fname; if ( $fname =~ s{ ^ (.*) [.] ($suffix) [.] (.*) }{ "$1.$3.$2" }ex ) { if ( -e $orig ) { if ( !rename $orig, $fname ) { $self->_warn("Could not rename '$orig' to '$fname' to shift suffix ('$suffix') to rightmost position, leaving as is"); $fname = $orig; } } } else { print STDERR "Regular expression substitution failed to adjust '$orig' to shift suffix ('$suffix') to rightmost position\n"; } } return $fname; } sub _info { my ( $self, $msg ) = @_; return Cpanel::Debug::log_info($msg); } sub _warn { my ( $self, $msg ) = @_; return Cpanel::Debug::log_warn($msg); } sub _debug { my ( $self, $msg ) = @_; return unless $Cpanel::Debug::level; return Cpanel::Debug::log_debug($msg); } sub _die { my ( $self, $msg ) = @_; return Cpanel::Debug::log_die($msg); } { my $caller; sub _callername { return $caller if defined $caller; ( $caller = $0 ) =~ s{\W}{_}g; $caller = uc $caller; return $caller; } BEGIN { _callername() } } sub cleanup { my $self = shift; return unless defined $self->{"needunlink_$$"} && ref $self->{"needunlink_$$"}; my @needunlink = reverse @{ $self->{"needunlink_$$"} }; for my $file (@needunlink) { if ( ( $file =~ tr/\/// ) < 1 ) { $self->_warn("Not removed: $file, as a temp file cannot be at top level"); # ok to not remove because invalid } elsif ( $file eq '/dev/null' ) { # at this writing we need this, unfortunately $self->_warn("Not removed: /dev/null, I flatly refuse to remove it"); } else { my $file_or_dir = -d $file ? "directory" : "file"; my $existed = -e _; if ( !$existed ) { $self->_debug("Not removing $file_or_dir $file, does not exist; perhaps already removed in a recursive dir cleanup, or by some other removal agent"); } else { if ( $file_or_dir eq 'directory' ) { local $?; my $old_dir = Cwd::abs_path( Cwd::getcwd($file) ); my $abs_path = Cwd::abs_path($file); if ( $old_dir eq $abs_path ) { $self->_warn("The cwd is temporary directory “$file”. The cwd was changed to “$file/..” in order to remove the temporary directory."); chdir("$file/..") or die "Failed to chdir('$file/..'): $!"; } Cpanel::SafeDir::RM::safermdir($file); } else { unlink($file); } my $intro = $existed && !-e $file ? "R" : "Not r"; $self->_debug("${intro}emoved: $file_or_dir $file"); } } } @{ $self->{"needunlink_$$"} } = (); return; } sub needunlink { my ( $self, $item ) = @_; push @{ $self->{"needunlink_$$"} }, $item; return; } sub DESTROY { my $self = shift; return if Cpanel::Destruct::in_dangerous_global_destruction(); $self->cleanup(); return; } 1; } # --- END Cpanel/TempFile.pm { # --- BEGIN Cpanel/Crypt/GPG/Import.pm package Cpanel::Crypt::GPG::Import; use strict; # use parent Cpanel::Crypt::GPG::Base (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Crypt::GPG::Base); } # use Cpanel::SafeRun::Object (); # perlpkg line 211 # use Cpanel::TempFile (); # perlpkg line 211 sub new { my ( $class, $opts_hr ) = @_; $opts_hr = {} if !( $opts_hr && 'HASH' eq ref $opts_hr ); my $self = eval { $class->SUPER::new($opts_hr) }; if ( !$self ) { return wantarray ? ( undef, "Failed to find the GnuPG binary." ) : undef; } my $tmp = ( $opts_hr->{tmp} ) ? $opts_hr->{tmp} : Cpanel::TempFile->new(); $self->{tmp} = $tmp; return $self; } sub verify { my ( $self, %args ) = @_; my ( $sig, @files ); if ( $args{sig} ) { $sig = $args{sig}; } elsif ( $args{sig_data} ) { $sig = $self->_write_data_to_temp_file( $args{sig_data}, $self->{tmp} ); } else { return wantarray ? ( undef, "Arguments 'sig' or 'sig_data' must be provided." ) : undef; } if ( $args{files} ) { @files = ( ref( $args{files} ) eq 'ARRAY' ) ? @{ $args{files} } : ( $args{files} ); } elsif ( defined( $args{files_data} ) ) { for my $file ( ( ref( $args{files_data} ) eq 'ARRAY' ) ? @{ $args{files_data} } : ( $args{files_data} ) ) { push @files, $self->_write_data_to_temp_file( $file, $self->{tmp} ); } } else { return wantarray ? ( undef, "Arguments 'files' or 'files_data' must be provided." ) : undef; } my @args = ( '--logger-fd', '1', '--status-fd', '1', $self->{homedir} ? ( '--homedir' => $self->{homedir} ) : (), '--verify', $sig, @files, ); my $run = Cpanel::SafeRun::Object->new( program => $self->{bin}, args => \@args, timeout => _gpg_timeout(), ); if ( !$run ) { return wantarray ? ( undef, "Failed to invoke gpg." ) : undef; } my $sig_data = undef; my $status = "Failed to validate signature due to some unknown error."; my %notes; my $curnote; for my $l ( split /\n/, $run->stdout() ) { if ( $l =~ /^\[GNUPG:\] VALIDSIG ([A-F0-9]+) (\d+-\d+-\d+) (\d+) ([A-F0-9]+) ([A-F0-9]+) ([A-F0-9]+) ([A-F0-9]+) ([A-F0-9]+) ([A-F0-9]+) ([A-F0-9]+)$/ ) { $sig_data = { id => substr( $1, -16 ), create_time => $3, expire_time => $4, }; $status = "Valid signature."; } elsif ( $l =~ /^\[GNUPG:\] BADSIG ([A-F0-9]+) (.+)$/ ) { $status = "Invalid signature."; } elsif ( $l =~ /^\[GNUPG:\] NO_PUBKEY ([A-F0-9]+)$/ ) { $status = "Could not find public key in keychain."; } elsif ( $l =~ /^\[GNUPG:\] NODATA ([A-F0-9]+)$/ ) { $status = "Could not find a GnuPG signature in the signature file."; } elsif ( $l =~ /^\[GNUPG:\] NOTATION_NAME (.+)$/ ) { $curnote = $1; $notes{$curnote} = ''; } elsif ( $l =~ /^\[GNUPG:\] NOTATION_DATA (.+)$/ ) { $notes{$curnote} .= $1; } } if ($sig_data) { $sig_data->{notations} = \%notes; } return wantarray ? ( $sig_data, "$status (@files)" ) : $sig_data; } sub add_pub_key { my ( $self, %args ) = @_; if ( !$args{key} ) { return wantarray ? ( undef, "No key provided." ) : undef; } my @args = ( '--logger-fd', '1', '--status-fd', '1', $self->{homedir} ? ( '--homedir' => $self->{homedir} ) : (), '--import' ); my $run = Cpanel::SafeRun::Object->new( program => $self->{bin}, args => \@args, stdin => $args{key}, timeout => _gpg_timeout(), ); if ( !$run ) { return wantarray ? ( undef, "Failed to invoke gpg." ) : undef; } my @r = ( undef, "Failed to import key." ); for my $l ( split /\n/, $run->stdout() ) { if ( $l =~ /^\[GNUPG:\] IMPORT_OK \d+ ([A-F0-9]+)$/ ) { my $id = substr( $1, -16 ); @r = ( $id, "Successfully imported key." ); } } return wantarray ? @r : shift @r; } sub get_key_id { my ( $self, %args ) = @_; if ( !$args{key} ) { return wantarray ? ( undef, "No key provided." ) : undef; } my @r = ( undef, "Failed to parse key id." ); if ( my $id = $self->add_pub_key(%args) ) { @r = ( $id, "Successfully parsed key id." ); } return wantarray ? @r : shift @r; } sub _write_data_to_temp_file { my ( $self, $data ) = @_; my ( $name, $handle ) = $self->{tmp}->file(); binmode $handle; # We may be opening binary OpenPGP data. print {$handle} $data; close($handle); return $name; } sub _gpg_timeout { return 60; } 1; } # --- END Cpanel/Crypt/GPG/Import.pm { # --- BEGIN Cpanel/Crypt/GPG/Import/Temp.pm package Cpanel::Crypt::GPG::Import::Temp; use strict; use warnings; no warnings 'once'; # use parent Cpanel::Crypt::GPG::Import (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::Crypt::GPG::Import); } # use Cpanel::TempFile (); # perlpkg line 211 sub new { my ( $class, $opts_hr ) = @_; $opts_hr = {} if !( $opts_hr && 'HASH' eq ref $opts_hr ); my $tmp = Cpanel::TempFile->new; my $path = $tmp->dir(); $opts_hr->{tmp} = $tmp; $opts_hr->{homedir} = $path; my $self = $class->SUPER::new($opts_hr); return $self; } 1; } # --- END Cpanel/Crypt/GPG/Import/Temp.pm { # --- BEGIN Cpanel/YAML.pm package Cpanel::YAML; use strict; use YAML::Syck (); # use Cpanel::YAML::Syck (); # perlpkg line 211 BEGIN { *Load = *YAML::Syck::Load; *SafeDump = \&Dump; *DumpFile = *YAML::Syck::DumpFile; } our $MAX_LOAD_LENGTH = 65535; our $MAX_PRIV_LOAD_LENGTH = 4194304; # four megs sub _is_openhandle { my $h = shift; if ( my $isa = ref($h) ) { return 1 if ( $isa eq 'GLOB' ); return 1 if ( $isa =~ m/^IO::/ ); } return 1 if ( ref( \$h ) eq 'GLOB' ); return; } sub SafeLoadFile { # only allow a small bit of data to be loaded return LoadFile( $_[0], $MAX_LOAD_LENGTH ); } sub LoadFile { my $file = shift; my $max = shift; my $str_r; if ( _is_openhandle($file) ) { if ($max) { my $togo = $max; my $buffer = ''; my $bytes_read; while ( $bytes_read = read( $file, $buffer, $togo, length $buffer ) && length $buffer < $max ) { $togo -= $bytes_read; } $str_r = \$buffer; } else { $str_r = \do { local $/; <$file> }; } } else { if ( !-e $file || -z $file ) { require Carp; Carp::croak("'$file' is non-existent or empty"); } open( my $fh, '<', $file ) or do { require Carp; Carp::croak("Cannot read from $file: $!"); }; $str_r = \do { local $/; <$fh> }; } return YAML::Syck::LoadYAML($$str_r); } sub Dump { my ( $data, @extra ) = @_; $data = _convert_json_boolean( $data, {} ); return YAML::Syck::Dump( $data, @extra ); } sub _convert_json_boolean { my ( $data, $seen ) = @_; return unless defined $data; return $data if $seen->{"$data"}; if ( my $isa = ref($data) ) { if ( index( $isa, 'JSON::' ) == 0 ) { if ( $isa eq 'JSON::PP::Boolean' || $isa eq 'JSON::XS::Boolean' ) { return $data ? 1 : 0; # true / false: prefer 1/0 for roundtrip purpose } } $seen->{"$data"} = 1; if ( $isa eq 'HASH' ) { foreach my $key ( keys %$data ) { $data->{$key} = _convert_json_boolean( $data->{$key}, $seen ); } } elsif ( $isa eq 'ARRAY' ) { foreach my $i ( 0 .. $#$data ) { $data->[$i] = _convert_json_boolean( $data->[$i], $seen ); } } } return $data; } 1; } # --- END Cpanel/YAML.pm { # --- BEGIN Cpanel/CachedDataStore.pm package Cpanel::CachedDataStore; use strict; use Try::Tiny; # use Cpanel::AdminBin::Serializer (); # perlpkg line 211 # use Cpanel::LoadFile::ReadFast (); # perlpkg line 211 # use Cpanel::Fcntl::Constants (); # perlpkg line 211 # use Cpanel::Debug (); # perlpkg line 211 # use Cpanel::Exception (); # perlpkg line 211 use Time::HiRes (); use constant { WRONLY_CREAT_EXCL => ( $Cpanel::Fcntl::Constants::O_WRONLY | $Cpanel::Fcntl::Constants::O_CREAT | $Cpanel::Fcntl::Constants::O_EXCL ), _EEXIST => 17, }; our $LOCK = 1; #const our $LAST_WRITE_CACHE_SERIALIZATION_ERROR; our $MAX_CACHE_ELEMENTS = 32768 + 1; my $MAX_CACHE_OBJECT_SIZE = 1024 * 512; # do not cache objects larger than 512k my $_iterations_since_last_cache_cleanup = 0; my %DATASTORE_CACHE; *_time = *Time::HiRes::time; *_utime = *Time::HiRes::utime; *_stat = *Time::HiRes::stat; sub store_ref { return savedatastore( $_[0], { 'data' => $_[1], ( ref $_[2] ? %{ $_[2] } : () ) } ); } sub fetch_ref { my ( $file, $is_array ) = @_; my $fetch_ref = loaddatastore($file); my $data_type = ref $fetch_ref->{'data'}; my $data = $data_type ? top_level_clone( $fetch_ref->{'data'} ) : undef; $data_type ||= 'UNDEF'; if ( $is_array && $data_type ne 'ARRAY' ) { return []; } elsif ( !$is_array && $data_type ne 'HASH' ) { return {}; } return $data; } sub load_ref { my ( $file, $into_ref, $opts_ref ) = @_; my $fetch_ref = loaddatastore( $file, 0, $into_ref, $opts_ref ); return $fetch_ref->{'data'}; } sub savedatastore { my ( $file, $opts ) = @_; require Cpanel::SafeFile; my $use_cache_file = !defined $opts->{'cache_file'} || $opts->{'cache_file'}; if ( !exists $opts->{'data'} || !defined $opts->{'data'} ) { Cpanel::Debug::log_warn("Expected data to be saved. \$opts->{'data'} was empty. $file has been left untouched."); if ( $opts->{'fh'} && $opts->{'safefile_lock'} ) { Cpanel::SafeFile::safeclose( $opts->{'fh'}, $opts->{'safefile_lock'} ); } elsif ( $opts->{'fh'} ) { close( $opts->{'fh'} ); } return; } my $use_memory_cache = !defined $opts->{'enable_memory_cache'} || $opts->{'enable_memory_cache'}; my $original_file = $file; substr( $file, -5, 5, '' ) if rindex( $file, '.yaml' ) == length($file) - 5; require Cpanel::YAML; my $output = Cpanel::YAML::Dump( $opts->{'data'} ); my $perms = exists $opts->{'mode'} ? $opts->{'mode'} & 00777 : undef; if ( !defined($perms) ) { if ( $opts->{'fh'} ) { die "Filehandle already closed!" if !defined fileno $opts->{'fh'}; $perms = ( stat $opts->{'fh'} )[2] & 0777; } elsif ( -e $original_file ) { $perms = ( stat _ )[2] & 0777; } else { $perms = 0644; } } require Cpanel::FileUtils::Write; my $fh = Cpanel::FileUtils::Write::overwrite( $original_file, $output, $perms ); @{$opts}{ 'inode', 'size', 'mtime' } = ( _stat($fh) )[ 1, 7, 9 ]; close $fh; if ($use_cache_file) { _write_cache_file( "$file.cache", $opts->{'data'}, $perms ); _utime( $opts->{'mtime'}, $opts->{'mtime'}, "$file.cache" ); } if ($use_memory_cache) { if ( $opts->{'size'} < $MAX_CACHE_OBJECT_SIZE ) { _cleanup_cache() if ++$_iterations_since_last_cache_cleanup > $MAX_CACHE_ELEMENTS && scalar keys %DATASTORE_CACHE >= $MAX_CACHE_ELEMENTS; @{ $DATASTORE_CACHE{$original_file} }{ 'cache', 'inode', 'mtime', 'size' } = @{$opts}{ 'data', 'inode', 'mtime', 'size' }; } else { delete $DATASTORE_CACHE{$original_file}; } } my $ok; if ( $opts->{'fh'} ) { if ( $opts->{'safefile_lock'} ) { $ok = Cpanel::SafeFile::safeclose( $opts->{'fh'}, $opts->{'safefile_lock'} ); } else { $ok = close( $opts->{'fh'} ); } } else { $ok = 1; } return $ok; } sub loaddatastore { ## no critic(Subroutines::ProhibitExcessComplexity) -- Refactoring this function is a project, not a bug fix my ( $datastore_file, $lock_required, $copy_data_ref, $opts ) = @_; my ( $loaded_data, $filesys_inode, $filesys_perms, $filesys_mtime, $filesys_size, $filesys_cache_mtime, $cache, $datastore_cache_file ); if ( !$datastore_file ) { Cpanel::Debug::log_warn('No datastore file specified'); return; } my $use_memory_cache = !defined $opts->{'enable_memory_cache'} || $opts->{'enable_memory_cache'}; my $custom_perms = exists $opts->{'mode'} ? $opts->{'mode'} & 00777 : undef; my $lock_datastore = 0; # default is to not lock if ( defined $lock_required ) { $lock_datastore = $lock_required ? 1 : 0; } elsif ( $opts->{'donotlock'} ) { $lock_datastore = 0; } if ( !$lock_datastore ) { ( $filesys_inode, $filesys_perms, $filesys_size, $filesys_mtime ) = ( _stat($datastore_file) )[ 1, 2, 7, 9 ]; if ( !$filesys_mtime ) { return; } if ( $use_memory_cache && exists $DATASTORE_CACHE{$datastore_file} # no-auto vivify && $DATASTORE_CACHE{$datastore_file}->{'mtime'} && $DATASTORE_CACHE{$datastore_file}->{'size'} && $filesys_mtime == $DATASTORE_CACHE{$datastore_file}->{'mtime'} && $filesys_size == $DATASTORE_CACHE{$datastore_file}->{'size'} && $filesys_inode == $DATASTORE_CACHE{$datastore_file}->{'inode'} ) { if ($copy_data_ref) { _copy_ref_data( $DATASTORE_CACHE{$datastore_file}->{'cache'}, $copy_data_ref, $datastore_file ); } if ( defined $custom_perms ) { if ( ( $filesys_perms & 0777 ) != $custom_perms ) { chmod $custom_perms, $datastore_file or do { warn sprintf( "chmod(0%03o, $datastore_file): $!", $custom_perms ); }; } } return bless { 'size' => $DATASTORE_CACHE{$datastore_file}->{'size'}, 'inode' => $DATASTORE_CACHE{$datastore_file}->{'inode'}, 'mtime' => $DATASTORE_CACHE{$datastore_file}->{'mtime'}, 'data' => $DATASTORE_CACHE{$datastore_file}->{'cache'}, 'file' => $datastore_file, }, __PACKAGE__; } } $datastore_cache_file = $datastore_file; if ( rindex( $datastore_cache_file, '.yaml' ) == length($datastore_cache_file) - 5 ) { substr( $datastore_cache_file, -5, 5, '.cache' ); } else { $datastore_cache_file .= '.cache'; } if ( !$lock_datastore ) { ( $filesys_cache_mtime, $cache ) = _load_datastore_cache_from_disk( $datastore_cache_file, $filesys_mtime, $datastore_file, $filesys_size, $filesys_inode ); if ( $filesys_cache_mtime && $filesys_cache_mtime >= $filesys_mtime && ref $cache ) { $loaded_data = $cache; } if ( $copy_data_ref && $loaded_data ) { _copy_ref_data( $loaded_data, $copy_data_ref, $datastore_file ); } if ($loaded_data) { if ( defined $custom_perms && ( $filesys_perms & 00777 ) != $custom_perms ) { chmod( $custom_perms, $datastore_file ) or do { warn( sprintf "chmod(0%o, %s) failed: %s", $custom_perms, $datastore_file, $! ); }; } if ($use_memory_cache) { if ( $filesys_size < $MAX_CACHE_OBJECT_SIZE ) { _cleanup_cache() if ++$_iterations_since_last_cache_cleanup > $MAX_CACHE_ELEMENTS && scalar keys %DATASTORE_CACHE >= $MAX_CACHE_ELEMENTS; @{ $DATASTORE_CACHE{$datastore_file} }{ 'inode', 'size', 'mtime', 'cache' } = ( $filesys_inode, $filesys_size, $filesys_mtime, $loaded_data ); } else { delete $DATASTORE_CACHE{$datastore_file}; } } return bless { 'inode' => $filesys_inode, 'size' => $filesys_size, 'mtime' => $filesys_mtime, 'data' => $loaded_data, 'file' => $datastore_file, }, __PACKAGE__; } } my $datastore_not_writable; my $data_fh; my $perms = defined $custom_perms ? $custom_perms : 0644; #0644 is the default my $orig_umask; if ( defined $perms ) { $orig_umask = umask( $perms ^ 07777 ); } my $created_datastore_file = 0; if ( !-e $datastore_file ) { if ( sysopen my $f, $datastore_file, WRONLY_CREAT_EXCL, $perms ) { $created_datastore_file = 1; } elsif ( $! != _EEXIST() ) { warn "Failed to create “$datastore_file” (EUID=$>): $!"; } } my $rlock; my $lock_failed; if ( !$lock_datastore ) { open( $data_fh, '<', $datastore_file ) or do { Cpanel::Debug::log_warn("Unable open $datastore_file for reading: $!"); undef $data_fh; }; $datastore_not_writable = 1; } else { my $open_mode = -w $datastore_file ? '+<' : '<'; require Cpanel::SafeFile; $rlock = Cpanel::SafeFile::safeopen( $data_fh, $open_mode, $datastore_file ); my $last_error = $@ || $!; $lock_failed = !$rlock || 1 == $rlock; if ($lock_failed) { Cpanel::Debug::log_warn("Unable get a lock on datastore $datastore_file: $last_error"); undef $data_fh; $datastore_not_writable = 1; } } umask($orig_umask) if defined $orig_umask; if ( !$created_datastore_file ) { my $data_fh_perms = ( _stat( $data_fh // $datastore_file ) )[2] || 0600; if ( defined $custom_perms && ( $data_fh_perms & 00777 ) != $custom_perms ) { chmod( $custom_perms, $data_fh ? $data_fh : $datastore_file ); $data_fh_perms = ( _stat( $data_fh // $datastore_file ) )[2] || 0600; } if ( $data_fh && fileno $data_fh ) { if ($lock_datastore) { ( $filesys_inode, $filesys_perms, $filesys_size, $filesys_mtime ) = ( _stat($data_fh) )[ 1, 2, 7, 9 ]; ( $filesys_cache_mtime, $cache ) = _load_datastore_cache_from_disk( $datastore_cache_file, $filesys_mtime, $datastore_file, $filesys_size, $filesys_inode ); } if ( $filesys_cache_mtime && ref $cache ) { $loaded_data = $cache; } else { $loaded_data = _load_inner_data( $datastore_file, $data_fh ); seek( $data_fh, 0, 0 ); } if ( $copy_data_ref && $loaded_data ) { _copy_ref_data( $loaded_data, $copy_data_ref, $datastore_file ); } } if ( !$lock_datastore || $datastore_not_writable ) { my @data_dir = split( /\/+/, $datastore_cache_file ); pop @data_dir; my $datastore_cache_file_dir = join( '/', @data_dir ); if ( $loaded_data && $filesys_mtime && ( !-e $datastore_cache_file || -w _ ) && ( _stat($datastore_cache_file_dir) )[4] == $> ) { _write_cache_file( $datastore_cache_file, $loaded_data, $data_fh_perms ) if !$filesys_cache_mtime; if ($use_memory_cache) { if ( $filesys_size < $MAX_CACHE_OBJECT_SIZE ) { _cleanup_cache() if ++$_iterations_since_last_cache_cleanup > $MAX_CACHE_ELEMENTS && scalar keys %DATASTORE_CACHE >= $MAX_CACHE_ELEMENTS; @{ $DATASTORE_CACHE{$datastore_file} }{ 'cache', 'inode', 'mtime', 'size' } = ( $loaded_data, $filesys_inode, $filesys_mtime, $filesys_size ); } else { delete $DATASTORE_CACHE{$datastore_file}; } } } } } if ( !$lock_datastore || $datastore_not_writable ) { if ( !$lock_datastore ) { close($data_fh); } else { require Cpanel::SafeFile; Cpanel::SafeFile::safeclose( $data_fh, $rlock ) unless $lock_failed; } $data_fh = undef; # data_fh is closed at this point $datastore_not_writable = 1; # if the datastore is closed, it isn't writable. } my %self = ( 'inode' => $filesys_inode, 'size' => $filesys_size, 'mtime' => $filesys_mtime, 'data' => $loaded_data, 'file' => $datastore_file, ); if ( !$datastore_not_writable ) { @self{ 'safefile_lock', 'fh' } = ( $rlock, $data_fh ); } return bless \%self, __PACKAGE__; } sub _load_datastore_cache_from_disk { my ( $datastore_cache_file, $filesys_mtime, $datastore_file, $filesys_size, $filesys_inode ) = @_; my $loaded_data; if ( open( my $datastore_cache_fh, '<:stdio', $datastore_cache_file ) ) { my $filesys_cache_mtime = ( _stat($datastore_cache_fh) )[9]; # stat the file handle to prevent a race condition if ( $filesys_size && $filesys_mtime && $filesys_cache_mtime >= $filesys_mtime && $filesys_cache_mtime <= _time() ) { eval { local $SIG{'__DIE__'}; # Suppress spewage as we may be reading an invalid cache local $SIG{'__WARN__'}; # and since failure is ok to throw it away $loaded_data = Cpanel::AdminBin::Serializer::LoadFile($datastore_cache_fh); }; my ( $filesys_inode_after_read, $filesys_size_after_read, $filesys_mtime_after_read ) = ( _stat($datastore_file) )[ 1, 7, 9 ]; if ( $filesys_mtime_after_read == $filesys_mtime && $filesys_size_after_read == $filesys_size && $filesys_inode_after_read == $filesys_inode ) { return ( $filesys_cache_mtime, $loaded_data ) if ref $loaded_data; } } } elsif ( $! != _ENOENT() ) { #ok if the file does not exist warn "Failed to open “$datastore_cache_file” for reading: $!"; } return 0; } sub _write_cache_file { my ( $path, $data, $perms ) = @_; $LAST_WRITE_CACHE_SERIALIZATION_ERROR = undef; try { my $serialized; try { $serialized = Cpanel::AdminBin::Serializer::Dump($data); } catch { $LAST_WRITE_CACHE_SERIALIZATION_ERROR = Cpanel::Exception::get_string($_); }; if ($serialized) { require Cpanel::FileUtils::Write; Cpanel::FileUtils::Write::overwrite( $path, $serialized, $perms, ); } } catch { my $str = Cpanel::Exception::get_string($_); Cpanel::Debug::log_warn("Failed to write the cache file “$path” ($str); this file will not be saved."); }; return; } sub file { return $_[0]->{'file'}; } sub fh { return $_[0]->{'fh'}; } sub mtime { return $_[0]->{'mtime'}; } sub size { return $_[0]->{'size'}; } sub clear_data { $_[0]->{'data'} = undef; return; } sub data { if ( defined $_[1] ) { $_[0]->{'data'} = $_[1]; return 1; } return $_[0]->{'data'}; } sub save { return savedatastore( $_[0]->{'file'}, $_[0] ); } sub abort { return unlockdatastore( $_[0] ); } sub unlockdatastore { my ($datastore) = @_; return 0 if !$datastore->{'fh'} || !$datastore->{'safefile_lock'}; require Cpanel::SafeFile; return Cpanel::SafeFile::safeclose( $datastore->{'fh'}, $datastore->{'safefile_lock'} ); } sub _copy_ref_data { my ( $src_ref, $dest_ref, $file ) = @_; if ( ref $src_ref eq 'HASH' ) { local $@; eval { %{$dest_ref} = %{$src_ref}; }; } elsif ( ref $src_ref eq 'ARRAY' ) { local $@; eval { @{$dest_ref} = @{$src_ref}; }; } else { if ($file) { Cpanel::Debug::log_warn("YAML in '$file' is not a hash or array reference"); } else { Cpanel::Debug::log_warn('Asked to duplicate a reference that is not a hash or array'); } $dest_ref = $src_ref; } return; } sub get_cache { return \%DATASTORE_CACHE; } sub clear_cache { %DATASTORE_CACHE = (); return; } sub clear_one_cache { my ($file) = @_; delete $DATASTORE_CACHE{$file}; return; } sub verify { my ($file) = @_; my $fh; open( $fh, '<', $file ) or die "Failed to open $file: $!"; my $data = _load_inner_data( $file, $fh ); return ref $data ? 1 : 0; } sub _load_inner_data { my ( $name, $fh ) = @_; my $data = ''; Cpanel::LoadFile::ReadFast::read_all_fast( $fh, $data ); my $loaded_data; if ( length $data ) { local $@; eval { local $SIG{'__WARN__'}; local $SIG{'__DIE__'}; require Cpanel::YAML; $loaded_data = ( Cpanel::YAML::Load($data) )[0]; }; } $loaded_data = undef unless ref $loaded_data; return $loaded_data; } sub top_level_clone { my ($data) = @_; if ( ref $data eq 'HASH' ) { return { %{ $_[0] } }; } elsif ( ref $data eq 'ARRAY' ) { return [ @{ $_[0] } ]; } return $data; } sub _cleanup_cache { my @oldest_keys = sort { $DATASTORE_CACHE{$b}{'mtime'} <=> $DATASTORE_CACHE{$a}{'mtime'} } keys %DATASTORE_CACHE; splice( @oldest_keys, -1 * int( $MAX_CACHE_ELEMENTS / 2 ) ); delete @DATASTORE_CACHE{@oldest_keys}; $_iterations_since_last_cache_cleanup = 0; return 1; } sub _ENOENT { return 2; } 1; } # --- END Cpanel/CachedDataStore.pm { # --- BEGIN Cpanel/CachedCommand/Utils.pm package Cpanel::CachedCommand::Utils; # use Cpanel::SV (); # perlpkg line 211 my ( $cached_datastore_myuid, $cached_datastore_dir ); sub destroy { my %OPTS = @_; my $cache_file = _get_datastore_filename( $OPTS{'name'}, ( $OPTS{'args'} ? @{ $OPTS{'args'} } : () ) ); if ( -e $cache_file ) { return unlink $cache_file; } else { return 1; } return; } *get_datastore_filename = *_get_datastore_filename; sub _get_datastore_filename { my ( $bin, @args ) = @_; my $file = join( '_', $bin, @args ); $file =~ tr{/}{_}; Cpanel::SV::untaint($file); my $datastore_dir = _get_datastore_dir($file); Cpanel::SV::untaint($datastore_dir); return $datastore_dir . '/' . $file; } sub _get_datastore_dir { my $file = shift; my $myuid = $>; if ( defined $cached_datastore_dir && length $cached_datastore_dir > 1 && defined $cached_datastore_myuid && $myuid == $cached_datastore_myuid ) { my $homedir = Cpanel::PwCache::gethomedir(); $cached_datastore_dir = "$homedir/$ENV{'TEAM_USER'}/.cpanel/datastore" if $ENV{'TEAM_USER'} && $file =~ /^AVAILABLE_APPLICATIONS_CACHE/; return $cached_datastore_dir; } require Cpanel::PwCache; $cached_datastore_dir = Cpanel::SV::untaint( Cpanel::PwCache::gethomedir() ); $cached_datastore_dir .= "/$ENV{'TEAM_USER'}" if $ENV{'TEAM_USER'} && $file =~ /^AVAILABLE_APPLICATIONS_CACHE/; if ( !-e $cached_datastore_dir . '/.cpanel/datastore' && $cached_datastore_dir ne '/' ) { # nobody's homedir is / require Cpanel::SafeDir::MK; Cpanel::SafeDir::MK::safemkdir( "$cached_datastore_dir/.cpanel/datastore", 0700 ) or warn "Failed to mkdir($cached_datastore_dir/.cpanel/datastore): $!"; } $cached_datastore_myuid = $myuid; $cached_datastore_dir .= '/.cpanel/datastore'; return $cached_datastore_dir; } sub invalidate_cache { my $ds_file = get_datastore_filename(@_); unlink $ds_file; return $ds_file; } sub clearcache { $cached_datastore_dir = undef; $cached_datastore_myuid = undef; return; } 1; } # --- END Cpanel/CachedCommand/Utils.pm { # --- BEGIN Cpanel/PublicSuffix.pm package Cpanel::PublicSuffix; use strict; use warnings; no warnings 'once'; # use parent IO::Socket::SSL::PublicSuffix (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(IO::Socket::SSL::PublicSuffix); } # use Cpanel::AdminBin::Serializer (); # perlpkg line 211 # use Cpanel::AdminBin::Serializer::FailOK (); # perlpkg line 211 our $VERSION = '1.2'; # must not end in zero for compat our $public_suffix_db; BEGIN { if ( !$INC{'Mozilla/PublicSuffix.pm'} ) { $INC{'Mozilla/PublicSuffix.pm'} = __FILE__; ## no critic qw(Variables::RequireLocalizedPunctuationVars) *Mozilla::PublicSuffix::public_suffix = sub { __PACKAGE__->get_io_socket_ssl_publicsuffix_handle()->public_suffix(@_); }; } } my %IS_SIMPLE_TLD = ( com => 1, net => 1, org => 1, info => 1, cloud => 1, arpa => 1, 'in-addr.arpa' => 1, 'ip6.arpa' => 1, ); sub domain_isa_tld { my ($domain) = @_; return 1 if ( $domain =~ tr/.// ) == 0; return 1 if $IS_SIMPLE_TLD{$domain}; return 1 if get_io_socket_ssl_publicsuffix_handle()->public_suffix($domain) eq $domain; return 0; } sub get_io_socket_ssl_publicsuffix_handle { return ( $public_suffix_db ||= bless {}, __PACKAGE__ ); } sub public_suffix { $_[0]->_ensure_loaded(); return $_[0]->SUPER::public_suffix( @_[ 1 .. $#_ ] ); } sub _ensure_loaded { if ( !scalar keys %{ $_[0] } ) { require IO::Socket::SSL::PublicSuffix; local $@; warn if !eval { # Try::Tiny will clobber $_[0] my $db = _load_cached_publicsuffix_db(); @{ $_[0] }{ keys %$db } = values %$db; 1; }; if ( scalar keys %{ $_[0] } ) { return; } my $db = IO::Socket::SSL::PublicSuffix->default(); die "Cold not load IO::Socket::SSL::PublicSuffix default database" if !$db; warn if !eval { _write_cached_publicsuffix_db($db); 1 }; @{ $_[0] }{ keys %$db } = values %$db; } return; } sub _DATASTORE_FILE { require Cpanel::CachedCommand::Utils; return Cpanel::CachedCommand::Utils::get_datastore_filename( __PACKAGE__, 'default' ); } sub _get_publicsuffix_size_mtime { if ( $INC{'IO/Socket/SSL/PublicSuffix.pm'} ) { return ( stat( $INC{'IO/Socket/SSL/PublicSuffix.pm'} ) )[ 7, 9 ]; } foreach my $path (@INC) { my ( $size, $mtime ) = ( stat("$path/IO/Socket/SSL/PublicSuffix.pm") )[ 7, 9 ]; return ( $size, $mtime ) if $size; } die "Cannot locate: IO/Socket/SSL/PublicSuffix.pm"; } sub _load_cached_publicsuffix_db { my $datastore_file = _DATASTORE_FILE(); if ( -e $datastore_file ) { my $datastore_mtime = ( stat(_) )[9]; my ( $public_suffix_size, $public_suffix_mtime ) = _get_publicsuffix_size_mtime(); return undef if !$public_suffix_size || !$public_suffix_mtime || $public_suffix_mtime > $datastore_mtime; my $cache = Cpanel::AdminBin::Serializer::FailOK::LoadFile($datastore_file); if ( ref $cache eq 'HASH' && $cache->{'VERSION'} && $cache->{'size'} && $cache->{'VERSION'} == $VERSION && $cache->{'size'} == $public_suffix_size ) { return $cache->{'data'}; } } return undef; } sub _write_cached_publicsuffix_db { my ($db) = @_; my $datastore_file = _DATASTORE_FILE(); my ( $public_suffix_size, $public_suffix_mtime ) = _get_publicsuffix_size_mtime(); my $unblessed = { %{$db} }; require Cpanel::FileUtils::Write; Cpanel::FileUtils::Write::overwrite( $datastore_file, Cpanel::AdminBin::Serializer::Dump( { 'VERSION' => $VERSION, 'size' => $public_suffix_size, 'data' => $unblessed } ), 0640 ); return 1; } sub clear_cache { my $datastore_file = _DATASTORE_FILE(); unlink $datastore_file; return; } 1; } # --- END Cpanel/PublicSuffix.pm { # --- BEGIN Cpanel/HTTP/Tiny/FastSSLVerify.pm package Cpanel::HTTP::Tiny::FastSSLVerify; use strict; use warnings; no warnings 'once'; # use parent HTTP::Tiny (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(HTTP::Tiny); } # use Cpanel::PublicSuffix (); # perlpkg line 211 my $orig_handle_connect = \&HTTP::Tiny::Handle::connect; our $VERSION = '1.0'; use constant NO_VERIFY_TOUCHFILE_PATH => '/var/cpanel/no_verify_SSL'; sub new { my ( $class, %opts ) = @_; my $connect_timeout = delete $opts{'connect_timeout'}; my $ssl_opts_hr = $opts{'SSL_options'}; $ssl_opts_hr &&= {%$ssl_opts_hr}; $ssl_opts_hr->{'SSL_verifycn_publicsuffix'} = Cpanel::PublicSuffix::get_io_socket_ssl_publicsuffix_handle(); my $verify_ssl = 1; if ( -f NO_VERIFY_TOUCHFILE_PATH ) { $verify_ssl = 0; } my $self = $class->SUPER::new( 'verify_SSL' => $verify_ssl, %opts, 'SSL_options' => $ssl_opts_hr, ); $self->{'connect_timeout'} = $connect_timeout if $connect_timeout; return $self; } sub request { my ( $self, @args ) = @_; no warnings 'redefine'; local *HTTP::Tiny::Handle::connect = sub { my ( $connect_self, @args ) = @_; local $connect_self->{'timeout'} = $self->{'connect_timeout'}; return $orig_handle_connect->( $connect_self, @args ); } if ( $self->{'connect_timeout'} ); use warnings 'redefine'; return $self->SUPER::request(@args); } 1; } # --- END Cpanel/HTTP/Tiny/FastSSLVerify.pm { # --- BEGIN Cpanel/HTTP/Client/Response.pm package Cpanel::HTTP::Client::Response; use strict; use warnings; no warnings 'once'; # use parent HTTP::Tiny::UA::Response (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(HTTP::Tiny::UA::Response); } sub new { my ( $class, $opts_hr, @extra ) = @_; my $self = $class->SUPER::new( $opts_hr, @extra ); $self->{'_cp_redirects'} = $opts_hr->{'redirects'}; return $self; } sub redirects { my ($self) = @_; return [ map { ( ref $self )->new($_) } @{ $self->{'_cp_redirects'} } ]; } sub TO_JSON { my $json = { %{ $_[0] } }; $json->{redirects} = delete $json->{_cp_redirects}; return $json; } 1; } # --- END Cpanel/HTTP/Client/Response.pm { # --- BEGIN Cpanel/HTTP/Client.pm package Cpanel::HTTP::Client; use strict; my %MODULE_PARAMS; # use Cpanel::HTTP::Tiny::FastSSLVerify (); # perlpkg line 238 our @ISA; BEGIN { push @ISA, qw(Cpanel::HTTP::Tiny::FastSSLVerify); } # use Cpanel::Exception (); # perlpkg line 211 # use Cpanel::HTTP::Client::Response (); # perlpkg line 211 our $VERSION = '1.0'; sub new { my ( $class, @args ) = @_; my $self = $class->SUPER::new(@args); $MODULE_PARAMS{$self} = {}; return $self; } sub die_on_http_error { my ($self) = @_; $MODULE_PARAMS{$self}{'die_on_http_error'} = 1; return $self; } sub return_on_http_error { my ($self) = @_; $MODULE_PARAMS{$self}{'die_on_http_error'} = 0; return $self; } sub request { my ( $self, $method, $url, $args_hr ) = @_; local $@; my $resp = $self->SUPER::request( $method, $url, $args_hr || () ); my $resp_obj = Cpanel::HTTP::Client::Response->new($resp); if ( $resp_obj->status() == 599 ) { my $error = $resp_obj->content(); chomp($error) if $error && !ref $error; die Cpanel::Exception::create( 'HTTP::Network', [ method => $method, url => $url, error => $error, redirects => $resp_obj->redirects(), ] ); } if ( $MODULE_PARAMS{$self}{'die_on_http_error'} && $resp->{'status'} >= 400 ) { die Cpanel::Exception::create( 'HTTP::Server', [ method => $method, content_type => scalar( $resp_obj->header('Content-Type') ), ( map { ( $_ => $resp_obj->$_() ) } qw( content status reason url headers redirects ) ), ], ); } return $resp_obj; } sub set_default_header { my ( $self, $header, $value ) = @_; $header =~ tr/[A-Z]/[a-z]/; $self->{'default_headers'}{$header} = $value; return 1; } sub delete_default_header { my ( $self, $header ) = @_; $header =~ tr/[A-Z]/[a-z]/; return delete $self->{'default_headers'}{$header}; } sub DESTROY { my ($self) = @_; delete $MODULE_PARAMS{$self}; $self->SUPER::DESTROY() if $self->can('SUPER::DESTROY'); return; } 1; } # --- END Cpanel/HTTP/Client.pm { # --- BEGIN Cpanel/SecureDownload.pm package Cpanel::SecureDownload; use strict; use warnings; no warnings 'once'; sub fetch_url { my ( $url, %opts ) = @_; my @methods = ( [ 'Cpanel::HTTP::Client' => \&_try_with_http_client ], [ 'curl' => \&_try_with_curl ], [ 'wget' => \&_try_with_wget ] ); my $all_errors; foreach my $method (@methods) { my ( $name, $sub ) = @{$method}; local $@; my $contents = eval { $sub->( $url, %opts ); }; return ( 1, $contents ) if !$@; my $error = "Failed to fetch using $name: $@"; $all_errors .= $error . "\n"; } return ( 0, $all_errors ); } sub _try_with_http_client { my ( $url, %opts ) = @_; die "Cpanel::HTTP::Client unavailable during initial install" if $ENV{'CPANEL_BASE_INSTALL'}; require Cpanel::HTTP::Client; my $http = Cpanel::HTTP::Client->new()->die_on_http_error(); $http->timeout( $opts{'timeout'} ) if exists $opts{'timeout'}; my $content = $http->get($url)->content(); return $content unless exists $opts{'output-file'}; my $temp_file = $opts{'output-file'} . '.' . time . '.temp'; open my $fh, '>', $temp_file or die "Unable to open $temp_file: $!"; print {$fh} $content; close $fh; unlink $opts{'output-file'} if -e $opts{'output-file'}; rename $temp_file, $opts{'output-file'}; return 1; } sub _try_with_curl { my ( $url, %opts ) = @_; my $curl_bin = _find_curl_bin(); die "Unable to find curl" unless $curl_bin; my @cmd_args = _build_curl_cmd_line( $url, %opts ); return _execute_download_tool( $curl_bin, @cmd_args ); } sub _try_with_wget { my ( $url, %opts ) = @_; my $wget_bin = _find_wget_bin(); die "Unable to find wget" unless $wget_bin; my @cmd_args = _build_wget_cmd_line( $url, %opts ); return _execute_download_tool( $wget_bin, @cmd_args ); } sub _get_mozilla_ca_file { my $ca_file = eval { require # Cpanel::Static OK - inside an eval Mozilla::CA; Mozilla::CA::SSL_ca_file(); }; return if $@; return unless -e $ca_file; return $ca_file; } sub _find_curl_bin { for my $bin (qw(/usr/bin/curl /bin/curl /usr/local/bin/curl)) { next if ( !-e $bin ); next if ( !-x _ ); next if ( -z _ ); return $bin; } return undef; } sub _find_wget_bin { for my $bin (qw(/usr/bin/wget /bin/wget /usr/local/bin/wget)) { next if ( !-e $bin ); next if ( !-x _ ); next if ( -z _ ); return $bin; } return undef; } sub _build_curl_cmd_line { my ( $url, %opts ) = @_; my @cmd_args; if ( exists $opts{'tries'} ) { push @cmd_args, '--retry'; push @cmd_args, $opts{'tries'}; } if ( exists $opts{'retry-delay'} ) { push @cmd_args, '--retry-delay'; push @cmd_args, $opts{'retry-delay'}; } if ( exists $opts{'timeout'} ) { push @cmd_args, '--max-time'; push @cmd_args, $opts{'timeout'}; } if ( exists $opts{'no-check-certificate'} && $opts{'no-check-certificate'} ) { push @cmd_args, '-k'; } else { my $ca_file = _get_mozilla_ca_file(); if ($ca_file) { push @cmd_args, "--cacert"; push @cmd_args, $ca_file; } } push @cmd_args, '--silent'; push @cmd_args, '-o'; push @cmd_args, exists $opts{'output-file'} ? $opts{'output-file'} : '-'; push @cmd_args, $url; return @cmd_args; } sub _build_wget_cmd_line { my ( $url, %opts ) = @_; my @cmd_args; push @cmd_args, '-nv' if exists $opts{'not-verbose'}; push @cmd_args, '--no-dns-cache' if exists $opts{'no-dns-cache'}; push @cmd_args, '--tries=' . $opts{'tries'} if exists $opts{'tries'}; push @cmd_args, '--timeout=' . $opts{'timeout'} if exists $opts{'timeout'}; push @cmd_args, '--dns-timeout=' . $opts{'dns-timeout'} if exists $opts{'dns-timeout'}; push @cmd_args, '--read-timeout=' . $opts{'read-timeout'} if exists $opts{'read-timeout'}; push @cmd_args, '--waitretry=' . $opts{'retry-delay'} if exists $opts{'retry-delay'}; push @cmd_args, '--retry-connrefused' if exists $opts{'retry-connrefused'}; if ( exists $opts{'no-check-certificate'} && $opts{'no-check-certificate'} ) { push @cmd_args, '--no-check-certificate'; } else { my $ca_file = _get_mozilla_ca_file(); if ($ca_file) { push @cmd_args, "--ca-certificate=$ca_file"; } } push @cmd_args, '-O'; push @cmd_args, exists $opts{'output-file'} ? $opts{'output-file'} : '-'; push @cmd_args, $url; return @cmd_args; } sub _execute_download_tool { my ( $bin, @cmd_args ) = @_; if ( _try_load_saferun_object() ) { return _run_with_saferun_object( $bin, @cmd_args ); } elsif ( _try_load_ipc_open3() ) { return _run_with_ipc_open3( $bin, @cmd_args ); } else { die "Unable to find a suitable method to fetch the URL\n"; } return; } sub _try_load_saferun_object { eval { require Cpanel::SafeRun::Object; }; return $@ ? 0 : 1; } sub _try_load_ipc_open3 { eval { require IPC::Open3; }; return $@ ? 0 : 1; } sub _run_with_saferun_object { my ( $bin, @cmd_args ) = @_; my $run = Cpanel::SafeRun::Object->new( program => $bin, args => \@cmd_args, ); if ( !$run ) { die "Failed to invoke $bin binary."; } my $rc = $run->CHILD_ERROR() >> 8; if ( $rc != 0 ) { my $full_command = $bin . ' ' . join ' ', @cmd_args; my $stderr = "Error encountered while running $full_command command: " . $run->stderr(); die $stderr; } my $stdout = $run->stdout(); return $stdout; } sub _run_with_ipc_open3 { my ( $bin, @cmd_args ) = @_; my ( $out_fh, $err_fh ); my $pid = IPC::Open3::open3( undef, $out_fh, $err_fh, $bin, @cmd_args ); waitpid( $pid, 0 ); if ($?) { my $full_command = $bin . ' ' . join ' ', @cmd_args; my $stderr = "Error encountered while running $full_command command: "; while ( my $line = <$err_fh> ) { $stderr .= $line; } die $stderr; } my $stdout; while ( my $line = <$out_fh> ) { $stdout .= $line; } return $stdout; } 1; } # --- END Cpanel/SecureDownload.pm { # --- BEGIN Cpanel/Crypt/GPG/VendorKeys.pm package Cpanel::Crypt::GPG::VendorKeys; use strict; use warnings; no warnings 'once'; # use Cpanel::Crypt::GPG::Import::Temp (); # perlpkg line 211 # use Cpanel::CachedDataStore (); # perlpkg line 211 # use Cpanel::SecureDownload (); # perlpkg line 211 our $VERSION = 1; sub _get_config_file { return '/var/cpanel/gpg/vendorkeys.yaml'; } sub _get_vendor_keys { return Cpanel::CachedDataStore::fetch_ref( _get_config_file() ); } sub _save_vendor_keys { my ($vk_ref) = @_; require File::Basename; my $keydir = File::Basename::dirname( _get_config_file() ); if ( !-d $keydir ) { require Cpanel::SafeDir::MK; Cpanel::SafeDir::MK::safemkdir( $keydir, 0700 ); } return Cpanel::CachedDataStore::savedatastore( _get_config_file(), { mode => 0600, data => $vk_ref } ); } sub set_keys { my (%args) = @_; $args{interval} = defined( $args{interval} ) ? $args{interval} : 86400; # 1 day, in seconds. $args{enabled} = defined( $args{enabled} ) ? $args{enabled} : 1; for my $a (qw{vendor category url keys}) { if ( !$args{$a} ) { return wantarray ? ( undef, "Argument '$a' is required." ) : undef; } } my %new_keys; my @ckeys = ( ref( $args{keys} ) eq 'ARRAY' ) ? @{ $args{keys} } : ( $args{keys} ); my $gpg = Cpanel::Crypt::GPG::Import::Temp->new(); if ( !$gpg ) { return wantarray ? ( undef, "Failed to create GPG object." ) : undef; } for my $ckey (@ckeys) { while ( $ckey =~ /(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----)/gs ) { my $skey = $1; my ( $key_id, $msg ) = $gpg->get_key_id( key => $skey ); if ( !$key_id ) { return wantarray ? ( undef, $msg ) : undef; } $new_keys{$key_id} = $skey; } } if ( !keys %new_keys ) { return wantarray ? ( undef, "No valid keys found." ) : undef; } my $vk_ref = _get_vendor_keys(); $vk_ref->{ $args{vendor} }->{ $args{category} } = { url => $args{url}, keychain => \%new_keys, enabled => $args{enabled}, interval => $args{interval}, noverify => $args{noverify}, last_updated => _get_current_time(), }; $vk_ref->{__VERSION} = $VERSION; if ( _save_vendor_keys($vk_ref) ) { return wantarray ? ( 1, 'Success' ) : 1; } return wantarray ? ( undef, "Failed to save key store." ) : undef; } sub _get_current_time { return int(time); } sub set_keys_from_url { my (%args) = @_; for my $a (qw{vendor category url}) { if ( !$args{$a} ) { return wantarray ? ( undef, "Argument '$a' is required." ) : undef; } } my $url = $args{url}; if ( ( !$args{noverify} ) && ( $url !~ /^https:\/\//i ) ) { return wantarray ? ( undef, "URL must use SSL." ) : undef; } my ( $ret, $download_data ) = Cpanel::SecureDownload::fetch_url( $url, ( 'timeout' => 60, 'no-check-certificate' => $args{noverify} ) ); if ( !$ret ) { return wantarray ? ( undef, $download_data ) : undef; } my ( $success, $msg ) = set_keys( vendor => $args{vendor}, category => $args{category}, url => $args{url}, keys => $download_data, enabled => $args{enabled}, interval => $args{interval}, noverify => $args{noverify}, ); if ( !$success ) { return wantarray ? ( undef, "Failure when adding key: $msg" ) : undef; } return wantarray ? ( 1, "Successfully added key." ) : 1; } sub get_keys { my (%args) = @_; if ( !$args{vendor} ) { return wantarray ? ( undef, "Argument 'vendor' is required." ) : undef; } if ( !( $args{category} || $args{categories} ) ) { return wantarray ? ( undef, "Argument 'category' or 'categories' is required." ) : undef; } if ( $args{category} && $args{categories} ) { return wantarray ? ( undef, "Both argument 'category' and 'categories' can not be used simultaneously." ) : undef; } my $argcat = $args{category} || $args{categories}; my @cats = ( ref($argcat) eq 'ARRAY' ) ? @{$argcat} : ($argcat); my $vk_ref = _get_vendor_keys(); if ( !$vk_ref->{ $args{vendor} } ) { return wantarray ? ( undef, "Keys for vendor '" . $args{vendor} . "' not found." ) : undef; } my %keys; for my $cat (@cats) { if ( !$vk_ref->{ $args{vendor} }->{$cat} ) { next; # skip over non-existent categories } if ( !$vk_ref->{ $args{vendor} }->{$cat}->{enabled} ) { next; # skip over disabled keychains } for my $key ( keys %{ $vk_ref->{ $args{vendor} }->{$cat}->{keychain} } ) { $keys{$key} = $vk_ref->{ $args{vendor} }->{$cat}->{keychain}->{$key}; } } return \%keys; } sub get_key_info { my ($keyid) = @_; my $keys = _get_vendor_keys(); foreach my $vendor ( keys %{$keys} ) { if ( index( $vendor, '__' ) == 0 ) { next; } foreach my $type ( keys %{ $keys->{$vendor} } ) { return ( $vendor, $type ) if grep { $keyid eq $_ } keys %{ $keys->{$vendor}->{$type}->{keychain} }; } } return ( 'UNKNOWN', 'UNKNOWN' ); } sub download_public_keys { my %opts = @_; require Cpanel::Logger; $opts{logger} ||= Cpanel::Logger->new(); my $warn = $opts{logger}->can("warn") ? 'warn' : 'warning'; my $error = $opts{logger}->can("error") ? 'error' : 'warn'; if ( $opts{noverify} ) { $opts{logger}->info("WARNING: Hostname verification is disabled!"); $opts{logger}->info("Can not ensure the legitimacy of downloaded keys."); } my $vk_ref = _get_vendor_keys(); my %update_keys; for my $vendor ( grep { index( $_, '__' ) != 0 } keys %{$vk_ref} ) { for my $category ( keys %{ $vk_ref->{$vendor} } ) { $update_keys{$vendor}->{$category}->{url} = $vk_ref->{$vendor}->{$category}->{url}; $update_keys{$vendor}->{$category}->{noverify} = $vk_ref->{$vendor}->{$category}->{noverify}; } } for my $key ( @{ _get_pubkey_defaults() } ) { my $vendor = $key->{vendor}; my $category = $key->{category}; my $url = $key->{url}; my $noverify = $key->{noverify}; $update_keys{$vendor}->{$category}->{url} = $url; $update_keys{$vendor}->{$category}->{noverify} = $noverify; } my @update_keys_list; for my $vendor ( keys %update_keys ) { for my $category ( keys %{ $update_keys{$vendor} } ) { my $key = { vendor => $vendor, category => $category, url => $update_keys{$vendor}->{$category}->{url}, noverify => $update_keys{$vendor}->{$category}->{noverify}, }; push @update_keys_list, $key; } } my $keys; if ( $opts{keys} ) { $keys = $opts{keys}; } else { $keys = \@update_keys_list; } my $success = 1; for my $key ( @{$keys} ) { my $interval = $vk_ref->{ $key->{vendor} }->{ $key->{category} }->{interval} || 0; my $last_updated = $vk_ref->{ $key->{vendor} }->{ $key->{category} }->{last_updated} || 0; my $current_time = _get_current_time(); next if ( !$opts{force} && defined $vk_ref->{__VERSION} && $vk_ref->{__VERSION} == $VERSION && $current_time <= ( $interval + $last_updated ) && $current_time >= $last_updated ); my ( $succ, $msg ) = set_keys_from_url( vendor => $key->{vendor}, category => $key->{category}, url => $key->{url}, noverify => $key->{noverify} || $opts{noverify}, ); if ($succ) { $opts{logger}->info("Retrieved public key from vendor: $key->{vendor}, category: $key->{category}, url: $key->{url}"); } else { $opts{logger}->$warn("Unable to download public key from vendor: $key->{vendor}, category: $key->{category}, url: $key->{url}"); $opts{logger}->info($msg); $success = 0; } } if ( !$success ) { $opts{logger}->$warn("Failed to download all specified public keys."); } return $success; } sub _get_pubkey_defaults { return [ { url => 'https://securedownloads.cpanel.net/cPanelPublicKey.asc', vendor => 'cpanel', category => 'release', }, { url => 'https://securedownloads.cpanel.net/cPanelDevelopmentKey.asc', vendor => 'cpanel', category => 'development', }, ]; } 1; } # --- END Cpanel/Crypt/GPG/VendorKeys.pm { # --- BEGIN Cpanel/FileUtils/Copy.pm package Cpanel::FileUtils::Copy; use strict; use warnings; no warnings 'once'; # use Cpanel::Fcntl (); # perlpkg line 211 # use Cpanel::Fcntl::Constants (); # perlpkg line 211 # use Cpanel::LoadModule (); # perlpkg line 211 # use Cpanel::Debug (); # perlpkg line 211 our $VERSION = '1.0'; my $COPY_CHUNK_SIZE = 131072; #2 ** 17 sub safecopy { ## no critic qw(Subroutines::ProhibitExcessComplexity) my $srcfile = shift; my $destfile = shift; my $normrfcomp = shift || 0; if ( !length $srcfile ) { Cpanel::Debug::log_warn("Source not specified for copy."); return 0; } if ( !length $destfile ) { Cpanel::Debug::log_warn("Destination not specified for copy."); return 0; } if ( !-r $srcfile && $srcfile !~ m/\*$/ ) { Cpanel::Debug::log_warn("Unable to read source for copy"); return 0; } my $is_file = -f $srcfile ? 1 : 0; my $srcfileinfo = q{}; my $unlinkdestsafe = 1; if ($is_file) { # Logic only for src files (not dirs). $srcfileinfo = join( '-', ( stat(_) )[ 0, 1 ] ); $unlinkdestsafe = 9; } my $src_lock; if ($is_file) { local $@; require Cpanel::SafeFile; $src_lock = eval { Cpanel::SafeFile::safelock_skip_dotlock_if_not_root($srcfile) }; } if ( !exists $INC{'File/Copy/Recursive.pm'} ) { Cpanel::LoadModule::lazy_load_module('File::Copy::Recursive'); } if ( !exists $INC{'Cpanel/Umask.pm'} ) { Cpanel::LoadModule::lazy_load_module('Cpanel::Umask'); } my $usefilecopyrecursive = ( exists $INC{'File/Copy/Recursive.pm'} && exists $INC{'Cpanel/Umask.pm'} ) ? 1 : 0; if ( !$usefilecopyrecursive ) { my $val = system( 'cp', '-rf', $srcfile, $destfile ); if ($is_file) { Cpanel::SafeFile::safeunlock($src_lock) } if ($val) { Cpanel::Debug::log_warn("Problem copying $srcfile to $destfile! : system = $val"); return 0; } return 1; } if ( $srcfileinfo ne '' && -f $destfile ) { my $destfileinfo = join( '-', ( stat(_) )[ 0, 1 ] ); if ( $srcfileinfo eq $destfileinfo ) { # files are the same Cpanel::SafeFile::safeunlock($src_lock) if $is_file; Cpanel::Debug::log_info("safecopy for $srcfile -> $destfile skipped. Target exists and has same size and inode number."); return 1; } if ( $unlinkdestsafe == 9 && !unlink($destfile) ) { $unlinkdestsafe = 0; } else { $unlinkdestsafe = 1; } } else { $unlinkdestsafe = 1; } { no warnings; $File::Copy::Recursive::RMTrgFil = $unlinkdestsafe; } if ( !$normrfcomp ) { $File::Copy::Recursive::CPRFComp = 1; } else { $File::Copy::Recursive::CPRFComp = 0; } undef $!; my $umask_obj = Cpanel::Umask->new(077); if ( File::Copy::Recursive::rcopy( $srcfile, $destfile ) ) { if ( $is_file && $src_lock ) { Cpanel::SafeFile::safeunlock($src_lock) } return 1; } else { my $err_msg; my $err_no; if ($!) { $err_no = int $!; $err_msg = "$!"; } else { $err_no = 85; $err_msg = 'Unknown copy failure'; } if ( $is_file && $src_lock ) { Cpanel::SafeFile::safeunlock($src_lock); } Cpanel::Debug::log_warn(qq{rcopy('$srcfile', '$destfile') failed: $err_msg}); $! = $err_no; ## no critic qw(Variables::RequireLocalizedPunctuationVars) return wantarray ? ( 0, $err_msg ) : 0; } } sub copy { my ( $source, $destination ) = @_; local $!; my ( $rfh, $wfh ); my ( $i_opened_the_source, $i_opened_the_destination ); if ( UNIVERSAL::isa( $source, 'GLOB' ) ) { if ( !fileno $source ) { return ( 0, "The source file handle is not open." ); } elsif ( fcntl( $source, $Cpanel::Fcntl::Constants::F_GETFL, 0 ) & 1 ) { return ( 0, "The source file handle is write-only." ); } $rfh = $source; } else { $i_opened_the_source = 1; open( $rfh, '<', $source ) or do { return ( 0, "The system failed to open the file “$source” for reading because of an error: $!" ); }; } my $buffer; read $rfh, $buffer, $COPY_CHUNK_SIZE or do { if ( length $! ) { return ( 0, "The system failed to read from the file “$source” because of an error: $!" ); } }; my $mode = ( stat $source )[2] & 07777; my $write_lock; if ( UNIVERSAL::isa( $destination, 'GLOB' ) ) { if ( !fileno $destination ) { return ( 0, "The destination file handle is not open." ); } elsif ( !( fcntl( $destination, $Cpanel::Fcntl::Constants::F_GETFL, 0 ) & 1 ) ) { return ( 0, "The destination file handle is read-only." ); } $wfh = $destination; } else { $i_opened_the_destination = 1; local $!; local $@; require Cpanel::SafeFile; $write_lock = eval { Cpanel::SafeFile::safesysopen( $wfh, $destination, Cpanel::Fcntl::or_flags(qw( O_WRONLY O_CREAT )), $mode ) } or do { return ( 0, "The system failed to open the file “$destination” for writing because of an error: " . ( $@ || $! ) ); }; } do { print {$wfh} $buffer or do { return ( 0, "The system failed to write to the file “$destination” because of an error: $!" ); }; } while read $rfh, $buffer, $COPY_CHUNK_SIZE; if ($!) { return ( 0, "The system failed to read from the file “$source” because of an error: $!" ); } truncate( $wfh, tell($wfh) ); if ($!) { return ( 0, "The system failed to truncate the file “$destination” because of an error: $!" ); } if ($i_opened_the_destination) { Cpanel::SafeFile::safeclose( $wfh, $write_lock ) or do { return ( 0, "The system failed to close the file “$destination” because of an error: $!" ); }; } if ($i_opened_the_source) { close $rfh or do { return ( 0, "The system failed to close the file “$source” because of an error: $!" ); }; } return 1; } 1; } # --- END Cpanel/FileUtils/Copy.pm { # --- BEGIN Cpanel/Math.pm package Cpanel::Math; use strict; our $VERSION = '2.0'; my $nonetxt; my $locale; *floatto = *_floatNum; *_toHumanSize = *_real_toHumanSize; *human_format_bytes = *_real_toHumanSize; sub ceil { my $cval = int $_[0]; return ( ( $_[0] - $cval ) > 0 ) ? ( $cval + 1 ) : $cval; } sub floor { return int $_[0]; } sub _floatNum { return sprintf( "%.$_[1]f", $_[0] ); } sub get_none_text { return 'None' if $Cpanel::Parser::Vars::altmode; # WHY DO WE DO THIS? If there is a reason please update this comment to explain return ( $nonetxt = _locale()->maketext('None') ); } sub _real_toHumanSize { if ( !$_[0] && $_[1] ) { return defined $nonetxt ? $nonetxt : get_none_text(); } return _locale()->format_bytes( $_[0] ); } sub roundto { return $_[0] >= $_[2] ? $_[2] : $_[1] * int( ( $_[0] + 0.50000000000008 * $_[1] ) / $_[1] ); } sub divide_with_random_translation { my ( $range, $divisor ) = @_; #“range”, i.e., [ 0 .. $range ] die 'Call in list context!' if !wantarray; ( $_ != int ) && die "Integers only, not “$_”!" for ( $range, $divisor ); if ( $range % $divisor ) { die "Invalid divisor: “$divisor” (must be a factor of $range)!"; #XXX } my $first_tick = int rand $divisor; my $ticks_count = $range / $divisor; return map { $first_tick + $_ * $divisor } ( 0 .. ( $ticks_count - 1 ) ); } sub _locale { return $locale if defined $locale; eval 'require Cpanel::Locale'; return ( $locale = 'Cpanel::Locale'->get_handle() ); } 1; } # --- END Cpanel/Math.pm { # --- BEGIN Cpanel/Parallelizer.pm package Cpanel::Parallelizer; use cPstrict; no warnings 'once'; use Try::Tiny; use IO::Select (); # use Cpanel::FHUtils::Blocking (); # perlpkg line 211 # use Cpanel::AdminBin::Serializer (); # perlpkg line 211 sub new { my ( $class, %self ) = @_; $self{'process_limit'} ||= 25; # Number of simultaneous processes $self{'total_time_limit'} ||= 3600; # Maximum total running time: One hour by default $self{'process_time_limit'} ||= 1800; # Maximum running time for a single child process: 30 minutes by default $self{'running'} = 0; $self{'_processes_'} = { 'running' => [], 'queued' => [], }; $self{'start_time'} = 0; return bless \%self, $class; } sub _set_get { my $self = shift; my $key = shift; my $val = shift; if ( defined $val ) { $self->{$key} = $val; } return $self->{$key}; } sub process_limit { my $self = shift; my $val = shift; return $self->_set_get( 'process_limit', $val ); } sub process_time_limit { my $self = shift; my $val = shift; return $self->_set_get( 'process_time_limit', $val ); } sub total_time_limit { my $self = shift; my $val = shift; return $self->_set_get( 'total_time_limit', $val ); } sub running { my $self = shift; return $self->{'running'}; } sub start_time { my $self = shift; return $self->{'start_time'}; } sub run { my $self = shift; return 1 unless $self->running(); my $now = time(); my $total_time_left = $self->{'total_time_limit'} - ( $now - $self->{'start_time'} ); while ( my $next_process = shift @{ $self->{'_processes_'}{'queued'} } ) { if ( $total_time_left > 0 ) { $self->_reap_one_process(); } $now = time(); $total_time_left = $self->{'total_time_limit'} - ( $now - $self->{'start_time'} ); if ( $total_time_left > 0 ) { $self->_start_process( $next_process, $now ); } else { &{ $next_process->{'error'} }( 'Total execution time exceeded!', @{ $next_process->{'args'} } ); } } while ( $self->_reap_one_process() ) { } $self->{'running'} = 0; return 1; } sub queue { my $self = shift; my $run_coderef = shift; my $args_ar = shift; my $return_coderef = shift; my $error_coderef = shift; my $now = time(); my $process_data = { 'run' => $run_coderef, 'args' => $args_ar, 'return' => $return_coderef, 'error' => $error_coderef, 'pid' => 0, 'spool' => '', 'spool_length' => 0, 'fh' => undef, 'start_time' => 0, }; unless ( $self->running() ) { $self->{'running'} = 1; $self->{'_processes_'}{'running'} = []; $self->{'_processes_'}{'queued'} = []; $self->{'start_time'} = $now; } if ( scalar @{ $self->{'_processes_'}{'running'} } < $self->{'process_limit'} ) { return $self->_start_process( $process_data, $now ); } else { push @{ $self->{'_processes_'}{'queued'} }, $process_data; return 1; } } sub _start_process { my $self = shift; my $process_data = shift; my $now = shift || time(); my ( $pid, $reader_fh, $writer_fh ); pipe( $reader_fh, $writer_fh ); $pid = fork(); if ( !defined $pid ) { close $reader_fh; close $writer_fh; if ( defined $process_data->{'error'} ) { &{ $process_data->{'error'} }( 'Failed to fork!', @{ $process_data->{'args'} } ); } return 0; } elsif ($pid) { close $writer_fh; Cpanel::FHUtils::Blocking::set_non_blocking($reader_fh); $process_data->{'start_time'} = $now; $process_data->{'fh'} = $reader_fh; $process_data->{'pid'} = $pid; my $total_time_left = $self->{'total_time_limit'} - ( $now - $self->{'start_time'} ); my $time_left = $self->{'process_time_limit'} < $total_time_left ? $self->{'process_time_limit'} : $total_time_left; $process_data->{'expires_at'} = $now + $time_left; push @{ $self->{'_processes_'}{'running'} }, $process_data; return 1; } else { close $reader_fh; if ( !$self->{'keep_stdout_open'} ) { open STDOUT, '>', '/dev/null' or warn "Failed to redirect STDOUT to /dev/null: $!"; } eval { my @return = &{ $process_data->{'run'} }( @{ $process_data->{'args'} } ); print $writer_fh Cpanel::AdminBin::Serializer::Dump( \@return ); close $writer_fh; exit 0; }; warn; exit 1; } } sub _reap_one_process { my $self = shift; my $read_count; return 0 unless ( $self->running() ); my $now; my $select_set = IO::Select->new(); foreach my $proc ( @{ $self->{'_processes_'}{'running'} } ) { $select_set->add( $proc->{'fh'} ); } while ( scalar @{ $self->{'_processes_'}{'running'} } ) { $now = time(); for ( my $x = 0; $x <= $#{ $self->{'_processes_'}{'running'} }; $x++ ) { my $process_data = $self->{'_processes_'}{'running'}[$x]; while ( $read_count = sysread( $process_data->{'fh'}, $process_data->{'spool'}, 4096, $process_data->{'spool_length'} ) ) { $process_data->{'spool_length'} += $read_count; } if ( defined $read_count ) { local $?; my $reaped = waitpid( $process_data->{'pid'}, 1 ); if ( $reaped == $process_data->{'pid'} ) { close $process_data->{'fh'}; if ( $? != 0 ) { if ( defined $process_data->{'error'} ) { &{ $process_data->{'error'} }( 'Exited with code ' . ( $? >> 8 ) . ' and signal ' . ( $? & 127 ), @{ $process_data->{'args'} } ); } } else { my @return; eval { @return = @{ Cpanel::AdminBin::Serializer::Load( $process_data->{'spool'} ) }; }; if ($@) { if ( defined $process_data->{'error'} ) { &{ $process_data->{'error'} }( "Could not make sense of returned data ($process_data->{'spool'}) - $@", @{ $process_data->{'args'} } ); } } elsif ( defined $process_data->{'return'} ) { &{ $process_data->{'return'} }(@return); } } splice( @{ $self->{'_processes_'}{'running'} }, $x, 1 ); return 1; } elsif ( $reaped == -1 ) { if ( defined $process_data->{'error'} ) { &{ $process_data->{'error'} }( 'Child disappeared during processing', @{ $process_data->{'args'} } ); } splice( @{ $self->{'_processes_'}{'running'} }, $x, 1 ); return 1; } } if ( $process_data->{'expires_at'} <= $now ) { kill 'KILL', $process_data->{'pid'}; local $?; waitpid( $process_data->{'pid'}, 0 ); if ( defined $process_data->{'error'} ) { &{ $process_data->{'error'} }( 'Timed Out', @{ $process_data->{'args'} } ); } splice( @{ $self->{'_processes_'}{'running'} }, $x, 1 ); return 1; } } $select_set->can_read(0.2); } return 0; } sub jobs_count { my $self = shift; return $self->active_count() + $self->queued_count(); } sub active_count { my $self = shift; return scalar @{ $self->{'_processes_'}{'running'} }; } sub queued_count { my $self = shift; return scalar @{ $self->{'_processes_'}{'queued'} }; } sub get_operations_per_process { my ( $self, $total_operations ) = @_; require Cpanel::Math; return Cpanel::Math::ceil( $total_operations / $self->process_limit() ); } sub pmap ( $code, @list ) { my $run_cb = sub { local $_ = shift; return $code->(); }; my $parallelizer = Cpanel::Parallelizer->new(); my $lim = scalar(@list); $lim = $lim < 20 ? $lim : 20; $parallelizer->process_limit($lim); my @ret; my $ret_cb = sub { push( @ret, @_ ); }; my $err_cb = sub { }; foreach my $x (@list) { $parallelizer->queue( $run_cb, [$x], $ret_cb, $err_cb ); } $parallelizer->run(); return @ret; } 1; } # --- END Cpanel/Parallelizer.pm { # --- BEGIN Cpanel/FileUtils/Link.pm package Cpanel::FileUtils::Link; use strict; use warnings; no warnings 'once'; # use Cpanel::Debug (); # perlpkg line 211 sub safeunlink { my $file = shift; return 1 if !-l $file && !-e _; if ( unlink $file ) { return 1; } else { Cpanel::Debug::log_warn("Unable to unlink $file: $!"); return; } } sub _replicate_file { my $orig = shift; my $dest = shift; my ( $mode, $uid, $gid, $atime, $mtime ) = ( stat($orig) )[ 2, 4, 5, 8, 9 ]; $mode = $mode & 07777; return 0 if ( !-e _ ); return 0 unless ( -r _ || -w _ || -x _ ); require Cpanel::SafeFile; my $ori_fh; my $dest_fh; open( $ori_fh, '<', $orig ) || return 0; my $destlock = Cpanel::SafeFile::safeopen( $dest_fh, '>', $dest ) || do { Cpanel::Debug::log_warn("Unable to open $dest for write!"); close($ori_fh); return 0; }; while (<$ori_fh>) { print {$dest_fh} $_; } close($ori_fh); Cpanel::SafeFile::safeclose( $dest_fh, $destlock ); if ( -z $orig != -z $dest ) { unlink($dest); Cpanel::Debug::log_warn("Unable to properly write $dest"); return 0; } unless ( chown( $uid, $gid, $dest ) ) { Cpanel::Debug::log_warn("Unable to chown $dest to UID $uid GID $gid"); } unless ( chmod( $mode, $uid, $dest ) ) { Cpanel::Debug::log_warn("Unable to chmod $dest for UID $uid"); } unless ( utime( $atime, $mtime, $dest ) ) { Cpanel::Debug::log_warn("Unable to set utime on $dest for UID $uid"); } return 1; } sub safelink { my $orig = shift; my $dest = shift; return 0 if ( $orig eq '' || $dest eq '' || !-e $orig ); return 0 unless ( -r $orig || -w $orig || -x $orig ); if ( !link( $orig, $dest ) ) { return _replicate_file( $orig, $dest ); } return 1; } sub forced_symlink { my ( $target, $file ) = @_; my $current_target = readlink($file); if ($current_target) { return 1 if $current_target eq $target; unlink($file); } return symlink( $target, $file ); } sub find_symlink_in_path { my ($path) = @_; my @split_path = split m{/}, $path; my $test_path = q{}; while (@split_path) { my $path_node = shift @split_path; next if !length $path_node; $test_path .= "/$path_node"; return $test_path if -l $test_path; last if !-e _; } return; } 1; } # --- END Cpanel/FileUtils/Link.pm { # --- BEGIN Cpanel/RPM/Versions/File/YAML.pm package Cpanel::RPM::Versions::File::YAML; use strict; use warnings; no warnings 'once'; use YAML::Syck (); BEGIN { $YAML::Syck::LoadBlessed = 0; $YAML::Syck::SortKeys = 1; } sub supported_file_format { my ($self) = @_; my $supported_file_format = 2; return $supported_file_format; } sub new { my ( $class, $args ) = @_; my $self = $class->init($args); bless $self, $class; $self->_loadfile(); return $self; } sub init { my ( $class, $args ) = @_; my $self = { yaml_file => $args->{'file'}, }; return $self; } sub _loadfile { my ($self) = @_; my $file = $self->yaml_file(); if ( !-e $file || -z _ ) { $self->{'data'} = {}; return 0; } eval { $self->{'data'} = YAML::Syck::LoadFile($file) }; if ($@) { die "Unable to load $file: $@"; } if ( !exists $self->{'data'}->{'file_format'}{'version'} || $self->{'data'}->{'file_format'}{'version'} != $self->supported_file_format() ) { die( 'Incorrect file format version in ' . $file ); } return scalar keys %{ $self->{'data'} }; } sub yaml_file { my ($self) = @_; return $self->{'yaml_file'}; } sub fetch { my ( $self, $args ) = @_; return if ( !keys %{ $self->{'data'} } ); my $section = $args->{'section'}; my $key = $args->{'key'}; if ($key) { return $self->{'data'}->{$section}->{$key}; } else { return $self->{'data'}->{$section} || {}; } } sub set { my ( $self, $args ) = @_; my $section = $args->{'section'}; my $key = $args->{'key'}; my $value = $args->{'value'}; if ( ref $key eq 'ARRAY' ) { $self->{'data'}->{$section} = {} if ( ref $self->{'data'}->{$section} ne 'HASH' ); _build_hash( $key, $self->{'data'}->{$section}, $value ); return $self->{'data'}->{$section}; } return $self->{'data'}->{$section}->{$key} = $value; } sub delete { my ( $self, $args ) = @_; return if ( !keys %{ $self->{'data'} } ); my $section = $args->{'section'}; my $key = $args->{'key'}; if ( ref $key eq 'ARRAY' ) { _delete_hash( $key, $self->{'data'}->{$section} ); return; } return delete $self->{'data'}->{$section}->{$key}; } sub visit_section { my ( $self, $section, $coderef ) = @_; foreach my $key ( keys %{ $self->{'data'}->{$section} } ) { $coderef->( $key, $self->{'data'}->{$section}->{$key} ); } } sub visit_all { my ( $self, $coderef ) = @_; foreach my $section ( keys %{ $self->{'data'} } ) { foreach my $key ( keys %{ $self->{'data'}->{$section} } ) { $coderef->( $section, $key, $self->{'data'}->{$section}->{$key} ); } } } sub save { my ($self) = @_; if ( !%{ $self->{'data'} } ) { return; } if ( !exists $self->{'data'}{'file_format'} ) { $self->{'data'}{'file_format'}{'version'} = $self->supported_file_format(); } return YAML::Syck::DumpFile( $self->yaml_file(), $self->{'data'} ); } sub _build_hash { my ( $keys, $hash_accumulator, $value ) = @_; while (@$keys) { my $key = shift @$keys; if ( ref $hash_accumulator->{$key} ne 'HASH' ) { $hash_accumulator->{$key} = @$keys ? {} : $value; } $hash_accumulator = $hash_accumulator->{$key}; } return; } sub _delete_hash { my ( $keys, $hash_accumulator ) = @_; while (@$keys) { my $key = shift @$keys; if ( !@$keys ) { if ( ref $hash_accumulator eq 'HASH' ) { delete $hash_accumulator->{$key}; return; } } $hash_accumulator = $hash_accumulator->{$key}; } return; } 1; } # --- END Cpanel/RPM/Versions/File/YAML.pm { # --- BEGIN Cpanel/Update/Config.pm package Cpanel::Update::Config; use cPstrict; no warnings 'once'; # use Cpanel::Config::LoadConfig (); # perlpkg line 211 our $VERSION = '2.1'; our $cpanel_update_conf = '/etc/cpupdate.conf'; use constant DEFAULT_TIER => 'release'; sub _default_preferences { return { 'CPANEL' => DEFAULT_TIER, 'RPMUP' => 'daily', 'SARULESUP' => 'daily', 'UPDATES' => 'daily', 'STAGING_DIR' => '/usr/local/cpanel', }; } sub valid_keys { return [qw/CPANEL RPMUP SARULESUP UPDATES STAGING_DIR/]; } sub load { my $default_rUPCONF = _default_preferences(); if ( ${^GLOBAL_PHASE} && ${^GLOBAL_PHASE} eq 'START' && lc($0) ne '-e' ) { die q[FATAL: load is called during compile time. You should postpone this call.]; } if ( !-e $cpanel_update_conf ) { save($default_rUPCONF); return wantarray ? %{$default_rUPCONF} : $default_rUPCONF; } my $rUPCONF = Cpanel::Config::LoadConfig::loadConfig($cpanel_update_conf); my $changed = sanitize($rUPCONF); foreach my $key ( keys %{$default_rUPCONF} ) { if ( !exists $rUPCONF->{$key} ) { $changed++; $rUPCONF->{$key} = $default_rUPCONF->{$key}; } } save($rUPCONF) if $changed; return wantarray ? %{$rUPCONF} : $rUPCONF; } sub sanitize ( $conf_ref = undef, $die_on_failure = undef ) { return if ref $conf_ref ne 'HASH'; my $changed = 0; my $valid_keys = valid_keys(); foreach my $key ( keys %{$conf_ref} ) { if ( !grep { $key eq $_ } @$valid_keys ) { delete $conf_ref->{$key}; $changed++; next; } my $value = $conf_ref->{$key}; if ($value) { $changed++ if ( $value =~ s/[\n\r]//g ); # Strip newline chars $changed++ if ( $value =~ s/^\s+// ); # Strip leading whitespace $changed++ if ( $value =~ s/\s+$// ); # Strip trailing whitespace $changed++ if ( $value ne '/' and $value =~ s{/+$}{} ); # Strip trailing slash. This is for STAGING_DIR but nothing else should have a slash in its value. if ( $key ne 'STAGING_DIR' ) { $changed++ if ( $value =~ tr/A-Z/a-z/ ); } if ( $key eq 'CPANEL' ) { my $new_value = _normalize_version($value); # Automatically add the 11 or strip the v when existing if ( $new_value ne $value ) { $value = $new_value; $changed++; } } } if ( $key eq 'STAGING_DIR' and not validate_staging_dir( $value, $die_on_failure ) ) { $value = _default_preferences()->{'STAGING_DIR'}; $changed++; # Flag for file save } if ( !defined $value ) { $value = ''; $changed++; } $conf_ref->{$key} = $value; } return $changed; } sub _normalize_version ( $version = undef ) { return if !length $version; my @version_ar = split /\./, $version, 4; if ( scalar @version_ar >= 3 ) { substr( $version_ar[0], 0, 1 ) = "" if rindex( $version_ar[0], "v", 0 ) == 0; # strip the 'v' unshift( @version_ar, '11' ) if @version_ar == 3 && $version_ar[0] != 11; # add the 11 if it's not the tiers format return join( '.', @version_ar ); } return $version; } sub _stat_directory { my $dir = shift; return stat($dir); } sub validate_staging_dir { my ( $value, $die_on_failure ) = @_; my $ulc = '/usr/local/cpanel'; my $ulc_dev = ( _stat_directory($ulc) )[0]; return if not $value; if ( !_is_valid_filepath($value) ) { die "'$value' is not a valid directory path\n" if $die_on_failure; return; } my @stat = _stat_directory($value) or return 1; if ( -e $value && !-d $value ) { die "'$value' exists on the file system, but is not a directory\n" if $die_on_failure; return; } if ( -e $value && ( !-d $value || !( -d $value && -w $value ) ) ) { die "'$value' exists on the file system, but is not a writable directory\n" if $die_on_failure; return; } if ( 0 != $stat[4] ) { die "'$value' exists on the file system, but is not owned by the root user\n" if $die_on_failure; return; } if ( $stat[0] == $ulc_dev && $value ne $ulc ) { die "'$value' is on the same file system as /usr/local/cpanel. Please use /usr/local/cpanel instead.\n" if $die_on_failure; return; } if ( $stat[2] & 022 ) { die "'$value' exists on the file system, but does not have the correct permissions. Directory must not have write permissions for group and non-root users\n" if $die_on_failure; return; } return 1; } sub save { my $conf_ref = shift; my $die_on_failure = shift; return if ref $conf_ref ne 'HASH'; return if ( $> != 0 ); sanitize( $conf_ref, $die_on_failure ); require Cpanel::Config::FlushConfig; if ( my $return = Cpanel::Config::FlushConfig::flushConfig( $cpanel_update_conf, $conf_ref, '=', undef, { 'sort' => 1 } ) ) { return $return; } else { die "Unable to save file, $cpanel_update_conf: $!\n" if $die_on_failure; return; } } sub get_tier { my ($update_config_ref) = @_; if ( !defined $update_config_ref ) { $update_config_ref = load(); } return if ref $update_config_ref ne 'HASH'; return $update_config_ref->{'CPANEL'}; } sub is_permitted { my $key = shift or return; my $up_conf = shift or return; ref $up_conf eq 'HASH' or return; $key = uc($key); # Force key case upper. my $key_value = $up_conf->{$key} or return; return if ( $key eq 'RPMUP' && $ENV{'CPANEL_BASE_INSTALL'} ); return if ( $key_value eq 'never' ); return if ( $ENV{'CPANEL_IS_CRON'} && $key_value eq 'manual' ); return 1; } sub get_update_type { my $rUPCONF = load(); return $rUPCONF->{'UPDATES'}; } sub _is_valid_filepath { my $filepath = shift; return 1 if index( $filepath, '/' ) == 0; # checking for / is the same as file_name_is_absolute return; } 1; } # --- END Cpanel/Update/Config.pm { # --- BEGIN Cpanel/Services/AlwaysInstalled.pm package Cpanel::Services::AlwaysInstalled; use strict; use warnings; no warnings 'once'; use constant SERVICES => ( 'cpanel_php_fpm', 'cpgreylistd', 'cphulkd', 'cpsrvd', 'dnsadmin', 'ipaliases', 'lmtp', 'named', 'queueprocd', 'tailwatchd', ); 1; } # --- END Cpanel/Services/AlwaysInstalled.pm { # --- BEGIN Cpanel/Validate/AnyAllMatcher.pm package Cpanel::Validate::AnyAllMatcher; use cPstrict; no warnings 'once'; sub match { my ( $args, $callback ) = @_; if ( !defined $args ) { require Cpanel::Exception; die Cpanel::Exception::create( 'MissingParameter', 'No parameter value specified.' ); } if ( !defined $callback ) { require Cpanel::Exception; die Cpanel::Exception::create( 'MissingParameter', 'No callback specified.' ); } if ( !ref $args ) { return $callback->($args) ? 1 : 0; } elsif ( ref $args eq 'HASH' ) { my $match = $args->{match} || 'all'; my $items = $args->{items}; if ( $match ne 'any' && $match ne 'all' && $match ne 'none' ) { require Cpanel::Exception; die Cpanel::Exception::create( 'InvalidParameter', 'The “[_1]” parameter must be “[_2]”, “[_3]” or “[_4]” value.', [qw(match any all none)] ); } if ( !$items || ref $items ne 'ARRAY' ) { require Cpanel::Exception; die Cpanel::Exception::create( 'InvalidParameter', 'The “[_1]” parameter must be an array reference.', ["items"] ); } foreach my $item (@$items) { my $bool = $callback->($item); return 1 if $bool && $match eq 'any'; return 0 if $bool && $match eq 'none'; return 0 if !$bool && $match eq 'all'; } return $match eq 'any' ? 0 : 1; } require Cpanel::Exception; die Cpanel::Exception::create( 'InvalidParameter', 'The input parameter must be a string or a hash reference.' ); } 1; } # --- END Cpanel/Validate/AnyAllMatcher.pm { # --- BEGIN Cpanel/StatCache.pm package Cpanel::StatCache; use strict; use warnings; no warnings 'once'; our $VERSION = 0.4; my %STATCACHE; our $USE_LSTAT = 0; sub StatCache_init { } sub cachedmtime { return ( exists $STATCACHE{ $_[0] } ? $STATCACHE{ $_[0] }->[0] : ( $STATCACHE{ $_[0] } = ( $USE_LSTAT && -l $_[0] ? [ ( lstat(_) )[ 9, 7, 10 ] ] : -e $_[0] ? [ ( stat(_) )[ 9, 7, 10 ] ] : [ 0, 0, 0 ] ) )->[0] ); } sub cachedmtime_size { return ( exists $STATCACHE{ $_[0] } ? @{ $STATCACHE{ $_[0] } }[ 0, 1 ] : @{ ( $STATCACHE{ $_[0] } = ( $USE_LSTAT && -l $_[0] ? [ ( lstat(_) )[ 9, 7, 10 ] ] : -e $_[0] ? [ ( stat(_) )[ 9, 7, 10 ] ] : [ 0, 0, 0 ] ) ) }[ 0, 1 ] ); } sub cachedmtime_ctime { return ( exists $STATCACHE{ $_[0] } ? @{ $STATCACHE{ $_[0] } }[ 0, 2 ] : @{ ( $STATCACHE{ $_[0] } = ( $USE_LSTAT && -l $_[0] ? [ ( lstat(_) )[ 9, 7, 10 ] ] : -e $_[0] ? [ ( stat(_) )[ 9, 7, 10 ] ] : [ 0, 0, 0 ] ) ) }[ 0, 2 ] ); } sub clearcache { %STATCACHE = (); return 1; } 1; } # --- END Cpanel/StatCache.pm { # --- BEGIN Cpanel/FindBin.pm package Cpanel::FindBin; use strict; use warnings; no warnings 'once'; use constant _ENOENT => 2; our $VERSION = 1.2; my %bin_cache; my @default_path = qw( /usr/bin /usr/local/bin /bin /sbin /usr/sbin /usr/local/sbin ); sub findbin { ## no critic qw(Subroutines::RequireArgUnpacking) my $binname = shift; return if !$binname; my @lookup_path = get_path(@_); my $nocache = grep( /nocache/, @_ ); if ( !$nocache && exists $bin_cache{$binname} && $bin_cache{$binname} ne '' ) { return $bin_cache{$binname}; } foreach my $path (@lookup_path) { next unless -d $path; $path .= "/$binname"; if ( -e $path ) { if ( -x _ ) { $bin_cache{$binname} = $path unless $nocache; return $path; } else { warn "“$path” exists but is not executable; ignoring.\n"; } } elsif ( $! != _ENOENT() ) { warn "stat($path): $!\n"; } } return; } sub get_path { if ( !$_[0] ) { return @default_path; } elsif ( scalar @_ > 1 ) { my %opts; %opts = @_ if ( scalar @_ % 2 == 0 ); if ( exists $opts{'path'} && ref $opts{'path'} eq 'ARRAY' ) { return @{ $opts{'path'} }; } else { return @_; } } elsif ( ref $_[0] eq 'ARRAY' ) { return @{ $_[0] }; } return @default_path; } 1; } # --- END Cpanel/FindBin.pm { # --- BEGIN Cpanel/CachedCommand/Valid.pm package Cpanel::CachedCommand::Valid; use strict; use warnings; no warnings 'once'; # use Cpanel::StatCache (); # perlpkg line 211 # use Cpanel::Debug (); # perlpkg line 211 sub is_cache_valid { ## no critic qw(Subroutines::ProhibitExcessComplexity) -- needs to be refactored my %OPTS = @_; my ( $datastore_file, $datastore_file_mtime, $datastore_file_size, $binary, $ttl, $mtime, $min_expire_time, $now ) = ( ( $OPTS{'datastore_file'} || '' ), ( $OPTS{'datastore_file_mtime'} || 0 ), ( $OPTS{'datastore_file_size'} || 0 ), ( $OPTS{'binary'} || '' ), ( $OPTS{'ttl'} || 0 ), ( $OPTS{'mtime'} || 0 ), ( $OPTS{'min_expire_time'} || 0 ), ( $OPTS{'now'} || 0 ) ); if ( !$datastore_file_mtime && !-e $datastore_file ) { print STDERR "is_cache_valid: rejecting $datastore_file because it does not exist.\n" if $Cpanel::Debug::level; return 0; } if ( !$datastore_file_size || !$datastore_file_mtime ) { ( $datastore_file_size, $datastore_file_mtime ) = ( stat(_) )[ 7, 9 ]; } if ( $datastore_file_mtime <= 0 ) { print STDERR "is_cache_valid: rejecting $datastore_file as mtime is zero.\n" if $Cpanel::Debug::level; return 0; } if ($binary) { if ( substr( $binary, 0, 1 ) ne '/' ) { require Cpanel::FindBin; $binary = Cpanel::FindBin::findbin( $binary, split( /:/, $ENV{'PATH'} ) ); } my ( $binary_mtime, $binary_ctime ) = Cpanel::StatCache::cachedmtime_ctime($binary); if ( ( $binary_mtime && $binary_mtime > $datastore_file_mtime ) || ( $binary_ctime && $binary_ctime > $datastore_file_mtime ) ) { if ($Cpanel::Debug::level) { print STDERR "is_cache_valid: rejecting $datastore_file as binary ($binary) ctime or mtime is newer.\n"; print STDERR "is_cache_valid: datastore_file:$datastore_file mtime[$datastore_file_mtime]\n"; print STDERR "is_cache_valid: binary_file:$binary mtime[$binary_mtime] ctime[$binary_ctime]\n"; } return 0; } } $now ||= time(); if ( $datastore_file_mtime > $now ) { print STDERR "is_cache_valid: rejecting $datastore_file as it is from the future (time warp safety).\n" if $Cpanel::Debug::level; return 0; } elsif ( $min_expire_time && $datastore_file_mtime > ( $now - $min_expire_time ) ) { print STDERR "is_cache_valid: accept $datastore_file (mtime=$datastore_file_mtime) as min_expire_time ($now - $min_expire_time) is older.\n" if $Cpanel::Debug::level; return 1; } elsif ( $mtime > $datastore_file_mtime ) { print STDERR "is_cache_valid: rejecting $datastore_file because mtime ($mtime) is newer then datastore mtime ($datastore_file_mtime).\n" if $Cpanel::Debug::level; return 0; } elsif ( $ttl && ( $datastore_file_mtime + $ttl ) < $now ) { print STDERR "is_cache_valid: rejecting $datastore_file as it has reached its time to live.\n" if $Cpanel::Debug::level; return 0; } print STDERR "is_cache_valid: accepting $datastore_file as it passes all tests.\n" if $Cpanel::Debug::level; return 1; } 1; } # --- END Cpanel/CachedCommand/Valid.pm { # --- BEGIN Cpanel/CachedCommand/Save.pm package Cpanel::CachedCommand::Save; use strict; use warnings; no warnings 'once'; # use Cpanel::CachedCommand::Utils (); # perlpkg line 211 # use Cpanel::FileUtils::Write (); # perlpkg line 211 # use Cpanel::Debug (); # perlpkg line 211 # use Cpanel::Exception (); # perlpkg line 211 use Try::Tiny; sub _savefile { my ( $filename, $content ) = @_; return if !defined $content; #should be able to store 0 $filename =~ tr{/}{}s; # collapse //s to / my @path = split( /\//, $filename ); my $file = pop(@path); my $dir = join( '/', @path ); my $dir_uid = ( stat($dir) )[4]; if ( !defined $dir_uid ) { Cpanel::Debug::log_warn("Unable to write datastore file: $filename: target directory: $dir does not exist."); return; } elsif ( $dir_uid != $> ) { Cpanel::Debug::log_warn("Unable to write datastore file: $filename: target directory: $dir does not match uid $>"); return; } local $!; my $ret; try { $ret = Cpanel::FileUtils::Write::overwrite( $filename, ( ref $content ? $$content : $content ), 0600 ); } catch { my $err = $_; Cpanel::Debug::log_warn( Cpanel::Exception::get_string($err) ); }; return $ret; } sub store { my %OPTS = @_; _savefile( Cpanel::CachedCommand::Utils::_get_datastore_filename( $OPTS{'name'} ), $OPTS{'data'} ); } 1; } # --- END Cpanel/CachedCommand/Save.pm { # --- BEGIN Cpanel/SafeRun/Env.pm package Cpanel::SafeRun::Env; use strict; # use Cpanel::Env (); # perlpkg line 211 # use Cpanel::Debug (); # perlpkg line 211 our $VERSION = '1.0'; sub saferun_r_cleanenv { return saferun_cleanenv2( { 'command' => \@_, 'return_ref' => 1, 'cleanenv' => { 'http_purge' => 1 } } ); } sub saferun_cleanenv2 { my $args_hr = shift; return unless ( defined $args_hr->{'command'} && ref $args_hr->{'command'} eq 'ARRAY' ); if ($Cpanel::AccessIds::ReducedPrivileges::PRIVS_REDUCED) { # PPI NO PARSE -- can't be reduced if the module isn't loaded die __PACKAGE__ . " cannot be used with ReducedPrivileges. Use Cpanel::SafeRun::Object instead"; } my @command = @{ $args_hr->{'command'} }; my $return_reference = $args_hr->{'return_ref'}; my $error_output = $args_hr->{'errors'}; my %cleanenv_args = defined $args_hr->{'cleanenv'} && ref $args_hr->{'cleanenv'} eq 'HASH' ? %{ $args_hr->{'cleanenv'} } : (); my $check_cpanel_homedir_user = defined $args_hr->{'check_cpanel_homedir_user'} ? $args_hr->{'check_cpanel_homedir_user'} : 1; return if ( substr( $command[0], 0, 1 ) eq '/' && !-x $command[0] ); my $output; if ( !@command ) { Cpanel::Debug::log_warn('Cannot execute a null program'); return \$output if $return_reference; return $output; } require Cpanel::Env; local ( $/, *PROG, *RNULL ); no strict 'refs'; open( RNULL, '<', '/dev/null' ); ## no critic(InputOutput::ProhibitBarewordFileHandles InputOutput::RequireCheckedOpen) my $pid = open( PROG, "-|" ); ## no critic(InputOutput::ProhibitBarewordFileHandles) if ( $pid > 0 ) { $output =}; $method eq 'print' ? print $txt : return $txt; } else { $method eq 'print' ? print qq{$statusdata...} : return qq{$statusdata...}; } return ''; } sub setstatusdone { Cpanel::LoadModule::load_perl_module('Cpanel::MagicRevision') if !$INC{'Cpanel/MagicRevision.pm'}; return _end_status_block( "Done", Cpanel::MagicRevision::calculate_magic_url( '/cjt/images/icons/success.png', $ENV{'REQUEST_URI'}, '/usr/local/cpanel/whostmgr/docroot' ) ); } sub setstatuserror { Cpanel::LoadModule::load_perl_module('Cpanel::MagicRevision') if !$INC{'Cpanel/MagicRevision.pm'}; return _end_status_block( "Failed", Cpanel::MagicRevision::calculate_magic_url( '/cjt/images/icons/error.png', $ENV{'REQUEST_URI'}, '/usr/local/cpanel/whostmgr/docroot' ) ); } sub _end_status_block { my ( $msg, $img ) = @_; local $| = 1; $status_block_depth--; if ( !$nohtml && !( -t STDOUT || !defined $ENV{'GATEWAY_INTERFACE'} || $ENV{'GATEWAY_INTERFACE'} !~ /CGI/i ) ) { my $txt = qq{...$msg