Sophie

Sophie

distrib > Mandriva > cs4.0 > x86_64 > by-pkgid > 78feba975b04df27341e5f54c7dc146f > scriptlet

kav4fs-5.5-14.i386.rpm

PREIN

/bin/sh
#!/bin/sh
# Test for Perl existence and version
PERLPATH=`which perl 2>/dev/null`
if [ $? = "127" ]; then
        echo "'which' utility is not installed. Installation aborted."
        exit 1
fi

if [ -z "$PERLPATH" ]; then
	echo "Perl is not installed. Installation aborted."
	exit 1
fi

if ! perl -e 'require 5.0' 2>/dev/null; then
	echo "You should install Perl 5.0 or greater. Installation aborted."
	exit 1
fi

# Directory for install
tempdir="/tmp/klinstall.$$"
if [ ! -d ${tempdir} ] ; then
	if mkdir ${tempdir} ; then
		true
	else
		exit 1
	fi
fi		
cd ${tempdir}


# drop preinstall.pl
cat > preinstall.pl <<BND1234567890ABCDEFGH_preinstall.pl_EOF
#!/usr/bin/perl -w
#
# Installation script for Kaspersky Lab products for Unix (R)
# Copyright (C) Kaspersky Lab 2003

# Really useful when script is run from the relative path
BEGIN { unshift @INC, \$1 if \$0 =~ /(.*)[\\/]/; }

use strict;
use klinstall;
use appdata;

############################## text strings ##################################
my \$INSTALL_MSG_1 = <<INSTALL_MSG_1_END;
%1 cannot be installed on this system: %2.
INSTALL_MSG_1_END

my \$INSTALL_MSG_2 = <<INSTALL_MSG_2_END;
%1 was not tested under this Linux distribution.
INSTALL_MSG_2_END

my \$INSTALL_MSG_3 = <<INSTALL_MSG_3_END;
%1 was not tested under this version of %2.
INSTALL_MSG_3_END

my \$INSTALL_MSG_4 = <<INSTALL_MSG_4_END;
%1 version %2 is already installed.
INSTALL_MSG_4_END

my \$INSTALL_MSG_5 = <<INSTALL_MSG_5_END;
%1 is not compatible with already installed %2 because of %3.

You should uninstall %2 before installing %1.
INSTALL_MSG_5_END

my \$INSTALL_MSG_6 = <<INSTALL_MSG_6_END;
%1 requires %2 version %3 or greater to work.
INSTALL_MSG_6_END

my \$INSTALL_MSG_7 = <<INSTALL_MSG_7_END;
%1 needs %2 to perform %3.
INSTALL_MSG_7_END

my \$INSTALL_MSG_9 = <<INSTALL_MSG_9_END;
License file (a file with .key extension) is your personal license key. You need to install it to use the application. 
To install it right now, just enter the path to the location of your license file (enter an empty string to continue without key file installation):
INSTALL_MSG_9_END

my \$INSTALL_MSG_10 = <<INSTALL_MSG_10_END;

Please enter another path to the location of your license file (enter an empty string to continue without key file installation):
INSTALL_MSG_10_END

my \$INSTALL_MSG_12 = <<INSTALL_MSG_12_END;
You must install a valid Kaspersky Lab license file to use the application.
To do this, run <B>%1</B>.
INSTALL_MSG_12_END

my \$INSTALL_MSG_13 = <<INSTALL_MSG_13_END;
Latest anti-virus bases are an essential part of your anti-virus protection. Do you want to download the latest anti-virus bases right now to insure your application is up to date? (If you answer 'yes', make sure you are connected to the Internet):
INSTALL_MSG_13_END

my \$INSTALL_MSG_14 = <<INSTALL_MSG_14_END;
Latest anti-virus bases are an essential part of your anti-virus protection. You must run <B>%1</B> to download the latest anti-virus bases before using the application.
INSTALL_MSG_14_END

my \$INSTALL_MSG_15 = <<INSTALL_MSG_15_END;
Latest anti-virus bases are an essential part of your anti-virus protection, and without them the application will not function. You must run %1 to download the latest anti-virus bases before using the application, and then run <B>%2</B> configuration script to set up the %3.
INSTALL_MSG_15_END

my \$INSTALL_MSG_16 = <<INSTALL_MSG_16_END;

%1 is installed.
Configuration file was installed in %2
Binaries were installed in %3

INSTALL_MSG_16_END

my \$INSTALL_MSG_17 = <<INSTALL_MSG_17_END;
If you use an http proxy server to access the Internet, you need to tell the %1 KeepUp2Date component about it. Please enter the address of your http proxy server in one of the following forms, http://proxyIP:port or http://user:pass\\@proxyIP:port. If you don't have or need a proxy server to access the Internet, enter 'no' here:
INSTALL_MSG_17_END

my \$INSTALL_MSG_18 = <<INSTALL_MSG_18_END;
%1 has been installed successfully but needs to be properly configured before using. 
Unfortunately, RPM is not able to run scripts interactively, so please run <B>%2</B> script by yourself to configure it.
INSTALL_MSG_18_END

my \$WEBMIN_MSG_1 = <<WEBMIN_MSG_1_END;
Default Webmin configuration file was not found. This means that either Webmin is not installed at all, or is installed into a non-default location.

Webmin (www.webmin.com) is a web-based interface for system administration for various Unix components. If you install it, you'll be able to configure and use Kaspersky Anti-Virus through the web interface. If you want to use this functionality, but haven't installed Webmin yet, you can skip this stage and install this module later using Webmin's built-in installation procedure.
If you have Webmin installed in a non-default path, please enter the path to the location of the Webmin configuration file, or leave blank to skip?
WEBMIN_MSG_1_END

my \$WEBMIN_MSG_2 = <<WEBMIN_MSG_2_END;
If you want to use this module later, you can install it using Webmin's own installation procedure. The module will be placed in %1.
WEBMIN_MSG_2_END

my \$WEBMIN_MSG_3 = <<WEBMIN_MSG_3_END;
Webmin configuration file %1 is incorrect. 
Please enter another path to the Webmin configuration file, or leave blank to skip?
WEBMIN_MSG_3_END

my \$WEBMIN_MSG_4 = <<WEBMIN_MSG_4_END;
Webmin module installed successfully. Check it on 'Others' web page.
Depending on Webmin configuration, you may also need to enable the Kaspersky Anti-Virus Webmin module. To do this, on the Webmin main page go to Webmin -> Webmin users -> <username> -> set the check box on <B>%1</B>.
WEBMIN_MSG_4_END

my \$WEBMIN_MSG_5 = <<WEBMIN_MSG_5_END;
failed to install Webmin module: %1
WEBMIN_MSG_5_END


############################### handlers ####################################
sub sigint_handler
{
	print STDERR "Interrupted.\\n";
	exit 0;
}


############################### routines ####################################
sub setup_webmin_module
{
	my (%APPINFO) = @_;

	my \$webminroot;
	my \$webmincfg = -f "/usr/local/etc/webmin/miniserv.conf" ? "/usr/local/etc/webmin/miniserv.conf" : "/etc/webmin/miniserv.conf";
	my \$webmindircfg = klinstall::internal_dirname (\$webmincfg);

	while ( !-f \$webmincfg )
	{
		\$webmincfg = klinstall::ask_question ("CONFIGURE_WEBMIN_ASKCFGPATH", "", \$WEBMIN_MSG_1);

		if ( !\$webmincfg )
		{
			klinstall::output (\$WEBMIN_MSG_2, \$APPINFO{"COMP_WEBMIN_MODULE"});
			return;
		}
	}

	while ( 1 )
	{
		if ( open FI, "<\$webmincfg" )
		{
			my @roots = grep (/^root=.*/, <FI>);
			close FI;

			\$webminroot = \$1 if @roots && \$roots[0] && \$roots[0] =~ /^root=(.*)\\s*\$/;
		}

		last if \$webminroot;
		\$webmincfg = klinstall::ask_question ("CONFIGURE_WEBMIN_ASKANOTHERCFGPATH", "", \$WEBMIN_MSG_3, \$webmincfg);
	}

	my (\$rc, \$outmsg) = klinstall::exec_cmd ("perl \$webminroot/install-module.pl \$APPINFO{COMP_WEBMIN_MODULE} \$webmindircfg");

	if ( \$rc == 0 )
	{
		klinstall::output (\$WEBMIN_MSG_4, \$APPINFO{"NAME"});
		return 1;
	}
	
	klinstall::warning (\$WEBMIN_MSG_5, \$outmsg);
	return;
}



############################### main() ######################################

	my %cmdline_selected;
	my %cmdline_options_list = 
			("debug" => "Enable debug mode",
			 "force" => "Force installation even if there's a conflict",
			 "help"  => "This help message");

	# handle Ctrl-C
	\$SIG{'INT'} = "sigint_handler";

	# check for root
	klinstall::check_for_root ("installation");

	# Analyze extra command-line options. 1st arg could be 'used logic'
	my (\$logic, \$pkgmgr) = klinstall::get_work_logic(\$0, \\@ARGV);

	# parse command-line options and display help only if run manually
	if ( !\$logic )
	{
		my @argslist = @ARGV;
		push @argslist, split ('\\s+', \$ENV{"KLINSTALL"}) if \$ENV{"KLINSTALL"};

		foreach (@argslist)
		{
			next if !\$_;

			my \$arg = \$_;
			\$arg = \$1 if \$arg =~ /^--(.*)\$/;

			if ( !\$cmdline_options_list{\$arg} )
			{
				print "Unsupported command line option: \$_\\n\\n";
				display_cmdline_options(%cmdline_options_list);
				exit 1;
			}

			\$cmdline_selected{\$arg} = 1;
		}

		# --help
		if ( \$cmdline_selected{"help"} )
		{
			display_cmdline_options();
			exit 1;
		}
	}

	# pre-install logic
	if ( !\$logic || \$logic eq "pre" )
	{
		# load appdata module
		my %APPINFO = appdata::get_application_info();

		# check for allowed arch/OS/version
		my (\$arch, \$name, \$rev) = klinstall::get_os_info();

		klinstall::debug "Got info: \$arch, os: \$name, ver: \$rev" 
			if \$cmdline_selected{"debug"};

		# Check for arch, OS etc.
		my \$os_ver_reason = appdata::app_check_os_ver (\$arch, \$name, \$rev);
		klinstall::fatal (\$INSTALL_MSG_1, \$APPINFO{"NAME"}, \$os_ver_reason)
			if \$os_ver_reason;

		# check for Linux distribution name
		my %linux_distro = klinstall::get_linux_info();
		if ( \$linux_distro{"NAME"} )
		{
			my \$res = appdata::app_check_linux_distro (lc \$linux_distro{"NAME"}, \$linux_distro{"VER"});

			\$res == 1 and klinstall::warning (\$INSTALL_MSG_2, \$APPINFO{"NAME"})
				or \$res == 2 and klinstall::warning (\$INSTALL_MSG_3, \$APPINFO{"NAME"}, \$linux_distro{"NAME"})
		}

		# Check for required components
		my @req_comps = appdata::app_check_required_components();
		klinstall::fatal (\$INSTALL_MSG_6, \$APPINFO{"NAME"}, \$req_comps[0]{"NAME"}, \$req_comps[0]{"VER"})
			if @req_comps;

		# Check for optional components
		my @opt_comps = appdata::app_check_optional_components();
		foreach (@opt_comps)
		{
			my %rec = %{\$_};
			klinstall::warning (\$INSTALL_MSG_7, \$APPINFO{"NAME"}, \$req_comps[0]{"NAME"}, \$req_comps[0]{"WHAT2DO"});
		}

		# Check whether the application is already installed - only for tar.gz
		if ( !\$pkgmgr && !\$cmdline_selected{"force"} )
		{
			my %already_installed = klinstall::read_app_info (\$APPINFO{"ID"});
			klinstall::fatal (\$INSTALL_MSG_4, \$APPINFO{"NAME"}, \$already_installed{"VERSION"}) if %already_installed;

            # Check for conflicting applications
			my %applist = appdata::app_get_conflict_ids ();
			foreach (keys %applist)
			{
				my %ai = klinstall::read_app_info (\$_);
				next if !%ai;

				klinstall::fatal (\$INSTALL_MSG_5, \$APPINFO{"NAME"}, \$ai{"NAME"}, \$applist{"\$_"});
			}
		}
	}

	my (@installed_files, @installed_dirs, %uniqmatch);

	# install (copy-files) logic
	if ( !\$logic )
	{
		# load appdata module
		my %APPINFO = appdata::get_application_info();

		foreach (split ("\\n", \$APPINFO{"DIRS"}))
		{
			next if !/^(\\d+)\\s+([\\w\\:]+)\\s+(.*)\$/;
			my (\$mode, \$own, \$dest) = (\$1, \$2, \$3);
			my \$realdest = \$dest;

			if ( \$dest =~ /^(\\w+)\\/(.*)\$/ )
			{
				if ( !defined \$APPINFO{\$1} )
				{
					klinstall::warning ("Bug in installer script: file \$2 should be installed in unknown directory \$1.");
					next;
				}

				\$realdest = defined \$2 && length \$2 ? "\$APPINFO{\$1}/\$2" : "\$APPINFO{\$1}";
			}

			next if -d \$realdest;
			push @installed_dirs, \$dest;

			klinstall::output ("Creating directory \$realdest\\n");
			klinstall::install_path (\$realdest, \$mode, \$own, \\@installed_dirs);
		}

		foreach (split ("\\n", \$APPINFO{"FILES"}))
		{
			next if !/^(\\d+)\\s+([\\w\\:]+)\\s+(.*?)\\s+(.*)\$/;
			my (\$mode, \$own, \$dest, \$src) = (\$1, \$2, \$3, \$4);
			my \$realdest = \$dest;

			if ( \$dest =~ /^(\\w+)\\/(.*)\$/ )
			{
				if ( !defined \$APPINFO{\$1} )
				{
					klinstall::warning ("Bug in installer script: file \$2 should be installed in unknown directory \$1.");
					next;
				}

				\$realdest = "\$APPINFO{\$1}/\$2";
			}

			if ( \$realdest =~ /(.*)\\/(.*?)\$/ && !-d \$1 )
			{
				my \$msg = klinstall::make_path (\$1, 0755, \\@installed_dirs);
				klinstall::fatal (\$msg) if \$msg;
			}

			push @installed_files, \$dest;
			klinstall::output ("Installing file \$realdest\\n");
			klinstall::install_file (\$src, \$realdest, \$mode, \$own);
		}

		%uniqmatch = ();
		@installed_files = grep { ! \$uniqmatch{\$_} ++ } @installed_files;
		%uniqmatch = ();
		@installed_dirs = grep { ! \$uniqmatch{\$_} ++ } @installed_dirs;

		print ("\\n");
	}

	# post-install logic
	if ( !\$logic || \$logic eq "post" )
	{
		my %APPINFO = appdata::get_application_info();
		my %INSTINFO = klinstall::read_app_info (\$APPINFO{"ID"});

		# Debian runs postinstall script in case preuninstall was failed
		# So in Debian case we skip postinstall stage if it is run the second 
		# time
		if ( \$pkgmgr eq "deb" )
		{
			exit 0 if %INSTINFO && \$INSTINFO{"USED_PKGMGR"} && \$INSTINFO{"USED_PKGMGR"} eq "deb";
		}

		# Store generic appinfo
		my %stored_info;
		\$stored_info{"ID"} = \$APPINFO{"ID"};
		\$stored_info{"NAME"} = \$APPINFO{"NAME"};
		\$stored_info{"VERSION"} = \$APPINFO{"VER"};
		\$stored_info{"DEFAULTCONFIG"} = \$APPINFO{"DEFAULT_CONFIG"};
		\$stored_info{"USED_PKGMGR"} = \$pkgmgr if \$pkgmgr;
		\$stored_info{"INSTROOT"} = \$APPINFO{"INSTROOT"};
		\$stored_info{"PATH_BASES"} = \$APPINFO{"PATH_BASES"} if \$APPINFO{"PATH_BASES"};
		\$stored_info{"PATH_LICENSES"} = \$APPINFO{"PATH_LICENSES"} if \$APPINFO{"PATH_LICENSES"};
		\$stored_info{"IS_UPDATE"} = time() if %INSTINFO; # store update time to differ between failed update

		if ( @installed_files || @installed_dirs )
		{
			\$stored_info{"FILE"} = \\@installed_files if @installed_files;
			\$stored_info{"DIR"} = \\@installed_dirs if @installed_dirs;
		}

		klinstall::write_app_info (\$APPINFO{"ID"}, %stored_info);

		if ( \$pkgmgr eq "rpm" )
		{
			klinstall::output (\$INSTALL_MSG_18, \$APPINFO{"NAME"}, \$APPINFO{"COMP_POSTINSTALL_SCRIPT"});
			exit 0;
		}

		appdata::app_modify_config_file();

		my \$av_bases_updated = 0;
		my \$postinstall_message = "";

		# Install licenses (key files)
		if ( \$APPINFO{"REQUIRE_LICENSES"} 
		&& appdata::app_is_license_needed() )
		{
			klinstall::output ("Installing license files.");

			my \$licpath = klinstall::ask_question ("CONFIGURE_ENTER_KEY_PATH", "", \$INSTALL_MSG_9);
			if ( \$licpath )
			{
				while ( 1 )
				{
					my \$errmsg = appdata::install_licenses (\$licpath);
					last if !\$errmsg;

					klinstall::output ("%1", \$errmsg);

					\$licpath = klinstall::ask_question ("CONFIGURE_ENTER_KEY_ANOTHER_PATH", "", \$INSTALL_MSG_10);
					last if !\$licpath;
				}
			}

			\$postinstall_message .= "\\n" . klinstall::translate_string (\$INSTALL_MSG_12, \$APPINFO{"TXT_WRTIL"})
				if !\$licpath;
		}

		# Configure the KeepUp2Date component
		if ( \$APPINFO{"REQUIRE_SETUP_KEEPUP2DATE"} )
		{
			klinstall::output ("\\nConfiguring KeepUp2Date proxy settings.");
			while ( 1 )
			{
				my \$http_proxy = klinstall::ask_question ("CONFIGURE_KEEPUP2DATE_ASKPROXY",
						"",
						\$INSTALL_MSG_17, 
						\$APPINFO{"NAME"});

				last if !\$http_proxy || \$http_proxy eq "no";
				if ( \$http_proxy =~ /^(http:\\/\\/.*?:.*?\\@[\\w\\-\\d\\.:]+)\\/?\$/
				|| \$http_proxy =~ /^(http:\\/\\/[\\w\\-\\d\\.:]+)\\/?\$/ )
				{
					appdata::setup_http_proxy(\$1);
					last;
				}
			}
		}

		# Set up the AV bases
		if ( \$APPINFO{"PATH_BASES"} )
		{
			my \$updates_path = \$ENV{"KLUPDATES"} ? \$ENV{"KLUPDATES"} : ( -d  "updates" ? "updates" : "../updates" );
			if ( !klinstall::install_AV_bases (\$updates_path, \$APPINFO{"PATH_BASES"}) )
			{
				if ( klinstall::ask_boolean ("CONFIGURE_RUN_KEEPUP2DATE", "yes", \$INSTALL_MSG_13) )
				{
					# run keepup2date
					\$av_bases_updated = 1 if appdata::update_AV_database();
				}

				\$postinstall_message .= "\\n" . klinstall::translate_string (\$APPINFO{"REQUIRE_AV_BASES"} ? \$INSTALL_MSG_15 : \$INSTALL_MSG_14, 
							\$APPINFO{"TXT_WRTUAB"},
							\$APPINFO{"COMP_SETUP_SCRIPT"},
							\$APPINFO{"NAME"}) 
					if !\$av_bases_updated;
			}
			else
			{
				\$av_bases_updated = 1;
			}
		}

		setup_webmin_module (%APPINFO) if \$APPINFO{"COMP_WEBMIN_MODULE"};

		# run setup.pl
		if ( !\$APPINFO{"REQUIRE_AV_BASES"} || \$av_bases_updated )
		{
			system ("perl \$APPINFO{COMP_SETUP_SCRIPT}");
		}

		klinstall::output (\$INSTALL_MSG_16, \$APPINFO{"NAME"}, \$APPINFO{"DEFAULT_CONFIG"}, "\$APPINFO{INSTROOT}/bin");
		klinstall::output ("\\n\$postinstall_message") if \$postinstall_message;
	}

	exit 0;
