You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by jf...@apache.org on 2013/02/06 21:47:11 UTC

svn commit: r1443205 [2/2] - in /vcl/branches/vcl-2.3-bugfixes/web/.ht-inc: groups.php privileges.php utils.php xmlrpcWrappers.php

Modified: vcl/branches/vcl-2.3-bugfixes/web/.ht-inc/xmlrpcWrappers.php
URL: http://svn.apache.org/viewvc/vcl/branches/vcl-2.3-bugfixes/web/.ht-inc/xmlrpcWrappers.php?rev=1443205&r1=1443204&r2=1443205&view=diff
==============================================================================
--- vcl/branches/vcl-2.3-bugfixes/web/.ht-inc/xmlrpcWrappers.php (original)
+++ vcl/branches/vcl-2.3-bugfixes/web/.ht-inc/xmlrpcWrappers.php Wed Feb  6 20:47:10 2013
@@ -69,7 +69,7 @@
 ///
 /// \brief gets all of the affilations for which users can log in to VCL\n
 /// \b NOTE: This is the only function available for which the X-User and X-Pass
-/// HTTP headers do not need to be passed\n
+/// HTTP headers do not need to be passed
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCaffiliations() {
@@ -90,7 +90,7 @@ function XMLRPCaffiliations() {
 /// \b id - id of the image\n
 /// \b name - name of the image
 ///
-/// \brief gets the images to which the user has access\n
+/// \brief gets the images to which the user has access
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCgetImages() {
@@ -98,11 +98,11 @@ function XMLRPCgetImages() {
 	$resources["image"] = removeNoCheckout($resources["image"]);
 	$return = array();
 	foreach($resources['image'] as $key => $val) {
-        $notes = getImageNotes($key);
-        $tmp = array('id' => $key,
-                     'name' => $val,
-                     'description' => $notes['description'],
-                     'usage' => $notes['usage']);
+		$notes = getImageNotes($key);
+		$tmp = array('id' => $key,
+		             'name' => $val,
+		             'description' => $notes['description'],
+		             'usage' => $notes['usage']);
 		array_push($return, $tmp);
 	}
 	return $return;
@@ -132,7 +132,7 @@ function XMLRPCgetImages() {
 /// \li \b requestid - identifier that should be passed to later calls when
 /// acting on the request
 ///
-/// \brief tries to make a request\n
+/// \brief tries to make a request
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCaddRequest($imageid, $start, $length, $foruser='') {
@@ -228,7 +228,7 @@ function XMLRPCaddRequest($imageid, $sta
 /// \li \b requestid - identifier that should be passed to later calls when
 /// acting on the request
 ///
-/// \brief tries to make a request with the specified ending time\n
+/// \brief tries to make a request with the specified ending time
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCaddRequestWithEnding($imageid, $start, $end, $foruser='') {
@@ -334,7 +334,7 @@ function XMLRPCaddRequestWithEnding($ima
 ///
 /// \b future - start time of request is in the future\n
 ///
-/// \brief determines and returns the status of the request\n
+/// \brief determines and returns the status of the request
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCgetRequestStatus($requestid) {
@@ -401,51 +401,57 @@ function XMLRPCgetRequestStatus($request
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
-/// \fn XMLRPCgetUserGroups()
+/// \fn XMLRPCgetUserGroups($groupType, $affiliationid)
 ///
-/// \return an array listing all of the groups to which the given user
-/// has read or write access. Each usergroup will be an array with the 
-/// following keys:\n
-/// id\n
-/// name\n
-/// groupaffiliation\n
-/// groupaffiliationid\n
-/// ownerid\n
-/// owner\n
-/// affiliation\n
-/// editgroupid\n
-/// editgroup\n
-/// editgroupaffiliationid\n
-/// editgroupaffiliation\n
-/// custom\n
-/// courseroll\n
-/// initialmaxtime\n
-/// maxextendtime\n
-/// overlapResCount\n
+/// \param $groupType - (optional, default=0) specify 0 for all groups, 1 for
+/// only custom groups, 2 for only courseroll groups
+/// \param $affiliationid - (optional, default=0) specifiy an affiliationid to
+/// limit returned groups to only those matching the affiliation; pass 0 for
+/// all affiliations
+///
+/// \return an array with two indices, one named 'status' which will have a
+/// value of 'success', the other named 'groups' which will be an array of
+/// arrays, each one having the following keys:\n
+/// \li \b id\n
+/// \li \b name\n
+/// \li \b groupaffiliation\n
+/// \li \b groupaffiliationid\n
+/// \li \b ownerid\n
+/// \li \b owner\n
+/// \li \b affiliation\n
+/// \li \b editgroupid\n
+/// \li \b editgroup\n
+/// \li \b editgroupaffiliationid\n
+/// \li \b editgroupaffiliation\n
+/// \li \b custom\n
+/// \li \b courseroll\n
+/// \li \b initialmaxtime\n
+/// \li \b maxextendtime\n
+/// \li \b overlapResCount\n
 ///
-/// \brief builds a list of user groups\n
+/// \brief builds a list of user groups
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCgetUserGroups($groupType=0, $affiliationid=0) {
-    global $user;
-    $groups = getUserGroups($groupType, $affiliationid);
-
-    // Filter out any groups to which the user does not have access.
-    $usergroups = array();
-    foreach($groups as $id => $group){
-        if($group['ownerid'] == $user['id'] || 
-            (array_key_exists("editgroupid", $group) &&
-            array_key_exists($group['editgroupid'], $user["groups"])) || 
-            (array_key_exists($id, $user["groups"]))){
-            array_push($usergroups, $group);
-        }
-    }
-    return array(
-            "status" => "success",
-            "groups" => $usergroups);
-}
+	global $user;
+	$groupType = processInputData($groupType, ARG_NUMERIC, 0, 0);
+	$affiliationid = processInputData($affiliationid, ARG_NUMERIC, 0, 0);
 
+	$groups = getUserGroups($groupType, $affiliationid);
 
+	// Filter out any groups to which the user does not have access.
+	$usergroups = array();
+	foreach($groups as $id => $group) {
+		if($group['ownerid'] == $user['id'] || 
+		   (array_key_exists("editgroupid", $group) &&
+		   array_key_exists($group['editgroupid'], $user["groups"])) || 
+		   (array_key_exists($id, $user["groups"]))) {
+			array_push($usergroups, $group);
+		}
+	}
+	return array("status" => "success",
+	             "groups" => $usergroups);
+}
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
@@ -461,7 +467,7 @@ function XMLRPCgetUserGroups($groupType=
 /// \li \b errormsg - error string\n
 ///
 /// \b ready - request is ready; there will be 3 additional elements in the
-/// array:
+/// array:\n
 /// \li \b serverIP - address of the reserved machine
 /// \li \b user - user to use when connecting to the machine
 /// \li \b password - password to use when connecting to the machine
@@ -469,7 +475,7 @@ function XMLRPCgetUserGroups($groupType=
 /// \b notready - request is not ready for connection
 ///
 /// \brief if request is ready, adds the connecting user's computer to the
-/// request and returns info about how to connect to the computer\n
+/// request and returns info about how to connect to the computer
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCgetRequestConnectData($requestid, $remoteIP) {
@@ -479,8 +485,8 @@ function XMLRPCgetRequestConnectData($re
 	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 ||
-		$matches[3] > 255 ||
-		$matches[4] > 255) {
+	   $matches[3] > 255 ||
+	   $matches[4] > 255) {
 		return array('status' => 'error',
 		             'errorcode' => 2,
 		             'errormsg' => 'invalid IP address');
@@ -509,10 +515,10 @@ function XMLRPCgetRequestConnectData($re
 		addChangeLogEntry($requestData["logid"], $remoteIP);
 		$serverIP = $requestData["reservations"][0]["reservedIP"];
 		$passwd = $requestData["reservations"][0]["password"];
-        $connectport = $requestData["reservations"][0]["connectport"];
-        $connectMethods = getImageConnectMethodTexts(
-                $requestData["reservations"][0]["imageid"],
-                $requestData["reservations"][0]["imagerevisionid"]);
+		$connectport = $requestData["reservations"][0]["connectport"];
+		$connectMethods = getImageConnectMethodTexts(
+		$requestData["reservations"][0]["imageid"],
+		$requestData["reservations"][0]["imagerevisionid"]);
 		if($requestData["forimaging"])
 			$thisuser = 'Administrator';
 		else
@@ -520,20 +526,20 @@ function XMLRPCgetRequestConnectData($re
 				$thisuser = $matches[1];
 			else
 				$thisuser = $user['unityid'];
-        foreach($connectMethods as $key => $cm){
-            $connecttext = $cm["connecttext"];
-            $connecttext = preg_replace("/#userid#/", $thisuser, $connecttext); 
-            $connecttext = preg_replace("/#password#/", $passwd, $connecttext); 
-            $connecttext = preg_replace("/#connectIP#/", $serverIP, $connecttext); 
-            $connecttext = preg_replace("/#connectport#/", $connectport, $connecttext); 
-            $connectMethods[$key]["connecttext"] = $connecttext;
-        }
+		foreach($connectMethods as $key => $cm) {
+			$connecttext = $cm["connecttext"];
+			$connecttext = preg_replace("/#userid#/", $thisuser, $connecttext); 
+			$connecttext = preg_replace("/#password#/", $passwd, $connecttext); 
+			$connecttext = preg_replace("/#connectIP#/", $serverIP, $connecttext); 
+			$connecttext = preg_replace("/#connectport#/", $connectport, $connecttext); 
+			$connectMethods[$key]["connecttext"] = $connecttext;
+		}
 		return array('status' => 'ready',
 		             'serverIP' => $serverIP,
 		             'user' => $thisuser,
-                     'password' => $passwd,
-                     'connectport' => $connectport,
-                     'connectMethods' => $connectMethods);
+		             'password' => $passwd,
+		             'connectport' => $connectport,
+		             'connectMethods' => $connectMethods);
 	}
 	return array('status' => 'notready');
 }
@@ -554,7 +560,7 @@ function XMLRPCgetRequestConnectData($re
 /// \b success - request was successfully extended\n
 ///
 /// \brief extends the length of an active request; if a request that has not
-/// started needs to be extended, delete the request and submit a new one\n
+/// started needs to be extended, delete the request and submit a new one
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCextendRequest($requestid, $extendtime) {
@@ -691,36 +697,36 @@ function XMLRPCextendRequest($requestid,
 ///
 /// \b success - image was removed from the group\n
 ///
-/// \brief removes an image from a resource group\n
+/// \brief removes an image from a resource group
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function XMLRPCremoveImageFromGroup($name, $imageid){
-    $groups = getUserResources(array("imageAdmin"), array("manageGroup"), 1);
-    
-    if($groupid = getResourceGroupID("image/$name")){
-        if(!array_key_exists($groupid, $groups['image'])){
-            return array('status' => 'error',
-                         'errorcode' => 46,
-                         'errormsg' => 'Unable to access image group');
-        }
-        $resources = getUserResources(array("imageAdmin"), array("manageGroup"));
-        if(!array_key_exists($imageid, $resources['image'])){
-            return array('status' => 'error',
-                         'errorcode' => 47,
-                         'errormsg' => 'Unable to access image');
-        }
-
-        $allimages = getImages();
-        $query = "DELETE FROM resourcegroupmembers "
-               . "WHERE resourceid={$allimages[$imageid]['resourceid']} "
-               . "AND resourcegroupid=$groupid";
-        doQuery($query, 287);
-        return array('status' => 'success');
-    } else {
-        return array('status' => 'error',
-                     'errorcode' => 83,
-                     'errormsg' => 'invalid resource group name');
-    }
+function XMLRPCremoveImageFromGroup($name, $imageid) {
+	if($groupid = getResourceGroupID("image/$name")) {
+		$groups = getUserResources(array("imageAdmin"), array("manageGroup"), 1);
+		if(! array_key_exists($groupid, $groups['image'])) {
+			return array('status' => 'error',
+			             'errorcode' => 46,
+			             'errormsg' => 'Unable to access image group');
+		}
+		$resources = getUserResources(array("imageAdmin"), array("manageGroup"));
+		if(! array_key_exists($imageid, $resources['image'])) {
+			return array('status' => 'error',
+			             'errorcode' => 47,
+			             'errormsg' => 'Unable to access image');
+		}
+
+		$allimages = getImages(0, $imageid);
+		$query = "DELETE FROM resourcegroupmembers "
+		       . "WHERE resourceid = {$allimages[$imageid]['resourceid']} AND "
+		       .       "resourcegroupid = $groupid";
+		doQuery($query);
+		return array('status' => 'success');
+	}
+	else {
+		return array('status' => 'error',
+		             'errorcode' => 83,
+		             'errormsg' => 'invalid resource group name');
+	}
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -738,36 +744,39 @@ function XMLRPCremoveImageFromGroup($nam
 ///
 /// \b success - image was added to the group\n
 ///
-/// \brief adds an image to a resource group\n
+/// \brief adds an image to a resource group
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function XMLRPCaddImageToGroup($name, $imageid){
-    $groups = getUserResources(array("imageAdmin"), array("manageGroup"), 1);
-    
-    if($groupid = getResourceGroupID("image/$name")){
-        if(!array_key_exists($groupid, $groups['image'])){
-            return array('status' => 'error',
-                         'errorcode' => 46,
-                         'errormsg' => 'Unable to access image group');
-        }
-        $resources = getUserResources(array("imageAdmin"), array("manageGroup"));
-        if(!array_key_exists($imageid, $resources['image'])){
-            return array('status' => 'error',
-                         'errorcode' => 47,
-                         'errormsg' => 'Unable to access image');
-        }
-
-        $allimages = getImages();
-        $query = "INSERT IGNORE INTO resourcegroupmembers "
-               . "(resourceid, resourcegroupid) VALUES "
-               . "({$allimages[$imageid]['resourceid']}, $groupid)";
-        doQuery($query, 287);
-        return array('status' => 'success');
-    } else {
-        return array('status' => 'error',
-                     'errorcode' => 83,
-                     'errormsg' => 'invalid resource group name');
-    }
+function XMLRPCaddImageToGroup($name, $imageid) {
+	if($groupid = getResourceGroupID("image/$name")) {
+		$groups = getUserResources(array("imageAdmin"), array("manageGroup"), 1);
+		if(! array_key_exists($groupid, $groups['image'])) {
+			return array('status' => 'error',
+			             'errorcode' => 46,
+			             'errormsg' => 'Unable to access image group');
+		}
+		$resources = getUserResources(array("imageAdmin"), array("manageGroup"));
+		if(! array_key_exists($imageid, $resources['image'])) {
+			return array('status' => 'error',
+			             'errorcode' => 47,
+			             'errormsg' => 'Unable to access image');
+		}
+
+		$allimages = getImages(0, $imageid);
+		$query = "INSERT IGNORE INTO resourcegroupmembers "
+		       .        "(resourceid, "
+		       .        "resourcegroupid) "
+		       . "VALUES "
+		       .       "({$allimages[$imageid]['resourceid']}, "
+		       .       "$groupid)";
+		doQuery($query);
+		return array('status' => 'success');
+	}
+	else {
+		return array('status' => 'error',
+		             'errorcode' => 83,
+		             'errormsg' => 'invalid resource group name');
+	}
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -782,32 +791,35 @@ function XMLRPCaddImageToGroup($name, $i
 /// \li \b errorcode - error number\n
 /// \li \b errormsg - error string\n
 ///
-/// \b success - returns an array of images\n
-///
-/// \brief gets a list of all images in a particular group\n
-///
-////////////////////////////////////////////////////////////////////////////////
-function XMLRPCgetGroupImages($name){
-    if($groupid = getResourceGroupID("image/$name")){
-        $membership = getResourceGroupMemberships('image');
-        $resources = getUserResources(array("imageAdmin"),
-                                      array("manageGroup"));
-
-        $images = array();
-        foreach($resources['image'] as $imageid => $image){
-            if(array_key_exists($imageid, $membership['image']) &&
-                    in_array($groupid, $membership['image'][$imageid])){
-                array_push($images, array('id' => $imageid, 'name' => $image));
-            }
-        }
-        return array('status' => 'success',
-                     'images' => $images);
-
-    } else {
-        return array('status' => 'error',
-                     'errorcode' => 83,
-                     'errormsg' => 'invalid resource group name');
-    }
+/// \b success - returns an array of images; there will be an additional element
+/// in the array with an index of 'images' that is an array of images with
+/// each element having the following two keys:\n
+/// \li \b id - id of the image\n
+/// \li \b name - name of the image
+///
+/// \brief gets a list of all images in a particular group
+///
+////////////////////////////////////////////////////////////////////////////////
+function XMLRPCgetGroupImages($name) {
+	if($groupid = getResourceGroupID("image/$name")) {
+		$membership = getResourceGroupMemberships('image');
+		$resources = getUserResources(array("imageAdmin"), array("manageGroup"));
+
+		$images = array();
+		foreach($resources['image'] as $imageid => $image) {
+			if(array_key_exists($imageid, $membership['image']) &&
+			   in_array($groupid, $membership['image'][$imageid]))
+				array_push($images, array('id' => $imageid, 'name' => $image));
+		}
+		return array('status' => 'success',
+		             'images' => $images);
+
+	}
+	else {
+		return array('status' => 'error',
+		             'errorcode' => 83,
+		             'errormsg' => 'invalid resource group name');
+	}
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -825,49 +837,50 @@ function XMLRPCgetGroupImages($name){
 ///
 /// \b success - successfully mapped an image group to a computer group\n
 ///
-/// \brief map an image group to a computer group\n
+/// \brief map an image group to a computer group
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function XMLRPCaddImageGroupToComputerGroup($imageGroup, $computerGroup){
-    $imageid = getResourceGroupID("image/$imageGroup");
-    $compid = getResourceGroupID("computer/$computerGroup");
-    if($imageid && $compid){
-        $tmp = getUserResources(array("imageAdmin"),
-                                array("manageMapping"), 1);
-        $imagegroups = $tmp['image'];
-        $tmp = getUserResources(array("computerAdmin"),
-                                array("manageMapping"), 1);
-        $computergroups = $tmp['computer'];
-
-        if(array_key_exists($compid, $computergroups) &&
-            array_key_exists($imageid, $imagegroups)){
-            $mapping = getResourceMapping("image", "computer",
-                                          $imageid,
-                                          $compid);
-            if(!array_key_exists($imageid, $mapping) ||
-                !array_key_exists($compid, $mapping[$imageid])){
-                $query = "INSERT INTO resourcemap "
-                       .        "(resourcegroupid1, "
-			           .        "resourcetypeid1, "
-			           .        "resourcegroupid2, "
-			           .        "resourcetypeid2) "
-			           . "VALUES ($imageid, "
-			           .         "13, "
-			           .         "$compid, "
-			           .         "12)";
-                doQuery($query, 101);
-            }
-            return array('status' => 'success');
-        } else {
-            return array('status' => 'error',
-                         'errorcode' => 84,
-                         'errormsg' => 'cannot access computer and/or image group');
-        }
-    } else {
-        return array('status' => 'error',
-                     'errorcode' => 83,
-                     'errormsg' => 'invalid resource group name');
-    }
+function XMLRPCaddImageGroupToComputerGroup($imageGroup, $computerGroup) {
+	$imageid = getResourceGroupID("image/$imageGroup");
+	$compid = getResourceGroupID("computer/$computerGroup");
+	if($imageid && $compid) {
+		$tmp = getUserResources(array("imageAdmin"),
+		                        array("manageMapping"), 1);
+		$imagegroups = $tmp['image'];
+		$tmp = getUserResources(array("computerAdmin"),
+		                        array("manageMapping"), 1);
+		$computergroups = $tmp['computer'];
+
+		if(array_key_exists($compid, $computergroups) &&
+			array_key_exists($imageid, $imagegroups)) {
+			$mapping = getResourceMapping("image", "computer",
+			                              $imageid, $compid);
+			if(! array_key_exists($imageid, $mapping) ||
+			   ! in_array($compid, $mapping[$imageid])) {
+				$query = "INSERT INTO resourcemap "
+				       .        "(resourcegroupid1, "
+				       .        "resourcetypeid1, "
+				       .        "resourcegroupid2, "
+				       .        "resourcetypeid2) "
+				       . "VALUES ($imageid, "
+				       .         "13, "
+				       .         "$compid, "
+				       .         "12)";
+				doQuery($query, 101);
+			}
+			return array('status' => 'success');
+		}
+		else {
+			return array('status' => 'error',
+			             'errorcode' => 84,
+			             'errormsg' => 'cannot access computer and/or image group');
+		}
+	}
+	else {
+		return array('status' => 'error',
+		             'errorcode' => 83,
+		             'errormsg' => 'invalid resource group name');
+	}
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -883,56 +896,57 @@ function XMLRPCaddImageGroupToComputerGr
 /// \li \b errorcode - error number\n
 /// \li \b errormsg - error string\n
 ///
-/// \b success - successfully removed the mapping from an 
-///     image group to a computer group\n
+/// \b success - successfully removed the mapping from an image group to a
+/// computer group\n
 ///
-/// \brief remove the mapping of an image group to a computer group\n
+/// \brief remove the mapping of an image group to a computer group
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function XMLRPCremoveImageGroupFromComputerGroup($imageGroup, $computerGroup){
-    $imageid = getResourceGroupID("image/$imageGroup");
-    $compid = getResourceGroupID("computer/$computerGroup");
-    if($imageid && $compid){
-        $tmp = getUserResources(array("imageAdmin"),
-                                array("manageMapping"), 1);
-        $imagegroups = $tmp['image'];
-        $tmp = getUserResources(array("computerAdmin"),
-                                array("manageMapping"), 1);
-        $computergroups = $tmp['computer'];
-
-        if(array_key_exists($compid, $computergroups) &&
-            array_key_exists($imageid, $imagegroups)){
-            $mapping = getResourceMapping("image", "computer",
-                                          $imageid,
-                                          $compid);
-            if(array_key_exists($imageid, $mapping) &&
-                array_key_exists($compid, $mapping[$imageid])){
-                $query = "DELETE FROM resourcemap "
-					   . "WHERE resourcegroupid1 = $imageid AND "
-					   .       "resourcetypeid1 = 13 AND "
-					   .       "resourcegroupid2 = $compid AND "
-					   .       "resourcetypeid2 = 12";
-			    doQuery($query, 101);
-            }
-            return array('status' => 'success');
-        } else {
-            return array('status' => 'error',
-                         'errorcode' => 84,
-                         'errormsg' => 'cannot access computer and/or image group');
-        }
-    } else {
-        return array('status' => 'error',
-                     'errorcode' => 83,
-                     'errormsg' => 'invalid resource group name');
-    }
+function XMLRPCremoveImageGroupFromComputerGroup($imageGroup, $computerGroup) {
+	$imageid = getResourceGroupID("image/$imageGroup");
+	$compid = getResourceGroupID("computer/$computerGroup");
+	if($imageid && $compid) {
+		$tmp = getUserResources(array("imageAdmin"),
+		                        array("manageMapping"), 1);
+		$imagegroups = $tmp['image'];
+		$tmp = getUserResources(array("computerAdmin"),
+		                        array("manageMapping"), 1);
+		$computergroups = $tmp['computer'];
+
+		if(array_key_exists($compid, $computergroups) &&
+			array_key_exists($imageid, $imagegroups)) {
+			$mapping = getResourceMapping("image", "computer",
+			                              $imageid, $compid);
+			if(array_key_exists($imageid, $mapping) &&
+			   in_array($compid, $mapping[$imageid])) {
+				$query = "DELETE FROM resourcemap "
+				       . "WHERE resourcegroupid1 = $imageid AND "
+				       .       "resourcetypeid1 = 13 AND "
+				       .       "resourcegroupid2 = $compid AND "
+				       .       "resourcetypeid2 = 12";
+				doQuery($query, 101);
+			}
+			return array('status' => 'success');
+		}
+		else {
+			return array('status' => 'error',
+			             'errorcode' => 84,
+			             'errormsg' => 'cannot access computer and/or image group');
+		}
+	}
+	else {
+		return array('status' => 'error',
+		             'errorcode' => 83,
+		             'errormsg' => 'invalid resource group name');
+	}
 }
 
-
 ////////////////////////////////////////////////////////////////////////////////
 ///
 /// \fn XMLRPCgetNodes($root)
 ///
-/// \param $root - (optional) the ID of the node forming the root of the hierarchy
+/// \param $root - (optional, default=top of tree) the ID of the node forming
+/// the root of the hierarchy
 ///
 /// \return an array with at least one index named 'status' which will have
 /// one of these values\n
@@ -940,40 +954,47 @@ function XMLRPCremoveImageGroupFromCompu
 /// \li \b errorcode - error number\n
 /// \li \b errormsg - error string\n
 ///
-/// \b success - returns an array of nodes\n
-///
-/// \brief gets a list of all nodes in the privilege tree\n
-///
-////////////////////////////////////////////////////////////////////////////////
-function XMLRPCgetNodes($root=NULL){
-    global $user;
-    if(in_array("nodeAdmin", $user['privileges'])){
-        $topNodes = $root ? getChildNodes($root) : getChildNodes();
-        $nodes = array();
-        $stack = array();
-        foreach($topNodes as $id => $node){
-            $node['id'] = $id;
-            array_push($nodes, $node);
-            array_push($stack, $node);
-        } 
-        while(count($stack)){
-            $item = array_shift($stack);
-            $children = getChildNodes($item['id']);
-            foreach($children as $id => $node){
-                $node['id'] = $id;
-                array_push($nodes, $node);
-                array_push($stack, $node);
-            }
-        }
-        return array(
-            'status' => 'success',
-            'nodes' => $nodes);
-    } else {
-        return array(
-            'status' => 'error',
-            'errorcode' => 56,
-            'errormsg' => 'User cannot access node content');
-    }
+/// \b success - returns an array of nodes; there will be an additional element
+/// in the array with an index of 'nodes' that is an array of nodes with each
+/// element having the following three keys:\n
+/// \li \b id - id of the node\n
+/// \li \b name - name of the node\n
+/// \li \b parent - id of the parent node
+///
+/// \brief gets a list of all nodes in the privilege tree
+///
+////////////////////////////////////////////////////////////////////////////////
+function XMLRPCgetNodes($root=NULL) {
+	global $user;
+	if(in_array("userGrant", $user["privileges"]) ||
+		in_array("resourceGrant", $user["privileges"]) ||
+		in_array("nodeAdmin", $user["privileges"])) {
+		$root = processInputData($root, ARG_NUMERIC);
+		$topNodes = $root ? getChildNodes($root) : getChildNodes();
+		$nodes = array();
+		$stack = array();
+		foreach($topNodes as $id => $node) {
+			$node['id'] = $id;
+			array_push($nodes, $node);
+			array_push($stack, $node);
+		} 
+		while(count($stack)) {
+			$item = array_shift($stack);
+			$children = getChildNodes($item['id']);
+			foreach($children as $id => $node) {
+				$node['id'] = $id;
+				array_push($nodes, $node);
+				array_push($stack, $node);
+			}
+		}
+		return array('status' => 'success',
+		             'nodes' => $nodes);
+	}
+	else {
+		return array('status' => 'error',
+		             'errorcode' => 70,
+		             'errormsg' => 'User cannot access node content');
+	}
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -992,28 +1013,37 @@ function XMLRPCgetNodes($root=NULL){
 /// \b success - returns an 'exists' element set to either 1 or 0\n
 ///
 /// \brief indicates whether a node with that name already exists at this
-///     location in the privilege tree\n
+/// location in the privilege tree
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function XMLRPCnodeExists($nodeName, $parentNode){
-    global $user;
-    if(in_array("nodeAdmin", $user['privileges'])){
-        // does a node with this name already exist?
-        $query = "SELECT id "
-               . "FROM privnode "
-               . "WHERE name = '$nodeName' AND parent = $parentNode";
-        $qh = doQuery($query, 335);
-        if(mysql_num_rows($qh)){
-            return array('status' => 'success', 'exists' => TRUE);
-        } else {
-            return array('status' => 'success', 'exists' => FALSE);
-        }
-    } else {
-        return array(
-            'status' => 'error',
-            'errorcode' => 56,
-            'errormsg' => 'User cannot access node content');
-    }
+function XMLRPCnodeExists($nodeName, $parentNode) {
+	global $user;
+	if(! is_numeric($parentNode)) {
+		return array('status' => 'error',
+		             'errorcode' => 78,
+		             'errormsg' => 'Invalid nodeid specified');
+	}
+	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 = mysql_real_escape_string($nodeName);
+		// does a node with this name already exist?
+		$query = "SELECT id "
+		       . "FROM privnode "
+		       . "WHERE name = '$nodeName' AND parent = $parentNode";
+		$qh = doQuery($query, 335);
+		if(mysql_num_rows($qh))
+			return array('status' => 'success', 'exists' => TRUE);
+		else
+			return array('status' => 'success', 'exists' => FALSE);
+	}
+	else {
+		return array('status' => 'error',
+		             'errorcode' => 70,
+		             'errormsg' => 'User cannot access node content');
+	}
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1030,32 +1060,34 @@ function XMLRPCnodeExists($nodeName, $pa
 ///
 /// \b success - node was successfully deleted
 ///
-/// \brief delete a node in the privilege tree\n
+/// \brief delete a node from the privilege tree
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function XMLRPCremoveNode($nodeID){
-    require_once(".ht-inc/privileges.php");
-    global $user;
-    if(!in_array("nodeAdmin", $user['privileges'])){
-        return array(
-            'status' => 'error',
-            'errorcode' => 56,
-            'errormsg' => 'User cannot administer nodes');
-    }
-    if(!checkUserHasPriv("nodeAdmin", $user['id'], $nodeID)){
-        return array(
-            'status' => 'error',
-            'errorcode' => 57,
-            'errormsg' => 'User cannot edit this node');
-    }
-    $nodes = recurseGetChildren($nodeID);
-    array_push($nodes, $nodeID);
-    $deleteNodes = implode(',', $nodes);
-    $query = "DELETE FROM privnode "
-           . "WHERE id IN ($deleteNodes)";
-    doQuery($query, 345);
-    return array(
-            'status' => 'success');
+function XMLRPCremoveNode($nodeID) {
+	require_once(".ht-inc/privileges.php");
+	global $user;
+	if(! is_numeric($nodeID)) {
+		return array('status' => 'error',
+		             'errorcode' => 78,
+		             'errormsg' => 'Invalid nodeid specified');
+	}
+	if(! in_array("nodeAdmin", $user['privileges'])) {
+		return array('status' => 'error',
+		             'errorcode' => 70,
+		             'errormsg' => 'User cannot administer nodes');
+	}
+	if(! checkUserHasPriv("nodeAdmin", $user['id'], $nodeID)) {
+		return array('status' => 'error',
+		             'errorcode' => 57,
+		             'errormsg' => 'User cannot edit this node');
+	}
+	$nodes = recurseGetChildren($nodeID);
+	array_push($nodes, $nodeID);
+	$deleteNodes = implode(',', $nodes);
+	$query = "DELETE FROM privnode "
+	       . "WHERE id IN ($deleteNodes)";
+	doQuery($query, 345);
+	return array('status' => 'success');
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1073,64 +1105,69 @@ function XMLRPCremoveNode($nodeID){
 ///
 /// \b success - node was successfully added
 ///
-/// \brief add a node to the privilege tree as a child of the
-///     specified parent node\n
+/// \brief add a node to the privilege tree as a child of the specified parent
+/// node
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function XMLRPCaddNode($nodeName, $parentNode){
-    require_once(".ht-inc/privileges.php");
-    global $user;
-    if(in_array("nodeAdmin", $user['privileges'])){
-        if(!$parentNode){
-            $topNodes = getChildNodes();
-            $keys = array_keys($topNodes);
-            $parentNode = array_shift($keys);
-        }
-
-        if(!preg_match("/^[-A-Za-z0-9_\. ]+$/", $nodeName)){
-            return array('status' => 'error',
-                         'errorcode' => 48,
-                         'errormsg' => 'Invalid node name');
-        }
-
-        if(checkUserHasPriv("nodeAdmin", $user['id'], $parentNode)){
-            $nodeInfo = getNodeInfo($parentNode);
-            $query = "SELECT id "
-                   . "FROM privnode "
-                   . "WHERE name = '$nodeName' AND parent = $parentNode";
-            $qh = doQuery($query, 335);
-            if(mysql_num_rows($qh)){
-                return array('status' => 'error',
-                             'errorcode' => 50,
-                             'errormsg' => 'A node of that name already exists under ' . $nodeInfo['name']);
-            }
-            $query = "INSERT IGNORE INTO privnode "
-                   .        "(parent, name) "
-                   . "VALUES "
-                   .        "($parentNode, '$nodeName')";
-            doQuery($query, 337);
-            $qh = doQuery("SELECT LAST_INSERT_ID() FROM privnode", 101);
-            if(!$row = mysql_fetch_row($qh)){
-                return array('status' => 'error',
-                             'errorcode' => 51,
-                             'errormsg' => 'Could not add node to database');
-            }
-            $nodeid = $row[0];
-            return array('status' => 'success',
-                         'nodeid' => $nodeid);
-        } else {
-            return array('status' => 'error',
-                         'errorcode' => 49,
-                         'errormsg' => 'Unable to add node at this location');
-        }
-    } else {
-        return array(
-            'status' => 'error',
-            'errorcode' => 56,
-            'errormsg' => 'User cannot access node content');
-    }
-}
+function XMLRPCaddNode($nodeName, $parentNode) {
+	require_once(".ht-inc/privileges.php");
+	global $user;
+	if(! is_numeric($parentNode)) {
+		return array('status' => 'error',
+		             'errorcode' => 78,
+		             'errormsg' => 'Invalid nodeid specified');
+	}
+	if(in_array("nodeAdmin", $user['privileges'])) {
+		$nodeInfo = getNodeInfo($parentNode);
+		if(is_null($tmp)) {
+			return array('status' => 'error',
+			             'errorcode' => 78,
+			             'errormsg' => 'Invalid nodeid specified');
+		}
 
+		if(! validateNodeName($nodeName, $tmp)) {
+			return array('status' => 'error',
+			             'errorcode' => 81,
+			             'errormsg' => 'Invalid node name');
+		}
+
+		if(checkUserHasPriv("nodeAdmin", $user['id'], $parentNode)) {
+			$query = "SELECT id "
+			       . "FROM privnode "
+			       . "WHERE name = '$nodeName' AND parent = $parentNode";
+			$qh = doQuery($query);
+			if(mysql_num_rows($qh)) {
+				return array('status' => 'error',
+				             'errorcode' => 82,
+				             'errormsg' => 'A node of that name already exists under ' . $nodeInfo['name']);
+			}
+			$query = "INSERT IGNORE INTO privnode "
+			       .        "(parent, name) "
+			       . "VALUES "
+			       .        "($parentNode, '$nodeName')";
+			doQuery($query);
+			$qh = doQuery("SELECT LAST_INSERT_ID() FROM privnode", 101);
+			if(! $row = mysql_fetch_row($qh)) {
+				return array('status' => 'error',
+				             'errorcode' => 85,
+				             'errormsg' => 'Could not add node to database');
+			}
+			$nodeid = $row[0];
+			return array('status' => 'success',
+			             'nodeid' => $nodeid);
+		}
+		else {
+			return array('status' => 'error',
+			             'errorcode' => 49,
+			             'errormsg' => 'Unable to add node at this location');
+		}
+	}
+	else {
+		return array('status' => 'error',
+		             'errorcode' => 70,
+		             'errormsg' => 'User cannot access node content');
+	}
+}
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
@@ -1149,33 +1186,13 @@ function XMLRPCaddNode($nodeName, $paren
 ///
 /// \b success - privileges were successfully removed
 ///
-/// \brief remove privileges from a resource group in the privilege
-///      node tree\n
+/// \brief remove privileges for a resource group from a node in the privilege
+/// tree
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function XMLRPCremoveResourceGroupPriv($name, $type, $nodeid, $permissions){
-    require_once(".ht-inc/privileges.php");
-    global $user;
-
-    if(! checkUserHasPriv("resourceGrant", $user['id'], $nodeid)){
-        return array('status' => 'error',
-                     'errorcode' => 53,
-                     'errormsg' => 'Unable to remove group privileges on this node');
-    }
-    if($typeid = getResourceTypeID($type)){
-        if(!checkForGroupName($name, 'resource', '', $typeid)){
-            return array('status' => 'error',
-                         'errorcode' => 28,
-                         'errormsg' => 'resource group does not exist');
-        }
-        $perms = explode(':', $permissions);
-        updateResourcePrivs("$type/$name", $nodeid, array(), $perms);
-        return array('status' => 'success');
-    } else {
-        return array('status' => 'error',
-                     'errorcode' => 56,
-                     'errormsg' => 'Invalid resource type');
-    }
+function XMLRPCremoveResourceGroupPriv($name, $type, $nodeid, $permissions) {
+	return _XMLRPCchangeResourceGroupPriv_sub('remove', $name, $type, $nodeid,
+	                                          $permissions);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1192,22 +1209,30 @@ function XMLRPCremoveResourceGroupPriv($
 /// \li \b errorcode - error number\n
 /// \li \b errormsg - error string\n
 ///
-/// \b success - an additional element is returned:
-/// \li \b privileges - a list of privileges available
+/// \b success - an additional element is returned:\n
+/// \li \b privileges - array of privileges assigned at the node
 ///
-/// \brief get a list of privileges for a user group at a particular
-///     location in the privilege tree\n
+/// \brief get a list of privileges for a user group at a particular node in the
+/// privilege tree
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function XMLRPCgetUserGroupPrivs($name, $affiliation, $nodeid){
-    require_once(".ht-inc/privileges.php");
-    global $user;
-
-    if(! checkUserHasPriv("userGrant", $user['id'], $nodeid)){
-        return array('status' => 'error',
-                     'errorcode' => 53,
-                     'errormsg' => 'Unable to add resource group to this node');
-    }
+function XMLRPCgetUserGroupPrivs($name, $affiliation, $nodeid) {
+	require_once(".ht-inc/privileges.php");
+	global $user;
+
+	if(! is_numeric($nodeid)) {
+		return array('status' => 'error',
+		             'errorcode' => 78,
+		             'errormsg' => 'Invalid nodeid specified');
+	}
+
+	if(! in_array("userGrant", $user["privileges"]) &&
+		! in_array("resourceGrant", $user["privileges"]) &&
+		! in_array("nodeAdmin", $user["privileges"])) {
+		return array('status' => 'error',
+		             'errorcode' => 62,
+		             'errormsg' => 'Unable to view user group privileges');
+	}
 
 	$validate = array('name' => $name,
 	                  'affiliation' => $affiliation);
@@ -1215,30 +1240,27 @@ function XMLRPCgetUserGroupPrivs($name, 
 	if($rc['status'] == 'error')
 		return $rc;
 
-    $privileges = array();
-    $nodePrivileges = getNodePrivileges($nodeid, 'usergroups');
-    $cascadedNodePrivileges = getNodeCascadePrivileges($nodeid, 'usergroups'); 
-    $cngp = $cascadedNodePrivileges['usergroups'];
-    $ngp = $nodePrivileges['usergroups'];
-    if(array_key_exists($name, $cngp)){
-        foreach($cngp[$name]['privs'] as $p){
-            if(! array_key_exists($name, $ngp) ||
-                    ! in_array("block", $ngp[$name]['privs'])){
-                array_push($privileges, $p);
-            }
-        }
-    }
-    if(array_key_exists($name, $ngp)){
-        foreach($ngp[$name]['privs'] as $p){
-            if($p != "block"){
-                array_push($privileges, $p);
-            }
-        }
-    }
-
-    return array(
-        'status' => 'success',
-        'privileges' => array_unique($privileges));
+	$privileges = array();
+	$nodePrivileges = getNodePrivileges($nodeid, 'usergroups');
+	$cascadedNodePrivileges = getNodeCascadePrivileges($nodeid, 'usergroups'); 
+	$cngp = $cascadedNodePrivileges['usergroups'];
+	$ngp = $nodePrivileges['usergroups'];
+	if(array_key_exists($name, $cngp)) {
+		foreach($cngp[$name]['privs'] as $p) {
+			if(! array_key_exists($name, $ngp) ||
+			   ! in_array("block", $ngp[$name]['privs']))
+				array_push($privileges, $p);
+		}
+	}
+	if(array_key_exists($name, $ngp)) {
+		foreach($ngp[$name]['privs'] as $p) {
+			if($p != "block")
+				array_push($privileges, $p);
+		}
+	}
+
+	return array('status' => 'success',
+	              'privileges' => array_unique($privileges));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1255,47 +1277,61 @@ function XMLRPCgetUserGroupPrivs($name, 
 /// \li \b errorcode - error number\n
 /// \li \b errormsg - error string\n
 ///
-/// \b success - an additional element is returned:
-/// \li \b privileges - a list of privileges available
+/// \b success - an additional element is returned:\n
+/// \li \b privileges - array of privileges assigned at the node
 ///
-/// \brief get a list of privileges for a resource group at a particular
-///     location in the privilege tree\n
+/// \brief get a list of privileges for a resource group at a particular node in
+/// the privilege tree
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function XMLRPCgetResourceGroupPrivs($name, $type, $nodeid){
-    require_once(".ht-inc/privileges.php");
-    global $user;
-
-    if(! checkUserHasPriv("resourceGrant", $user['id'], $nodeid)){
-        return array('status' => 'error',
-                     'errorcode' => 53,
-                     'errormsg' => 'Unable to add resource group to this node');
-    }
-
-    if($typeid = getResourceTypeID($type)){
-        if(!checkForGroupName($name, 'resource', '', $typeid)){
-            return array('status' => 'error',
-                         'errorcode' => 28,
-                         'errormsg' => 'resource group does not exist');
-        }
-        $nodePrivileges = getNodePrivileges($nodeid, 'resources');
-        $nodePrivileges = getNodeCascadePrivileges($nodeid, 'resources', $nodePrivileges); 
-        foreach($nodePrivileges['resources'] as $resource => $privs){
-            if(strstr($resource, "$type/$name")){
-                return array(
-                    'status' => 'success',
-                    'privileges' => $privs);
-            }
-        }
-        return array(
-            'status' => 'error',
-            'errorcode' => 29,
-            'errormsg' => 'could not find resource name in privilege list');
-    } else {
-        return array('status' => 'error',
-                     'errorcode' => 56,
-                     'errormsg' => 'Invalid resource type');
-    }
+function XMLRPCgetResourceGroupPrivs($name, $type, $nodeid) {
+	require_once(".ht-inc/privileges.php");
+	global $user;
+
+	if(! is_numeric($nodeid)) {
+		return array('status' => 'error',
+		             'errorcode' => 78,
+		             'errormsg' => 'Invalid nodeid specified');
+	}
+
+	if(! in_array("userGrant", $user["privileges"]) &&
+		! in_array("resourceGrant", $user["privileges"]) &&
+		! in_array("nodeAdmin", $user["privileges"])) {
+		return array('status' => 'error',
+		             'errorcode' => 63,
+		             'errormsg' => 'Unable to view resource group privileges');
+	}
+
+	if($typeid = getResourceTypeID($type)) {
+		if(! $groupid = getResourceGroupID("$type/$name")) {
+			return array('status' => 'error',
+			             'errorcode' => 74,
+			             'errormsg' => 'resource group does not exist');
+		}
+		$np = getNodePrivileges($nodeid, 'resources');
+		$cnp = getNodeCascadePrivileges($nodeid, 'resources'); 
+		$key = "$type/$name/$groupid";
+		if(array_key_exists($key, $np['resources']) &&
+			(in_array('block', $np['resources'][$key]) ||
+		   ! array_key_exists($key, $cnp['resources'])))
+			$privs = $np['resources'][$key];
+		elseif(array_key_exists($key, $cnp['resources']) &&
+		   array_key_exists($key, $np['resources'])) {
+			$allprivs = array_merge($cnp['resources'][$key], $np['resources'][$key]);
+			$privs = array_unique($allprivs);
+		}
+		elseif(array_key_exists($key, $cnp['resources']))
+			$privs = $cnp['resources'][$key];
+		else
+			$privs = array();
+		return array('status' => 'success',
+		             'privileges' => $privs);
+	}
+	else {
+		return array('status' => 'error',
+		             'errorcode' => 71,
+		             'errormsg' => 'Invalid resource type');
+	}
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1315,43 +1351,22 @@ function XMLRPCgetResourceGroupPrivs($na
 ///
 /// \b success - privileges were successfully added
 ///
-/// \brief add privileges for a resource group at a particular
-///     location in the privilege tree\n
+/// \brief add privileges for a resource group at a particular node in the
+/// privilege tree
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function XMLRPCaddResourceGroupPriv($name, $type, $nodeid, $permissions){
-    require_once(".ht-inc/privileges.php");
-    global $user;
-
-    if(! checkUserHasPriv("resourceGrant", $user['id'], $nodeid)){
-        return array('status' => 'error',
-                     'errorcode' => 53,
-                     'errormsg' => 'Unable to add resource group to this node');
-    }
-
-    if($typeid = getResourceTypeID($type)){
-        if(!checkForGroupName($name, 'resource', '', $typeid)){
-            return array('status' => 'error',
-                         'errorcode' => 28,
-                         'errormsg' => 'resource group does not exist');
-        }
-        $perms = explode(':', $permissions);
-        updateResourcePrivs("$type/$name", $nodeid, $perms, array());
-        return array('status' => 'success');
-    } else {
-        return array('status' => 'error',
-                     'errorcode' => 56,
-                     'errormsg' => 'Invalid resource type');
-    }
+function XMLRPCaddResourceGroupPriv($name, $type, $nodeid, $permissions) {
+	return _XMLRPCchangeResourceGroupPriv_sub('add', $name, $type, $nodeid,
+	                                          $permissions);
 }
 
-
 ////////////////////////////////////////////////////////////////////////////////
 ///
-/// \fn XMLRPCremoveResourceGroupPriv($name, $type, $nodeid, $permissions)
+/// \fn XMLRPCremoveUserGroupPriv($name, $affiliation, $nodeid,
+///                                   $permissions)
 ///
-/// \param $name - the name of the resource group
-/// \param $type - the resource group type
+/// \param $name - the name of the user group
+/// \param $affiliation - the affiliation of the user group
 /// \param $nodeid - the ID of the node in the privilege tree
 /// \param $permissions - a colon (:) delimited list of privileges to remove
 ///
@@ -1363,19 +1378,25 @@ function XMLRPCaddResourceGroupPriv($nam
 ///
 /// \b success - privileges were successfully removed
 ///
-/// \brief remove privileges for a resource group at a particular
-///     location in the privilege tree\n
+/// \brief remove privileges for a resource group at a particular node in the
+/// privilege tree
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function XMLRPCremoveUserGroupPriv($name, $affiliation, $nodeid, $permissions){
-    require_once(".ht-inc/privileges.php");
+function XMLRPCremoveUserGroupPriv($name, $affiliation, $nodeid, $permissions) {
+	require_once(".ht-inc/privileges.php");
 	global $user;
 
-    if(! checkUserHasPriv("userGrant", $user['id'], $nodeid)){
+	if(! is_numeric($nodeid)) {
+		return array('status' => 'error',
+		             'errorcode' => 78,
+		             'errormsg' => 'Invalid nodeid specified');
+	}
+
+	if(! checkUserHasPriv("userGrant", $user['id'], $nodeid)) {
 		return array('status' => 'error',
-                     'errorcode' => 53,
-                     'errormsg' => 'Unable to remove group privileges on this node');
-    }
+		             'errorcode' => 65,
+		             'errormsg' => 'Unable to remove user group privileges on this node');
+	}
 
 	$validate = array('name' => $name,
 	                  'affiliation' => $affiliation);
@@ -1383,33 +1404,40 @@ function XMLRPCremoveUserGroupPriv($name
 	if($rc['status'] == 'error')
 		return $rc;
 
-    $groupid = $rc['id'];
-    $groupname = "$name@$affiliation";
-    $perms = explode(':', $permissions);
-    $usertypes = getTypes('users');
-    array_push($usertypes["users"], "block");
+	$groupid = $rc['id'];
+	#$name = "$name@$affiliation";
+	$perms = explode(':', $permissions);
+	$usertypes = getTypes('users');
+	array_push($usertypes["users"], "block");
 	array_push($usertypes["users"], "cascade");
-    $cascadePrivs = getNodeCascadePriviliges($nodeid, "usergroups");
-    $removegroupprivs = array();
-    if(array_key_exists($groupname, $cascadePrivs['usergroups'])){
-        foreach($perms as $permission){
-            if(in_array($permission, $cascadePrivs['usergroups'][$groupname]['privs'])){
-                array_push($removegroupprivs, $permission);
-            }
-        }
-        $diff = array_diff($cascadePrivs['usergroups'][$groupname], $removegroupprivs);
-        if(count($diff) == 1 && in_array("cascade", $diff)){
-            array_push($removegroupprivs, "cascade");
-	}
-	}
-    if(empty($removegroupprivs)){
+
+	$diff = array_diff($perms, $usertypes['users']);
+	if(count($diff)) {
 		return array('status' => 'error',
-                     'errorcode' => 53,
-                     'errormsg' => 'Invalid or missing permissions list supplied');
+		             'errorcode' => 66,
+		             'errormsg' => 'Invalid or missing permissions list supplied');
 	}
 
-    updateUserOrGroupPrivs($groupid, $nodeid, array(), $removegroupprivs, "group");
-    return array('status' => 'success');
+	$cnp = getNodeCascadePrivileges($nodeid, "usergroups");
+	$np = getNodePrivileges($nodeid, "usergroups");
+
+	if(array_key_exists($name, $cnp['usergroups']) &&
+	   (! array_key_exists($name, $np['usergroups']) ||
+	   ! in_array('block', $np['usergroups'][$name]))) {
+		$intersect = array_intersect($cnp['usergroups'][$name]['privs'], $perms);
+		if(count($intersect)) {
+			return array('status' => 'error',
+			             'errorcode' => 80,
+			             'errormsg' => 'Unable to modify privileges cascaded to this node');
+		}
+	}
+
+	$diff = array_diff($np['usergroups'][$name]['privs'], $perms);
+	if(count($diff) == 1 && in_array("cascade", $diff))
+		array_push($perms, "cascade");
+
+	updateUserOrGroupPrivs($groupid, $nodeid, array(), $perms, "group");
+	return array('status' => 'success');
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1429,18 +1457,24 @@ function XMLRPCremoveUserGroupPriv($name
 ///
 /// \b success - privileges were successfully added
 ///
-/// \brief add privileges for a user group at a particular
-///     location in the privilege tree\n
+/// \brief add privileges for a user group at a particular node in the
+/// privilege tree
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function XMLRPCaddUserGroupPriv($name, $affiliation, $nodeid, $permissions){
-    require_once(".ht-inc/privileges.php");
-    global $user;
+function XMLRPCaddUserGroupPriv($name, $affiliation, $nodeid, $permissions) {
+	require_once(".ht-inc/privileges.php");
+	global $user;
 
-    if(! checkUserHasPriv("userGrant", $user['id'], $nodeid)){
+	if(! is_numeric($nodeid)) {
 		return array('status' => 'error',
-                     'errorcode' => 52,
-                     'errormsg' => 'Unable to add a user group to this node');
+		             'errorcode' => 78,
+		             'errormsg' => 'Invalid nodeid specified');
+	}
+
+	if(! checkUserHasPriv("userGrant", $user['id'], $nodeid)) {
+		return array('status' => 'error',
+		             'errorcode' => 52,
+		             'errormsg' => 'Unable to add a user group to this node');
 	}
 
 	$validate = array('name' => $name,
@@ -1449,28 +1483,30 @@ function XMLRPCaddUserGroupPriv($name, $
 	if($rc['status'] == 'error')
 		return $rc;
 
-    $groupid = $rc['id'];
-    $perms = explode(':', $permissions);
-    $usertypes = getTypes('users');
-    array_push($usertypes["users"], "block");
+	$groupid = $rc['id'];
+	#$name = "$name@$affiliation";
+	$perms = explode(':', $permissions);
+	$usertypes = getTypes('users');
+	array_push($usertypes["users"], "block");
 	array_push($usertypes["users"], "cascade");
-	$newgroupprivs = array();
-	foreach($usertypes["users"] as $type) {
-		if(in_array($type, $perms))
-			array_push($newgroupprivs, $type);
-	}
-	if(empty($newgroupprivs) || (count($newgroupprivs) == 1 && 
-           in_array("cascade", $newgroupprivs))) {
+
+	$diff = array_diff($perms, $usertypes['users']);
+	if(count($diff) || (count($perms) == 1 && $perms[0] == 'cascade')) {
 		return array('status' => 'error',
-                    'errorcode' => 53,
-                    'errormsg' => 'Invalid or missing permissions list supplied');
+		             'errorcode' => 66,
+		             'errormsg' => 'Invalid or missing permissions list supplied');
 	}
-    updateUserOrGroupPrivs($groupid, $nodeid, $newgroupprivs, array(), "group");
-	return array('status' => 'success');
-}
 
+	$cnp = getNodeCascadePrivileges($nodeid, "usergroups");
+	$np = getNodePrivileges($nodeid, "usergroups", $cnp);
 
+	$diff = array_diff($perms, $np['usergroups'][$name]['privs']);
+	if(empty($diff))
+		return array('status' => 'success');
 
+	updateUserOrGroupPrivs($groupid, $nodeid, $diff, array(), "group");
+	return array('status' => 'success');
+}
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
@@ -1489,7 +1525,7 @@ function XMLRPCaddUserGroupPriv($name, $
 /// \b success - request was successfully extended\n
 ///
 /// \brief modifies the end time of an active request; if a request that has not
-/// started needs to be modifed, delete the request and submit a new one\n
+/// started needs to be modifed, delete the request and submit a new one
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCsetRequestEnding($requestid, $end) {
@@ -1521,6 +1557,13 @@ function XMLRPCsetRequestEnding($request
 
 	$end = processInputData($end, ARG_NUMERIC);
 
+	$maxend = datetimeToUnix("2038-01-01 00:00:00");
+	if($end < 0 || $end > $maxend) {
+		return array('status' => 'error',
+		             'errorcode' => 36,
+		             'errormsg' => "received invalid input for end");
+	}
+
 	$startts = datetimeToUnix($request['start']);
 	if($end % (15 * 60))
 		$end= unixFloor15($end) + (15 * 60);
@@ -1618,7 +1661,7 @@ function XMLRPCsetRequestEnding($request
 ///
 /// \b success - request was successfully ended\n
 ///
-/// \brief ends/deletes a request\n
+/// \brief ends/deletes a request
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCendRequest($requestid) {
@@ -1659,9 +1702,13 @@ function XMLRPCendRequest($requestid) {
 /// \li \b imageid - id of the image\n
 /// \li \b imagename - name of the image\n
 /// \li \b start - unix timestamp of start time\n
-/// \li \b end - unix timestamp of end time
+/// \li \b end - unix timestamp of end time\n
+/// \li \b OS - name of OS used in image\n
+/// \li \b isserver - 0 or 1 - whether or not this is a server reservation\n
+/// \li \b state - current state of reservation\n
+/// \li \b servername - only included if isserver == 1 - name of the reservation
 ///
-/// \brief gets information about all of user's requests\n
+/// \brief gets information about all of user's requests
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCgetRequestIds() {
@@ -1669,6 +1716,7 @@ function XMLRPCgetRequestIds() {
 	$requests = getUserRequests("all");
 	if(empty($requests))
 		return array('status' => 'success', 'requests' => array());
+	$states = getStates();
 	$ret = array();
 	foreach($requests as $req) {
 		$start = datetimeToUnix($req['start']);
@@ -1677,7 +1725,15 @@ function XMLRPCgetRequestIds() {
 		             'imageid' => $req['imageid'],
 		             'imagename' => $req['prettyimage'],
 		             'start' => $start,
-		             'end' => $end);
+		             'end' => $end,
+		             'OS' => $req['OS'],
+		             'isserver' => $req['server']);
+		if($req['currstateid'] == 14)
+			$tmp['state'] = $states[$req['laststateid']];
+		else
+			$tmp['state'] = $states[$req['currstateid']];
+		if($req['server'])
+			$tmp['servername'] = $req['servername'];
 		array_push($ret, $tmp);
 	}
 	return array('status' => 'success', 'requests' => $ret);
@@ -1694,7 +1750,7 @@ function XMLRPCgetRequestIds() {
 /// \param $end - mysql datetime for the end time
 /// \param $numMachines - number of computers to allocate
 /// \param $usergroupid - id of user group for checking user access to machines
-/// \param $ignoreprivileges (optional, default=0) - 0 (false) or 1 (true) - set
+/// \param $ignoreprivileges  - (optional, default=0) 0 (false) or 1 (true) - set
 /// to 1 to select computers from any that are mapped to be able to run the
 /// image; set to 0 to only select computers from ones that are both mapped and
 /// that users in the usergroup assigned to this block allocation have been
@@ -1703,32 +1759,33 @@ function XMLRPCgetRequestIds() {
 /// \return an array with blockTimesid as an index with the value of the newly
 /// created block time and at least one other index named 'status' which will
 /// have one of these values:\n
-/// \b error - error occurred; there will be 2 additional elements in the array:
-/// \li \b errorcode - error number
-/// \li \b errormsg - error string
+/// \b error - error occurred; there will be 2 additional elements in the
+/// array:\n
+/// \li \b errorcode - error number\n
+/// \li \b errormsg - error string\n
 ///
 /// \b success - blockTimesid was processed; there will be two additional
-/// elements in this case:
+/// elements in this case:\n
 /// \li \b allocated - total number of desired allocations that have been
-/// processed
+/// processed\n
 /// \li \b unallocated - total number of desired allocations that have not been
-/// processed
+/// processed\n
 ///
 /// \b warning - there was a non-fatal issue that occurred while processing
-/// the call; there will be four additional elements in this case:
-/// \li \b warningcode - warning number
-/// \li \b warningmsg - warning string
+/// the call; there will be four additional elements in this case:\n
+/// \li \b warningcode - warning number\n
+/// \li \b warningmsg - warning string\n
 /// \li \b allocated - total number of desired allocations that have been
-/// processed
+/// processed\n
 /// \li \b unallocated - total number of desired allocations that have not been
-/// processed
+/// processed\n\n
 ///
-/// note that status may be warning, but allocated may be 0 indicating there
+/// \b NOTE: status may be warning, but allocated may be 0 indicating there
 /// were no errors that occurred, but there simply were not any machines
 /// available
 ///
 /// \brief creates and processes a block allocation according to the passed
-/// in criteria\n
+/// in criteria
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCblockAllocation($imageid, $start, $end, $numMachines,
@@ -1739,6 +1796,59 @@ function XMLRPCblockAllocation($imageid,
 		             'errorcode' => 34,
 		             'errormsg' => 'access denied for managing block allocations');
 	}
+
+	# valid $imageid
+	$resources = getUserResources(array("imageAdmin", "imageCheckOut"));
+	$resources["image"] = removeNoCheckout($resources["image"]);
+	if(! array_key_exists($imageid, $resources['image'])) {
+		return array('status' => 'error',
+		             'errorcode' => 3,
+		             'errormsg' => "access denied to $imageid");
+	}
+
+	# validate $start and $end
+	$dtreg = '([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})';
+	$startts = datetimeToUnix($start);
+	$endts = datetimeToUnix($end);
+	$maxend = datetimeToUnix("2038-01-01 00:00:00");
+	if(! preg_match("/^$dtreg$/", $start) || $startts < 0 ||
+	   $startts > $maxend) {
+		return array('status' => 'error',
+		             'errorcode' => 4,
+		             'errormsg' => "received invalid input for start");
+	}
+	if(! preg_match("/^$dtreg$/", $end) || $endts < 0 ||
+	   $endts > $maxend) {
+		return array('status' => 'error',
+		             'errorcode' => 36,
+		             'errormsg' => "received invalid input for end");
+	}
+
+	# validate $numMachines
+	if(! is_numeric($numMachines) || $numMachines < MIN_BLOCK_MACHINES ||
+	   $numMachines > MAX_BLOCK_MACHINES) {
+		return array('status' => 'error',
+		             'errorcode' => 64,
+		             'errormsg' => 'The submitted number of seats must be between ' . MIN_BLOCK_MACHINES . ' and ' . MAX_BLOCK_MACHINES . '.');
+	}
+
+	# validate $usergroupid
+	$groups = getUserGroups();
+	if(! array_key_exists($usergroupid, $groups)) {
+		return array('status' => 'error',
+		             'errorcode' => 67,
+		             'errormsg' => 'Submitted user group does not exist');
+	}
+
+	# validate ignoreprivileges
+	if(! is_numeric($ignoreprivileges) ||
+	   $ignoreprivileges < 0 ||
+		$ignoreprivileges > 1) {
+		return array('status' => 'error',
+		             'errorcode' => 86,
+		             'errormsg' => 'ignoreprivileges must be 0 or 1');
+	}
+
 	$ownerid = getUserlistID('vclreload@Local');
 	$name = "API:$start";
 	$managementnodes = getManagementNodes('future');
@@ -1782,6 +1892,42 @@ function XMLRPCblockAllocation($imageid,
 	       .        "'$end')";
 	doQuery($query, 101);
 	$btid = dbLastInsertID();
+	$query = "INSERT INTO blockWebDate "
+	       .        "(blockRequestid, "
+	       .        "start, "
+	       .        "end, "
+	       .        "days) "
+	       . "VALUES "
+	       .        "($brid, "
+	       .        "'$start', "
+	       .        "'$end', "
+	       .        "0)";
+	doQuery($query);
+	$sh = date('g', $startts);
+	$smi = date('i', $startts);
+	$sme = date('a', $startts);
+	$eh = date('g', $startts);
+	$emi = date('i', $startts);
+	$eme = date('a', $startts);
+	$query = "INSERT INTO blockWebTime "
+	       .        "(blockRequestid, "
+	       .        "starthour, "
+	       .        "startminute, "
+	       .        "startmeridian, "
+	       .        "endhour, "
+	       .        "endminute, "
+	       .        "endmeridian, "
+	       .        "`order`) "
+	       . "VALUES "
+	       .        "($brid, "
+	       .        "$sh,"
+	       .        "$smi,"
+	       .        "'$sme',"
+	       .        "$eh,"
+	       .        "$emi,"
+	       .        "'$eme',"
+	       .        "0)";
+	doQuery($query);
 	$return = XMLRPCprocessBlockTime($btid, $ignoreprivileges);
 	$return['blockTimesid'] = $btid;
 	return $return;
@@ -1792,7 +1938,7 @@ function XMLRPCblockAllocation($imageid,
 /// \fn XMLRPCprocessBlockTime($blockTimesid, $ignoreprivileges)
 ///
 /// \param $blockTimesid - id from the blockTimes table
-/// \param $ignoreprivileges (optional, default=0) - 0 (false) or 1 (true) - set
+/// \param $ignoreprivileges - (optional, default=0) 0 (false) or 1 (true) - set
 /// to 1 to select computers from any that are mapped to be able to run the
 /// image; set to 0 to only select computers from ones that are both mapped and
 /// that users in the usergroup assigned to this block allocation have been
@@ -1806,27 +1952,27 @@ function XMLRPCblockAllocation($imageid,
 ///
 /// \b completed - blockTimesid was previously successfully processed\n
 /// \b success - blockTimesid was processed; there will be two additional
-/// elements in this case:
+/// elements in this case:\n
 /// \li \b allocated - total number of desired allocations that have been
-/// processed
+/// processed\n
 /// \li \b unallocated - total number of desired allocations that have not been
-/// processed
+/// processed\n
 ///
 /// \b warning - there was a non-fatal issue that occurred while processing
-/// the call; there will be four additional elements in this case:
-/// \li \b warningcode - warning number
-/// \li \b warningmsg - warning string
+/// the call; there will be four additional elements in this case:\n
+/// \li \b warningcode - warning number\n
+/// \li \b warningmsg - warning string\n
 /// \li \b allocated - total number of desired allocations that have been
-/// processed
+/// processed\n
 /// \li \b unallocated - total number of desired allocations that have not been
-/// processed
+/// processed\n\n
 ///
-/// note that status may be warning, but allocated may be 0 indicating there
+/// \b NOTE: status may be warning, but allocated may be 0 indicating there
 /// were no errors that occurred, but there simply were not any machines
 /// available
 ///
 /// \brief processes a block allocation for the blockTimes entry associated
-/// with blockTimesid\n
+/// with blockTimesid
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCprocessBlockTime($blockTimesid, $ignoreprivileges=0) {
@@ -1836,6 +1982,23 @@ function XMLRPCprocessBlockTime($blockTi
 		             'errorcode' => 34,
 		             'errormsg' => 'access denied for managing block allocations');
 	}
+
+	# validate $blockTimesid
+	if(! is_numeric($blockTimesid)) {
+		return array('status' => 'error',
+		             'errorcode' => 77,
+		             'errormsg' => 'Invalid blockTimesid specified');
+	}
+
+	# validate ignoreprivileges
+	if(! is_numeric($ignoreprivileges) ||
+	   $ignoreprivileges < 0 ||
+		$ignoreprivileges > 1) {
+		return array('status' => 'error',
+		             'errorcode' => 86,
+		             'errormsg' => 'ignoreprivileges must be 0 or 1');
+	}
+
 	$return = array('status' => 'success');
 	$query = "SELECT bt.start, "
 	       .        "bt.end, "
@@ -1937,17 +2100,17 @@ function XMLRPCprocessBlockTime($blockTi
 				$blockCompVals[] = "($blockTimesid, $compid, $subimageid, $reqid)";
 
 				$query = "INSERT INTO reservation "
-						 .        "(requestid, "
-						 .        "computerid, "
-						 .        "imageid, "
-						 .        "imagerevisionid, "
-						 .        "managementnodeid) "
-						 . "VALUES "
-						 .       "($reqid, "
-						 .       "$compid, "
-						 .       "$subimageid, "
-						 .       "$subrevid, "
-						 .       "$mgmtnodeid)";
+				       .        "(requestid, "
+				       .        "computerid, "
+				       .        "imageid, "
+				       .        "imagerevisionid, "
+				       .        "managementnodeid) "
+				       . "VALUES "
+				       .       "($reqid, "
+				       .       "$compid, "
+				       .       "$subimageid, "
+				       .       "$subrevid, "
+				       .       "$mgmtnodeid)";
 				doQuery($query, 101);
 			}
 		}
@@ -2000,7 +2163,7 @@ function XMLRPCprocessBlockTime($blockTi
 			$userids = array_splice($userids, 0, $reqToAlloc);
 	}
 
-	# staggering: stagger start times for this round (ie, don't worry about
+	# staggering: stagger start times for this round (ie, do not worry about
 	#   previous processing of this block time) such that there is 1 minute
 	#   between the start times for each allocation
 	$stagExtra = $reqToAlloc * 60;
@@ -2058,17 +2221,17 @@ function XMLRPCprocessBlockTime($blockTi
 			$blockCompVals[] = "($blockTimesid, $compid, $subimageid, $reqid)";
 
 			$query = "INSERT INTO reservation "
-					 .        "(requestid, "
-					 .        "computerid, "
-					 .        "imageid, "
-					 .        "imagerevisionid, "
-					 .        "managementnodeid) "
-					 . "VALUES "
-					 .       "($reqid, "
-					 .       "$compid, "
-					 .       "$subimageid, "
-					 .       "$subrevid, "
-					 .       "$mgmtnodeid)";
+			       .        "(requestid, "
+			       .        "computerid, "
+			       .        "imageid, "
+			       .        "imagerevisionid, "
+			       .        "managementnodeid) "
+			       . "VALUES "
+			       .       "($reqid, "
+			       .       "$compid, "
+			       .       "$subimageid, "
+			       .       "$subrevid, "
+			       .       "$mgmtnodeid)";
 			doQuery($query, 101);
 		}
 		semUnlock();
@@ -2106,19 +2269,19 @@ function XMLRPCprocessBlockTime($blockTi
 ///                        for a reservation (including all extensions)
 /// \param $maxExtendTime - (minutes) max length of time users can request as an
 ///                         extension to a reservation at a time
-/// \param $custom (optional, default=1) - set custom flag for user group; if
+/// \param $custom - (optional, default=1) set custom flag for user group; if
 ///                set to 0, $owner and $managingGroup will be ignored and group
 ///                membership will be managed via authentication protocol
 ///
 /// \return an array with at least one index named 'status' which will have
 /// one of these values:\n
 /// \b error - error occurred; there will be 2 additional elements in the array:
-/// \li \b errorcode - error number
+/// \li \b errorcode - error number\n
 /// \li \b errormsg - error string
 ///
 /// \b success - user group was successfully created
 ///
-/// \brief creates a new user group with the specified parameters\n
+/// \brief creates a new user group with the specified parameters
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCaddUserGroup($name, $affiliation, $owner, $managingGroup,
@@ -2128,7 +2291,7 @@ function XMLRPCaddUserGroup($name, $affi
 	if(! in_array('groupAdmin', $user['privileges'])) {
 		return array('status' => 'error',
 		             'errorcode' => 16,
-		             'errormsg' => 'access denied for managing user groups');
+		             'errormsg' => 'access denied for managing groups');
 	}
 	$validate = array('name' => $name,
 	                  'affiliation' => $affiliation,
@@ -2143,6 +2306,8 @@ function XMLRPCaddUserGroup($name, $affi
 		return $rc;
 	if($custom != 0 && $custom != 1)
 		$custom = 1;
+	if(! $custom)
+		$rc['managingGroupID'] = NULL;
 	$data = array('type' => 'user',
 	              'owner' => $owner,
 	              'name' => $name,
@@ -2173,25 +2338,24 @@ function XMLRPCaddUserGroup($name, $affi
 /// \li \b errorcode - error number\n
 /// \li \b errormsg - error string\n
 ///
-/// \b success - an 'groups' element will contain a list of groups
-///         of the given type.\n
+/// \b success - a 'groups' element will contain an array of groups of the given
+/// type\n
 ///
-/// \brief get a list of resource groups of a particular type\n
+/// \brief get a list of resource groups of a particular type
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function XMLRPCgetResourceGroups($type){
-    global $user;
-    $resources = getUserResources(array("groupAdmin"), array("manageGroup"), 1);
-    if(array_key_exists($type, $resources)){
-        return array(
-            'status' => 'success',
-            'groups' => $resources[$type]);
-    } else {
-        return array(
-            'status' => 'error',
-            'errorcode' => 29,
-            'errormsg' => 'invalid resource group type');
-    }
+function XMLRPCgetResourceGroups($type) {
+	global $user;
+	$resources = getUserResources(array("groupAdmin"), array("manageGroup"), 1);
+	if(array_key_exists($type, $resources)) {
+		return array('status' => 'success',
+		             'groups' => $resources[$type]);
+	}
+	else {
+		return array('status' => 'error',
+		             'errorcode' => 73,
+		             'errormsg' => 'invalid resource group type');
+	}
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -2209,88 +2373,41 @@ function XMLRPCgetResourceGroups($type){
 ///
 /// \b success - the resource group was removed\n
 ///
-/// \brief remove a resource group\n
-///
-////////////////////////////////////////////////////////////////////////////////
-function XMLRPCremoveResourceGroup($name, $type){
-    global $user;
-    if(! in_array("groupAdmin", $user['privileges'])){
-        return array('status' => 'error',
-                     'errorcode' => 16,
-                     'errormsg' => 'access denied for managing user groups');
-    }
-
-    if($groupid = getResourceGroupID("$type/$name")){
-        $userresources = getUserResources(
-            array("groupAdmin"),
-            array("manageGroup"), 1);
-        if(array_key_exists($type, $userresources)){
-            if(array_key_exists($groupid, $userresources[$type])){
-                $query = "DELETE FROM resourcegroup "
-                       . "WHERE id = $groupid";
-                doQuery($query, 315);
-                return array('status' => 'success');
-            }
-        }
-    }
-    return array('status' => 'error',
-                 'errorcode' => 39,
-                 'errormsg' => 'invalid resource group name');
-}
-
-////////////////////////////////////////////////////////////////////////////////
-///
-/// \fn XMLRPCremoveUserGroup($name, $affiliation)
-///
-/// \param $name - the name of the resource group
-/// \param $affiliation - the affiliation of the user group
-///
-/// \return an array with at least one index named 'status' which will have
-/// one of these values\n
-/// \b error - error occurred; there will be 2 additional elements in the array:
-/// \li \b errorcode - error number\n
-/// \li \b errormsg - error string\n
-///
-/// \b success - the user group was removed\n
-///
-/// \brief remove a user group\n
+/// \brief remove a resource group
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function XMLRPCremoveUserGroup($name, $affiliation){
-    global $user;
+function XMLRPCremoveResourceGroup($name, $type) {
+	global $user;
+	if(! in_array("groupAdmin", $user['privileges'])) {
+		return array('status' => 'error',
+		             'errorcode' => 16,
+		             'errormsg' => 'access denied for managing groups');
+	}
 
-    if(! in_array("groupAdmin", $user['privileges'])){
-        return array('status' => 'error',
-                     'errorcode' => 16,
-                     'errormsg' => 'access denied for managing user groups');
-    }
-
-    $validate = array(
-        'name' => $name,
-        'affiliation' => $affiliation);
-
-    $rc = validateAPIgroupInput($validate, 1);
-    if($rc['status'] == 'error')
-        return $rc;
-
-    $groups = getUserGroups();
-    $groupid = $rc['id'];
-    if(array_key_exists($groupid, $groups)){
-        $group = $groups[$groupid];
-        if($group['ownerid'] == $user['id'] ||
-                (array_key_exists("editgroupid", $group) &&
-                array_key_exists($group['editgroupid'], $user["groups"])) || 
-                (array_key_exists($groupid, $user["groups"]))){
-            $query = "DELETE FROM usergroup "
-                   . "WHERE id = $groupid";
-            doQuery($query, 315);
-            return array('status' => 'success');
-        }
-    }
-    return array(
-        'status' => 'error',
-        'errorcode' => 17,
-        'errormsg' => 'access denied for editing specified group');
+	if($groupid = getResourceGroupID("$type/$name")) {
+		$userresources = getUserResources(array("groupAdmin"),
+		                                  array("manageGroup"), 1);
+		if(array_key_exists($type, $userresources)) {
+			if(array_key_exists($groupid, $userresources[$type])) {
+				if(checkForGroupUsage($groupid, 'resource')) {
+					return array('status' => 'error',
+					             'errorcode' => 72,
+					             'errormsg' => 'group currently in use and cannot be removed');
+				}
+				$query = "DELETE FROM resourcegroup "
+				       . "WHERE id = $groupid";
+				doQuery($query, 315);
+				return array('status' => 'success');
+			}
+			else
+				return array('status' => 'error',
+				             'errorcode' => 75,
+				             'errormsg' => 'access denied to specified resource group');
+		}
+	}
+	return array('status' => 'error',
+	             'errorcode' => 83,
+	             'errormsg' => 'invalid resource group name');
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -2307,48 +2424,55 @@ function XMLRPCremoveUserGroup($name, $a
 /// \li \b errorcode - error number\n
 /// \li \b errormsg - error string\n
 ///
-/// \b success - the resource group was added\n
+/// \b success - the resource group was added
 ///
-/// \brief add a resource group\n
+/// \brief add a resource group
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function XMLRPCaddResourceGroup($name, $managingGroup, $type){
-    global $user;
-    if(! in_array("groupAdmin", $user['privileges'])){
-        return array('status' => 'error',
-                     'errorcode' => 16,
-                     'errormsg' => 'access denied for managing user groups');
-    }
-
-    $validate = array(
-        'managingGroup' => $managingGroup);
-    
-    $rc = validateAPIgroupInput($validate, 0);
-    if($rc['status'] == 'error')
-        return $rc;
-
-    if($typeid = getResourceTypeID($type)){
-        if(checkForGroupName($name, 'resource', '', $typeid)){
-            return array('status' => 'error',
-                         'errorcode' => 28,
-                         'errormsg' => 'resource group already exists');
-        }
-        $data = array(
-            'type' => $type,
-            'ownergroup' => $rc['managingGroupID'],
-            'resourcetypeid' => $typeid,
-            'name' => $name);
-        if(! addGroup($data)){
-            return array('status' => 'error',
-                         'errorcode' => 26,
-                         'errormsg' => 'failure while adding group to database');
-        }
-    } else {
-        return array('status' => 'error',
-                     'errorcode' => 68,
-                     'errormsg' => 'invalid resource type');
-    }
-    return array('status' => 'success');
+function XMLRPCaddResourceGroup($name, $managingGroup, $type) {
+	global $user;
+	if(! in_array("groupAdmin", $user['privileges'])) {
+		return array('status' => 'error',
+		             'errorcode' => 16,
+		             'errormsg' => 'access denied for managing groups');
+	}
+
+	$validate = array('managingGroup' => $managingGroup);
+
+	$rc = validateAPIgroupInput($validate, 0);
+	if($rc['status'] == 'error')
+		return $rc;
+
+	if($typeid = getResourceTypeID($type)) {
+		if(checkForGroupName($name, 'resource', '', $typeid)) {
+			return array('status' => 'error',
+			             '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,
+			             'errormsg' => 'Name must be between 3 and 30 characters and can only contain letters, numbers, spaces, and these characters: - . _');
+		}
+		$name = mysql_real_escape_string($name);
+		$data = array('type' => 'resource',
+		              'ownergroup' => $rc['managingGroupID'],
+		              'resourcetypeid' => $typeid,
+		              'name' => $name);
+		if(! addGroup($data)) {
+			return array('status' => 'error',
+			             'errorcode' => 26,
+			             'errormsg' => 'failure while adding group to database');
+		}
+	}
+	else {
+		return array('status' => 'error',
+		             'errorcode' => 68,
+		             'errormsg' => 'invalid resource type');
+	}
+	return array('status' => 'success');
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -2364,7 +2488,7 @@ function XMLRPCaddResourceGroup($name, $
 /// \li \b errorcode - error number
 /// \li \b errormsg - error string
 ///
-/// \b success - there will be five additional elements in this case:
+/// \b success - there will be six additional elements in this case:
 /// \li \b owner - user that will be the owner of the group in
 ///                username\@affiliation form
 /// \li \b managingGroup - user group that can manage membership of this one in
@@ -2375,8 +2499,10 @@ function XMLRPCaddResourceGroup($name, $
 ///                       a reservation (including all extensions)
 /// \li \b maxExtendTime - (minutes) max length of time users can request as an
 ///                        extension to a reservation at a time
+/// \li \b overlapResCount - maximum allowed number of overlapping reservations
+/// allowed for users in this group
 ///
-/// \brief gets information about a user group\n
+/// \brief gets information about a user group
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function XMLRPCgetUserGroupAttributes($name, $affiliation) {
@@ -2384,7 +2510,7 @@ function XMLRPCgetUserGroupAttributes($n
 	if(! in_array('groupAdmin', $user['privileges'])) {
 		return array('status' => 'error',
 		             'errorcode' => 16,
-		             'errormsg' => 'access denied for managing user groups');
+		             'errormsg' => 'access denied for managing groups');
 	}
 	$validate = array('name' => $name,
 	                  'affiliation' => $affiliation);
@@ -2414,24 +2540,26 @@ function XMLRPCgetUserGroupAttributes($n
 		             'errorcode' => 18,
 		             'errormsg' => 'user group with submitted name and affiliation does not exist');
 	}
-	# if not owner and not member of managing group, no access
+	// if not owner and not member of managing group, no access
 	if($user['id'] != $row['ownerid'] && 
 	   ! array_key_exists($row['editgroupid'], $user['groups'])) {
 		return array('status' => 'error',
-		             'errorcode' => 28,
+		             'errorcode' => 69,
 		             'errormsg' => 'access denied to user group with submitted name and affiliation');
 	}
-	return array('status' => 'success',
+	$ret = array('status' => 'success',
 	             'owner' => $row['owner'],
 	             'managingGroup' => "{$row['editgroup']}@{$row['editgroupaffiliation']}",
 	             'initialMaxTime' => $row['initialmaxtime'],
 	             'totalMaxTime' => $row['totalmaxtime'],
-	             'maxExtendTime' => $row['maxextendtime']);
+	             'maxExtendTime' => $row['maxextendtime'],
+	             'overlapResCount' => $row['overlapResCount']);
+	return $ret;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
-/// \fn XMLRPCdeleteUserGroup($name, $affiliation)
+/// \fn XMLRPCremoveUserGroup($name, $affiliation)
 ///
 /// \param $name - name of user group
 /// \param $affiliation - affiliation of user group
@@ -2442,24 +2570,27 @@ function XMLRPCgetUserGroupAttributes($n
 /// \li \b errorcode - error number
 /// \li \b errormsg - error string
 ///
-/// \b success - user group was successfully deleted
+/// \b success - user group was successfully removed
 ///
-/// \brief deletes a user group along with all of its privileges\n
+/// \brief removes a user group along with all of its privileges
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function XMLRPCdeleteUserGroup($name, $affiliation) {
+function XMLRPCremoveUserGroup($name, $affiliation) {
 	global $user, $mysql_link_vcl;
 	if(! in_array('groupAdmin', $user['privileges'])) {
 		return array('status' => 'error',
 		             'errorcode' => 16,
-		             'errormsg' => 'access denied for managing user groups');
+		             'errormsg' => 'access denied for managing groups');
 	}
 	$validate = array('name' => $name,
 	                  'affiliation' => $affiliation);
 	$rc = validateAPIgroupInput($validate, 1);
 	if($rc['status'] == 'error')
 		return $rc;
-	$query = "SELECT ownerid "
+	$query = "SELECT ownerid, "
+	       .        "affiliationid, "
+	       .        "custom, "
+	       .        "courseroll "
 	       . "FROM usergroup "
 	       . "WHERE id = {$rc['id']}";
 	$qh = doQuery($query, 101);
@@ -2468,14 +2599,24 @@ function XMLRPCdeleteUserGroup($name, $a
 		             'errorcode' => 18,
 		             'errormsg' => 'user group with submitted name and affiliation does not exist');
 	}
-	# if not owner no access to delete group
-	if($user['id'] != $row['ownerid']) {
+
+	// if custom and not owner or custom/courseroll and no federated user group access, no access to delete group
+	if(($row['custom'] == 1 && $user['id'] != $row['ownerid']) ||
+	   (($row['custom'] == 0 || $row['courseroll'] == 1) &&
+	   ! checkUserHasPerm('Manage Federated User Groups (global)') &&
+	   (! checkUserHasPerm('Manage Federated User Groups (affiliation only)') ||
+	   $row['affiliationid'] != $user['affiliationid']))) {
 		return array('status' => 'error',
 		             'errorcode' => 29,
 		             'errormsg' => 'access denied to delete user group with submitted name and affiliation');
 	}
+	if(checkForGroupUsage($rc['id'], 'user')) {
+		return array('status' => 'error',
+		             'errorcode' => 72,
+		             'errormsg' => 'group currently in use and cannot be removed');
+	}
 	$query = "DELETE FROM usergroup "
-			 . "WHERE id = {$rc['id']}";
+	       . "WHERE id = {$rc['id']}";
 	doQuery($query, 101);
 	# validate something deleted
 	if(mysql_affected_rows($mysql_link_vcl) == 0) {
@@ -2488,6 +2629,31 @@ function XMLRPCdeleteUserGroup($name, $a
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
+/// \fn XMLRPCdeleteUserGroup($name, $affiliation)
+///
+/// \param $name - name of user group
+/// \param $affiliation - affiliation of user group
+///
+/// \return an array with at least one index named 'status' which will have
+/// one of these values:\n
+/// \b error - error occurred; there will be 2 additional elements in the array:
+/// \li \b errorcode - error number
+/// \li \b errormsg - error string
+///
+/// \b success - user group was successfully removed
+///
+/// \brief alias for XMLRPCremoveUserGroup
+///
+////////////////////////////////////////////////////////////////////////////////
+function XMLRPCdeleteUserGroup($name, $affiliation) {
+	# This was the original function. All other functions use 'remove' rather
+	# than 'delete'. The function was renamed to XMLRPCremoveUserGroup. This was
+	# kept for compatibility reasons
+	return XMLRPCremoveUserGroup($name, $affiliation);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
 /// \fn XMLRPCeditUserGroup($name, $affiliation, $newName, $newAffiliation,
 ///                         $newOwner, $newManagingGroup, $newInitialMaxTime,
 ///                         $newTotalMaxTime, $newMaxExtendTime)
@@ -2520,7 +2686,7 @@ function XMLRPCdeleteUserGroup($name, $a
 ///
 /// \brief modifies attributes of a user group\n
 /// \b NOTE: an empty string may be passed for any of the new* fields to leave
-/// that item unchanged\n
+/// that item unchanged
 ///
 ////////////////////////////////////////////////////////////////////////////////

[... 510 lines stripped ...]