Merge branch 'develop' into VCL-1116_use_database_hostnames_for_ad_joined_computers
diff --git a/managementnode/bin/vclmessages.pl b/managementnode/bin/vclmessages.pl
new file mode 100755
index 0000000..20ae532
--- /dev/null
+++ b/managementnode/bin/vclmessages.pl
@@ -0,0 +1,202 @@
+#!/usr/bin/perl -w
+
+use Getopt::Long;
+use YAML;
+use DBI;
+use Data::Dumper;
+
+my $getnames = 0;
+my $dumpmessage = '';
+my $setmessage = '';
+my $resetmessage = '';
+my $htmlfile = '';
+my $subject = '';
+my $help = 0;
+
+GetOptions ('getmessagenames' => \$getnames,
+            'dumpmessage:s' => \$dumpmessage,
+            'resetmessage:s' => \$resetmessage,
+            'setmessage:s' => \$setmessage,
+            'htmlfile:s' => \$htmlfile,
+            'subject:s' => \$subject,
+            'help|?' => \$help);
+
+if ($help ||
+	($getnames == 1 && ($dumpmessage ne '' || $setmessage ne '' || $resetmessage ne '' || $htmlfile ne '' || $subject ne '')) ||
+	($getnames == 0 && $dumpmessage ne '' && ($setmessage ne '' || $resetmessage ne '' || $htmlfile ne '' || $subject ne '')) ||
+	($getnames == 0 && $resetmessage ne '' && ($setmessage ne '' || $dumpmessage ne '' || $htmlfile ne '' || $subject ne '')) ||
+	($getnames == 0 && $setmessage ne '' && ($dumpmessage ne '' || $resetmessage ne '' || $htmlfile eq '' || $subject eq '')) ||
+	($getnames == 0 && $setmessage eq '' && $dumpmessage eq '' && $resetmessage eq ''))
+{
+	print "Usage:\n\n";
+	print "vclmessages.pl --getmessagenames\n";
+	print "vclmessages.pl --dumpmessage '<name of message>'\n";
+	print "vclmessages.pl --setmessage '<name of message>' --htmlfile <filename> --subject <message subject>\n";
+	print "vclmessages.pl --resetmessage '<name of message>'\n\n";
+	print "vclmessages.pl --help|-?\n\n";
+	print "Where\n\n";
+	print "--getmessagenames displays a list of all available names that can be used\n";
+	print "--dumpmessage displays the current value of a message\n";
+	print "--setmessage sets the value of a message to the contents of the specified file\n";
+	print "--resetmessage sets the value of a message back to the original value as distributed with VCL\n\n";
+	print "<name of message> = the name of the message from the database (enclose in single quotes)\n";
+	print "\tuse --getmessagenames to get a list of message names\n\n";
+	print "<filename> = filename (including path) of file containing html contents for email message\n\n";
+	print "<message subject> = subject for email message (enclose in single quotes)\n\n";
+	exit 0;
+}
+
+my $mode = 'getnames';
+$mode = 'dumpmessage' if($dumpmessage ne '');
+$mode = 'setmessage' if($setmessage ne '');
+$mode = 'resetmessage' if($resetmessage ne '');
+
+my $messagename = $dumpmessage;
+$messagename = $setmessage if($mode eq 'setmessage');
+$messagename = $resetmessage if($mode eq 'resetmessage');
+
+my $database = `grep ^database /etc/vcl/vcld.conf | awk -F '=' '{print \$2}'`;
+my $hostname = `grep ^server /etc/vcl/vcld.conf | awk -F '=' '{print \$2}'`;
+my $user = `grep ^LockerWrtUser /etc/vcl/vcld.conf | awk -F '=' '{print \$2}'`;
+my $password = `grep ^wrtPass /etc/vcl/vcld.conf | awk -F '=' '{print \$2}'`;
+
+chomp $database;
+chomp $hostname;
+chomp $user;
+chomp $password;
+
+my $dsn = "DBI:mysql:database=$database;host=$hostname";
+my $dbh = DBI->connect($dsn, $user, $password);
+
+# ================= get names ================
+if($mode eq 'getnames')
+{
+	my $sth = $dbh->prepare(
+		"SELECT name FROM variable WHERE name LIKE 'usermessage%' OR name LIKE 'adminmessage%' ORDER BY name")
+		or die "Error: Failed to prepare database query: $dbh->errstr()";
+	$sth->execute();
+	while (my $ref = $sth->fetchrow_hashref()) {
+		print "$ref->{'name'}\n";
+	}
+	$sth->finish;
+	$sth->finish;
+	$dbh->disconnect;
+	exit 0;
+}
+# ================ dump message ===============
+elsif($mode eq 'dumpmessage')
+{
+	my $sth = $dbh->prepare(
+		"SELECT value FROM variable WHERE name = ?")
+		or die "Error: Failed to prepare database query: $dbh->errstr()";
+	$sth->execute($messagename);
+	if($sth->rows == 0)
+	{
+		print "Error: Failed to find message with name $messagename\n";
+		$sth->finish;
+		$dbh->disconnect;
+		exit 0;
+	}
+	if($sth->rows > 1)
+	{
+		print "Error: Found multiple messages with name $messagename\n";
+		$sth->finish;
+		$dbh->disconnect;
+		exit 0;
+	}
+	my $ref = $sth->fetchrow_hashref();
+	my $data = YAML::Load($ref->{'value'});
+	#print Dumper($data);
+	print "Subject: $data->{'subject'}\n";
+	print "Message:\n";
+	print "$data->{'message'}\n";
+
+	$sth->finish;
+	$dbh->disconnect;
+	exit 0;
+}
+# ================= reset message ===============
+elsif($mode eq 'resetmessage')
+{
+	my $sth = $dbh->prepare(
+		'SELECT value FROM messagereset WHERE name = ?')
+		or die "Error: Failed to prepare database query: $dbh->errstr()";
+	$sth->execute($messagename) or die "Error: failed to query database: $dbh->errstr()";
+	if($sth->rows == 0)
+	{
+		print "Error: Failed to find message with name $messagename\n";
+		$sth->finish;
+		$dbh->disconnect;
+		exit 0;
+	}
+	if($sth->rows > 1)
+	{
+		print "Error: Found multiple messages with name $messagename\n";
+		$sth->finish;
+		$dbh->disconnect;
+		exit 0;
+	}
+
+	my $ref = $sth->fetchrow_hashref();
+	my $message = $ref->{'value'};
+
+	$sth = $dbh->prepare(
+		"UPDATE variable SET value = ?, setby = 'setemail script', timestamp = NOW() WHERE name = ?")
+		or die "Error: Failed to prepare database query: $dbh->errstr()";
+
+	$sth->bind_param(1, $message);
+	$sth->bind_param(2, $messagename);
+	$sth->execute() or die "Error: Failed to update value for $messagename\n";
+
+	$sth->finish;
+	$dbh->disconnect;
+	print "Success: Value reset for $messagename\n";
+}
+# ================= set message ===============
+elsif($mode eq 'setmessage')
+{
+	my $htmlemail;
+	open(my $fh, '<', $htmlfile) or die "Error: failed to open $htmlfile for reading";
+	{
+		local $/;
+		$htmlemail = <$fh>;
+	}
+	close($fh);
+
+	my $sth = $dbh->prepare(
+		'SELECT value FROM variable WHERE name = ?')
+		or die "Error: Failed to prepare database query: $dbh->errstr()";
+	$sth->execute($messagename) or die "Error: failed to query database: $dbh->errstr()";
+	if($sth->rows == 0)
+	{
+		print "Error: Failed to find message with name $messagename\n";
+		$sth->finish;
+		$dbh->disconnect;
+		exit 0;
+	}
+	if($sth->rows > 1)
+	{
+		print "Error: Found multiple messages with name $messagename\n";
+		$sth->finish;
+		$dbh->disconnect;
+		exit 0;
+	}
+
+	my $ref = $sth->fetchrow_hashref();
+	my $data = YAML::Load($ref->{'value'});
+	$data->{'message'} = $htmlemail;
+	$data->{'subject'} = $subject;
+	my $yaml = YAML::Dump($data);
+
+	$sth = $dbh->prepare(
+		"UPDATE variable SET value = ?, setby = 'setemail script', timestamp = NOW() WHERE name = ?")
+		or die "Error: Failed to prepare database query: $dbh->errstr()";
+
+	$sth->bind_param(1, $yaml);
+	$sth->bind_param(2, $messagename);
+	$sth->execute() or die "Error: Failed to update value for $messagename\n";
+
+	$sth->finish;
+	$dbh->disconnect;
+	print "Success: Value for $messagename updated from contents of $htmlfile\n";
+}
diff --git a/managementnode/lib/VCL/DataStructure.pm b/managementnode/lib/VCL/DataStructure.pm
index 6ab5421..ba8d614 100644
--- a/managementnode/lib/VCL/DataStructure.pm
+++ b/managementnode/lib/VCL/DataStructure.pm
@@ -2642,6 +2642,8 @@
 			next;
 		}
 		#notify($ERRORS{'DEBUG'}, 0, "extracted subroutine mapping key from section of input string: '$input_substitute_section' --> '$subroutine_mapping_key'");
+		# skip keys derived from [if ...] and [endif] to prevent creation of mappings from HTML comment conditionals
+		next if ($subroutine_mapping_key =~ /^if / || $subroutine_mapping_key eq "endif");
 		
 		# Attempt to retrieve the substitution value from the DataStructure data
 		# Check if DataStructure.pm implements a matching 'get_' function
diff --git a/managementnode/lib/VCL/Module/OS.pm b/managementnode/lib/VCL/Module/OS.pm
index 2b74bf0..24bacca 100644
--- a/managementnode/lib/VCL/Module/OS.pm
+++ b/managementnode/lib/VCL/Module/OS.pm
@@ -4444,12 +4444,14 @@
 		my $router = $server_variable_data->{router};
 		my $netmask = $server_variable_data->{netmask};
 		my @dns = @{$server_variable_data->{dns}};
+
+		my $return = 1;
 		
-		notify($ERRORS{'OK'}, 0, "updated data server request router info") if ($self->data->set_server_request_router($server_variable_data->{router}));
-		notify($ERRORS{'OK'}, 0, "updated data server request netmask info") if ($self->data->set_server_request_netmask($server_variable_data->{netmask}));
-		notify($ERRORS{'OK'}, 0, "updated data server request dns info") if ($self->data->set_server_request_dns_servers(@{$server_variable_data->{dns}}));
+		notify($ERRORS{'OK'}, 0, "updated data server request router info") or $return = 0 if ($self->data->set_server_request_router($server_variable_data->{router}));
+		notify($ERRORS{'OK'}, 0, "updated data server request netmask info") or $return = 0 if ($self->data->set_server_request_netmask($server_variable_data->{netmask}));
+		notify($ERRORS{'OK'}, 0, "updated data server request dns info") or $return = 0 if ($self->data->set_server_request_dns_servers(@{$server_variable_data->{dns}}));
 		notify($ERRORS{'DEBUG'}, 0, "router= $router, netmask= $netmask, dns= @dns");
-		
+		return $return;
 	}
 	else {
 		notify($ERRORS{'DEBUG'}, 0, "data is not set for $variable_name");
diff --git a/managementnode/lib/VCL/Module/OS/Linux.pm b/managementnode/lib/VCL/Module/OS/Linux.pm
index 4fd61b1..4620b6a 100644
--- a/managementnode/lib/VCL/Module/OS/Linux.pm
+++ b/managementnode/lib/VCL/Module/OS/Linux.pm
@@ -6699,20 +6699,30 @@
 		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
 		return;
 	}
-	
+
 	my $computer_name = $self->data->get_computer_short_name();
 	my $public_ip_configuration = $self->data->get_management_node_public_ip_configuration();
-	my @public_dns_servers = shift || $self->data->get_management_node_public_dns_servers();
-	
-	if ($public_ip_configuration !~ /static/i) {	
-		notify($ERRORS{'WARNING'}, 0, "unable to update resolv.conf on $computer_name, management node's IP configuration is set to $public_ip_configuration");
+	my @mn_dns_servers = shift || $self->data->get_management_node_public_dns_servers();
+
+	my @server_request_dns_servers = $self->data->get_server_request_dns_servers();
+
+	my @dns_servers;
+	if (@server_request_dns_servers) {
+		@dns_servers = @server_request_dns_servers;
+		notify($ERRORS{'DEBUG'}, 0, "server request specific DNS servers will be statically set on $computer_name: " . join(", ", @dns_servers));
+	}
+	elsif ($public_ip_configuration =~ /static/i && @mn_dns_servers) {
+		@dns_servers = @mn_dns_servers;
+		notify($ERRORS{'DEBUG'}, 0, "management node IP configuration set to $public_ip_configuration, management node DNS servers will be statically set on $computer_name: " . join(", ", @dns_servers));
+	}
+	else {
+		notify($ERRORS{'WARNING'}, 0, "$computer_name not configured to use static DNS servers:\n" .
+			"management node IP configuration               : $public_ip_configuration\n" .
+			"management node DNS servers configured         : " . (@mn_dns_servers ? 'yes' : 'no')
+		);
 		return;
 	}
-	elsif (!@public_dns_servers) {
-		notify($ERRORS{'WARNING'}, 0, "unable to update resolv.conf on $computer_name, DNS server argument was not provided and management node's public DNS server is not configured");
-		return;
-	}
-	
+
 	my $resolv_conf_path = "/etc/resolv.conf";
 	
 	my @resolv_conf_lines_existing = $self->get_file_contents($resolv_conf_path);
@@ -6725,16 +6735,16 @@
 			push @resolv_conf_lines_new, $line;
 		}
 	}
