# http-monitor.pl
# Monitor a remote HTTP server

sub get_http_status
{
# Connect to the server
local $up=0;
local $st = time();
eval {
	local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
	alarm($_[0]->{'alarm'} ? $_[0]->{'alarm'} : 10);

	local $re = $_[0]->{'regexp'};
	local $method = $_[0]->{'method'} || "HEAD";
	local $con = &make_http_connection($_[0]->{'host'}, $_[0]->{'port'},
				   $_[0]->{'ssl'}, $method, $_[0]->{'page'});
	if (!ref($con)) {
		return { 'up' => 0 };
		}
	&write_http_connection($con, "Host: $_[0]->{'host'}\r\n");
	&write_http_connection($con, "User-agent: Webmin\r\n");
	if ($_[0]->{'user'}) {
		local $auth = &encode_base64("$_[0]->{'user'}:$_[0]->{'pass'}");
		$auth =~ s/\n//g;
		&write_http_connection($con, "Authorization: basic $auth\r\n");
		}
	&write_http_connection($con, "\r\n");
	local $line = &read_http_connection($con);
	$up = $line =~ /^HTTP\/1\..\s+(200|301|302)\s+/ ? 1 : 0;
	if ($re && $up) {
		# Read the headers
		local %header;
		while(1) {
			$line = &read_http_connection($con);
			$line =~ tr/\r\n//d;
			$line =~ /^(\S+):\s+(.*)$/ || last;
			$header{lc($1)} = $2;
			}

		# Read the body
		local ($buf, $data);
		while(defined($buf = &read_http_connection($con))) {
			$data .= $buf;
			}
		if ($data !~ /$re/i) {
			$up = 0;
			}
		}

	&close_http_connection($con);
	alarm(0);
	};

if ($@) {
	die unless $@ eq "alarm\n";   # propagate unexpected errors
	return { 'up' => 0 };
	}
else { 
	return { 'up' => $up, 'time' => time() - $st};
	}
}

sub show_http_dialog
{
print "<tr> <td><b>$text{'http_url'}</b></td>\n";
printf "<td><input name=url size=40 value='%s'></td>\n",
 $_[0]->{'host'} ? ($_[0]->{'ssl'} ? "https" : "http").
		   "://$_[0]->{'host'}:$_[0]->{'port'}$_[0]->{'page'}"
		 : "http://";

print "<td><b>$text{'http_alarm'}</b></td>\n";
printf "<td><input type=radio name=alarm_def value=1 %s> %s\n",
	$_[0]->{'alarm'} ? '' : 'checked', $text{'default'};
printf "<input type=radio name=alarm_def value=0 %s>\n",
	$_[0]->{'alarm'} ? 'checked' : '';
print "<input name=alarm size=5 value='$_[0]->{'alarm'}'></td> </tr>\n";

print "<tr> <td><b>$text{'http_method'}</b></td>\n";
print "<td colspan=3><select name=method>\n";
foreach $m ('HEAD', 'GET', 'POST') {
	printf "<option value=%s %s>%s\n",
		$m, $_[0]->{'method'} eq $m ? "selected" : "", $m;
	}
print "</select></td> </tr>\n";

print "<tr> <td><b>$text{'http_login'}</b></td> <td colspan=3>\n";
printf "<input type=radio name=user_def value=1 %s> %s\n",
	$_[0]->{'user'} ? "" : "checked", $text{'http_none'};
printf "<input type=radio name=user_def value=0 %s> %s\n",
	$_[0]->{'user'} ? "checked" : "", $text{'http_user'};
printf "<input name=user size=15 value='%s'> %s\n",
	$_[0]->{'user'}, $text{'http_pass'};
printf "<input name=pass type=password size=15 value='%s'></td> </tr>\n",
	$_[0]->{'pass'};

print "<tr> <td><b>$text{'http_regexp'}</b></td> <td colspan=3>\n";
print &ui_opt_textbox("regexp", $_[0]->{'regexp'}, 50, $text{'http_none2'});
print "</td> </tr>\n";
}

sub parse_http_dialog
{
if ($in{'url'} =~ /^(http|https):\/\/([^:]+):(\d+)(\/.*)$/) {
	$_[0]->{'ssl'} = $1 eq "https";
	$_[0]->{'host'} = $2;
	$_[0]->{'port'} = $3;
	$_[0]->{'page'} = $4;
	}
elsif ($in{'url'} =~ /^(http|https):\/\/([^\/]+)(\/.*)$/) {
	$_[0]->{'ssl'} = $1 eq "https";
	$_[0]->{'host'} = $2;
	$_[0]->{'port'} = $1 eq "https" ? 443 : 80;
	$_[0]->{'page'} = $3;
	}
elsif ($in{'url'} =~ /^(http|https):\/\/([^:]+):(\d+)$/) {
	$_[0]->{'ssl'} = $1 eq "https";
	$_[0]->{'host'} = $2;
	$_[0]->{'port'} = $3;
	$_[0]->{'page'} = "/";
	}
elsif ($in{'url'} =~ /^(http|https):\/\/([^\/]+)$/) {
	$_[0]->{'ssl'} = $1 eq "https";
	$_[0]->{'host'} = $2;
	$_[0]->{'port'} = $1 eq "https" ? 443 : 80;
	$_[0]->{'page'} = "/";
	}
else {
	&error($text{'http_eurl'});
	}

if ($in{'alarm_def'}) {
	delete($_[0]->{'alarm'});
	}
else {
	$in{'alarm'} =~ /^\d+$/ || &error($text{'http_ealarm'});
	$_[0]->{'alarm'} = $in{'alarm'};
	}

if ($in{'user_def'}) {
	delete($_[0]->{'user'});
	delete($_[0]->{'pass'});
	}
else {
	$in{'user'} || &error($text{'http_euser'});
	$_[0]->{'user'} = $in{'user'};
	$_[0]->{'pass'} = $in{'pass'};
	}

$_[0]->{'method'} = $in{'method'};

if ($in{'regexp_def'}) {
	delete($_[0]->{'regexp'});
	}
else {
	$in{'regexp'} || &error($text{'http_eregexp'});
	$_[0]->{'regexp'} = $in{'regexp'};
	$in{'method'} eq 'HEAD' && &error($text{'http_ehead'});
	}
}

