#!/usr/local/bin/perl
# index.cgi
# Display a list of all virtual servers, and links for various types
# of global configuration

require './apache-lib.pl';

# check for the base directory
if (!(-d $config{'httpd_dir'})) {
	&header($text{'index_title'}, "", undef, 1, 1);
	print "<hr><p>\n";
	print &text('index_eroot', "<tt>$config{'httpd_dir'}</tt>",
		    "$gconfig{'webprefix'}/config.cgi?$module_name"),"<p>\n";
	print "<hr>\n";
	&footer("/", $text{'index'});
	exit;
	}

# check for the executable
if (!-x $config{'httpd_path'} || -d $config{'httpd_path'}) {
	&header($text{'index_title'}, "", undef, 1, 1);
	print "<hr><p>\n";
	print &text('index_eserver', "<tt>$config{'httpd_path'}</tt>",
		    "$gconfig{'webprefix'}/config.cgi?$module_name"),"<p>\n";
	print "<hr>\n";
	&footer("/", $text{'index'});
	exit;
	}

# check if this is a new apache install, by looking for -dist files
$conf = "$config{'httpd_dir'}/etc";
if (!-d $conf) { $conf = "$config{'httpd_dir'}/conf"; }
if (!$config{'httpd_conf'} && !(-e "$conf/httpd.conf") &&
    (-e "$conf/httpd.conf-dist") && (-d $conf)) {
	# copy all the .dist files and fix up @@ServerRoot@@ references
	# Only needed for apache versions < 1.3, which don't do this as part
	# of the 'make install'
	$sroot = $config{'httpd_dir'};
	opendir(CONF, $conf);
	foreach $f (readdir(CONF)) {
		if ($f =~ /^(.*)-dist$/) {
			open(DIST, "$conf/$f");
			@dist = <DIST>;
			close(DIST);
			open(REAL, "> $conf/$1");
			foreach (@dist) {
				s/\/usr\/local\/etc\/httpd/$sroot/g;
				s/\@\@ServerRoot\@\@/$sroot/g;
				print REAL $_;
				}
			close(REAL);
			}
		}
	close(CONF);
	}

# check for the httpd.conf file
if ($config{'httpd_conf'}) { $htconf = $config{'httpd_conf'}; }
else { $htconf = "$conf/httpd.conf"; }
if (!-e $htconf) {
	# still doesn't exist!
	&header($text{'index_title'}, "", undef, 1, 1);
	print "<hr><p>\n";
	print &text('index_econf', "<tt>$htconf</tt>",
		    "$gconfig{'webprefix'}/config.cgi?$module_name"),"<p>\n";
	print "<hr>\n";
	&footer("/", $text{'index'});
	exit;
	}

# check if apache executable has changed..
@st = stat($config{'httpd_path'});
if ($st[7] != $httpd_size || $httpd_modules{'core'} < 1) {
	# Changed .. redirect to reconfig form
	&redirect("/$module_name/reconfig_form.cgi?size=$st[7]");
	exit;
	}

# check for multiple port directives
$conf = &get_config();
@prt = &find_directive("Port", $conf);
if (@prt > 1 && $httpd_modules{'core'} < 1.3) {
	&header($text{'index_title'}, "", undef, 1, 1);
	print "<hr><p>\n";
	print &text('index_eports', 'Port'),"<p>\n";
	print "<hr>\n";
	&footer("/", $text{'index'});
	exit;
	}

# add default server
if (&can_edit_virt()) {
	push(@vname, $text{'index_defserv'});
	push(@vlink, "virt_index.cgi");
	push(@vdesc, $text{'index_defdesc1'});
	push(@vaddr, $text{'index_any'});
	push(@vport, $text{'index_any'});
	push(@vserv, &def(&find_directive("ServerName", $conf),
			  $text{'index_auto'}));
	push(@vroot, &def(&find_directive("DocumentRoot", $conf),
			  $text{'index_auto'}));
	$showing_default++;
	}

