#use strict;

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

#==================================================
#
# global settings
#

package main;

use Exporter;
#@ISA = qw( Exporter );

sub safe_do($;$);

use vars qw( %lang_text %bin @EXPORT);

use vars qw(
$OSTYPE
$version
$user_homeDir
$installDir
$stdShell
$userGroup
$popGroup
$giduser
$gidpop
$passwdDir
$shadowDir
$groupDir
$min_uid
$max_uid
$hostname
$PIDDir
$user_prefix
$use_quota
$mail_quota
$user_quota
$inode_std
$pm_apache_reload
$pm_apache_start
$pm_apache_user
$pm_apache_name
$pm_mail_reload
$pm_mail_start
$pm_mail_user
$pm_mail_name
$pm_bind_reload
$pm_bind_start
$pm_bind_user
$pm_bind_name
$pm_spamassassin_reload
$pm_spamassassin_start
$pm_spamassassin_user
$pm_spamassassin_name
$pm_ftpd_noscript
$pm_ftpd_reload
$pm_ftpd_start
$null_device

$language
$langfileversion
$lang_version
$index_wap
$index_php
$index_ssi
$index_html
$show_emailtransfer
$max_emailrcpts
$disable_md5
$virtuozzo
$dot_passwd
$restore_users_permissions

$apacheBackupSize
$apacheBackupDay
$apacheBackupLocal
$apacheBackupExpire
$apacheBackupDir
$apacheLogDir
$apacheDefSSL
$confixx_homeDir
$confixx_htmlDir
$confixx_cgiDir
$confixx_tmpDir
$confixx_binDir
$confixx_sbinDir
$confixx_IP
$httpd_conf
$vhost_conf
$mhost_conf
$apacheGroup
$apacheUser
$gidapache
$confixx_uid
$confixx_gid
$confixx_user
$confixx_group
$sslKeyDir
$sslCrtDir
$fpfake
$fp_homeDir
$fp_uid
$fp_gid
$apache_root
$local_cgi
$secure_fp
$excludeNVH
$httpbytes
$httpd

$mta
$mailSpool
$maildrop
$mailBoxName
$virtUserTableDB
$virtUserTableFile
$localDomainsFile
$bin_makemap
$bin_postmap
$bin_postfix
$bin_newaliases
$MailConfigFile
$pop_homeDir
$aliases
$bin_autorespond
$use_autorespond
$mta_uid
$mta_gid
$bin_sendmail
$mail_realHome
$mail_server

$spamassassin_support
$spamassassinConfig
$spamassassinUid
$spamassassinScript

$bin_confixxevent
$use_events
$scponly_shell
$scponly_chroot
$coldfusion_support
$cronjobs_support
$append_mail_disk_space  

$majordomo_home
$majordomo_wrapper
$majordomo_ldir
$majordomo_user
$majordomo_quota
$majordomo_config

$idn_shell
$idn_vendor
$iconv_shell
$iconv_utf8

$bin_find
$bin_cp
$bin_grep
$bin_chown
$bin_chmod
$bin_rm
$bin_du
$bin_ifconfig
$bin_webalizer
$bin_fpsrvadm
$bin_openssl
$bin_psql
$bin_mysql
$bin_mysqldump
$bin_gzip
$bin_tar
$bin_unzip
$bin_iconv
$bin_idn
$bin_su
$bin_quota
$bin_quotaon
$bin_quotaoff
$bin_quotacheck
$bin_setquota
$bin_df
$bin_ldd
$bin_perl

$ftpDaemon
$ftpConfFile
$ftpConfAdmin
$ftpLogFile
$ftpbytes
$chrootUsers
$ftpEmail
$ftpdType
$ftp_bin_ls

$dbType
$dbServer
$dbPort
$dbUser
$dbPw
$dbDB
$dbMysqlHost
$dbMysqlVersion
$mysqlUserServer
$mysqlUserPort
$mysqlUserUser
$mysqlUserPw
$mysqlUserHost
$mysqlUserVersion

$mysql_homeDir
$use_mysqlshell
$dbQuotes

$mail_pop3Server

$dns_server
$dns_type
$dns_dir
$dns_extension
$dns_configure
$dns_serverid
$dns_chroot
$dns_copyconf
$dns_conf

$db_address
$no_pipelog_mode
$rpm_version_flag
$no_questions_mode

$stdIP
$stdDomain
$use_SSL
$confixx_domain
$confixx_IP
$confixx_droot
$confixx_accessLog
$confixx_errorLog
$confixx_admin_user
$confixx_admin_pw
$confixx_admin_pw_crypt
$use_scponly
$use_webmail
$use_webftp
$modpython_support
$mysql_shell_user
$mysql_shell_user_host
$mysql_shell_uid
$mysql_shell_user_pw
$mysql_shell_user_pw_crypt
$phpmyadminpfad
$use_phpmyadmin
$use_mysql
$install_default_users
$lokaleips
$dbRootUser
$dbRootPw
$use_dns
$use_dnr
$ip_pns
$ip_sns

$confixxState

);

