#!/usr/bin/perl -T

########################################################################
# 
# mindterm.cgi - CGI for launching MindTerm at UofT / CSLab
#
# Author: Dan Astoorian <djast@cs.toronto.edu>
#
########################################################################

use strict qw/refs subs vars/;
use CGI qw/:standard *ul xmp *table/;

########################################################################
# Global variables

my $content_type = 'text/html; charset=iso-8859-1';
my $title = 'AppGate MindTerm';
my $vers = 2.1;
my $code = 'com.mindbright.application.MindTerm.class';

my $https_url;
# $https_url = 'https://cns.utoronto.ca/~cks/mindterm/mindterm.jar';

# clean up path_info components in any links we produce
my $path_info = path_info;
my $npath_info = &modpath($path_info, qw/download- mindterm.htm-/);

my $domain = 'utoronto.ca';
   $domain = 'toronto.edu' if url =~ /toronto\.edu/;

my $signed_default;
my $debug = 0;
my $expert = 0;
my $allopts = 0;

my $msie = 0;
my $netscape = 0;
my $jvm_available = 0;

my $cslab = 0;	# CSLab customizations (e.g. menu with CSLab hosts)

my $signature = param('signature');
my $run_applet = defined param('startssh');
my $download = $signature eq 'local';
my $local_jarfile = param('local-jarfile');

my $host = param('server');
my $shortname = param('server-uoft');

my ($docbase, $archive, $cabfile);

my $remote_addr = remote_addr();
my $user_agent = user_agent;

my $uoft = ($remote_addr =~ /^(128\.100|142\.15[01])/);

# elements of the form which have been accounted for
my %form_element;

# Get our real document root.  Since we may be rewriting the
# BASE tag to get the unsigned applet to work, we need to
# supply full URLs for any links on this page.
my $full_base = url;
   $full_base =~ s@/[^/]*$@@;
my $full_base_parent = $full_base;
   $full_base_parent =~ s@/[^/]*$@@;
my $absolute_base = script_name;
   $absolute_base =~ s@/[^/]*$@@;
my $real_docroot;
{
    my $script_name = $ENV{'SCRIPT_NAME'};
    $ENV{'SCRIPT_NAME'} = '';
    $real_docroot = url;
    $ENV{'SCRIPT_NAME'} = $script_name;
}

# Constant HTML snippets we're likely to want to include
my $userguidelink =
    a({-href => "$full_base/MindTerm_User.pdf"},
    "MindTerm User's Guide");

# Ideally, this trailer should be generated from the copy in
# /local/src/www/htdocs/tcl/cslab.tcl .
my $trailer = p(hr,
    address('Please send inquiries about this page to',
	br,
	a({-href => 'mailto:requests@math.toronto.edu'},
	   '&lt;requests@math.toronto.edu&gt;'
	)
    )
);

my $thanks = join("\n",
    hr,
    h2('Acknowledgements'),
    p(a({-href => 'http://www.appgate.com/'}, em('AppGate')),
	'is a registered trademark of AppGate AB.'
    ),
    p('The University of Toronto',
	a({-href => 'http://www.math.toronto.edu/'},
	    'Department of Mathematics'
	),
    <<'END_PARA'),
thanks AppGate for making this applet available to the Internet
community.
END_PARA
);

# Sections of the output HTML
my ($applet, $applet_preamble,
    $uoft_disclaimer,
    $introduction,
    $form,
    $debug_html,
);

# generic loop indices
my ($h, $i, $j);

########################################################################

my $TF = [ qw/true false/ ];

# Encyption, MAC, and compression algorithms available
my $ENCS = [ qw/
    aes128-cbc	blowfish-cbc	twofish128-cbc	aes192-cbc
    aes256-cbc	twofish-cbc	cast128-cbc	3des-cbc
    arcfour
/ ];
my $MACS = [ qw/
    hmac-md5		hmac-sha1
    hmac-sha1-96	hmac-md5-96
    hmac-ripemd160
/ ];
my $COMPS = [ qw/none zlib/ ];