BND1234567890ABCDEFGH_preinstall.pl_EOF

# drop klinstall.pm
cat > klinstall.pm <<BND1234567890ABCDEFGH_klinstall.pm_EOF
#!/usr/bin/perl -w

package klinstall;

# Constants. We don't use 'use constant' - it is perl 5.6 specific.
my \$INI_ERROR_TEXT = "";
my \$CFG_AUTOANSWERS_FILE = \$ENV{"KLAUTOANSWERS"} ? \$ENV{"KLAUTOANSWERS"} : "autoanswers.conf";
my \$CFG_APPSETUP_FILE = "/var/opt/kaspersky/applications.setup";
my %AUTOANSWERS;

my %PKGMGRS = ("rpm" => "rpm", "deb" => "deb", "pkg" => "pkg", "opkg" => "pkg");
my \$IS_FREEBSD = (\$^O =~ /^freebsd\$/i) ? 1 : 0;

################### module initialization #############################
\$| = 1;


# read autoanswers file if present
if ( open FILE, "<\$CFG_AUTOANSWERS_FILE" )
{
	foreach (<FILE>)
	{
		s/[\\n\\r]//g;
		next if !/^(\\w+)\\s*=\\s*(.*)/;
		\$AUTOANSWERS{\$1} = \$2;
	}

	close FILE;	
}

# every module should return true to be loaded successfully
1;


################## external subs #########################################