-	
+
 	# Add a comment marking what was added by VCL
 	my $timestamp = POSIX::strftime("%m-%d-%Y %H:%M:%S", localtime);
 	push @resolv_conf_lines_new, "# $timestamp: The following was added by VCL";
 	
 	# Add a nameserver line for each configured DNS server
-	for my $public_dns_server (@public_dns_servers) {
+	for my $public_dns_server (@dns_servers) {
 		push @resolv_conf_lines_new, "nameserver $public_dns_server";
 	}
-	
+
 	my $resolv_conf_contents_new = join("\n", @resolv_conf_lines_new);
 	if ($self->create_text_file($resolv_conf_path, $resolv_conf_contents_new)) {
 		notify($ERRORS{'DEBUG'}, 0, "updated $resolv_conf_path on $computer_name:\n$resolv_conf_contents_new");
diff --git a/managementnode/lib/VCL/Module/OS/Windows.pm b/managementnode/lib/VCL/Module/OS/Windows.pm
index 16118a0..027e333 100644
--- a/managementnode/lib/VCL/Module/OS/Windows.pm
+++ b/managementnode/lib/VCL/Module/OS/Windows.pm
@@ -1145,15 +1145,25 @@
 		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
 		return 0;
 	}
-	
+
 	my $computer_name = $self->data->get_computer_short_name();
-	
+
 	# Check if the computer is joined to any AD domain
 	my $computer_current_domain_name = $self->ad_get_current_domain();
 	if ($computer_current_domain_name) {
-		$self->ad_delete_computer();
+		# check that node is not a domain controller
+		my $check_dc = $self->ad_check_domain_controller();
+		if (!defined($check_dc) || $check_dc == 0) {
+			# if call to ad_check_domain_controller fails, still attempt to
+			# delete from domain; unusual for node to be a domain controller
+			notify($ERRORS{'DEBUG'}, 0, "attempting to delete computer from domain");
+			$self->ad_delete_computer();
+		}
+		elsif ($check_dc == 1) {
+			notify($ERRORS{'DEBUG'}, 0, "computer is a domain controller, not attempting to delete computer from its own domain");
+		}
 	}
-	
+
 	return $self->SUPER::pre_reload();
 }
 
@@ -14217,7 +14227,19 @@
 		notify($ERRORS{'DEBUG'}, 0, "$computer_name does not need to be removed from AD because it is not currently joined to a domain");
 		return 1;
 	}
-	
+
+	# check that node is not a domain controller
+	my $check_dc = $self->ad_check_domain_controller();
+	if (!defined($check_dc) || $check_dc == 0) {
+		# if call to ad_check_domain_controller fails, still attempt to
+		# delete from domain; unusual for node to be a domain controller
+		notify($ERRORS{'DEBUG'}, 0, "attempting to delete computer from domain");
+	}
+	elsif ($check_dc == 1) {
+		notify($ERRORS{'DEBUG'}, 0, "computer is a domain controller, not attempting to delete computer from its own domain");
+		return 1;
+	}
+
 	# Expected output:
 	# Executing (\\<COMPUTERNAME>\ROOT\CIMV2:Win32_ComputerSystem.Name="<COMPUTERNAME>")->UnJoinDomainOrWorkgroup()
 	# Method execution successful.s
@@ -14862,6 +14884,50 @@
 
 #//////////////////////////////////////////////////////////////////////////////
 
+=head2 ad_check_domain_controller
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Checks if computer is configured as a domain controller; returns
+               0 if not a domain controller, 1 if a domain controller, and
+               no value on error
+
+=cut
+
+sub ad_check_domain_controller {
+	my $self = shift;
+	if (ref($self) !~ /windows/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+
+	my $system32_path = $self->get_system32_path() || return;
+	my $check_dc_command = "echo | cmd.exe /c \"$system32_path/Wbem/wmic.exe /INTERACTIVE:OFF COMPUTERSYSTEM GET DomainRole\"";
+	my ($check_dc_exit_status, $check_dc_output) = $self->execute($check_dc_command);
+	if (!defined($check_dc_output)) {
+		notify($ERRORS{'DEBUG'}, 0, "failed to check for node being a domain controller");
+		return;
+	}
+	elsif (grep(/ERROR/i, @$check_dc_output)) {
+		notify($ERRORS{'DEBUG'}, 0, "failed to check for node being a domain controller, output:\n" . join("\n", @$check_dc_output));
+		return;
+	}
+	elsif (@{$check_dc_output}[1] =~ /^[0-3]$/) {
+		notify($ERRORS{'OK'}, 0, "node is a not a domain controller");
+		return 0;
+	}
+	elsif (@{$check_dc_output}[1] =~ /^[4-5]$/) {
+		notify($ERRORS{'OK'}, 0, "node is a domain controller");
+		return 1;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "unexpected output checking for node being a domain controller, output:\n" . join("\n", @$check_dc_output));
+		return;
+	}
+}
+
+#//////////////////////////////////////////////////////////////////////////////
+
 =head2 grant_administrative_access
 
  Parameters  : $username
diff --git a/managementnode/lib/VCL/Module/Provisioning/libvirt/KVM.pm b/managementnode/lib/VCL/Module/Provisioning/libvirt/KVM.pm
index 43741eb..e183690 100644
--- a/managementnode/lib/VCL/Module/Provisioning/libvirt/KVM.pm
+++ b/managementnode/lib/VCL/Module/Provisioning/libvirt/KVM.pm
@@ -621,7 +621,7 @@
 	
 	my $start_time = time;
 	my ($exit_status, $output) = $self->vmhost_os->execute($command, 0, 7200);
-	if (defined($output && grep(/Unknown option.*compat/, @$output))) {
+	if (defined($output) && grep(/Unknown option.*compat/, @$output)) {
 		# Check for older versions which don't support '-o compat=':
 		#    Unknown option 'compat'
 		#    qemu-img: Invalid options for file format 'qcow2'.
diff --git a/managementnode/lib/VCL/utils.pm b/managementnode/lib/VCL/utils.pm
index 2342e37..75cf782 100644
--- a/managementnode/lib/VCL/utils.pm
+++ b/managementnode/lib/VCL/utils.pm
@@ -1306,28 +1306,22 @@
 		$shared_mail_box = $management_node_info->{SHARED_EMAIL_BOX} if $management_node_info->{SHARED_EMAIL_BOX};
 	}
 
+	my $mail_args = {From => $from, To => $to, Subject => $subject};
 	if ($shared_mail_box) {
-		my $bcc = $shared_mail_box;
-		if ($mailer->open({From => $from, To => $to, Bcc => $bcc, Subject => $subject})) {
-			print $mailer $mailstring;
-			$mailer->close();
-			notify($ERRORS{'OK'}, 0, "SUCCESS -- Sending mail To: $to, $subject");
-		}
-		else {
-			notify($ERRORS{'WARNING'}, 0, "NOTICE --  Problem sending mail to: $to From");
-		}
-	} ## end if ($shared_mail_box)
+		$mail_args->{Bcc} = $shared_mail_box;
+	}
+	if($mailstring =~ /<html>/ || $mailstring =~ /<html .*>/) {
+		$mail_args->{'Content-Type'} = "text/html";
+		notify($ERRORS{'DEBUG'}, 0, "Encountered message containing <html> tag, adding Content-Type header");
+	}
+	if ($mailer->open($mail_args)) {
+		print $mailer $mailstring;
+		$mailer->close();
+		notify($ERRORS{'OK'}, 0, "SUCCESS -- Sending mail To: $to, $subject");
+	}
 	else {
-		if ($mailer->open({From => $from, To => $to, Subject => $subject,}))
-		{
-			print $mailer $mailstring;
-			$mailer->close();
-			notify($ERRORS{'OK'}, 0, "SUCCESS -- Sending mail To: $to, $subject");
-		}
-		else {
-			notify($ERRORS{'WARNING'}, 0, "NOTICE --  Problem sending mail to: $to From");
-		}
-	} ## end else [ if ($shared_mail_box)
+		notify($ERRORS{'WARNING'}, 0, "NOTICE --  Problem sending mail to: $to");
+	}
 } ## end sub mail
 
 #//////////////////////////////////////////////////////////////////////////////
diff --git a/mysql/update-vcl.sql b/mysql/update-vcl.sql
index 1dea030..624f3f1 100644
--- a/mysql/update-vcl.sql
+++ b/mysql/update-vcl.sql
@@ -1128,6 +1128,18 @@
 
 -- --------------------------------------------------------
 
+-- 
+-- Table structure for table `messagereset`
+-- 
+
+CREATE TABLE IF NOT EXISTS `messagereset` (
+  `name` varchar(128) NOT NULL,
+  `value` longtext NOT NULL,
+  PRIMARY KEY (`name`)
+) ENGINE=InnoDB  DEFAULT CHARSET=latin1;
+
+-- --------------------------------------------------------
+
 --
 -- Table structure change for table `module`
 --
@@ -1751,6 +1763,30 @@
 -- --------------------------------------------------------
 
 -- 