# add other servers
@virt = &find_directive_struct("VirtualHost", $conf);
if ($httpd_modules{'core'} >= 1.3) {
	# build list of name-based virtual host IP addresses
	@nv = &find_directive("NameVirtualHost", $conf);
	foreach $nv (@nv) {
		$nv{$nv eq "*" ? "*" : &to_ipaddress($nv)}++;
		}
	}
elsif ($httpd_modules{'core'} >= 1.2) {
	# only one name-based virtual host IP address - the default address
	$ba = &find_directive("ServerName", $conf);
	$nv{&to_ipaddress($ba ? $ba : &get_system_hostname())}++;
	}
@virt = grep { &can_edit_virt($_) } @virt;
if ($config{'show_order'} == 1) {
	# sort by server name
	@virt = sort { &server_name_sort($a) cmp &server_name_sort($b) } @virt;
	}
elsif ($config{'show_order'} == 2) {
	# sort by IP address
	@virt = sort { &server_ip_sort($a) cmp &server_ip_sort($b) } @virt;
	}
foreach $v (@virt) {
	$vm = $v->{'members'};
	if ($v->{'value'} =~ /^(\S+):(\S+)$/) {
		$addr = $1;
		$port = $2;
		}
	else {
		$addr = $v->{'value'};
		if ($httpd_modules{'core'} < 2.0) {
			$port = &def(&find_directive("Port", $conf), 80);
			}
		else {
			$port = "*";
			}
		}
	push(@vname, $text{'index_virt'});
	push(@vlink, "virt_index.cgi?virt=".&indexof($v, @$conf));
	$sname = &find_directive("ServerName", $vm);
	if ($nv{"*"}) {
		if ($addr eq "_default_" || $addr eq "*") {
			push(@vdesc, &text('index_vnamed', "<tt>$sname</tt>"));
			}
		else {
			push(@vdesc, &text('index_vname', "<tt>$sname</tt>",
					   "<tt>$addr</tt>"));
			}
		}
	elsif ($addr ne "_default_" && $addr ne "*" && $nv{&to_ipaddress($addr)}) {
		push(@vdesc, &text('index_vname', "<tt>$sname</tt>",
				   "<tt>$addr</tt>"));
		}
	elsif (($addr eq "_default_" || $addr eq "*") && $port eq "*") {
		push(@vdesc, $text{'index_vdef'});
		$vdesc[0] = $text{'index_defdesc2'};
		}
	elsif ($addr eq "_default_" || $addr eq "*") {
		push(@vdesc, &text('index_vport', $port));
		}
	elsif ($port eq "*") {
		push(@vdesc, &text('index_vaddr', "<tt>$addr</tt>"));
		}
	else {
		push(@vdesc, &text('index_vaddrport', "<tt>$addr</tt>", $port));
		}
	push(@vaddr, $addr eq "_default_" || $addr eq "*" ? $text{'index_any'}
							  : $addr);
	push(@vport, $port eq "*" ? $text{'index_any'} : $port);
	push(@vserv, &def(&find_vdirective("ServerName", $vm, $conf),
			  $text{'index_auto'}));
	push(@vroot, &def(&find_vdirective("DocumentRoot", $vm, $conf),
			  $text{'index_default'}));
	$cname{$v} = sprintf "%s:%s (%s)", $vserv[@vserv-1], $vport[@vport-1],
					   $vroot[@vroot-1];
	}

# global config options
$ver = $httpd_modules{'core'};
$ver =~ s/^(\d+)\.(\d)(\d+)$/$1.$2.$3/;
&header($text{'index_title'}, "", undef, 1, 1, undef, &restart_button()."<br>".
	&help_search_link("apache", "man", "doc", "google"), undef, undef,
	&text('index_version', $ver));