#
#
#=========================================================
#
#

package lib_module_common;


use File::Basename;
use Cwd;
use Cwd qw( abs_path getcwd );

use DBI;

use Common::Config;

# The module performs reading of confixx configuration file 
# and connection to database

use vars qw(@ISA @EXPORT @EXPORT_OK);

@ISA = qw( Exporter );

#
# Below is the list of ALL configuration variables for Confixx
# It is required to make this variables visible in global scope
# (compatibility issues)
#
@EXPORT = qw ( &ltext &header2 &dbg_mess &getConfPath &getCanonPath
							 &isLoadedPath &initConfig $Config	&initConfig
							 &soft_error &hard_error );

@EXPORT_OK = qw( &loadConfFile &restoreFromAdmin &getCanonPath );

my $Config;
my $debug_mode = 0;


# find and read confixx configuration file(s)
#
# parameters: <dir>,<dir>,... 
#          or <path>
#          or <empty>
# 
sub loadConfFile{
  my ($conf_file,$dir,%stdLoc,@std_loc, @files, $file);

	$conf_file = shift;
	unless( $conf_file && -T $conf_file ) {
		unshift @_,$conf_file;
		%stdLoc = map{ $_=> 1 } grep{ $_ && -d $_ } @_ ;
		@std_loc = grep{ $stdLoc{$_} } @_;

		my $base = dirname( $0 );
		unless( $base =~ /^\// ) {
			$base = &abs_path( $base );
		}	

		map { push @std_loc,$_; $stdLoc{$_} = 1 } 
			grep { !$stdLoc{$_} } ( $base, "$base/..", "$base/../..",
															'/root/confixx', '/usr/local' );
	
		unless( $^X =~ /(^|[\/\\])perl(\.exe)?$/ ) {
			$base = dirname($^X);
			unless ( $base=~/^\// ) {
				$base = &abs_path( $base );
			}	
			map { push @std_loc,$_; $stdLoc{$_} = 1 }
				grep { !$stdLoc{$_} } ($base, "$base/..", "$base/../..");
		}

	# looking for a confixx_main.conf
		foreach my $path ( @std_loc ) {
      $file = "$path/confixx_main.conf";
      if ( -T $file ) {
				$file = &getCanonPath($file);
				$conf_file ||= $file;
				push @files, $file;
      }
    }
  }

  unless ( -T $conf_file ) {
    die("Couldn't find confixx_main.conf at (@std_loc)\n");	# FATAL error
  }

	if ( @files > 1 ) {
		foreach $file (@files) {
			$path = dirname( $file );
			my($dir);
			if ( open( IN, '<', $file ) ){
				while ( <IN> ) {
					chomp;

					next if /^\s*(#|$)/; ## skip empty line & comment

					if ( /^\s*\$installDir\s*=\s*(.*)\s*;/ ){
						if ( ( $dir = $1 ) =~ /^('|")(.*)\1/ ) {
							$dir = $2;
						}
						last;
					}
				}
				close ( IN );
				if ( $dir eq $path ) {
					$conf_file = $file;
					last;
				}
			}
		}
	}

	# read config: old style 
  &dbg_mess (1, "Configuration file is found: $conf_file");

package main; ## go to main context

  do $conf_file;

	if ( $@ ) {
		warn "Compile error in main config ('$conf_file'):\n$@\n";
	}

package lib_module_common; ## return to module's context


# read config: new style
  if ( ref( $Config ) !~ /Config/ ) {
    $Config = Common::Config->new();
  }

  $Config->read_config( $conf_file );

  &dbg_mess( 1, "%d record(s) was read from $conf_file", $Config->numParams() );

  return $Config;
}

#
# restore parameters from 'admin'-table
#
# arguments:
# $dbh - DBI-connect to SQL-base (optioanl)
#
sub restoreFromAdmin {
  my $dbh = shift;
	my ($needDisconnect);
  unless( ref($dbh) =~ /DBI/ ) {
    $dbh = DBI->connect($db_address,$dbUser, $dbPw)
      or die ("Unable to connect to SQL-base: $DBI::errstr\n");
    $needDisconnect=1;
  }
  my $sth=$dbh->prepare("select * from admin");
  my $ptrHash;
  if ( $sth && $sth->execute){
    $ptrHash = $sth->fetchrow_hashref;
    $::stdDomain = $ptrHash->{'standarddomain'};
    $sth->finish;
  }
  if($needDisconnect){
    $dbh->disconnect;
  }
  return $ptrHash;
}

sub getCanonPath(){
  my $path = shift;
  unless ($path){
    return $path;
  }

	if ( $path eq '.' ){
		return getcwd();
	}

  my ($name,$dir) = fileparse( $path );
  
  my $abs =  ( $dir =~ /^\// )? 1: 0;
  unless ($abs){
    if ($dir =~ /^~([^\/]*)/){
			my ($home,$name);
			$name = $1;
			if ( $name ) {
				$home = (getpwnam( $name ))[7];
			} else {
				$home = (getpwuid( $EUID ))[7];
			}
			$dir =~ s/^~[^\/]*/$home/;
			$abs = 1;
		} elsif ( $dir =~ /^\.(\/|$)/ ) {
			my $cwd = getcwd();
			$dir =~ s/^\./$cwd/;
			$abs = 1;
    } elsif ( !$dir ) {
			$dir = getcwd();
			$abs = 1;
		}
  }

#
# working with . & ..
#
  my @chunks = split(/\//,$dir);
	my ($i,$j);
  for ( $i=0; $i<@chunks; $i++ ) {
    if ( $chunks[$i]=~/^\.(\.?)$/ ) {
      if ( $1 ) {
				for ( $j=$i-1; $j>=0; $j-- ) {
					if ( $chunks[$j] ) {
						$chunks[$j] = '';
						last;
					}
				}
      }
      $chunks[$i] = '';
    }
  }

  $dir = '/' if $abs;
	$dir .= join('/', grep{$_} @chunks).'/';

  return "$dir$name";
}

sub getConfPath(){
  if ( ref($Config) =~ /Config/ ) {
    my $path = $Config->Path();
    return $path;
  } else {
    print "Undefined \$Config\n";
    return undef;
  }
}

sub isLoadedPath(){
  if ( ref($Config) =~ /Config/ ) {
    my $path = shift;
    return $Config->IsReaded($path);

  } else {
    print "Undefined \$Config\n";
    return undef;
  }
}

# localize text message
#
sub ltext {

  my $text_name = shift;
  if (!scalar(%main::lang_text)) {
		$::language ||= 'en';
		my ($langFile);
		if ( $::installDir && -d $::installDir && -d "$::installDir/admin/languages" ) {
			$langFile = "$::installDir/admin/languages/$::language/scripts.local";
		} else {
			my $wDir = dirname($0);
			foreach my $dir ( $wDir, "$wDir/..", '.', '..' ) {
				if ( -d "$dir/languages" ) {
					$langFile = "$dir/languages/$::language/scripts.local";
					last;
				}
			}
		}
package main;
    do $langFile;
package lib_module_common;
    
    &dbg_mess(1, "%d record(s) was read from $langFile\n", scalar(%main::lang_text));
	}
  
	unless ( defined($main::lang_text{$text_name} ) ) {
    return "Sorry, text $text_name not found!";

  } else {
    my @VAR = @_;
    my $text = $main::lang_text{$text_name};
    $text =~ s/\$VAR\[(\d+)\]/$VAR[$1]/g;
    if ($text) {
      return $text;
    } else {
      return "Sorry, localizing text $text_name failed!";
    }
  }
}

sub dbg_mess {
    my ($level, $format, @args) = @_;
    return if ($debug_mode < $level);
    # we can not call 'sprintf @args', because in this case sprintf
    # forces @args to scalar context
    my $string = sprintf $format, @args;
    print STDERR "DBG: $string\n";
}

# output formatted header
#
sub header2{
  my ($header) = @_;
  my ($length, $count, $fix, $space);
  $fix = 35;
  $length = length($header);
  if($length > $fix){
    $fix = $length + 2;
  }
  $space = int(( $fix - $length ) / 2);
	print '#' x $fix, "\n";
	print ' ' x $space, $header,"\n";
	print '#' x $fix, "\n\n";
}

sub initConfig {

	my @dirs = @_;

	unless( ref($Config) =~ /Config/ ) {

		$Config = &loadConfFile( @dirs );

	}
	return $Config;
}

sub hard_error {
  my ($msg) = @_;

  print "$msg\n";
  exit 1;

}

sub soft_error {
  my ($msg) = @_;

  print "$msg\n";

}

#
#
#=========================================================
#
#

package main;

sub safe_do($;$) {
	my ( $script, $no_debug) = @_;
	my ( $ret );
	if ( $script ) {
		$ret = do $script;
		if ( $@ ) {
			&lib_module_common::hard_error( $no_debug? $@ :
																			"Error: safe_do: do script '$script' failed:\n$@\n" );
		}
	} else {
		&lib_module_common::soft_error( "Warning: safe_do: do nothing\n" );
	}
	return $ret;
}

#
#
#===================================================

return 1;