+-- Inserts for table `messagereset`
+-- 
+
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES ('adminmessage|image_creation_failed', '---\nmessage: |\n  VCL Image Creation Failed\n  \n  Management node: [management_node_short_name]\n  \n  Request ID: [request_id]\n  Reservation ID: [reservation_id]\n  PID: [process_pid]\n  \n  Image ID: [image_id]\n  Image revision ID: [imagerevision_id]\n  Image name: [image_name]\n  Image display name: [image_prettyname]\n  Image OS package: [image_os_module_perl_package]\n  \n  User ID: [user_id]\n  User login name: [user_login_id]\n  User name: [user_firstname] [user_lastname]\n  User affiliation: [user_affiliation_name]\n  \n  Provisioning module: [computer_provisioning_pretty_name] ([computer_provisioning_name])\n  Provisioning package: [computer_provisioning_module_perl_package]\n  \n  Computer ID: [computer_id]\n  Computer name: [computer_short_name]\n  \n  VM host ID: [vmhost_id]\n  VM host computer ID: [vmhost_computer_id]\n  VM host computer name: [vmhost_short_name]\n  \n  VM host profile ID: [vmhost_profile_id]\n  VM host profile name: [vmhost_profile_name]\nsubject: ''VCL -- NOTICE FAILED Image [image_capture_type] [image_prettyname]''\n');
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES ('adminmessage|image_creation_complete', '---\nmessage: |\n  VCL Image [image_capture_type] Completed\n  \n  Request ID: [request_id]\n  Reservation ID: [reservation_id]\n  PID: [process_pid]\n  \n  Image ID: [image_id]\n  Image name: [image_name]\n  Image size: [image_size]\n  \n  Revision ID: [imagerevision_id]\n  \n  Management node: [management_node_short_name]\n  \n  Username: [user_login_id]\n  User ID: [user_id]\n  \n  Computer ID: [computer_id]\n  Computer name: [computer_short_name]\n  \n  Use Sysprep: [imagemeta_sysprep]\nsubject: ''VCL IMAGE [image_capture_type] Completed: [image_name]''\n');
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES ('adminmessage|image_creation_started', '---\nmessage: |\n  VCL Image Creation Started\n  \n  Request ID: [request_id]\n  Reservation ID: [reservation_id]\n  PID: [process_pid]\n  \n  Image ID: [image_id]\n  Image name: [image_name]\n  Base image size: [image_size]\n  Base revision ID: [imagerevision_id]\n  \n  Management node: [management_node_short_name]\n  \n  Username: [user_login_id]\n  User ID: [user_id]\n  \n  Computer ID: [computer_id]\n  Computer name: [computer_short_name]\n  \n  Use Sysprep: [imagemeta_sysprep]\nsubject: ''VCL IMAGE Creation Started: [image_name]''\n');
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES ('usermessage|endtime_reached|Global', '---\nmessage: |\n  Your reservation of [image_prettyname] has ended. Thank you for using [user_affiliation_sitewwwaddress].\n  \n  Regards,\n  VCL Team\n  \n  \n  ******************************************************************\n  This is an automated notice. If you need assistance please respond \n  with detailed information on the issue and a help ticket will be \n  generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  \n  ******************************************************************\nshort_message: ~\nsubject: ''VCL -- End of reservation''\n');
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES ('usermessage|reserved|Global', '---\nmessage: |\n  The resources for your VCL reservation have been successfully reserved.\n  Connection will not be allowed until you click the ''Connect'' button on the ''Current Reservations'' page.\n  You must acknowledge the reservation within the next 15 minutes or the resources will be reclaimed for other VCL users.\n  \n  -Visit [user_affiliation_sitewwwaddress]\n  -Select "Current Reservations"\n  -Click the "Connect" button\n  Upon acknowledgement, all of the remaining connection details will be displayed.\n  \n  Thank You,\n  VCL Team\n  \n  ******************************************************************\n  This is an automated notice. If you need assistance please respond \n  with detailed information on the issue and a help ticket will be \n  generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  \n  ******************************************************************\nshort_message: ~\nsubject: ''VCL -- [image_prettyname] reservation''\n');
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES ('usermessage|timeout_no_initial_connection|Global', '---\nmessage: |\n  Your reservation has timed out for image [image_prettyname] because no initial connection was made.\n  \n  To make another reservation, please revisit [user_affiliation_sitewwwaddress].\n  \n  Thank You,\n  VCL Team\n  \n  \n  ******************************************************************\n  This is an automated notice. If you need assistance\n  please respond with detailed information on the issue\n  and a help ticket will be generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  ******************************************************************\nshort_message: ~\nsubject: ''VCL -- Reservation Timeout''\n');
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES ('usermessage|endtime_imminent|Global', '---\nmessage: |\n  You have [notice_interval] until the end of your reservation for image [image_prettyname], please save all work and prepare to exit.\n  \n  Reservation extensions are available if the machine you are on does not have a reservation immediately following.\n  \n  Visit [user_affiliation_sitewwwaddress] and select Current Reservations to edit this reservation.\n  \n  Thank You,\n  VCL Team\n  \n  \n  ******************************************************************\n  This is an automated notice. If you need assistance please respond \n  with detailed information on the issue and a help ticket will be \n  generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  \n  ******************************************************************\nshort_message: ''You have [notice_interval] until the end of your reservation. Please save all work and prepare to log off.''\nsubject: ''VCL -- [notice_interval] until end of reservation''\n');
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES ('usermessage|production_imagerevision|Global', '---\nmessage: |\n  Revision [imagerevision_revision] of your VCL ''[image_prettyname]'' image has been made production.  Any new reservations for the image will receive this revision by default.\n  \n  If you have any questions, please contact [user_affiliation_helpaddress].\n  \n  Thank You,\n  VCL Team\nshort_message: ~\nsubject: ''VCL -- Image [image_prettyname] made production''\n');
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES ('usermessage|timeout_inactivity|Global', '---\nmessage: |\n  Your reservation has timed out due to inactivity for image [image_prettyname].\n  \n  To make another reservation, please revisit:\n  [user_affiliation_sitewwwaddress]\n  \n  Thank You,\n  VCL Team\n  \n  \n  ******************************************************************\n  This is an automated notice. If you need assistance please respond \n  with detailed information on the issue and a help ticket will be \n  generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  \n  ******************************************************************\nshort_message: ~\nsubject: ''VCL -- reservation timeout''\n');
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES ('usermessage|image_creation_delayed|Global', '---\nmessage: |\n  We apologize for the inconvenience.\n  Your image creation of [image_prettyname] has been delayed\n  due to a system issue that prevented the automatic completion.\n  \n  The image creation request and the computing resource have\n  been placed in a safe mode. The VCL system administrators\n  have been notified for manual intervention.\n  \n  Once the issues have been resolved, you will be notified\n  by the successful completion email or contacted directly\n  by the VCL system administrators.\n  \n  If you do not receive a response within one business day, please\n  reply to this email.\n  \n  Thank You,\n  VCL Team\nshort_message: ~\nsubject: ''VCL -- NOTICE DELAY Image Creation [image_prettyname]''\n');
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES ('usermessage|reinstalled|Global', '---\nmessage: |\n  Your reservation was successfully reinstalled and you can proceed to reconnect. \n  Please revisit the ''Current Reservations'' page for any additional information.\n  \n  Thank You,\n  VCL Team\n  \n  ******************************************************************\n  This is an automated notice. If you need assistance please respond \n  with detailed information on the issue and a help ticket will be \n  generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  \n  ******************************************************************''\nshort_message: ~\nsubject: ''VCL -- [image_prettyname] reservation reinstalled''\n');
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES ('usermessage|endtime_reached_imaging|Global', '---\nmessage: |\n  Your imaging reservation of [image_prettyname] has reached it''s scheduled end time.\n  \n  To avoid losing your work we have started an automatic capture of this image. Upon completion of the \n  image capture. You will be notified about the completion of the image capture.\n  \n  Thank You,\n  VCL Team\n  \n  \n  ******************************************************************\n  This is an automated notice. If you need assistance please respond \n  with detailed information on the issue and a help ticket will be \n  generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  \n  ******************************************************************\nshort_message: ~\nsubject: ''VCL Image Reservation - Auto capture started''\n');
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES ('usermessage|image_creation_success|Global', '---\nmessage: |\n  Your VCL image creation request for [image_prettyname] has succeeded.\n  \n  Please visit [user_affiliation_sitewwwaddress] and you should see an image called [image_prettyname].\n  \n  Please test this image to confirm it works correctly.\n  \n  Thank You,\n  VCL Team\nshort_message: ~\nsubject: ''VCL -- [image_prettyname] Image Creation Succeeded''\n');
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES ('usermessage|image_checkpoint_success|Global', '---\nmessage: |\n  Your VCL image checkpoint creation request for [image_prettyname] has succeeded.\n  \n  You will need to visit the "Current Reservations" page and click "Connect" in order to be able to reconnect to the computer.\n  \n  Thank You,\n  VCL Team\nshort_message: ~\nsubject: ''VCL -- [image_prettyname] Image Checkpoint Succeeded''\n');
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES ('usermessage|timeout_no_acknowledgement|Global', '---\nmessage: |\n  Your reservation has timed out for image [image_prettyname] because no initial connection was made.\n  \n  To make another reservation, please revisit [user_affiliation_sitewwwaddress].\n  \n  Thank You,\n  VCL Team\n  \n  \n  ******************************************************************\n  This is an automated notice. If you need assistance\n  please respond with detailed information on the issue\n  and a help ticket will be generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  ******************************************************************\nshort_message: ~\nsubject: ''VCL -- Reservation Timeout''\n');
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES ('usermessage|future_endtime|Global', '---\nmessage: |\n  You have [notice_interval] until the scheduled end time of your reservation for image [image_prettyname].\n  \n  Reservation extensions are available if the machine you are on does not have a reservation immediately following.\n  \n  To edit this reservation:\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select Current Reservations\n  \n  Thank You,\n  VCL Team\n  \n  \n  ******************************************************************\n  This is an automated notice. If you need assistance please respond \n  with detailed information on the issue and a help ticket will be \n  generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  \n  ******************************************************************\nshort_message: "You have [notice_interval] until the scheduled end time of your reservation. VCL Team\\n"\nsubject: ''VCL -- [notice_interval] until end of reservation for [image_prettyname]''\n');
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES ('usermessage|endtime_imminent_imaging|Global', '---\nmessage: |\n  You have [notice_interval] until the end of your reservation for image [image_prettyname]. \n  \n  At the scheduled end time your imaging reservation will be automatically captured. \n  \n  To prevent this auto capture, visit the VCL site [user_affiliation_sitewwwaddress] manually start the image creation process.\n  \n  Please note this auto capture feature is intended to prevent destorying any work you have done to the image.\n  \n  Thank You,\n  VCL Team\n  \n  \n  ******************************************************************\n  This is an automated notice. If you need assistance please respond \n  with detailed information on the issue and a help ticket will be \n  generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  \n  ******************************************************************\nshort_message: ''You have [notice_interval] until the auto capture process is started.''\nsubject: ''VCL Imaging Reservation -- [notice_interval] until starting auto capture''\n');
+
+-- --------------------------------------------------------
+
+-- 
 -- Inserts for table `module`
 -- 
 
diff --git a/mysql/vcl.sql b/mysql/vcl.sql
index 39db00d..dea4ea9 100644
--- a/mysql/vcl.sql
+++ b/mysql/vcl.sql
@@ -710,6 +710,18 @@
 
 -- --------------------------------------------------------
 
+-- 
+-- Table structure for table `messagereset`
+-- 
+
+CREATE TABLE IF NOT EXISTS `messagereset` (
+  `name` varchar(128) NOT NULL,
+  `value` longtext NOT NULL,
+  PRIMARY KEY (`name`)
+) ENGINE=InnoDB  DEFAULT CHARSET=latin1;
+
+-- --------------------------------------------------------
+
 --
 -- Table structure for table `module`
 --
@@ -1788,6 +1800,29 @@
 (1, 'none');
 
 -- 