if ($access{'global'}) {
	print "<hr>\n";
	print "<h3>$text{'index_global'}</h3>\n";
	if ($access{'global'} == 1) {
		$ht_icon = { "icon" => "images/dir.gif",
			     "name" => $text{'htaccess_title'},
			     "link" => "htaccess.cgi" };
		$rc_icon = { "icon" => "images/recon.gif",
			     "name" => $text{'reconfig_title'},
			     "link" =>
				"reconfig_form.cgi?size=$httpd_size&vol=1" };
		$df_icon = { "icon" => "images/defines.gif",
			     "name" => $text{'defines_title'},
			     "link" => "edit_defines.cgi" };
		$ed_icon = { "icon" => "images/edit.gif",
			     "name" => $text{'manual_configs'},
			     "link" => "allmanual_form.cgi" };
		$ds_icon = { "icon" => "images/virt.gif",
			     "name" => $text{'index_defserv'},
			     "link" => "virt_index.cgi" };
		&config_icons("global", "edit_global.cgi?",
			      $ht_icon, $rc_icon, $df_icon,
			      $access{'types'} eq '*' &&
			      $access{'virts'} eq "*" ? ( $ed_icon ) : ( ),
			      $showing_default &&
			      @vname > $config{'max_servers'} &&
			      $config{'max_servers'} ? ( $ds_icon ) : ( ) );
		}
	else {
		&icons_table([ "htaccess.cgi" ],
			     [ $text{'htaccess_title'} ],
			     [ "images/dir.gif" ]);
		}
	}

# show virtual hosts header
if ($access{'virts'}) {
	print "<hr>\n";
	print "<h3>$text{'index_virts'}</h3>\n";
	}

# display servers
$formno = 0;
if ($config{'max_servers'} && @vname > $config{'max_servers'}) {
	# as search form for people with lots and lots of servers
	print "<b>$text{'index_toomany'}</b><br>\n";
	print "<form action=search_virt.cgi>\n";
	print "<b>$text{'index_find'}</b> <select name=field>\n";
	print "<option value=name checked> $text{'index_name'}\n";
	print "<option value=port> $text{'index_port'}\n";
	print "<option value=addr> $text{'index_addr'}\n";
	print "<option value=root> $text{'index_root'}\n";
	print "</select> <select name=match>\n";
	print "<option value=0 checked>$text{'index_equals'}\n";
	print "<option value=1>$text{'index_matches'}\n";
	print "<option value=2>$text{'index_nequals'}\n";
	print "<option value=3>$text{'index_nmatches'}\n";
	print "</select> <input name=what size=15>&nbsp;&nbsp;\n";
	print "<input type=submit value=\"$text{'find'}\"></form>\n";
	$formno++;
	}
elsif ($config{'show_list'} && scalar(@vname)) {
	# as list for people with lots of servers
	print "<table width=100% border=1>\n";
	print "<tr $tb> <td><b>$text{'index_type'}</b></td> ",
	      "<td><b>$text{'index_addr'}</b></td> ",
	      "<td><b>$text{'index_port'}</b></td> ",
	      "<td><b>$text{'index_name'}</b></td> ",
	      "<td><b>$text{'index_root'}</b></td> </tr>\n";
	for($i=0; $i<@vname; $i++) {
		print "<tr $cb>\n";
		print "<td><a href=\"$vlink[$i]\">$vname[$i]</a></td>\n";
		print "<td>",&html_escape($vaddr[$i]),"</td>\n";
		print "<td>",&html_escape($vport[$i]),"</td>\n";
		print "<td>",&html_escape($vserv[$i]),"</td>\n";
		print "<td>",&html_escape($vroot[$i]),"</td>\n";
		print "</tr>\n";
		}
	print "</table>\n";
	}
