Merge branch 'apache:develop' into perl-5.26
diff --git a/web/.ht-inc/addomain.php b/web/.ht-inc/addomain.php
index f86ebf7..ec1e253 100644
--- a/web/.ht-inc/addomain.php
+++ b/web/.ht-inc/addomain.php
@@ -513,13 +513,13 @@
 		$errormsg = array();
 
 		$return['rscid'] = getContinuationVar('rscid', 0);
-		$return["name"] = processInputVar("name", ARG_STRING);
+		$return["name"] = processInputVar("name", ARG_STRING, '');
 		$return["owner"] = processInputVar("owner", ARG_STRING, "{$user["unityid"]}@{$user['affiliation']}");
-		$return["domaindnsname"] = processInputVar("domaindnsname", ARG_STRING);
-		$return["username"] = processInputVar("username", ARG_STRING);
-		$return["password"] = $_POST['password'];
-		$return["password2"] = $_POST['password2'];
-		$return["dnsservers"] = processInputVar("dnsservers", ARG_STRING);
+		$return["domaindnsname"] = processInputVar("domaindnsname", ARG_STRING, '');
+		$return["username"] = processInputVar("username", ARG_STRING, '');
+		$return["password"] = $_POST['password'] ? $_POST['password'] : '';
+		$return["password2"] = $_POST['password2'] ? $_POST['password2'] : '';
+		$return["dnsservers"] = processInputVar("dnsservers", ARG_STRING, '');
 		$return["usedbhostnames"] = processInputVar('usedbhostnames', ARG_NUMERIC, 0);
 
 		if(! preg_match("/^([A-Za-z0-9-!@#$%^&\*\(\)_=\+\[\]{}\\\|:;,\.\/\?~` ]){2,30}$/", $return['name'])) {
diff --git a/web/.ht-inc/authentication.php b/web/.ht-inc/authentication.php
index cb72534..f908fb8 100644
--- a/web/.ht-inc/authentication.php
+++ b/web/.ht-inc/authentication.php
@@ -78,10 +78,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 function readAuthCookie() {
 	global $keys, $AUTHERROR, $shibauthed;
-	if(get_magic_quotes_gpc())
-		$cookie = stripslashes($_COOKIE["VCLAUTH"]);
-	else
-		$cookie = $_COOKIE["VCLAUTH"];
+	$cookie = $_COOKIE["VCLAUTH"];
 	$cookie = base64_decode($cookie);
 	if(! openssl_public_decrypt($cookie, $tmp, $keys['public'])) {
 		# cookie is invalid; clear it and return NULL so will get redirected to log in again
@@ -157,10 +154,7 @@
 	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 = $_COOKIE["VCLAUTH"];
 	$cookie = base64_decode($cookie);
 	if(! openssl_public_decrypt($cookie, $tmp, $keys['public'])) {
 		$AUTHERROR["code"] = 3;
@@ -192,7 +186,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 function selectAuth() {
 	global $HTMLheader, $printedHTMLheader, $authMechs, $skin;
-	$authtype = getContinuationVar('authtype', processInputVar("authtype", ARG_STRING));
+	$authtype = getContinuationVar('authtype', processInputVar("authtype", ARG_STRING, ''));
 	if($authtype == '' && array_key_exists('VCLAUTHSEL', $_COOKIE))
 		$authtype = $_COOKIE['VCLAUTHSEL'];
 	if(array_key_exists('clearselection', $_GET) && $_GET['clearselection'] == 1) {
@@ -285,7 +279,7 @@
 function printLoginPage($servertimeout=0) {
 	global $authMechs, $skin, $user;
 	$user['id'] = 0;
-	$authtype = getContinuationVar("authtype", processInputVar("authtype", ARG_STRING));
+	$authtype = getContinuationVar("authtype", processInputVar("authtype", ARG_STRING, ''));
 	if($authtype == '' && array_key_exists('VCLAUTHSEL', $_COOKIE))
 		$authtype = $_COOKIE['VCLAUTHSEL'];
 	if(isset($_GET['userid']))
@@ -298,8 +292,6 @@
 		dbDisconnect();
 		exit;
 	}
-	if(get_magic_quotes_gpc())
-		$userid = stripslashes($userid);
 	$userid = htmlspecialchars($userid);
 	$extrafailedmsg = '';
 	if($servertimeout)
@@ -386,7 +378,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 function submitLogin() {
 	global $authMechs;
-	$authtype = getContinuationVar("authtype", processInputVar('authtype', ARG_STRING));
+	$authtype = getContinuationVar("authtype", processInputVar('authtype', ARG_STRING, ''));
 	if(! array_key_exists($authtype, $authMechs)) {
 		// FIXME - hackerish
 		dbDisconnect();
@@ -400,10 +392,6 @@
 		selectAuth();
 		return;
 	}
-	if(get_magic_quotes_gpc()) {
-		$userid = stripslashes($userid);
-		$passwd = stripslashes($passwd);
-	}
 	if($authMechs[$authtype]['type'] == 'ldap')
 		ldapLogin($authtype, $userid, $passwd);
 	elseif($authMechs[$authtype]['type'] == 'local')
@@ -631,6 +619,8 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function testGeneralAffiliation(&$login, &$affilid) {
+	if(is_null($login))
+		return 0;
 	if(preg_match('/^([^@]+)@([^@\.]*)$/', $login, $matches)) {
 		$login = $matches[1];
 		$affilid = getAffiliationID($matches[2]);
diff --git a/web/.ht-inc/authmethods/itecsauth.php b/web/.ht-inc/authmethods/itecsauth.php
index a271450..74b6e0e 100644
--- a/web/.ht-inc/authmethods/itecsauth.php
+++ b/web/.ht-inc/authmethods/itecsauth.php
@@ -345,6 +345,8 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function testITECSAffiliation(&$login, &$affilid) {
+	if(is_null($login))
+		return 0;
 	if(preg_match('/^([^@]*@[^@]*\.[^@]*)@ITECS$/', $login, $matches) ||
 	   preg_match('/^([^@]*@[^@]*\.[^@]*)$/', $login, $matches)) {
 		$login = $matches[1];
diff --git a/web/.ht-inc/authmethods/ldapauth.php b/web/.ht-inc/authmethods/ldapauth.php
index 3848ebe..57a0631 100644
--- a/web/.ht-inc/authmethods/ldapauth.php
+++ b/web/.ht-inc/authmethods/ldapauth.php
@@ -416,7 +416,8 @@
 		$qh = doQuery($query, 101);
 		if(! $user = mysqli_fetch_assoc($qh))
 			return NULL;
-		$user['sshpublickeys'] = htmlspecialchars($user['sshpublickeys']);
+		if(! empty($user['sshpublickeys']))
+			$user['sshpublickeys'] = htmlspecialchars($user['sshpublickeys']);
 	}
 
 	// TODO handle generic updating of groups
diff --git a/web/.ht-inc/authmethods/shibauth.php b/web/.ht-inc/authmethods/shibauth.php
index 947035e..e585fca 100644
--- a/web/.ht-inc/authmethods/shibauth.php
+++ b/web/.ht-inc/authmethods/shibauth.php
@@ -134,19 +134,6 @@
 	}
 	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'];
@@ -157,13 +144,13 @@
 
 	addLoginLog($userid, 'shibboleth', $affilid, 1);
 
-	if($affil == 'UNCG') {
-		$gid = getUserGroupID('All UNCG Users', $affilid);
+	/*if($affil == 'EXAMPLE1') {
+		$gid = getUserGroupID('All EXAMPLE1 Users', $affilid);
 		$query = "INSERT IGNORE INTO usergroupmembers "
 				 . "(userid, usergroupid) "
 				 . "VALUES ($usernid, $gid)";
-		doQuery($query, 307);
-	}
+		doQuery($query);
+	}*/
 
 	if(array_key_exists('SHIB_LOGOUTURL', $_SERVER))
 		$logouturl = $_SERVER['SHIB_LOGOUTURL'];
@@ -177,8 +164,9 @@
 							'SHIB_LOGOUTURL' => $logouturl,
 							'SHIB_EPPN' => $_SERVER['SHIB_EPPN'],
 							#'SHIB_UNAFFILIATION' => $_SERVER['SHIB_UNAFFILIATION'],
-							'SHIB_AFFILIATION' => $_SERVER['SHIB_AFFILIATION'],
 	);
+	if(isset($_SERVER['SHIB_AFFILIATION']))
+		$shibdata['SHIB_AFFILIATION'] = $_SERVER['SHIB_AFFILIATION'];
 	$serdata = vcl_mysql_escape_string(serialize($shibdata));
 	$query = "SELECT id "
 			 . "FROM shibauth "
@@ -249,7 +237,7 @@
 		print "</iframe>\n";
 	}
 	$shibdata = getShibauthDataByUser($user['id']);
-	if(array_key_exists('Shib-Identity-Provider', $shibdata) &&
+	if(isset($shibdata['Shib-Identity-Provider']) &&
 		! empty($shibdata['Shib-Identity-Provider'])) {
 		$tmp = explode('/', $shibdata['Shib-Identity-Provider']);
 		$idp = "{$tmp[0]}//{$tmp[2]}";
diff --git a/web/.ht-inc/blockallocations.php b/web/.ht-inc/blockallocations.php
index ed0fffa..8e7b3ca 100644
--- a/web/.ht-inc/blockallocations.php
+++ b/web/.ht-inc/blockallocations.php
@@ -49,7 +49,7 @@
 		print "<h2>" . i("Manage Block Allocations") . "</h2>\n";
 		$cont = addContinuationsEntry('viewBlockAllocatedMachines');
 		print "<a href=\"" . BASEURL . SCRIPT . "?continuation=$cont\">";
-		print i("View Block Allocated Machines") . "</a>\n";
+		print i("View Block Allocated Machines") . "</a><br><br>\n";
 		print "<div id=\"blocklist\">\n";
 		print getCurrentBlockHTML();
 		print "</div>\n";
@@ -1180,6 +1180,7 @@
 	$query .=      "b.status = 'accepted' "
 	       . "ORDER BY b.name";
 	$allblockids = array();
+	$blocks = array();
 	$qh = doQuery($query, 101);
 	while($row = mysqli_fetch_assoc($qh)) {
 		if($row['group'] == '') {
@@ -1218,9 +1219,6 @@
 			$blocks[$row['id']]['nextstartactive'] = 0;
 		}
 	}
-	if(empty($blocks)) {
-		return "There are currently no block allocations.<br>\n";
-	}
 	foreach($blocks as $id => $request) {
 		if($request['available'] == 'weekly') {
 			$query = "SELECT DATE_FORMAT(start, '%m/%d/%Y') AS swdate, "
@@ -1325,60 +1323,64 @@
 	}
 	$rt = '';
 	$rt .= "<input type=\"hidden\" id=\"timezone\" value=\"" . date('T') . "\">\n";
-	$rt .= "<table summary=\"lists current block allocations\">\n";
-	$rt .= "  <TR align=center>\n";
-	$rt .= "    <TD colspan=3></TD>\n";
-	$rt .= "    <TH>" . i("Name") . "</TH>\n";
-	$rt .= "    <TH>" . i("Environment") . "</TH>\n";
-	$rt .= "    <TH>" . i("Reserved<br>Machines") . "</TH>\n";
-	$rt .= "    <TH>" . i("Reserved<br>For") . "</TH>\n";
-	$rt .= "    <TH>" . i("Repeating") . "</TH>\n";
-	$rt .= "    <TH>" . i("Next Start Time") . "</TH>\n";
-	$rt .= "  </TR>\n";
-	foreach($blocks as $block) {
+	if(empty($blocks))
+		$rt .= "There are currently no block allocations.\n";
+	else {
+		$rt .= "<table summary=\"lists current block allocations\">\n";
 		$rt .= "  <TR align=center>\n";
-		$rt .= "    <TD>\n";
-		$rt .= "      <button dojoType=\"dijit.form.Button\" type=\"button\">\n";
-		$rt .= i(      "Edit") . "\n";
-		$rt .= "        <script type=\"dojo/method\" event=\"onClick\">\n";
-		$cont = addContinuationsEntry('editBlockAllocation', array('blockid' => $block['id']));
-		$rt .= "          location.href = '" . BASEURL . SCRIPT . "?continuation=$cont';\n";
-		$rt .= "        </script>\n";
-		$rt .= "      </button>\n";
-		$rt .= "    </TD>\n";
-		$rt .= "    <TD>\n";
-		$rt .= "      <button dojoType=\"dijit.form.Button\" type=\"button\">\n";
-		$rt .= i(      "Delete") . "\n";
-		$rt .= "        <script type=\"dojo/method\" event=\"onClick\">\n";
-		$cont = addContinuationsEntry('AJdeleteBlockAllocationConfirm', $block, SECINDAY);
-		$rt .= "          deleteBlockConfirm('$cont');\n";
-		$rt .= "        </script>\n";
-		$rt .= "      </button>\n";
-		$rt .= "    </TD>\n";
-		$rt .= "    <TD>\n";
-		$rt .= "      <button dojoType=\"dijit.form.Button\" type=\"button\">\n";
-		$rt .= i(      "View Times") . "\n";
-		$rt .= "        <script type=\"dojo/method\" event=\"onClick\">\n";
-		$cont = addContinuationsEntry('AJviewBlockAllocationTimes', array('blockid' => $block['id']), SECINDAY);
-		$rt .= "          viewBlockTimes('$cont');\n";
-		$rt .= "        </script>\n";
-		$rt .= "      </button>\n";
-		$rt .= "    </TD>\n";
-		$rt .= "    <TD>{$block['blockname']}</TD>\n";
-		$rt .= "    <TD>{$block['image']}</TD>\n";
-		$rt .= "    <TD><a href=\"javascript:void(0)\" onclick=\"viewBlockUsage({$block['id']});\">{$block['machinecnt']}</a></TD>\n";
-		$rt .= "    <TD>{$block['group']}</TD>\n";
-		$rt .= "    <TD>" . i($block['available']) . "</TD>\n";
-		if($block['nextstartactive']) {
-			$cont = addContinuationsEntry('viewBlockStatus', array('id' => $block['id']));
-			$rt .= "    <TD><a href=\"" . BASEURL . SCRIPT . "?continuation=$cont\">";
-			$rt .= "{$block['nextstart']}</a></TD>\n";
-		}
-		else
-			$rt .= "    <TD>{$block['nextstart']}</TD>\n";
+		$rt .= "    <TD colspan=3></TD>\n";
+		$rt .= "    <TH>" . i("Name") . "</TH>\n";
+		$rt .= "    <TH>" . i("Environment") . "</TH>\n";
+		$rt .= "    <TH>" . i("Reserved<br>Machines") . "</TH>\n";
+		$rt .= "    <TH>" . i("Reserved<br>For") . "</TH>\n";
+		$rt .= "    <TH>" . i("Repeating") . "</TH>\n";
+		$rt .= "    <TH>" . i("Next Start Time") . "</TH>\n";
 		$rt .= "  </TR>\n";
+		foreach($blocks as $block) {
+			$rt .= "  <TR align=center>\n";
+			$rt .= "    <TD>\n";
+			$rt .= "      <button dojoType=\"dijit.form.Button\" type=\"button\">\n";
+			$rt .= i(      "Edit") . "\n";
+			$rt .= "        <script type=\"dojo/method\" event=\"onClick\">\n";
+			$cont = addContinuationsEntry('editBlockAllocation', array('blockid' => $block['id']));
+			$rt .= "          location.href = '" . BASEURL . SCRIPT . "?continuation=$cont';\n";
+			$rt .= "        </script>\n";
+			$rt .= "      </button>\n";
+			$rt .= "    </TD>\n";
+			$rt .= "    <TD>\n";
+			$rt .= "      <button dojoType=\"dijit.form.Button\" type=\"button\">\n";
+			$rt .= i(      "Delete") . "\n";
+			$rt .= "        <script type=\"dojo/method\" event=\"onClick\">\n";
+			$cont = addContinuationsEntry('AJdeleteBlockAllocationConfirm', $block, SECINDAY);
+			$rt .= "          deleteBlockConfirm('$cont');\n";
+			$rt .= "        </script>\n";
+			$rt .= "      </button>\n";
+			$rt .= "    </TD>\n";
+			$rt .= "    <TD>\n";
+			$rt .= "      <button dojoType=\"dijit.form.Button\" type=\"button\">\n";
+			$rt .= i(      "View Times") . "\n";
+			$rt .= "        <script type=\"dojo/method\" event=\"onClick\">\n";
+			$cont = addContinuationsEntry('AJviewBlockAllocationTimes', array('blockid' => $block['id']), SECINDAY);
+			$rt .= "          viewBlockTimes('$cont');\n";
+			$rt .= "        </script>\n";
+			$rt .= "      </button>\n";
+			$rt .= "    </TD>\n";
+			$rt .= "    <TD>{$block['blockname']}</TD>\n";
+			$rt .= "    <TD>{$block['image']}</TD>\n";
+			$rt .= "    <TD><a href=\"javascript:void(0)\" onclick=\"viewBlockUsage({$block['id']});\">{$block['machinecnt']}</a></TD>\n";
+			$rt .= "    <TD>{$block['group']}</TD>\n";
+			$rt .= "    <TD>" . i($block['available']) . "</TD>\n";
+			if($block['nextstartactive']) {
+				$cont = addContinuationsEntry('viewBlockStatus', array('id' => $block['id']));
+				$rt .= "    <TD><a href=\"" . BASEURL . SCRIPT . "?continuation=$cont\">";
+				$rt .= "{$block['nextstart']}</a></TD>\n";
+			}
+			else
+				$rt .= "    <TD>{$block['nextstart']}</TD>\n";
+			$rt .= "  </TR>\n";
+		}
+		$rt .= "</table>\n";
 	}
-	$rt .= "</table>\n";
 	if($listonly)
 		return $rt;
 
@@ -1824,6 +1826,7 @@
 	$d = '';
 	$groups = getUserGroups(0, $user['affiliationid']);
 	while($row = mysqli_fetch_assoc($qh)) {
+		unset($start);
 		if($row['repeating'] == 'weekly') {
 			$query2 = "SELECT DATE_FORMAT(start, '%m/%d/%y') AS swdate, "
 			        .        "DATE_FORMAT(end, '%m/%d/%y')AS ewdate, " 
@@ -1836,6 +1839,7 @@
 			if(! $row2 = mysqli_fetch_assoc($qh2))
 				abort(101);
 			$row = array_merge($row, $row2);
+			$start = $row['swdate'];
 			$wdays = array();
 			for($i = 0; $i < 7; $i++) {
 				if($row['days'] & (1 << $i))
@@ -1881,6 +1885,7 @@
 			if(! $row2 = mysqli_fetch_assoc($qh2))
 				abort(101);
 			$row = array_merge($row, $row2);
+			$start = $row['smdate'];
 			$query2 = "SELECT starthour, "
 			        .        "startminute, "
 			        .        "startmeridian, "
@@ -1917,6 +1922,8 @@
 			        . "ORDER BY start";
 			$qh2 = doQuery($query2, 101);
 			while($row2 = mysqli_fetch_assoc($qh2)) {
+				if(! isset($start))
+					$start = $row2['date'];
 				if($row2['date'] == '00/00/00')
 					$row['date'][$row2['order']] = '';
 				else
@@ -1975,7 +1982,7 @@
 			$d .= "<td>{$row['unityid']}</td>\n";
 		$d .= "<td>{$row['numMachines']}</td>\n";
 		$d .= "<td>" . i($row['repeating']) . "</td>\n";
-		$d .= "<td>{$row2['start']}</td>\n";
+		$d .= "<td>$start</td>\n";
 		$d .= "<td>{$row['lastdate']}</td>\n";
 		$d .= "  </tr>\n";
 	}
@@ -2486,8 +2493,6 @@
 		$err = 1;
 	}
 	if($validemail) {
-		if(get_magic_quotes_gpc())
-			$emailtext = stripslashes($emailtext);
 		if(! $err && preg_match('/[<>|]/', $emailtext)) {
 			$errmsg = i("<>\'s and pipes (|) are not allowed in the email text.");
 			$err = 1;
@@ -2707,8 +2712,6 @@
 		$errmsg = i("Please include a reason for rejecting the block allocation in the email.");
 		$err = 1;
 	}
-	if(get_magic_quotes_gpc())
-		$emailtext = stripslashes($emailtext);
 	if(! $err && preg_match('/[<>|]/', $emailtext)) {
 		if($validemail)
 			$errmsg = i("<>\'s and pipes (|) are not allowed in the email text.");
@@ -2860,10 +2863,8 @@
 		print i("The selected Block Allocation no longer exists.");
 		return;
 	}
-	$startunix = datetimeToUnix($data['start']);
-	$endunix = datetimeToUnix($data['end']);
-	$start = strftime('%x %l:%M %P %Z', $startunix);
-	$end = strftime('%x %l:%M %P %Z', $endunix);
+	$start = prettyDatetime($data['start'], 1, 0, 0, 1);
+	$end = prettyDatetime($data['end'], 1, 0, 0, 1);
 	print "<div id=statusdiv>\n";
 	print "<table class=blockStatusData summary=\"lists attributes of block allocation\">\n";
 	print "  <tr>\n";
@@ -3267,8 +3268,6 @@
 	}
 	if($method == 'request') {
 		$return['comments'] = processInputVar('comments', ARG_STRING);
-		if(get_magic_quotes_gpc())
-			$return['comments'] = stripslashes($return['comments']);
 		if(! $err && preg_match('/[<>]/', $return['comments'])) {
 			$errmsg = i("<>\'s are not allowed in the comments.");
 			$err = 1;
diff --git a/web/.ht-inc/computer.php b/web/.ht-inc/computer.php
index d1f6ca6..56b9944 100644
--- a/web/.ht-inc/computer.php
+++ b/web/.ht-inc/computer.php
@@ -1540,7 +1540,7 @@
 			if($olddata['stateid'] == 10 && $data['stateid'] == 10) {
 				$testnotes = $olddata['notes'];
 				# check for notes being changed
-				if(strpos($testnotes, '@') === true) {
+				if(! is_null($testnotes) && strpos($testnotes, '@') === true) {
 					$tmp = explode('@', $olddata['notes']);
 					$testnotes = $tmp[1];
 				}
@@ -1695,23 +1695,23 @@
 		$return = array('error' => 0);
 
 		$return['rscid'] = getContinuationVar('rscid', 0);
-		$return['name'] = processInputVar('name', ARG_STRING);
+		$return['name'] = processInputVar('name', ARG_STRING, '');
 		$return['startnum'] = processInputVar('startnum', ARG_NUMERIC);
 		$return['endnum'] = processInputVar('endnum', ARG_NUMERIC);
 		$return['owner'] = processInputVar('owner', ARG_STRING, "{$user['unityid']}@{$user['affiliation']}");
-		$return['type'] = processInputVar('type', ARG_STRING);
-		$return['IPaddress'] = processInputVar('ipaddress', ARG_STRING);
-		$return['privateIPaddress'] = processInputVar('privateipaddress', ARG_STRING);
-		$return['eth0macaddress'] = processInputVar('privatemac', ARG_STRING);
-		$return['eth1macaddress'] = processInputVar('publicmac', ARG_STRING);
-		$return['startpubipaddress'] = processInputVar('startpubipaddress', ARG_STRING);
-		$return['endpubipaddress'] = processInputVar('endpubipaddress', ARG_STRING);
-		$return['startprivipaddress'] = processInputVar('startprivipaddress', ARG_STRING);
-		$return['endprivipaddress'] = processInputVar('endprivipaddress', ARG_STRING);
-		$return['startmac'] = processInputVar('startmac', ARG_STRING);
+		$return['type'] = processInputVar('type', ARG_STRING, '');
+		$return['IPaddress'] = processInputVar('ipaddress', ARG_STRING, '');
+		$return['privateIPaddress'] = processInputVar('privateipaddress', ARG_STRING, '');
+		$return['eth0macaddress'] = processInputVar('privatemac', ARG_STRING, '');
+		$return['eth1macaddress'] = processInputVar('publicmac', ARG_STRING, '');
+		$return['startpubipaddress'] = processInputVar('startpubipaddress', ARG_STRING, '');
+		$return['endpubipaddress'] = processInputVar('endpubipaddress', ARG_STRING, '');
+		$return['startprivipaddress'] = processInputVar('startprivipaddress', ARG_STRING, '');
+		$return['endprivipaddress'] = processInputVar('endprivipaddress', ARG_STRING, '');
+		$return['startmac'] = processInputVar('startmac', ARG_STRING, '');
 		$return['provisioningid'] = processInputVar('provisioningid', ARG_NUMERIC);
 		$return['stateid'] = processInputVar('stateid', ARG_NUMERIC);
-		$return['notes'] = processInputVar('notes', ARG_STRING);
+		$return['notes'] = processInputVar('notes', ARG_STRING, '');
 		$return['vmprofileid'] = processInputVar('vmprofileid', ARG_NUMERIC);
 		$return['platformid'] = processInputVar('platformid', ARG_NUMERIC);
 		$return['scheduleid'] = processInputVar('scheduleid', ARG_NUMERIC);
@@ -1723,9 +1723,9 @@
 		$return['natenabled'] = processInputVar('natenabled', ARG_NUMERIC);
 		$return['nathostid'] = processInputVar('nathostid', ARG_NUMERIC);
 		$return['nathostenabled'] = processInputVar('nathostenabled', ARG_NUMERIC);
-		$return['natpublicIPaddress'] = processInputVar('natpublicipaddress', ARG_STRING);
-		$return['natinternalIPaddress'] = processInputVar('natinternalipaddress', ARG_STRING);
-		$return['location'] = processInputVar('location', ARG_STRING);
+		$return['natpublicIPaddress'] = processInputVar('natpublicipaddress', ARG_STRING, '');
+		$return['natinternalIPaddress'] = processInputVar('natinternalipaddress', ARG_STRING, '');
+		$return['location'] = processInputVar('location', ARG_STRING, '');
 		$addmode = processInputVar('addmode', ARG_STRING);
 
 		if(! is_null($addmode) && $addmode != 'single' && $addmode != 'multiple') {
@@ -3581,8 +3581,6 @@
 		elseif($newstateid == 10 || $newstateid == 23) {
 			if($newstateid == 10) {
 				$notes = processInputVar('notes', ARG_STRING);
-				if(get_magic_quotes_gpc())
-					$notes = stripslashes($notes);
 				$notes = vcl_mysql_escape_string($notes);
 				$notes = $user["unityid"] . " " . unixToDatetime(time()) . "@"
 				       . $notes;
@@ -4841,6 +4839,45 @@
 			$msg .= "<hr>";
 			$data[] = array('name' => $row['hostname'], 'msg' => $msg);
 		}
+		$query = "SELECT UNIX_TIMESTAMP(bt.start) AS start, "
+		       .        "UNIX_TIMESTAMP(bt.end) AS end, "
+		       .        "i.prettyname AS image, "
+		       .        "ir.revision, "
+		       .        "c.hostname AS hostname, "
+		       .        "br.name AS blockname, "
+		       .        "ug.name AS usergroup, "
+		       .        "CONCAT(u.unityid, '@', a.name) AS owner, "
+		       .        "bc.reloadrequestid AS requestid, "
+		       .        "vh.hostname AS vmhost "
+		       . "FROM blockComputers bc "
+		       . "JOIN blockTimes bt ON (bc.blockTimeid = bt.id) "
+		       . "JOIN blockRequest br ON (bt.blockRequestid = br.id) "
+		       . "JOIN computer c ON (bc.computerid = c.id) "
+		       . "JOIN image i ON (br.imageid = i.id) "
+		       . "JOIN imagerevision ir ON (ir.imageid = br.imageid AND ir.production = 1) "
+		       . "JOIN usergroup ug ON (ug.id = br.groupid) "
+		       . "JOIN user u ON (br.ownerid = u.id) "
+		       . "JOIN affiliation a ON (u.affiliationid = a.id) "
+		       . "LEFT JOIN vmhost v ON (c.vmhostid = v.id) "
+		       . "LEFT JOIN computer vh ON (v.computerid = vh.id) "
+		       . "WHERE bc.computerid IN ($complist) AND "
+		       .       "br.status = 'accepted'";
+		$qh = doQuery($query);
+		while($row = mysqli_fetch_assoc($qh)) {
+			$msg = "<strong>{$row['hostname']} - Block Request</strong><br>";
+			$msg .= "Block Request: {$row['blockname']}<br>";
+			$msg .= "Image: {$row['image']}<br>";
+			$msg .= "Revision: {$row['revision']}<br>";
+			$msg .= "Start: " . prettyDatetime($row['start'], 1) . "<br>";
+			$msg .= "End: " . prettyDatetime($row['end'], 1) . "<br>";
+			$msg .= "User Group: {$row['usergroup']}<br>";
+			$msg .= "Owner: {$row['owner']}<br>";
+			if(! is_null($row['vmhost']))
+				$msg .= "VM Host: {$row['vmhost']}<br>";
+			$msg .= "Reload Request ID: {$row['requestid']}<br>";
+			$msg .= "<hr>";
+			$data[] = array('name' => $row['hostname'], 'msg' => $msg);
+		}
 		uasort($data, 'sortKeepIndex');
 		$msg = '';
 		if(count($data) != 0) {
diff --git a/web/.ht-inc/dashboard.php b/web/.ht-inc/dashboard.php
index 9018c20..82a1673 100644
--- a/web/.ht-inc/dashboard.php
+++ b/web/.ht-inc/dashboard.php
@@ -28,6 +28,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function dashboard() {
+	$affilid = getDashboardAffilID();
 	print "<h2>VCL Dashboard</h2>\n";
 	print "(Times and dates on this page are in " . date('T') . ")<br><br>\n";
 	if(checkUserHasPerm('View Dashboard (global)')) {
@@ -46,6 +47,7 @@
 	print addWidget('topimages', 'Top 5 Images in Use', '(Reservations &lt; 24 hours long)');
 	print addWidget('toplongimages', 'Top 5 Long Term Images in Use', '(Reservations &gt; 24 hours long)');
 	print addWidget('toppastimages', 'Top 5 Images From Past Day', '(Reservations with a start<br>time within past 24 hours)');
+	print addWidget('toppast6moimages', 'Top 5 Images From Past 6 Months', '(Reservations with a start<br>time within past 6 months)', 1);
 	print addWidget('topfailedcomputers', 'Top Recent Computer Failures', '(Failed in the last 5 days)');
 	print addWidget('blockallocation', 'Block Allocation Status');
 	print "</div>\n"; # dashleft
@@ -65,6 +67,24 @@
 		print addWidget('failedimaging', 'Failed Imaging Reservations', '(Imaging Reservations in the maintenance state)');
 	$cont = addContinuationsEntry('AJupdateDashboard', array('val' => 0), 90, 1, 0);
 	print "<input type=\"hidden\" id=\"updatecont\" value=\"$cont\">\n";
+	$cont = addContinuationsEntry('AJdashboardDetail', array('affilid' => $affilid));
+	print "<input type=\"hidden\" id=\"detailcont\" value=\"$cont\">\n";
+
+	# detail dialog
+	$h = '';
+	$h .= "<div dojoType=dijit.Dialog\n";
+	$h .= "      id=\"detaildialog\"\n";
+	$h .= "      duration=250\n";
+	$h .= "      autofocus=false\n";
+	$h .= "      draggable=true>\n";
+	$h .= "<h3><div id=\"detailtitle\"></div></h3>\n";
+	$h .= "<div id=\"detailcontent\"></div>\n";
+	$h .= "<input type=\"hidden\" id=\"submitcont\">\n";
+	$h .= "<div style=\"text-align: center;\"><br>\n";
+	$h .= dijitButton('canceldetailbtn', 'Close', 'cancelDetail();', 0);
+	$h .= "</div>\n"; # btn div
+	$h .= "</div>\n"; # detaildialog
+	print $h;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -80,7 +100,8 @@
 	$data['status'] = getStatusData();
 	$data['topimages'] = getTopImageData();
 	$data['toplongimages'] = getTopLongImageData();
-	$data['toppastimages'] = getTopPastImageData();
+	$data['toppastimages'] = getTopPastImageData(5, 'DAY', 1);
+	$data['toppast6moimages'] = getTopPastImageData(5, 'MONTH', 6);
 	$data['topfailed'] = getTopFailedData();
 	$data['topfailedcomputers'] = getTopFailedComputersData();
 	$data['reschart'] = getActiveResChartData();
@@ -93,21 +114,48 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
+/// \fn AJdashboardDetail()
+///
+/// \param id - id of widget type
+///
+/// \brief gets detailed information for specified type
+///
+////////////////////////////////////////////////////////////////////////////////
+function AJdashboardDetail() {
+	$id = processInputVar('id', ARG_STRING);
+	switch($id) {
+	case 'toppast6moimages':
+		$data = array('divid' => 'detailcontent');
+		$data['title'] = "Top Images From Past 6 Months";
+		$data['result'] = getTopPastImageData(30, 'MONTH', 6);
+		break;
+	default:
+	}
+	sendJSON($data);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
 /// \fn addWidget($id, $title, extra)
 ///
 /// \param $id - dom id for div
 /// \param $title - title to print at top of box
 /// \param $extra (optional, default='') - extra text to be placed below title,
 ///        but above data
+/// \param $clicktitle - (optional, default=0) boolean for title being clickable
+///        to display more details
 ///
 /// \return div element for a section of data
 ///
 /// \brief creates HTML for a box of data to be displayed
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function addWidget($id, $title, $extra='') {
+function addWidget($id, $title, $extra='', $clicktitle=0) {
 	$txt  = "<div class=\"dashwidget\">\n";
-	$txt .= "<h3>$title</h3>\n";
+	if($clicktitle)
+		$txt .= "<h3><a onclick=\"showdetail('$id');\">$title</a></h3>\n";
+	else
+		$txt .= "<h3>$title</h3>\n";
 	if($extra != '')
 		$txt .= "<div class=\"extra\">$extra</div>\n";
 	$txt .= "<div id=\"$id\"></div>\n";
@@ -343,7 +391,11 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
-/// \fn getTopPastImageData()
+/// \fn getTopPastImageData($imagecnt, $intervalunit, $intervalnum)
+///
+/// \param $imagecnt - number of images to return
+/// \param $intervalunit - units of interval for DATE_SUB in query
+/// \param $intervalnum - how many interval units to use in query
 ///
 /// \return array of data with these keys:\n
 /// \b prettyname - name of image\n
@@ -352,7 +404,7 @@
 /// \brief gets data about top reserved images over past day
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function getTopPastImageData() {
+function getTopPastImageData($imagecnt, $intervalunit, $intervalnum) {
 	$affilid = getDashboardAffilID();
 	$reloadid = getUserlistID('vclreload@Local');
 	if($affilid == 0) {
@@ -363,10 +415,10 @@
 		       . "WHERE l.imageid = i.id AND "
 		       .       "l.wasavailable = 1 AND "
 		       .       "l.userid != $reloadid AND "
-		       .       "l.start > DATE_SUB(NOW(), INTERVAL 1 DAY) "
+		       .       "l.start > DATE_SUB(NOW(), INTERVAL $intervalnum $intervalunit) "
 		       . "GROUP BY l.imageid "
 		       . "ORDER BY count DESC "
-		       . "LIMIT 5";
+		       . "LIMIT $imagecnt";
 	}
 	else {
 		$query = "SELECT COUNT(l.imageid) AS count, "
@@ -379,10 +431,10 @@
 		       .       "l.imageid = i.id AND "
 		       .       "l.wasavailable = 1 AND "
 		       .       "l.userid != $reloadid AND "
-		       .       "l.start > DATE_SUB(NOW(), INTERVAL 1 DAY) "
+		       .       "l.start > DATE_SUB(NOW(), INTERVAL $intervalnum $intervalunit) "
 		       . "GROUP BY l.imageid "
 		       . "ORDER BY count DESC "
-		       . "LIMIT 5";
+		       . "LIMIT $imagecnt";
 	}
 	$data = array();
 	$qh = doQuery($query, 101);
@@ -918,7 +970,7 @@
 	global $user;
 	if(! checkUserHasPerm('View Dashboard (global)'))
 		return $user['affiliationid'];
-	$affilid = processInputVar('affilid', ARG_NUMERIC);
+	$affilid = getContinuationVar('affilid', processInputVar('affilid', ARG_NUMERIC, 0));
 	$affils = getAffiliations();
 	if($affilid != 0 && ! array_key_exists($affilid, $affils))
 		return 0;
diff --git a/web/.ht-inc/groups.php b/web/.ht-inc/groups.php
index 306395e..91a0fdb 100644
--- a/web/.ht-inc/groups.php
+++ b/web/.ht-inc/groups.php
@@ -311,7 +311,7 @@
 	elseif(checkUserHasPerm('Manage Federated User Groups (affiliation only)'))
 		$showfederatedaffil = 1;
 	$items = array();
-	$lengths = getReservationLengths(201600);
+	$lengths = getReservationLengths(302400);
 	foreach($affilusergroups as $id => $group) {
 		if($group['name'] == 'None' || preg_match('/^\s*None/', $group['name']))
 			continue;
@@ -784,7 +784,7 @@
 			print "  <TR>\n";
 			print "    <TH align=right>Initial Max Time:</TH>\n";
 			print "    <TD>";
-			$lengths = getReservationLengths(201600);
+			$lengths = getReservationLengths(302400);
 			if(! array_key_exists($data['initialmax'], $lengths))
 				$data['initialmax'] = getReservationLengthCeiling($data['initialmax']);
 			printSelectInput("initialmax", $lengths, $data['initialmax']);
@@ -993,7 +993,7 @@
 	$return["type"] = getContinuationVar("type");
 	$return["custom"] = getContinuationVar("custom", 1);
 	$return["courseroll"] = getContinuationVar("courseroll", 0);
-	$return["name"] = getContinuationVar('name', processInputVar("name", ARG_STRING));
+	$return["name"] = getContinuationVar('name', processInputVar("name", ARG_STRING, ''));
 	$return["affiliationid"] = getContinuationVar('affiliationid', processInputVar("affiliationid", ARG_NUMERIC, $user['affiliationid']));
 	$return["resourcetypeid"] = getContinuationVar('resourcetypeid', processInputVar("resourcetypeid", ARG_NUMERIC));
 	$return["owner"] = getContinuationVar('owner', processInputVar("owner", ARG_STRING));
@@ -1004,10 +1004,12 @@
 	$return["totalmax"] = getContinuationVar('totalmax', processInputVar("totalmax", ARG_NUMERIC));
 	$return["maxextend"] = getContinuationVar('maxextend', processInputVar("maxextend", ARG_NUMERIC));
 	$return["overlap"] = getContinuationVar('overlap', processInputVar("overlap", ARG_NUMERIC, 0));
-	$return['editgroupids'] = getContinuationVar('editgroupids');
+	$return['editgroupids'] = getContinuationVar('editgroupids', '');
 	$editgroupids = explode(',', $return['editgroupids']);
-	$return['ownergroupids'] = getContinuationVar('ownergroupids');
-	$ownergroupids = explode(',', $return['ownergroupids']);
+	if($return['type'] == 'resource') {
+		$return['ownergroupids'] = getContinuationVar('ownergroupids');
+		$ownergroupids = explode(',', $return['ownergroupids']);
+	}
 	$groupwasnone = getContinuationVar('groupwasnone');
 	$editname = getContinuationVar('editname', 1);
 
@@ -1488,7 +1490,7 @@
 			print "    <TD>" . $usergroups[$data["editgroupid"]]["name"] . "</TD>\n";
 			print "  </TR>\n";
 		}
-		$lengths = getReservationLengths(201600);
+		$lengths = getReservationLengths(302400);
 		print "  <TR>\n";
 		print "    <TH align=right>Initial Max Time:</TH>\n";
 		print "    <TD>{$lengths[$data["initialmax"]]}</TD>\n";
diff --git a/web/.ht-inc/help.php b/web/.ht-inc/help.php
index b038d97..b19e3ab 100644
--- a/web/.ht-inc/help.php
+++ b/web/.ht-inc/help.php
@@ -39,15 +39,10 @@
 function printHelpForm() {
 	global $user, $submitErr, $noHTMLwrappers;
 	if($submitErr) {
-		$name = processInputVar("name", ARG_STRING);
-		$email = processInputVar("email", ARG_STRING);
+		$name = processInputVar("name", ARG_STRING, '');
+		$email = processInputVar("email", ARG_STRING, '');
 		$summary = processInputVar("summary", ARG_STRING);
 		$text = processInputVar("comments", ARG_STRING);
-		if(get_magic_quotes_gpc()) {
-			$name = stripslashes($name);
-			$summary = stripslashes($summary);
-			$text = stripslashes($text);
-		}
 		$name = preg_replace(array('/"/', '/>/'), array('&quot;', '&gt;'), $name);
 		$summary = preg_replace(array('/"/', '/>/'), array('&quot;', '&gt;'), $summary);
 	}
@@ -126,16 +121,14 @@
 	$text = processInputVar("comments", ARG_STRING);
 
 	$testname = $name;
-	if(get_magic_quotes_gpc())
-		$testname = stripslashes($name);
-	if(! preg_match('/^([-A-Za-z \']{1,} [-A-Za-z \']{2,})*$/', $testname)) {
+	if(is_null($testname) || ! preg_match('/^([-A-Za-z \']{1,} [-A-Za-z \']{2,})*$/', $testname)) {
 		$submitErr |= NAMEERR;
 		$submitErrMsg[NAMEERR] = "Name can only contain letters, spaces, apostrophes ('), and dashes (-). Both first and last name must be specified.";
 	}
-	if(! preg_match('/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/i',
-	   $email)) {
+	if(is_null($email) || ! filter_var($email, FILTER_VALIDATE_EMAIL)) {
 		$submitErr |= EMAILERR;
-		$submitErrMsg[EMAILERR] = "Invalid email address, please correct";
+		$submitErrMsg[EMAILERR] = "Invalid email address specified";
+		$_POST['email'] = $user['email'];
 	}
 	if(empty($summary)) {
 		$submitErr |= SUMMARYERR;
@@ -176,8 +169,6 @@
 	}
 
 	$from = $user["email"];
-	if(get_magic_quotes_gpc())
-		$text = stripslashes($text);
 	$message = "Problem report submitted from VCL web form:\n\n"
 	         . "User: " . $user["unityid"] . "\n"
 	         . "Name: " . $testname . "\n"
@@ -225,7 +216,7 @@
 		$resultlen = strlen(i('Fail'));
 	$qh = doQuery($query);
 	$logins = array();
-	while($row = mysql_fetch_assoc($qh)) {
+	while($row = mysqli_fetch_assoc($qh)) {
 		$tmp = prettyDatetime($row['timestamp'], 1, 1);
 		$row['timestamp'] = str_replace('&nbsp;', ' ', $tmp);
 		if($row['passfail'])
@@ -268,8 +259,6 @@
 	if(! $indrupal)
 		print "<H2>VCL Help</H2>\n";
 	$mailParams = "-f" . ENVELOPESENDER;
-	if(get_magic_quotes_gpc())
-		$summary = stripslashes($summary);
 	$helpemail = getHelpEmail($user['affiliationid']);
 	if(! mail($helpemail, "$summary", $message,
 	   "From: $from\r\nReply-To: $email\r\n", $mailParams)){
@@ -302,7 +291,7 @@
 		$field = 'name';
 	$query = "SELECT helpaddress FROM affiliation WHERE $field = '$affil'";
 	$qh = doQuery($query);
-	if($row = mysql_fetch_assoc($qh))
+	if($row = mysqli_fetch_assoc($qh))
 		if($row['helpaddress'] != '')
 			return $row['helpaddress'];
 	return HELPEMAIL;
diff --git a/web/.ht-inc/image.php b/web/.ht-inc/image.php
index 329cec8..8bfe440 100644
--- a/web/.ht-inc/image.php
+++ b/web/.ht-inc/image.php
@@ -25,6 +25,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 class Image extends Resource {
+	var $imagerevisionid;
 	/////////////////////////////////////////////////////////////////////////////
 	///
 	/// \fn __construct()
@@ -394,11 +395,11 @@
 		# RAM
 		$extra = array('smallDelta' => 256, 'largeDelta' => 1024);
 		$h .= labeledFormItem('ram', i('Required RAM') . ' (MB)', 'spinner', '{min:512, max:8388607}',
-		                      1, 1024, '', '', $extra);
+		                      1, 4096, '', '', $extra);
 		# cores
 		$extra = array('smallDelta' => 1, 'largeDelta' => 2);
 		$h .= labeledFormItem('cores', i('Required Cores'), 'spinner', '{min:1, max:255}',
-		                      1, 1, '', '', $extra);
+		                      1, 2, '', '', $extra);
 		# proc speed
 		$extra = array('smallDelta' => 500, 'largeDelta' => 8000);
 		$h .= labeledFormItem('cpuspeed', i('Processor Speed'), 'spinner', '{min:500, max:8000}',
@@ -434,7 +435,7 @@
 		$h .= "</div>\n";
 		# Max reservation time
 		$tmp = array('0' => 'Default for User');
-		$lengths = $tmp + getReservationLengths(201600);
+		$lengths = $tmp + getReservationLengths(302400);
 		$h .= labeledFormItem('maxinitialtime', i('Max Reservation Duration'), 'select', $lengths);
 		# sysprep
 		if($add) {
@@ -1045,8 +1046,6 @@
 		elseif(! $autocaptured) {
 			$comments = processInputVar('comments', ARG_STRING, '');
 			$comments = htmlspecialchars($comments);
-			if(get_magic_quotes_gpc())
-				$comments = stripslashes($comments);
 		}
 
 		if(! $autocaptured)
@@ -1252,7 +1251,13 @@
 
 		# ad authentication
 		if($data['adauthenabled']) {
-			$esc_baseou = vcl_mysql_escape_string($data['baseou']);
+			if(is_null($data['baseou'])) {
+				$esc_baseou = 'NULL';
+			}
+			else {
+				$esc_baseou = vcl_mysql_escape_string($data['baseou']);
+				$esc_baseou = "'$esc_baseou'";
+			}
 			$query = "INSERT INTO imageaddomain "
 			       .        "(imageid, "
 			       .        "addomainid, "
@@ -1260,7 +1265,7 @@
 			       . "VALUES "
 			       .        "($imageid, "
 			       .        "{$data['addomainid']}, "
-			       .        "'$esc_baseou')";
+			       .        "$esc_baseou)";
 			doQuery($query);
 		}
 	
@@ -1534,7 +1539,7 @@
 			sendJSON($arr);
 			return;
 		}
-		$remids = processInputVar('imageids', ARG_STRING);
+		$remids = processInputVar('imageids', ARG_STRING, '');
 		$remids = explode(',', $remids);
 		foreach($remids as $id) {
 			if(! is_numeric($id)) {
@@ -1632,48 +1637,42 @@
 
 		$return = array('error' => 0);
 
-		$return["name"] = processInputVar("name", ARG_STRING);
+		$return["name"] = processInputVar("name", ARG_STRING, '');
 		$return["owner"] = processInputVar("owner", ARG_STRING, "{$user["unityid"]}@{$user['affiliation']}");
-		$return["ram"] = processInputVar("ram", ARG_NUMERIC, 512);
-		$return["cores"] = processInputVar("cores", ARG_NUMERIC);
-		$return["cpuspeed"] = processInputVar("cpuspeed", ARG_NUMERIC);
+		$return["ram"] = processInputVar("ram", ARG_NUMERIC, 4096);
+		$return["cores"] = processInputVar("cores", ARG_NUMERIC, 2);
+		$return["cpuspeed"] = processInputVar("cpuspeed", ARG_NUMERIC, 2000);
 		$return["networkspeed"] = (int)processInputVar("networkspeed", ARG_NUMERIC);
 		$return["concurrent"] = processInputVar("concurrent", ARG_NUMERIC, 0);
-		$return["reload"] = processInputVar("reload", ARG_NUMERIC); # not in add
+		$return["reload"] = processInputVar("reload", ARG_NUMERIC, 0); # not in add
 		$return["checkout"] = processInputVar("checkout", ARG_NUMERIC);
 		$return["checkuser"] = processInputVar("checkuser", ARG_NUMERIC);
 		$return["rootaccess"] = processInputVar("rootaccess", ARG_NUMERIC);
 		$return["sethostname"] = processInputVar("sethostname", ARG_NUMERIC);
 		$return["maxinitialtime"] = processInputVar("maxinitialtime", ARG_NUMERIC, 0);
 		$return["sysprep"] = processInputVar("sysprep", ARG_NUMERIC); # only in add
-		$return["connectmethodids"] = processInputVar("connectmethodids", ARG_STRING); # only in add
-		$return["adauthenabled"] = processInputVar("adauthenabled", ARG_NUMERIC);
+		$return["connectmethodids"] = processInputVar("connectmethodids", ARG_STRING, ''); # only in add
+		$return["adauthenabled"] = processInputVar("adauthenabled", ARG_NUMERIC, 0);
 		$return["addomainid"] = processInputVar("addomainid", ARG_NUMERIC);
-		$return["baseou"] = processInputVar("baseou", ARG_STRING);
+		$return["baseou"] = processInputVar("baseou", ARG_STRING, '');
 
 		$return['requestid'] = getContinuationVar('requestid'); # only in add
 		$return["imageid"] = getContinuationVar('imageid');
 		$return['baserevisionid'] = getContinuationVar('baserevisionid');
 
-		$return["desc"] = processInputVar("desc", ARG_STRING);
-		if(get_magic_quotes_gpc())
-			$return["desc"] = stripslashes($return['desc']);
+		$return["desc"] = processInputVar("desc", ARG_STRING, '');
 		$return['desc'] = preg_replace("/[\n\s]*$/", '', $return['desc']);
 		$return['desc'] = preg_replace("/\r/", '', $return['desc']);
 		$return['desc'] = htmlspecialchars($return['desc']);
 		$return['desc'] = preg_replace("/\n/", '<br>', $return['desc']);
 
-		$return["usage"] = processInputVar("usage", ARG_STRING);
-		if(get_magic_quotes_gpc())
-			$return["usage"] = stripslashes($return['usage']);
+		$return["usage"] = processInputVar("usage", ARG_STRING, '');
 		$return['usage'] = preg_replace("/[\n\s]*$/", '', $return['usage']);
 		$return['usage'] = preg_replace("/\r/", '', $return['usage']);
 		$return['usage'] = htmlspecialchars($return['usage']);
 		$return['usage'] = preg_replace("/\n/", '<br>', $return['usage']);
 
-		$return["comments"] = processInputVar("imgcomments", ARG_STRING);
-		if(get_magic_quotes_gpc())
-			$return["comments"] = stripslashes($return['comments']);
+		$return["comments"] = processInputVar("imgcomments", ARG_STRING, '');
 		$return['comments'] = preg_replace("/[\n\s]*$/", '', $return['comments']);
 		$return['comments'] = preg_replace("/\r/", '', $return['comments']);
 		$return['comments'] = htmlspecialchars($return['comments']);
@@ -1712,7 +1711,7 @@
 			$return['error'] = 1;
 			$errormsg[] = i("Cores must be between 0 and 255");
 		}
-		if($return["cpuspeed"] < 0 || $return["cpuspeed"] > 20000) {
+		if($return["cpuspeed"] < 1 || $return["cpuspeed"] > 20000) {
 			$return['error'] = 1;
 			$errormsg[] = i("Processor Speed must be between 0 and 20000");
 		}
@@ -1727,7 +1726,7 @@
 			$errormsg[] = i("Max concurrent usage must be between 0 and 255");
 		}
 		if($return['mode'] == 'edit' && 
-		   ($return["reload"] < 0 || $return["reload"] > 120)) {
+		   ($return["reload"] < 1 || $return["reload"] > 120)) {
 			$return['error'] = 1;
 			$errormsg[] = i("Estimated Reload Time must be between 0 and 120");
 		}
@@ -1735,23 +1734,27 @@
 			$return['error'] = 1;
 			$errormsg[] = i("Submitted ID is not valid");
 		}
-		if($return['checkout'] != 0 && $return['checkout'] != 1) {
+		if(is_null($return['checkout']) || 
+		   ($return['checkout'] != 0 && $return['checkout'] != 1)) {
 			$return['error'] = 1;
 			$errormsg[] = i("Available for Checkout must be Yes or No");
 		}
-		if($return['checkuser'] != 0 && $return['checkuser'] != 1) {
+		if(is_null($return['checkuser']) || 
+		   ($return['checkuser'] != 0 && $return['checkuser'] != 1)) {
 			$return['error'] = 1;
 			$errormsg[] = i("Check for Logged in User must be Yes or No");
 		}
-		if($return['rootaccess'] != 0 && $return['rootaccess'] != 1) {
+		if(is_null($return['rootaccess']) || 
+		   ($return['rootaccess'] != 0 && $return['rootaccess'] != 1)) {
 			$return['error'] = 1;
 			$errormsg[] = i("Users Have Administrative Access must be Yes or No");
 		}
-		if($return['sethostname'] != 0 && $return['sethostname'] != 1) {
+		if(is_null($return['sethostname']) || 
+		   ($return['sethostname'] != 0 && $return['sethostname'] != 1)) {
 			$return['error'] = 1;
 			$errormsg[] = i("Set Computer Hostname must be Yes or No");
 		}
-		if($return['maxinitialtime'] < 0 || $return['maxinitialtime'] > 201600) {
+		if($return['maxinitialtime'] < 0 || $return['maxinitialtime'] > 302400) {
 			$return['error'] = 1;
 			$errormsg[] = i("Invalid Max Reservation Duration selected");
 		}
@@ -2256,10 +2259,8 @@
 	function AJupdateRevisionComments() {
 		$imageid = getContinuationVar('imageid');
 		$revisionid = getContinuationVar('revisionid');
-		$comments = processInputVar('comments', ARG_STRING);
+		$comments = processInputVar('comments', ARG_STRING, '');
 		$comments = htmlspecialchars($comments);
-		if(get_magic_quotes_gpc())
-			$comments = stripslashes($comments);
 		$comments = vcl_mysql_escape_string($comments);
 		$query = "UPDATE imagerevision "
 		       . "SET comments = '$comments' "
@@ -2299,7 +2300,7 @@
 	function AJdeleteRevisions() {
 		$revids = getContinuationVar('revids');
 		$imageid = getContinuationVar('imageid');
-		$checkedids = processInputVar('checkedids', ARG_STRING);
+		$checkedids = processInputVar('checkedids', ARG_STRING, '');
 		$ids = explode(',', $checkedids);
 		if(empty($ids)) {
 			sendJSON(array());
diff --git a/web/.ht-inc/managementnode.php b/web/.ht-inc/managementnode.php
index dd49e2c..6fb9028 100644
--- a/web/.ht-inc/managementnode.php
+++ b/web/.ht-inc/managementnode.php
@@ -712,35 +712,30 @@
 		$return = array('error' => 0);
 
 		$return['rscid'] = getContinuationVar('rscid', 0);
-		$return['name'] = processInputVar('name', ARG_STRING);
+		$return['name'] = processInputVar('name', ARG_STRING, '');
 		$return['owner'] = processInputVar('owner', ARG_STRING, "{$user['unityid']}@{$user['affiliation']}");
-		$return['ipaddress'] = processInputVar('ipaddress', ARG_STRING);
-		$return['stateid'] = processInputVar('stateid', ARG_NUMERIC);
-		$return['sysadminemail'] = processInputVar('sysadminemail', ARG_STRING);
-		$return['sharedmailbox'] = processInputVar('sharedmailbox', ARG_STRING);
-		$return['installpath'] = processInputVar('installpath', ARG_STRING);
-		$return['timeservers'] = processInputVar('timeservers', ARG_STRING);
-		$return['keys'] = processInputVar('keys', ARG_STRING);
+		$return['ipaddress'] = processInputVar('ipaddress', ARG_STRING, '');
+		$return['stateid'] = processInputVar('stateid', ARG_NUMERIC, 0);
+		$return['sysadminemail'] = processInputVar('sysadminemail', ARG_STRING, '');
+		$return['sharedmailbox'] = processInputVar('sharedmailbox', ARG_STRING, '');
+		$return['installpath'] = processInputVar('installpath', ARG_STRING, '');
+		$return['timeservers'] = processInputVar('timeservers', ARG_STRING, '');
+		$return['keys'] = processInputVar('keys', ARG_STRING, '');
 		$return['sshport'] = processInputVar('sshport', ARG_NUMERIC);
 		$return['imagelibenable'] = processInputVar('imagelibenable', ARG_NUMERIC);
 		$return['imagelibgroupid'] = processInputVar('imagelibgroupid', ARG_NUMERIC);
-		$return['imagelibuser'] = processInputVar('imagelibuser', ARG_STRING);
-		$return['imagelibkey'] = processInputVar('imagelibkey', ARG_STRING);
-		$return['publicIPconfig'] = processInputVar('publicIPconfig', ARG_STRING);
-		$return['publicnetmask'] = processInputVar('publicnetmask', ARG_STRING);
-		$return['publicgateway'] = processInputVar('publicgateway', ARG_STRING);
-		$return['publicdnsserver'] = processInputVar('publicdnsserver', ARG_STRING);
+		$return['imagelibuser'] = processInputVar('imagelibuser', ARG_STRING, '');
+		$return['imagelibkey'] = processInputVar('imagelibkey', ARG_STRING, '');
+		$return['publicIPconfig'] = processInputVar('publicIPconfig', ARG_STRING, '');
+		$return['publicnetmask'] = processInputVar('publicnetmask', ARG_STRING, '');
+		$return['publicgateway'] = processInputVar('publicgateway', ARG_STRING, '');
+		$return['publicdnsserver'] = processInputVar('publicdnsserver', ARG_STRING, '');
 		$return['checkininterval'] = processInputVar('checkininterval', ARG_NUMERIC);
-		$return['availablenetworks'] = processInputVar('availablenetworks', ARG_STRING);
-		$return['federatedauth'] = processInputVar('federatedauth', ARG_STRING);
-		$return['nathostenabled'] = processInputVar('nathostenabled', ARG_NUMERIC);
-		$return['natpublicIPaddress'] = processInputVar('natpublicipaddress', ARG_STRING);
-		$return['natinternalIPaddress'] = processInputVar('natinternalipaddress', ARG_STRING);
-
-		if(get_magic_quotes_gpc()) {
-			$return['sysadminemail'] = stripslashes($return['sysadminemail']);
-			$return['sharedmailbox'] = stripslashes($return['sharedmailbox']);
-		}
+		$return['availablenetworks'] = processInputVar('availablenetworks', ARG_STRING, '');
+		$return['federatedauth'] = processInputVar('federatedauth', ARG_STRING, '');
+		$return['nathostenabled'] = processInputVar('nathostenabled', ARG_NUMERIC, 2);
+		$return['natpublicIPaddress'] = processInputVar('natpublicipaddress', ARG_STRING, '');
+		$return['natinternalIPaddress'] = processInputVar('natinternalipaddress', ARG_STRING, '');
 
 		$olddata = getContinuationVar('olddata');
 
@@ -889,8 +884,14 @@
 			}
 		}
 		else {
-			$return['publicnetmask'] = $olddata['publicnetmask'];
-			$return['publicgateway'] = $olddata['publicgateway'];
+			if($return['mode'] == 'edit') {
+				$return['publicnetmask'] = $olddata['publicnetmask'];
+				$return['publicgateway'] = $olddata['publicgateway'];
+			}
+			else {
+				$return['publicnetmask'] = '';
+				$return['publicgateway'] = '';
+			}
 		}
 		# stateid  2 - available, 5 - failed, 10 - maintenance
 		if(! preg_match('/^(2|5|10)$/', $return['stateid'])) {
diff --git a/web/.ht-inc/oneclick.php b/web/.ht-inc/oneclick.php
index d8b62c9..0f8f023 100755
--- a/web/.ht-inc/oneclick.php
+++ b/web/.ht-inc/oneclick.php
@@ -232,8 +232,8 @@
 	global $user, $submitErr, $submitErrMsg;
 	$maxlength = getContinuationVar('maxlength');
 	$imageid = processInputVar("imageid", ARG_NUMERIC);
-	$name = processInputVar("newOneClickName", ARG_STRING);
-	$duration = processInputVar("length", ARG_NUMERIC);
+	$name = processInputVar("newOneClickName", ARG_STRING, '');
+	$duration = processInputVar("length", ARG_NUMERIC, 120);
 	$autologin = processInputVar("autologin", ARG_NUMERIC) == 1 ? 1 : 0;
 
 	# validate access to $imageid
@@ -410,8 +410,8 @@
 	global $submitErr, $submitErrMsg;
 	$oneclickid = getContinuationVar('oneclickid');
 	$maxlength = getContinuationVar('maxlength');
-	$name = processInputVar('name', ARG_STRING);
-	$duration = processInputVar("duration", ARG_NUMERIC);
+	$name = processInputVar('name', ARG_STRING, '');
+	$duration = processInputVar("duration", ARG_NUMERIC, 120);
 	$autologin = processInputVar("autologin", ARG_NUMERIC) == 1 ? 1 : 0;
 
 	# validate $name
diff --git a/web/.ht-inc/privileges.php b/web/.ht-inc/privileges.php
index 714b910..4130169 100644
--- a/web/.ht-inc/privileges.php
+++ b/web/.ht-inc/privileges.php
@@ -1164,6 +1164,13 @@
 function AJsubmitAddChildNode() {
 	global $user;
 	$parent = processInputVar("activeNode", ARG_NUMERIC);
+	if(is_null($parent)) {
+		$text = "Invalid parent node submitted.";
+		print "dojo.byId('childNodeName').value = ''; ";
+		print "dijit.byId('addNodePane').hide(); ";
+		print "alert('$text');";
+		return;
+	}
 	if(! checkUserHasPriv("nodeAdmin", $user["id"], $parent)) {
 		$text = "You do not have rights to add children to this node.";
 		print "dojo.byId('childNodeName').value = ''; ";
@@ -1171,7 +1178,7 @@
 		print "alert('$text');";
 		return;
 	}
-	$newnode = processInputVar("newnode", ARG_STRING);
+	$newnode = processInputVar("newnode", ARG_STRING, '');
 	$errmsg = '';
 	if(! validateNodeName($newnode, $errmsg)) {
 		print "dojo.byId('addChildNodeStatus').innerHTML = '$errmsg';";
@@ -1308,7 +1315,7 @@
 		sendJSON($arr);
 		return;
 	}
-	$newname = processInputVar('newname', ARG_STRING);
+	$newname = processInputVar('newname', ARG_STRING, '');
 	$errmsg = '';
 	if(! validateNodeName($newname, $errmsg)) {
 		$arr = array('error' => 2, 'message' => $errmsg);
@@ -1350,6 +1357,12 @@
 	$oldparentid = processInputVar('oldparentid', ARG_NUMERIC);
 	$newparentid = processInputVar('newparentid', ARG_NUMERIC);
 
+	if(is_null($moveid) || is_null($oldparentid) || is_null($newparentid)) {
+		$arr = array('status' => 'invalidreload');
+		sendJSON($arr);
+		return;
+	}
+
 	if(! checkUserHasPriv("nodeAdmin", $user["id"], $moveid) ||
 	   ! checkUserHasPriv("nodeAdmin", $user["id"], $newparentid) ||
 	   ! checkUserHasPriv("nodeAdmin", $user["id"], $oldparentid)) {
@@ -1463,9 +1476,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 function userLookup() {
 	global $user;
-	$userid = processInputVar("userid", ARG_STRING);
-	if(get_magic_quotes_gpc())
-		$userid = stripslashes($userid);
+	$userid = processInputVar("userid", ARG_STRING, '');
 	$affilid = processInputVar('affiliationid', ARG_NUMERIC, $user['affiliationid']);
 	$force = processInputVar('force', ARG_NUMERIC, 0);
 	print "<div align=center>\n";
@@ -1965,6 +1976,24 @@
 			print "<table>\n";
 			$first = 1;
 			foreach($requests as $req) {
+				# get information about last time Connect button clicked
+				$query = "SELECT timestamp, "
+				       .        "query "
+				       . "FROM querylog "
+				       . "WHERE userid = {$userdata['id']} AND "
+				       .       "mode = 'AJconnectRequest' AND "
+				       .       "timestamp > DATE_SUB(NOW(), INTERVAL 1 WEEK) AND "
+				       .       "query LIKE 'UPDATE reservation SET remoteIP = % WHERE requestid = {$req['requestid']}' "
+				       . "ORDER BY timestamp DESC "
+				       . "LIMIT 5";
+				$qh = doQuery($query);
+				$connects = array();
+				while($row = mysqli_fetch_assoc($qh)) {
+					preg_match("/^UPDATE reservation SET remoteIP = '([0-9\.]+)' WHERE requestid = {$req['requestid']}$/", $row['query'], $matches);
+					if(isset($matches[1]))
+						$connects[] = "{$row['timestamp']} from {$matches[1]}";
+				}
+				$connectstr = implode('<br>', $connects);
 				if($first)
 					$first = 0;
 				else {
@@ -2042,6 +2071,12 @@
 				print "    <th align=right>Management Node:</th>\n";
 				print "    <td>{$req['managementnode']}</td>\n";
 				print "  </tr>\n";
+				if(count($connects)) {
+					print "  <tr>\n";
+					print "    <th align=right>Connect last clicked:</th>\n";
+					print "    <td>$connectstr</td>\n";
+					print "  </tr>\n";
+				}
 			}
 			print "</table>\n";
 		}
@@ -2095,6 +2130,26 @@
 				print "<table>\n";
 				$first = 1;
 				foreach($requests as $req) {
+					# get information about last time Connect button clicked
+					$connects = array();
+					if(count($requests) < 15) {
+						$query = "SELECT timestamp, "
+						       .        "query "
+						       . "FROM querylog "
+						       . "WHERE userid = {$userdata['id']} AND "
+						       .       "mode = 'AJconnectRequest' AND "
+						       .       "timestamp > DATE_SUB(NOW(), INTERVAL 1 WEEK) AND "
+						       .       "query LIKE 'UPDATE reservation SET remoteIP = % WHERE requestid = {$req['requestid']}' "
+						       . "ORDER BY timestamp DESC "
+						       . "LIMIT 5";
+						$qh = doQuery($query);
+						while($row = mysqli_fetch_assoc($qh)) {
+							preg_match("/^UPDATE reservation SET remoteIP = '([0-9\.]+)' WHERE requestid = {$req['requestid']}$/", $row['query'], $matches);
+							if(isset($matches[1]))
+								$connects[] = "{$row['timestamp']} from {$matches[1]}";
+						}
+						$connectstr = implode('<br>', $connects);
+					}
 					if($first)
 						$first = 0;
 					else {
@@ -2166,6 +2221,12 @@
 					print "    <th align=right>Management Node:</th>\n";
 					print "    <td>{$req['managementnode']}</td>\n";
 					print "  </tr>\n";
+					if(count($connects)) {
+						print "  <tr>\n";
+						print "    <th align=right>Connect last clicked:</th>\n";
+						print "    <td>$connectstr</td>\n";
+						print "  </tr>\n";
+					}
 				}
 				print "</table>\n";
 			}
@@ -2465,8 +2526,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 function jsonGetUserGroupMembers() {
 	global $user;
-	$usergrpid = processInputVar('groupid', ARG_NUMERIC);
-	$domid = processInputVar('domid', ARG_STRING);
+	$usergrpid = processInputVar('groupid', ARG_NUMERIC, 0);
+	$domid = processInputVar('domid', ARG_STRING, '');
 	$query = "SELECT g.ownerid, "
 	       .        "g.affiliationid, "
 	       .        "g.custom, "
@@ -2645,8 +2706,8 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function jsonGetResourceGroupMembers() {
-	$resgrpid = processInputVar('groupid', ARG_NUMERIC);
-	$domid = processInputVar('domid', ARG_STRING);
+	$resgrpid = processInputVar('groupid', ARG_NUMERIC, 0);
+	$domid = processInputVar('domid', ARG_STRING, '');
 	$query = "SELECT rt.name "
 	       . "FROM resourcegroup rg, "
 	       .      "resourcetype rt "
@@ -3116,7 +3177,7 @@
 function AJchangeUserPrivs() {
 	global $user;
 	$node = processInputVar("activeNode", ARG_NUMERIC);
-	if(! checkUserHasPriv("userGrant", $user["id"], $node)) {
+	if(is_null($node) || ! checkUserHasPriv("userGrant", $user["id"], $node)) {
 		$text = "You do not have rights to modify user privileges at this node.";
 		print "alert('$text');";
 		return;
@@ -3125,6 +3186,12 @@
 	$newpriv = processInputVar('priv', ARG_STRING);
 	$newprivval = processInputVar('value', ARG_STRING);
 
+	if(is_null($newpriv) || ! preg_match('/^[- a-zA-Z0-9]+$/', $newpriv)) {
+		$text = "Invalid user privilege submitted.";
+		print "alert('$text');";
+		return;
+	}
+
 	if(! validateUserid($newuser)) {
 		$text = "Invalid user submitted.";
 		print "alert('$text');";
@@ -3172,7 +3239,7 @@
 function AJchangeUserGroupPrivs() {
 	global $user;
 	$node = processInputVar("activeNode", ARG_NUMERIC);
-	if(! checkUserHasPriv("userGrant", $user["id"], $node)) {
+	if(is_null($node) || ! checkUserHasPriv("userGrant", $user["id"], $node)) {
 		$text = "You do not have rights to modify user privileges at this node.";
 		print "alert('$text');";
 		return;
@@ -3181,6 +3248,12 @@
 	$newpriv = processInputVar('priv', ARG_STRING);
 	$newprivval = processInputVar('value', ARG_STRING);
 
+	if(is_null($newpriv) || ! preg_match('/^[- a-zA-Z0-9]+$/', $newpriv)) {
+		$text = "Invalid user privilege submitted.";
+		print "alert('$text');";
+		return;
+	}
+
 	$newusergrp = getUserGroupName($newusergrpid);
 	if($newusergrp === 0) {
 		$text = "Invalid user group submitted.";
@@ -3229,12 +3302,12 @@
 function AJchangeResourcePrivs() {
 	global $user;
 	$node = processInputVar("activeNode", ARG_NUMERIC);
-	if(! checkUserHasPriv("resourceGrant", $user["id"], $node)) {
+	if(is_null($node) || ! checkUserHasPriv("resourceGrant", $user["id"], $node)) {
 		$text = "You do not have rights to modify resource privileges at this node.";
 		print "alert('$text');";
 		return;
 	}
-	$resourcegrp = processInputVar("item", ARG_STRING);
+	$resourcegrp = processInputVar("item", ARG_STRING, '');
 	$newpriv = processInputVar('priv', ARG_STRING);
 	$newprivval = processInputVar('value', ARG_STRING);
 
@@ -3307,7 +3380,7 @@
 function AJsubmitAddUserPriv() {
 	global $user;
 	$node = processInputVar("activeNode", ARG_NUMERIC);
-	if(! checkUserHasPriv("userGrant", $user["id"], $node)) {
+	if(is_null($node) || ! checkUserHasPriv("userGrant", $user["id"], $node)) {
 		$text = "You do not have rights to add new users at this node.";
 		print "addUserPaneHide(); ";
 		print "alert('$text');";
@@ -3320,7 +3393,7 @@
 		return;
 	}
 
-	$perms = explode(':', processInputVar('perms', ARG_STRING));
+	$perms = explode(':', processInputVar('perms', ARG_STRING, ''));
 	$usertypes = getTypes("users");
 	array_push($usertypes["users"], "block");
 	array_push($usertypes["users"], "cascade");
@@ -3359,7 +3432,7 @@
 function AJsubmitAddUserGroupPriv() {
 	global $user;
 	$node = processInputVar("activeNode", ARG_NUMERIC);
-	if(! checkUserHasPriv("userGrant", $user["id"], $node)) {
+	if(is_null($node) || ! checkUserHasPriv("userGrant", $user["id"], $node)) {
 		$text = "You do not have rights to add new user groups at this node.";
 		print "addUserGroupPaneHide(); ";
 		print "alert('$text');";
@@ -3374,7 +3447,7 @@
 		return;
 	}
 
-	$perms = explode(':', processInputVar('perms', ARG_STRING));
+	$perms = explode(':', processInputVar('perms', ARG_STRING, ''));
 
 	$usertypes = getTypes("users");
 	array_push($usertypes["users"], "block");
@@ -3413,13 +3486,13 @@
 function AJsubmitAddResourcePriv() {
 	global $user;
 	$node = processInputVar("activeNode", ARG_NUMERIC);
-	if(! checkUserHasPriv("resourceGrant", $user["id"], $node)) {
+	if(is_null($node) || ! checkUserHasPriv("resourceGrant", $user["id"], $node)) {
 		$text = "You do not have rights to add new resource groups at this node.";
 		print "addResourceGroupPaneHide(); ";
 		print "alert('$text');";
 		return;
 	}
-	$newgroupid = processInputVar("newgroupid", ARG_NUMERIC);
+	$newgroupid = processInputVar("newgroupid", ARG_NUMERIC, -1);
 	$privs = array("computerAdmin", "mgmtNodeAdmin", "imageAdmin",
 	               "scheduleAdmin", "serverProfileAdmin");
 	$resourcegroups = getUserResources($privs, array("manageGroup"), 1);
@@ -3441,7 +3514,7 @@
 		return;
 	}
 
-	$perms = explode(':', processInputVar('perms', ARG_STRING));
+	$perms = explode(':', processInputVar('perms', ARG_STRING, ''));
 	$privtypes = getResourcePrivs();
 	$newgroupprivs = array();
 	foreach($privtypes as $type) {
@@ -3564,7 +3637,7 @@
 		sendJSON(array('failed' => 'noaccess'));
 		return;
 	}
-	$permids = processInputVar('permids', ARG_STRING);
+	$permids = processInputVar('permids', ARG_STRING, '');
 	if(! preg_match('/^[0-9,]*$/', $permids)) {
 		sendJSON(array('failed' => 'invalid input'));
 		return;
diff --git a/web/.ht-inc/requests.php b/web/.ht-inc/requests.php
index 72c9b36..84d175a 100644
--- a/web/.ht-inc/requests.php
+++ b/web/.ht-inc/requests.php
@@ -152,6 +152,9 @@
 					$cdata2['notbyowner'] = 0;
 					if($user['id'] != $requests[$i]['userid'])
 						$cdata2['notbyowner'] = 1;
+					$cdata2['imageadmin'] = 0;
+					if(array_key_exists($imageid, $resources['image']))
+						$cdata2['imageadmin'] = 1;
 					$cont = addContinuationsEntry('AJconfirmDeleteRequest', $cdata2, SECINDAY);
 					$text .= getViewRequestHTMLitem('deletebtn', $cont);
 				}
@@ -247,6 +250,9 @@
 						$cdata2['notbyowner'] = 0;
 						if($user['id'] != $requests[$i]['userid'])
 							$cdata2['notbyowner'] = 1;
+						$cdata2['imageadmin'] = 0;
+						if(array_key_exists($imageid, $resources['image']))
+							$cdata2['imageadmin'] = 1;
 						$cont = addContinuationsEntry('AJconfirmDeleteRequest', $cdata2, SECINDAY);
 						$text .= getViewRequestHTMLitem('deletebtn', $cont);
 					}
@@ -262,6 +268,9 @@
 					$cdata2['notbyowner'] = 0;
 					if($user['id'] != $requests[$i]['userid'])
 						$cdata2['notbyowner'] = 1;
+					$cdata2['imageadmin'] = 0;
+					if(array_key_exists($imageid, $resources['image']))
+						$cdata2['imageadmin'] = 1;
 					$cont = addContinuationsEntry('AJconfirmDeleteRequest', $cdata2, SECINDAY);
 					$text .= getViewRequestHTMLitem('deletebtn', $cont);
 				}
@@ -1433,24 +1442,7 @@
 	$h .= "   <input type=\"hidden\" id=\"openend\" value=\"$openend\">\n";
 	$h .= "   <div id=\"newResDlgContent\">\n";
 
-	/*$cbtn  = "   <div align=\"center\"><br>\n";
-	$cbtn .= "   <button dojoType=\"dijit.form.Button\">\n";
-	$cbtn .= "     " . i("Close") . "\n";
-	$cbtn .= "     <script type=\"dojo/method\" event=\"onClick\">\n";
-	$cbtn .= "       dijit.byId('newResDlg').hide();\n";
-	$cbtn .= "     </script>\n";
-	$cbtn .= "   </button>\n";
-	$cbtn .= "   </div>\n"; # center
-
-	if($forimaging) {
-		$h .= "<h2>" . i("Create / Update an Image") . "</h2>\n";
-		if($imagingaccess == 0) {
-			$h .= i("You don't have access to any base images from which to create new images.") . "<br>\n";
-			return $h . $cbtn;
-		}
-	}
-	else*/
-		$h .= "<h2>" . i("New Reservation") . "</h2>\n";
+	$h .= "<h2>" . i("New Reservation") . "</h2>\n";
 
 	if(! count($images)) {
 		$h .= i("You do not have access to any environments.");
@@ -1467,28 +1459,6 @@
 		$h .= "</div>\n"; # newResDlg
 		return $h;
 	}
-
-	/*$h .= "<span id=\"deployprofileslist\" class=\"hidden\">\n";
-	$h .= "<div dojoType=\"dojo.data.ItemFileWriteStore\" jsId=\"profilesstore\" ";
-	$h .= "data=\"profilesstoredata\"></div>\n";
-	$h .= i("Profile:") . " ";
-	$h .= "<select dojoType=\"dijit.form.Select\" id=\"deployprofileid\" ";
-	$h .= "onChange=\"deployProfileChanged();\" sortByLabel=\"true\"></select><br>\n";
-	$h .= "<fieldset>\n";
-	$h .= "<legend>" . i("Description:") . "</legend>\n";
-	$h .= "<div id=\"deploydesc\"></div>\n";
-	$h .= "</fieldset>\n";
-	$cont = addContinuationsEntry('AJserverProfileData', array('mode' => 'checkout'));
-	$h .= "<button dojoType=\"dijit.form.Button\" id=\"deployFetchProfilesBtn\">\n";
-	$h .= "	" . i("Apply Profile") . "\n";
-	$h .= "	<script type=\"dojo/method\" event=onClick>\n";
-	$h .= "		getServerProfileData('$cont', 'deployprofileid', getServerProfileDataDeployCB);\n";
-	$h .= "	</script>\n";
-	$h .= "</button>";
-	$h .= "<br><br>\n";
-	$h .= "<input type=\"hidden\" id=\"appliedprofileid\" value=\"0\">\n";
-	$h .= "</span>\n"; # deployprofileslist*/
-
 	# directions
 	$h .= "<span id=\"nrdirections\">";
 	$h .= i("Please select the environment you want to use from the list:");
@@ -1884,7 +1854,7 @@
 	   ($type == 'server' && ! $serveraccess))
 		return;
 
-		print "showHideTypeInputs();";
+	print "showHideTypeInputs();";
 
 	if($type == 'imaging')
 		$imaging = 1;
@@ -2097,13 +2067,12 @@
 function printImageDescription($imageid) {
 	$imagenotes = getImageNotes($imageid);
 	if(! preg_match('/^\s*$/', $imagenotes['description'])) {
-		$desc = preg_replace("/\n/", '<br>', $imagenotes['description']);
-		$desc = preg_replace("/\r/", '', $desc);
+		$desc = preg_replace("/\r/", '', $imagenotes['description']);
 		$desc = preg_replace("/'/", '&#39;', $desc);
-		$desc = preg_replace("/(.{1,60}([ \n]|$))/", '\1<br>', $desc);
+		$desc = htmlwrap($desc, 80);
 		print "dojo.byId('imgdesc').innerHTML = '<b>";
 		print i("Image Description") . "</b>:<br>";
-		print "$desc<br>'; ";
+		print "$desc<br><br>'; ";
 	}
 }
 
@@ -2218,7 +2187,7 @@
 		for($cnt = 0, $amount = 900, $e = datetimeToUnix($reqdata['end']) + 900;
 		    $cnt < 15 && $amount <= $maxextend && $amount < 7200;
 		    $cnt++, $amount += 900, $e += 900) {
-			$end = strftime('%x %l:%M %P', $e);
+			$end = prettyDatetime($e, 1, 0, 1, 1);
 			$extenstion = getReservationExtenstion($amount / 60);
 			if($cnt % 2)
 				$html .= "<tr class=\"tablerow0\">";
@@ -2234,7 +2203,7 @@
 		}
 		for(; $cnt < 15 && $amount <= $maxextend;
 		    $cnt++, $amount += 3600, $e += 3600) {
-			$end = strftime('%x %l:%M %P', $e);
+			$end = prettyDatetime($e, 1, 0, 1, 1);
 			$extenstion = getReservationExtenstion($amount / 60);
 			if($cnt % 2)
 				$html .= "<tr class=\"tablerow0\">";
@@ -2262,7 +2231,7 @@
 		foreach($slots as $key => $slot) {
 			$cnt++;
 			$slot['startts'] += $_SESSION['persistdata']['tzoffset'] * 60;
-			$start = strftime('%x %l:%M %P', $slot['startts']);
+			$start = prettyDatetime($slot['startts'], 1, 0, 1, 1);
 			if(($slot['startts'] - time()) + $slot['startts'] + $slot['duration'] >= 2114402400)
 				# end time >= 2037-01-01 00:00:00
 				$duration = 'indefinite';
@@ -3095,6 +3064,7 @@
 	print "    <TD>\n";
 	$cdata = array('requestid' => $requestid,
 	               'notbyowner' => 1,
+	               'imageadmin' => 0,
 	               'ttdata' => getContinuationVar('ttdata'),
 	               'fromtimetable' => 1);
 	$cont = addContinuationsEntry('AJconfirmDeleteRequest', $cdata, SECINDAY);
@@ -3418,7 +3388,7 @@
 	else
 		$maxcheck = $maxtimes['total'];
 	if(! $openend && ($reslen >= $maxcheck)) {
-		$h  = sprintf(i("You are only allowed to extend your reservation such that it has a total length of %s. "), minToHourMin($maxcheck));
+		$h  = sprintf(i("You are only allowed to extend your reservation such that it has a total length of %s. "), minToDaysHourMin($maxcheck));
 		$h .= i("This reservation already meets that length. Therefore, you are not allowed to extend your reservation any further.");
 		$h = preg_replace("/(.{1,60}([ \n]|$))/", '\1<br>', $h) . "<br>";
 		sendJSON(array('status' => 'nomodify', 'html' => $h));
@@ -3470,7 +3440,7 @@
 	$lengths = array();
 	if($request['forimaging'] && $maxtimes['total'] < 720) # make sure at least 12 hours available for imaging reservations
 		$maxtimes['total'] = 720;
-	elseif(! $request['forimaging'] && $maximglen) {
+	elseif(! $request['forimaging'] && $maximglen && ($maximglen < $maxtimes['total'])) {
 		$maxtimes['total'] = $maximglen;
 		$currduration = (datetimeToUnix($request['end']) - datetimeToUnix($request['start'])) / 60;
 		$maxtimes['extend'] = $maximglen - $currduration;
@@ -3528,7 +3498,7 @@
 			else
 				$maxcheck = $maxtimes['total'];
 			$m = sprintf(i("You can extend this reservation by up to %s but not exceeding %s for your total reservation time."),
-			             minToHourMin($maxtimes['extend']), minToHourMin($maxcheck));
+			             minToDaysHourMin($maxtimes['extend']), minToDaysHourMin($maxcheck));
 			$h .= preg_replace("/(.{1,60}([ \n]|$))/", '\1<br>', $m) . "<br>";
 		}
 	}
@@ -3989,6 +3959,7 @@
 	global $user;
 	$requestid = getContinuationVar('requestid', 0);
 	$notbyowner = getContinuationVar('notbyowner', 0);
+	$imageadmin = getContinuationVar('imageadmin', 0);
 	$fromtimetable = getContinuationVar('fromtimetable', 0);
 	$skipconfirm = processInputVar('skipconfirm', ARG_NUMERIC, 0);
 	if($skipconfirm != 0 && $skipconfirm != 1)
@@ -4034,7 +4005,7 @@
 		                prettyDatetime($request["start"]));
 	}
 	else {
-		if($notbyowner == 0 && ! $reservation["production"] && count($request['reservations']) == 1) {
+		if($imageadmin && $notbyowner == 0 && ! $reservation["production"] && count($request['reservations']) == 1) {
 			AJconfirmDeleteRequestProduction($request);
 			return;
 		}
@@ -4402,7 +4373,7 @@
 		$h .= "</big></font><br><br>\n";
 	}
 	$imagenotes = getImageNotes($requestData['reservations'][0]['imageid']);
-	if(! preg_match('/^\s*$/', $imagenotes['usage'])) {
+	if(! is_null($imagenotes['usage']) && ! preg_match('/^\s*$/', $imagenotes['usage'])) {
 		$h .= "<h3>" . i("Notes on using this environment:") . "</h3>\n";
 		$h .= "{$imagenotes['usage']}<br><br><br>\n";
 	}
@@ -4415,6 +4386,7 @@
 		$h .= i("This is a cluster reservation. Depending on the makeup of the cluster, you may need to use different methods to connect to the different environments in your cluster.");
 		$h .= "<br><br>\n";
 	}
+	$copybtnbase = "<a onclick=\"navigator.clipboard.writeText('%s');\"><img src=\"images/copy_icon.png\" style=\"height: 1.1em; width: 1em;\"></a>";
 	foreach($requestData["reservations"] as $key => $res) {
 		$osname = $res["OS"];
 		if(array_key_exists($user['id'], $requestData['passwds'][$res['reservationid']]))
@@ -4441,12 +4413,17 @@
 				$conuser = $matches[1];
 			else
 				$conuser = $user['unityid'];
-			if($requestData['reservations'][0]['domainDNSName'] != '' && ! strlen($passwd))
-				$conuser .= "@" . $requestData['reservations'][0]['domainDNSName'];
-			elseif($requestData['reservations'][0]['OStype'] == 'windows')
-				$conuser = ".\\$conuser";
-			if(! strlen($passwd))
-				$passwd = i('(use your campus password)');
+			if($requestData['reservations'][0]['OStype'] == 'windows') {
+				if($requestData['reservations'][0]['domainDNSName'] != '' && (is_null($passwd) || ! strlen($passwd)))
+					$conuser .= "@" . $requestData['reservations'][0]['domainDNSName'];
+				else
+					$conuser = ".\\$conuser";
+			}
+			$conuser = sprintf("$conuser&nbsp;$copybtnbase", preg_replace('/\\\/', '\\\\\\\\\\', $conuser));
+			if(is_null($passwd) || ! strlen($passwd))
+				$_passwd = i('(use your campus password)');
+			else
+				$_passwd = sprintf("$passwd&nbsp;$copybtnbase", $passwd);
 			if($cluster)
 				$h .= "<h4>" . i("Connect to reservation using") . " {$method['description']}</h4>\n";
 			else
@@ -4468,8 +4445,16 @@
 					$method['connecttext'] = preg_replace("/#connectIP#/", "#connectIP#:{$method['ports'][0]['key']}", $method['connecttext']);
 				}
 			}
+			if(preg_match('/(#connectIP#.#Port-(TCP|UDP)-[0-9]+#)/', $method['connecttext'], $matches)) {
+				$copyip = sprintf($copybtnbase, $matches[1]);
+				$method['connecttext'] = preg_replace("_((?<!/)#connectIP#.#Port-(TCP|UDP)-[0-9]+#)_", "\\1&nbsp;$copyip", $method['connecttext']);
+			}
+			else {
+				$copyip = sprintf($copybtnbase, $res['connectIP']);
+				$method['connecttext'] = preg_replace("|(?<!/)(#connectIP#)|", "\\1&nbsp;$copyip", $method['connecttext']);
+			}
 			$tos = array($conuser,
-			             $passwd,
+			             $_passwd,
 			             $res['connectIP']);
 			$msg = preg_replace($froms, $tos, $method['connecttext']);
 			foreach($method['ports'] as $port) {
@@ -4531,6 +4516,11 @@
 function AJcheckConnectTimeout() {
 	$requestid = getContinuationVar('requestid');
 	$reqdata = getRequestInfo($requestid, 1);
+	if(is_null($reqdata)) {
+		$data['status'] = 'timeout';
+		sendJSON($data);
+		return;
+	}
 	$stateid = $reqdata['stateid'];
 	if($stateid == 14)
 		$stateid = $reqdata['laststateid'];
@@ -4714,7 +4704,7 @@
 		$return['nousercheck'] = 0;
 
 	# revisionid
-	$revids = processInputVar("revisionid", ARG_STRING);
+	$revids = processInputVar("revisionid", ARG_STRING, '');
 	$revids = explode(':', $revids);
 	$images = getImages(0, $return['imageid']);
 	$return['revisionids'] = array();
@@ -4777,7 +4767,7 @@
 	# server specific input
 	if($return['type'] == 'server') {
 		# name
-		$return['name'] = processInputVar('name', ARG_STRING);
+		$return['name'] = processInputVar('name', ARG_STRING, '');
 		if(! preg_match('/^([-a-zA-Z0-9_\. ]){0,255}$/', $return['name'])) {
 			$return['err'] = 1;
 			$return['errmsg'] = i('The reservation name can only contain letters, numbers, spaces, dashes(-), underscores(_), and periods(.) and can be up to 255 characters long');
@@ -4899,8 +4889,6 @@
 		$userconfigs = $tmp['config'];
 		$initconfigs = getMappedConfigs($return['imageid']);
 		if(array_key_exists('configdata', $_POST)) {
-			if(get_magic_quotes_gpc())
-				$_POST['configdata'] = stripslashes($_POST['configdata']);
 			$configdata = json_decode($_POST['configdata']);
 		}
 		if(array_key_exists('configdata', $_POST) &&
diff --git a/web/.ht-inc/resource.php b/web/.ht-inc/resource.php
index 04a5e10..4ba93ec 100644
--- a/web/.ht-inc/resource.php
+++ b/web/.ht-inc/resource.php
@@ -801,7 +801,7 @@
 		$h .= "selectionMode=\"extended\">\n";
 		$h .= "<thead>\n";
 		$h .= "<tr>\n";
-		$h .= "<th field=\"name\" width=\"160px\"></th>\n";
+		$h .= "<th field=\"name\" width=\"220px\"></th>\n";
 		$h .= "</tr>\n";
 		$h .= "</thead>\n";
 		$h .= "</table>\n";
@@ -830,7 +830,7 @@
 		$h .= "selectionMode=\"extended\">\n";
 		$h .= "<thead>\n";
 		$h .= "<tr>\n";
-		$h .= "<th field=\"name\" width=\"160px\"></th>\n";
+		$h .= "<th field=\"name\" width=\"220px\"></th>\n";
 		$h .= "</tr>\n";
 		$h .= "</thead>\n";
 		$h .= "</table>\n";
@@ -894,7 +894,12 @@
 		}
 
 		$groups = getUserResources(array($this->restype . "Admin"), array("manageGroup"), 1);
-		$tmp = processInputVar('listids', ARG_STRING);
+		$tmp = processInputVar('listids', ARG_STRING, '');
+		if($tmp == '') {
+				$arr = array('status' => 'invalid');
+				sendJSON($arr);
+				return;
+		}
 		$tmp = explode(',', $tmp);
 		$groupids = array();
 		foreach($tmp as $id) {
@@ -979,7 +984,7 @@
 		$h .= "selectionMode=\"extended\" sortInfo=\"1\">\n";
 		$h .= "<thead>\n";
 		$h .= "<tr>\n";
-		$h .= "<th field=\"name\" width=\"160px\"></th>\n";
+		$h .= "<th field=\"name\" width=\"220px\"></th>\n";
 		$h .= "</tr>\n";
 		$h .= "</thead>\n";
 		$h .= "</table>\n";
@@ -1008,7 +1013,7 @@
 		$h .= "selectionMode=\"extended\" sortInfo=\"1\">\n";
 		$h .= "<thead>\n";
 		$h .= "<tr>\n";
-		$h .= "<th field=\"name\" width=\"160px\"></th>\n";
+		$h .= "<th field=\"name\" width=\"220px\"></th>\n";
 		$h .= "</tr>\n";
 		$h .= "</thead>\n";
 		$h .= "</table>\n";
@@ -1075,6 +1080,11 @@
 
 		$resources = getUserResources(array($this->restype . "Admin"), array("manageGroup"));
 		$tmp = processInputVar('listids', ARG_STRING);
+		if($tmp == '') {
+				$arr = array('status' => 'invalid');
+				sendJSON($arr);
+				return;
+		}
 		$tmp = explode(',', $tmp);
 		$rscids = array();
 		foreach($tmp as $id) {
@@ -1154,7 +1164,10 @@
 		$h = '';
 
 		if(! count($groups) || ! count($mapgroups)) {
+			$h .= "<div id=\"mapbyresgroupdiv\" dojoType=\"dijit.layout.ContentPane\" ";
+			$h .= "title=\"" . i("Map By {$this->restypename} Group") . "\">\n";
 			$h .= i("You don't have access to manage any mappings for this resource type.");
+			$h .= "</div>\n";
 			return $h;
 		}
 
@@ -1179,7 +1192,7 @@
 		$h .= "selectionMode=\"extended\">\n";
 		$h .= "<thead>\n";
 		$h .= "<tr>\n";
-		$h .= "<th field=\"name\" width=\"160px\"></th>\n";
+		$h .= "<th field=\"name\" width=\"220px\"></th>\n";
 		$h .= "</tr>\n";
 		$h .= "</thead>\n";
 		$h .= "</table>\n";
@@ -1210,7 +1223,7 @@
 		$h .= "selectionMode=\"extended\">\n";
 		$h .= "<thead>\n";
 		$h .= "<tr>\n";
-		$h .= "<th field=\"name\" width=\"160px\"></th>\n";
+		$h .= "<th field=\"name\" width=\"220px\"></th>\n";
 		$h .= "</tr>\n";
 		$h .= "</thead>\n";
 		$h .= "</table>\n";
@@ -1347,8 +1360,11 @@
 		$h = '';
 
 		if(! count($mapgroups) || ! count($groups)) {
+			$h .= "<div id=\"mapbymaptogroupdiv\" dojoType=\"dijit.layout.ContentPane\" ";
+			$h .= "title=\"" . i("Map By {$this->maptypename} Group") . "\">\n";
 			$h .= "You don't have access to manage any mappings for this resource ";
 			$h .= "type.<br>\n";
+			$h .= "</div>\n";
 			return $h;
 		}
 
@@ -1373,7 +1389,7 @@
 		$h .= "selectionMode=\"extended\">\n";
 		$h .= "<thead>\n";
 		$h .= "<tr>\n";
-		$h .= "<th field=\"name\" width=\"160px\"></th>\n";
+		$h .= "<th field=\"name\" width=\"220px\"></th>\n";
 		$h .= "</tr>\n";
 		$h .= "</thead>\n";
 		$h .= "</table>\n";
@@ -1402,7 +1418,7 @@
 		$h .= "selectionMode=\"extended\">\n";
 		$h .= "<thead>\n";
 		$h .= "<tr>\n";
-		$h .= "<th field=\"name\" width=\"160px\"></th>\n";
+		$h .= "<th field=\"name\" width=\"220px\"></th>\n";
 		$h .= "</tr>\n";
 		$h .= "</thead>\n";
 		$h .= "</table>\n";
diff --git a/web/.ht-inc/schedule.php b/web/.ht-inc/schedule.php
index d0760e8..7b0bca7 100644
--- a/web/.ht-inc/schedule.php
+++ b/web/.ht-inc/schedule.php
@@ -331,9 +331,9 @@
 		$errormsg = array();
 
 		$return['rscid'] = getContinuationVar('rscid', 0);
-		$return["name"] = processInputVar("name", ARG_STRING);
+		$return["name"] = processInputVar("name", ARG_STRING, '');
 		$return["owner"] = processInputVar("owner", ARG_STRING, "{$user["unityid"]}@{$user['affiliation']}");
-		$times = processInputVar('times', ARG_STRING);
+		$times = processInputVar('times', ARG_STRING, '');
 
 		if(! preg_match("/^([A-Za-z0-9-!@#$%^&\*\(\)_=\+\[\]{}\\\|:;,\.\/\?~` ]){2,30}$/", $return['name'])) {
 			$return['error'] = 1;
diff --git a/web/.ht-inc/serverprofiles.php b/web/.ht-inc/serverprofiles.php
index 9d9ad37..3bcace5 100644
--- a/web/.ht-inc/serverprofiles.php
+++ b/web/.ht-inc/serverprofiles.php
@@ -662,17 +662,17 @@
 	global $user;
 	$ret = array();
 	$ret['profileid'] = processInputVar('id', ARG_NUMERIC);
-	$ret['name'] = processInputVar('name', ARG_STRING);
-	$ret['desc'] = processInputVar('desc', ARG_STRING);
+	$ret['name'] = processInputVar('name', ARG_STRING, '');
+	$ret['desc'] = processInputVar('desc', ARG_STRING, '');
 	$ret['imageid'] = processInputVar('imageid', ARG_NUMERIC);
-	$ret['fixedMAC'] = processInputVar('fixedMAC', ARG_STRING);
-	$ret['admingroupid'] = processInputVar('admingroupid', ARG_NUMERIC);
-	$ret['logingroupid'] = processInputVar('logingroupid', ARG_NUMERIC);
-	$monitored = processInputVar('monitored', ARG_STRING);
-	$ret['fixedIP'] = processInputVar('fixedIP', ARG_STRING);
-	$ret['netmask'] = processInputVar('netmask', ARG_STRING);
-	$ret['router'] = processInputVar('router', ARG_STRING);
-	$ret['dns'] = processInputVar('dns', ARG_STRING);
+	$ret['fixedMAC'] = processInputVar('fixedMAC', ARG_STRING, '');
+	$ret['admingroupid'] = processInputVar('admingroupid', ARG_NUMERIC, 0);
+	$ret['logingroupid'] = processInputVar('logingroupid', ARG_NUMERIC, 0);
+	$monitored = processInputVar('monitored', ARG_STRING, '');
+	$ret['fixedIP'] = processInputVar('fixedIP', ARG_STRING, '');
+	$ret['netmask'] = processInputVar('netmask', ARG_STRING, '');
+	$ret['router'] = processInputVar('router', ARG_STRING, '');
+	$ret['dns'] = processInputVar('dns', ARG_STRING, '');
 	$ret['dnsArr'] = array();
 
 	$err = array();
@@ -950,7 +950,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function AJaddGroupToProfile() {
-	$profileid = processInputVar('id', ARG_NUMERIC);
+	$profileid = processInputVar('id', ARG_NUMERIC, 0);
 	$resources = getUserResources(array("serverProfileAdmin"), array("manageGroup"));
 	// check access to profile
 	if(! array_key_exists($profileid, $resources['serverprofile'])) {
@@ -961,7 +961,7 @@
 
 	// check access to groups
 	$groups = getUserResources(array("serverProfileAdmin"), array("manageGroup"), 1);
-	$tmp = processInputVar('listids', ARG_STRING);
+	$tmp = processInputVar('listids', ARG_STRING, '');
 	$tmp = explode(',', $tmp);
 	$groupids = array();
 	foreach($tmp as $id) {
@@ -998,7 +998,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function AJremGroupFromProfile() {
-	$profileid = processInputVar('id', ARG_NUMERIC);
+	$profileid = processInputVar('id', ARG_NUMERIC, 0);
 	$resources = getUserResources(array("serverProfileAdmin"), array("manageGroup"));
 	if(! array_key_exists($profileid, $resources['serverprofile'])) {
 		$arr = array('groups' => array(), 'addrem' => 0);
@@ -1007,7 +1007,7 @@
 	}
 
 	$groups = getUserResources(array("serverProfileAdmin"), array("manageGroup"), 1);
-	$tmp = processInputVar('listids', ARG_STRING);
+	$tmp = processInputVar('listids', ARG_STRING, '');
 	$tmp = explode(',', $tmp);
 	$groupids = array();
 	foreach($tmp as $id) {
@@ -1056,7 +1056,7 @@
 	}
 
 	$resources = getUserResources(array("serverProfileAdmin"), array("manageGroup"));
-	$tmp = processInputVar('listids', ARG_STRING);
+	$tmp = processInputVar('listids', ARG_STRING, '');
 	$tmp = explode(',', $tmp);
 	$profileids = array();
 	foreach($tmp as $id) {
@@ -1102,7 +1102,7 @@
 	}
 
 	$resources = getUserResources(array("serverProfileAdmin"), array("manageGroup"));
-	$tmp = processInputVar('listids', ARG_STRING);
+	$tmp = processInputVar('listids', ARG_STRING, '');
 	$tmp = explode(',', $tmp);
 	$profileids = array();
 	foreach($tmp as $id) {
diff --git a/web/.ht-inc/siteconfig.php b/web/.ht-inc/siteconfig.php
index bda65f2..f77f3fe 100644
--- a/web/.ht-inc/siteconfig.php
+++ b/web/.ht-inc/siteconfig.php
@@ -179,7 +179,7 @@
 		return;
 	}
 	$origval = getContinuationVar('origval');
-	$val = processInputVar('timesource', ARG_STRING);
+	$val = processInputVar('timesource', ARG_STRING, '');
 	$val = preg_replace('/\s+/', '', $val);
 	if($origval != $val) {
 		$servers = explode(',', $val);
@@ -209,6 +209,29 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
+/// \fn fixAffectedRowsRC(&$rc)
+///
+/// \param $rc (pass by reference) - return code to evaluate
+///
+/// \brief checks if $rc is -1, and if so check that a row was successfully
+/// updated and no errors were encountered and change $rc to 1 if that is the
+/// case
+///
+////////////////////////////////////////////////////////////////////////////////
+function fixAffectedRowsRC(&$rc) {
+	global $mysqli_link_vcl;
+	if($rc == -1) {
+		# weird condition where row gets successfully updated and there is no
+		# error, but -1 is returned
+		$errno = mysqli_errno($mysqli_link_vcl);
+		$qinfo = mysqli_info($mysqli_link_vcl);
+		if($errno == 0 && $qinfo == 'Rows matched: 1  Changed: 1  Warnings: 0')
+			$rc = 1;
+	}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
 /// \class TimeVariable
 ///
 /// \brief base class for time related variables related to when vcld takes
@@ -400,7 +423,8 @@
 		if(! array_key_exists($affilid, $affils)) {
 			$arr = array('status' => 'failed',
 			             'msgid' => "{$this->domidbase}msg",
-			             'errmsg' => i('Invalid affiliation submitted.'));
+			             'errmsg' => i('Invalid affiliation submitted.'),
+			             'btn' => "{$this->domidbase}addbtn");
 			sendJSON($arr);
 			return;
 		}
@@ -1070,12 +1094,13 @@
 		if(! array_key_exists($affilid, $affils)) {
 			$arr = array('status' => 'failed',
 			             'msgid' => "{$this->domidbase}msg",
-			             'errmsg' => i('Invalid affiliation submitted.'));
+			             'errmsg' => i('Invalid affiliation submitted.'),
+			             'btn' => "{$this->domidbase}addbtn");
 			sendJSON($arr);
 			return;
 		}
 		$value = processInputVar('value', ARG_STRING);
-		if(! $this->validateValue($value)) {
+		if(is_null($value) || ! $this->validateValue($value)) {
 			$arr = array('status' => 'failed',
 			             'msgid' => "{$this->domidbase}msg",
 			             'errmsg' => i('Invalid value submitted.'),
@@ -1147,9 +1172,9 @@
 			$id = "{$this->domidbase}_$affilid";
 			$newval = processInputVar($id, ARG_STRING);
 			if($newval !== NULL ||
-			   ! $this->allowempty ||
-			   ($affilid == $this->globalid && ! $this->allowglobalempty)) {
-				if(! $this->validateValue($newval)) {
+			   ($newval === NULL && ! $this->allowempty) ||
+			   (($newval === NULL && $affilid == $this->globalid && ! $this->allowglobalempty))) {
+				if($newval === NULL || ! $this->validateValue($newval)) {
 					$affil = getAffiliationName($affilid);
 					$arr = array('status' => 'failed',
 					             'msgid' => "{$this->domidbase}msg",
@@ -1216,7 +1241,7 @@
 		if(! array_key_exists($affilid, $origvals)) {
 			$arr = array('status' => 'failed',
 			             'msgid' => "{$this->domidbase}msg",
-			             'msg' => i('Invalid data submitted.'));
+			             'errmsg' => i('Invalid data submitted.'));
 			sendJSON($arr);
 			return;
 		}
@@ -1322,6 +1347,7 @@
 		       . "WHERE id = $affilid";
 		doQuery($query);
 		$rc = mysqli_affected_rows($mysqli_link_vcl);
+		fixAffectedRowsRC($rc);
 		if($rc == 1)
 			return 1;
 		return 0;
@@ -1345,6 +1371,7 @@
 		       . "WHERE id = $affilid";
 		doQuery($query);
 		$rc = mysqli_affected_rows($mysqli_link_vcl);
+		fixAffectedRowsRC($rc);
 		if($rc == 1)
 			return 1;
 		return 0;
@@ -1370,7 +1397,7 @@
 		parent::__construct();
 		$this->name = i("Site Web Address");
 		$this->desc = i("This is the web address in emails sent by the VCL system to users.");
-		$this->constraints = '^http(s)?://([-A-Za-z0-9]{1,63})(\.[A-Za-z0-9-_]+)*(\.?[A-Za-z0-9])(/[-a-zA-Z0-9\._~&\+,=:@]*)*$';
+		$this->constraints = '^http(s)?://([-A-Za-z0-9]{1,63})(\.[A-Za-z0-9-_]+)*(\.?[A-Za-z0-9])(/[-a-zA-Z0-9\._~&\+,=:@%\?]*)*$';
 		$this->errmsg = i("Invalid web address(es) specified");
 		$this->domidbase = "affilwebaddr";
 		$this->jsname = "affilwebaddr";
@@ -1421,6 +1448,7 @@
 		       . "WHERE id = $affilid";
 		doQuery($query);
 		$rc = mysqli_affected_rows($mysqli_link_vcl);
+		fixAffectedRowsRC($rc);
 		if($rc == 1)
 			return 1;
 		return 0;
@@ -1444,6 +1472,7 @@
 		       . "WHERE id = $affilid";
 		doQuery($query);
 		$rc = mysqli_affected_rows($mysqli_link_vcl);
+		fixAffectedRowsRC($rc);
 		if($rc == 1)
 			return 1;
 		return 0;
@@ -1609,6 +1638,7 @@
 			       .       "affiliationid = $affilid";
 			doQuery($query);
 			$tmp = mysqli_affected_rows($mysqli_link_vcl);
+			fixAffectedRowsRC($tmp);
 			if($rc2)
 				$rc2 = $tmp;
 		}
@@ -1649,6 +1679,17 @@
 		       . "WHERE affiliationid = $affilid";
 		doQuery($query);
 		$rc = mysqli_affected_rows($mysqli_link_vcl);
+		# code to handle mysqli_affected_rows incorrectly returning -1
+		$errno = mysqli_errno($mysqli_link_vcl);
+		if($rc == -1 && $errno == 0) {
+			$query = "SELECT affiliationid FROM winKMS WHERE affiliationid = $affilid";
+			$qh = doQuery($query);
+			if(mysqli_num_rows($qh))
+				return 0;
+			else
+				return 1;
+		}
+		# end -1 handling code
 		if($rc == 1)
 			return 1;
 		return 0;
@@ -1740,6 +1781,7 @@
 		       . "WHERE id = $affilid";
 		doQuery($query);
 		$rc = mysqli_affected_rows($mysqli_link_vcl);
+		fixAffectedRowsRC($rc);
 		if($rc == 1)
 			return 1;
 		return 0;
@@ -1763,6 +1805,7 @@
 		       . "WHERE id = $affilid";
 		doQuery($query);
 		$rc = mysqli_affected_rows($mysqli_link_vcl);
+		fixAffectedRowsRC($rc);
 		if($rc == 1)
 			return 1;
 		return 0;
@@ -1859,6 +1902,7 @@
 		       . "WHERE id = $affilid";
 		doQuery($query);
 		$rc = mysqli_affected_rows($mysqli_link_vcl);
+		fixAffectedRowsRC($rc);
 		if($rc == 1)
 			return 1;
 		return 0;
@@ -1974,6 +2018,7 @@
 		       . "WHERE id = $affilid";
 		doQuery($query);
 		$rc = mysqli_affected_rows($mysqli_link_vcl);
+		fixAffectedRowsRC($rc);
 		if($rc == 1)
 			return 1;
 		return 0;
@@ -1997,6 +2042,7 @@
 		       . "WHERE id = $affilid";
 		doQuery($query);
 		$rc = mysqli_affected_rows($mysqli_link_vcl);
+		fixAffectedRowsRC($rc);
 		if($rc == 1)
 			return 1;
 		return 0;
@@ -2021,6 +2067,7 @@
 	var $defaultval;
 	var $updatemsg;
 	var $type;
+	var $invalidvaluemsg;
 
 	/////////////////////////////////////////////////////////////////////////////
 	///
@@ -2127,7 +2174,7 @@
 				sendJSON($arr);
 				return;
 			case 'textarea':
-				$newval = processInputVar('newval', ARG_STRING); 
+				$newval = processInputVar('newval', ARG_STRING, ''); 
 				if(! $this->validateValue($newval)) {
 					$arr = array('status' => 'failed',
 					             'msgid' => "{$this->domidbase}msg",
@@ -2176,6 +2223,8 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 class userPasswordLength extends GlobalSingleVariable {
+	var $minval;
+	var $maxval;
 	/////////////////////////////////////////////////////////////////////////////
 	///
 	/// \fn __construct()
@@ -2300,6 +2349,13 @@
 	var $deleteCBextra;
 	var $saveCBextra;
 	var $allowduplicates;
+	var $savekeys;
+	var $setkeys;
+	var $addmsg;
+	var $delmsg;
+	var $constraint;
+	var $invalidmsg;
+	var $invalidvaluemsg;
 
 	/////////////////////////////////////////////////////////////////////////////
 	///
@@ -2481,7 +2537,7 @@
 			sendJSON($arr);
 			return;
 		}
-		if(! $this->validateValue($newval)) {
+		if(is_null($newval) || ! $this->validateValue($newval)) {
 			$arr = array('status' => 'failed',
 			             'msgid' => "{$this->domidbase}msg",
 			             'btn' => "{$this->domidbase}addbtn",
@@ -2617,7 +2673,7 @@
 				case 'text':
 				case 'textarea':
 					$newval = processInputVar("{$this->domidbase}|$key", ARG_STRING); 
-					if(! $this->validateValue($newval, $key)) {
+					if(is_null($newval) || ! $this->validateValue($newval, $key)) {
 						$arr = array('status' => 'failed',
 						             'msgid' => "{$this->domidbase}msg",
 						             'btn' => "{$this->domidbase}btn",
@@ -2723,6 +2779,8 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 class NFSmounts extends GlobalMultiVariable {
+	var $invalidmsg;
+	var $invalidvaluemsg;
 	/////////////////////////////////////////////////////////////////////////////
 	///
 	/// \fn __construct()
@@ -2737,13 +2795,15 @@
 		foreach($this->units as $key => $val) {
 			$this->units[$key]['name'] = $val['hostname'];
 		}
-		$vals = getVariablesRegex('^nfsmount\\\|[0-9]+$');
+		$this->setValues();
+		/*$vals = getVariablesRegex('^nfsmount\\\|[0-9]+$');
 		$this->values = array();
 		foreach($vals as $key => $val) {
 			$tmp = explode('|', $key);
 			$id = $tmp[1];
-			$this->values[$id] = $val;
-		}
+			if(isset($this->units[$id]))
+				$this->values[$id] = $val;
+		}*/
 		$formbase = ' &lt;hostname or IP&gt;:&lt;export path&gt;,&lt;mount path&gt;';
 		$this->desc = _("NFS Mounts are NFS exports that are to be mounted within each reservation deployed by a given management node.<br>Values must be like") . $formbase;
 		$this->domidbase = 'nfsmount';
@@ -2768,12 +2828,13 @@
 	///
 	/////////////////////////////////////////////////////////////////////////////
 	function setValues() {
-		$vals = getVariablesRegex('^nfsmount\\\|[0-9]+$');
+		$vals = getVariablesRegex('^nfsmount\|[0-9]+$');
 		$this->values = array();
 		foreach($vals as $key => $val) {
 			$tmp = explode('|', $key);
 			$id = $tmp[1];
-			$this->values[$id] = $val;
+			if(isset($this->units[$id]))
+				$this->values[$id] = $val;
 		}
 	}
 
@@ -2963,7 +3024,7 @@
 			return;
 		}
 		$newval = processInputVar('multival', ARG_STRING);
-		if(! $this->validateValue($newval)) {
+		if(is_null($newval) || ! $this->validateValue($newval)) {
 			$arr = array('status' => 'failed',
 			             'msgid' => "{$this->domidbase}msg",
 			             'btn' => "{$this->domidbase}addbtn",
@@ -3122,9 +3183,9 @@
 		$this->globalopts = $globalopts;
 
 		if($this->globalopts)
-			$data = getVariablesRegex('^(usermessage\\\||adminmessage\\\|)');
+			$data = getVariablesRegex('^(usermessage\||adminmessage\|)');
 		else
-			$data = getVariablesRegex('^usermessage\\\|');
+			$data = getVariablesRegex('^usermessage\|');
 		foreach($data as $key => $item) {
 			# 0 - category, 1 - type, 2 - affil
 			$keyparts = explode('|', $key);
@@ -3278,7 +3339,7 @@
 	////////////////////////////////////////////////////////////////////////////////
 	function AJdeleteMessages() {
 		global $user;
-		$key = processInputVar('key', ARG_STRING);
+		$key = processInputVar('key', ARG_STRING, '');
 		$affilid = processInputVar('affilid', ARG_NUMERIC);
 		$keyparts = explode('|', $key);
 		if(! array_key_exists($key, $this->basekeys) ||
@@ -3315,7 +3376,7 @@
 	////////////////////////////////////////////////////////////////////////////////
 	function AJsaveMessages() {
 		global $user;
-		$key = processInputVar('key', ARG_STRING);
+		$key = processInputVar('key', ARG_STRING, '');
 		$affilid = processInputVar('affilid', ARG_NUMERIC);
 		$subject = processInputVar('subject', ARG_STRING);
 		$body = processInputVar('body', ARG_STRING);
@@ -3335,7 +3396,7 @@
 			sendJSON($arr);
 			return;
 		}
-		if(preg_match('/^\s*$/', $body)) {
+		if(is_null($body) || preg_match('/^\s*$/', $body)) {
 			$arr = array('status' => 'failed',
 			             'msgid' => "messagesmsg",
 			             'btn' => "messagessavebtn",
@@ -3367,7 +3428,7 @@
 		}
 		if($changed) {
 			if(preg_match('/\[.*\]/', $body) ||
-			   preg_match('/\[.*\]/', $shortmsg))
+			   (! is_null($shortmsg) && preg_match('/\[.*\]/', $shortmsg)))
 				setVariable('usermessage_needs_validating', 1, 'none');
 			unset($data['invalidfields']);
 			setVariable($savekey, $data, 'yaml');
diff --git a/web/.ht-inc/sitemaintenance.php b/web/.ht-inc/sitemaintenance.php
index fe833dc..dd80080 100644
--- a/web/.ht-inc/sitemaintenance.php
+++ b/web/.ht-inc/sitemaintenance.php
@@ -453,25 +453,37 @@
 function processSiteMaintenanceInput() {
 	$start = processInputVar('start', ARG_NUMERIC);
 	$end = processInputVar('end', ARG_NUMERIC);
-	$data['hoursahead'] = processInputVar('hoursahead', ARG_NUMERIC);
-	$data['allowreservations'] = processInputVar('allowreservations', ARG_NUMERIC);
-	$data['reason'] = processInputVar('reason', ARG_STRING);
-	$data['usermessage'] = processInputVar('usermessage', ARG_STRING);
+	$data['hoursahead'] = processInputVar('hoursahead', ARG_NUMERIC, 168);
+	$data['allowreservations'] = processInputVar('allowreservations', ARG_NUMERIC, 1);
+	$data['reason'] = processInputVar('reason', ARG_STRING, '');
+	$data['usermessage'] = processInputVar('usermessage', ARG_STRING, '');
 
 	$err = 0;
 
 	$now = time();
-	$data['startdt'] = numdatetimeToDatetime($start . '00');
-	$data['startts'] = datetimeToUnix($data['startdt']);
-	$data['enddt'] = numdatetimeToDatetime($end . '00');
-	$data['endts'] = datetimeToUnix($data['enddt']);
+
+	if(is_null($start) || ! preg_match('/^[0-9]{12}$/', $start)) {
+		$errmsg = 'Invalid start time submitted.';
+		$err = 1;
+	}
+	if(! $err && (is_null($end) || ! preg_match('/^[0-9]{12}$/', $end))) {
+		$errmsg = 'Invalid end time submitted.';
+		$err = 1;
+	}
+
+	if(! $err) {
+		$data['startdt'] = numdatetimeToDatetime($start . '00');
+		$data['startts'] = datetimeToUnix($data['startdt']);
+		$data['enddt'] = numdatetimeToDatetime($end . '00');
+		$data['endts'] = datetimeToUnix($data['enddt']);
+	}
 
 	$reg = "/^[-0-9a-zA-Z\.,\?:;_@!#\(\)\n ]+$/";
-	if(! preg_match($reg, $data['reason'])) {
+	if(! $err && ! preg_match($reg, $data['reason'])) {
 		$errmsg = "Reason can only contain letters, numbers, spaces,\\nand these characters: . , ? : ; - _ @ ! # ( )";
 		$err = 1;
 	}
-	if(! preg_match($reg, $data['usermessage'])) {
+	if(! $err && ! preg_match($reg, $data['usermessage'])) {
 		$errmsg = "User Message can only contain letters, numbers, spaces,\\nand these characters: . , ? : ; - _ @ ! # ( )";
 		$err = 1;
 	}
diff --git a/web/.ht-inc/states.php b/web/.ht-inc/states.php
index 2e7cb06..9ac803e 100644
--- a/web/.ht-inc/states.php
+++ b/web/.ht-inc/states.php
@@ -136,6 +136,7 @@
                         'AJdeleteSiteMaintenance',
                         'AJvalidateUserid',
                         'AJupdateDashboard',
+                        'AJdashboardDetail',
                         'AJgetStatData',
                         'AJgetBlockAllocatedMachineData',
                         'AJpermSelectUserGroup',
@@ -554,9 +555,11 @@
 $actions['mode']['dashboard'] = "dashboard";
 $actions['mode']['AJupdateDashboard'] = "AJupdateDashboard";
 $actions['mode']['AJrestartImageCapture'] = "AJrestartImageCapture";
+$actions['mode']['AJdashboardDetail'] = "AJdashboardDetail";
 $actions['pages']['dashboard'] = "dashboard";
 $actions['pages']['AJupdateDashboard'] = "dashboard";
 $actions['pages']['AJrestartImageCapture'] = "dashboard";
+$actions['pages']['AJdashboardDetail'] = "dashboard";
 
 # site configuration
 $actions['mode']['siteconfig'] = "siteconfig";
diff --git a/web/.ht-inc/statistics.php b/web/.ht-inc/statistics.php
index 9d749fe..c803b1c 100644
--- a/web/.ht-inc/statistics.php
+++ b/web/.ht-inc/statistics.php
@@ -37,7 +37,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function selectStatistics() {
-	global $submitErr, $user;
+	global $submitErr, $user, $locale;
 	list($month1, $day1, $year1) = explode(',', date('n,j,Y', time() - 
 	                                    (SECINDAY * 6)));
 	list($month2, $day2, $year2) = explode(',', date('n,j,Y', time()));
@@ -58,8 +58,10 @@
 		$affilid = $user['affiliationid'];
 	print i("Select a starting date:") . "<br>\n";
 	$months = array('');
+	$df = new IntlDateFormatter($locale, IntlDateFormatter::FULL, IntlDateFormatter::FULL);
+	$df->setPattern('MMMM');
 	for($i = 2 * SECINDAY, $cnt = 1; $cnt < 13; $i += SECINMONTH, $cnt++)
-		$months[$cnt] = strftime('%B', $i);
+		$months[$cnt] = $df->format($i);
 	unset($months[0]);
 	$days = array();
 	for($i = 0; $i < 32; $i++) {
@@ -140,12 +142,12 @@
 	define("1HOUR", 3600);
 	define("2HOURS", 7200);
 	define("4HOURS", 14400);
-	$month1 = processInputVar("month1", ARG_NUMERIC);
-	$day1 = processInputVar("day1", ARG_NUMERIC);
-	$year1 = processInputVar("year1", ARG_NUMERIC);
-	$month2 = processInputVar("month2", ARG_NUMERIC);
-	$day2 = processInputVar("day2", ARG_NUMERIC);
-	$year2 = processInputVar("year2", ARG_NUMERIC);
+	$month1 = (int)processInputVar("month1", ARG_NUMERIC);
+	$day1 = (int)processInputVar("day1", ARG_NUMERIC);
+	$year1 = (int)processInputVar("year1", ARG_NUMERIC);
+	$month2 = (int)processInputVar("month2", ARG_NUMERIC);
+	$day2 = (int)processInputVar("day2", ARG_NUMERIC);
+	$year2 = (int)processInputVar("year2", ARG_NUMERIC);
 	$affilid = processInputVar("affilid", ARG_NUMERIC, $user['affiliationid']);
 	$mode2 = getContinuationVar('mode', 'default');
 	$provid = processInputVar('provid', ARG_NUMERIC, 0);
@@ -197,9 +199,10 @@
 	print "(Times and dates on this page are in " . date('T') . ")<br>\n";
 	print "<H3>";
 	$tmp = mktime(0, 0, 0, $month1, $day1, $year1);
-	$starttime = strftime('%x', $tmp);
+	$df = new IntlDateFormatter($locale, IntlDateFormatter::SHORT, IntlDateFormatter::NONE);
+	$starttime = $df->format($tmp);
 	$tmp = mktime(0, 0, 0, $month2, $day2, $year2);
-	$endtime = strftime('%x', $tmp);
+	$endtime = $df->format($tmp);
 	printf(i("Reservation information between %s and %s:"), $starttime, $endtime);
 	print "</H3>\n";
 	$reloadid = getUserlistID('vclreload@Local');
diff --git a/web/.ht-inc/userpreferences.php b/web/.ht-inc/userpreferences.php
index fcdc6f7..475de3e 100644
--- a/web/.ht-inc/userpreferences.php
+++ b/web/.ht-inc/userpreferences.php
@@ -562,8 +562,6 @@
 		$user['usepublickeys'] = $newval;
 	}
 	if($pubkeyauth == 2 && preg_match('|^[-a-zA-Z0-9\+/ @=\.\n\r]*$|', $pubkeys)) {
-		if(get_magic_quotes_gpc())
-			$pubkeys = stripslashes($pubkeys);
 		$_pubkeys = vcl_mysql_escape_string($pubkeys);
 		$query = "UPDATE user SET sshpublickeys = '$_pubkeys' WHERE id = {$user['id']}";
 		doQuery($query);
@@ -614,6 +612,7 @@
 	   $submitErrMsg[PREFNAMEERR] = i("Preferred name can only be up to 25 characters");
 	}
 	if(! preg_match('/^[a-zA-Z ]*$/', $return["preferredname"])) {
+		$_POST['preferredname'] = preg_replace('/[^a-zA-Z ]/', '', $return['preferredname']);
 	   $submitErr |= PREFNAMEERR;
 	   $submitErrMsg[PREFNAMEERR] = i("Preferred name can only contain letters and spaces");
 	}
@@ -621,11 +620,6 @@
 		$return['newpassword'] = $_POST['newpassword'];
 		$confirmpwd = $_POST['confirmpassword'];
 		$curr = $_POST['currentpassword'];
-		if(get_magic_quotes_gpc()) {
-			$return['newpassword'] = stripslashes($return['newpassword']);
-			$confirmpwd = stripslashes($confirmpwd);
-			$curr = stripslashes($curr);
-		}
 		if(! empty($return['newpassword']) && ! empty($confirmpwd) &&
 		   ! validateLocalAccount($user['unityid'], $curr)) {
 			$submitErr |= LOCALPASSWORDERR;
diff --git a/web/.ht-inc/utils.php b/web/.ht-inc/utils.php
index 21c3304..3032e5a 100644
--- a/web/.ht-inc/utils.php
+++ b/web/.ht-inc/utils.php
@@ -48,6 +48,8 @@
 /// global variable to store if header has been printed
 $printedHTMLheader = 0;
 
+spl_autoload_register('vclAutoLoader');
+
 ////////////////////////////////////////////////////////////////////////////////
 ///
 /// \fn initGlobals()
@@ -142,6 +144,7 @@
 	if(isset($_COOKIE['VCLAUTH']) ||
 	   $mode == 'submitLogin' ||
 	   $mode == 'selectauth' ||
+	   $mode == 'xmlrpccall' ||
 	   $mode == 'main') {
 		// open keys
 		$fp = fopen(".ht-inc/keys.pem", "r");
@@ -357,21 +360,21 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
-/// \fn __autoload($class)
+/// \fn vclAutoLoader($class)
 ///
 /// \param $class - name of a class
 ///
 /// \brief handles loading class implementation file for a specified class
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function __autoload($class) {
+function vclAutoLoader($class) {
 	global $actions;
 	$class = strtolower($class);
+	require_once(".ht-inc/resource.php");
 	if(array_key_exists($class, $actions['classmapping'])) {
 		require_once(".ht-inc/{$actions['classmapping'][$class]}.php");
 		return;
 	}
-	require_once(".ht-inc/resource.php");
 	require_once(".ht-inc/$class.php");
 }
 
@@ -419,8 +422,6 @@
 			exit;
 		}
 		$xmlpass = $_SERVER['HTTP_X_PASS'];
-		if(get_magic_quotes_gpc())
-			$xmlpass = stripslashes($xmlpass);
 		$apiver = processInputData($_SERVER['HTTP_X_APIVERSION'], ARG_NUMERIC, 1);
 		if($apiver == 1) {
 			addLoginLog($xmluser, 'unknown', $user['affilid'], 0);
@@ -833,7 +834,7 @@
 		}
 		else
 			print i("This site is currently in maintenance.") . "<br>\n";
-		$niceend = strftime('%A, %x, %l:%M %P', $end);
+		$niceend = prettyDatetime($end, 1, 0, 1);
 		printf(i("The maintenance is scheduled to end <strong>%s</strong>.") . "<br><br><br>\n", $niceend);
 		printHTMLFooter();
 		exit;
@@ -863,8 +864,8 @@
 				$_SESSION['usersessiondata'] = array();
 				return;
 			}
-			$nicestart = strftime('%A, %x, %l:%M %P', $start);
-			$niceend = strftime('%A, %x, %l:%M %P', datetimeToUnix($item['end']));
+			$nicestart = prettyDatetime($start, 1, 0, 1);
+			$niceend = prettyDatetime($item['end'], 1, 0, 1);
 			print "<div id=\"maintenancenotice\">\n";
 			print "<strong>" . i("NOTICE:") . "</strong> ";
 			print i("This site will be down for maintenance during the following times:") . "<br><br>\n";
@@ -1290,8 +1291,6 @@
 		if(QUERYLOGGING != 0 && (! $nolog) &&
 		   preg_match('/^(UPDATE|INSERT|DELETE)/', $query) &&
 		   strpos($query, 'UPDATE continuations SET expiretime = ') === FALSE) {
-			$logquery = str_replace("'", "\'", $query);
-			$logquery = str_replace('"', '\"', $logquery);
 			if(isset($user['id']))
 				$id = $user['id'];
 			else
@@ -1302,11 +1301,13 @@
 			   .        "mode, "
 			   .        "query) "
 			   . "VALUES "
-			   .        "($id, "
+			   .        "(?, " # $id
 			   .        "NOW(), "
-			   .        "'$mode', "
-			   .        "'$logquery')";
-			mysqli_query($mysqli_link_vcl, $q);
+			   .        "?, " # $mode
+			   .        "?)"; # $logquery
+			$s = mysqli_prepare($mysqli_link_vcl, $q);
+			mysqli_stmt_bind_param($s, 'iss', $id, $mode, $query);
+			mysqli_stmt_execute($s);
 		}
 		for($i = 0; ! ($qh = mysqli_query($mysqli_link_vcl, $query)) && $i < 3; $i++) {
 			if(mysqli_errno($mysqli_link_vcl) == '1213') # DEADLOCK, sleep and retry
@@ -1326,6 +1327,76 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
+/// \fn doPSQuery($query, $paramtypes, $params, $errcode, $db, $nolog)
+///
+/// \param $query - SQL statement
+/// \param $paramtypes - string containing the types of parameters to fill in
+/// for the ?s in the query, ex: 'ssi' for string string integer
+/// \param $params - array of parameters to fill in for the ?s in the query
+/// \param $errcode - error code
+/// \param $db - (optional, defaul=vcl), database to query against
+/// \param $nolog - (optional, defaul=0), don't log to queryLog table
+///
+/// \return $qh - query handle or NULL if problem encountered
+///
+/// \brief performs the query and returns $qh or aborts on error
+///
+////////////////////////////////////////////////////////////////////////////////
+function doPSQuery($query, $paramtypes, $params, $errcode=101, $db="vcl",
+                   $nolog=0) {
+	global $mysqli_link_vcl, $mysqli_link_acct, $user, $mode, $ENABLE_ITECSAUTH;
+	global $totalQueries, $queryTimes, $totalQueryTime;
+	$totalQueries++;
+	if(strlen($paramtypes) != count($params))
+		return NULL;
+	if($db == "vcl") {
+		if(QUERYLOGGING != 0 && (! $nolog) &&
+		   preg_match('/^(UPDATE|INSERT|DELETE)/', $query) &&
+		   strpos($query, 'UPDATE continuations SET expiretime = ') === FALSE) {
+			if(isset($user['id']))
+				$id = $user['id'];
+			else
+				$id = 0;
+			$q = "INSERT INTO querylog "
+			   .        "(userid, "
+			   .        "timestamp, "
+			   .        "mode, "
+			   .        "query) "
+			   . "VALUES "
+			   .        "(?, " # $id
+			   .        "NOW(), "
+			   .        "?, " # $mode
+			   .        "?)"; # $logquery
+			$s = mysqli_prepare($mysqli_link_vcl, $q);
+			mysqli_stmt_bind_param($s, 'iss', $id, $mode, $query);
+			mysqli_stmt_execute($s);
+		}
+		$stmt = mysqli_prepare($mysqli_link_vcl, $query);
+		if(strlen($paramtypes))
+			mysqli_stmt_bind_param($stmt, $paramtypes, ...$params);
+		for($i = 0; ! mysqli_stmt_execute($stmt) && $i < 3; $i++) {
+			if(mysqli_errno($mysqli_link_vcl) == '1213') # DEADLOCK, sleep and retry
+				usleep(50);
+			else
+				abort($errcode, $query);
+		}
+		$qh = mysqli_stmt_get_result($stmt);
+	}
+	elseif($db == "accounts") {
+		if($ENABLE_ITECSAUTH) {
+			$stmt = mysqli_prepare($mysqli_link_acct, $query);
+			mysqli_stmt_bind_param($stmt, $paramtypes, ...$params);
+			mysqli_stmt_execute($stmt);
+			$qh = mysqli_stmt_get_result($stmt) or abort($errcode, $query);
+		}
+		else
+			$qh = NULL;
+	}
+	return $qh;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
 /// \fn dbLastInsertID()
 ///
 /// \return last insert id for $mysqli_link_vcl
@@ -1352,6 +1423,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 function vcl_mysql_escape_string($string) {
 	global $mysqli_link_vcl;
+	if(is_null($string))
+		$string = '';
 	return mysqli_real_escape_string($mysqli_link_vcl, $string);
 }
 
@@ -1753,8 +1826,8 @@
 function getImageNotes($imageid) {
 	if(empty($imageid))
 		$imageid = 0;
-	$query = "SELECT description, "
-	       .        "`usage` "
+	$query = "SELECT COALESCE(description, '') as description, "
+	       .        "COALESCE(`usage`, '') as `usage` "
 	       . "FROM image "
 	       . "WHERE id = $imageid";
 	$qh = doQuery($query, 101);
@@ -4043,6 +4116,8 @@
 		}
 	}
 	else {
+		if(is_null($return))
+			$return = '';
 		$return = strip_tags($return);
 		if($stripwhitespace)
 			$return = trim($return);
@@ -4290,6 +4365,7 @@
 	       .        "u.lastupdated AS lastupdated, "
 	       .        "u.usepublickeys, "
 	       .        "u.sshpublickeys, "
+	       .        "COALESCE(u.sshpublickeys, '') AS sshpublickeys, "
 	       .        "af.shibonly "
 	       . "FROM affiliation af, "
 	       .      "user u "
@@ -5529,7 +5605,7 @@
 	$rc = mysqli_affected_rows($mysqli_link_vcl);
 
 	# check to see if another process allocated this one
-	if($rc) {
+	if($rc > 0) {
 		$query = "SELECT rq.id "
 		       . "FROM request rq, "
 		       .      "reservation rs "
@@ -10054,12 +10130,17 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
-/// \fn prettyDatetime($stamp, $showyear=0, $notzoffset=0)
+/// \fn prettyDatetime($stamp, $showyear=0, $notzoffset=0, $numericdate=0
+///                    $nodayname=0)
 ///
 /// \param $stamp - a timestamp in unix or mysql datetime format
 /// \param $showyear (optional, default=0) - set to 1 to include year
 /// \param $notzoffset (optional, default=0) - set to 1 to prevent timezone
 /// conversion
+/// \param $numericdate (optional, default=0) - set to 1 to use a numeric date
+/// instead of a written out date
+/// \param $nodayname (optional, default=0) - set to 1 to leave off name of day
+/// of week
 ///
 /// \return date/time in html format of [Day of week], [month] [day of month],
 /// [HH:MM] [am/pm]
@@ -10067,17 +10148,28 @@
 /// \brief reformats the datetime to look better
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function prettyDatetime($stamp, $showyear=0, $notzoffset=0) {
+function prettyDatetime($stamp, $showyear=0, $notzoffset=0, $numericdate=0,
+                        $nodayname=0) {
 	global $locale;
 	if(! preg_match('/^[\d]+$/', $stamp))
 		$stamp = datetimeToUnix($stamp);
 	if(! $notzoffset && isset($_SESSION['persistdata']['tzoffset']))
 		$stamp += $_SESSION['persistdata']['tzoffset'] * 60;
+	$dateformatter = IntlDateFormatter::MEDIUM;
+	if($numericdate)
+		$dateformatter = IntlDateFormatter::SHORT;
+	$df = new IntlDateFormatter($locale, $dateformatter, IntlDateFormatter::SHORT);
+	$ptn = $df->getPattern();
+	$dayptn = 'EEEE, ';
+	if($nodayname)
+		$dayptn = '';
 	if($showyear)
-		$return = strftime('%A, %b&nbsp;%-d,&nbsp;%Y, %l:%M %P', $stamp);
-	else
-		$return = strftime('%A, %b&nbsp;%-d, %l:%M %P', $stamp);
-	return $return;
+		$df->setPattern("{$dayptn}$ptn z"); #Tuesday, May 2, 2023, 11:56 AM EDT
+	else {
+		$ptn = preg_replace('|[/ ]?y[,/]?|', '', $ptn);
+		$df->setPattern("{$dayptn}$ptn z"); #Tuesday, May 2, 11:56 AM EDT
+	}
+	return $df->format($stamp);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -10106,6 +10198,36 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
+/// \fn minToDaysHourMin($min)
+///
+/// \param $min - minutes
+///
+/// \return a string value
+///
+/// \brief um, I don't know how to describe this, just look at the code
+///
+////////////////////////////////////////////////////////////////////////////////
+function minToDaysHourMin($min) {
+	if($min < 60)
+		return $min . " " . i("minutes");
+	elseif($min < 2880) {
+		if($min == 60)
+			return i("1 hour");
+		elseif($min % 60 == 0)
+			return sprintf("%d " . i("hours"), $min / 60);
+		elseif($min % 30 == 0)
+			return sprintf("%.1f " . i("hours"), $min / 60);
+		else
+			return sprintf("%.2f " . i("hours"), $min / 60);
+	}
+	elseif($min < 64800)
+		return sprintf("%d " . i("days"), $min / 1440);
+	else
+		return sprintf("%d " . i("weeks"), $min / 10080);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
 /// \fn secToMinSec($sec)
 ///
 /// \param $sec - seconds
@@ -10157,6 +10279,74 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
+/// \fn htmlwrap($str, $linelen)
+///
+/// \param $str - string to be wrapped
+/// \param $linelen - max length of each line
+///
+/// \brief breaks $str up into multiple lines no longer than $linelen with each
+/// line ending with a break tag (<br/>)
+///
+////////////////////////////////////////////////////////////////////////////////
+function htmlwrap($str, $linelen) {
+	$str = str_replace('<br>', '<br/>', $str);
+	$str = str_replace('<br />', '<br/>', $str);
+	$word = '';
+	$nextstr = '';
+	$curlen = 0;
+	$strlen = strlen($str);
+	$wrapped = '';
+	$intag = 0;
+	for($i = 0; $i < $strlen; $i++) {
+		$nextstr .= $str[$i];
+		if($str[$i] == '<') {
+			$intag = 1;
+			continue;
+		}
+		elseif($str[$i] == '>') {
+			$intag = 0;
+			if($i > 4 && substr($nextstr, -5, 5) == '<br/>') {
+				if(strlen($nextstr)) {
+					if($curlen <= $linelen) {
+						$wrapped .= $nextstr;
+					}
+					else {
+						$wrapped .= "<br/>$nextstr";
+					}
+					$word = '';
+					$nextstr = '';
+				}
+				$curlen = 0;
+			}
+			continue;
+		}
+		if(! $intag) {
+			$curlen++;
+			$word .= $str[$i];
+			if($str[$i] == ' ') {
+				if($curlen <= $linelen) {
+					$wrapped .= $nextstr;
+				}
+				else {
+					$wrapped .= "<br/>$nextstr";
+					$curlen = strlen($word);
+				}
+				$word = '';
+				$nextstr = '';
+			}
+		}
+	}
+	if($curlen <= $linelen) {
+		$wrapped .= $nextstr;
+	}
+	else {
+		$wrapped .= "<br/>$nextstr";
+	}
+	return $wrapped;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
 /// \fn AJsetTZoffset()
 ///
 /// \brief sets tzoffset in persistdata array in session
@@ -10348,6 +10538,8 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function getUserGroupName($id, $incAffil=0) {
+	if(! is_numeric($id))
+		return 0;
 	if($incAffil) {
 		$query = "SELECT CONCAT(u.name, '@', a.name) as name "
 		       . "FROM usergroup u, "
@@ -10603,7 +10795,7 @@
 		$userid =  $matches[1];
 	else
 		$userid = $user["unityid"];
-	if($request['reservations'][0]['domainDNSName'] != '' && ! strlen($passwd))
+	if($request['reservations'][0]['domainDNSName'] != '' && (is_null($passwd) || ! strlen($passwd)) && $request['reservations'][0]['OStype'] == 'windows')
 		$userid .= "@" . $request['reservations'][0]['domainDNSName'];
 	elseif($request['reservations'][0]['OStype'] == 'windows')
 		$userid = ".\\$userid";
@@ -10958,6 +11150,8 @@
 
 	$allgroups = getUserGroups();
 	foreach($groupids as $id) {
+		if(! isset($allgroups[$id]))
+			continue;
 		if($return["initial"] < $allgroups[$id]["initialmaxtime"])
 			$return["initial"] = $allgroups[$id]["initialmaxtime"];
 		if($return["total"] < $allgroups[$id]["totalmaxtime"])
@@ -12015,7 +12209,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 function cleanSemaphore() {
 	global $mysqli_link_vcl, $uniqid;
-	if(! is_resource($mysqli_link_vcl) || ! get_resource_type($mysqli_link_vcl) == 'mysql link')
+	if(! is_object($mysqli_link_vcl) || get_class($mysqli_link_vcl) != 'mysqli')
 		return;
 	$query = "DELETE FROM semaphore "
 	       . "WHERE procid = '$uniqid'";
@@ -12450,8 +12644,8 @@
 	       .        "timestamp, ";
 	$query .=       "value ";
 	$query .= "FROM variable "
-	       .  "WHERE name = '$key'";
-	$qh = doQuery($query);
+	       .  "WHERE name = ?"; # $key
+	$qh = doPSQuery($query, 's', array($key));
 	if($row = mysqli_fetch_assoc($qh)) {
 		if($incparams) {
 			switch($row['serialization']) {
@@ -12500,8 +12694,8 @@
 	       .        "serialization, "
 	       .        "value "
 	       . "FROM variable "
-	       . "WHERE name REGEXP '$pattern'";
-	$qh = doQuery($query);
+	       . "WHERE name REGEXP ?"; # $pattern
+	$qh = doPSQuery($query, 's', array($pattern));
 	$ret = array();
 	while($row = mysqli_fetch_assoc($qh)) {
 		switch($row['serialization']) {
@@ -12537,8 +12731,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 function setVariable($key, $data, $serialization='') {
 	$update = 0;
-	$query = "SELECT serialization FROM variable WHERE name = '$key'";
-	$qh = doQuery($query);
+	$query = "SELECT serialization FROM variable WHERE name = ?"; # $key
+	$qh = doPSQuery($query, 's', array($key));
 	if($row = mysqli_fetch_assoc($qh)) {
 		if($serialization == '')
 			$serialization = $row['serialization'];
@@ -12549,37 +12743,37 @@
 	$_SESSION['variables'][$key] = $data;
 	switch($serialization) {
 		case 'none':
-			$qdata = vcl_mysql_escape_string($data);
+			$qdata = $data;
 			break;
 		case 'yaml':
-			$yaml = Spyc::YAMLDump($data);
-			$qdata = vcl_mysql_escape_string($yaml);
+			$qdata = Spyc::YAMLDump($data);
 			break;
 		case 'phpserialize':
-			$qdata = vcl_mysql_escape_string(serialize($data));
+			$qdata = serialize($data);
 			break;
 	}
 	if($update)
 		$query = "UPDATE variable "
-		       . "SET value = '$qdata', "
-		       .     "serialization = '$serialization', "
+		       . "SET serialization = ?, " # $serialization
+		       .     "value = ?, " # $qdata
 		       .     "setby = 'webcode', "
 		       .     "timestamp = NOW() "
-		       . "WHERE name = '$key'";
+		       . "WHERE name = ?"; # $key
 	else
 		$query = "INSERT INTO variable "
-		       .        "(name, "
-		       .        "serialization, "
+		       .        "(serialization, "
 		       .        "value, "
+		       .        "name, "
 		       .        "setby, "
 		       .        "timestamp) "
 		       . "VALUES "
-		       .        "('$key', "
-		       .        "'$serialization', "
-		       .        "'$qdata', "
+		       .        "(?, " # $serialization
+		       .        "?, " # $qdata
+		       .        "?, " # $key
 		       .        "'webcode', "
 		       .        "NOW())";
-	doQuery($query);
+	$params = array($serialization, $qdata, $key);
+	doPSQuery($query, 'sss', $params);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -13763,6 +13957,7 @@
 			$filename = 'vclDashboard.js';
 			$dojoRequires = array('dojo.parser',
 			                      'dijit.Tooltip',
+			                      'dijit.Dialog',
 			                      'dijit.form.Button',
 			                      'dojox.charting.widget.Chart2D',
 			                      'dojox.charting.action2d.Tooltip',
@@ -14439,7 +14634,8 @@
 		if(! file_exists("{$dir}/language"))
 			continue;
 		$fh = fopen("{$dir}/language", 'r');
-		while($line = fgetss($fh)) {
+		while($line = fgets($fh)) {
+			$line = strip_tags($line);
 			if(preg_match('/(^#)|(^\s*$)/', $line)) {
 				continue;
 			}
diff --git a/web/.ht-inc/vm.php b/web/.ht-inc/vm.php
index df10b43..d351cf0 100644
--- a/web/.ht-inc/vm.php
+++ b/web/.ht-inc/vm.php
@@ -354,7 +354,7 @@
 	$data = getVMHostData($vmhostid);
 
 	$resources = getUserResources(array("computerAdmin"), array("administer"));
-	if(! array_key_exists($data[$vmhostid]['computerid'], $resources['computer'])) {
+	if(is_null($vmhostid) || ! array_key_exists($data[$vmhostid]['computerid'], $resources['computer'])) {
 		sendJSON(array('failed' => 'noaccess'));
 		return;
 	}
@@ -505,7 +505,7 @@
 	
 	$hostdata = getVMHostData($hostid);
 	$resources = getUserResources(array("computerAdmin"), array("administer"));
-	if(! array_key_exists($hostdata[$hostid]['computerid'], $resources['computer'])) {
+	if(is_null($hostid) || ! array_key_exists($hostdata[$hostid]['computerid'], $resources['computer'])) {
 		sendJSON(array('failed' => 'nohostaccess'));
 		return;
 	}
@@ -514,7 +514,7 @@
 	$fails = array();
 
 	$vmlistids = processInputVar('listids', ARG_STRING);
-	if(! preg_match('/^(\d+)(,\d+)*$/', $vmlistids)) {
+	if(is_null($vmlistids) || ! preg_match('/^(\d+)(,\d+)*$/', $vmlistids)) {
 		sendJSON(array('failed' => 'invaliddata'));
 		return;
 	}
@@ -578,14 +578,14 @@
 	
 	$hostdata = getVMHostData($hostid);
 	$resources = getUserResources(array("computerAdmin"), array("administer"));
-	if(! array_key_exists($hostdata[$hostid]['computerid'], $resources['computer'])) {
+	if(is_null($hostid) || ! array_key_exists($hostdata[$hostid]['computerid'], $resources['computer'])) {
 		sendJSON(array('failed' => 'nohostaccess'));
 		return;
 	}
 
 	$fails = array();
 	$vmlistids = processInputVar('listids', ARG_STRING);
-	if(! preg_match('/^(\d+)(,\d+)*$/', $vmlistids)) {
+	if(is_null($vmlistids) || ! preg_match('/^(\d+)(,\d+)*$/', $vmlistids)) {
 		sendJSON(array('failed' => 'invaliddata'));
 		return;
 	}
@@ -717,14 +717,14 @@
 	
 	$hostdata = getVMHostData($hostid);
 	$resources = getUserResources(array("computerAdmin"), array("administer"));
-	if(! array_key_exists($hostdata[$hostid]['computerid'], $resources['computer'])) {
+	if(is_null($hostid) || ! array_key_exists($hostdata[$hostid]['computerid'], $resources['computer'])) {
 		sendJSON(array('failed' => 'nohostaccess'));
 		return;
 	}
 
 	$fails = array();
 	$requestids = processInputVar('listids', ARG_STRING);
-	if(! preg_match('/^(\d+)(,\d+)*$/', $requestids)) {
+	if(is_null($requestids) || ! preg_match('/^(\d+)(,\d+)*$/', $requestids)) {
 		sendJSON(array('failed' => 'invaliddata'));
 		return;
 	}
@@ -774,11 +774,11 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function AJprofileData($profileid="") {
-	if(! checkUserHasPerm('Manage VM Profiles')) {
+	$profileid = processInputVar('profileid', ARG_NUMERIC, $profileid);
+	if(empty($profileid) || ! checkUserHasPerm('Manage VM Profiles')) {
 		sendJSON(array('failed' => 'noaccess'));
 		return;
 	}
-	$profileid = processInputVar('profileid', ARG_NUMERIC, $profileid);
 	$profiledata = getVMProfiles($profileid);
 	foreach($profiledata[$profileid] AS $key => $value) {
 		if(is_null($value))
@@ -819,7 +819,11 @@
 		return;
 	}
 	$profileid = processInputVar('profileid', ARG_NUMERIC);
-	$item = processInputVar('item', ARG_STRING);
+	if(empty($profileid) || ! checkUserHasPerm('Manage VM Profiles')) {
+		print "alert('Invalid data submitted.');";
+		return;
+	}
+	$item = processInputVar('item', ARG_STRING, '');
 	if(! preg_match('/^(profilename|imageid|resourcepath|folderpath|repositorypath|repositoryimagetypeid|datastorepath|datastoreimagetypeid|vmdisk|vmpath|virtualswitch[0-3]|username|password|eth0generated|eth1generated)$/', $item)) {
 		print "alert('Invalid data submitted.');";
 		return;
@@ -841,15 +845,26 @@
 		if(! in_array($newvalue, $vmdisks))
 			$newvalue = $vmdisks[0];
 	}
-	elseif($item == 'password')
-		$newvalue = $_POST['newvalue'];
+	elseif($item == 'password') {
+		if(isset($_POST['newvalue']))
+			$newvalue = $_POST['newvalue'];
+		else
+			$newvalue = '';
+	}
+	elseif($item == 'profilename') {
+		$newvalue = processInputVar('newvalue', ARG_STRING);
+		if(empty($newvalue) || ! preg_match('/^[-a-zA-Z0-9 \.\(\),@#_\+:;]$/', $newvalue)) {
+			$profile = getVMProfiles($profileid);
+			print "alert('Invalid value submitted for Name');";
+			print "dijit.byId('pname').set('value', '{$profile[$profileid]['name']}');";
+			return;
+		}
+	}
 	else
 		$newvalue = processInputVar('newvalue', ARG_STRING);
-	if($newvalue == '')
+	if(empty($newvalue))
 		$newvalue2 = 'NULL';
 	else {
-		if(get_magic_quotes_gpc())
-			$newvalue = stripslashes($newvalue);
 		$newvalue2 = vcl_mysql_escape_string($newvalue);
 		$newvalue2 = "'$newvalue2'";
 	}
@@ -940,7 +955,8 @@
 	       . "SET `$item` = $newvalue2 "
 	       . "WHERE id = $profileid";
 	doQuery($query, 101);
-	$newvalue = preg_replace("/'/", "\\'", $newvalue);
+	if(! is_null($newvalue))
+		$newvalue = preg_replace("/'/", "\\'", $newvalue);
 	print "curprofile.$item = '$newvalue';";
 }
 
@@ -954,13 +970,17 @@
 ////////////////////////////////////////////////////////////////////////////////
 function AJnewProfile() {
 	$newprofile = processInputVar('newname', ARG_STRING);
-	if(get_magic_quotes_gpc())
-		$newprofile = stripslashes($newprofile);
+	if(empty($newprofile) || ! preg_match('/^[-a-zA-Z0-9 \.\(\),@#_\+:;]$/', $newprofile)) {
+		sendJSON(array('failed' => 'invalid',
+		               'errmsg' => 'Invalid name submitted for new profile.'));
+		return;
+	}
 	$newprofile = vcl_mysql_escape_string($newprofile);
 	$query = "SELECT id FROM vmprofile WHERE profilename = '$newprofile'";
 	$qh = doQuery($query, 101);
 	if($row = mysqli_fetch_assoc($qh)) {
-		sendJSON(array('failed' => 'exists'));
+		sendJSON(array('failed' => 'exists',
+		               'errmsg' => 'A profile with this name already exists.'));
 		return;
 	}
 	$imageid = getImageId('noimage');
@@ -992,6 +1012,10 @@
 		return;
 	}
 	$profileid = processInputVar('profileid', ARG_NUMERIC);
+	if(empty($profileid)) {
+		sendJSON(array('failed' => 'noaccess'));
+		return;
+	}
 	# check to see if profile is in use
 	$query = "SELECT vh.computerid, "
 	       .        "s.name "
diff --git a/web/.ht-inc/xmlrpcWrappers.php b/web/.ht-inc/xmlrpcWrappers.php
index 750000e..5a1605b 100644
--- a/web/.ht-inc/xmlrpcWrappers.php
+++ b/web/.ht-inc/xmlrpcWrappers.php
@@ -98,7 +98,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCtest($string) {
-	$string = processInputData($string, ARG_STRING);
+	$string = processInputData($string, ARG_STRING, 0, '');
 	return array('status' => 'success',
 	             'message' => 'RPC call worked successfully',
 	             'string' => $string);
@@ -168,7 +168,7 @@
 	global $user;
 	$imageid = processInputData($imageid, ARG_NUMERIC);
 	$start = processInputData($start, ARG_STRING, 1);
-	$length = processInputData($length, ARG_NUMERIC);
+	$length = processInputData($length, ARG_NUMERIC, 0, 60);
 	#$foruser = processInputData($foruser, ARG_STRING, 1);
 
 	// make sure user didn't submit a request for an image he
@@ -425,9 +425,7 @@
 		             'errormsg' => "access denied to $imageid");
 	}
 	if($admingroup != '') {
-		$admingroup = processInputData($admingroup, ARG_STRING);
-		if(get_magic_quotes_gpc())
-			$admingroup = stripslashes($admingroup);
+		$admingroup = processInputData($admingroup, ARG_STRING, 0, '');
 		if(preg_match('/@/', $admingroup)) {
 			$tmp = explode('@', $admingroup);
 			$escadmingroup = vcl_mysql_escape_string($tmp[0]);
@@ -452,9 +450,7 @@
 	else
 		$admingroupid = '';
 	if($logingroup != '') {
-		$logingroup = processInputData($logingroup, ARG_STRING);
-		if(get_magic_quotes_gpc())
-			$logingroup = stripslashes($logingroup);
+		$logingroup = processInputData($logingroup, ARG_STRING, 0, '');
 		if(preg_match('/@/', $logingroup)) {
 			$tmp = explode('@', $logingroup);
 			$esclogingroup = vcl_mysql_escape_string($tmp[0]);
@@ -478,7 +474,7 @@
 	}
 	else
 		$logingroupid = '';
-	$ipaddr = processInputData($ipaddr, ARG_STRING);
+	$ipaddr = processInputData($ipaddr, ARG_STRING, 0, '');
 	$ipaddrArr = explode('.', $ipaddr);
 	if($ipaddr != '' && (! preg_match('/^(([0-9]){1,3}\.){3}([0-9]){1,3}$/', $ipaddr) ||
 		$ipaddrArr[0] < 1 || $ipaddrArr[0] > 255 ||
@@ -490,7 +486,7 @@
 		             'errormsg' => "Invalid IP address. Must be w.x.y.z with each of "
 		                         . "w, x, y, and z being between 1 and 255 (inclusive)");
 	}
-	$macaddr = processInputData($macaddr, ARG_STRING);
+	$macaddr = processInputData($macaddr, ARG_STRING, 0, '');
 	if($macaddr != '' && ! preg_match('/^(([A-Fa-f0-9]){2}:){5}([A-Fa-f0-9]){2}$/', $macaddr)) {
 		return array('status' => 'error',
 		             'errorcode' => 58,
@@ -504,9 +500,7 @@
 	$end = processInputData($end, ARG_STRING, 1);
 	#$foruser = processInputData($foruser, ARG_STRING, 1);
 
-	$name = processInputData($name, ARG_STRING);
-	if(get_magic_quotes_gpc())
-		$name = stripslashes($name);
+	$name = processInputData($name, ARG_STRING, 0, '');
 	if(! preg_match('/^([-a-zA-Z0-9_\. ]){0,255}$/', $name)) {
 		return array('status' => 'error',
 		             'errorcode' => 58,
@@ -572,8 +566,6 @@
 	       . "WHERE requestid = {$return['requestid']}";
 	doQuery($query);
 	if($userdata != '') {
-		if(get_magic_quotes_gpc())
-			$userdata = stripslashes($userdata);
 		$esc_userdata = vcl_mysql_escape_string($userdata);
 		$query = "INSERT INTO variable "
 		       .        "(name, "
@@ -806,7 +798,7 @@
 function XMLRPCgetRequestConnectData($requestid, $remoteIP) {
 	global $user;
 	$requestid = processInputData($requestid, ARG_NUMERIC);
-	$remoteIP = processInputData($remoteIP, ARG_STRING, 1);
+	$remoteIP = processInputData($remoteIP, ARG_STRING, 0, '');
 	if(! preg_match('/^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/', $remoteIP, $matches) ||
 	   $matches[1] < 1 || $matches[1] > 223 ||
 	   $matches[2] > 255 ||
@@ -921,7 +913,7 @@
 function XMLRPCextendRequest($requestid, $extendtime) {
 	global $user;
 	$requestid = processInputData($requestid, ARG_NUMERIC);
-	$extendtime = processInputData($extendtime, ARG_NUMERIC);
+	$extendtime = processInputData($extendtime, ARG_NUMERIC, 0, 0);
 
 	$userRequests = getUserRequests('all', $user['id']);
 	$found = 0;
@@ -1130,7 +1122,7 @@
 		             'errormsg' => "access denied to specify end time");
 	}
 
-	$end = processInputData($end, ARG_NUMERIC);
+	$end = processInputData($end, ARG_NUMERIC, 0, 0);
 
 	$maxend = datetimeToUnix("2038-01-01 00:00:00");
 	if($end < 0 || $end > $maxend) {
@@ -1185,7 +1177,7 @@
 	if($timeToNext > -1) {
 		$lockedall = 1;
 		if(count($request['reservations']) > 1) {
-			# get semaphore on each existing node in cluster so that nothing 
+			# get semaphore on each existing node in cluster so that nothing
 			# can get moved to the nodes during this process
 			$unixend = datetimeToUnix($request['end']);
 			$checkend = unixToDatetime($unixend + 900);
@@ -1770,8 +1762,6 @@
 	if(in_array("userGrant", $user["privileges"]) ||
 		in_array("resourceGrant", $user["privileges"]) ||
 		in_array("nodeAdmin", $user["privileges"])) {
-		if(get_magic_quotes_gpc())
-			$nodeName = stripslashes($nodeName);
 		$nodeName = vcl_mysql_escape_string($nodeName);
 		// does a node with this name already exist?
 		$query = "SELECT id "
@@ -2620,8 +2610,6 @@
 	#   are valid
 	$validate = array('name' => $name,
 	                  'affiliation' => $affiliation);
-	if(get_magic_quotes_gpc())
-		$newOwner = stripslashes($newOwner);
 	if(! empty($newOwner))
 		$validate['owner'] = $newOwner;
 	if(! empty($newManagingGroup))
@@ -2672,8 +2660,6 @@
 		$validate = array('name' => $name,
 		                  'affiliation' => $affiliation);
 		if(! empty($newName)) {
-			if(get_magic_quotes_gpc())
-				$newName = stripslashes($newName);
 			$validate['name'] = $newName;
 			$tmp = vcl_mysql_escape_string($newName);
 			$updates[] = "name = '$tmp'";
@@ -2940,8 +2926,6 @@
 	foreach($users as $_user) {
 		if(empty($_user))
 			continue;
-		if(get_magic_quotes_gpc())
-			$_user = stripslashes($_user);
 		$esc_user = vcl_mysql_escape_string($_user);
 		if(validateUserid($_user) == 1)
 			addUserGroupMember($esc_user, $rc['id']);
@@ -3022,8 +3006,6 @@
 	foreach($users as $_user) {
 		if(empty($_user))
 			continue;
-		if(get_magic_quotes_gpc())
-			$_user = stripslashes($_user);
 		$esc_user = vcl_mysql_escape_string($_user);
 		# check that affiliation of user can be determined because getUserlistID
 		#   will abort if it cannot find it
@@ -3128,8 +3110,6 @@
 			             'errorcode' => 76,
 			             'errormsg' => 'resource group already exists');
 		}
-		if(get_magic_quotes_gpc())
-			$name = stripslashes($name);
 		if(! preg_match('/^[-a-zA-Z0-9_\. ]{3,30}$/', $name)) {
 			return array('status' => 'error',
 			             'errorcode' => 87,
@@ -3935,7 +3915,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCgetOneClickParams($oneclickid) {
 	global $user;
-	$oneclickid = processInputData($oneclickid, ARG_NUMERIC);
+	$oneclickid = processInputData($oneclickid, ARG_NUMERIC, 0, 0);
 	$query = "SELECT o.id, "
 	       .        "o.userid, "
 	       .        "o.imageid, "
@@ -4073,8 +4053,8 @@
 	global $user;
 	$userid = $user['id'];
 	$imageid = processInputData($imageid, ARG_NUMERIC);
-	$name = processInputData($name, ARG_STRING);
-	$duration = processInputData($duration, ARG_NUMERIC);
+	$name = processInputData($name, ARG_STRING, 0, '');
+	$duration = processInputData($duration, ARG_NUMERIC, 0, 120);
 	$autologin = processInputData($autologin, ARG_NUMERIC) == 1 ? 1 : 0;
 
 	# validate $imageid
@@ -4163,10 +4143,10 @@
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCeditOneClick($oneclickid, $name, $imageid, $duration, $autologin) {
 	global $user;
-	$oneclickid = processInputData($oneclickid, ARG_NUMERIC);
+	$oneclickid = processInputData($oneclickid, ARG_NUMERIC, 0, 0);
 	$imageid = processInputData($imageid, ARG_NUMERIC);
-	$name = processInputData($name, ARG_STRING);
-	$duration = processInputData($duration, ARG_NUMERIC);
+	$name = processInputData($name, ARG_STRING, 0, '');
+	$duration = processInputData($duration, ARG_NUMERIC, 0, 120);
 	$autologin = processInputData($autologin, ARG_NUMERIC) == 1 ? 1 : 0;
 
 	# validate $imageid
@@ -4254,7 +4234,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCdeleteOneClick($oneclickid) {
 	global $user;
-	$oneclickid = processInputData($oneclickid, ARG_NUMERIC);
+	$oneclickid = processInputData($oneclickid, ARG_NUMERIC, 0, 0);
 
 	$query = "SELECT id "
 	       . "FROM oneclick "
diff --git a/web/css/dashboard.css b/web/css/dashboard.css
index c592364..5c1ae0b 100644
--- a/web/css/dashboard.css
+++ b/web/css/dashboard.css
@@ -18,7 +18,8 @@
 	padding-right: 10px;
 }
 
-#dashboard table td {
+#dashboard table td,
+#detailcontent table td {
 	padding-left: 5px;
 }
 
@@ -45,3 +46,20 @@
 	margin-top: 0px;
 	margin-bottom: 2px;
 }
+
+.dashwidget h3 a {
+	background: #0053fb;
+	color: white;
+	margin-top: 0px;
+	margin-bottom: 2px;
+}
+
+.dashwidget h3 a:hover {
+	background: black;
+	color: white;
+	margin-top: 0px;
+	margin-bottom: 2px;
+	text-decoration: none;
+	cursor: pointer;
+}
+
diff --git a/web/images/copy_icon.png b/web/images/copy_icon.png
new file mode 100755
index 0000000..8f397a9
--- /dev/null
+++ b/web/images/copy_icon.png
Binary files differ
diff --git a/web/js/dashboard.js b/web/js/dashboard.js
index 0591c5c..582825a 100644
--- a/web/js/dashboard.js
+++ b/web/js/dashboard.js
@@ -35,6 +35,7 @@
 	updateTopImages(data.items.topimages);
 	updateTopLongImages(data.items.toplongimages);
 	updateTopPastImages(data.items.toppastimages);
+	updateTopPast6MonthImages(data.items.toppast6moimages);
 	updateTopFailed(data.items.topfailed);
 	updateTopFailedComputers(data.items.topfailedcomputers);
 	updateResChart(data.items.reschart);
@@ -134,6 +135,31 @@
 	obj.innerHTML = txt;
 }
 
+function updateTopPast6MonthImages(data) {
+	if('items' in data && 'divid' in data.items) {
+	    var obj = dojo.byId(data.items.divid);
+	    dojo.byId('detailtitle').innerHTML = data.items.title;
+		data = data.items.result;
+	}
+	else {
+		var obj = dojo.byId('toppast6moimages');
+	}
+	console.log("data length: " + data.length);
+	if(data.length == 0) {
+		obj.innerHTML = 'No recent reservations';
+		return;
+	}
+	var txt = '<table>';
+	for(var i = 0; i < data.length; i++) {
+		txt += '<tr><th align="right">'
+			+ data[i].prettyname
+			+ '</th><td>'
+			+ data[i].count
+			+ '</td></tr>';
+	}
+	txt += '</table>';
+	obj.innerHTML = txt;
+}
 function updateTopFailed(data) {
 	var obj = dojo.byId('topfailed');
 	if(data.length == 0) {
@@ -372,3 +398,20 @@
 	var min = parseInt((time - (hour * 3600)) / 60);
 	return dojox.string.sprintf('%d:%02d hour(s)', hour, min);
 }
+
+function cancelDetail() {
+    dijit.byId('detaildialog').hide();
+}
+
+function showdetail(id) {
+	var data = {
+		id: id,
+		continuation: dojo.byId('detailcont').value
+	};
+	RPCwrapper(data, showDetailCB, 1);
+}
+
+function showDetailCB(data, ioArgs) {
+	updateTopPast6MonthImages(data);
+	dijit.byId('detaildialog').show();
+}
diff --git a/web/js/resources.js b/web/js/resources.js
index aa0dd5f..6a15e61 100644
--- a/web/js/resources.js
+++ b/web/js/resources.js
@@ -116,6 +116,9 @@
 	else if(data.items.status == 'noaccess') {
 		alert(_('You do not have access to the submitted resource or group'));
 	}
+	else if(data.items.status == 'invalid') {
+		alert(_('Invalid value submitted'));
+	}
 	document.body.style.cursor = 'default';
 }
 
diff --git a/web/themes/dropdownmenus/css/theme.css b/web/themes/dropdownmenus/css/theme.css
index be025f7..3b68286 100644
--- a/web/themes/dropdownmenus/css/theme.css
+++ b/web/themes/dropdownmenus/css/theme.css
@@ -380,9 +380,15 @@
 #addResourceGroupPane td.privCascade:hover {
 	background-color: #008000 !important;
 }
-#content div.dashwidget h3 {
+#content div.dashwidget h3,
+#content div.dashwidget h3 a {
 	background-color: #ed1c24;
 }
+#content div.dashwidget h3 a:hover {
+	background-color: black;
+	color: white;
+	cursor: pointer;
+}
 a:hover, a:active {
   text-decoration: underline;
 }