+-- Dumping data for table `messagereset`
+-- 
+
+INSERT IGNORE INTO `messagereset` (`name`, `value`) VALUES
+('adminmessage|image_creation_failed', '---\nmessage: |\n  VCL Image Creation Failed\n  \n  Management node: [management_node_short_name]\n  \n  Request ID: [request_id]\n  Reservation ID: [reservation_id]\n  PID: [process_pid]\n  \n  Image ID: [image_id]\n  Image revision ID: [imagerevision_id]\n  Image name: [image_name]\n  Image display name: [image_prettyname]\n  Image OS package: [image_os_module_perl_package]\n  \n  User ID: [user_id]\n  User login name: [user_login_id]\n  User name: [user_firstname] [user_lastname]\n  User affiliation: [user_affiliation_name]\n  \n  Provisioning module: [computer_provisioning_pretty_name] ([computer_provisioning_name])\n  Provisioning package: [computer_provisioning_module_perl_package]\n  \n  Computer ID: [computer_id]\n  Computer name: [computer_short_name]\n  \n  VM host ID: [vmhost_id]\n  VM host computer ID: [vmhost_computer_id]\n  VM host computer name: [vmhost_short_name]\n  \n  VM host profile ID: [vmhost_profile_id]\n  VM host profile name: [vmhost_profile_name]\nsubject: ''VCL -- NOTICE FAILED Image [image_capture_type] [image_prettyname]''\n'),
+('adminmessage|image_creation_complete', '---\nmessage: |\n  VCL Image [image_capture_type] Completed\n  \n  Request ID: [request_id]\n  Reservation ID: [reservation_id]\n  PID: [process_pid]\n  \n  Image ID: [image_id]\n  Image name: [image_name]\n  Image size: [image_size]\n  \n  Revision ID: [imagerevision_id]\n  \n  Management node: [management_node_short_name]\n  \n  Username: [user_login_id]\n  User ID: [user_id]\n  \n  Computer ID: [computer_id]\n  Computer name: [computer_short_name]\n  \n  Use Sysprep: [imagemeta_sysprep]\nsubject: ''VCL IMAGE [image_capture_type] Completed: [image_name]''\n'),
+('adminmessage|image_creation_started', '---\nmessage: |\n  VCL Image Creation Started\n  \n  Request ID: [request_id]\n  Reservation ID: [reservation_id]\n  PID: [process_pid]\n  \n  Image ID: [image_id]\n  Image name: [image_name]\n  Base image size: [image_size]\n  Base revision ID: [imagerevision_id]\n  \n  Management node: [management_node_short_name]\n  \n  Username: [user_login_id]\n  User ID: [user_id]\n  \n  Computer ID: [computer_id]\n  Computer name: [computer_short_name]\n  \n  Use Sysprep: [imagemeta_sysprep]\nsubject: ''VCL IMAGE Creation Started: [image_name]''\n'),
+('usermessage|endtime_reached|Global', '---\nmessage: |\n  Your reservation of [image_prettyname] has ended. Thank you for using [user_affiliation_sitewwwaddress].\n  \n  Regards,\n  VCL Team\n  \n  \n  ******************************************************************\n  This is an automated notice. If you need assistance please respond \n  with detailed information on the issue and a help ticket will be \n  generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  \n  ******************************************************************\nshort_message: ~\nsubject: ''VCL -- End of reservation''\n'),
+('usermessage|reserved|Global', '---\nmessage: |\n  The resources for your VCL reservation have been successfully reserved.\n  Connection will not be allowed until you click the ''Connect'' button on the ''Current Reservations'' page.\n  You must acknowledge the reservation within the next 15 minutes or the resources will be reclaimed for other VCL users.\n  \n  -Visit [user_affiliation_sitewwwaddress]\n  -Select "Current Reservations"\n  -Click the "Connect" button\n  Upon acknowledgement, all of the remaining connection details will be displayed.\n  \n  Thank You,\n  VCL Team\n  \n  ******************************************************************\n  This is an automated notice. If you need assistance please respond \n  with detailed information on the issue and a help ticket will be \n  generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  \n  ******************************************************************\nshort_message: ~\nsubject: ''VCL -- [image_prettyname] reservation''\n'),
+('usermessage|timeout_no_initial_connection|Global', '---\nmessage: |\n  Your reservation has timed out for image [image_prettyname] because no initial connection was made.\n  \n  To make another reservation, please revisit [user_affiliation_sitewwwaddress].\n  \n  Thank You,\n  VCL Team\n  \n  \n  ******************************************************************\n  This is an automated notice. If you need assistance\n  please respond with detailed information on the issue\n  and a help ticket will be generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  ******************************************************************\nshort_message: ~\nsubject: ''VCL -- Reservation Timeout''\n'),
+('usermessage|endtime_imminent|Global', '---\nmessage: |\n  You have [notice_interval] until the end of your reservation for image [image_prettyname], please save all work and prepare to exit.\n  \n  Reservation extensions are available if the machine you are on does not have a reservation immediately following.\n  \n  Visit [user_affiliation_sitewwwaddress] and select Current Reservations to edit this reservation.\n  \n  Thank You,\n  VCL Team\n  \n  \n  ******************************************************************\n  This is an automated notice. If you need assistance please respond \n  with detailed information on the issue and a help ticket will be \n  generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  \n  ******************************************************************\nshort_message: ''You have [notice_interval] until the end of your reservation. Please save all work and prepare to log off.''\nsubject: ''VCL -- [notice_interval] until end of reservation''\n'),
+('usermessage|production_imagerevision|Global', '---\nmessage: |\n  Revision [imagerevision_revision] of your VCL ''[image_prettyname]'' image has been made production.  Any new reservations for the image will receive this revision by default.\n  \n  If you have any questions, please contact [user_affiliation_helpaddress].\n  \n  Thank You,\n  VCL Team\nshort_message: ~\nsubject: ''VCL -- Image [image_prettyname] made production''\n'),
+('usermessage|timeout_inactivity|Global', '---\nmessage: |\n  Your reservation has timed out due to inactivity for image [image_prettyname].\n  \n  To make another reservation, please revisit:\n  [user_affiliation_sitewwwaddress]\n  \n  Thank You,\n  VCL Team\n  \n  \n  ******************************************************************\n  This is an automated notice. If you need assistance please respond \n  with detailed information on the issue and a help ticket will be \n  generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  \n  ******************************************************************\nshort_message: ~\nsubject: ''VCL -- reservation timeout''\n'),
+('usermessage|image_creation_delayed|Global', '---\nmessage: |\n  We apologize for the inconvenience.\n  Your image creation of [image_prettyname] has been delayed\n  due to a system issue that prevented the automatic completion.\n  \n  The image creation request and the computing resource have\n  been placed in a safe mode. The VCL system administrators\n  have been notified for manual intervention.\n  \n  Once the issues have been resolved, you will be notified\n  by the successful completion email or contacted directly\n  by the VCL system administrators.\n  \n  If you do not receive a response within one business day, please\n  reply to this email.\n  \n  Thank You,\n  VCL Team\nshort_message: ~\nsubject: ''VCL -- NOTICE DELAY Image Creation [image_prettyname]''\n'),
+('usermessage|reinstalled|Global', '---\nmessage: |\n  Your reservation was successfully reinstalled and you can proceed to reconnect. \n  Please revisit the ''Current Reservations'' page for any additional information.\n  \n  Thank You,\n  VCL Team\n  \n  ******************************************************************\n  This is an automated notice. If you need assistance please respond \n  with detailed information on the issue and a help ticket will be \n  generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  \n  ******************************************************************''\nshort_message: ~\nsubject: ''VCL -- [image_prettyname] reservation reinstalled''\n'),
+('usermessage|endtime_reached_imaging|Global', '---\nmessage: |\n  Your imaging reservation of [image_prettyname] has reached it''s scheduled end time.\n  \n  To avoid losing your work we have started an automatic capture of this image. Upon completion of the \n  image capture. You will be notified about the completion of the image capture.\n  \n  Thank You,\n  VCL Team\n  \n  \n  ******************************************************************\n  This is an automated notice. If you need assistance please respond \n  with detailed information on the issue and a help ticket will be \n  generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  \n  ******************************************************************\nshort_message: ~\nsubject: ''VCL Image Reservation - Auto capture started''\n'),
+('usermessage|image_creation_success|Global', '---\nmessage: |\n  Your VCL image creation request for [image_prettyname] has succeeded.\n  \n  Please visit [user_affiliation_sitewwwaddress] and you should see an image called [image_prettyname].\n  \n  Please test this image to confirm it works correctly.\n  \n  Thank You,\n  VCL Team\nshort_message: ~\nsubject: ''VCL -- [image_prettyname] Image Creation Succeeded''\n'),
+('usermessage|image_checkpoint_success|Global', '---\nmessage: |\n  Your VCL image checkpoint creation request for [image_prettyname] has succeeded.\n  \n  You will need to visit the "Current Reservations" page and click "Connect" in order to be able to reconnect to the computer.\n  \n  Thank You,\n  VCL Team\nshort_message: ~\nsubject: ''VCL -- [image_prettyname] Image Checkpoint Succeeded''\n'),
+('usermessage|timeout_no_acknowledgement|Global', '---\nmessage: |\n  Your reservation has timed out for image [image_prettyname] because no initial connection was made.\n  \n  To make another reservation, please revisit [user_affiliation_sitewwwaddress].\n  \n  Thank You,\n  VCL Team\n  \n  \n  ******************************************************************\n  This is an automated notice. If you need assistance\n  please respond with detailed information on the issue\n  and a help ticket will be generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  ******************************************************************\nshort_message: ~\nsubject: ''VCL -- Reservation Timeout''\n'),
+('usermessage|future_endtime|Global', '---\nmessage: |\n  You have [notice_interval] until the scheduled end time of your reservation for image [image_prettyname].\n  \n  Reservation extensions are available if the machine you are on does not have a reservation immediately following.\n  \n  To edit this reservation:\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select Current Reservations\n  \n  Thank You,\n  VCL Team\n  \n  \n  ******************************************************************\n  This is an automated notice. If you need assistance please respond \n  with detailed information on the issue and a help ticket will be \n  generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  \n  ******************************************************************\nshort_message: "You have [notice_interval] until the scheduled end time of your reservation. VCL Team\\n"\nsubject: ''VCL -- [notice_interval] until end of reservation for [image_prettyname]''\n'),
+('usermessage|endtime_imminent_imaging|Global', '---\nmessage: |\n  You have [notice_interval] until the end of your reservation for image [image_prettyname]. \n  \n  At the scheduled end time your imaging reservation will be automatically captured. \n  \n  To prevent this auto capture, visit the VCL site [user_affiliation_sitewwwaddress] manually start the image creation process.\n  \n  Please note this auto capture feature is intended to prevent destorying any work you have done to the image.\n  \n  Thank You,\n  VCL Team\n  \n  \n  ******************************************************************\n  This is an automated notice. If you need assistance please respond \n  with detailed information on the issue and a help ticket will be \n  generated.\n  \n  To disable email notices\n  -Visit [user_affiliation_sitewwwaddress]\n  -Select User Preferences\n  -Select General Preferences\n  \n  ******************************************************************\nshort_message: ''You have [notice_interval] until the auto capture process is started.''\nsubject: ''VCL Imaging Reservation -- [notice_interval] until starting auto capture''\n');
+
+-- 
 -- Dumping data for table `module`
 -- 
 
diff --git a/web/.ht-inc/addomain.php b/web/.ht-inc/addomain.php
index c4fba74..e59d72c 100644
--- a/web/.ht-inc/addomain.php
+++ b/web/.ht-inc/addomain.php
@@ -528,10 +528,6 @@
 			$return['error'] = 1;
 			$errormsg[] = i("An AD domain already exists with this name.");
 		}
-		elseif($this->checkExistingField('domainDNSName', $return['domaindnsname'], $return['rscid'])) {
-			$return['error'] = 1;
-			$errormsg[] = i("An AD domain already exists with this Domain DNS Name.");
-		}
 		if(! validateUserid($return['owner'])) {
 			$return['error'] = 1;
 			$errormsg[] = i("Submitted owner is not valid");
diff --git a/web/.ht-inc/authentication.php b/web/.ht-inc/authentication.php
index 7a93cc0..cb72534 100644
--- a/web/.ht-inc/authentication.php
+++ b/web/.ht-inc/authentication.php
@@ -19,13 +19,21 @@
 /**
  * \file
  */
+
+$authFuncs['local'] = array('test' => function() {return 0;},
+                            'auth' => function() {return NULL;},
+                            'unauth' => 'unauthLocal');
+
 ////////////////////////////////////////////////////////////////////////////////
 ///
-/// \fn getAuthCookieData($loginid, $valid)
+/// \fn getAuthCookieData($loginid, $authtype, $valid, $shibauthid)
 ///
 /// \param $loginid - login id for user
+/// \param $authtype - type of authentication used; should be an index from the
+/// global $authFuncs array
 /// \param $valid - (optional, default=600) - time in minutes the cookie
 /// should be valid
+/// \param $shibauthid - (optional) id of shibboleth session
 ///
 /// \return on failure, an error message; on success, an array with 2 elements:\n
 /// data - encrypted payload for auth cookie\n
@@ -35,16 +43,16 @@
 /// a timestamp
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function getAuthCookieData($loginid, $valid=600, $shibauthid=0) {
+function getAuthCookieData($loginid, $authtype, $valid=600, $shibauthid=0) {
 	global $keys;
 	$ts = time() + ($valid * 60);
 	$remoteIP = $_SERVER["REMOTE_ADDR"];
 	if(empty($remoteIP))
 		return "Failed to obtain remote IP address for fixed cookie type";
 	if($shibauthid)
-		$cdata = "$loginid|$remoteIP|$ts|$shibauthid";
+		$cdata = "$loginid|$remoteIP|$ts|$authtype|$shibauthid";
 	else
-		$cdata = "$loginid|$remoteIP|$ts";
+		$cdata = "$loginid|$remoteIP|$ts|$authtype";
 
 	# 245 characters can be encrypted; anything over that, and
 	#   openssl_private_encrypt will fail
@@ -75,19 +83,32 @@
 	else
 		$cookie = $_COOKIE["VCLAUTH"];
 	$cookie = base64_decode($cookie);
-   if(! openssl_public_decrypt($cookie, $tmp, $keys['public'])) {
-      $AUTHERROR["code"] = 3;
-      $AUTHERROR["message"] = "Failed to decrypt auth cookie";
-      return NULL;
-   }
+	if(! openssl_public_decrypt($cookie, $tmp, $keys['public'])) {
+		# cookie is invalid; clear it and return NULL so will get redirected to log in again
+		setcookie("VCLAUTH", "", time() - 10, "/", COOKIEDOMAIN);
+		$AUTHERROR["code"] = 3;
+		$AUTHERROR["message"] = "Failed to decrypt auth cookie";
+		return NULL;
+	}
 
-   $tmparr = explode('|', $tmp);
+	# $loginid|$remoteIP|$ts|$authtype|$shibauthid (shibauthd optional)
+	$tmparr = explode('|', $tmp);
 	$loginid = $tmparr[0];
 	$remoteIP = $tmparr[1];
 	$ts = $tmparr[2];
-	if(count($tmparr) > 3) {
-		$shibauthed = $tmparr[3];
-	
+
+	# check for old style auth cookie before $authtype was included
+	if(count($tmparr) < 4 || is_numeric($tmparr[3])) {
+		# log user out to get new style auth cookie
+		setcookie("VCLAUTH", "", time() - 10, "/", COOKIEDOMAIN);
+		stopSession();
+		dbDisconnect();
+		header("Location: " . BASEURL);
+		exit;
+	}
+	if(count($tmparr) > 4) {
+		$shibauthed = $tmparr[5];
+
 		# check to see if shibauth entry still exists for $shibauthed
 		$query = "SELECT ts FROM shibauth WHERE id = $shibauthed";
 		$qh = doQuery($query, 101);
@@ -105,19 +126,61 @@
 		}
 	}
 
-   if($ts < time()) {
-      $AUTHERROR["code"] = 4;
-      $AUTHERROR["message"] = "Auth cookie has expired";
-      return NULL;
-   }
-   if($_SERVER["REMOTE_ADDR"] != $remoteIP) {
-      //setcookie("ITECSAUTH", "", time() - 10, "/", COOKIEDOMAIN);
-      $AUTHERROR["code"] = 4;
-      $AUTHERROR["message"] = "remote IP in auth cookie doesn't match user's remote IP";
-      return NULL;
-   }
+	if($ts < time()) {
+		# cookie is expired; clear it and return NULL so will get redirected to log in again
+		setcookie("VCLAUTH", "", time() - 10, "/", COOKIEDOMAIN);
+		$AUTHERROR["code"] = 4;
+		$AUTHERROR["message"] = "Auth cookie has expired";
+		return NULL;
+	}
+	if($_SERVER["REMOTE_ADDR"] != $remoteIP) {
+		# cookie has wrong IP; clear it and return NULL so will get redirected to log in again
+		setcookie("VCLAUTH", "", time() - 10, "/", COOKIEDOMAIN);
+		$AUTHERROR["code"] = 4;
+		$AUTHERROR["message"] = "remote IP in auth cookie doesn't match user's remote IP";
+		return NULL;
+	}
 
-   return $loginid;
+	return $loginid;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn getAuthTypeFromAuthCookie()
+///
+/// \return on success, type of authentication used; NULL on failure
+///
+/// \brief parses the VCLAUTH cookie to get the authtype saved in it
+///
+////////////////////////////////////////////////////////////////////////////////
+function getAuthTypeFromAuthCookie() {
+	global $keys, $AUTHERROR;
+	if(! array_key_exists('VCLAUTH', $_COOKIE))
+		return NULL;
+	if(get_magic_quotes_gpc())
+		$cookie = stripslashes($_COOKIE["VCLAUTH"]);
+	else
+		$cookie = $_COOKIE["VCLAUTH"];
+	$cookie = base64_decode($cookie);
+	if(! openssl_public_decrypt($cookie, $tmp, $keys['public'])) {
+		$AUTHERROR["code"] = 3;
+		$AUTHERROR["message"] = "Failed to decrypt auth cookie";
+		return NULL;
+	}
+
+	# $loginid|$remoteIP|$ts|$authtype|$shibauthid (shibauthd optional)
+	$tmparr = explode('|', $tmp);
+	$remoteIP = $tmparr[1];
+	$authtype = $tmparr[3];
+
+	if($_SERVER["REMOTE_ADDR"] != $remoteIP) {
+		//setcookie("ITECSAUTH", "", time() - 10, "/", COOKIEDOMAIN);
+		$AUTHERROR["code"] = 4;
+		$AUTHERROR["message"] = "remote IP in auth cookie doesn't match user's remote IP";
+		return NULL;
+	}
+
+	return $authtype;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -351,120 +414,6 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
-/// \fn ldapLogin($authtype, $userid, $passwd)
-///
-/// \param $authtype - index from $authMechs array
-/// \param $userid - userid without affiliation
-/// \param $passwd - submitted password
-///
-/// \brief tries to authenticate user via ldap; calls printLoginPageWithSkin if
-/// authentication fails
-///
-////////////////////////////////////////////////////////////////////////////////
-function ldapLogin($authtype, $userid, $passwd) {
-	global $HTMLheader, $printedHTMLheader, $authMechs, $phpVer;
-	$esc_userid = vcl_mysql_escape_string($userid);
-	if(! $fh = fsockopen($authMechs[$authtype]['server'], 636, $errno, $errstr, 5)) {
-		printLoginPageWithSkin($authtype, 1);
-		return;
-	}
-	fclose($fh);
-	$ds = ldap_connect("ldaps://{$authMechs[$authtype]['server']}/");
-	if(! $ds) {
-		addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 0);
-		print $HTMLheader;
-		$printedHTMLheader = 1;
-		selectAuth();
-		return;
-	}
-	ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
-	ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
-	if(array_key_exists('lookupuserbeforeauth', $authMechs[$authtype]) &&
-	   $authMechs[$authtype]['lookupuserbeforeauth'] &&
-	   array_key_exists('lookupuserfield', $authMechs[$authtype])) {
-		# in this case, we have to look up what part of the tree the user is in
-		#   before we can actually look up the user
-		$auth = $authMechs[$authtype];
-		if(array_key_exists('masterlogin', $auth) && strlen($auth['masterlogin']))
-			$res = ldap_bind($ds, $auth['masterlogin'], $auth['masterpwd']);
-		else
-			$res = ldap_bind($ds);
-		if(! $res) {
-			addLoginLog($userid, $authtype, $auth['affiliationid'], 0);
-			printLoginPageWithSkin($authtype);
-			return;
-		}
-		$search = ldap_search($ds,
-		                      $auth['binddn'], 
-		                      "{$auth['lookupuserfield']}=$userid",
-		                      array('dn'), 0, 3, 15);
-		if($search) {
-			$tmpdata = ldap_get_entries($ds, $search);
-			if(! $tmpdata['count'] || ! array_key_exists('dn', $tmpdata[0])) {
-				addLoginLog($userid, $authtype, $auth['affiliationid'], 0);
-				printLoginPageWithSkin($authtype);
-				return;
-			}
-			$ldapuser = $tmpdata[0]['dn'];
-		}
-		else {
-			addLoginLog($userid, $authtype, $auth['affiliationid'], 0);
-			printLoginPageWithSkin($authtype);
-			return;
-		}
-	}
-	else
-		$ldapuser = sprintf($authMechs[$authtype]['userid'], $userid);
-	$res = ldap_bind($ds, $ldapuser, $passwd);
-	if(! $res) {
-		// login failed
-		$err = ldap_error($ds);
-		if($err == 'Invalid credentials')
-			addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 0, $err);
-		else
-			addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 0);
-		printLoginPageWithSkin($authtype);
-		return;
-	}
-	else {
-		addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 1);
-		# used to rely on later code to update user info if update timestamp was expired
-		// see if user in our db
-		/*$query = "SELECT id "
-		       . "FROM user "
-		       . "WHERE unityid = '$esc_userid' AND "
-		       .       "affiliationid = {$authMechs[$authtype]['affiliationid']}";
-		$qh = doQuery($query, 101);
-		if(! mysqli_num_rows($qh)) {
-			// if not, add user
-			$newid = updateLDAPUser($authtype, $userid);
-			if(is_null($newid))
-				abort(8);
-		}*/
-		# now, we always update the user info
-		$newid = updateLDAPUser($authtype, $userid);
-		if(is_null($newid))
-			abort(8);
-		// get cookie data
-		$cookie = getAuthCookieData("$userid@" . getAffiliationName($authMechs[$authtype]['affiliationid']));
-		// set cookie
-		if(version_compare(PHP_VERSION, "5.2", ">=") == true)
-			setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN, 0, 1);
-		else
-			setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN, 0);
-		# set skin cookie based on affiliation
-		$skin = getAffiliationTheme($authMechs[$authtype]['affiliationid']);
-		$ucskin = strtoupper($skin);
-		setcookie("VCLSKIN", "$ucskin", (time() + (SECINDAY * 31)), "/", COOKIEDOMAIN);
-		// redirect to main page
-		header("Location: " . BASEURL . SCRIPT);
-		dbDisconnect();
-		exit;
-	}
-}
-
-////////////////////////////////////////////////////////////////////////////////
-///
 /// \fn localLogin($userid, $passwd, $authtype)
 ///
 /// \param $userid - userid without affiliation
