#!/usr/bin/perl

########## Confixx(R) 3.0 Professional ############
####### Copyright SWsoft, Inc. 2004-2005 ##########
#### http://www.sw-soft.com - info@sw-soft.com ####


# help script to find its local modules
BEGIN {
  use FindBin;
  use lib "$FindBin::Bin/subs";
  use lib "$FindBin::Bin/scripts";
}
# end

use File::Basename;
use File::Copy;

use lib_module_common;
use lib_module_db;
use lib_module_password;

use strict;

use vars qw/$createDB $confixx_conf_ende $wDir $confixxInstallScript
						$psqldump $mysqldump/;

## einige Variablen
umask 077;

## Error codes.
# Scripts execution: #1xxx, #1001
##

#####################################################
# Default settings
#####################################################
# Standard Confixx Professional version

# 0 - not RPM installation
$rpm_version_flag = 0;

# 0 - allow interactive questions
$no_questions_mode = 0;

# 0 - use pipelog utility
$no_pipelog_mode = 0;
#####################################################

$confixxState = 'install';

$wDir = &getCanonPath( dirname($0) );

my $scriptDir = '/scripts';
my $cgiDir = '/cgis';
my $htmlDir = '/html';
$confixxInstallScript = 1;

my $cron_install_script = "$wDir/subs/cron_install.pl";
my $proFTPD_install_script = "$wDir/subs/proFTPD_install.pl";
my $wuftpd_install_script = "$wDir/subs/wu-ftpd_install.pl";
my $vsftpd_install_script = "$wDir/subs/vsftpd_install.pl";
my $spamassassin_wizard = "$wDir/subs/spamassassin_wizard.pl";
my $subs_include_dns = "$wDir/subs/subs_include_dns.pl";


$mysqldump = "$wDir/subs/mysqltables";
$psqldump = "$wDir/subs/psqltables";
my $configFile = "$wDir/.config";
## /einige Variablen

unless( -f $configFile ) {
  $language = 'en';
  die( &ltext('install_tmpconf_exist', $configFile) );
}

&initConfig( $configFile );

unless($confixx_conf_ende == 77){
  die( &ltext('install_tmpconf_corrupt', $configFile) );
}

safe_do "$wDir/subs/subs_include_questions.pl";
safe_do "$wDir/subs/subs_include_modules.pl";

&checkRequirement( $dbType );

# install all needed modules
my @modules  = ( 'Logfile::Rotate',
								 'Compress::Zlib',
								 'Proc::ProcessTable',
								 'Term::ReadKey',
								 'Expect',
								 'IO::Stty',
								 'IO::Tty',
								 'Storable',
								 'Curses::UI',
								 'Unicode::Map8',
								 'IO::Socket::SSL' );
				
if( $use_quota ) {
	push @modules, 'Quota';  # install Quota-Module
}


umask 022;
unless ( &checkAndInstallFlat( \@modules ) ) {
	
	unless ( &YesNoQuestion( &ltext( 'install_modules_failed' ) ) ) {
		my $listPkgs = join(',', &checkPkgs( \@modules ) );
		if ( $listPkgs ) {
			die( &ltext( 'install_question_module_load', $listPkgs) );
		}
	}
}
umask 077;
  # /install all needed modules


## Pre-Main
foreach my $script ( qw ( subs_include_files.pl
													subs_include_events.pl
													subs_include_quota.pl
													subs_include_mhost.pl
													subs_include_db.pl
												)
									 ) {
	safe_do "$wDir/subs/$script";
}


#
# copy old log
#
my $oldLog = "INSTALLATION_PROBLEMS.LOG";
my $newLog = "$installDir/$oldLog";

&RecCreateDir($installDir, 0700);

if ( open( NEW, '>', $newLog ) ) {
	my ($cnt);
	foreach my $log ($oldLog,"$wDir/$oldLog") {
		if ( -T $log ){
			if ( open( OLD, "< $log") ) {
				$cnt = 0;
				while (<OLD>) {
					print NEW $_;
					$cnt++;
				}
				if ( $cnt ) {
#					print NEW "\n### end insert from '$log' ###\n\n";
				}
				close (OLD);
				unlink $log;
			} else {
				warn "Can't open file '$log' to read: $!\n";
			}
		}
	}
	close ( NEW );
} else {
	warn "Can't open file '$newLog' to write: $!\n";
}
#
# /copy old log
#

