package SB::OS;

use strict;
use warnings;

use Carp;
use FindBin;
use Cwd;

BEGIN {
	use Exporter;
	our (@ISA, $VERSION, @EXPORT, @EXPORT_OK);
	$VERSION =  4.00;
	@ISA = qw(Exporter);
	@EXPORT    = qw();
	@EXPORT_OK = qw();
}

use constant PSA_CONF => '/etc/psa/psa.conf';

my %HTTPDUSER = ( 
	redhat      => "apache:apache",
	debian      => "www-data:www-data",
	suse        => "wwwrun:www",
	darwin      => "www:www",
	freebsd     => "www:www",
);

#VHost directories of different OS'es:
my %APACHEVHOSTDIR = (
	redhat   => "/etc/httpd/conf.d",
	debian   => "/etc/apache2/sites-available",
	suse     => "/etc/apache2/vhosts.d",
	freebsd  => "/usr/local/etc/apache2/Includes",
	darwin   => "/private/etc/httpd/users",
	cpanel	 => "/etc/httpd/conf/sites",
);

my %ERRORLOGDIR = (
	redhat         => "logs/sitebuilder_error.log",
	debian         => "/var/log/apache2/sitebuilder_error.log",
	suse           => "/var/log/apache2/sitebuilder_error.log",
	freebsd        => "/var/log/sitebuilder_error.log",
	freebsd_psa    => "/var/log/sitebuilder_error.log",
	darwin         => "/var/log/httpd/sitebuilder_error.log",
	darwin_psa     => "/usr/local/psa/apache/logs/sitebuilder_error.log",
	cpanel		   => "/etc/httpd/domlogs/sitebuilder_error.log",
);

#Apache control scripts of different OS'es:
our %APACHECTLCMD =  (
	redhat   => { 
		reload => "/etc/init.d/httpd graceful",
		start  => "/etc/init.d/httpd start" 
	},
	debian   => { 
		reload => "/etc/init.d/apache2 reload",
		start  => "/etc/init.d/apache2 start" 
	},
	suse     => { 
		reload => "/etc/init.d/apache2 reload",
		start  => "/etc/init.d/apache2 start"
	},
	freebsd  => { 
		reload => "/usr/local/etc/rc.d/apache2.sh reload",
		start  => "/usr/local/etc/rc.d/apache2.sh start"
	},
	darwin   => { 
		reload => "/System/Library/StartupItems/Apache/Apache restart",
		start  => "/System/Library/StartupItems/Apache/Apache start"
	},
	psa => { 
		reload => "/admin/sbin/websrvmng -v -a",
		start => "/admin/sbin/websrvmng -v -a" 
	},
	cpanel => {
		reload => "/etc/httpd/bin/apachectl graceful",
		start => "/etc/httpd/bin/apachectl start"
	}
);

sub uname {
	return `uname`;
}

sub getOsName {
	my $name;
	my %os = (
		darwin => sub { 
			return ($^O eq "darwin");
		},
		debian  => sub { 
			return ($^O eq "linux") && ( -e "/etc/debian_version"); 
		},
		freebsd => sub { 
			return ($^O eq "freebsd") && (-e "/etc/rc.conf"); 
		},
		redhat  => sub { 
			return ($^O eq "linux") && (-e "/etc/redhat-release"); 
		},
		suse    => sub { 
			return ($^O eq "linux") && (-e "/etc/SuSE-release"); 
		},
	);
	foreach my $name (sort {$b cmp $a} (keys %os)) {
		if ($os{$name}->()) {
			return $name;
		}
	}
	confess("Cannot determine OS version") unless $name;
}

sub getInstallPrefix() {
	return Cwd::realpath($FindBin::RealBin . "/../");
	#return "/opt" if (getOsName() eq "debian");
	#return "/usr/local";
}

sub getOsVersion {
}

sub getApacheStartCmd {
	my $osname = getOsName();
	if (hasPleskInstalled()) {
		my $cfg = parsePleskConfig();
		return $cfg->{'PRODUCT_ROOT_D'} . $APACHECTLCMD{"psa"}->{'start'};
	}
	elsif (hasCPanelInstalled()) {
		$osname = "cpanel";
	}
	return $APACHECTLCMD{$osname}->{'start'};
}

sub getApacheReloadCmd {
	my $osname = getOsName();
	if (hasPleskInstalled()) {
		my $cfg = parsePleskConfig();
		return $cfg->{'PRODUCT_ROOT_D'} . $APACHECTLCMD{"psa"}->{'reload'};
	}
	elsif (hasCPanelInstalled()) {
		$osname = "cpanel";
	}
	return $APACHECTLCMD{$osname}->{'reload'};
}

sub getApacheVHostDir {
	my $osname = getOsName();
	if (hasPleskInstalled()) {
		my $cfg = parsePleskConfig();
		return $cfg->{'HTTPD_INCLUDE_D'} if (exists($cfg->{'HTTPD_INCLUDE_D'}));
		return $cfg->{'HTTPD_CONF_D'}
	}
	elsif (hasCPanelInstalled()) {
		$osname = "cpanel";
	}
	return $APACHEVHOSTDIR{$osname};
}

sub getApacheErrorLogDir {
	my $osname = getOsName();
	if (hasPleskInstalled()) {
		return $ERRORLOGDIR{"${osname}_psa"} 
			if (exists($ERRORLOGDIR{"${osname}_psa"}));
	}
	elsif (hasCPanelInstalled()) {
		$osname = "cpanel";
	}
	return $ERRORLOGDIR{$osname};
}

sub getApacheUser() {
	if (hasPleskInstalled()) {
		return _getPleskApacheUser();
	}
	elsif (hasCPanelInstalled()) {
		return _getApacheUser("/etc/httpd/conf/httpd.conf");
	}
	else {
		my $osname = getOsName();
		return $HTTPDUSER{$osname};
	}
}

sub hasCPanelInstalled {
	return (-d "/usr/local/cpanel");
}

sub hasPleskInstalled {
	return (-e PSA_CONF);
}

sub parsePleskConfig {
	my $psa_conf = shift;
	$psa_conf = PSA_CONF unless $psa_conf;
	my %config = ();
	if  ( -e $psa_conf ) {
		open(F, $psa_conf) or return \%config;
		while (<F>) {
			chomp;
			next if m/^\s*#/;
			next unless $_;
			my ($key, $value) = split ;
			$config{$key} = $value;
		}
		close(F);
	}
	return \%config;
}

sub _getPleskApacheUser() {
	my $cfg = parsePleskConfig();
	return _getApacheUser($cfg->{'HTTPD_CONF_D'} . "/httpd.conf");
}

sub _getApacheUser($) {
	my $htconf = shift;	
	my $os = getOsName();
	my ($defuser, $defgroup) = split(':', $HTTPDUSER{$os});
	my %owner = (user => $defuser, group => $defgroup);

	open(HTTPDCFG, $htconf) or
		return $owner{'user'} . ":" . $owner{'group'};

	foreach (<HTTPDCFG>) {
		if (/^\s*User\s+(.*)$/i) {
			$owner{'user'} = $1;
		}
		if (/^\s*Group\s+(.*)$/i) {
			$owner{'group'} = $1;
		}
	}
	close(HTTPDCFG);

	return $owner{'user'} . ":" . $owner{'group'};
}

1;