@@ -480,7 +429,7 @@
 	if(validateLocalAccount($userid, $passwd)) {
 		addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 1);
 		//set cookie
-		$cookie = getAuthCookieData("$userid@local");
+		$cookie = getAuthCookieData("$userid@local", 'local');
 		if(version_compare(PHP_VERSION, "5.2", ">=") == true)
 			setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN, 0, 1);
 		else
@@ -503,6 +452,24 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
+/// \fn unauthLocal
+///
+/// \param $mode - headers or content
+///
+/// \brief for headers, simply returns; for content, prints information that
+/// user has been logged out; VCLAUTH cookie is cleared elsewhere
+///
+////////////////////////////////////////////////////////////////////////////////
+function unauthLocal($mode) {
+	if($mode == 'headers')
+		return;
+	print "<h2>Logout</h2>\n";
+	print "You are now logged out of VCL.<br><br>\n";
+	print "<a href=\"" . BASEURL . SCRIPT . "?mode=selectauth\">Return to Login</a><br><br><br>\n";
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
 /// \fn validateLocalAccount($user, $pass)
 ///
 /// \param $user - unityid from user table
diff --git a/web/.ht-inc/authmethods/itecsauth.php b/web/.ht-inc/authmethods/itecsauth.php
index be9b537..a271450 100644
--- a/web/.ht-inc/authmethods/itecsauth.php
+++ b/web/.ht-inc/authmethods/itecsauth.php
@@ -22,6 +22,79 @@
  * \file
  */
 
+$authFuncs['itecs'] = array('test' => 'testITECSAuth',
+                            'auth' => 'processITECSAuth',
+                            'unauth' => 'unauthITECS');
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn testITECSAuth()
+///
+/// \return 1 if ITECSAUTH cookie found, 0 if not
+///
+/// \brief tests for existance of authentication information for ITECS auth
+///
+////////////////////////////////////////////////////////////////////////////////
+function testITECSAuth() {
+	if(array_key_exists('ITECSAUTH', $_COOKIE))
+		return 1;
+	return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn processITECSAuth()
+///
+/// \return userid in form of emailaddress@ITECS or NULL
+///
+/// \brief processes authentication information; returns userid or NULL if
+/// unsuccessful
+///
+////////////////////////////////////////////////////////////////////////////////
+function processITECSAuth() {
+	$authdata = authUser();
+	if(! ($error = getAuthError())) {
+		$userid = "{$authdata["email"]}@ITECS";
+		$affilid = getAffiliationID('ITECS');
+		addLoginLog($userid, 'ITECS', $affilid, 1);
+
+		# get cookie data
+		$cookie = getAuthCookieData($userid, 'itecs', 600);
+		# set cookie
+		if(version_compare(PHP_VERSION, "5.2", ">=") == true)
+			setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN, 0, 1);
+		else
+			setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN);
+
+		return $userid;
+	}
+	return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn unauthITECS($mode)
+///
+/// \param $mode - headers or content
+///
+/// \brief for headers mode, destroys authentication information; for content
+/// mode, prints information about having been logged out
+///
+////////////////////////////////////////////////////////////////////////////////
+function unauthITECS($mode) {
+	if($mode == 'headers') {
+		$time = time() - 10;
+		setcookie("ITECSAUTH_RETURN", "", $time, "/", COOKIEDOMAIN);
+		setcookie("ITECSAUTH_CSS", "", $time, "/", COOKIEDOMAIN);
+		setcookie("ITECSAUTH", "", $time, "/", COOKIEDOMAIN);
+	}
+	elseif($mode == 'content') {
+		print "<h2>Logout</h2>\n";
+		print "You are now logged out of VCL.<br><br>\n";
+		print "<a href=\"" . BASEURL . SCRIPT . "?mode=selectauth\">Return to Login</a><br><br><br>\n";
+	}
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 ///
 /// \fn addITECSUser($loginid)
diff --git a/web/.ht-inc/authmethods/ldapauth.php b/web/.ht-inc/authmethods/ldapauth.php
index 8aa53c6..1c2ee53 100644
--- a/web/.ht-inc/authmethods/ldapauth.php
+++ b/web/.ht-inc/authmethods/ldapauth.php
@@ -20,6 +20,143 @@
  * \file
  */
 
+$authFuncs['ldap'] = array('test' => function() {return 0;},
+                           'auth' => function() {return NULL;},
+                           'unauth' => 'unauthLDAP');
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn unauthLDAP($mode)
+///
+/// \param $mode - headers or content
+///
+/// \brief for headers, simply returns; for content, prints information that
+/// user has been logged out; VCLAUTH cookie is cleared elsewhere
+///
+////////////////////////////////////////////////////////////////////////////////
+function unauthLDAP($mode) {
+	if($mode == 'headers')
+		return;
+	print "<h2>" . _('Logout') . "</h2>\n";
+	print _("You are now logged out of VCL.") . "<br><br>\n";
+	print "<a href=\"" . BASEURL . SCRIPT . "?mode=selectauth\">" . _("Return to Login");
+	print "</a><br><br><br>\n";
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn ldapLogin($authtype, $userid, $passwd)
+///
+/// \param $authtype - index from $authMechs array
+/// \param $userid - userid without affiliation
+/// \param $passwd - submitted password
+///
+/// \brief tries to authenticate user via ldap; calls printLoginPageWithSkin if
+/// authentication fails
+///
+////////////////////////////////////////////////////////////////////////////////
+function ldapLogin($authtype, $userid, $passwd) {
+	global $HTMLheader, $printedHTMLheader, $authMechs, $phpVer;
+	$esc_userid = vcl_mysql_escape_string($userid);
+	if(! $fh = fsockopen($authMechs[$authtype]['server'], 636, $errno, $errstr, 5)) {
+		printLoginPageWithSkin($authtype, 1);
+		return;
+	}
+	fclose($fh);
+	$ds = ldap_connect("ldaps://{$authMechs[$authtype]['server']}/");
+	if(! $ds) {
+		addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 0);
+		print $HTMLheader;
+		$printedHTMLheader = 1;
+		selectAuth();
+		return;
+	}
+	ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
+	ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
+	if(array_key_exists('lookupuserbeforeauth', $authMechs[$authtype]) &&
+	   $authMechs[$authtype]['lookupuserbeforeauth'] &&
+	   array_key_exists('lookupuserfield', $authMechs[$authtype])) {
+		# in this case, we have to look up what part of the tree the user is in
+		#   before we can actually look up the user
+		$auth = $authMechs[$authtype];
+		if(array_key_exists('masterlogin', $auth) && strlen($auth['masterlogin']))
+			$res = ldap_bind($ds, $auth['masterlogin'], $auth['masterpwd']);
+		else
+			$res = ldap_bind($ds);
+		if(! $res) {
+			addLoginLog($userid, $authtype, $auth['affiliationid'], 0);
+			printLoginPageWithSkin($authtype);
+			return;
+		}
+		$search = ldap_search($ds,
+		                      $auth['binddn'], 
+		                      "{$auth['lookupuserfield']}=$userid",
+		                      array('dn'), 0, 3, 15);
+		if($search) {
+			$tmpdata = ldap_get_entries($ds, $search);
+			if(! $tmpdata['count'] || ! array_key_exists('dn', $tmpdata[0])) {
+				addLoginLog($userid, $authtype, $auth['affiliationid'], 0);
+				printLoginPageWithSkin($authtype);
+				return;
+			}
+			$ldapuser = $tmpdata[0]['dn'];
+		}
+		else {
+			addLoginLog($userid, $authtype, $auth['affiliationid'], 0);
+			printLoginPageWithSkin($authtype);
+			return;
+		}
+	}
+	else
+		$ldapuser = sprintf($authMechs[$authtype]['userid'], $userid);
+	$res = ldap_bind($ds, $ldapuser, $passwd);
+	if(! $res) {
+		// login failed
+		$err = ldap_error($ds);
+		if($err == 'Invalid credentials')
+			addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 0, $err);
+		else
+			addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 0);
+		printLoginPageWithSkin($authtype);
+		return;
+	}
+	else {
+		addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 1);
+		# used to rely on later code to update user info if update timestamp was expired
+		// see if user in our db
+		/*$query = "SELECT id "
+		       . "FROM user "
+		       . "WHERE unityid = '$esc_userid' AND "
+		       .       "affiliationid = {$authMechs[$authtype]['affiliationid']}";
+		$qh = doQuery($query, 101);
+		if(! mysqli_num_rows($qh)) {
+			// if not, add user
+			$newid = updateLDAPUser($authtype, $userid);
+			if(is_null($newid))
+				abort(8);
+		}*/
+		# now, we always update the user info
+		$newid = updateLDAPUser($authtype, $userid);
+		if(is_null($newid))
+			abort(8);
+		// get cookie data
+		$cookie = getAuthCookieData("$userid@" . getAffiliationName($authMechs[$authtype]['affiliationid']), 'ldap');
+		// set cookie
+		if(version_compare(PHP_VERSION, "5.2", ">=") == true)
+			setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN, 0, 1);
+		else
+			setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN, 0);
+		# set skin cookie based on affiliation
+		$skin = getAffiliationTheme($authMechs[$authtype]['affiliationid']);
+		$ucskin = strtoupper($skin);
+		setcookie("VCLSKIN", "$ucskin", (time() + (SECINDAY * 31)), "/", COOKIEDOMAIN);
+		// redirect to main page
+		header("Location: " . BASEURL . SCRIPT);
+		dbDisconnect();
+		exit;
+	}
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 ///
 /// \fn addLDAPUser($authtype, $userid)
