#!/usr/local/bin/perl
# create_virt.cgi
# Create a new virtual host.

require './apache-lib.pl';
&ReadParse();
$access{'create'} || &error($text{'cvirt_ecannot'});
&error_setup($text{'cvirt_err'});
$conf = &get_config();

# Validate inputs
if ($in{'addr_def'}) {
	if ($httpd_modules{'core'} >= 1.2) { $addr = "_default_"; }
	else { $addr = "*"; }
	}
elsif ($in{'addr'} !~ /\S/) { &error($text{'cvirt_eaddr1'}); }
elsif (!gethostbyname($in{'addr'}) && !&check_ipaddress($in{'addr'}) &&
       $in{'addr'} ne '*')
	{ &error(&text('cvirt_eaddr2', $in{'addr'})); }
else { $addr = $in{'addr'}; }

if ($in{'port_mode'} == 0) { $port = ""; }
elsif ($in{'port_mode'} == 1) { $port = ":*"; }
elsif ($in{'port'} !~ /^\d+$/) { &error(&text('cvirt_eport', $in{'port'})); }
else { $port = ":$in{'port'}"; }
if (!$in{'name_def'}) {
	@names = split(/\s+/, $in{'name'});
	@names || &error(&text('cvirt_ename', $in{'name'}));
	}

# Check if the virtual server already exists
if ($in{'name_def'}) {
	$aclname = "$addr$port";
	}
else {
	$aclname = "$in{'name'}$port";
	}
@virt = &find_directive_struct("VirtualHost", $conf);
foreach $v (@virt) {
	if (&virt_acl_name($v) eq $aclname) {
		&error($text{'cvirt_etaken'});
		}
	}

# Check if the root directory is allowed
!$in{'root'} || &allowed_auth_file($in{'root'}) ||
	&error(&text('cvirt_eroot3', $in{'root'}));

if ($in{'root'} && !-d $in{'root'}) {
	# create the document root
	mkdir($in{'root'}, 0755) ||
		&error(&text('cvirt_eroot2', $in{'root'}, $!));
	$user = &find_directive("User", $conf);
	$group = &find_directive("Group", $conf);
	$uid = $user ? getpwnam($user) : 0;
	$gid = $group ? getgrnam($group) : 0;
	chown($uid, $gid, $in{'root'});
	}

# find file to add to
if ($in{'fmode'} == 0) {
	# use the first file in config (usually httpd.conf)
	$vconf = &get_virtual_config();
	$f = $vconf->[0]->{'file'};
	for($j=0; $vconf->[$j]->{'file'} eq $f; $j++) { }
	$l = $vconf->[$j-1]->{'eline'}+1;
	}
elsif ($in{'fmode'} == 1) {
	$f = $config{'virt_file'};
	}
else {
	$f = $in{'file'};
	}
-r $f || open(FILE, ">>$f") || &error(&text('cvirt_efile', $f, $!));
close(FILE);

&lock_apache_files();
&lock_file($f);

local $ip = &to_ipaddress($in{'addr'});

if ($in{'listen'} && !$in{'addr_def'} && $ip) {
	# add Listen if needed
	local @listen = &find_directive("Listen", $conf);
	local $lfound;
	foreach $l (@listen) {
		$lfound++ if ($l eq '*' || $l =~ /^\*:\d+$/ ||
			      ($l =~ /^(\S+):\d+$/ && $1 eq $ip) || $l eq $ip);
		}
	if (!$lfound && @listen > 0) {
		# Apache is listening on some IP addresses, but not the
		# entered one.
		local $lip;
		if ($httpd_modules{'core'} >= 2) {
			$lip = $in{'port_mode'} == 2 ? "$ip:$in{'port'}"
						     : "$ip:80";
			}
		else {
			$lip = $in{'port_mode'} == 2 ? "$ip:$in{'port'}" : $ip;
			}
		&save_directive("Listen", [ @listen, $lip ], $conf, $conf);
		}
	}

# add NameVirtualHost if needed
if ($in{'nv'} && !$in{'addr_def'} && $ip) {
	local $found;
	local @nv = &find_directive("NameVirtualHost", $conf);
	foreach $nv (@nv) {
		$found++ if ($nv eq $ip ||
			     $nv =~ /^(\S+):(\S+)/ && $1 eq $ip ||
			     $nv eq '*');
		}
	if (!$found) {
		&save_directive("NameVirtualHost", [ @nv, $ip ], $conf, $conf);
		}
	}

# get directives from clone
if ($in{'clone'} ne '') {
	$clone = $conf->[$in{'clone'}];
	@cmems = grep { $_->{'name'} ne 'ServerName' &&
		        $_->{'name'} ne 'Port' &&
		        $_->{'name'} ne 'DocumentRoot' &&
		        $_->{'name'} ne 'ServerAlias' } @{$clone->{'members'}};
	@clines = &directive_lines(@cmems);
	}

$lref = &read_file_lines($f);
push(@$lref, "");
push(@$lref, "<VirtualHost $addr$port>");
push(@$lref, "DocumentRoot $in{'root'}") if ($in{'root'});
if (@names) {
	push(@$lref, "ServerName $names[0]");
	shift(@names);
	foreach $sa (@names) {
		push(@$lref, "ServerAlias $sa");
		}
	}
push(@$lref, @clines);
push(@$lref, "</VirtualHost>");
&flush_file_lines();
&unlock_file($f);
&unlock_apache_files();
&webmin_log("virt", "create", ($in{'name_def'} ? $addr : $in{'name'}).$port,
	    \%in);

# add to acl
if ($access{'virts'} ne '*') {
	$access{'virts'} .= " $aclname";
	&save_module_acl(\%access);
	}
&redirect("");