# Standard formatted output
sub output
{
	my \$text = translate_string(@_) . "\\n";
    my \$right_margin = 65;
	my \$margin = \$right_margin - 1;
    my (\$para, \$accum, \$outstr);

    foreach \$para (split ("\\n", \$text))
	{
		\$accum = '';
		\$para =~ s/\\s+/ /g;
		\$para .= ' ';
		
		while (\$para =~ s/^([^\\n]{0,\$margin})\\s//)
		{
			\$accum .= \$1 . "\\n";
		}
		
		\$accum .= \$para if length (\$para) > \$margin;
		\$outstr .= \$accum;
    } 

    print \$outstr if defined \$outstr;
	return 1;
}


# Debug output
sub debug
{
	output "DEBUG: " . translate_string(@_) . "\\n";
}

# Terminate installation process
sub fatal
{
	output "\\nFatal error: " . translate_string(@_) . "\\n";
	exit 2;
}

# Generate a warning
sub warning
{
	output "Warning: " . translate_string(@_) . "\\n";
}

# Replace %1, %2 etc. by args. 
# Args can contain %1 too, but they should not be replaced
sub translate_string
{
	my (\$str, @args) = @_;

	# First, convert color sequences
	\$str =~ s/<B>/\\x1B\\x5B1m/g;
	\$str =~ s/<\\/B>/\\x1B\\x5B22m/g;

	for ( my \$i = 0; \$i < scalar @args; \$i++ )
	{
		warn ("Empty argument \$i in string '\$str'\\n") if !defined \$args[\$i];
		my \$pattern = "%" . (\$i + 1);
		\$str =~ s/\$pattern/\$args[\$i]/g;
	}

	return \$str;
}

# Return information about Linux distribution
sub get_linux_info
{
	my %ld;

	\$ld{"NAME"} = "RedHat";
	\$ld{"VERSION"} = "7.2";

	return %ld;
}


# Return application info for current ID
sub read_app_info
{
	my \$id = shift;
	my %appinfo;

	# read settings data
	open F, "<\$CFG_APPSETUP_FILE" or return;
	flock F, 2; # LOCK_EX
	my \$content = join ("", <F>);
	flock F, 8; # LOCK_UN
	close F;
	\$content =~ s/\\r//g;

	return unless \$content =~ /\\[\$id\\]\\n(.*?)\\n\\n/s;
	\$content = \$1;

	foreach (split (/\\n/, \$content))
	{
		next if !/^(.*?)=(.*)\$/;

		if ( !defined \$appinfo{\$1} )
		{
			\$appinfo{\$1} = \$2;
			next;
		}

		# Create an array ref
		if ( ref \$appinfo{\$1} ne "ARRAY" )
		{
			my @arr = (\$appinfo{\$1}, \$2);
			\$appinfo{\$1} = \\@arr;
		}
		else
		{
			push @{\$appinfo{\$1}}, \$2;
		}
	}

	close F;
	return %appinfo;
}


# Stores application info for specified ID (or adds the existing info)
sub write_app_info
{
	my (\$appid, %appinfo) = @_;
	my \$content = "";

	# store all the data in text string
	my %olddata = read_app_info (\$appid);
	%appinfo = (%olddata, %appinfo) if %olddata;

	my \$newdata = "[\$appid]\\n";
	foreach my \$key (sort keys %appinfo)
	{
		my \$value = defined \$appinfo{\$key} ? \$appinfo{\$key} : "";

		if ( ref \$value eq "ARRAY" )
		{
			foreach (@{\$value})
			{
				\$newdata .= "\$key=\$_\\n";
			}
			next;
		}

		\$newdata .= "\$key=\$value\\n";
	}

	\$newdata .= "\\n";

	# read settings data
	if ( open F, "+<\$CFG_APPSETUP_FILE" )
	{
		flock F, 2; # LOCK_EX
		\$content = join ("", <F>);
		\$content =~ s/\\r//g;
		truncate F, 0;
		seek F, 0, 0;
	}
	else
	{
		open F, ">\$CFG_APPSETUP_FILE" or return;
	}

	\$content = \$content =~ /\\[\$appid\\]\\n.*?\\n\\n/s
			? \$\` . \$newdata . \$'
			: "\$content\$newdata";

	print F \$content;
	flock F, 8; # LOCK_UN
	close F;

	return 1;
}


# Removes application info for specified ID
sub remove_app_info
{
	my \$appid = shift;

	# read settings data
	open F, "+<\$CFG_APPSETUP_FILE" or return;
	flock F, 2; # LOCK_EX
	my \$content = join ("", <F>);
	\$content =~ s/\\r//g;

	if ( \$content =~ /\\[\$appid\\]\\n.*?\\n\\n/s )
	{
		\$content = \$\` . \$';
		# and store them
		truncate F, 0;
		seek F, 0, 0;
		print F \$content;
	}

	flock F, 8; # LOCK_UN
	close F;

	unlink \$CFG_APPSETUP_FILE if -s \$CFG_APPSETUP_FILE == 0;
	return 1;
}

# returns directory component from the path
sub internal_dirname
{
	return (\$_[0] =~ /(.*)\\/[^\\/]+\$/) ? \$1 : \$_[0];
}

# Return machine information - arch, os name, os version
sub get_os_info
{
	my \$arch = \`uname -p 2>/dev/null\`;
	my \$rev = \`uname -r\`;
	my \$name = \`uname -s\`;
	\$arch = \`uname -m\` if !\$arch || \$arch =~ /^unknown/;
	
	\$arch =~ s/[\\s\\r\\n]//g;
	\$rev =~ s/[\\s\\r\\n]//g;
	\$name =~ s/[\\s\\r\\n]//g;

    # Special version handling for FreeBSD, OpenBSD...
	\$rev = \$1 if \$name =~ /bsd/i && \$rev =~ /^([\\d\\.]+)/;

	# hey, this is Linux!
	return (\$arch, \$name, \$rev);
}


# Display a simple help about command-line options
sub display_cmdline_options
{
	my %optlist = @_;
	print "Supported command line options:\\n";
	foreach (keys %optlist)
	{
		next if !\$optlist{\$_};
		print ("    \$_ - \$optlist{\$_}\\n");
	}
}

# checks for root permissions, and aborts if not
sub check_for_root
{
	my \$procname = shift;

	return if \$^O eq "cygwin" || \$^O eq "MSWin32";
	klinstall::fatal ("%1 must be run by root!", \$procname) if \$> != 0;
}


# Does a file lookup in all the paths specified in argument list.
sub file_lookup
{
	my (\$fn, @paths) = @_;

	foreach my \$pathlist (@paths)
	{
		my \$path = "\$pathlist/\$fn";
		\$path =~ s/\\/\\//\\//g;
		return \$path if -f \$path;
	}

	return;
}


# Get a pid(s) of a running process with specified name, or undef
sub get_process_pids
{
	my \$processname = shift;
	my (%pids, @pidlist);

	# ps options and patterns are different on different systems
	my @osdata = get_os_info();

	if ( \$osdata[1] =~ /hpux|sunos/i )
	{
		my @plist = split ("\\n", \`ps -ef\`);
		shift @plist;
		foreach (@plist)
		{
			my \$pid_part = substr (\$_, 9, 6);
			my \$cmd_part = substr (\$_, 47);
			next if \$pid_part !~ /\\s*(\\d+)\\s\$/;
			\$pid_part = \$1;

			\$pids{\$pid_part} = \$cmd_part;
			\$pids{\$pid_part} = \$1 if \$pids{\$pid_part} =~ /^(.*?)\\s+/;
		}
	}
	else
	{
		my @plist = split ("\\n", \`ps ax\`);
		shift @plist;
		foreach (@plist)
		{
			s/\\s+\$//;
			next if !/^\\s*(\\d+)/;
			my \$pid_part = \$1;
			my \$cmd_part = substr (\$_, 27);
			\$pids{\$pid_part} = \$cmd_part;

			\$pids{\$pid_part} = \$1 if \$pids{\$pid_part} =~ /^(.*?)\\s+/;
		}
	}

	foreach (keys %pids)
	{
		next if \$pids{\$_} !~ /\\b\$processname\\b/;
		push @pidlist, \$_;
	}

	return @pidlist;
}


# Make recursive path. Mode argument is optional
sub make_path
{
	my (\$dirname, \$mode, \$trackref) = @_;

	return if -d \$dirname;
	if ( \$dirname =~ /(.+)\\/[^\\/]+\$/ )
	{
		my \$msg = make_path (\$1, \$mode, \$trackref);
		return \$msg if \$msg;
	}

	return "Could not create directory \$dirname: \$!" 
		if !mkdir (\$dirname, \$mode);

	push (@{\$trackref}, \$dirname) if \$trackref;
	return;    	
}


# Remove recursive path. Mode argument is optional
sub remove_path
{
	my \$dirname = shift;

	return 1 if !-d \$dirname;
	remove_path (\$1) if \$dirname =~ /\\/([\\/+])\$/;

	warning "Could not delete directory \$dirname: \$!\\n" if !rmdir \$dirname;
}

# Copies a file. Returns the error message if failed
sub copy_file
{
	my (\$src, \$dest) = @_;

	# if \$dest is a directory, add the source filename
	\$dest .= "/\$1" if -d \$dest && \$src =~ /([^\\/]+)\$/;

	open FSRC, "<\$src" or return "Could not read file \$src: \$!";
	open FDST, ">\$dest" or return "Could not write file \$dest: \$!";

	binmode FSRC;
	binmode FDST;
	my \$length;

	while ( (\$length = sysread (FSRC, my \$data, 8192)) > 0 )
	{
		if ( syswrite (FDST, \$data, \$length) != \$length )
		{
			close FSRC;
			close FDST;
				
			unlink \$dest;
			return "Could not write file \$dest: \$!";
		}
	}

	close FSRC;
	close FDST;

	if ( !defined \$length )
	{
		unlink \$dest;
		return "Couldn't read file \$src: \$!";
	}

	# Set the same owner and mode
	my @statinfo = stat (\$src);
	if ( @statinfo )
	{
		chown \$statinfo[4], \$statinfo[5], \$dest;
		chmod ((\$statinfo[2] & 07777), \$dest);
	}

	return;
}


# Copies the matched files. Returns the error messages array if failed
sub copy_files
{
	my (\$srcdir, \$destdir, \$pattern) = @_;
	my @errormessages;

	if ( opendir (DIR, \$srcdir) )
	{
		my @files = grep { -f "\$srcdir/\$_" && /\$pattern/i } readdir DIR;
		closedir DIR;

		foreach (@files)
		{
			my \$msg = klinstall::copy_file ("\$srcdir/\$_", "\$destdir/\$_");
			push @errormessages, \$msg if \$msg;
		}
	}
	else
	{
		push @errormessages, "Could not open directory \$srcdir: \$!";
	}

	return @errormessages;
}


# Alters the file/dir owner/group
sub lazy_chown
{
	my \$usergroup = shift;
	my @targets = @_;

	my @arr = split (/:/, \$usergroup);
	my \$user = (\$arr[0] && getpwnam(\$arr[0])) ? getpwnam(\$arr[0]) : -1;
	my \$group = (\$arr[1] && getgrnam(\$arr[1])) ? getgrnam(\$arr[1]) : -1;

	# Do we need to change ownership?
	return if \$user == -1 && \$group == -1;

	chown (\$user, \$group, @targets);
}


# Copies a file, and sets up its owner/permission
sub install_file
{
	my (\$src, \$dest, \$mode, \$owner) = @_;

	my \$msg = copy_file (\$src, \$dest);
	fatal (\$msg) if \$msg;
	lazy_chown (\$owner, \$dest);
	chmod (oct(\$mode), \$dest) if \$mode;
}


# Creates a directory, and sets up its permission
sub install_path
{
	my (\$dir, \$mode, \$owner, \$trackref) = @_;

	my \$msg = make_path (\$dir, oct(\$mode), \$trackref);
	fatal (\$msg) if \$msg;

	lazy_chown (\$owner, \$dir);
	chmod (oct(\$mode), \$dir);
}


# Asks a question from user, or from autoanswer file
sub ask_question
{
	my (\$qid, \$def_answer, \$question, @args) = @_;

	# don't ask anything if question is already answered
	return \$AUTOANSWERS{\$qid} if defined \$AUTOANSWERS{\$qid};

	my \$qtext = translate_string (\$question, @args);
	chomp (\$qtext);

	output (\$def_answer ? "\$qtext [\$def_answer]: " : \$qtext);

	my \$answer = <STDIN>;
	\$answer = "" if !defined \$answer;
	\$answer =~ s/[\\r\\n]//g;
	\$answer = \$def_answer if length(\$answer) == 0;

	# For debug mode: record the question and the answer in the appropriate file
	if ( defined \$ENV{"KAV_INSTALL_HISTORY_FILE"} && open F, ">>\$ENV{KAV_INSTALL_HISTORY_FILE}" )
	{
		print F "\$qid=\$answer\\n";
		close F;
	}

	output "\\n";
	return \$answer;
}


# Ask a 'yes/no' question
sub ask_boolean
{
	while ( 1 )
	{
		my \$answ = ask_question (@_);

		\$answ = "yes" if \$answ =~ /^yes\$/i || \$answ =~ /^y/i;
		\$answ = "no"  if \$answ =~ /^no\$/i  || \$answ =~ /^n/i;

		return 1 if \$answ eq "yes";
		return 0 if \$answ eq "no";
		
		output "Please answer either 'yes' or 'no'.\\n";
	}
}


# Parses command-line args and script name, gets the work-logic
sub get_work_logic
{
	my (\$parsename, \$argsref) = @_;
	my (\$pkgname, \$part) = ("", "");

	# cut the path
	\$parsename = \$1 if \$parsename =~ /([^\\/]+)\$/;

	# if argv[0] is package manager name, get it
	if ( @{\$argsref} && defined \$PKGMGRS{@{\$argsref}[0]} )
	{
		\$pkgname = \$PKGMGRS{@{\$argsref}[0]};
		shift @{\$argsref};
	}

	# if argv[1] is logic part name, get it
	if ( @{\$argsref} 
	&& (@{\$argsref}[0] eq "pre" || @{\$argsref}[0] eq "post") )
	{
		\$part = @{\$argsref}[0];
		shift @{\$argsref};
		return (\$part, \$pkgname);
	}

	# parse name
	\$part = "pre" if \$parsename =~ /^pre/;
	\$part = "post" if \$parsename =~ /^post/;

	return (\$part, \$pkgname);
}


# Check the source directory for valid AV bases set, and install them
sub install_AV_bases
{
	my (\$srcdir, \$destdir) = @_;

	open ASET, "<\$srcdir/avp.set" or return;
	my @set_content = <ASET>;
	close ASET;

	# check for all the files existance
	foreach (@set_content)
	{
		s/[\\n\\r]//g;
		next if /^[;#]/ || /^\$/;
		return if !-f "\$srcdir/\$_";
	}

	# and copy the files
	klinstall::output ("Found Kaspersky Anti-Virus bases in \$srcdir, copying them.");
	klinstall::copy_files (\$srcdir, \$destdir, ".+");

	return 1;
}


# execute a system command
sub exec_cmd
{
	my \$cmd = shift;
	my \$msg;

	# Escape shell args
	\$cmd =~ s/([\\&;\\\`'\\\\\\|"*?~<>^\\(\\)\\[\\]\\{\\}\\\$\\n\\r])/\\\\\$1/g;

	my \$tmpfile = "/tmp/klinstallexec.\$\$.tmp";
	my \$retcode = system ("\$cmd 1>\$tmpfile 2>&1");
	\$retcode = (\$retcode == -1 ? "undef" : \$?); # -1 means system() failed

	if ( open FILE, "<\$tmpfile" )
	{
		\$msg = join ("", <FILE>);
		close FILE;

		unlink \$tmpfile;
	}

	return (\$retcode, \$msg);
}


# execute a system command, escaping arguments
sub exec_cmd_safe
{
	my @args = @_;
	my (\$msg, \$cmd);

	# Escape shell args
	foreach (@args)
	{
		s/([\\&;\\\`'\\\\\\|"*?~<>^\\(\\)\\[\\]\\{\\}\\\$\\n\\r])/\\\\\$1/g;
	}

	my \$tmpfile = "/tmp/klinstallexec.\$\$.tmp";
	my \$cmdline = join (" ", @args) . " 1>\$tmpfile 2>&1";

	my \$retcode = system (\$cmdline);
	\$retcode = (\$retcode == -1 ? "undef" : \$?); # -1 means system() failed

	if ( open FILE, "<\$tmpfile" )
	{
		\$msg = join ("", <FILE>);
		close FILE;

		unlink \$tmpfile;
	}

	return (\$retcode, \$msg);
}


# execute a system command. If the command doesn't exit with code 0, abort
# with the error message
sub exec_zero
{
	my (\$rc, \$msg) = exec_cmd (@_);

	if ( !defined \$rc		# system() failed
	|| (\$? >> 8) != 0		# exit code != 0
	|| (\$? & 127) != 0 )	# signal num
	{
		fatal ("execute (\$_[0]) failed: \$msg");
	}
}


# Ini file error message
sub get_ini_error
{
	return \$INI_ERROR_TEXT ? \$INI_ERROR_TEXT : undef;
}

# Load some data from the configuration (ini-like) file
sub load_ini_file
{
	if ( !open FILE, "<\$_[0]" )
	{
		\$INI_ERROR_TEXT = "unable to read file \$_[0]: \$!";
		return;
	}

	my \$content = join ("", <FILE>);
	close FILE;

	# just in case
	\$content =~ s/\\r//g;

	my (\$sname, \$sdata) = ("&%HEADER%&", "");
	my (%inicontent);

	foreach my \$line (split ("\\n", \$content))
	{
		# section header
		if ( \$line =~ /^\\s*\\[(.*?)\\]\\s*/ )
		{
			if ( \$sname ne "&%HEADER%&" )
			{
				\$inicontent{"sections"}{\$sname} = \$sdata;
				push @{\$inicontent{"order"}}, \$sname;
			}
			else
			{
				\$inicontent{"header"} = \$sdata;
			}

			(\$sname, \$sdata) = (\$1, "");
			next;
		}

		\$sdata .= \$line . "\\n";
	}

	if ( \$sname ne "&%HEADER%&" )
	{
		\$inicontent{"sections"}{\$sname} = \$sdata;
		push @{\$inicontent{"order"}}, \$sname;
	}
	else
	{
		\$inicontent{"header"} = \$sdata;
	}

	# no sections
	if ( !\$inicontent{"order"} || !@{\$inicontent{"order"}} )
	{
		\$INI_ERROR_TEXT = "no sections found in file \$_[0]";
		return;
	}

	return %inicontent;
}


sub save_ini_file
{
	my \$filename = shift;
	my %inidata = @_;

	if ( !open FILE, ">\$filename" )
	{
		\$INI_ERROR_TEXT = "unable to write file \$filename: \$!";
		return;
	}

	print FILE "\$inidata{header}" if \$inidata{"header"};

	foreach my \$name (@{\$inidata{"order"}})
	{
    	print FILE "[\$name]\\n\$inidata{sections}->{\$name}";
    	print FILE "\\n" if \$inidata{"sections"}->{\$name} !~ /\\n\\n\$/;
	}

    close FILE;
	return 1;
}


# Get ini file value
sub get_ini_value
{
	my (\$ref, \$section, \$key) = @_;

	my \$undefpattern = "^\$key\\\\s*=\\\\s*\\\$";
	my \$pattern = "^\$key\\\\s*=\\\\s*(.+?)\\\$";

	return undef if !\$ref->{"sections"}->{\$section}
		|| \$ref->{"sections"}->{\$section} =~ /\$undefpattern/m
		|| \$ref->{"sections"}->{\$section} !~ /\$pattern/m;

	return \$1;
}


# Set ini file value
sub set_ini_value
{
	my (\$ref, \$section, %data) = @_;

	# add the section if not exist
	if ( !\$ref->{"sections"}->{\$section} )
	{
		push @{\$ref->{"order"}}, \$section;
		\$ref->{"sections"}->{\$section} = "";
	}

	# search through the content
	foreach my \$key (keys %data)
	{
		my \$value = defined \$data{\$key} ? \$data{\$key} : "";

		\$ref->{"sections"}->{\$section} =~ m/^\\s*\$key\\s*=\\s*/m
			and \$ref->{"sections"}->{\$section} =~ s/^\\s*\$key\\s*=.*?\\n/\$key=\$value\\n/m
				or \$ref->{"sections"}->{\$section} = "\$key=\$value\\n\$ref->{sections}->{\$section}";
	}
}


# Delete the whole section, or ini file key=value
sub remove_ini_value
{
	my (\$ref, \$section, @keys) = @_;

	return if !\$ref->{"sections"}->{\$section};

	foreach my \$key (@keys)
	{
		\$ref->{"sections"}->{\$section} =~ s/^\\s*\$key\\s*=\\s*.*\\n?//gm;
	}

	# add delete the section if empty
	if ( !@keys || \$ref->{"sections"}->{\$section} =~ /^\\s*\$/s )
	{
		delete \$ref->{"sections"}->{\$section};
		@{\$ref->{"order"}} = grep { \$_ ne \$section } @{\$ref->{"order"}};
	}
}


# Modify some data in the configuration (ini-like) file
sub update_ini_file
{
	my (\$filename, \$section, %data) = @_;

	# read inifile
	my %inidata = load_ini_file (\$filename);
	return if !%inidata;

	set_ini_value (\\%inidata, \$section, %data);

	return save_ini_file (\$filename, %inidata);
}


# Creates a new user account if not exist, returns undef if OK, or the error message text.
# It also creates homedir if it is not exist.
sub add_user
{
	my (\$username, \$group, \$shell, \$home) = @_;

	return 1 if getpwnam (\$username);
	my @cmd = \$IS_FREEBSD ? ("pw", "useradd", "-n", \$username) : ("useradd");

	push @cmd, ("-g", \$group) if \$group;
	push @cmd, ("-s", \$shell) if \$shell;
	push @cmd, ("-d", \$home) if \$home;

	push @cmd, \$username if !\$IS_FREEBSD;

	make_path (\$home, 0755) if !-d \$home;

	return 1 if system (@cmd) == 0;
	\$@ = "Could not add user '\$username'";
	return undef;
}


sub add_group
{
	my \$group = shift;

	return 1 if getgrnam (\$group);
	my @cmd = \$IS_FREEBSD ? ("pw", "groupadd", "-n", \$group) : ("groupadd", \$group);

	return 1 if system (@cmd) == 0;
	\$@ = "Could not add group '\$group'";
	return undef;
}


sub add_user_to_group
{
	my (\$user, \$group) = @_;

	# Check whether the user is already in this secondary group
	my \$groupmembers = ((getgrnam (\$user))[3]);
	my \$userrx = quotemeta (\$user);
	my @cmd;

	return 1 if \$groupmembers && \$groupmembers =~ /\\b\$userrx\\b/;

	if ( \$IS_FREEBSD ) {
		@cmd = ("pw", "usermod", \$user, "-G", \$group);
	} elsif ( \$^O =~ /^openbsd\$/i ) {
		@cmd =("usermod", "-G", \$group, \$user);
	} else {
		@cmd = ("groupmod", "-A", \$user, \$group);
	}

	return 1 if system (@cmd) == 0;
	\$@ = "Could not add user '\$user' to group 'group'";
	return undef;
}

sub exec_cmd_as_user
{
	my (\$user, @args) = @_;
	my \$uid = getpwnam(\$user);

	return 255 if !defined \$uid;

	my \$pid = fork();

	return -1 if \$pid == -1;

	if ( !\$pid )
	{
		# child
		\$! = 0;
		\$< = \$> = \$uid;

		exit 255 if \$! != 0;
		
		# reopen file descriptors
		open (STDOUT, "> /dev/null"); 
		open (STDERR, "> /dev/null");

		exec @args;
		exit 255;
	}

	wait();
	return \$?;
}
BND1234567890ABCDEFGH_klinstall.pm_EOF

# drop appdata.pm
cat > appdata.pm <<BND1234567890ABCDEFGH_appdata.pm_EOF
package appdata;

use klinstall;

# This line should be modified by installer
my \$MODE_MAILSERVER = 0;

# Set up application ID
my \$APPID = \$MODE_MAILSERVER ? 1135 : 1136;

my \$KAVKASROOT = "/var/db/kav/savedsettings/v1";

############################## text strings ##################################
my \$SETUPMSG_1 = <<MSG_END;
Set up mail server anti-virus protection.

The Installer has found this mail server installed on your computer:
Mail server: %1
Mail server binary path: %2
Mail server configuration file: %3

Please enter 'Y' to confirm that you want to protect this mail server with Kaspersky Anti-Virus. Enter 'N' if mail server has been detected incorrectly, or if you do not want to protect it.
MSG_END

my \$SETUPMSG_2 = <<MSG_END;
Set up mail server anti-virus protection.

Setup was unable to detect an existing installation of a mail server on your computer. Either it is not installed or has been installed to an unknown location.
If it has been installed, and you know the installation details, enter 'Y'. Otherwise enter 'N' (configuration will be aborted):
MSG_END

my \$SETUPMSG_3 = <<MSG_END;
Once you have installed and configured the mail server, you can run the configuration script again by running <B>%1</B>.
MSG_END

my \$SETUPMSG_4 = <<MSG_END;
What mail server are you using (sendmail, qmail, postfix, exim)
MSG_END

my \$SETUPMSG_5 = <<MSG_END;
Please enter the full path (without the filename) to your %1 binary %2
MSG_END

my \$SETUPMSG_6 = <<MSG_END;
Please enter the full path to your %1 configuration file %2
MSG_END

my \$SETUPMSG_7 = <<MSG_END;
Could not modify Kaspersky Anti-Virus for mail servers configuration file: %1.
You should set up the ForwardMailer option manually.
MSG_END

my \$SETUPMSG_8 = <<MSG_END;
Kaspersky Anti-Virus for mail servers has successfully configured anti-virus protection for your %1. To activate it, you must start your %1 with <B>%2</B>.
Note that if you ignore this and do not start %1 with this script, your server WILL NOT be protected. Be careful!
MSG_END

my \$SETUPMSG_9 = <<MSG_END;
Kaspersky Anti-Virus for mail servers has successfully configured anti-virus protection for your Postfix mail server. To activate it, you must restart Postfix.
MSG_END

my \$SETUPMSG_10 = <<MSG_END;
Kaspersky Anti-Virus for mail servers has successfully configured anti-virus protection for your qmail.
MSG_END

my \$SETUPMSG_11 = <<MSG_END;
Warning: the 'aveserver' component could not be started. Until it is running, it is not safe to configure mail server anti-virus protection. For security reason, the mail server with antivirus protection enabled will not accept incoming mail when aveserver is not running. Therefore, after the mail server is configured, it will stop receiving new mail until you start aveserver.

Before setting up anti-virus protection for your mail server, we suggest to solve the aveserver startup problems. You can do this by installing license files, updating anti-virus databases or fixing the file/directory permissions. Please check /var/log/kav/5.5/kav4mailservers/aveserver.log file for error messages. Only then it is safe to configure mail server protection.

Do you still want to ignore this warning, and set up the mail server anti-virus protection right now?
MSG_END

my \$LICENSEMSG_1 = <<MSG_END;
Both traffic-based and per-user license files are found. What license type do you want to use (enter 'user' or 'traffic')
MSG_END

my \$LICENSEMSG_2 = <<MSG_END;
License note: your user list %1 is not empty. Kaspersky Anti-Virus 5.5 does not require you to create and maintain the list of licensed users manually anymore. Instead it will be maintained automatically. Please read the documentation.
MSG_END

my \$LICENSEMSG_3 = <<MSG_END;
To protect your users, and to apply automatic accounting of the license information, please enter the comma-separated list of the licensed mail domains. You should use shell masks (with ?, * and [] characters); check the documentation for details. Note that by default, * mask will be used, which will mean that ANY mail domain is licensed.
Examples: avp\\\\.ru,*\\\\.us[12345]\\\\.kaspersky\\\\.com

MSG_END

my \$IMPORTMSG_1 = <<MSG_END;
Setup has found the existing %1 configuration file at %2. Do you want to import the settings to the v5.5 configuration file?
MSG_END

my \$IMPORTMSG_2 = <<MSG_END;
Your settings from version 5.0.3.x have been successfully imported to the v5.5 configuration file. Your anti-virus databases and license files have also been copied. Please review the new configuration file at %1.
The default configuration file has been copied to %2.
MSG_END

my \$IMPORTMSG_3 = <<MSG_END;
Warning: ExtraWgetOptions is set to '%1'
The new keepup2date component no longer uses wget, and therefore the ExtraWgetOptions setting will not work. Please correct your configuration file manually, as needed.
MSG_END

my \$IMPORTMSG_4 = <<MSG_END;
Your settings from version 5.0 have been imported successfully to the v5.5 configuration file. The default configuration file has been copied to %2. Your anti-virus databases and license files also have been copied.

Note that the executable name, the settings, and the behavior of kavupdater component have been completely changed. Most components also contain significant changes. Please read the documentation about the changes (especially if you previously routinely updated from the local server). The default behavior is set to update through the Internet. Please examine the new configuration file at %1, and make all necessary changes.
MSG_END

my \$IMPORTMSG_5 = <<MSG_END;
Some of your settings from version 4.0 have been imported successfully to the v5.5 configuration file stored as %1. Your anti-virus databases and license files also have been copied.

Note that the executable names, the settings, and the behavior of all the components have been changed. Therefore it is impossible to completely retain all of your settings, especially in more complicated cases. Please read the documentation about the changes.
Please review the configuration file created at %1, make all necessary changes and copy it to %2.
MSG_END


my \$UNINSTALL_MSG_1 = <<MSG_END;
Uninstallation aborted: you must stop the Kaspersky Anti-Virus On-Access Scanner (kavmonitor) before uninstalling Kaspersky Anti-Virus for Unix.
MSG_END

my \$UNINSTALL_MSG_2 = <<MSG_END;
the file %1 has been modified since the installation of %2. Because it is not possible to merge or replace these modifications automatically, it should be done manually. Your modified file is saved as %3, and the old file (dated %4) is restored in its place.
MSG_END

my \$UNINSTALL_MSG_3 = <<MSG_END;
the file %1 created during installation of %2, has been modified. Because it is not possible to merge these modifications into the working configuration automatically, it should be done manually. Your modified file is saved as %3.
MSG_END

my \$SECURITY_CHECK_MSG_1 = <<MSG_END;

<B>Warning:</B> some files/directories have insecure permissions.
This is a big security risk. It leads to known <B>local root exploit</B> if any malicious user has access to this computer. We suggest to fix it by changing the permissions to 775 (or 770). Unfortunately that after the fix, you will not be able to run keepup2date from non-root user anymore.
Answer 'Y' if you want fix the permissions now, 'N' if you want to left them intact, and '?' to see the list of directories and permissions/owners to be changed.
MSG_END


my \$KLUSER = "kluser";
my \$KLGROUP = "klusers";

# every module should return true to be loaded successfully
return 1;

# Returns application information.
#
# Should define at least these hash values:
#
my %APPINFO_CACHE;
sub get_application_info
{
	# Take install data
	if ( !%APPINFO_CACHE )
	{
		my %AI;
		seek (DATA, 0, 0);
		foreach (<DATA>)
		{
			chomp;
			m/^f\\s+(.*)\$/ and \$AI{"FILES"} .= "\$1\\n"
				or m/^d\\s+(.*)\$/ and \$AI{"DIRS"} .= "\$1\\n"
					or m/^(\\w+)=(.*)\$/ and \$AI{\$1} = \$2;
		}

		klinstall::fatal ("Corrupted installation!") 
			if !\$AI{"INSTROOT"};

		\$AI{"INSTROOT"} =~ s/\\/\$//; # remove trailing slash

		\$AI{"ID"} = \$APPID;

		\$AI{"NAME"} = "Kaspersky Anti-Virus for Unix";

		\$AI{"DEFAULT_CONFIG"} = "\$AI{CFGPATH}/\$AI{PRODUCT}.conf";

		\$AI{"DBPATH"} = "\$AI{DBROOT}/\$AI{PRODUCT}";
		\$AI{"PATH_BASES"}     = "\$AI{DBPATH}/bases";
		\$AI{"PATH_LICENSES"}  = "\$AI{DBPATH}/licenses";

		\$AI{"REQUIRE_AV_BASES"} = "1";
		\$AI{"REQUIRE_SETUP_KEEPUP2DATE"} = "1";
		\$AI{"REQUIRE_LICENSES"} = "1";

		\$AI{"TXT_WRTUAB"} = "keepup2date component";
		\$AI{"TXT_WRTIL"}  = "\$AI{INSTROOT}/bin/\$AI{PRODUCT}-licensemanager -a <keyfile>";

		\$AI{"COMP_WEBMIN_MODULE"} = "\$AI{SHAREPATH}/contrib/\$AI{PRODUCT}.wbm";
		\$AI{"COMP_SETUP_SCRIPT"}  = "\$AI{LIBEXEC}/setup/setup.pl";
		\$AI{"COMP_POSTINSTALL_SCRIPT"} = "\$AI{LIBEXEC}/setup/postinstall.pl";

		# Internally used
		\$AI{"PATH_SMTPSCAN"} = "\$AI{INSTROOT}/bin/smtpscanner";
		\$AI{"PATH_QMAILQUE"} = "\$AI{INSTROOT}/bin/qmail-queue";
		\$AI{"PATH_LICMANAGER"} = "\$AI{INSTROOT}/bin/\$AI{PRODUCT}-licensemanager";
		\$AI{"PATH_KEEPUP2DATE"} = "\$AI{INSTROOT}/bin/\$AI{PRODUCT}-keepup2date";
		\$AI{"PATH_CONV40SCRIPT"} = "\$AI{LIBEXEC}/setup/convertsettings40to50.pl";

		%APPINFO_CACHE = %AI;
	}

	my %aicopy = %APPINFO_CACHE;
	return %aicopy;
}

# Check for OS name and version. Called during pre-install cycle.
# Gets next args:
# 	- arch. Current architecture. i386/sparc/hpux
# 	- osname. The name of operating system. linux/freebsd/openbsd/solaris
# 	- osver. OS version. 2.4.20
#
# Should return true if 
sub app_check_os_ver
{
	my (\$arch, \$osname, \$osver) = @_;

	my %AI = appdata::get_application_info();
	my \$req_os_ver  = \$AI{'PKG_OS_VER'};
	my \$req_os_name = \$AI{'PKG_OS_NAME'};

	return "Invalid OS version. This package is only for \$req_os_name"
	    if \$req_os_ver && ("\$osname \$osver" !~ /^\$req_os_ver/i );

	return 0;
}

# Generic checks
sub app_check_linux_distro { return 0; }
sub app_get_conflict_ids { return; }
sub app_check_required_components { return; }

sub app_check_optional_components
{
	my %AI = get_application_info();

	# Create kluser/klusers if absent
	my \$shell = -f "/sbin/nologin" ? "/sbin/nologin" : "/bin/false";

	klinstall::add_group (\$KLGROUP) or klinstall::fatal(\$@);
	klinstall::add_user (\$KLUSER, \$KLGROUP, \$shell, \$AI{'DBROOT'}) or klinstall::fatal(\$@);
	return;
}


sub app_start
{
	return;
}


sub app_stop
{
	return;
}


sub app_checks_preuninstall
{
	my %AI = get_application_info();

	if ( !\$MODE_MAILSERVER ) {
	    return \$UNINSTALL_MSG_1 if klinstall::get_process_pids("\$AI{PRODUCT}-kavmonitor");
	}

	return;
}


sub app_is_license_needed
{
	my %AI = get_application_info();
	my \$lictool = \$AI{"PATH_LICMANAGER"};

	# Test whether the valid key file is already installed
	my (\$rc, \$msg) = klinstall::exec_cmd_as_user (\$KLUSER, "\$lictool", "-s");
	if ((\$rc != 0) && \$AI{'WITHKEY'} && -f "\$AI{SHAREPATH}/license/\$AI{WITHKEY}") {
	    (\$rc, \$msg) = klinstall::exec_cmd_as_user (\$KLUSER, "\$lictool", "-q", "-a", "\$AI{SHAREPATH}/license/\$AI{WITHKEY}");
	}

	return \$rc == 0 ? 0 : 1;
}


sub install_licenses
{
	my \$licpath = shift;
	my %AI = get_application_info();
	my \$lictool = \$AI{"PATH_LICMANAGER"};

	opendir LICDIR, \$licpath or return "Could not open directory \$licpath: \$!";
	my @keyfiles = grep { /\\.key\$/i && -f "\$licpath/\$_" } readdir (LICDIR);
	closedir LICDIR;

	return "No license files (files with .key extension) were found in the directory '\$licpath'."
		if !@keyfiles;

	# Check all the key files for validity
	my (%validkeys, @errormsgs);

	foreach (@keyfiles)
	{
		# Check whether it is a KL key file and is valid
		my (\$rc, \$msg) = klinstall::exec_cmd_safe (\$lictool, "-q", "-k", "\$licpath/\$_");

		if ( !defined \$rc || ( \$rc & 127 ) )
		{
			klinstall::output ("Could not execute licensemanager: \$msg\\n");
			next;
		}

		\$rc >>= 8;

        \$rc != 0 and push @errormsgs, "\$_ rejected - not a valid Kaspersky Lab license file."
        	or \$msg !~ /\\bALLOWED=yes\\b/ and push @errormsgs, "\$_ rejected - not valid for this product."
        		or \$validkeys{"\$licpath/\$_"} = \$msg;
	}

	if ( !%validkeys )
	{
		klinstall::output ("\\n" . join ("\\n", @errormsgs));
		return "None of the Kaspersky Lab license files found is valid for this product.";
	}

	# Recheck all the keys, and generate warnings
	if ( \$MODE_MAILSERVER )
	{
		my (\$users, \$traffic) = (0, 0);
		foreach (keys %validkeys)
		{
			next if \$validkeys{\$_} !~ /^LICENSE_TYPE\\s*=\\s*(\\w+)\$/m;
			my \$lictype = \$1;

			\$users = 1 if \$lictype =~ /user/i;
			\$traffic = 1 if \$lictype =~ /traffic/i;
		}

		# Ask the license type if ambiguous
		while ( \$users && \$traffic )
		{
			my \$type = klinstall::ask_question ("KAVMS_SETUP_LICENSE_AMBIGUOUS", "user", \$LICENSEMSG_1);
			\$traffic = 0 if \$type =~ /^user/;
			\$users = 0 if \$type =~ /^traffic/;
		}

		klinstall::output (\$LICENSEMSG_2) if -s "\$AI{PATH_LICENSES}/users";
		my \$lictype = \$traffic ? "traffic" : "users";
	
		klinstall::warning ("Could not set up license type to \$lictype: ", klinstall::get_ini_error())
			if !klinstall::update_ini_file ( \$AI{"DEFAULT_CONFIG"}, "smtpscan.license", ("LicenseType" => \$lictype) );

		my \$licdomains = klinstall::ask_question ("KAVMS_SETUP_LICENSE_DOMAINS", "*", \$LICENSEMSG_3);
		klinstall::warning ("Could not set up license domains to \$licdomains: ", klinstall::get_ini_error())
			if !klinstall::update_ini_file ( \$AI{"DEFAULT_CONFIG"}, "smtpscan.license", ("LicenseDomains" => \$licdomains) );
	}

	# Try to install all the keys from the list
	@errormsgs = ();
	my \$installed = 0;
	foreach my \$keyfile (keys %validkeys)
	{
		\$keyfile =~ s/\\/+/\\//g; # remove extra /

		my (\$rc, \$msg) = klinstall::exec_cmd_safe ("\$lictool", "-q", "-a", \$keyfile);
		if ( \$rc == 0 )
		{
			klinstall::output ("License file %1 has been installed", \$keyfile);
			\$installed = 1;
		}
		else
		{
			push @errormsgs, "Error copying license file \$keyfile to \$AI{PATH_LICENSES}: \$msg";
		}
	}

	# Fix the permissions
	klinstall::exec_cmd_safe ("chown", "-R", "\$KLUSER:\$KLGROUP", \$AI{"PATH_LICENSES"});
	return if \$installed;

	klinstall::output ("\\n" . join ("\\n", @errormsgs)) if @errormsgs;
	return "None of the Kaspersky Lab license files found can be installed for this product.";
}


sub setup_http_proxy
{
	my \$addr = shift;
	my %AI = get_application_info();
	klinstall::warning ("Could not set up proxy address: ", klinstall::get_ini_error())
		if !klinstall::update_ini_file ( \$AI{"DEFAULT_CONFIG"}, "updater.options", ("ProxyAddress" => \$addr, "UseProxy" => "yes") );
}


sub update_AV_database
{
	my %AI = get_application_info();
	my \$updater_cmd = "\$AI{PATH_KEEPUP2DATE} -k -c \$AI{DEFAULT_CONFIG}";

	# Escape shell args
	klinstall::output "\\nRunning keepup2date to update your anti-virus database.\\n";
	\$updater_cmd =~ s/([\\&;\\\`'\\\\\\|"*?~<>^\\(\\)\\[\\]\\{\\}\\\$\\n\\r])/\\\\\$1/g; #'

	my \$retcode = system ("\$updater_cmd");
	
	# return code 1 is 256. perldoc -f wait
	return (defined \$retcode && (\$retcode == 0 || \$retcode == 256)) ? 1 : 0;
}


sub kavms_get_using_mailserver()
{
	my %mailserver_data =
		(
			"sendmail"	=>
				{
				"binname" => "sendmail",
				"confname" => "sendmail.cf",
				"binpaths" => [ "/usr/sbin", "/usr/local/sbin", "/usr/sbin" ],
				"confpaths" => [ "/etc/mail", "/usr/local/etc/mail", "/etc" ]
				},

			"qmail"		=> 
				{
				"binname" => "qmail-queue",
				"binpaths" => [ "/var/qmail/bin" ],
				},
			
			"postfix"	=>
				{
				"binname" => "postfix",
				"confname" => "master.cf",
				"binpaths" => [ "/usr/sbin", "/usr/local/sbin" ],
				"confpaths" => [ "/etc/postfix", "/usr/local/etc/postfix" ],
				"dont_ask_bins" => 1
				},

			"exim"	=>
				{
				"binname" => "exim",
				"confname" => "exim.conf",
				"binpaths" => [ "/usr/sbin", "/usr/local/sbin" ],
				"confpaths" => [ "/etc/exim" ]
				},
		);

	my %msconfig;

	# Find the mail server the customer is using.
	# Sendmail should be searched AFTER postfix and exim; use 'sort' for this
	foreach my \$mailer (sort keys %mailserver_data)
	{
		my %rec = %{\$mailserver_data{\$mailer}};
		my @bins = @{\$rec{"binpaths"}};

		# Search for binary and config
		for (my \$i = 0; \$i < scalar(@bins); \$i++)
		{
			next if ! -x "\$bins[\$i]/\$rec{binname}";
			
			if ( \$rec{"confpaths"} )
			{
				# There could be several binary paths and less config paths
				# In this case, first config path will be used.
				my @confs = @{\$rec{"confpaths"}};
				my \$ci = \$i;
				\$ci = 0 if \$i >= scalar (@confs);
				next if ! -f "\$confs[\$ci]/\$rec{confname}";
				\$msconfig{"conf"} = "\$confs[\$ci]/\$rec{confname}";
			}
			else
			{
				\$msconfig{"conf"} = "not needed";
			}

			\$msconfig{"found"} = 1;
			\$msconfig{"type"} = \$mailer;
			\$msconfig{"bin"} = "\$bins[\$i]/\$rec{binname}";
			last;
		}

		last if \$msconfig{"found"};
	}

	# Confirm all the data
	return %msconfig 
		if \$msconfig{"found"} 
		&& klinstall::ask_boolean ("KAVMS_SETUP_CONFIRM_FOUND", "Y", \$SETUPMSG_1, \$msconfig{"type"}, \$msconfig{"bin"}, \$msconfig{"conf"}) == 1;

	# If not found, we should confirm the mail server configuration at all
	if ( !\$msconfig{"found"}
	&& klinstall::ask_boolean ("KAVMS_SETUP_AT_ALL", "Y", \$SETUPMSG_2) != 1 )
	{
		my %APPINFO = appdata::get_application_info();
		klinstall::output (\$SETUPMSG_3, \$APPINFO{"COMP_SETUP_SCRIPT"});
        return;
	}

	# Autodetect failed or not confirmed. 
	# Ask the user for the mail server type.
	while ( 1 )
	{
		my \$type = klinstall::ask_question ("KAVMS_SETUP_MAILSERVER_TYPE", "sendmail", \$SETUPMSG_4);
		\$type =~ s/\\s//g;

		if ( !\$mailserver_data{\$type} )
		{
			klinstall::output ("Invalid server type: %1", \$type);
			next;
		}

		\$msconfig{"type"} = \$type;
		last;
	}

	# Ask user for binaries (only if mailer does not specify 'dont_ask_bins')
	while ( !\$mailserver_data{\$msconfig{"type"}}->{"dont_ask_bins"} )
	{
		my @bins = @{\$mailserver_data{\$msconfig{"type"}}->{"binpaths"}};
		my \$binpath = klinstall::ask_question ("KAVMS_SETUP_MAILSERVER_BINPATH", \$bins[0] . "/" . \$mailserver_data{\$msconfig{"type"}}->{"binname"}, \$SETUPMSG_5, \$msconfig{"type"}, \$mailserver_data{\$msconfig{"type"}}->{"binname"});

		-d \$binpath and \$binpath .= "/\$mailserver_data{\$msconfig{type}}->{binname}";
		if ( !-f \$binpath || !-x \$binpath )
		{
			klinstall::output ("File not found, or not an executable: %1", \$binpath);
			next;
		}

		\$msconfig{"bin"} = \$binpath;
		last;
	}

	# Ask user for configuration file (only if !qmail)
	while ( defined \$mailserver_data{\$msconfig{"type"}}->{"confpaths"} )
	{
		my @confs = @{\$mailserver_data{\$msconfig{"type"}}->{"confpaths"}};
		my \$confpath = klinstall::ask_question ("KAVMS_SETUP_MAILSERVER_CONFPATH", \$confs[0] . "/" . \$mailserver_data{\$msconfig{"type"}}->{"confname"}, \$SETUPMSG_6, \$msconfig{"type"}, \$mailserver_data{\$msconfig{"type"}}->{"confname"});

		-d \$confpath and \$confpath .= "/\$mailserver_data{\$msconfig{type}}->{confname}";
		if ( !-f \$confpath )
		{
			klinstall::output ("File not found: %1", \$confpath);
			next;
		}

		\$msconfig{"conf"} = \$confpath;
		last;
	}

	return %msconfig;
}


sub make_kas_backup
{
	my (\$kasdir, \$origfilename, \$newext) = @_;

	die if \$origfilename !~ /.*\\/(.*)/;
	my \$filename = \$1;

	my \$msg = klinstall::copy_file (\$origfilename, "\$kasdir/\$filename.\$newext");
	klinstall::warning (\$msg) if \$msg;
}


sub change_script
{
        my (\$filename, %vars) = @_;

        open F, "<\$filename" or return "Could not read file \$filename: \$!";
        my \$data = join ("", <F>);
        close F;

        foreach my \$name (keys %vars)
        {
                my \$value = \$vars{\$name};
                \$data =~ s/^\$name=.*\$/\$name=\\"\$value\\"/m;
        }

        open F, ">\$filename" or return "Could not write file \$filename: \$!";
        print F \$data;
        close F;
	return;
}


sub kavms_setup_sendmail
{
	my (\$confpath, \$binpath, \$smtpscanpath, \$airef, \$kasdatadir) = @_;
	my @changedfiles;
	my \$spool = "/var/spool/mqueue.kav";
	my \$pidpath = "/var/run/sm-listen.pid";
	my \$newcf = "\$confpath.listen";
	my \$runscript = "\$airef->{INSTROOT}/contrib/run_sendmail.sh";
	my \$initscript = "\$airef->{INSTROOT}/init.d/kavsendmail.sh";

	if ( -f \$newcf )
	{
		klinstall::warning ("\$newcf already exist.\\nKaspersky Anti-Virus installer will create a backup copy of this file as \$newcf.backup.\\n");
		klinstall::copy_file (\$newcf, "\$newcf.backup");
		make_kas_backup (\$kasdatadir, \$newcf, "orig");
	}

	my \$msg = klinstall::make_path (\$spool, 0755) if !-d \$spool;
	klinstall::fatal ("Configuration aborted: %1", \$msg) if \$msg;

	# KAS stuff
	open F, "<\$confpath" or klinstall::fatal ("Configuration aborted: could not read \$confpath: \$!");
	my \$sendmailcf = join ("", <F>);
	close F;

	# If Kaspersky Anti-Spam is present, remove everything 
	# it has been added to the sendmail.cf
	if ( \$sendmailcf =~ /^(O InputMailFilters.*?kasfilter.*?)\$/m )
	{
		make_kas_backup (\$kasdatadir, \$confpath, "orig");
		push @changedfiles, \$confpath;

		my \$oldcf = \$sendmailcf;
		\$oldcf =~ s/^Xkasfilter.*\$//gmi;

		# /O InputMailFilters/ cleanup - remove kasfilter
		\$oldcf =~ s/(^O InputMailFilters=.*?),?\\s*kasfilter(,?.*?)\$/\$1\$2/mgi;

		# Remove empty /O InputMailFilters=\\n/ strings
		\$oldcf =~ s/^O InputMailFilters=\\s+//msgi;

		# Remove the first comma from strings like /O InputMailFilters=,newfilter/
		\$oldcf =~ s/^(O InputMailFilters=)\\s*,/\$1/mgi;

		open F, ">\$confpath" or klinstall::fatal ("Configuration aborted: could not write \$confpath: \$!");
		print F \$oldcf;
		close F;
	}

	\$sendmailcf =~ s/^(O QueueDirectory).*\$/\$1=\$spool/m;
	\$sendmailcf =~ s/^(SParseLocal=98)/\$1\\n\\nR\\\$*\\t\\t\\\$#smtpscanner \\\$\\@\\\$1 \\\$:\\\$1/m;

	# replace the pid file
	\$sendmailcf =~ s/^#?\\s*(O PidFile).*\$/\$1=\$pidpath/m;

	\$sendmailcf .= <<EOMSG;

######################*****##########################
###   Kaspersky SmtpScanner Mailer specification  ###
##################*****##############################

Msmtpscanner,	P=\$smtpscanpath, F=PSXmnz9, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\\\\r\\\\n, L=2040,
\\t\\tT=SMTP,
\\t\\tU=\$KLUSER,
\\t\\tA=smtpscanner
EOMSG

	open F, ">\$newcf" or klinstall::fatal ("Configuration aborted: could not create new sendmail configuration file \$newcf: \$!");
	print F \$sendmailcf;
	close F;

	open F, ">\$runscript" or klinstall::fatal ("Configuration aborted: could not create sendmail startup script \$runscript: \$!");
	print F <<EOMSG;
#!/bin/sh

\$initscript start
EOMSG
	close F;
	chmod 0755, \$runscript;
	
	\$msg = change_script (\$initscript, "sendmail_bin" => \$binpath, "sendmail_cf" => \$confpath, "sendmail_listen_cf" => \$newcf);
	klinstall:fatal (\$msg) if \$msg;

	klinstall::warning (\$SETUPMSG_7, klinstall::get_ini_error())
		if !klinstall::update_ini_file (\$airef->{"DEFAULT_CONFIG"}, "smtpscan.general", ("ForwardMailer" => "smtp:(\$binpath -bs -C \$confpath)") );

	klinstall::output (\$SETUPMSG_8, "sendmail", \$runscript);

	make_kas_backup (\$kasdatadir, \$confpath, "modified");
	make_kas_backup (\$kasdatadir, \$newcf, "modified");

	push @changedfiles, \$newcf;
	return @changedfiles;
}


sub kavms_setup_exim
{
	my (\$confpath, \$binpath, \$smtpscanpath, \$airef, \$kasdatadir) = @_;
	my @changedfiles;
	my \$newcf = "\$confpath.listen";
	my \$kascfg = "/usr/local/ap-mailfilter/etc/kas-pipe-exim.conf";
	my \$runscript = "\$airef->{INSTROOT}/contrib/run_exim.sh";
	my \$initscript = "\$airef->{INSTROOT}/init.d/kavexim.sh";
	my \$kav_lmtp_transport = "kav_lmtp_transport :\\n  driver = lmtp\\n  user = \$KLUSER\\n  command = \$smtpscanpath";

	open F, "<\$confpath" or klinstall::fatal ("Configuration aborted: could not read \$confpath: \$!");
	my @eximcf = <F>;
	close F;

	# Check whether the KAS is set up
	if ( -f \$newcf && -f \$kascfg )
	{
		# KAS is set up. Integrate into \$kascfg
		open F, "<\$kascfg" or klinstall::fatal ("Configuration aborted: could not read \$kascfg: \$!");
		my \$data = join ("", <F>);
		close F;

		make_kas_backup (\$kasdatadir, \$kascfg, "orig");

		\$data =~ s/\\r//g;
		\$data =~ s/^OutProtocolLMTP .*/OutProtocolLMTP yes/m;

		\$data =~ /^OutgoingAddr\\s+exec:(.*)/m or klinstall::fatal ("Configuration aborted: strange (non-exec) exim integration; probably newest version of KAS?");
		klinstall::warning (\$SETUPMSG_7, klinstall::get_ini_error())
			if !klinstall::update_ini_file (\$airef->{"DEFAULT_CONFIG"}, "smtpscan.general", ("ForwardMailer" => "smtp:(\$1)") );

		\$data =~ s/^OutgoingAddr .*/OutgoingAddr exec:\$smtpscanpath/m;

		open F, ">\$kascfg" or klinstall::fatal ("Configuration aborted: could not write \$kascfg: \$!");
		print F \$data;
		close F;

		make_kas_backup (\$kasdatadir, \$kascfg, "modified");
		push @changedfiles, \$kascfg;
		return @changedfiles;
	}
	
	# Get the exim version
	klinstall::output ("Getting the exim mailer version by executing exim.");
	my \$eximoutput = \`\$binpath -bV 2>/dev/null\`;
	if ( \$eximoutput =~ /Exim\\s+version\\s+([\\d\\.]+)/ && \$1 < 4.0 )
	{
		\$kav_lmtp_transport .= "\\n  home_directory = /var/db/kav";
	}
	
	# If exim.listen is present, and it is not KAS file, make a backup.
	if ( -f \$newcf )
	{
		klinstall::warning ("\$newcf already exist.\\nKaspersky Anti-Virus installed made a copy of this file as \$newcf.backup.\\n");
		klinstall::copy_file (\$newcf, "\$newcf.backup");
		make_kas_backup (\$kasdatadir, \$newcf, "orig");
	}

	# KAS stuff - backup an original config
	make_kas_backup (\$kasdatadir, \$confpath, "orig");
	push @changedfiles, \$confpath;

	my \$confdata = join ("", @eximcf);
	if ( \$confdata =~ /^\\s*trusted_users\\s*=(.*)/m )
	{
		my \$exusers = \$1;

		if ( \$exusers !~ /\\b\$KLUSER\\b/ )
		{
			my \$adduser = (\$exusers =~ /^\\s*\$/) ? \$KLUSER : " : \$KLUSER";
			\$confdata =~ s/^(\\s*trusted_users = .*)\\n/\$1\$adduser\\n/m;
			open F, ">\$confpath" or klinstall::fatal ("Configuration aborted: could not modify exim configuration file \$confpath: \$!");
			print F \$confdata;
			close F;
		}
	}
	else
	{
		\$confdata =~ s/^(\\s*begin\\s.*)\$/trusted_users = \$KLUSER\\n\$1/m;
		open F, ">\$confpath" or klinstall::fatal ("Configuration aborted: could not modify exim configuration file \$confpath: \$!");
		print F \$confdata;
		close F;
	}

	open F, ">\$newcf" or klinstall::fatal ("Configuration aborted: could not create new exim configuration file \$newcf: \$!");
	my \$found = 0;
	my \$transport_added = 0;

	foreach (@eximcf)
	{
		if ( /^(localuser|dnslookup|local_user|real_local):\$/ )
		{
			\$found = 1 ;
			print F \$_;
			next;
		}

		\$found = 0 if \$found && s/(.*)transport.*/\$1transport = kav_lmtp_transport/;
		
		if ( /^local_delivery:/ && !\$transport_added )
		{
		    \$transport_added = 1;
                    print F "\$kav_lmtp_transport\\n\\n";
		}

		print F \$_;
		
		if ( /^begin\\stransports/ )
		{
		    \$transport_added = 1;
		    print F "\\n\$kav_lmtp_transport\\n";
		}
	}
	close F;

	open F, ">\$runscript" or klinstall::fatal ("Configuration aborted: could not create exim startup script \$runscript: \$!");
	print F <<EOMSG;
#!/bin/sh

\$initscript start
EOMSG
	close F;
	chmod 0755, \$runscript;

	\$msg = change_script (\$initscript, "exim_bin" => \$binpath, "exim_conf" => \$confpath, "exim_listen_conf" => \$newcf);
	klinstall:fatal (\$msg) if \$msg;

	klinstall::warning (\$SETUPMSG_7, klinstall::get_ini_error())
		if !klinstall::update_ini_file (\$airef->{"DEFAULT_CONFIG"}, "smtpscan.general", ("ForwardMailer" => "smtp:(\$binpath -bs -C \$confpath)") );

	klinstall::output (\$SETUPMSG_8, "exim", \$runscript);
	return @changedfiles;
}


# To ignore absense of IO::Socket::INET, this sub call should be wrapped
# into the eval block
sub safely_check_local_port
{
	my \$port = shift;
	require IO::Socket::INET;
	my \$sock = IO::Socket::INET->new (PeerAddr => '127.0.0.1',
                                 	PeerPort => \$port,
                                 	Proto    => 'tcp');
	die if !\$sock;
	return 1;
}


sub kavms_setup_postfix
{
	my (\$confpath, \$smtpscanpath, \$airef, \$kasdatadir) = @_;
	my @changedfiles;
	my \$backuppath = "\$confpath.backup";
	my \$kascfg = "/usr/local/ap-mailfilter/etc/kas-pipe-postfix.conf";

	my \$home = "/var/spool/filter";
	klinstall::exec_zero ("mkdir -p \$home") if ! -d \$home;
	klinstall::lazy_chown ("\$KLUSER:\$KLGROUP", \$home);

	# Read master.cf
	open F, "<\$confpath" or klinstall::fatal ("Configuration aborted: could not read \$confpath: \$!");
	my \$postfixcf = join ("", <F>);
	close F;

	# Create a backup copy
	open F, ">\$backuppath" or klinstall::fatal ("Configuration aborted: could not write \$backuppath: \$!");
	print F \$postfixcf;
	close F;

	if ( \$postfixcf =~ /### KASPERSKY ANTI-SPAM  BEGIN ###/ )
	{
		# KAS is set up. Integrate into \$kascfg
		open F, "<\$kascfg" or klinstall::fatal ("Configuration aborted: could not read \$kascfg: \$!");
		my \$data = join ("", <F>);
		close F;

		make_kas_backup (\$kasdatadir, \$kascfg, "orig");
		push @changedfiles, \$kascfg;

		if ( \$data =~ /^OutgoingAddr\\s+tcp:.*?:(\\d+)/im )
		{
			klinstall::warning (\$SETUPMSG_7, klinstall::get_ini_error())
				if !klinstall::update_ini_file (\$airef->{"DEFAULT_CONFIG"}, "smtpscan.general", ("ForwardMailer" => "smtp:127.0.0.1:\$1") );
		}

		\$data =~ s/\\r//g;
		\$data =~ s/^OutProtocolLMTP .*/OutProtocolLMTP yes/m;
		\$data =~ s/^OutgoingAddr .*/OutgoingAddr exec:\$smtpscanpath/m;

		open F, ">\$kascfg" or klinstall::fatal ("Configuration aborted: could not write \$kascfg: \$!");
		print F \$data;
		close F;

		make_kas_backup (\$kasdatadir, \$kascfg, "modified");
		return @changedfiles;
	}

	# Remove everything if already set up in config
	\$postfixcf =~ s/##<KIS55> ## Added by Kaspersky Anti-Virus Installer ##.*?##<KIS55> ## Added by Kaspersky Anti-Virus Installer ##\\n//gs;

	# Check for registration from version 5.0
	if ( \$postfixcf =~ /^## This line is added by Kaspersky Antivirus Installer.+?^##\$/ms
	|| \$postfixcf =~ /^## Added by Kaspersky Anti-Virus Installer ##.+?^## Added by Kaspersky Anti-Virus Installer ##/ms )
	{
		\$postfixcf =~ s/^## This line is added by Kaspersky Antivirus Installer.+?^##\$//msg;
        \$postfixcf =~ s/^## Added by Kaspersky Anti-Virus Installer ##.+?^## Added by Kaspersky Anti-Virus Installer ##//msg;

		# also clean up main.cf
		my \$maincf = \$confpath;
		\$maincf =~ s/master\\.cf\$/main.cf/;
		if ( open F, "<\$maincf" )
		{
			my \$maincfdata = join ("", <F>);
			close F;

			\$maincfdata =~ s/^## This line is added by Kaspersky Antivirus Installer.+?^##\$//msg;
            \$maincfdata =~ s/^## Added by Kaspersky Anti-Virus Installer ##.+?^## Added by Kaspersky Anti-Virus Installer ##//msg;

            if ( open F, ">\$maincf" )
            {
            	print F \$maincfdata;
            	close F;
            	\$maincf = undef;
            }
		}

		klinstall::warning ("Could not clean up Postfix main.cf configuration file. Please do this manually")
			if \$maincf;
	}

	# Look up for two free ports
	klinstall::output ("\\nProbing for two free ports - please wait.\\n");
	my @ports;
	foreach (10030 ... 49152)
	{
		next if \$postfixcf =~ /:\$_/;
		next if eval { safely_check_local_port(\$_); };

		klinstall::output ("Checking port: \$_ - Ok\\n");
		push @ports, \$_;
		last if scalar (@ports) > 1;
	}

	my \$extrasection = "#<KIS55>\\n"
			. "127.0.0.1:\$ports[0]     inet  n      n      n      -      20     spawn\\n"
			. "\\t\\tuser=\$KLUSER   argv=\$smtpscanpath\\n"
			. "127.0.0.1:\$ports[1]    inet  n      -      n      -      21      smtpd\\n"
			. "\\t -o content_filter=\\n"
			. "\\t -o local_recipient_maps=\\n"
			. "\\t -o relay_recipient_maps=\\n"
			. "\\t -o smtpd_restriction_classes=\\n"
			. "\\t -o smtpd_client_restrictions=\\n"
			. "\\t -o smtpd_helo_restrictions=\\n"
			. "\\t -o smtpd_sender_restrictions=\\n"
			. "\\t -o mynetworks=127.0.0.0/8\\n"
			. "\\t -o strict_rfc821_envelopes=yes\\n"
			. "\\t -o smtpd_error_sleep_time=0\\n"
			. "\\t -o smtpd_soft_error_limit=1001\\n"
			. "\\t -o smtpd_hard_error_limit=1000\\n"
			. "\\t -o myhostname=" . \`hostname\` . "\\n"
			. "#<KIS55>\\n";

	my \$contentfilter = "##<KIS55> ## Added by Kaspersky Anti-Virus Installer ## \\n"
			. "\\t\\t-o content_filter=lmtp:127.0.0.1:\$ports[0]\\n"
			. "## Added by Kaspersky Anti-Virus Installer ##<KIS55>\\n";

	\$postfixcf =~ s/(^smtp\\s+inet\\s+.*smtpd\\s*\\n)/\$1\$contentfilter/mg;
	\$postfixcf =~ s/(^pickup\\s+fifo\\s+.*pickup\\s*\\n)/\$1\$contentfilter/mg;

	\$postfixcf .= \$extrasection;

	make_kas_backup (\$kasdatadir, \$confpath, "orig");
	push @changedfiles, \$confpath;

	# Overwrite master.cf
	open F, ">\$confpath" or klinstall::fatal ("Configuration aborted: could not modify Postfix configuration file \$confpath: \$!");
	print F \$postfixcf;
	close F;

	klinstall::warning (\$SETUPMSG_7, klinstall::get_ini_error())
		if !klinstall::update_ini_file (\$airef->{"DEFAULT_CONFIG"}, "smtpscan.general", ("ForwardMailer" => "smtp:127.0.0.1:\$ports[1]") );

	klinstall::output (\$SETUPMSG_9);

	make_kas_backup (\$kasdatadir, \$confpath, "modified");
	return @changedfiles;
}



sub kavms_setup_qmail
{
	my (\$binpath, \$smtpscanpath, \$airef, \$kasdatadir) = @_;
	my @changedfiles;
	my (\$newbinpath, \$origbinary, \$kasbinary) = (\$binpath, \$binpath, \$binpath);
	\$newbinpath =~ s/qmail-queue/qmail-queue.kav55/;
	\$kasbinary =~ s/qmail-queue/qmail-queue.kas/;
	\$origbinary =~ s/qmail-queue/qmail-que/;

	# Restore original qmail-queue if needed
	if ( -f \$origbinary )
	{
		klinstall::install_file (\$origbinary, \$binpath, '4711', "qmailq:qmail");
		unlink (\$origbinary);
	}

	if ( -f \$kasbinary )
	{
		# KAS-specific logic.
		make_kas_backup (\$kasdatadir, \$kasbinary, "orig");

		# This is original qmail-queue
		rename \$kasbinary, \$newbinpath if ! -f \$newbinpath;
		klinstall::install_file (\$airef->{"PATH_QMAILQUE"}, \$kasbinary, '4711', "kluser:qmail");

		make_kas_backup (\$kasdatadir, \$kasbinary, "modified");
		make_kas_backup (\$kasdatadir, \$newbinpath, "modified");

		push @changedfiles, \$kasbinary;
		push @changedfiles, \$newbinpath;
	}
	else
	{
		# And install new
		if ( ! -f \$newbinpath )
		{
			klinstall::install_file (\$binpath, \$newbinpath, '4711', "qmailq:qmail");
			my %appdata = klinstall::read_app_info (\$APPID);
			push @{\$appdata{"FILE"}}, \$newbinpath;
			klinstall::write_app_info (\$APPID, %appdata);
		}

		make_kas_backup (\$kasdatadir, \$binpath, "orig");
		klinstall::install_file (\$airef->{"PATH_QMAILQUE"}, \$binpath, '4711', "kluser:qmail");

		make_kas_backup (\$kasdatadir, \$binpath, "modified");
		push @changedfiles, \$binpath;
	}

	klinstall::warning (\$SETUPMSG_7, klinstall::get_ini_error())
		if !klinstall::update_ini_file (\$airef->{"DEFAULT_CONFIG"}, "smtpscan.general", ("ForwardMailer" => "qmail:(\$newbinpath)") );
		
	klinstall::output (\$SETUPMSG_10);

	# For Qmail, we need to convert all administrators from /var/qmail/alias/.qmail-postmaster
	# to workaround the message loop.	
	my @adminrecipients = ("postmaster\\@localhost");

	if ( open F, "</var/qmail/alias/.qmail-postmaster" )
	{
		while ( <F> )
		{
			s/[\\n\\r]//g;
			m/^\\&(.*)/ and push @adminrecipients, quotemeta (\$1)
				or m/^[\\d\\w]/ and push @adminrecipients, quotemeta (\$_)
		}

		close F;
	}

	my \$reclist = join (",", @adminrecipients);
	klinstall::update_ini_file (\$airef->{"DEFAULT_CONFIG"}, "smtpscan.group:kavadministrators", ("Recipients" => \$reclist) );

	return @changedfiles;
}


sub _replace_ini_value
{
	my (\$c1, \$c2, \$sec, \$key) = @_;
	my \$value = klinstall::get_ini_value (\$c2, \$sec, \$key);
	return if !defined \$value;
	klinstall::set_ini_value (\$c1, \$sec, \$key, \$value);
}


sub kav_import_settings_5030
{
	my (\$c5030, \$c55) = @_;

	# Store old values
	my \$oldbasespath = klinstall::get_ini_value (\$c5030, "path", "BasesPath");
	my \$oldkeysspath = klinstall::get_ini_value (\$c5030, "path", "LicensePath");
	my \$oldbackuppath = klinstall::get_ini_value (\$c5030, "path", "BackupPath");
	my \$newbasespath = klinstall::get_ini_value (\$c55, "path", "BasesPath");
	my \$newkeysspath = klinstall::get_ini_value (\$c55, "path", "LicensePath");
	my \$newbackuppath = klinstall::get_ini_value (\$c55, "updater.path", "BackUpPath");

	# Replace the values
	_replace_ini_value (\$c5030, \$c55, "path", "BasesPath");
	_replace_ini_value (\$c5030, \$c55, "path", "LicensePath");
	_replace_ini_value (\$c5030, \$c55, "path", "LocalSocketPath");
	_replace_ini_value (\$c5030, \$c55, "path", "IcheckerDbFile");
	_replace_ini_value (\$c5030, \$c55, "updater.options", "PostUpdateCmd");
	_replace_ini_value (\$c5030, \$c55, "updater.report", "ReportFileName");
	_replace_ini_value (\$c5030, \$c55, "scanner.report", "ReportFileName");
	_replace_ini_value (\$c5030, \$c55, "aveserver.report", "ReportFileName");

	klinstall::set_ini_value (\$c5030, "updater.path", "BackUpPath", \$newbackuppath);
	klinstall::set_ini_value (\$c5030, "updater.path", "AVBasesTestPath", klinstall::get_ini_value (\$c55, "updater.path", "AVBasesTestPath"));
	klinstall::set_ini_value (\$c5030, "updater.path", "DiffUtilPath", klinstall::get_ini_value (\$c55, "updater.path", "DiffUtilPath"));
	klinstall::set_ini_value (\$c5030, "updater.path", "UploadPatchPath", klinstall::get_ini_value (\$c55, "updater.path", "UploadPatchPath"));

	my \$passftp = klinstall::get_ini_value (\$c55, "updater.options", "PassiveFtp");
	\$passftp = "no" if !\$passftp;
	klinstall::set_ini_value (\$c5030, "updater.options", "PassiveFtp", \$passftp);
	klinstall::set_ini_value (\$c5030, "updater.options", "UpdateServerUrl", "");

	klinstall::remove_ini_value (\$c5030, "path", "BackUpPath");
	klinstall::remove_ini_value (\$c5030, "path", "UserFile");

	klinstall::set_ini_value (\$c5030, "scanner.options", "UseAVbasesSet", "standard");
	klinstall::set_ini_value (\$c5030, "aveserver.options", "UseAVbasesSet", "standard");

	klinstall::set_ini_value (\$c5030, "updater.options", "RegionSettings", "Russia")
		if !klinstall::get_ini_value (\$c5030, "updater.options", "RegionSettings");

	klinstall::set_ini_value (\$c5030, "updater.options", "ConnectTimeout", "30")
		if !klinstall::get_ini_value (\$c5030, "updater.options", "ConnectTimeout");

	klinstall::set_ini_value (\$c5030, "smtpscan.report", "ReportLevel", klinstall::get_ini_value (\$c5030, "smtpscan.report", "ReportLevel") + 1)
		if klinstall::get_ini_value (\$c5030, "smtpscan.report", "ReportLevel");

	klinstall::set_ini_value (\$c5030, "aveserver.report", "ReportLevel", klinstall::get_ini_value (\$c5030, "aveserver.report", "ReportLevel") + 1)
		if klinstall::get_ini_value (\$c5030, "aveserver.report", "ReportLevel");

	klinstall::set_ini_value (\$c5030, "scanner.report", "ReportLevel", klinstall::get_ini_value (\$c5030, "scanner.report", "ReportLevel") + 1)
		if klinstall::get_ini_value (\$c5030, "scanner.report", "ReportLevel");

	klinstall::set_ini_value (\$c5030, "updater.report", "ReportLevel", klinstall::get_ini_value (\$c5030, "updater.report", "ReportLevel") + 1)
		if klinstall::get_ini_value (\$c5030, "updater.report", "ReportLevel");

	# For mail servers
	if ( \$MODE_MAILSERVER )
	{
		_replace_ini_value (\$c5030, \$c55, "smtpscan.report", "ReportFileName");
		klinstall::remove_ini_value (\$c5030, "smtpscan.license", "LicenseWarningNotifySize");
		klinstall::set_ini_value (\$c5030, "smtpscan.general", "Protocol", "lmtp");

		# Replace all the Template= entries in [smtpscan.notify*]
		foreach my \$name (keys %{\$c5030->{"sections"}})
		{
			next if \$name !~ /^smtpscan\\.notify/;
			\$c5030->{"sections"}->{\$name} =~ s/^(template=\\/etc\\/kav)\\/5.0\\/(.*)\$/\$1\\/5.5\\/kav4mailservers\\/templates\\/\$2/mgi;
		}

		# Copy the templates
		klinstall::output ("Copying old templates to /etc/kav/5.5/kav4mailservers/templates/\\n");
		klinstall::copy_files ("/etc/kav/5.0/", "/etc/kav/5.5/kav4mailservers/templates/", "^template");
	}

	klinstall::output ("Copying license files\\n");
	klinstall::copy_files (\$oldkeysspath, \$newkeysspath, "\\.key\\\$|\\.dat\\\$");

	klinstall::output ("Copying anti-virus bases\\n");
	klinstall::copy_files (\$oldbasespath, \$newbasespath, ".+");

	if ( \$oldbackuppath && -d \$oldbackuppath )
	{
		klinstall::output ("Copying anti-virus bases backup\\n");
		klinstall::copy_files (\$oldbackuppath, \$newbackuppath, ".+");
	}
}


sub kav_import_settings_5000
{
	my (\$c50, \$c55) = @_;

	# store the values
	my \$extrawget = klinstall::get_ini_value (\$c50, "updater.options", "ExtraWgetOptions");
	my \$keepsil = klinstall::get_ini_value (\$c50, "updater.options", "KeepSilent");

	# Wipe the section, and add new values
	klinstall::remove_ini_value (\$c50, "path", "UpdateServersFile");
	klinstall::remove_ini_value (\$c50, "updater.options");
	klinstall::set_ini_value (\$c50, "updater.options", "KeepSilent", \$keepsil);
	klinstall::set_ini_value (\$c50, "updater.options", "ProxyAddress", "");
	klinstall::set_ini_value (\$c50, "updater.options", "UseProxy", "no");
	klinstall::set_ini_value (\$c50, "updater.options", "UseUpdateServerUrl", "no");
	klinstall::set_ini_value (\$c50, "updater.options", "UseUpdateServerUrlOnly", "no");
	klinstall::set_ini_value (\$c50, "updater.options", "UpdateServerUrl", "");
	klinstall::set_ini_value (\$c50, "updater.options", "RegionSettings", "");
	klinstall::set_ini_value (\$c50, "updater.options", "ConnectTimeout", "");
	klinstall::set_ini_value (\$c50, "updater.options", "PassiveFtp", "no");

	klinstall::set_ini_value (\$c50, "scanner.options", "Ichecker", "yes");
	klinstall::set_ini_value (\$c50, "scanner.path", "BackupPath", "");

	klinstall::output (\$IMPORTMSG_3, \$extrawget) if \$extrawget;

	kav_import_settings_5030 (\$c50, \$c55);
}


sub kav_import_settings_4000
{
	my (\$cfg40, \$c55) = @_;
	my %AI = appdata::get_application_info();

	my \$mode = \$MODE_MAILSERVER ? "ms" : "fs";
	klinstall::exec_zero ("perl \$AI{PATH_CONV40SCRIPT} \$mode \$AI{DEFAULT_CONFIG}");

	# remove 4.0 startup scripts
	unlink ("/etc/init.d/kavwt");
	unlink ("/etc/init.d/kavcc");
}


sub kav_import_settings
{
	my \$cfg50 = \$MODE_MAILSERVER ? "/etc/kav/5.0/kav4mailservers.conf" : "/etc/kav/5.0/kav4unix.conf";
	my \$cfg40 = -f "/opt/AVP/AvpUnix.ini" ? "/opt/AVP/AvpUnix.ini" : "/usr/local/share/AVP/AvpUnix.ini";

	return if !-f \$cfg50 && !-f \$cfg40;

	my %AI = appdata::get_application_info();
	my \$confbackup = "\$AI{DEFAULT_CONFIG}.original";

	my %newconf = klinstall::load_ini_file (\$AI{"DEFAULT_CONFIG"});
	klinstall::save_ini_file (\$confbackup, %newconf);

	if ( -f \$cfg50 )
	{
		my %oldconf = klinstall::load_ini_file (\$cfg50);
		return if !%oldconf || !\$oldconf{"sections"};

		if ( \$oldconf{"sections"}->{"updater.options"} =~ /^PostUpdateCmd=/m )
		{
			return if klinstall::ask_boolean ("KAVMS_IMPORT_START_5030", "Y", \$IMPORTMSG_1, "version 5.0.3 and above", \$cfg50) == 0;
			kav_import_settings_5030 (\\%oldconf, \\%newconf);
			klinstall::output (\$IMPORTMSG_2, \$AI{"DEFAULT_CONFIG"}, \$confbackup);
		}
		else
		{
			return if klinstall::ask_boolean ("KAVMS_IMPORT_START_5000", "Y", \$IMPORTMSG_1, "version 5.0", \$cfg50) == 0;
			kav_import_settings_5000 (\\%oldconf, \\%newconf);
			klinstall::output (\$IMPORTMSG_4, \$AI{"DEFAULT_CONFIG"}, \$confbackup);
		}

		klinstall::save_ini_file (\$AI{"DEFAULT_CONFIG"}, %oldconf)
			or print "Could not save new configuration file: " . klinstall::get_ini_error();
	}
	else
	{
		return if klinstall::ask_boolean ("KAVMS_IMPORT_START_4000", "Y", \$IMPORTMSG_1, "version 4.0", \$cfg40) == 0;
		kav_import_settings_4000 (\$cfg40, \\%newconf);
		klinstall::output (\$IMPORTMSG_5, "\$AI{DEFAULT_CONFIG}.new", \$AI{"DEFAULT_CONFIG"});
	}
}


sub detect_kavkas_dir
{
	my \$ms = shift;
	my \$path = \$KAVKASROOT;

	\$ms eq "sendmail" and \$path .= "/s"
		or \$ms eq "qmail" and \$path .= "/q"
			or \$ms eq "postfix" and \$path .= "/p"
				or \$ms eq "exim" and \$path .= "/e"
					or klinstall::fatal ("Unknown mailer: \$ms");

	return "\$path/1" if !-d "\$path/1/" || !open F, "<\$path/1/setup";
	my @res = grep (/^PRODUCT=KAV\\s+\$/s, <F>);
	close F;

	return "\$path/1" if length(@res);
	return "\$path/2";
}



sub kavms_setup
{
	print "\\n\\n";
	my %APPINFO = appdata::get_application_info();
	my (\$rc, \$outmsg) = klinstall::exec_cmd ("\$APPINFO{INSTROOT}/bin/aveserver");

	# Ask again if the field is empty
	my %conf = klinstall::load_ini_file (\$APPINFO{"DEFAULT_CONFIG"});

	if ( !klinstall::get_ini_value (\\%conf, "smtpscan.license", "LicenseDomains") )
	{
		my \$licdomains = klinstall::ask_question ("KAVMS_SETUP_LICENSE_DOMAINS", "*", \$LICENSEMSG_3);

		klinstall::warning ("Could not set up license domains to \$licdomains: ", klinstall::get_ini_error())
			if !klinstall::update_ini_file ( \$APPINFO{"DEFAULT_CONFIG"}, "smtpscan.license", ("LicenseDomains" => \$licdomains) );
	}

	if ( \$rc != 0 && \$rc != (33 << 8) )
	{
		return 1 if klinstall::ask_boolean ("KAVMS_SETUP_NOAVESERVER", "N", \$SETUPMSG_11) == 0;
	}

	my %mssetup = kavms_get_using_mailserver();
	return if !%mssetup;

	my (\$configpfn, @configargs);

	if ( \$mssetup{"type"} eq "postfix" )
	{
		\$configpfn = "kavms_setup_postfix";
		push @configargs, \$mssetup{"conf"};
	}
	elsif ( \$mssetup{"type"} eq "sendmail" )
	{
		\$configpfn = "kavms_setup_sendmail";
		push @configargs, \$mssetup{"conf"};
		push @configargs, \$mssetup{"bin"};
	}
	elsif ( \$mssetup{"type"} eq "exim" )
	{
		\$configpfn = "kavms_setup_exim";
		push @configargs, \$mssetup{"conf"};
		push @configargs, \$mssetup{"bin"};
	}
	elsif ( \$mssetup{"type"} eq "qmail" )
	{
		\$configpfn = "kavms_setup_qmail";
		push @configargs, \$mssetup{"bin"};
	}

	# Do previous backup
	my \$kasdir = detect_kavkas_dir (\$mssetup{"type"});
	klinstall::make_path (\$kasdir, 0700) if !-d \$kasdir;

	open SF, ">\$kasdir/setup" or klinstall::fatal ("Could not write \$kasdir/setup: \$!");

	print SF "PRODUCT=KAV\\n";
	print SF "VERSION=5.5\\n";
	print SF "RECONFIGURE=perl \$APPINFO{INSTROOT}/setup/reconfigure.pl " . join (" ", @configargs) . "\\n";

	push @configargs, \$APPINFO{"PATH_SMTPSCAN"};
	push @configargs, \\%APPINFO;
	push @configargs, \$kasdir;

	my @files = &\$configpfn (@configargs);

	foreach (@files)
	{
		print SF "FILE=\$_\\n";
	}

	close SF;
	return 1;
}


sub kavfs_setup
{
	my %APPINFO = appdata::get_application_info();
	my \$buildscript = "\$APPINFO{SRCPATH}/build.pl";

	if (-f \$buildscript) {
	    my \$retcode = system ("perl \$buildscript");
	    if ((\$retcode >> 8) == 0) {
	        print "Starting kavmonitor: ";
		system("\$APPINFO{RCDPATH} start");
	    }
	}
	return 1;
}


sub app_modify_config_file
{
	kav_import_settings();
}


sub check_directory_permissions
{
	my %dirs = ( 
		"/var/log/kav/" => "0755 root",
		"/var/log/kav/5.5" => "0755 root",
		"/var/log/kav/5.5/kav4unix" => "0770 \$KLUSER:\$KLGROUP",
		"/var/log/kav/5.5/kav4mailservers" => "0770 \$KLUSER:\$KLGROUP",
		"/var/db/kav/5.5/kav4mailservers/licenses" => "0770 \$KLUSER:\$KLGROUP",
		"/var/db/kav/5.5/kav4unix/licenses" => "0770 \$KLUSER:\$KLGROUP",
		"/var/db/kav/5.5/kav4mailservers/licenses/application.dat" => "0666 \$KLUSER:\$KLGROUP",
		"/var/db/kav/5.5/kav4unix/licenses/application.dat" => "0666 \$KLUSER:\$KLGROUP"
		 );

	my %dirs2change;

	foreach my \$dir ( keys %dirs )
	{
		die "Bad pattern: \$dirs{\$dir}" if \$dirs{\$dir} !~ /^(\\d+) (\\w+):?(\\w+)?\$/;
		my (\$rmode, \$ruser, \$rgroup) = (\$1, \$2, \$3);

		my @stats = stat (\$dir) or next;
		my \$dmode = \$stats[2] & 07777;
		my \$duser = getpwuid (\$stats[4]);
		my \$dgroup = getgrgid (\$stats[5]);

		\$dirs2change{\$dir}->{"chmod"} = \$rmode if oct(\$rmode) != \$dmode;

		if ( \$rgroup )	{
			\$dirs2change{\$dir}->{"chown"} = "\$ruser:\$rgroup" if \$duser ne \$ruser || \$dgroup ne \$rgroup;
		} else {
			\$dirs2change{\$dir}->{"chown"} = "\$ruser" if \$duser ne \$ruser;
		}
	}

	return if !%dirs2change;

	while ( (my \$answ = klinstall::ask_question ("KAV_SECURITY_FIX_PERMS", "Y", \$SECURITY_CHECK_MSG_1, join (", ", @unsecuredirs))) !~ /^y/i )
	{
		return if \$answ =~ /^n/i;

		if ( \$answ eq '?' )
		{
			foreach my \$d ( keys %dirs2change )
			{
				my @data;
				my \$info = "Dir \$d:";
				push @data, "chmod \$dirs2change{\$d}->{chmod}" if \$dirs2change{\$d}->{"chmod"};
				push @data, "chown \$dirs2change{\$d}->{chown}" if \$dirs2change{\$d}->{"chown"};

				print "\$info " . join (", ", @data) . "\\n";
			}
		}
	}

	foreach my \$d ( keys %dirs2change )
	{
		chmod oct(\$dirs2change{\$d}->{"chmod"}), \$d or klinstall::warning ("Could not change permissions for \$d")
			if \$dirs2change{\$d}->{"chmod"};

		klinstall::lazy_chown (\$dirs2change{\$d}->{"chown"}, \$d) or klinstall::warning ("Could not change ownership for \$d")
			if \$dirs2change{\$d}->{"chown"};
	}
}


sub app_register()
{
	klinstall::check_for_root ("setup script");
	check_directory_permissions();
	return \$MODE_MAILSERVER ? kavms_setup() : kavfs_setup();
}


sub mailer_reconfigure
{
	my \$mailer = shift;
	my \$data = shift;

	my %APPINFO = appdata::get_application_info();
	my %appdata = klinstall::read_app_info (\$APPID);

	my \$funcname = "kavms_setup_\$mailer";

	&\$funcname (\$data, \$APPINFO{"PATH_SMTPSCAN"}, \\%APPINFO, \\%appdata);
}


sub compare_files
{
	my (\$file1, \$file2) = @_;

	open F, "<\$file1" or return 1;
	my \$c1 = join ("", <F>);
	close F;

	open F, "<\$file2" or return 1;
	my \$c2 = join ("", <F>);
	close F;
	return \$c1 eq \$c2;
}


sub check_and_restore_files
{
	my (\$productname, \$pathcheck, \$pathrestore, @files) = @_;
	my \$restoredfiles = 0;

	foreach my \$file (@files)
	{
		die if \$file !~ /(.*)\\/(.*)/;
		my (\$dir, \$filename) = (\$1, \$2);
		my \$origfile = "\$pathrestore/\$filename.orig";
		my \$modfile = "\$pathcheck/\$filename.modified";
		my \$olddate = -f \$origfile ? scalar localtime ((stat(\$origfile))[9]) : "";

		# We can't do anything if modified file is absent
		if ( !-f \$modfile )
		{
			klinstall::warning ("Installation backup file %1 has been removed. Unable to restore the old file.", \$modfile);
			next;
		}

		# Compare modified and current configuration, and generate a warning
		# if they're different
		if ( -f \$file && !compare_files (\$file, \$modfile) )
		{
			# the warning message differs depending of the file
			my \$renamedfile = "\$dir/\$filename.modified";
			my \$olddate = (-f \$origfile) ? (scalar localtime ((stat(\$origfile))[9])) : undef;

			if ( !rename (\$file, \$renamedfile) )
			{
				klinstall::warning ("Could not rename file %1 to %2: %3. Unable to restore the old configuration.", \$file, \$renamedfile, \$!);
				next;
			}

			if ( \$olddate ) {
				klinstall::warning (\$UNINSTALL_MSG_2, \$file, \$productname, \$renamedfile, \$olddate);
			} else { 
				klinstall::warning (\$UNINSTALL_MSG_3, \$file, \$productname, \$renamedfile);
			}
		}

		# Remove the newly created configuration file if exist
		if ( -f \$file && !unlink (\$file) )
		{
			klinstall::warning ("Could not remove file %1: %3. Unable to restore the old configuration.", \$file, \$!);
			next;
		}

		# And copy the original configuration file if exist
		if ( -f \$origfile )
		{
			my \$msg = klinstall::copy_file (\$origfile, \$file);
			if ( \$msg )
			{
				klinstall::warning (\$msg);
				next;
			}
		}

		\$restoredfiles++;
	}

	return scalar (@files) == \$restoredfiles;
}


sub app_unregister
{
	my %AI = appdata::get_application_info();
	my %appdata = klinstall::read_app_info (\$APPID);

	# Remove mailer start scripts
	unlink ("\$AI{INSTROOT}/contrib/run_sendmail.sh");
	unlink ("\$AI{INSTROOT}/contrib/run_exim.sh");

	# Enumerate through all the directories in 1/ directory.
	my %installedproducts;
	foreach my \$mailer ("s", "e", "p", "q")
	{
		foreach my \$dir ("2", "1")
		{
			next if !-d "\$KAVKASROOT/\$mailer/\$dir/" 
			|| !open F, "<\$KAVKASROOT/\$mailer/\$dir/setup";

			my %productinfo;

			while ( <F> )
			{
				s/[\\n\\r]//g; # strip spaces
				next unless /([A-Z]+)=(.*)/;

				\$1 eq "FILE" and push @{\$productinfo{"FILE"}}, \$2
					or \$productinfo{\$1} = \$2;
			}

            close F;
            next if !defined (\$productinfo{"PRODUCT"}) 
            	 || \$productinfo{"PRODUCT"} !~ /^KAV\$|^KAS\$/;

            \$installedproducts{\$mailer}{\$dir} = \\%productinfo;
		}
	}

	foreach my \$mailer ("s", "e", "p", "q")
	{
		next if !\$installedproducts{\$mailer};
		my \$proot = "\$KAVKASROOT/\$mailer";

		my %this = %{\$installedproducts{\$mailer}};

		# Is our product installed first or alone?
		if ( \$this{1}{"PRODUCT"} eq "KAV" )
		{
			if ( \$this{2} && \$this{2}{"PRODUCT"} eq "KAS" )
			{
				# The product was installed first, and KAS has been installed later
				check_and_restore_files (\$AI{"NAME"}, "\$proot/2", "\$proot/1", @{\$this{2}{"FILE"}});

				klinstall::exec_cmd_safe ("rm", "-rf", "\$proot/1", "\$proot/2");
				klinstall::exec_cmd (\$this{2}{"RECONFIGURE"})
			}
			else
			{
				# The product was installed alone
				check_and_restore_files (\$AI{"NAME"}, "\$proot/1", "\$proot/1", @{\$this{1}{"FILE"}});
				\`rm -rf \$proot/1\`;
			}
		}
		elsif ( \$this{2}{"PRODUCT"} eq "KAV" )
		{
				# The product was installed second after KAS
				check_and_restore_files (\$AI{"NAME"}, "\$proot/\$mailer/2", "\$proot/1", @{\$this{1}{"FILE"}});
				klinstall::exec_cmd_safe ("rm", "-rf", "\$proot/\$mailer/2");
		}
	}

	# If the directory is not empty, it won't be removed anyway
	rmdir ("\$KAVKASROOT/s");
	rmdir ("\$KAVKASROOT/q");
	rmdir ("\$KAVKASROOT/e");
	rmdir ("\$KAVKASROOT/p");

	# Remove the AV bases backup directory
	my %conf = klinstall::load_ini_file (\$AI{"DEFAULT_CONFIG"});
	my \$bpath = klinstall::get_ini_value (\\%conf, "updater.path", "BackUpPath");

	system ("rm -f \$bpath/*") if \$bpath && -d \$bpath && -f "\$bpath/avp.set";
}

__DATA__
INSTROOT=/opt/kaspersky/kav4fs
VER=5.5.14
PRODUCT=kav4fs
CFGPATH=/etc/opt/kaspersky
DBROOT=/var/opt/kaspersky
LIBEXEC=/opt/kaspersky/kav4fs/lib/bin
SHAREPATH=/opt/kaspersky/kav4fs/share
SRCPATH=/opt/kaspersky/kav4fs/src
RCDPATH=/etc/init.d/kav4fs
PKG_OS_VER=
PKG_OS_NAME=
WITHKEY=003F6E0C.key
BND1234567890ABCDEFGH_appdata.pm_EOF
# Run script
perl preinstall.pl rpm
exitcode=$?
cd /
rm -rf ${tempdir}
exit ${exitcode}

PREUN

/bin/sh
perl /opt/kaspersky/kav4fs/lib/bin/setup/uninstall.pl rpm
test "$?" != 0 && exit 1

for dir in /etc/rc.d /etc /sbin/rc.d /sbin; do
	if [ -d "$dir/rc3.d" -o -h "$dir/rc3.d" ]; then
		if [ -z "$rcdir" ]; then
			rcdir="$dir"
		fi
	fi
done

if [ -n "$rcdir" ]; then
    initdir="$rcdir"
    if [ -d "$rcdir/init.d" ]; then
	initdir="$rcdir/init.d"
    fi

    if [ "$1" = "0" ]  ; then
	if [ -x /sbin/chkconfig ] ; then
	    /sbin/chkconfig --del kav4fs
	else
	    for level in 2 3 4 5 ; do
    		/bin/rm -f "$rcdir/rc$level.d/S50kav4fs"
		/bin/rm -f "$rcdir/rc$level.d/K30kav4fs"
	    done
	fi
	/bin/rm -f "$initdir/kav4fs"
    fi
fi

test "$?" != 0 && exit 1

exit 0

POSTIN

/bin/sh
for dir in /etc/rc.d /etc /sbin/rc.d /sbin; do
	if [ -d "$dir/rc3.d" -o -h "$dir/rc3.d" ]; then
		if [ -z "$rcdir" ]; then
			rcdir="$dir"
		fi
	fi
done

if [ -n "$rcdir" ]; then
    initdir="$rcdir"
    if [ -d "$rcdir/init.d" ]; then
    	initdir="$rcdir/init.d"
    fi

    /bin/ln -sf "/opt/kaspersky/kav4fs/lib/bin/kav4fs" "$initdir/kav4fs"

    if [ -x /sbin/chkconfig ] ; then
	/sbin/chkconfig --add kav4fs
    else
	for level in 2 3 4 5 ; do
	    /bin/ln -sf "$initdir/kav4fs" "$rcdir/rc$level.d/S50kav4fs"
	    /bin/ln -sf "$initdir/kav4fs" "$rcdir/rc$level.d/K30kav4fs"
	done
    fi
fi

perl /opt/kaspersky/kav4fs/lib/bin/setup/postinstall.pl rpm