%bin = (
  'grep' 		=> $bin_grep,
  'cp' 			=> $bin_cp,
  'find' 		=> $bin_find,
  'chown' 		=> $bin_chown,
  'rm' 			=> $bin_rm,
  'chmod' 		=> $bin_chmod,
  'ifconfig' 	=> $bin_ifconfig,
  'webalizer' 	=> $bin_webalizer,
  'fpsrvadm' 	=> $bin_fpsrvadm,
  'mysql' 		=> $bin_mysql,
  'mysqldump' 		=> $bin_mysqldump,
  'psql' 		=> $bin_psql,
  'du' 			=> $bin_du,
  'sendmail' 	=> $bin_sendmail,
  'openssl' 	=> $bin_openssl,
  'gzip'		=> $bin_gzip,
  'su'			=> $bin_su,
  'tar'			=> $bin_tar,
  'df'          => $bin_df,
  'unzip'		=> $bin_unzip,	
);

## /Pre-Main


## Main
&InstallAll;

## /Main

#
# unlink empty log
#
if ( -e $newLog && -z $newLog ) { ## if exists & size is zero
	unlink $newLog;
}


## UNTERPROGRAMME
sub InstallAll{

  ## defaults (confixx_main.conf)

  $show_emailtransfer = 0;
  $apacheBackupLocal = 1;
  $apacheBackupDay = 1;

  if($use_quota){
    $mail_quota = 1;
    $user_quota = 1;
  }

	unless( $mysqlUserPort ) {
		$mysqlUserPort ||= $mysqlUserServer eq 'localhost'?'localhost':$stdIP;
  }

  ## /defaults


  unless ( $mail_server == 2 || $dns_server == 2 ) { ## primary confixx server
    # create database !!

    safe_do "$wDir/subs/createDB_install.pl", 'no_debug';

    unless( $createDB ) {
      die( &ltext('install_error', '#1077'));
    }
    &checkDB;

  } else { ## secondary confixx server
    &updateDbForSecondary();
		&getMainSettings();
  }

  # create Confixx-installdirectory
  unless ( $rpm_version_flag ) {
	  &RecCreateDir($installDir, 0700);
	  mkdir("$installDir/safe", 0700);
	  mkdir("$installDir/cgi", 0700);
	  open(FILE, ">$installDir/cgi/aendern");
	  print FILE "#" . &ltext('install_stdcgi_comment') . ":\n#cgi-bin/FormMail.cgi:755\n#order.html:644\n";
	  close(FILE);
	  mkdir("$installDir/cgi/html", 0700);
	  mkdir("$installDir/cgi/html/cgi-bin", 0700);
	  mkdir("$installDir/backup", 0700);
	  mkdir("$installDir/admin", 0700);
  }

  # write configfiles for the first time ...
  safe_do "$wDir/subs/subs_include_writeConfig.pl";

  &WriteMainConfigFile;
  &tmp_conf;

  umask 022;
  # create other directories
	if($mail_server != 2 && $dns_server != 2){
		&RecCreateDir("$user_homeDir", 0755);
		mkdir("$user_homeDir/empty", 0444);
		chmod(0444, "$user_homeDir/empty");
		chown(0, 0, "$user_homeDir/empty");
		&RecCreateDir("$apacheLogDir", 0700);
		chmod(0700, "$apacheLogDir");
		chown(0, 0, "$apacheLogDir");
		&RecCreateDir("$apacheBackupDir", 0700);
		chmod(0700, "$apacheBackupDir");
		chown(0, 0, "$apacheBackupDir");
		&createDir("$apacheLogDir/kunden/access");
		&createDir("$apacheLogDir/domains/access");
		&createDir("$apacheLogDir/kunden/error");
		&createDir("$apacheLogDir/domains/error");
		&createDir("$apacheBackupDir/access");
		&createDir("$apacheBackupDir/error");

		my $dir = dirname($confixx_accessLog);
    &RecCreateDir( $dir, 0700 );
		$dir = dirname($confixx_errorLog);
    &RecCreateDir( $dir, 0700 );
		if ( $sslKeyDir ) {
			&RecCreateDir( $sslKeyDir, 0700 );
		}
		if ( $sslCrtDir ) {
			&RecCreateDir( $sslCrtDir, 0700 );
		}
	
		if ($majordomo_home && -d $majordomo_home){

			safe_do "$wDir/subs/majordomo_install.pl";

			&installMajordomo();

		}

		if (-x $scponly_shell){
			my $chrootDir;
			if ($scponly_chroot){
				$chrootDir="$user_homeDir/$scponly_chroot";
				&RecCreateDir($chrootDir, 0700);
				safe_do "$wDir/subs/scponly_install.pl";
				if ( -x $bin_ldd ) {
					$bin{'ldd'} = $bin_ldd;
				}
				&scponlyMakeChroot($chrootDir,\%bin);
			}
		}
	}
  &createDir($PIDDir);

  print "\n";
  # backup Files later to be changed by Confixx
  &BackUpFile($passwdDir, 	"$installDir/backup/system/passwd");
  &BackUpFile($shadowDir, 	"$installDir/backup/system/shadow");
  &BackUpFile($groupDir, 	"$installDir/backup/system/group");
  &BackUpFile($httpd_conf, 	"$installDir/backup/apache/httpd.conf");

  # add Confixx-Web-User to system
  if($mail_server != 2 && $dns_server != 2){
    $confixx_gid = &AddGroup($confixx_group);    
    unless(getpwnam($confixx_user)){

      print "\n";
      $confixx_uid = $min_uid - 4;
      &AddUser($confixx_user, $confixx_gid, $confixx_homeDir, '', $confixx_uid);
      &RecCreateDir($confixx_homeDir, 0750);

    } else {

      $confixx_uid = getpwnam($confixx_user);
    }
    $gidapache = &AddGroup($apacheGroup);
	if ( $userGroup ) { 
      $giduser = &AddGroup($userGroup);
	} else {
	  $giduser = undef;
	}   

    if(-d $confixx_homeDir){
      chown($confixx_uid, $gidapache, $confixx_homeDir);
      chmod(0750, $confixx_homeDir);
    }
  }

  if( ((($mail_server == 0) && ($dns_server != 2)) || ($mail_server > 0)) && ($popGroup ne "") ){    
    $gidpop = &AddGroup($popGroup);
  }

  &UpdateMainConfig;
  &tmp_conf;

  umask 022;
  print "\n";
  # add Confixx-Virthost to Apache-Conf
  unless( $mail_server == 2 || $dns_server == 2 ) { ## primary confixx server
    print( &ltext('install_do_file_edit', $httpd_conf) );

    my $pat = qr/^\s*Include\s+\Q$mhost_conf\E(?:\s|$)/; ## compile regular expression
    my $found;
#
# check if there is the confixx part in httpd.conf
#
		if(open(FILE,"<$httpd_conf")){
			while(<FILE>){
				next if (/^\s*(#|$)/); ## exclude commentary & blank lines
				if(/$pat/){
					$found=1;
					last;
				}
			}
			close (FILE);
		}

		unless($found){
			open(FILE, ">>$httpd_conf");
			my ($comment);
			$comment = &ltext('install_httpdconf_comment');
			print FILE <<HTTPD_CONF;

## CONFIXX

Include $mhost_conf

# $comment

## /CONFIXX
HTTPD_CONF
      close(FILE);
    }

	unless ( $bin_openssl && ( -x $bin_openssl ) ){
	  &report_error(
"######################################################################################
'openssl' binary not found. The Confixx interface will not be accessible through HTTPS.
In order to enable HTTPS support for the Confixx interface, after the installation 
  1. install openssl 
  2. run admin.pl and activate SSL support.
#######################################################################################"
	  );
	}

    &writeMHost ( $confixx_IP, $confixx_domain, $confixx_accessLog, $confixx_errorLog );
  }


#
# create an empty confixx_vhost.conf
#
	if ( open( TOUCH, '>', $vhost_conf ) ) {
		close( TOUCH );
	}

	$bin_cp ||= $bin{'cp'} || 'cp';

  print &ltext('install_do_dir_copy', "$wDir/languages", "$installDir/admin/languages");
  system("$bin_cp -rf $wDir/languages $installDir/admin/");

  print &ltext('install_do_dir_copy', "$wDir/contrib", "$installDir/admin/contrib");
  system("$bin_cp -rf $wDir/contrib $installDir/admin/");

  print "\n\n";
  # configure Email
	my ($return);

  if ( $mail_server != 0 ) {

    umask 022;
    if ( $pop_homeDir ) {
      &RecCreateDir( $pop_homeDir, 0755 );
    }

    if ( $mta eq 'sendmail' ) {
      safe_do "$wDir/subs/sendmail_install.pl";
      $use_autorespond = 1;
			$use_events = 1;

    } elsif ( $mta eq 'postfix' ) {
      safe_do "$wDir/subs/postfix_install.pl";
      $use_autorespond = 1;
			$use_events = 1;

    } elsif ( $mta eq 'qmail' ) {
      safe_do "$wDir/subs/qmail_install.pl";
      $use_autorespond = 1;
			$use_events = 1;
    }

    if ( $pop_homeDir && !-d $pop_homeDir ) {
      &RecCreateDir( $pop_homeDir, 0755 );
    }

  }

  umask 022;
  print "\n\n";

  # configure FTPD
  unless( $mail_server == 2 || $dns_server == 2 ) {

    if ( $ftpDaemon eq 'ProFTPD' ) {
      $return = system( $proFTPD_install_script );
      &etc_shells;

    } elsif ($ftpDaemon eq 'wu-ftpd' ) {
      $return = system( $wuftpd_install_script );
      &etc_shells;

    }   elsif ($ftpDaemon eq 'vsftpd' ) {
      $return = system( $vsftpd_install_script );
      &etc_shells;
    }
  }
  # install spamassassin
  if ( $spamassassin_support ) {

		my $spamassassin_install_script = "$wDir/subs/spamassassin_install.pl";
		safe_do "$wDir/subs/spamassassin_install.pl";

    unless ( &installSpamassassin() ) {
      warn("Can not execute $spamassassin_install_script: $!\n".
					 "To complete SpamAssassin support installation you should ".
					 "launch $spamassassin_install_script manually after the installation.\n");
		}
  }

  # configure dns
  if($dns_server > 0){

		safe_do "$wDir/subs/subs_include_dns.pl";

		&installDns();

  }

  print "\n\n";
  # install UpdateScript, Traffik, etc ...
  safe_do "$wDir/subs/scripts_install.pl";

  umask 022;
  unless( $mail_server == 2 || $dns_server == 2 ) {
    print "\n\n";
    # install Confixx-Weppages & cgis

    safe_do "$wDir/subs/webPages_install.pl";

    print "\n\n";
		safe_do "$wDir/subs/cgis_install.pl";
		&installAllCGIs();

  }

#
# Quota support
#
  if ($use_quota) {
    &quotaSupportCheck;
  }

  print "\n\n";
  $no_questions_mode = 0;	# rpm installations is complete. we can ask interactively now
  &UpdateMainConfig; # Just to be sure it is recent enough ;-)
  &tmp_conf;

	&exec_script( "$installDir/admin/subs/confixx_install.pl" )	or 
		die("Can not complete installation: Error #1001\n");
	&install_confixx_300();

 safe_do "$installDir/copy_libraries.pl";

# store %bin into SQL-server
  if (-x $scponly_shell){
		my %scpBin;
		$scpBin{'scponly'} = $scponly_shell ;
		$scpBin{'ldd'} = $bin{'ldd'};
		$scpBin{'df'} = $bin{'df'};
	
		&StoreBin(\%scpBin,'scponly'); 
  }
  &StoreBin;

#
# restrat apache on primary confixx server
#
 if ( !( $dns_server == 2 || $mail_server == 2 ) &&
			$pm_apache_reload ) {

	 my $apache_restart = $pm_apache_reload;
	 $apache_restart =~ s/(?<=\s)reload$/restart/;
	 system( $apache_restart );

 }


  # run update script first time
  system( "$installDir/confixx_updatescript.pl" );

  # finally insert updatescript into cron ...
  &fertig;
  unlink($configFile);

  $wDir = dirname($0);
  if((-T "$wDir/../confixx_main.conf") && !(-x "$wDir/../confixx_updatescript.pl")){
    unlink("$wDir/../confixx_main.conf");
  }
  unlink($configFile);

  if ($rpm_version_flag) {
    my $script1 = "$installDir/install_default_license.pl";
    if (-x $script1) {
			system($script1) == 0
				or warn("ERROR: $script1 failed: $!");
    } else {
			print "WARNING: File $script1 does not exist or is not executable. So installing default license is skipped.\n";
			print "You may launch the script manually or install fully functional key.\n";
    }
    my $script2 = "$installDir/install/configure_cron.sh";
    if (-x $script2) {
			system("$script2 -add") == 0
				or warn("ERROR: $script2 failed: $!");
    } else {
			print "WARNING: File $script2 does not exist or is not executable. So configuration of crontab is skipped.\n";
			print "You may configure crontab manually.\n";
    }
    &show_congratulations;
  }
}



sub checkDB{
  my($dbh, $sth, $dbaddress, $wert);
  $wert = "abababab";

	$dbaddress = &makeDSN($dbType,$dbServer,$dbDB,$dbPort);

  $dbh = DBI->connect($dbaddress, $dbUser, $dbPw)
    or die ( &ltext('db_connect', '#2098', "$DBI::errstr") );

  $sth = $dbh->prepare("SELECT confixxfaktor FROM zeiten");
  $sth->execute or die ( &ltext('install_dberror', "$DBI::errstr") );
  $wert = $sth->fetchrow;
  $sth->finish;
  $dbh->disconnect;
  unless($wert == 2){
    die( &ltext('install_dbinstall_failed', $dbDB) );
  }
}

sub getMainSettings {
  my $dbaddress = &makeDSN( $dbType, $dbServer,$dbDB, $dbPort );
  my $dbh = DBI->connect($dbaddress, $dbUser, $dbPw)
    or die ( &ltext('db_connect', '#2098', "$DBI::errstr") );

	my $sql = "SELECT * FROM admin";
	my $sth = $dbh->prepare( $sql ) or
		die "Can't get main settings: $DBI::errstr\n";
	if ( $sth->execute ) {
		my %admin = %{$sth->fetchrow_hashref};

		$user_prefix = $admin{'userprefix'};

		$sth->finish;
	}
	$dbh->disconnect;
}

sub updateDbForSecondary {
  my $dbaddress = &makeDSN( $dbType, $dbServer,$dbDB, $dbPort );
  my $dbh = DBI->connect($dbaddress, $dbUser, $dbPw)
    or die ( &ltext('db_connect', '#2098', "$DBI::errstr") );

  my ($maxpop,$maxemail,$maxautoresponder,$maillist,$sql);
  my $use_mail = ($mta eq "noEmail" || $mta eq "")?0:1;
  $maxpop = $maxemail = $use_mail?'-1':'0';
  $maxautoresponder = $mta?'-1':'0';

#
# mta
#
  $spamassassin_support=0 unless $spamassassin_support;

	if ( $mail_server == 2 ) {

		$sql = "UPDATE admin SET pop=$use_mail,email=$use_mail,webmail=$use_mail".
			",spamfilter=$spamassassin_support,autoresponder=1";

		if ( $majordomo_home && ( -d $majordomo_home ) && ( -x $majordomo_wrapper ) ) {
			$sql .= ",majordomo=1,majordomohome=".$dbh->quote($majordomo_home).
				",majordomoml=".$dbh->quote($majordomo_ldir);
			$maillist = '-1';

		}else{
			$sql .= ",majordomo=0,majordomohome='',majordomoml=''";
			$maillist = '0';
		}

		$dbh->do($sql)
			or die ("#2024: $DBI::errstr\n");
	}
#
# dns
#
  if($dns_server == 2 ){
    $sql="UPDATE admin SET dnr=$use_dnr, dns=$use_dns, ip_pns=".$dbh->quote($ip_pns).
      ",ip_sns=".$dbh->quote($ip_sns);
    $dbh->do($sql)
      or die ("#2024: $DBI::errstr\n");
  }

#
# mta for build-in user & reseller
#
  if($mail_server == 2){
#
# build-in reseller
#
    $sql="UPDATE anbieter SET maxpop=$maxpop,maxpoplimit=0".
      ",maxemail=$maxemail,maxemaillimit=0,maxautoresponder=$maxautoresponder".
      ",maxmaillist=$maillist,maxmaillistlimit=0,spamfilter=$spamassassin_support".
	  " where anbieter=".$dbh->quote('res0');
    $dbh->do($sql)
      or die ("#2024: $DBI::errstr\n");

#
# build-in user
#
    $sql="UPDATE kunden SET maxpop=$maxpop,maxemail=$maxemail,".
      "maxmaillist=$maillist,maxautoresponder=$maxautoresponder,spamfilter=$spamassassin_support".
      " WHERE kunde=".$dbh->quote($user_prefix . '0');
    $dbh->do($sql)
      or die ("#2024: $DBI::errstr\n");
  }

  $dbh->disconnect;
}


sub checkRequirement {

	my $type = @_? shift: $dbType;

	unless ( $type ) {
		$type = &SelectQuestion( &ltext('install_question_selectdb') , 'MySQL', 'PostgreSQL');
		if ( $type eq 'MySQL' ) {
			$type = 'mysql';
		} else {
			$type = 'Pg';
		}
		$dbType = $type;
	}

	my @req = ( 'DBI',
							"DBD::$type",
							'XML::Parser',
							'XML::DOM' );

  &checkAndInstallPkgs( @req );

	foreach my $pkg (@req) {
		unless( &loadPackage( $pkg ) ) {
			die( &ltext('install_question_module_load', $pkg));
		}
	}

}

sub createDir{
  my ($dir) = @_;
	if ($dir ) {
		unless( -d $dir ) {
			print &ltext('install_do_dir_create', $dir);
			&RecCreateDir( $dir, 0755);
		}
  }
}

sub fertig{
  system( "clear" );
  print &ltext('install_install_post', $installDir);
}


sub tmp_conf{
  print "\n";
  print &ltext('install_do_file_copy', "$installDir/confixx_main.conf", "$wDir/../confixx_main.conf");
  copy("$installDir/confixx_main.conf", "$wDir/../confixx_main.conf");
}

sub etc_shells{
	my $shells = "/etc/shells";
  unless ( -T $shells ) {
		return;
	}
	unless(open(FILE,'<',$shells)){
		warn "Error: unable to open file '$shells': $!\n";
		return 0;
	}
	while (<FILE>) {
		chomp;
		if (/^\/bin\/false$/) {
			close( FILE );
			return 2;
		}
	}
	close FILE;

	if ( open( FILE, '>>', $shells ) ){
		print FILE "/bin/false\n";
		close(FILE);
	} else {
		warn "Error: unable to open file '$shells': $!\n";
		return 0;
	}
	return 1;
}

sub show_congratulations() {

    my $PRODNAME_BIG	= "Confixx Professional";
    my $passwd		= 'confixx';
    my $product_bs	= 'SWsoft sales';
    my $sales_email	= 'sales@sw-soft.com';

    print << "EOF";
                             Congratulations!
        All stages of the installation were successfully completed.
        ${PRODNAME_BIG} is now running on the system.
        To complete the system configuration process, proceed to URL:
        http://<your domain name>/admin or
        http://<your ip address>/admin

		LOGIN
		  Username: 'admin'
		  Password: '$passwd'

 ****************************************************************************
 *
 *      NOTE:   A default key file with limited functionality has been
 *              installed for ${PRODNAME_BIG}. The current key allows two
 *              users, two domains, two emails, two pop3 boxes and two ftp 
 *              accounts to be created on the system.
 *              To receive a fully functional key contact the ${product_bs} 
 *              team via email at ${sales_email}
 *
 ****************************************************************************

EOF

}

sub exec_script($) {
	my ($exec_script) = @_;
	my (undef, $main_script, undef) = caller;
	my ($return);
	unless ($return = do $exec_script) {
		warn "Failed parsing of '$exec_script': $@\n"   if $@;
		warn "Failed reading '$exec_script' file: $!\n" unless defined $return;
		warn "Failed execution of '$exec_script'\n"     unless $return;
		return 0;
	}
	return 1;
}

sub report_error($) {
  my ($str) = @_;

  warn "PROBLEM FOUND: $str\n";
  my $logfile = "$installDir/INSTALLATION_PROBLEMS.LOG";
  unless (open(FILE, ">>$logfile")) {
    warn "Warning: can not save problem description to $logfile: can not open file $logfile: $!\n";
    return;
  }
  print FILE "$str\n";
  unless (close(FILE)) {
    warn "Warning: can not save problem description to $logfile: can not close file $logfile: $!\n";
    return;
  }
}

## /UNTERPROGRAMME