else {
	# as icons for niceness
	print "<table width=100% cellpadding=5>\n";
	for($i=0; $i<@vname; $i++) {
		print "<tr> <td valign=top align=center nowrap>";
		&generate_icon("images/virt.gif", $vname[$i], $vlink[$i]);
		print "</td> <td valign=top>\n";
		print "$vdesc[$i]<br>\n";
		print "<table width=100%><tr>\n";
		print "<td width=30%><b>$text{'index_addr'}</b> ",
		      &html_escape($vaddr[$i]),"<br>\n";
		print "<b>$text{'index_port'}</b> ",
		      &html_escape($vport[$i]),"</td>\n";
		print "<td width=70%><b>$text{'index_name'}</b> ",
		      &html_escape($vserv[$i]),"<br>\n";
		print "<b>$text{'index_root'}</b> ",
		      &html_escape($vroot[$i]),"</td> </tr>\n";
		print "</table></td> </tr>\n";
		}
	print "</table>\n";
	}

if ($access{'create'}) {
	print "<form action=create_virt.cgi>\n";
	print "<table border>\n";
	print "<tr $tb> <td><b>$text{'index_create'}</b></td> </tr>\n";
	print "<tr $cb> <td><table>\n";
	print "<tr> <td><b>$text{'index_addr'}</b></td>\n";
	print "<td>",&opt_input("", "addr", $text{'index_any'}, 20),
	      "</td> </tr>\n";

	print "<tr> <td></td>\n";
	print "<td><input type=checkbox name=nv value=1 checked> ",
	      "$text{'index_nv'}</td> </tr>\n";

	print "<tr> <td></td>\n";
	print "<td><input type=checkbox name=listen value=1 checked> ",
	      "$text{'index_listen'}</td> </tr>\n";


	print "<tr> <td><b>$text{'index_port'}</b></td>\n";
	print "<td>",&choice_input("0", "port_mode", "0",
				   "$text{'index_default'},0",
				   "$text{'index_any'},1", ",2"),
	      "<input name=port size=5></td> </tr>\n";

	print "<tr> <td><b>$text{'index_root'}</b></td>\n";
	print "<td><input name=root size=40>\n";
	print &file_chooser_button("root", 1, $formno);
	print "</td> </tr>\n";

	print "<tr> <td><b>$text{'index_name'}</b></td>\n";
	print "<td>",&opt_input("", "name", $text{'index_auto'}, 30),
	      "</td> </tr>\n";

	print "<tr> <td valign=top><b>$text{'index_file'}</b></td> <td>\n";
	printf "<input type=radio name=fmode value=0 %s> %s<br>\n",
		$config{'virt_file'} ? "" : "checked",
		&text('index_fmode0', "<tt>httpd.conf</tt>");
	printf "<input type=radio name=fmode value=1 checked> %s<br>\n",
		&text('index_fmode1', "<tt>$config{'virt_file'}</tt>")
		if ($config{'virt_file'});
	printf "<input type=radio name=fmode value=2> %s\n",
		$text{'index_fmode2'};
	printf "<input name=file size=30> %s</td> </tr>\n",
		&file_chooser_button("file");

	print "<tr> <td><b>$text{'index_clone'}</b></td>\n";
	print "<td><select name=clone>\n";
	print "<option value='' checked>$text{'index_noclone'}\n";
	foreach $v (@virt) {
		printf "<option value=%s>%s\n",
			&indexof($v, @$conf), $cname{$v};
		}
	print "</select> &nbsp;&nbsp;\n";
	print "<input type=submit value=\"$text{'create'}\"></td> </tr>\n";
	print "</table></td></tr></table>\n";
	print "</form>\n";
	}

print "<hr>\n";
&footer("/", $text{'index'});

sub server_name_sort
{
return &def(&find_vdirective("ServerName", $_[0]->{'members'}, $conf),
	    $_[0]->{'value'});
}

sub server_ip_sort
{
local $addr = $_[0]->{'value'} =~ /^(\S+):(\S+)/ ? $1 : $_[0]->{'value'};
return $addr eq '_default_' || $addr eq '*' ? undef :
       &check_ipaddress($addr) ? $addr :
			         &to_ipaddress($addr);
}