########################################################################
# - documented applet parameters for MindTerm.
#   * "values" lists valid values for a parameter, if there are only
#     a limited number of values which make sense.
#   * "multi" indicates that more than one value can be selected
#   * "default" indicates what default is (we think) compiled into the applet 
#   * "localdefault" defines a default which should be different
#     from the applet's default value.
my %option_desc;

########################################################################
# %applet_options:
# - MindTerm parameters which apply only when MindTerm is running as an
# applet.
my %applet_options = (
    'sepframe'		=> { values => $TF, localdefault => 'true' },
    'verbose'		=> { values => $TF, default => 'false' },
    'debug'		=> { values => $TF, default => 'false' },
    'quiet'		=> { values => $TF, localdefault => 'true' },
# cmdsh seems to have been silently removed
#    'cmdsh'		=> { values => $TF, default => 'false' },
    'menus'		=> {
	values => [ 'menu-bar', qw/
	    no	pop	pop1	pop2	pop3
	/ ],
	default => 'menu-bar',
    },
    'autoprops'		=> {
	values => [ qw/
	    save	load	both	none
	/ ],
	default => 'both'
    },
    'propsfile'		=> undef,
    'commandline'	=> undef,
    'sshhome'		=> undef,
    'appletbg'		=> undef,

);
$option_desc{\%applet_options} =
    "Applet Parameters (see Chapter 7 of the $userguidelink)";

########################################################################
# %connection_options:
# - MindTerm connection parameters.
my %connection_options = (
    'alive'		=> { default => '0' },
    'auth-method'	=> {
	values => [ qw/
	    password	publickey	tis	secureid
	    cryptocard	keyboard-interactive
	/ ],
	default => 'password',
    },
    'compression'	=> {
	values => [ 0..9 ],
	default => 0,
    },
    'display'		=> { default => 'localhost:0' },
    'exit-on-logout'	=> { values => $TF, default => 'false' },
    'force-pty'		=> { values => $TF, default => 'true' },
    'local-bind'	=> { default => '127.0.0.1' },
    'port'		=> { default => 22 },
    'private-key'	=> undef,
    'real-server'	=> undef,
    'server'		=> { localdefault => undef },
    'ssh1-cipher'	=> {
	values => [ qw/
	    blowfish-cbc	3des-cbc	idea-cbc
	/ ],
	default => 'blowfish-cbc',
    },
    'username'		=> { localdefault => '' },
    'x11-forward'	=> { values => $TF, default => 'false' },
# "password" and "passphrase" options are too dangerous to allow
# in the submission form!
#    'password'		=> undef,
#    'passphrase'	=> undef,
    'proxy-type'	=> {
	values => [ qw/
	    none	http	socks4	socks5
	/ ],
	default => 'none',
    },
    'proxy-port'	=> undef,
    'proxy-user'	=> undef,
# "proxy-password" is also too dangerous to allow in the submission form
#    'proxy-password'	=> undef,
    'sftpbridge-host'	=> undef,
    'sftpbridge-port'	=> undef,
    'strict-hostid'	=> { values => $TF, default => 'false' },
    'protocol'		=> {
	values => [ qw/auto ssh1 ssh2/ ],
	default => 'auto',

    },
);
$option_desc{\%connection_options} =
    "Connection Parameters (see Appendix A of the $userguidelink)";

########################################################################
# %ssh2_options:
# - MindTerm parameters for protocol version 2.
my %ssh2_options = (
    'kex-algorithms'	=> {
	values => [ qw/
	    diffie-hellman-group1-sha
	    diffie-hellman-group-exchange-sha1
	/ ],
	multi => 1
    },
    'server-host-key-algorithms'	=> {
	values => [ qw/
	    ssh-rsa	ssh-dss
	/ ],
	multi => 1
    },
    'enc-algorithms-cli2srv'	=> { values => $ENCS, multi => 1 },
    'enc-algorithms-srv2cli'	=> { values => $ENCS, multi => 1 },
    'mac-algorithms-cli2srv'	=> { values => $MACS, multi => 1 },
    'mac-algorithms-srv2cli'	=> { values => $MACS, multi => 1 },
    'comp-algorithms-cli2srv'	=> { values => $COMPS, default => 'none' },
    'comp-algorithms-srv2cli'	=> { values => $COMPS, default => 'none' },
    'package-version'		=> {
	default => "SSH-2.0-MindTerm_${vers} (non-commercial)",
    },
);
$option_desc{\%ssh2_options} =
    "SSH2 Parameters (see Appendix B of the $userguidelink)";

