opt
/
kaspersky
/
kav4fs
/
lib
/
perl
/
KL
➕ New
📤 Upload
✎ Editing:
AppBase.pm
← Back
package KL::AppBase; use strict; use KL::AppInfo; use KL::Utils; use Getopt::Long; use POSIX qw(strftime); my $ENV_AUTO_INSTALL_FILE = 'KLI_AUTO_INSTALL_FILE'; my $ENV_AUTO_INSTALL_SAVE = 'KLI_AUTO_INSTALL_SAVE'; ### Text strings BEGIN ### #--- my $HEADER_SHOW_EULA = <<EOT; Accepting the End User License Agreement (EULA) EOT my $MSG_SHOW_EULA_BEGIN = <<EOT; Please read and accept the End User License Agreement (EULA) to continue. EOT my $MSG_SHOW_EULA_HOWTO_QUIT = <<EOT; <B>NOTE:</B> To quit the EULA viewer, press the "q" key. EOT my $MSG_SHOW_EULA_END = <<EOT; Press Enter to display it. EOT my $MSG_SHOW_EULA_ERROR = <<EOT; Couldn\'t display the EULA file %1: %2. EOT my $MSG_SHOW_EULA_QUESTION = <<EOT; Do you accept EULA? (yes/no) EOT my $MSG_SHOW_EULA_NOT_ACCEPTED = <<EOT; EULA was not accepted. EOT #--- my $HEADER_INSTALL_KEY = <<EOT; Installing the license EOT my $MSG_INSTALL_KEY_ENTER_PATH = <<EOT; The key file (a file with the .key extension) contains information about your license. You need to install it to use the application. To install it now, enter the path to your key file (or enter an empty string to continue without installing the key file): EOT my $MSG_INSTALL_KEY_ENTER_OTHER_PATH = <<EOT; Enter another path to your key file (or enter an empty string to continue without installing the key file): EOT my $MSG_INSTALL_OPENDIR_FAILED = <<EOT; Could not open the %1 directory: %2. EOT my $MSG_INSTALL_KEY_SUCCESS = <<EOT; The license from %1 has been installed. EOT my $MSG_INSTALL_KEY_FAILED = <<EOT; The license from %1 could not be installed: %2 EOT my $MSG_INSTALL_KEY_REJECTED = <<EOT; The %1 key file was rejected because it is not suitable for this application: %2 EOT my $MSG_INSTALL_KEY_INVALID_PATH = <<EOT; The specified path is incorrect. EOT my $MSG_INSTALL_KEY_NO_VALID_FOUND = <<EOT; None of the found key files is correct for this application. EOT my $MSG_INSTALL_KEY_NO_KEYS_FOUND = <<EOT; No key files (files with the .key extension) were found in the %1 directory. EOT #--- my $HEADER_SETUP_PROXY = <<EOT; Configuring the proxy settings to connect to the updates source EOT my $MSG_SET_HTTP_PROXY = <<EOT; If you use an HTTP proxy server to access the Internet, you need to specify its address to allow the application to connect to the updates source. Please enter the address of your HTTP proxy server in one of the following formats: proxyIP:port or user:pass\@proxyIP:port. If you don\'t have or need a proxy server to access the Internet, enter 'no' here, or enter 'skip' to use current settings without changes. EOT my $MSG_SET_PROXY_UPDATED = <<EOT; Proxy settings is set to '%1' EOT #--- my $HEADER_SETUP_AUTOUPDATES = <<EOT; Enabling scheduled updates of the application databases EOT my $MSG_SET_AUTOUPDATES = <<EOT; Would you like to enable scheduled updates? EOT my $MSG_SET_AUTOUPDATES_SUCCESS = <<EOT; Scheduled updates are enabled successfully. %1 EOT my $MSG_SET_AUTOUPDATES_FAILED = <<EOT; An error occurred while enabling scheduled updates: %1. EOT #--- my $HEADER_DOWNLOAD_BASES = <<EOT; Downloading the latest application databases EOT my $MSG_RUN_UPDATER = <<EOT; The latest databases are an essential part of your server protection. Would you like to download the latest databases now? (If you answer 'yes', make sure you are connected to the Internet): EOT my $MSG_NOT_CONFIGURED_NOTICE = <<EOT; <B>%1</B> has been installed successfully, but it must be properly configured before using. Please run <B>%2</B> script manually to configure it. EOT my $MSG_AI_EXECUTED_INFO = <<EOT; Executing automatic installation using parameters from file '%1' EOT my $MSG_AI_LOAD_FAILED = <<EOT; Cannot read parameters of automatic installation from file '%1' EOT my $MSG_AI_SAVE_FAILED = <<EOT; Cannot write automatic installation parameter %1=%2 to file %3: %4 EOT my $MSG_AI_VALIDATION_FAILED = <<EOT; Automatic installation failed, invalid values found. EOT my $MSG_AI_INSTALLATION_CANCELED = <<EOT; Automatic installation is canceled. EOT my $MSG_CMD_HELP_POSTINSTALL = "--postinstall\tperform post-install configuration (default)"; my $MSG_CMD_HELP_AUTOINSTALL = "--auto-install=<file>\tperform automatic post-install configuration using values from file"; my $MSG_CMD_HELP_HELP = "-h, --help\tshow usage syntax"; ### Text strings END ### sub new { my $class = shift; my $appid = shift; my $self = { 'SETTINGS' => {}, 'OPTIONS' => {}, 'DEFAULT_COMMAND' => 'postinstall', }; $self->{'COMMANDS'} = [ { 'id' => 'postinstall', 'spec' => 'postinstall', 'sub' => 'do_postinstall', 'descr' => $MSG_CMD_HELP_POSTINSTALL, }, { 'id' => 'autoinstall', 'spec' => 'auto-install=s', 'sub' => 'auto_install', 'descr' => $MSG_CMD_HELP_AUTOINSTALL, }, { 'id' => 'trigger', 'spec' => 'trigger=s', 'sub' => 'do_trigger', }, { 'id' => 'upgrade', 'spec' => 'upgrade', }, { 'id' => 'debug', 'spec' => 'd|debug', }, { 'id' => 'help', 'spec' => 'help', 'sub' => 'do_show_help', 'default' => undef, 'descr' => $MSG_CMD_HELP_HELP, }, ]; $self->{'AUTOINSTALL'} = []; $self->{APPINFO} = new KL::AppInfo($appid); KL::Utils::fatal(2, "Cannot read info file for application ID '%1'", $appid) if !defined $self->{APPINFO}->{VALUES}; bless $self, $class; $self->{'SETUP'} = undef; $self->{'TITLE'} = $self->get_name_version(); return $self; } sub appinfo { my $self = shift; return $self->{APPINFO}->value(@_); } sub get_path { my $self = shift; my $name = shift; return $self->{APPINFO}->value('paths', $name); } sub get_name_version { my $self = shift; my $title = $self->appinfo('product', 'title') . ' version ' . $self->appinfo('product', 'version') . '/' . $self->appinfo('product', 'release'); } sub get_applog_path { my $self = shift; return $self->get_path('logs') . "/install.log"; } sub applog { my $self = shift; my $message = shift; my $logfile = $self->get_applog_path(); my $stamp = strftime('[%d/%m/%y %H:%M:%S]', localtime); my @lines = split /\n/, $message; foreach (@lines) { $_ = "$stamp $_"; } $message = join("\n", @lines) . "\n"; if ( open F, ">>$logfile" ) { print F $message; close F; } else { print STDERR "LOG: $message"; } } sub options { my $self = shift; my $name = shift; my $value = shift; if (defined $value) { $self->{OPTIONS}->{$name} = $value; } return $self->{OPTIONS}->{$name}; } sub settings { my $self = shift; my $name = shift; my $value = shift; if (defined $value) { $self->{SETTINGS}->{''}->{$name} = $value; $self->save_settings(); KL::Utils::debug("AppBase::settings('$name','$value')"); } else { $value = $self->{SETTINGS}->{''}->{$name}; KL::Utils::debug("AppBase::settings('$name') = '$value'"); } return $value; } sub remove_settings { my $self = shift; while (@_) { my $name = shift; delete $self->{SETTINGS}->{''}->{$name}; } $self->save_settings(); } sub load_settings { my $self = shift; my $filename = $self->get_path('var'); $self->{'SETTINGS'} = {}; return if $filename eq ''; $filename .= '/installer.dat'; return 1 if ! -f $filename; my $data = KL::Utils::load_ini_file($filename); if (defined $data) { $self->{'SETTINGS'} = $data ; return 1; } return 0; } sub save_settings { my $self = shift; my $filename = $self->get_path('var'); return if $filename eq ''; $filename .= '/installer.dat'; return KL::Utils::save_ini_file($filename, $self->{'SETTINGS'}); } sub show_EULA { my $self = shift; my $eula_file = shift; my $eula_agreed = $self->settings('EULA_AGREED'); if ($eula_agreed ne 'yes') { KL::Utils::header ($HEADER_SHOW_EULA); my $pager; my $message = $MSG_SHOW_EULA_BEGIN; if (defined($ENV{'PAGER'})) { $pager = $ENV{'PAGER'}; } else { foreach my $bin ('/usr/bin/less', '/bin/more', '/bin/cat') { if ( -x $bin ) { $pager = $bin; last; } } } if ($pager =~ /less/) { $pager .= ' --quit-at-eof'; $message .= $MSG_SHOW_EULA_HOWTO_QUIT; } elsif ($pager =~ /more/) { $message .= $MSG_SHOW_EULA_HOWTO_QUIT; } $message .= $MSG_SHOW_EULA_END; KL::Utils::ask_question('', $message); my $rc = -1; if (defined $pager) { $rc = system("$pager $eula_file"); } if ($rc != 0) { open(EULA, "<$eula_file") or KL::Utils::fatal(2, $MSG_SHOW_EULA_ERROR, $eula_file, $!); while (<EULA>) { print; } close(EULA); } print "\n"; # this question MUST not have default answer if (KL::Utils::ask_boolean('', $MSG_SHOW_EULA_QUESTION) == 0) { KL::Utils::fatal(2, $MSG_SHOW_EULA_NOT_ACCEPTED, 0); } $self->settings('EULA_AGREED', 'yes'); $self->save_settings(); } $self->ai_save('EULA_AGREED', 'yes'); } ### function to be overloaded in KL::App.pm sub check_key_installed { my $self = shift; KL::Utils::warning("App::check_key_installed(...) is not implemented!"); return (0, "check_key_installed not implemented"); } sub check_key_file { my $self = shift; my $file = shift; KL::Utils::warning("App::check_key_file(...) is not implemented!"); return (0, "check_key_file not implemented"); } sub install_key_file { my $self = shift; my $file = shift; KL::Utils::warning("App::install_key_file(...) is not implemented!"); return (0, "App::install_key_file not implemented"); } sub get_http_proxy { my $self = shift; KL::Utils::warning("App::get_http_proxy(...) is not implemented!"); return (0, "App::get_http_proxy not implemented"); } sub set_http_proxy { my $self = shift; my $value = shift; KL::Utils::warning("App::set_http_proxy(...) is not implemented!"); return (0, "App::set_http_proxy not implemented"); } sub run_updater { my $self = shift; KL::Utils::warning("App::run_updater(...) is not implemented!"); return 0; } sub enable_autoupdates { my $self = shift; KL::Utils::warning("App::enable_autoupdates(...) is not implemented!"); return (0, "App::enable_autoupdates not implemented"); } sub do_auto_install { my $self = shift; KL::Utils::warning("App::do_auto_install(...) is not implemented!"); return 0; } sub do_postinstall { my $self = shift; KL::Utils::warning("App::do_postinstall(...) is not implemented!"); return 0; } sub do_uninstall { my $self = shift; KL::Utils::warning("App::do_uninstall(...) is not implemented!"); return 0; } ### Auto-install subs sub ai_save { my $self = shift; my $name = shift; my $value = shift; return if not defined($ENV{$ENV_AUTO_INSTALL_SAVE}); my $filename = $ENV{$ENV_AUTO_INSTALL_SAVE}; my $values = {}; if ( -f $filename ) { $values = KL::Utils::load_ini_file($filename); } $values->{''}->{$name} = $value; if (!KL::Utils::save_ini_file($filename, $values)) { KL::Utils::warning($MSG_AI_SAVE_FAILED, $name, $value, $filename, $!); } } sub ai_load { my $self = shift; my $filename = shift; $self->{AI_VALUES} = {}; my $values = KL::Utils::load_ini_file($filename); if ($values) { $self->{AI_VALUES} = $values; return 1; } return 0; } sub ai_validate { my $self = shift; my $errors = 0; foreach my $rule (@{$self->{'AUTOINSTALL'}}) { my $id = $rule->{'id'}; my $type = $rule->{'type'}; my $value = $self->ai_value($id); if (defined $value) { my ($res, $error); if (defined $rule->{'list'}) { ($res, $error) = $self->ai_validate_list($rule, $value); next if ($res); } if (defined $type) { my $function = "ai_validate_${type}"; ($res, $error) = $self->$function($rule, $value); next if ($res); } $errors++; KL::Utils::error("'%2' is invalid value for '%1': %3.\n", $id, $value, $error); } else { if (defined($rule->{'required'}) and $rule->{'required'}) { KL::Utils::error("Required parameter '%1' is not set", $id); $errors++; } } } return ($errors == 0) ? 1 : 0; } sub ai_validate_mask { my $self = shift; my $rule = shift; my $value = shift; my $id = $rule->{'id'}; my $mask = $rule->{'mask'}; if ( $value =~ /$mask/) { return 1; } return (0, undef); } sub ai_validate_list { my $self = shift; my $rule = shift; my $value = shift; my $id = $rule->{'id'}; my @list = @{$rule->{'list'}}; foreach my $item (@list) { return 1 if $item eq $value; $item = "'$item'"; } my $valid_list = pop @list; if (scalar(@list)) { $valid_list = join(', ', @list) . ' or ' . $valid_list; } return (0, $valid_list); } sub ai_validate_dir { my $self = shift; my $rule = shift; my $value = shift; if (-d $value) { return 1; } return (0, "is not a path to directory"); } sub ai_validate_file { my $self = shift; my $rule = shift; my $value = shift; if (-f $value) { return 1; } return (0, "is not a path to file"); } sub ai_validate_url { my $self = shift; my $rule = shift; my $value = shift; my $protocol = ''; if ($value =~ /^(\w+):\/\/(.*)$/ ) { $protocol = $1; $value = $2; if ( defined $rule->{'protocols'} ) { if ( not grep(/^${protocol}$/, @{$rule->{'protocols'}}) ) { return (0, "$protocol is not valid protocol"); } } } if ( ($protocol eq '') and defined($rule->{'protocol_requred'}) and $rule->{'protocol_requred'}) { return (0, "protocol must be specified for this URL"); } if ($value =~ /^((.*?)(:(.*?))?@)?(.*?)(:\d+)?/) { return 1; } return (0, "is not valid URL"); } sub ai_value { my $self = shift; my $section = shift; my $name = shift; if (not defined $name) { return $self->{AI_VALUES}->{''}->{$section}; } else { return $self->{AI_VALUES}->{$section}->{$name}; } } sub _ai_error { my $self = shift; my $errorcode = shift; if ($errorcode < 70) { KL::Utils::fatal($errorcode, $MSG_AI_INSTALLATION_CANCELED); } if (not defined $self->{_AI_ERROR}) { $self->{_AI_ERROR} = $errorcode; } } sub auto_install { my $self = shift; my $values = shift; my $file = $values->{'autoinstall'}; KL::Utils::warning($MSG_AI_EXECUTED_INFO, $file); if ( !$self->ai_load($file) ) { KL::Utils::fatal(2, $MSG_AI_LOAD_FAILED, $file); } if ($self->ai_validate()) { $self->{IS_AUTOINSTALL} = 1; $self->{_AI_ERROR} = undef; my $res = $self->do_auto_install(); if (defined $self->{_AI_ERROR}) { exit($self->{_AI_ERROR}); } return $res; } KL::Utils::fatal(2, $MSG_AI_VALIDATION_FAILED); } ### Triggers handlers sub trigger_install { my $self = shift; my $values = shift; my $upgrade = defined $values->{'upgrade'}; if (defined($ENV{$ENV_AUTO_INSTALL_FILE})) { my $file = $ENV{$ENV_AUTO_INSTALL_FILE}; $self->show_app_title(); $self->{IS_UPGRADE} = $upgrade; $values->{'autoinstall'} = $file; return $self->auto_install($values); } if ( defined $self->{'SETUP'} ) { my $title = $self->{APPINFO}->value('product', 'title'); KL::Utils::output($MSG_NOT_CONFIGURED_NOTICE, $title, $self->{'SETUP'}); } return 1; } sub trigger_uninstall { my $self = shift; my $values = shift; my $upgrade = defined $values->{'upgrade'}; return $self->do_uninstall($upgrade); } sub do_trigger { my $self = shift; my $values = shift; my $trigger = $values->{'trigger'}; if ($trigger eq 'install') { return $self->trigger_install($values); } elsif ($trigger eq 'uninstall') { return $self->trigger_uninstall($values); } KL::Utils::fatal(2, "Value for --trigger must be 'install' or 'uninstall', but not '%1'", $trigger); return 0; } ### sub install_key { my $self = shift; my $key_file = shift; if (defined $key_file) { KL::Utils::header ($HEADER_INSTALL_KEY); my ($res, $message) = $self->install_key_file( $key_file ); if ($res) { $self->ai_save('INSTALL_KEY', 'yes'); $self->ai_save('INSTALL_KEY_FILE', $key_file); KL::Utils::output ($MSG_INSTALL_KEY_SUCCESS, $key_file); return 1; } KL::Utils::output ($MSG_INSTALL_KEY_FAILED, $key_file, $message); return 0; } my ($res, $message) = $self->check_key_installed(); return 1 if $res; # Install licenses (key files) KL::Utils::header ($HEADER_INSTALL_KEY); my $keypath = KL::Utils::ask_question ('', $MSG_INSTALL_KEY_ENTER_PATH); if ( $keypath ) { while ( 1 ) { $keypath = KL::Utils::detildefy( $keypath ); if ( -d $keypath ) { my @errormsgs; if (!opendir LICDIR, $keypath) { push @errormsgs, KL::Utils::translate_string($MSG_INSTALL_OPENDIR_FAILED, $keypath, $!); } else { my @keyfiles = grep { /\.key$/i && -f "$keypath/$_" } readdir (LICDIR); closedir LICDIR; if (@keyfiles) { # Check all the key files for validity my %validkeys; foreach (@keyfiles) { # Check whether it is a KL key file and is valid ($res, $message) = $self->check_key_file("$keypath/$_"); if ($res) { $validkeys{"$keypath/$_"} = 1; } else { push @errormsgs, KL::Utils::translate_string($MSG_INSTALL_KEY_REJECTED, $_, $message); } } if ( %validkeys ) { # Try to install all the keys from the list @errormsgs = (); my $installed = 0; foreach my $keyfile (keys %validkeys) { $keyfile =~ s/\/+/\//g; # remove extra / ($res, $message) = $self->install_key_file( $keyfile ); if ($res) { $self->ai_save('INSTALL_KEY', 'auto'); $self->ai_save('INSTALL_KEY_FILE', $key_file); KL::Utils::output ($MSG_INSTALL_KEY_SUCCESS, $keyfile); return 1; } else { push @errormsgs, KL::Utils::translate_string($MSG_INSTALL_KEY_FAILED, $keyfile, $message); } } } else { push @errormsgs, $MSG_INSTALL_KEY_NO_VALID_FOUND; } } else { push @errormsgs, KL::Utils::translate_string($MSG_INSTALL_KEY_NO_KEYS_FOUND, $keypath); } } KL::Utils::output ("\n" . join ("\n", @errormsgs)) if @errormsgs; #return "None of the Kaspersky Lab license files found can be installed for this product."; } elsif ( -f $keypath ) { ($res, $message) = $self->install_key_file( $keypath ); if ($res) { $self->ai_save('INSTALL_KEY', 'auto'); $self->ai_save('INSTALL_KEY_FILE', $keypath); KL::Utils::output ($MSG_INSTALL_KEY_SUCCESS, $keypath); return 1; } else { KL::Utils::output ($MSG_INSTALL_KEY_FAILED, $keypath, $message); } } else { KL::Utils::output ($MSG_INSTALL_KEY_INVALID_PATH); } $keypath = KL::Utils::ask_question ('', $MSG_INSTALL_KEY_ENTER_OTHER_PATH); last if !$keypath; } } return 0; } sub setup_proxy { my $self = shift; my $value = shift; # Configure the Updater component KL::Utils::header ($HEADER_SETUP_PROXY); if (defined $value) { my ($ok, $str) = $self->set_http_proxy($value); if ($ok) { KL::Utils::output($MSG_SET_PROXY_UPDATED, $value); return 1; } KL::Utils::error("%1\n\n", $str); return 0; } while ( 1 ) { my $default = 'no'; my ($res, $str) = $self->get_http_proxy(); if ($res) { $default = $str; } my $value = KL::Utils::ask_question ($default, $MSG_SET_HTTP_PROXY); return 0 if $value eq 'skip'; ($res, $str) = $self->set_http_proxy($value); if ($res) { $self->ai_save('UPDATER_PROXY', $value); return 1; } KL::Utils::warning("%1\n\n", $str); } } sub download_bases { my $self = shift; my $auto = shift; KL::Utils::header($HEADER_DOWNLOAD_BASES); # Set up the AV bases if ( !$auto && !KL::Utils::ask_boolean ('yes', $MSG_RUN_UPDATER) ) { $self->ai_save('UPDATER_EXECUTE', 'no'); return; } $self->ai_save('UPDATER_EXECUTE', 'yes'); # run updater module return $self->run_updater(); } sub setup_autoupdates { my $self = shift; my $auto = shift; KL::Utils::header ($HEADER_SETUP_AUTOUPDATES); # this question MUST must have default answer 'No' if (!$auto && !KL::Utils::ask_boolean('N', $MSG_SET_AUTOUPDATES) ) { $self->ai_save('UPDATER_ENABLE_AUTO', 'no'); return 0; } $self->ai_save('UPDATER_ENABLE_AUTO', 'yes'); my ($ok, $message) = $self->enable_autoupdates(); if (not $ok) { KL::Utils::warning($MSG_SET_AUTOUPDATES_FAILED, $message); return 0; } KL::Utils::output($MSG_SET_AUTOUPDATES_SUCCESS, $message); return 1; } sub show_app_title { my $self = shift; KL::Utils::header($self->{'TITLE'}); } sub do_show_help { my $self = shift; print "USAGE: $0 [OPTION]\n"; my $maxlen = 0; my @lines; foreach my $option (@{$self->{'COMMANDS'}}) { my $descr = $option->{'descr'}; next if not defined $descr; my ($opts, $info) = split(/\t/, $descr, 2); push @lines, $opts, $info; if ($option->{'id'} eq 'autoinstall') { push @lines, "", "Valid auto-install options is:"; foreach my $auto (@{$self->{'AUTOINSTALL'}}) { push @lines, "", " " . $auto->{'id'} . $auto->{'descr'}; } } $maxlen = length($opts) if length($opts) > $maxlen; } while (@lines) { my $opts = shift @lines; my $info = shift @lines; my $space = $maxlen > length($opts) ? ' ' x ($maxlen - length($opts)) : ''; print "\t$opts$space\t$info\n"; } } sub parse_cmdline { my $self = shift; my $values = {}; my %specs; my @commands; my %functions; foreach my $option (@{$self->{'COMMANDS'}}) { my $id = $option->{'id'}; my $spec = $option->{'spec'}; my $default = $option->{'default'}; $values->{$id} = $default; $specs{$spec} = \$values->{$id}; if ($option->{'sub'}) { push @commands, $id; $functions{$id} = $option->{'sub'}; } } my $res = GetOptions (%specs); if (!$res) { $self->do_show_help(); exit(1); } if ( !$values->{'trigger'} ) { $self->show_app_title(); } KL::Utils::debug_mode(1) if $values->{'debug'}; my ($command, $function); foreach my $cmd (@commands) { if ( defined $values->{$cmd} ) { $command = $cmd; last; } } $command = $self->{'DEFAULT_COMMAND'} if not defined $command; $function = $functions{$command}; return $self->$function($values); } 1;
💾 Save Changes
Cancel
📤 Upload File
×
Select File
Upload
Cancel
➕ Create New
×
Type
📄 File
📁 Folder
Name
Create
Cancel
✎ Rename Item
×
Current Name
New Name
Rename
Cancel
🔐 Change Permissions
×
Target File
Permission (e.g., 0755, 0644)
0755
0644
0777
Apply
Cancel