diff --git a/web/.ht-inc/authmethods/shibauth.php b/web/.ht-inc/authmethods/shibauth.php
index 33d7b5d..947035e 100644
--- a/web/.ht-inc/authmethods/shibauth.php
+++ b/web/.ht-inc/authmethods/shibauth.php
@@ -20,6 +20,286 @@
  * \file
  */
 
+$authFuncs['shibboleth'] = array('test' => 'testShibAuth',
+                                 'auth' => 'processShibAuth',
+                                 'unauth' => 'unauthShib');
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn testShibAuth()
+///
+/// \returns 1 if SHIB_EPPN found in $_SERVER; 0 otherwise
+///
+/// \brief checks for authentication information related to Shibboleth
+///
+////////////////////////////////////////////////////////////////////////////////
+function testShibAuth() {
+	// TODO check for other shib variables, if found but EPPN not found, alert user that EPPN is not being released
+	if(array_key_exists('SHIB_EPPN', $_SERVER))
+		return 1;
+	return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn processShibAuth()
+///
+/// \returns userid in userid@AFFILIATION form
+///
+/// \brief processes Shibboleth authentication information
+///
+////////////////////////////////////////////////////////////////////////////////
+function processShibAuth() {
+	# get VCL affiliation from shib affiliation
+	$tmp = explode(';', $_SERVER['SHIB_EPPN']);
+	$tmp = explode('@', $tmp[0]);
+	$username = strtolower($tmp[0]);
+	$shibaffil = vcl_mysql_escape_string(strtolower($tmp[1]));
+	$query = "SELECT name, shibonly FROM affiliation WHERE shibname = '$shibaffil'";
+	$qh = doQuery($query, 101);
+	# if shib affiliation not already in VCL, create affiliation
+	if(! ($row = mysqli_fetch_assoc($qh))) {
+		$affil = strtolower($tmp[1]);
+		$tmp = explode('.', $affil);
+		array_pop($tmp);
+		$affilname = strtoupper(implode('', $tmp));
+		$affilname = preg_replace('/[^A-Z0-9]/', '', $affilname);
+		$query = "SELECT name, "
+				 .        "shibname "
+				 . "FROM affiliation "
+				 . "WHERE name LIKE '$affilname%' "
+				 . "ORDER BY name DESC "
+				 . "LIMIT 1";
+		$qh = doQuery($query, 101);
+		if($row = mysqli_fetch_assoc($qh)) {
+			if(preg_match("/$affilname([0-9]+)/", $row['name'], $matches)) {
+				$cnt = $matches[1];
+				$cnt++;
+				$newaffilname = $affilname . $cnt;
+			}
+			elseif($affilname != strtoupper($row['name']) && $affil != $row['shibname']) {
+				$newaffilname = $affilname;
+			}
+			else {
+				$msg = "Someone tried to log in to VCL using Shibboleth from an IdP "
+					  . "affiliation that could not be automatically added.\n\n"
+					  . "eppn: {$_SERVER['SHIB_EPPN']}\n"
+					  . "givenName: {$_SERVER['SHIB_GIVENNAME']}\n"
+					  . "sn: {$_SERVER['SHIB_SN']}\n";
+				if(array_key_exists('SHIB_MAIL', $_SERVER))
+					$msg .= "mail: {$_SERVER['SHIB_MAIL']}\n\n";
+				$msg .="tried to add VCL affiliation name \"$affilname\" with "
+					  . "shibname \"$affil\"";
+				$mailParams = "-f" . ENVELOPESENDER;
+				mail(ERROREMAIL, "Error with VCL pages (problem adding shib affil)", $msg, '', $mailParams);
+				print "<html><head></head><body>\n";
+				print "<h2>Error encountered</h2>\n";
+				print "You have attempted to log in to VCL using a Shibboleth<br>\n";
+				print "Identity Provider that VCL has not been configured to<br>\n";
+				print "work with. VCL administrators have been notified of the<br>\n";
+				print "problem.<br>\n";
+				print "</body></html>\n";
+				dbDisconnect();
+				exit;
+			}
+		}
+		else
+			$newaffilname = $affilname;
+		$query = "INSERT INTO affiliation "
+				 .        "(name, "
+				 .        "shibname, "
+				 .        "shibonly) "
+				 . "VALUES "
+				 .        "('$newaffilname', "
+				 .        "'" . vcl_mysql_escape_string($affil) . "', "
+				 .        "1)";
+		doQuery($query, 101, 'vcl', 1);
+		unset($row);
+		$row = array('name' => $newaffilname, 'shibonly' => 1);
+	}
+	$affil = $row['name'];
+	$affilid = getAffiliationID($affil);
+
+	# create VCL userid
+	$userid = "$username@$affil";
+
+	if($row['shibonly']) {
+		$userdata = updateShibUser($userid);
+		if(array_key_exists('SHIB_AFFILIATION', $_SERVER))
+			$groups = $_SERVER['SHIB_AFFILIATION'];
+		else
+			$groups = array('shibaffil' => $shibaffil);
+		updateShibGroups($userdata['id'], $groups);
+		$usernid = $userdata['id'];
+	}
+	else {
+		$usernid = getUserlistID($userid, 1);
+		# NCSU specific
+		if(is_null($userid) && $affil == 'NCSU') {
+			$tmp = updateLDAPUser('NCSU LDAP', $username);
+			$usernid = $tmp['id'];
+		}
+		/*if($affil == 'NCSU') {
+			if(array_key_exists('SHIB_AFFILIATION', $_SERVER))
+				$groups = $_SERVER['SHIB_AFFILIATION'];
+			else
+				$groups = array('shibaffil' => $shibaffil);
+			updateShibGroups($usernid, $groups);
+		}*/
+		# end NCSU specific
+		if(is_null($usernid)) {
+			$tmp = updateShibUser($userid);
+			$usernid = $tmp['id'];
+			# call this so that user groups get correctly populated
+			updateUserData($usernid, "numeric", $affilid);
+		}
+	}
+
+	addLoginLog($userid, 'shibboleth', $affilid, 1);
+
+	if($affil == 'UNCG') {
+		$gid = getUserGroupID('All UNCG Users', $affilid);
+		$query = "INSERT IGNORE INTO usergroupmembers "
+				 . "(userid, usergroupid) "
+				 . "VALUES ($usernid, $gid)";
+		doQuery($query, 307);
+	}
+
+	if(array_key_exists('SHIB_LOGOUTURL', $_SERVER))
+		$logouturl = $_SERVER['SHIB_LOGOUTURL'];
+	else
+		$logouturl = '';
+
+	# save data to shibauth table
+	$shibdata = array('Shib-Application-ID' => $_SERVER['Shib-Application-ID'],
+							'Shib-Identity-Provider' => $_SERVER['Shib-Identity-Provider'],
+							#'Shib-AuthnContext-Dec' => $_SERVER['Shib-AuthnContext-Decl'],
+							'SHIB_LOGOUTURL' => $logouturl,
+							'SHIB_EPPN' => $_SERVER['SHIB_EPPN'],
+							#'SHIB_UNAFFILIATION' => $_SERVER['SHIB_UNAFFILIATION'],
+							'SHIB_AFFILIATION' => $_SERVER['SHIB_AFFILIATION'],
+	);
+	$serdata = vcl_mysql_escape_string(serialize($shibdata));
+	$query = "SELECT id "
+			 . "FROM shibauth "
+			 . "WHERE sessid = '{$_SERVER['Shib-Session-ID']}'";
+	$qh = doQuery($query, 101);
+	if($row = mysqli_fetch_assoc($qh)) {
+		$shibauthid = $row['id'];
+	}
+	else {
+		$ts = strtotime($_SERVER['Shib-Authentication-Instant']);
+		$ts = unixToDatetime($ts);
+		$query = "INSERT INTO shibauth "
+				 .        "(userid, " 
+				 .        "ts, "
+				 .        "sessid, "
+				 .        "data) "
+				 . "VALUES "
+				 .        "($usernid, "
+				 .        "'$ts', "
+				 .        "'{$_SERVER['Shib-Session-ID']}', "
+				 .        "'$serdata')";
+		doQuery($query, 101);
+		$qh = doQuery("SELECT LAST_INSERT_ID()", 101);
+		if(! $row = mysqli_fetch_row($qh)) {
+			# todo
+		}
+		$shibauthid = $row[0];
+	}
+
+	# get cookie data
+	$cookie = getAuthCookieData($userid, 'shibboleth', 600, $shibauthid);
+	# set cookie
+	if(version_compare(PHP_VERSION, "5.2", ">=") == true)
+		#setcookie("VCLAUTH", "{$cookie['data']}", $cookie['ts'], "/", COOKIEDOMAIN, 1, 1);
+		setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN, 0, 1);
+	else
+		#setcookie("VCLAUTH", "{$cookie['data']}", $cookie['ts'], "/", COOKIEDOMAIN, 1);
+		setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN);
+
+	# TODO do something to set VCLSKIN cookie based on affiliation
+
+	return $userid;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn unauthShib($mode)
+///
+/// \param $mode - headers or content
+//
+/// \brief for headers, simply returns; for content, prints information that
+/// user has been logged out and an iframe to log user out of Shibboleth if
+/// SHIB_LOGOUTURL was provided; VCLAUTH cookie is cleared elsewhere
+///
+////////////////////////////////////////////////////////////////////////////////
+function unauthShib($mode) {
+	global $user;
+	if($mode == 'headers')
+		return;
+
+	print "<h2>Logout</h2>\n";
+	print "You are now logged out of VCL and other Shibboleth authenticated web sites.<br><br>\n";
+	print "<a href=\"" . BASEURL . SCRIPT . "?mode=selectauth\">Return to Login</a><br><br><br>\n";
+	print "<iframe src=\"https://{$_SERVER['SERVER_NAME']}/Shibboleth.sso/Logout\" class=hidden>\n";
+	print "</iframe>\n";
+	if(array_key_exists('SHIB_LOGOUTURL', $_SERVER)) {
+	  	print "<iframe src=\"{$_SERVER['SHIB_LOGOUTURL']}\" class=hidden>\n";
+		print "</iframe>\n";
+	}
+	$shibdata = getShibauthDataByUser($user['id']);
+	if(array_key_exists('Shib-Identity-Provider', $shibdata) &&
+		! empty($shibdata['Shib-Identity-Provider'])) {
+		$tmp = explode('/', $shibdata['Shib-Identity-Provider']);
+		$idp = "{$tmp[0]}//{$tmp[2]}";
+		print "<iframe src=\"$idp/idp/logout.jsp\" class=hidden>\n";
+		print "</iframe>\n";
+	}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn getShibauthDataByUser($userid)
+///
+/// \param $userid - numeric id of a user
+///
+/// \return NULL if id not found in table or array of data with these keys:\n
+/// \b userid - id of user that data belongs to\n
+/// \b ts - datetime of when authdata was created\n
+/// \b sessid - shibboleth session id\n
+/// \b Shib-Application-ID - ??\n
+/// \b Shib-Identity-Provider - ??\n
+/// \b Shib-AuthnContext-Dec - ??\n
+/// \b Shib-logouturl - idp's logout url\n
+/// \b eppn - edu person principal name for user\n
+/// \b unscoped-affiliation - shibboleth unscoped affiliation\n
+/// \b affiliation - shibboleth scoped affiliation
+///
+/// \brief gets entry from shibauth table
+///
+////////////////////////////////////////////////////////////////////////////////
+function getShibauthDataByUser($userid) {
+	$query = "SELECT id, "
+	       .        "userid, "
+	       .        "ts, "
+	       .        "sessid, "
+	       .        "data "
+	       . "FROM shibauth "
+	       . "WHERE userid = $userid AND "
+	       .       "ts > DATE_SUB(NOW(), INTERVAL 12 HOUR) "
+	       . "ORDER BY ts DESC "
+	       . "LIMIT 1";
+	$qh = doQuery($query, 101);
+	if($row = mysqli_fetch_assoc($qh)) {
+		$data = unserialize($row['data']);
+		unset($row['data']);
+		$data2 = array_merge($row, $data);
+		return $data2;
+	}
+	return NULL;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 ///
 /// \fn updateShibUser($userid)
@@ -45,35 +325,40 @@
 		return NULL;
 
 	$displast = '';
-	if(array_key_exists('displayName', $_SERVER) &&
-	   ! empty($_SERVER['displayName'])) {
-		# split displayName into first and last names
-		if(preg_match('/,/', $_SERVER['displayName'])) {
-			$names = explode(',', $_SERVER['displayName']);
+
+	$displayname = getShibVar('displayName');
+	$givenname = getShibVar('givenName');
+	$sn = getShibVar('sn');
+	$mail = getShibVar('mail');
+
+	if($displayname != '') {
+		# split displayname into first and last names
+		if(preg_match('/,/', $displayname)) {
+			$names = explode(',', $displayname);
 			$user['firstname'] = preg_replace('/^\s+/', '', $names[1]);
 			$user['firstname'] = preg_replace('/\s+$/', '', $user['firstname']);
 			$displast = preg_replace('/^\s+/', '', $names[0]);
 			$displast = preg_replace('/\s+$/', '', $displast);
 		}
 		else {
-			$names = explode(' ', $_SERVER['displayName']);
+			$names = explode(' ', $displayname);
 			$displast = array_pop($names);
 			$user['firstname'] = array_shift($names);
 		}
 	}
-	elseif(array_key_exists('givenName', $_SERVER) &&
-	   ! empty($_SERVER['givenName']))
-		$user['firstname'] = $_SERVER['givenName'];
+	elseif($givenname != '')
+		$user['firstname'] = $givenname;
 	else
 		$user['firstname'] = '';
 
-	if(array_key_exists('sn', $_SERVER) &&
-	   ! empty($_SERVER['sn']))
-		$user["lastname"] = $_SERVER['sn'];
+	if($sn != '')
+		$user["lastname"] = $sn;
 	else
 		$user['lastname'] = $displast;
-	if(array_key_exists('mail', $_SERVER))
-		$user["email"] = $_SERVER['mail'];
+
+	if($mail != '')
+		$user["email"] = $mail;
+
 	$user['unityid'] = $userid;
 	$user['affilid'] = $affilid;
 
@@ -188,7 +473,12 @@
 		# get id for the group's affiliation
 		$query = "SELECT id FROM affiliation WHERE shibname = '$shibaffil'";
 		$qh = doQuery($query, 101);
-		$row = mysqli_fetch_assoc($qh);
+		if(! ($row = mysqli_fetch_assoc($qh))) {
+			$query = "SELECT id FROM affiliation WHERE shibname LIKE '%.$shibaffil'";
+			$qh = doQuery($query, 101);
+			if(! ($row = mysqli_fetch_assoc($qh)))
+				continue;
+		}
 		$affilid = $row['id'];
 		# prepend shib- and escape it for mysql
 		$grp = vcl_mysql_escape_string("shib-" . $name);
@@ -244,4 +534,24 @@
 		return NULL;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn getShibVar($key)
+///
+/// \param $key - shib variable to check for
+///
+/// \return value of shib variable or empty string if not found
+///
+/// \brief checks for various forms of $key in $_SERVER
+///
+////////////////////////////////////////////////////////////////////////////////
+function getShibVar($key) {
+	$key2 = "SHIB_" . strtoupper($key);
+	$val = '';
+	if(isset($_SERVER[$key]) && ! empty($_SERVER[$key]))
+		return $_SERVER[$key];
+	elseif(isset($_SERVER[$key2]) && ! empty($_SERVER[$key2]))
+		return $_SERVER[$key2];
+}
+
 ?>
diff --git a/web/.ht-inc/conf-default.php b/web/.ht-inc/conf-default.php
index e64ea50..50f204b 100644
--- a/web/.ht-inc/conf-default.php
+++ b/web/.ht-inc/conf-default.php
@@ -61,6 +61,9 @@
 	$host = substr($host, 0, strpos($host, ':'));
 }
 
+define("SSLOFFLOAD", 0); // set this to 1 to use external load balancer to manage SSL termination
+                         // set the BASEURL and HOMEURL paths to also be plain HTTP
+                         // The VCL application will not force HTTPS urls as HTTPS is enforced at the load balancer
 define("BASEURL", "https://{$_SERVER['HTTP_HOST']}/vcl");   // no trailing slash - all of the URL except /index.php
 define("SCRIPT", "/index.php");                 // this should only be "/index.php" unless you rename index.php to something else
 define("HOMEURL", "https://{$_SERVER['HTTP_HOST']}/vcl/"); // url to go to when someone clicks HOME or Logout
@@ -135,7 +138,7 @@
 	                            "affiliationid" => 1,
 	                            "help" => "Only use Local Account if there are no other options"),
 	/*"Shibboleth (UNC Federation)" => array("type" => "redirect",
-	                     "URL" => "https://federation.northcarolina.edu/wayf/wayf_framed.php?fed=FED_SHIB_UNC_DEV&version=dropdown&entityID=https%3A%2F%2Fvcl.ncsu.edu%2Fsp%2Fshibboleth&return=http%3A%2F%2Fvcl.ncsu.edu%2FShibboleth.sso%2FDS%3FSAMLDS%3D1%26target%3Dhttp%3A%2F%2Fvcl.ncsu.edu%2Fscheduling%2Fshibauth%2F",
+	                     "URL" => "https://federation.northcarolina.edu/wayf/wayf_framed.php?fed=FED_SHIB_UNC_DEV&version=dropdown&entityID=https%3A%2F%2Fvcl.ncsu.edu%2Fsp%2Fshibboleth&return=http%3A%2F%2Fvcl.ncsu.edu%2FShibboleth.sso%2FDS%3FSAMLDS%3D1%26target%3Dhttp%3A%2F%2Fvcl.ncsu.edu%2Fscheduling%2F/",
 	                     "affiliationid" => 0, // this should always be 0 for Shibboleth authentication
 	                     "help" => "Use Shibboleth (UNC Federation) if you are from a University in the UNC system and do not see another method specifically for your university"),*/
 	/*"EXAMPLE1 LDAP" => array("type" => "ldap",
diff --git a/web/.ht-inc/siteconfig.php b/web/.ht-inc/siteconfig.php
index a8f5d39..27d6e0f 100644
--- a/web/.ht-inc/siteconfig.php
+++ b/web/.ht-inc/siteconfig.php
@@ -3134,6 +3134,15 @@
 
 			if($keyparts[0] == 'adminmessage')
 				$keyparts[2] = 'Global';
+			foreach(array('message', 'subject', 'short_message') as $type) {
+				if(! isset($item[$type]))
+					continue;
+				$test = strip_tags($item[$type]);
+				if($test != $item[$type]) {
+					$item['DBmanagedHTML'] = 1;
+					$item[$type] = '';
+				}
+			}
 			$this->units[$k][$keyparts[2]] = $item;
 		}
 		uasort($this->basekeys, "sortKeepIndex");
diff --git a/web/.ht-inc/utils.php b/web/.ht-inc/utils.php
index 1550297..b10627a 100644
--- a/web/.ht-inc/utils.php
+++ b/web/.ht-inc/utils.php
@@ -170,11 +170,17 @@
 		if(! is_null($userid))
 			$authed = 1;
 	}
-	elseif(preg_match('/_shibsession/', join(',', array_keys($_COOKIE)))) {
-		# redirect to shibauth directory
-		header('Location: ' . BASEURL . "/shibauth/");
-		dbDisconnect();
-		exit;
+	else {
+		global $authFuncs;
+		foreach($authFuncs as $type) {
+			if($type['test']()) {
+				$userid = $type['auth']();
+				if(! is_null($userid)) {
+					$authed = 1;
+					break;
+				}
+			}
+		}
 	}
 	# end auth check
 
@@ -13108,7 +13114,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 function sendHeaders() {
 	global $mode, $user, $authed, $oldmode, $actionFunction;
-	global $shibauthed;
+	global $shibauthed, $authFuncs;
 	if(! $authed && $mode == "auth") {
 		header("Location: " . BASEURL . SCRIPT . "?mode=selectauth");
 		dbDisconnect();
@@ -13116,78 +13122,22 @@
 	}
 	switch($mode) {
 		case 'logout':
-			if($shibauthed) {
-				$shibdata = getShibauthData($shibauthed);
-				// TODO make shib-logouturl comparison caseless
-				if(array_key_exists('Shib-logouturl', $shibdata) &&
-				   ! empty($shibdata['Shib-logouturl'])) {
-					dbDisconnect();
-					header("Location: {$shibdata['Shib-logouturl']}");
-					exit;
-				}
-			}
-		case 'shiblogout':
-			setcookie("ITECSAUTH", "", time() - 10, "/", COOKIEDOMAIN);
-			setcookie("VCLAUTH", "", time() - 10, "/", COOKIEDOMAIN);
-			if($shibauthed) {
-				$msg = '';
-				$shibdata = getShibauthData($shibauthed);
-				# find and clear shib cookies
-				/*foreach(array_keys($_COOKIE) as $key) {
-					if(preg_match('/^_shibsession[_0-9a-fA-F]+$/', $key))
-						setcookie($key, "", time() - 10, "/", $_SERVER['SERVER_NAME']);
-					elseif(preg_match('/^_shibstate_/', $key))
-						setcookie($key, "", time() - 10, "/", $_SERVER['SERVER_NAME']);
-				}*/
-				doQuery("DELETE FROM shibauth WHERE id = $shibauthed", 101);
+			$authtype = getAuthTypeFromAuthCookie();
+			if(is_null($authtype)) {
 				stopSession();
 				dbDisconnect();
-				if(array_key_exists('Shib-logouturl', $shibdata) &&
-				   ! empty($shibdata['Shib-logouturl'])) {
-					print "<html>\n";
-					print "   <head>\n";
-					print "      <style type=\"text/css\">\n";
-					print "         .red {\n";
-					print "            color: red;\n";
-					print "         }\n";
-					print "         body{\n";
-					print "            margin:0px; color: red;\n";
-					print "         }\n";
-					print "      </style>\n";
-					print "   </head>\n";
-					print "   <body>\n";
-					print "      <span class=red>Done.</span>&nbsp;&nbsp;&nbsp;<a target=\"_top\" href=\"" . BASEURL . "/\">Return to VCL</a>\n";
-					print "   </body>\n";
-					print "</html>\n";
-				}
-				else {
-					print "<html>\n";
-					print "<head>\n";
-					print "<META HTTP-EQUIV=REFRESH CONTENT=\"5;url=" . BASEURL . "\">\n";
-					print "<style type=\"text/css\">\n";
-					print "  .hidden {\n";
-					print "    display: none;\n";
-					print "  }\n";
-					print "</style>\n";
-					print "</head>\n";
-					print "<body>\n";
-					print "Logging out of VCL...";
-					print "<iframe src=\"https://{$_SERVER['SERVER_NAME']}/Shibboleth.sso/Logout\" class=hidden>\n";
-					print "</iframe>\n";
-					if(array_key_exists('Shib-Identity-Provider', $shibdata) &&
-					   ! empty($shibdata['Shib-Identity-Provider'])) {
-						$tmp = explode('/', $shibdata['Shib-Identity-Provider']);
-						$idp = "{$tmp[0]}//{$tmp[2]}";
-						print "<iframe src=\"$idp/idp/logout.jsp\" class=hidden>\n";
-						print "</iframe>\n";
-					}
-					print "</body>\n";
-					print "</html>\n";
-				}
+				header("Location: " . BASEURL . SCRIPT);
 				exit;
 			}
-			header("Location: " . HOMEURL);
+			$authFuncs[$authtype]['unauth']('headers');
+			setcookie("VCLAUTH", "", time() - 10, "/", COOKIEDOMAIN);
+			$authed = 0;
+			ob_start();
+			printHTMLHeader();
+			$authFuncs[$authtype]['unauth']('content');
+			printHTMLFooter();
 			stopSession();
+			ob_end_flush();
 			dbDisconnect();
 			exit;
 	}
diff --git a/web/index.php b/web/index.php
index 6ac26f6..0d059c9 100644
--- a/web/index.php
+++ b/web/index.php
@@ -20,9 +20,12 @@
 $VCLversion = '2.5';
 
 require_once(".ht-inc/conf.php");
-if(! isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") {
-	header("Location: " . BASEURL . "/");
-	exit;
+
+if (SSLOFFLOAD == 0) {
+    if(! isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") {
+        header("Location: " . BASEURL . "/");
+        exit;
+    }
 }
 
 $user = '';
diff --git a/web/js/requests.js b/web/js/requests.js
index 8cfe95f..4a28222 100644
--- a/web/js/requests.js
+++ b/web/js/requests.js
@@ -435,8 +435,7 @@
 		else {
 			var tmp = dojo.byId('deploystartday').value;
 			tmp = new Date(tmp * 1000);
-			var offset = tmp.getTimezoneOffset() * 60000;
-			var date = new Date(tmp.getTime() + offset);
+			var date = new Date(tmp.getTime());
 			var hour = parseInt(dojo.byId('deployhour').value);
 			var m = dojo.byId('deploymeridian').value;
 			if(m == 'pm' && hour < 12)
diff --git a/web/js/siteconfig.js b/web/js/siteconfig.js
index 072c01f..0be32b5 100644
--- a/web/js/siteconfig.js
+++ b/web/js/siteconfig.js
@@ -685,7 +685,22 @@
 	}
 	dojo.byId('messagesaffil').innerHTML = affiltype;
 	dijit.byId('messagessubject').set('value', item['subject']);
-	dijit.byId('messagesbody').set('value', item['message']);
+	if(('DBmanagedHTML' in item) && item['DBmanagedHTML'] == 1) {
+		dijit.byId('messagesbody').set('value', 'This message body contains HTML that is set directly in the database');
+		dijit.byId('messagesbody').set('disabled', true);
+		dijit.byId('messagessubject').set('disabled', true);
+		dijit.byId('messagesshortmsg').set('disabled', true);
+		dijit.byId('messagessavebtn').set('disabled', true);
+		dijit.byId('messagesdelbtn').set('disabled', true);
+	}
+	else {
+		dijit.byId('messagesbody').set('value', item['message']);
+		dijit.byId('messagesbody').set('disabled', false);
+		dijit.byId('messagessubject').set('disabled', false);
+		dijit.byId('messagesshortmsg').set('disabled', false);
+		dijit.byId('messagessavebtn').set('disabled', false);
+		dijit.byId('messagesdelbtn').set('disabled', false);
+	}
 	if('short_message' in item)
 		dijit.byId('messagesshortmsg').set('value', item['short_message']);
 	else
diff --git a/web/shibauth/index.php b/web/shibauth/index.php
index 64c33c5..c6ad42a 100644
--- a/web/shibauth/index.php
+++ b/web/shibauth/index.php
@@ -1,263 +1,4 @@
 <?php
-/*
-  Licensed to the Apache Software Foundation (ASF) under one or more
-  contributor license agreements.  See the NOTICE file distributed with
-  this work for additional information regarding copyright ownership.
-  The ASF licenses this file to You under the Apache License, Version 2.0
-  (the "License"); you may not use this file except in compliance with
-  the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-*/
-
-chdir("..");
-require_once('.ht-inc/conf.php');
-
-require_once('.ht-inc/utils.php');
-require_once('.ht-inc/errors.php');
-function getFooter() {}
-$noHTMLwrappers = array();
-
-dbConnect();
-
-header("Cache-Control: no-cache, must-revalidate");
-header("Expires: Sat, 1 Jan 2000 00:00:00 GMT");
-
-/*
-	# check for eppn; if there, see if it is a user we already have
-	if(array_key_exists('eppn', $_SERVER)) {
-		#$tmp = explode('@', $_SERVER['eppn']);
-		$tmp = explode(';', $_SERVER['eppn']);
-		$tmp = explode('@', $tmp[0]);
-		$query = "SELECT u.firstname, "
-				 .        "u.lastname "
-				 . "FROM user u, "
-				 .      "affiliation a "
-				 . "WHERE u.unityid = '{$tmp[0]}' AND "
-				 .       "a.shibname = '{$tmp[1]}' AND "
-				 .       "u.affiliationid = a.id";
-		$qh = doQuery($query, 101);
-		if($row = mysqli_fetch_assoc($qh)) {
-			$_SERVER['sn'] = $row['lastname'];
-			$_SERVER['givenName'] = $row['firstname'];
-		}
-		else {
-*/
-
-if(! array_key_exists('eppn', $_SERVER)) {
-	# check to see if any shib stuff in $_SERVER, if not redirect
-	$keys = array_keys($_SERVER);
-	$allkeys = '{' . implode('{', $keys);
-	if(! preg_match('/\{Shib-/', $allkeys)) {
-		# no shib data, clear _shibsession cookie
-		#print "$allkeys<br>\n";
-		foreach(array_keys($_COOKIE) as $key) {
-			if(preg_match('/^_shibsession[_0-9a-fA-F]+$/', $key))
-				setcookie($key, "", time() - 10, "/", $_SERVER['SERVER_NAME']);
-		}
-		# redirect to main select auth page
-		header("Location: " . BASEURL . SCRIPT . "?mode=selectauth");
-		dbDisconnect();
-		exit;
-	}
-	print "<h2>Error with Shibboleth authentication</h2>\n";
-	print "You have attempted to log in using Shibboleth from an<br>\n";
-	print "institution that does not allow VCL to see your<br><br>\n";
-	print "eduPersonPrincipalName.<br><br>\n";
-	print "You need to contact the administrator of your institution's<br>\n";
-	print "IdP to have eduPersonPrincipalName made available to VCL in<br>\n";
-	print "order to log in using Shibboleth.\n";
-
-	$msg = "Someone tried to log in to VCL using Shibboleth from an IdP "
-	     . "that does not release eppn to us.\n\n"
-	     . "The following data was in \$_SERVER:\n\n";
-	foreach($_SERVER as $key => $val)
-		$msg .= "$key => $val\n";
-	$mailParams = "-f" . ENVELOPESENDER;
-	mail(ERROREMAIL, "Error with VCL pages (eppn not provided)", $msg, '', $mailParams);
-	dbDisconnect();
-	exit;
-}
-
-// open keys
-$fp = fopen(".ht-inc/keys.pem", "r");
-$key = fread($fp, 8192);
-fclose($fp);
-$keys["private"] = openssl_pkey_get_private($key, $pemkey);
-if(! $keys['private'])
-	abort(6);
-$fp = fopen(".ht-inc/pubkey.pem", "r");
-$key = fread($fp, 8192);
-fclose($fp);
-$keys["public"] = openssl_pkey_get_public($key);
-if(! $keys['public'])
-	abort(7);
-
-# get VCL affiliation from shib affiliation
-$tmp = explode(';', $_SERVER['eppn']);
-$tmp = explode('@', $tmp[0]);
-$username = strtolower($tmp[0]);
-$tmp1 = vcl_mysql_escape_string(strtolower($tmp[1]));
-$query = "SELECT name, shibonly FROM affiliation WHERE shibname = '$tmp1'";
-$qh = doQuery($query, 101);
-# if shib affiliation not already in VCL, create affiliation
-if(! ($row = mysqli_fetch_assoc($qh))) {
-	$affil = strtolower($tmp[1]);
-	$tmp = explode('.', $affil);
-	array_pop($tmp);
-	$affilname = strtoupper(implode('', $tmp));
-	$affilname = preg_replace('/[^A-Z0-9]/', '', $affilname);
-	$query = "SELECT name, "
-	       .        "shibname "
-	       . "FROM affiliation "
-	       . "WHERE name LIKE '$affilname%' "
-	       . "ORDER BY name DESC "
-	       . "LIMIT 1";
-	$qh = doQuery($query, 101);
-	if($row = mysqli_fetch_assoc($qh)) {
-		if(preg_match("/$affilname([0-9]+)/", $row['name'], $matches)) {
-			$cnt = $matches[1];
-			$cnt++;
-			$newaffilname = $affilname . $cnt;
-		}
-		elseif($affilname != $row['name'] && $affil != $row['shibname']) {
-			$newaffilname = $affilname;
-		}
-		else {
-			$msg = "Someone tried to log in to VCL using Shibboleth from an IdP "
-			     . "affiliation that could not be automatically added.\n\n"
-			     . "eppn: {$_SERVER['eppn']}\n"
-			     . "givenName: {$_SERVER['givenName']}\n"
-			     . "sn: {$_SERVER['sn']}\n";
-			if(array_key_exists('mail', $_SERVER))
-				$msg .= "mail: {$_SERVER['mail']}\n\n";
-			$msg .="tried to add VCL affiliation name \"$affilname\" with "
-			     . "shibname \"$affil\"";
-			$mailParams = "-f" . ENVELOPESENDER;
-			mail(ERROREMAIL, "Error with VCL pages (problem adding shib affil)", $msg, '', $mailParams);
-			print "<html><head></head><body>\n";
-			print "<h2>Error encountered</h2>\n";
-			print "You have attempted to log in to VCL using a Shibboleth<br>\n";
-			print "Identity Provider that VCL has not been configured to<br>\n";
-			print "work with.  VCL administrators have been notified of the<br>\n";
-			print "problem.<br>\n";
-			print "</body></html>\n";
-			dbDisconnect();
-			exit;
-		}
-	}
-	else
-		$newaffilname = $affilname;
-	$query = "INSERT INTO affiliation "
-	       .        "(name, "
-	       .        "shibname, "
-	       .        "shibonly) "
-	       . "VALUES "
-	       .        "('$newaffilname', "
-	       .        "'" . vcl_mysql_escape_string($affil) . "', "
-	       .        "1)";
-	doQuery($query, 101, 'vcl', 1);
-	unset($row);
-	$row = array('name' => $newaffilname, 'shibonly' => 1);
-}
-$affil = $row['name'];
-# create VCL userid
-$userid = "$username@$affil";
-
-if($row['shibonly']) {
-	$userdata = updateShibUser($userid);
-	updateShibGroups($userdata['id'], $_SERVER['affiliation']);
-	$usernid = $userdata['id'];
-}
-else {
-	$usernid = getUserlistID($userid, 1);
-	if(is_null($usernid)) {
-		$tmp = updateShibUser($userid);
-		$usernid = $tmp['id'];
-	}
-}
-
-$affilid = getAffiliationID($affil);
-addLoginLog($userid, 'shibboleth', $affilid, 1);
-
-# uncomment the following and change EXAMPLE1 to match your needs to add all
-# users from a specific affiliation to a particular user group
-/*if($affil == 'EXAMPLE1') {
-	$gid = getUserGroupID('All EXAMPLE1 Users', $affilid);
-	$query = "INSERT IGNORE INTO usergroupmembers "
-	       . "(userid, usergroupid) "
-	       . "VALUES ($usernid, $gid)";
-	doQuery($query, 307);
-}*/
-
-if(array_key_exists('Shib-logouturl', $_SERVER))
-	$logouturl = $_SERVER['Shib-logouturl'];
-else
-	$logouturl = '';
-
-# save data to shibauth table
-$shibdata = array('Shib-Application-ID' => $_SERVER['Shib-Application-ID'],
-                  'Shib-Identity-Provider' => $_SERVER['Shib-Identity-Provider'],
-                  #'Shib-AuthnContext-Dec' => $_SERVER['Shib-AuthnContext-Decl'],
-                  'Shib-logouturl' => $logouturl,
-                  'eppn' => $_SERVER['eppn'],
-                  'unscoped-affiliation' => $_SERVER['unscoped-affiliation'],
-                  'affiliation' => $_SERVER['affiliation'],
-);
-$serdata = vcl_mysql_escape_string(serialize($shibdata));
-$query = "SELECT id "
-       . "FROM shibauth "
-       . "WHERE sessid = '{$_SERVER['Shib-Session-ID']}'";
-$qh = doQuery($query, 101);
-if($row = mysqli_fetch_assoc($qh)) {
-	$shibauthid = $row['id'];
-}
-else {
-	$ts = strtotime($_SERVER['Shib-Authentication-Instant']);
-	$ts = unixToDatetime($ts);
-	$query = "INSERT INTO shibauth "
-	       .        "(userid, " 
-	       .        "ts, "
-	       .        "sessid, "
-	       .        "data) "
-	       . "VALUES "
-	       .        "($usernid, "
-	       .        "'$ts', "
-	       .        "'{$_SERVER['Shib-Session-ID']}', "
-	       .        "'$serdata')";
-	doQuery($query, 101);
-	$qh = doQuery("SELECT LAST_INSERT_ID() FROM shibauth", 101);
-	if(! $row = mysqli_fetch_row($qh)) {
-		# todo
-	}
-	$shibauthid = $row[0];
-}
-
-# get cookie data
-$cookie = getAuthCookieData($userid, 600, $shibauthid);
-# set cookie
-if(version_compare(PHP_VERSION, "5.2", ">=") == true)
-	#setcookie("VCLAUTH", "{$cookie['data']}", $cookie['ts'], "/", COOKIEDOMAIN, 1, 1);
-	setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN, 0, 1);
-else
-	#setcookie("VCLAUTH", "{$cookie['data']}", $cookie['ts'], "/", COOKIEDOMAIN, 1);
-	setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN);
-# set skin cookie based on affiliation
-switch($affil) {
-	case 'Example1':
-	case 'EXAMPLE2':
-		$skin = strtoupper($affil);
-		setcookie("VCLSKIN", $skin, (time() + 2678400), "/", COOKIEDOMAIN);
-		break;
-	default:
-		setcookie("VCLSKIN", "default", (time() + 2678400), "/", COOKIEDOMAIN);
-}
-header("Location: " . BASEURL . "/");
-dbDisconnect();
+@require_once('../.ht-inc/conf.php');
+header("Location: " . BASEURL . SCRIPT);
 ?>
diff --git a/web/testsetup.php b/web/testsetup.php
index 8f384d2..609f0ab 100644
--- a/web/testsetup.php
+++ b/web/testsetup.php
@@ -222,8 +222,10 @@
 	else {
 		if(substr_compare(BASEURL, 'https:', 0, 6, true) == 0)
 			pass("BASEURL correctly set to use https");
+		elseif(SSLOFFLOAD == 1 && substr_compare(BASEURL, 'http:', 0, 5, true) == 0)
+		        pass("BASEURL set to use http as SSL is offloaded to load balancer");
 		else
-			fail("BASEURL is not set to use https. https is required.");
+			fail("BASEURL is not set to use https and SSL offloading is not enabled. https is required.");
 	}
 	print "</ul>\n";