########################################################################
# %terminal_options:
# - MindTerm parameters related to terminal emulation.
my %terminal_options = (
    'rev-video'		=> { values => $TF, default => 'false' },
    'autowrap'		=> { values => $TF, default => 'true'  },
    'rev-autowrap'	=> { values => $TF, default => 'false' },
    'insert-mode'	=> { values => $TF, default => 'false' },
    'auto-linefeed'	=> { values => $TF, default => 'false' },
    'repos-input'	=> { values => $TF, default => 'true'  },
    'repos-output'	=> { values => $TF, default => 'true'  },
    'local-pgkeys'	=> { values => $TF, default => 'false' },
    'copy-crnl'		=> { values => $TF, default => 'false' },
    'visible-cursor'	=> { values => $TF, default => 'true'  },
    'ascii-line'	=> { values => $TF, default => 'false' },
    'local-echo'	=> { values => $TF, default => 'false' },
    'visual-bell'	=> { values => $TF, default => 'false' },
    'map-ctrl-space'	=> { values => $TF, default => 'true'  },
    '80x132-toggle'	=> { values => $TF, default => 'false' },
    '80x132-enable'	=> { values => $TF, default => 'true'  },
    'copy-select'	=> { values => $TF, default => 'true'  },
    'font-name'		=> undef,
    'font-size'		=> { default => 12 },
    'geometry'		=> {
	default => '80x24',
	localdefault => '80x32+50+50',
    },
    'term-type'		=> {
	values => [ qw/
	    xterm	linux	scoansi	att6386	sun
	    aixterm	vt220	vt100	ansi
	    vt52	xterm-color
	    linux-lat	at386	vt320	vt102
	/ ],
	default => 'xterm'
    },
    'save-lines'	=> { default => 512 },
    'scrollbar'		=> {
	values => [ qw/
	    none	left	right
	/ ],
	default => 'right'
    },
    'bg-color'		=> { default => 'white' },
    'fg-color'		=> { default => 'black' },
    'cursor-color'	=> { default => 'i_blue' },
    'resize-gravity'	=> { values => [ qw/top bottom/ ], default=>'bottom' },
    'backspace-send'	=> { values => [ qw/BS DEL/ ], default => 'DEL'},
    'delete-send'	=> { values => [ qw/BS DEL/ ], default => 'DEL'},
# default for select-delim is '" "', but that doesn't work well from here
#    'select-delim'	=> { default => ' ' },
    'paste-button'	=> {
	values => [ qw/
	    shift+left	middle	right
	/ ],
	default => 'middle'
    },
);
$option_desc{\%terminal_options} =
    "Terminal Parameters (see Appendix C of the $userguidelink)";

my @all_options = (
    \%applet_options,
    \%connection_options,
    \%ssh2_options,
    \%terminal_options
);

########################################################################
# %path_info_options:
# - options settable in PATH_INFO
#
my %path_info_options = (
    # 'unsigned' implies cslab customization.
    unsigned =>	sub { $signed_default = 'never'; $cslab = 1 },
    signed =>	sub { $signed_default = 'always' },
    download =>	sub { $download = 1 },

    advanced =>	sub { $expert = 1 },
    all =>	sub { $expert = 1; $allopts = 1 },

    debug =>	sub { $debug = 1 },
    notlocal =>	sub { $uoft = 0 },
    cslab =>	sub { $cslab = 1 }, # CSLab customizations
);

########################################################################
# @user_agents:
# - preferences/defaults for specific user-agents.  Only the first
#   regular expression to match the User-Agent: header will be used.
#
my @user_agents = (
     { 'Windows NT' =>	sub {
	$jvm_available = 1;
	return 0;	# fall through
     } },
     { 'MSIE [0-3]' =>	sub { $msie = 1; return 1; } },
     { 'MSIE ' =>	sub { $msie = 1; return 1; } },
     { 'Mozilla/4\.7' =>	sub { $netscape = 1; return 1; } },
     { 'Mozilla/5' =>		sub { $netscape = 1; return 1; } },
);

########################################################################
# apply any relevant hooks for PATH_INFO and User-Agent:

foreach $i (split '/', $path_info) {
    if (exists $path_info_options{$i}) {
	&{$path_info_options{$i}};
    }
}

AGENTS: foreach $i (@user_agents) {
    foreach $j (keys(%$i)) {
	if ($user_agent =~ /$j/) {
	    &{$i->{$j}} && last AGENTS;
	}
    }
}

$signed_default = ($netscape || $msie) unless defined $signed_default;

# Did user click on 'More Options'?
if (defined param('moreopts')) {
    if ($expert) {
	$allopts = 1;
	$npath_info = &modpath($npath_info, qw/advanced- all+/);
    } else {
	$expert = 1;
	$npath_info = &modpath($npath_info, qw/advanced+/);
    }
}


my $my_url = url . $npath_info;
my $download_url = url . &modpath($npath_info, qw/signed- unsigned- download+/);
my $signed_url = url . &modpath($npath_info, qw/unsigned-/);
my $unsigned_url = url . &modpath($npath_info, 'unsigned+');

########################################################################
# Define any restrictions on which servers may be connected to.

if ($cslab) {
    $connection_options{'server'} = {
	values => [ qw/
	    dvp.cs.toronto.edu	qew.cs.toronto.edu otp.cs.toronto.edu
	/ ],
	localdefault => 'qew.cs.toronto.edu',
    }
}

if ($signed_default ne 'never') {
    if ($uoft) {
	undef $connection_options{'server'}->{values};

    } elsif (!$cslab || $expert) {
	# replace "server" in the form with a shortname version of the option
	delete $connection_options{'server'};
	if ($cslab) {
	    $connection_options{'server-uoft'} = { localdefault => 'qew.cs' };
	} else {
	    $connection_options{'server-uoft'} = undef;
	}
    }
}

########################################################################
# Did the user forget to specify the local jarfile?
if ($signature eq 'local' && $local_jarfile eq '') {
    $run_applet = 0;
}

########################################################################
# subroutines

# &make_form_elt - generate an appropriate form element.
# Parameters:
# - $eltname: the element name being generated
# - $dflt:
#	0: don't include "d-" form element
#	1: include a hidden "d-" form element if a local default exists
#	   for the element
#	2: _always_ include a hidden "d-" form element
# - %special: special options to be specified to the form element 
#	routine (e.g., -size)
sub make_form_elt {
    my ($eltname, $dflt, %special) = @_;
    my ($i, $opthash, $result);

    foreach $i (@all_options) {
	$opthash = $i if exists $i->{$eltname};
    }
    return undef if !defined $opthash;

    my $option = $opthash->{$eltname};
    my $values = exists $option->{values} ? $option->{values} : undef;
    my $default =
	exists $option->{localdefault} ? $option->{localdefault} :
	exists $option->{default} ?  $option->{default} :
	undef
    ;
    if ($values == $TF) {
	$result = radio_group(
		    -name => $eltname,
		    -values => $TF,
		    -default => $default,
		    %special,
	) ;
    } elsif (defined $values) {
	if ($option->{multi}) {
	    $result = scrolling_list(
		    -multiple => 1,
		    -name => $eltname,
		    -values => $values,
		    -default => $default,
		    %special,
	    );
	} else {
	    $result = popup_menu(
		    -name => $eltname,
		    -values => $values,
		    -default => $default,
		    %special,
	    );
	}
    } else {
	$result = textfield(
		-name => $eltname,
		-default => $default,
		%special,
	);
    }
    if ($eltname eq 'server-uoft') {
	$result .= tt(".$domain");
    }

    if ($dflt) {
	if ($dflt > 1 || exists $option->{localdefault}) {
	    $result .= hidden({
		-name => "d-$eltname",
		-default => 'on'
	    })
	}
    };
    $form_element{$eltname} = 1;

    return $result;
}

# &modpath - add or remove path_info components
# Parameters:
# - $pinfo: the path to be altered
# - @change: a list of items to be added or removed.  Each item
#   should end with either '-' or '+' to indicate whether the
#   item is being added or removed.
sub modpath {
    my ($pinfo, @change) = @_;
    my $i;

    foreach $i (@change) {
	my $op = chop($i);
	$pinfo =~ s@/$i/@/@g;
	$pinfo =~ s@/$i$@@g;
	if ($op eq '+') {
	    $pinfo .= '/' if $pinfo !~ m@/$@;
	    $pinfo .= $i
	}
    }
    return $pinfo;
}

########################################################################
########################################################################
## Start processing the form.
########################################################################
########################################################################

########################################################################
# Generate the form.

FORM: {
    # The form is a distraction if the page is loaded from a local source.
    if ($download && $run_applet) {
	last FORM;
    }

    # Components of the form
    my (
	$jarfile_elements,
	$formhdr,
	$instructions,
	$host_menu, $geom_menu, $appsrc_menus, $expert_menus,
	$moreopts
    );
    if ($download) {
	my $appsource = "$full_base/mindterm.jar";
	my $nsappsource = "$full_base/mindterm_ns.jar";
	my $ieappsource = "$full_base/mindterm_ie.cab";

	my $jar = tt('.jar');
	my $cab = tt('.cab');

	if (defined param('startssh')) {
	    $jarfile_elements = 
		strong('*** You did not enter the location of the',
		"$jar or $cab file in the box. ***")
	};

	$jarfile_elements .= join ("\n",
	    h2('Downloading MindTerm to a local disk'),
	    p(<<'END_PARA'),
To be able to launch the MindTerm applet from a local disk, perform the
following steps:
END_PARA
	    ol(li[
		<<"END_PARA" .
Put the MindTerm Java Archive ($jar) or Microsoft Cabinets ($cab) file
onto your local disk.  You can get it from the AppGate web site, or
download one of the following to your local disk:
END_PARA
		ul(li[
		    a({-href => $appsource}, "Unsigned $jar file"),
		    a({-href => $nsappsource},
			"Signed $jar file for Netscape 4"
		    ),
		    a({-href => $ieappsource},
			"Signed $cab file for Microsoft Internet Explorer"
		    ),
		]),
		$jvm_available ? (
		    strong("Try double-clicking the $jar file you " .
		    "just downloaded on your desktop.  "
		    ) . <<"END_PARA"
Windows 2000/NT and later (which you appear to be running) can launch
Java applications directly from the unsigned $jar file, without going
through a web browser; this tends to be much more reliable than running
the applet through Netscape or Internet Explorer.  If this works, you
can skip the rest of the steps below.  (Note: make sure you use the
unsigned $jar file, and not the $cab file, when launching the applet
directly from the desktop.)
END_PARA
		) : (),
		"Enter the filename where you stored the $jar or $cab" .
		' file on the local disk (' . em('e.g.') . ', ' .
		    tt('C:\TMP\MINDTERM.JAR') .
		    ') in this box: ' . textfield(
			-name => 'local-jarfile',
			-size => 32
		    ),
		'Set any other options, and click on the "Start MindTerm SSH" ' .
		    'button.',
		'In your browser window, choose ' .
		    tt('File -> Save As...') .
		    ' and save the HTML page on your local disk as well.' ,
		'Bookmark the file you just saved (' . em('e.g.') . ', ' .
		    tt('C:\TMP\MINDTERM.HTM') .
		    ') and use this page to launch the applet.'
	    ])
	);

	$formhdr = h2("Parameters for local MindTerm ${vers} applet:");
	$appsrc_menus = hidden(-name => 'signature', -default => 'local');
	# This will smooth the next step of saving to disk.
	$my_url .= '/mindterm.htm' unless $my_url =~ /.htm$/;

    } elsif ($signed_default eq 'always') {
	$formhdr = h2("Parameters for signed MindTerm ${vers} applet:");
	$appsrc_menus = hidden(-name => 'signature', -default => 'signed' );

    } elsif ($signed_default eq 'never') {
	$formhdr = h2("Parameters for unsigned MindTerm ${vers} applet:");
	$appsrc_menus = hidden(-name => 'signature', -default=>'unsigned');

    } else {
	$formhdr = h2("Parameters for MindTerm ${vers} applet (remember that you should see a line in the MindTerm window with our hostkey fingerprint, namely<br>openssh md5: 5a:08:02:dd:0b:db:8a:40:08:8c:29:ce:ab:3b:c4:2b):");
	if ($https_url ne '') {
	    $appsrc_menus = radio_group(
		    -name => 'signature', -values => [ qw/signed ssl/ ],
		    -default => $signed_default ? 'signed' : 'ssl',
		    -labels => {
			signed => 'Signed applet',
			ssl => 'Unsigned applet via SSL (https)',
		    }
		) . br;
	} else {
	    $appsrc_menus = hidden(-name => 'signature', -default => 'signed');
	}
    }

    if ($allopts) {
	$instructions = h2('Instructions') .
	    p(<<"END_PARA") .
Below are all of the documented options which can be set for MindTerm.
See the $userguidelink to learn more about the options and what they
do.
END_PARA
	    p(<<'END_PARA') .
If the box at the left of the option is checked, the option will be
supplied to the applet even if you don't change it from the default
value.  (If you find that the default listed for an option below is
incorrect, try checking the box--and please let us know about the
error.)
END_PARA
	    p(strong('Note:'), <<'END_PARA')
This interface does not verify that the options you supply are sensible.
Supplying incorrect options may prevent MindTerm from starting or
operating correctly.  You may need to exit and restart your browser
if you provide an option which the MindTerm applet cannot understand.
END_PARA
	    ;

	my $options_html = '';

	$appsrc_menus .= p(
	    'Applet frame size (used only when',
	    em('sepframe'),
	    'is set to "false"):',
	    br,
	    'Width:', textfield(
		-name => 'framewidth',
		-default => 640,
		-size => 4,
		-maxlength => 4
	    ),
		'Height:', textfield(
		-name => 'frameheight',
		-default => 480,
		-size => 4,
		-maxlength => 4
	    ),
	    br,
	);

	# Add form elements for all available options
	foreach $h (@all_options) {
	    $options_html .= h2($option_desc{$h});
	    $options_html .= join("\n",
		start_table({border => 1}),
		th(['*', 'Option','Value'])
	    );
	    foreach $i (sort keys %$h) {
		my $option = $h->{$i};
		my $values = exists $option->{values} ? $option->{values} : undef;
		my $default =
		    exists $option->{localdefault} ?  $option->{localdefault} :
		    exists $option->{default} ?  $option->{default} :
		    undef
		;
		my $cb = checkbox({
		    -name => "d-$i",
		    -label => '',
		    -checked => exists $option->{localdefault},
		});

		my $element = &make_form_elt($i, 0);
		$i = 'server' if $i eq 'server-uoft';
		$options_html .= Tr( td([$cb, $i, $element]));
	    }
	    $options_html .= end_table;
	}
	$expert_menus .= $options_html;
    } else {
	$host_menu = join("\n",
	    'Host:',
	    # only one of these two will actually produce a form element
	    &make_form_elt('server', 1),
	    &make_form_elt('server-uoft', 1),
	    br,
	);

	if ($expert) {
	    $geom_menu = join("\n",
		'Rows:', popup_menu('rows',
		    [25, 32, 50, 66],
		    32),
		'Columns:', popup_menu('columns',
		    [80, 132],
		    80),
		'Font size',
		 &make_form_elt('font-size', 1,
		    -size => 3, -maxlength => 3) . 'pt.',
		br,
		'Backspace sends:', &make_form_elt('backspace-send', 2),
		'Delete sends:', &make_form_elt('delete-send', 2),
		br,
		'Terminal type:',
		 &make_form_elt('term-type', 1),
		'Port:',
		&make_form_elt('port', 1,
		    -size => 5, -maxlength => 5),
		br,
	    );
	    # rows + columns take the place of 'geometry'
	    $form_element{'geometry'} = 1;

	    $host_menu = join("\n",
		'Username:',
		&make_form_elt('username', 1,
		    -size => 8, -maxlength => 8),
		$host_menu
	    );

	}

	$moreopts = submit(-label => 'More Options...', -name => 'moreopts')
    }

    # set local defaults if form elements have not already been added for
    # them
    foreach $h (@all_options) {
	foreach $i (sort keys %$h) {
	    next if $form_element{$i};

	    my $option = $h->{$i};
	    next if !exists $option->{localdefault};

	    $expert_menus .= hidden(
		-name => $i,
		-default => $option->{localdefault}
	    ) . hidden(
		-name => "d-$i",
		-default => 'on'
	    ) . "\n";
	    $form_element{$i} = 1;
	}
    }

    $form = join("\n",
	hr,
	startform(-method => 'POST', -action => $my_url),
	$jarfile_elements,
	$instructions,
	$formhdr,
	$host_menu,
	$geom_menu,
	$appsrc_menus,
	$expert_menus,
	submit(-label => 'Start MindTerm SSH', -name => 'startssh'),
	$moreopts,
	defaults,
	reset,
    endform);
} # FORM:

########################################################################
# Generate the <APPLET> tag and the associated preamble

if (defined $shortname) {
    # shortname given: translate 'server-uoft' into 'server'
    if ($shortname eq '') {
	# No shortname given: don't launch the applet
	undef $run_applet;
    } else {
	$host = $shortname . ".$domain";
	param('server', $host);
	Delete('server-uoft');
	$connection_options{'server'} = undef;
	delete $connection_options{'server-uoft'};
    }
}

if ($run_applet) {
    my $startmsg;

    if ($signature eq 'local') {
	# convert pathname into a valid "file:" URL
	$local_jarfile =~ s@\\@/@g;
	$local_jarfile = '/' . $local_jarfile unless $local_jarfile =~ m@^/@;
	$local_jarfile =~ m@(.*)/(.*)@;
	($docbase,$archive) = ($1,$2);
	$docbase = "file:${docbase}/";

	# if it's an IE cabfile, set the cabinets tag instead of 
	# the archive tag
	if ($local_jarfile =~ /\.cab$/i) {
	    $cabfile = $archive;
	    undef $archive;
	}

    } elsif ($signature eq 'unsigned') {
	$archive = "mindterm${vers}.jar";
	$docbase = "http://$host:8808/";

    } elsif ($https_url ne '' && $signature eq 'ssl') {
	$https_url =~ m@(.*/)(.*)@;
	($docbase,$archive) = ($1,$2);

    } else {	# signed
	$archive = "$absolute_base/mindterm_ns.jar";
	$cabfile = "$absolute_base/mindterm_ie.cab";
    }

    if (!defined param{'geometry'}) {
	# Generate geometry property from rows and columns.
	if (defined param('columns') && defined param('rows')) {
	    param('geometry',
		param('columns') . 'x' . param('rows') . '+50+50'
	    );
	}
    }

    if (defined($host)) {
	$startmsg = p(strong("Starting MindTerm SSH to $host...")),
    } else {
	$startmsg = p(strong("Starting MindTerm SSH...")),
    }
    if ($download) {
	$startmsg .= <<'END_PARA';
<P>
If everything is working correctly, the applet should pop up.
<P>
You should now:
<OL>
<LI>Save this page (<TT>File -> Save As...</TT>) to your local disk.
<LI>Bookmark the file you just saved (<EM>e.g.</EM>,
<TT>C:\TMP\MINDTERM.HTM</TT>).  You can use that copy of the page to
launch the applet from your local disk.
</OL>
</P>
END_PARA
    } else {
	$startmsg .= p(join("\n",
	    strong('Tip:'), 
	    'If you save this page (' . tt('File -> Save As...') . ')' ,
	    <<'END_PARA'
to your local disk, and bookmark it there, you can use the saved copy
later to restart the applet with the same options.
END_PARA
	));
    }

    # Generate the parameter list.
    my @param_list = ('');
    my ($h, $i);
    foreach $h (@all_options) {
	foreach $i (sort keys %$h) {
	    my $option = $h->{$i};
	    my $param = join(',', param($i));
	    my $default = $option->{default};
	    if (($param ne $default && $param ne '') || param("d-$i")) {
		push @param_list, Param({
		    -name => $i,
		    -value => $param
		});
	    }
	}
    }

    $applet_preamble = join("\n",
	$startmsg,
	p(strong(<<'END_PARA')));
Warning: This window controls the applet.  The applet may be terminated or stop
responding once this window is closed, or you leave this page.
END_PARA
    my ($framewidth, $frameheight);
    if (param('sepframe') eq 'false') {
	($framewidth, $frameheight) = (
	    param('framewidth') || 640,
	    param('frameheight') || 480
	);
	
    } else {
	($framewidth, $frameheight) = (1, 1);
    }
    $applet = join ("\n",
	applet({
	  -code => $code,
	  defined($archive) ? (-archive => $archive) : (),
	  defined($cabfile) ? (-cabinets => $cabfile) : (),
	  -width => $framewidth,
	  -height => $frameheight},
        join("\n", @param_list),
	  p('Java (1.1 or later) must be enabled to use MindTerm.')
	),
    );
    $applet = pre(CGI::escapeHTML($applet)) . "<!--\n$applet\n-->"  if $debug;

    # If we're running the applet in a separate frame, then we want the
    # tag to appear at the bottom of the document, because Netscape gets
    # confused by the width/height of 1 and stops rendering the page.
    # However, if we're running the applet in the main browser pane, we
    # want it to appear immediately following the preamble.

    if (param('sepframe') eq 'false') {
	$applet_preamble .= $applet;
	undef $applet;
    }

} else {
    my $thispageinfo = "\n" . <<'END_PARA';
This page allows you to access MindTerm as a digitally-signed applet for
Netscape or Microsoft Internet Explorer.  You can grant the signed
applet permission to read or write your local files; this allows the
applet to connect to any host, upload and download files, and enables
many more features.
END_PARA

    my $unsigned_info = "\n" . <<'END_PARA' . ' ';
MindTerm will not be able to provide all of its features when launched
this way, and will only permit you to connect to the host you downloaded
the applet from; however, it will still give you a simple way to connect
to CSLab.  We provide it in case you encounter problems with the
END_PARA

    if ($cslab) {
	if ($signed_default eq 'never') {
	    # Override the default above
	    $thispageinfo = <<'END_PARA' . $unsigned_info .
This page allows you to access MindTerm as an unsigned applet directly
from one of CSLab's timesharing servers.
END_PARA
		a({-href => $signed_url}, 'signed applet') . '.';
	} else {
	    # Supplement the default with additional info
	    $thispageinfo .= 'You can also access MindTerm as an ' .
		a({-href => $unsigned_url}, 'unsigned applet') .
		" from CSLab's timesharing servers." . $unsigned_info .
		'signed applet.';
	}
    }

    if (!$download) {
	$introduction = join ("\n",
	    h2('Introduction'),
	    p(a({-href => 'http://www.appgate.com/mindterm/'},
		    'AppGate MindTerm'),
		<<'END_PARA',
    is a Java implementation of a secure shell client.  It is available free
    of charge for personal and non-commercial use.
END_PARA
		$thispageinfo),
	     p('Alternatively, you can',
		a({-href => $download_url}, 'download'),
		<<'END_PARA'),
    the applet to your local disk, so that you don't have to retrieve the
    applet over the network every time you want to run it.
END_PARA
	    $cslab ?  p('See our',
		a({-href => "$full_base_parent/mindterm-notes.html"},
		    'notes'
		),
		"and the $userguidelink for more information about MindTerm."
	    ) : p(
		"See the $userguidelink for more information about MindTerm."
	    )
	);
    }
}

if (!$uoft) {
    $uoft_disclaimer =  p(strong('Note:'), <<'END_PARA'
This applet is provided for the convenience of members of the
University of Toronto community.
END_PARA
    . strong('Use of this page by anyone else is unauthorized.'));
}

if ($debug) {
    $debug_html = join("\n",
	hr,
	&CGI::dump,
	($docbase ne '') ? p('Document base is: "' . tt($docbase) . '"') : '',
	p('Your user-agent is: "' . tt(user_agent) . '"'),
    );
}

# We're done; output the page.
print header(	-type => $content_type),
    start_html( -xbase => $docbase,
		-base => $run_applet,
		-title => $title,
		-head => [
		    meta({-http_equiv => 'Content-Type',
			  -content => $content_type
			})
		]
    ),
    h1($title),
    join("\n",
	$uoft_disclaimer,
	$applet_preamble,
	$introduction,
	$form,
	$thanks,
	$debug_html,
	$trailer,
	$applet,
	end_html,
	''
    );
