Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/LibraryServlet.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/LibraryServlet.java	(revision 25091)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/LibraryServlet.java	(revision 25092)
@@ -13,4 +13,7 @@
 import javax.servlet.*;
 import javax.servlet.http.*;
+
+import java.security.Principal;
+import java.util.Collection;
 import java.util.Enumeration;
 import java.util.ArrayList;
@@ -96,5 +99,5 @@
 	 */
 	protected Hashtable session_ids_table = new Hashtable();
-
+	
 	/**
 	 * the maximum interval that the cached info remains in session_ids_table
@@ -356,6 +359,6 @@
 	{
 		logUsageInfo(request);
-		
-		Map<String,String[]> queryMap = request.getParameterMap();
+
+		Map<String, String[]> queryMap = request.getParameterMap();
 		if (queryMap != null)
 		{
@@ -473,4 +476,5 @@
 		String subaction = request.getParameter(GSParams.SUBACTION);
 		String collection = request.getParameter(GSParams.COLLECTION);
+		String document = request.getParameter(GSParams.DOCUMENT);
 		String service = request.getParameter(GSParams.SERVICE);
 
@@ -695,4 +699,98 @@
 						response.setHeader(name, value);
 					}
+				}
+			}
+		}
+
+		//Check if we need to login or logout
+		Map<String, String[]> params = request.getParameterMap();
+		String[] username = params.get("username");
+		String[] password = params.get("password");
+		String[] logout = params.get("logout");
+
+		if (logout != null)
+		{
+			request.logout();
+		}
+
+		if (username != null && password != null)
+		{
+			if (request.getAuthType() != null)
+			{
+				request.logout();
+			}
+			request.login(username[0], password[0]);
+		}
+		
+		if(request.getAuthType() != null)
+		{
+			Element userInformation = this.doc.createElement("userInformation");
+			xml_request.appendChild(userInformation);
+			userInformation.setAttribute("username", request.getUserPrincipal().getName());
+		}
+			
+
+		//If we are in a collection-related page then make sure this user is allowed to access it
+		if (collection != null && !collection.equals(""))
+		{
+			//Get the security info for this collection
+			Element securityMessage = this.doc.createElement(GSXML.MESSAGE_ELEM);
+			Element securityRequest = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_SECURITY, collection, userContext);
+			securityMessage.appendChild(securityRequest);
+			if (document != null && !document.equals(""))
+			{
+				securityRequest.setAttribute("oid", document);
+			}
+
+			Element securityResponse = (Element) GSXML.getChildByTagName(this.recept.process(securityMessage), GSXML.RESPONSE_ELEM);
+			ArrayList<String> groups = GSXML.getGroupsFromSecurityResponse(securityResponse);
+
+			//If guests are not allowed to access this page then check to see if the user is in a group that is allowed to access the page
+			if (!groups.contains(""))
+			{
+				boolean found = false;
+				for (String group : groups)
+				{
+					if (request.isUserInRole(group))
+					{
+						found = true;
+						break;
+					}
+				}
+
+				//The current user is not allowed to access the page so produce a login page
+				if (!found)
+				{
+					Element loginPageMessage = this.doc.createElement(GSXML.MESSAGE_ELEM);
+					Element loginPageRequest = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PAGE, "", userContext);
+					loginPageRequest.setAttribute(GSXML.ACTION_ATT, "p");
+					loginPageRequest.setAttribute(GSXML.SUBACTION_ATT, "login");
+					loginPageRequest.setAttribute(GSXML.OUTPUT_ATT, "html");
+					loginPageMessage.appendChild(loginPageRequest);
+
+					Element paramList = this.doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
+					loginPageRequest.appendChild(paramList);
+					
+					Element messageParam = this.doc.createElement(GSXML.PARAM_ELEM);
+					messageParam.setAttribute(GSXML.NAME_ATT, "loginMessage");
+					if(request.getAuthType() == null)
+					{
+						messageParam.setAttribute(GSXML.VALUE_ATT, "Please log in to view this page");
+					}
+					else
+					{
+						messageParam.setAttribute(GSXML.VALUE_ATT, "You are not in the correct group to view this page");
+					}
+					paramList.appendChild(messageParam);
+					
+					Element urlParam = this.doc.createElement(GSXML.PARAM_ELEM);
+					urlParam.setAttribute(GSXML.NAME_ATT, "redirectURL");
+					urlParam.setAttribute(GSXML.VALUE_ATT, this.getServletName() + "?" + request.getQueryString().replace("&", "&amp;"));
+					paramList.appendChild(urlParam);
+
+					Node loginPageResponse = this.recept.process(loginPageMessage);
+					out.println(this.converter.getPrettyString(loginPageResponse));
+
+					return;
 				}
 			}
Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/collection/Collection.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/collection/Collection.java	(revision 25091)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/collection/Collection.java	(revision 25092)
@@ -30,6 +30,4 @@
 
 import java.io.*;
-import java.io.File;
-import java.util.HashMap;
 import java.util.*;
 
@@ -70,4 +68,13 @@
 	/** earliestDatestamp of this collection. Necessary for OAI */
 	protected long earliestDatestamp = 0;
+
+	/** Stores the default accessibility of guest users */
+	protected boolean _publicAccess = true;
+	/** Stores the scope of any security rules (either collection or document) */
+	protected boolean _securityScopeCollection = true;
+
+	protected HashMap<String, ArrayList<Element>> _documentSets = new HashMap<String, ArrayList<Element>>();
+
+	protected ArrayList<HashMap<String, ArrayList<String>>> _securityExceptions = new ArrayList<HashMap<String, ArrayList<String>>>();
 
 	/**
@@ -125,5 +132,5 @@
 			col_type = search.getAttribute(GSXML.TYPE_ATT);
 		}
-		
+
 		Element browse = (Element) GSXML.getChildByTagName(coll_config_xml, GSXML.INFODB_ELEM);
 		if (browse != null)
@@ -138,4 +145,6 @@
 		// process the metadata and display items
 		findAndLoadInfo(coll_config_xml, build_config_xml);
+
+		loadSecurityInformation(coll_config_xml);
 
 		// now do the services
@@ -207,5 +216,4 @@
 	protected Element loadBuildConfigFile()
 	{
-
 		File build_config_file = new File(GSFile.collectionBuildConfigFile(this.site_home, this.cluster_name));
 		if (!build_config_file.exists())
@@ -232,6 +240,4 @@
 	protected boolean findAndLoadInfo(Element coll_config_xml, Element build_config_xml)
 	{
-
-		// metadata
 		Element meta_list = (Element) GSXML.getChildByTagName(coll_config_xml, GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER);
 		addMetadata(meta_list);
@@ -293,4 +299,92 @@
 		return true;
 
+	}
+
+	protected void loadSecurityInformation(Element coll_config_xml)
+	{
+		Element securityBlock = (Element) GSXML.getChildByTagName(coll_config_xml, GSXML.SECURITY_ELEM);
+
+		if(securityBlock == null)
+		{
+			return;
+		}
+		
+		String scope = securityBlock.getAttribute(GSXML.SCOPE_ATT);
+		String defaultAccess = securityBlock.getAttribute(GSXML.DEFAULT_ACCESS_ATT);
+
+		if (defaultAccess.toLowerCase().equals("public"))
+		{
+			_publicAccess = true;
+		}
+		else if (defaultAccess.toLowerCase().equals("private"))
+		{
+			_publicAccess = false;
+		}
+		else
+		{
+			logger.warn("Default access for collection " + this.cluster_name + " is neither public or private, assuming public");
+		}
+
+		if (scope.toLowerCase().equals("collection"))
+		{
+			_securityScopeCollection = true;
+		}
+		else if (scope.toLowerCase().equals("documents") || scope.toLowerCase().equals("document"))
+		{
+			_securityScopeCollection = false;
+		}
+		else
+		{
+			logger.warn("Security scope is neither collection or document, assuming collection");
+		}
+
+		NodeList exceptions = GSXML.getChildrenByTagName(securityBlock, GSXML.EXCEPTION_ELEM);
+
+		if (exceptions.getLength() > 0)
+		{
+			if (!_securityScopeCollection)
+			{
+				NodeList documentSetElems = GSXML.getChildrenByTagName(securityBlock, GSXML.DOCUMENT_SET_ELEM);
+				for (int i = 0; i < documentSetElems.getLength(); i++)
+				{
+					Element documentSet = (Element) documentSetElems.item(i);
+					String setName = documentSet.getAttribute(GSXML.NAME_ATT);
+					NodeList matchStatements = GSXML.getChildrenByTagName(documentSet, GSXML.MATCH_ELEM);
+					ArrayList<Element> matchStatementList = new ArrayList<Element>();
+					for (int j = 0; j < matchStatements.getLength(); j++)
+					{
+						matchStatementList.add((Element) matchStatements.item(j));
+					}
+					_documentSets.put(setName, matchStatementList);
+				}
+			}
+
+			for (int i = 0; i < exceptions.getLength(); i++)
+			{
+				HashMap<String, ArrayList<String>> securityException = new HashMap<String, ArrayList<String>>();
+				ArrayList<String> exceptionGroups = new ArrayList<String>();
+				ArrayList<String> exceptionSets = new ArrayList<String>();
+
+				Element exception = (Element) exceptions.item(i);
+				NodeList groups = GSXML.getChildrenByTagName(exception, GSXML.GROUP_ELEM);
+				for (int j = 0; j < groups.getLength(); j++)
+				{
+					Element group = (Element) groups.item(j);
+					String groupName = group.getAttribute(GSXML.NAME_ATT);
+					exceptionGroups.add(groupName);
+				}
+				NodeList docSets = GSXML.getChildrenByTagName(exception, GSXML.DOCUMENT_SET_ELEM);
+				for (int j = 0; j < docSets.getLength(); j++)
+				{
+					Element docSet = (Element) docSets.item(j);
+					String docSetName = docSet.getAttribute(GSXML.NAME_ATT);
+					exceptionSets.add(docSetName);
+				}
+
+				securityException.put("groups", exceptionGroups);
+				securityException.put("sets", exceptionSets);
+				_securityExceptions.add(securityException);
+			}
+		}
 	}
 
@@ -431,5 +525,5 @@
 				classifier = request.getAttribute("classifier");
 			}
-			
+
 			// check for version file
 			String directory = new File(GSFile.collectionConfigFile(this.site_home, this.cluster_name)).getParent() + File.separator;
@@ -661,4 +755,19 @@
 			}
 		}
+		else if (type.equals(GSXML.REQUEST_TYPE_SECURITY))
+		{
+			String oid = request.getAttribute("oid");
+			ArrayList<String> groups = getPermittedGroups(oid);
+			
+			Element groupList = this.doc.createElement(GSXML.GROUP_ELEM + GSXML.LIST_MODIFIER);
+			response.appendChild(groupList);
+			
+			for(String groupName : groups)
+			{
+				Element group = this.doc.createElement(GSXML.GROUP_ELEM);
+				groupList.appendChild(group);
+				group.setAttribute(GSXML.NAME_ATT, groupName);
+			}
+		}
 		else
 		{ // unknown type
@@ -669,3 +778,152 @@
 	}
 
+	protected ArrayList<String> getPermittedGroups(String oid)
+	{
+		ArrayList<String> groups = new ArrayList<String>();
+		
+		if (_securityScopeCollection)
+		{
+			if (_publicAccess)
+			{
+				groups.add("");
+			}
+			else
+			{
+				for (HashMap<String, ArrayList<String>> exception : _securityExceptions)
+				{
+					for (String group : exception.get("groups"))
+					{
+						groups.add(group);
+					}
+				}
+			}
+		}
+		else
+		{
+			if(oid != null && !oid.equals(""))
+			{
+				boolean inSet = false;
+				for (HashMap<String, ArrayList<String>> exception : _securityExceptions)
+				{
+					for (String setName : exception.get("sets"))
+					{
+						if (documentIsInSet(oid, setName))
+						{
+							inSet = true;
+							for (String group : exception.get("groups"))
+							{
+								groups.add(group);
+							}
+						}
+					}
+				}
+				
+				if(!inSet && _publicAccess)
+				{
+					groups.add("");
+				}
+			}
+			else
+			{
+				groups.add("");
+			}
+		}
+
+		return groups;
+	}
+
+	protected boolean documentIsInSet(String oid, String setName)
+	{
+		ArrayList<Element> matchStatements = _documentSets.get(setName);
+		if (matchStatements == null || matchStatements.size() == 0)
+		{
+			return false;
+		}
+
+		for (Element currentMatchStatement : matchStatements)
+		{
+			String fieldName = currentMatchStatement.getAttribute(GSXML.FIELD_ATT);
+			if (fieldName == null || fieldName.equals(""))
+			{
+				fieldName = "oid";
+			}
+
+			String type = currentMatchStatement.getAttribute(GSXML.TYPE_ATT);
+			if (type == null || type.equals(""))
+			{
+				type = "match";
+			}
+
+			String fieldValue = "";
+			if (!fieldName.equals("oid"))
+			{
+				fieldValue = getFieldValue(oid, fieldName);
+				if(fieldValue == null)
+				{
+					return false;
+				}
+			}
+			else
+			{
+				fieldValue = oid;
+			}
+
+			String matchValue = GSXML.getNodeText(currentMatchStatement);
+			if (type.equals("match"))
+			{ 
+				if(matchValue.equals(fieldValue))
+				{
+					return true;
+				}
+			}
+			else if (type.equals("regex"))
+			{
+				if(fieldValue.matches(matchValue))
+				{
+					return true;
+				}
+			}
+			else
+			{
+				logger.warn("Unknown type of match specified in security block of collection " + this.cluster_name + ".");
+			}
+		}
+
+		return false;
+	}
+
+	protected String getFieldValue(String oid, String fieldName)
+	{
+		Element metadataMessage = this.doc.createElement(GSXML.MESSAGE_ELEM);
+		Element metadataRequest = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, this.cluster_name + "/DocumentMetadataRetrieve", new UserContext());
+		metadataMessage.appendChild(metadataRequest);
+
+		Element paramList = this.doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
+		metadataRequest.appendChild(paramList);
+		
+		Element param = this.doc.createElement(GSXML.PARAM_ELEM);
+		paramList.appendChild(param);
+		
+		param.setAttribute(GSXML.NAME_ATT, "metadata");
+		param.setAttribute(GSXML.VALUE_ATT, fieldName);
+		
+		Element docList = this.doc.createElement(GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER);
+		metadataRequest.appendChild(docList);
+		
+		Element doc = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+		docList.appendChild(doc);
+		
+		doc.setAttribute(GSXML.NODE_ID_ATT, oid);
+		
+		Element response = (Element) this.router.process(metadataMessage);
+		NodeList metadataElems = response.getElementsByTagName(GSXML.METADATA_ELEM);
+		
+		if(metadataElems.getLength() > 0)
+		{
+			Element metadata = (Element) metadataElems.item(0);
+			return GSXML.getNodeText(metadata);
+		}
+		
+		return null;
+	}
 }
Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/Receptionist.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/Receptionist.java	(revision 25091)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/Receptionist.java	(revision 25092)
@@ -170,5 +170,4 @@
 	public Node process(Node message_node)
 	{
-
 		Element message = this.converter.nodeToElement(message_node);
 
@@ -182,4 +181,9 @@
 		// check the request type 
 		String type = request.getAttribute(GSXML.TYPE_ATT); // returns "" if no att of this name
+		if(type.equals(GSXML.REQUEST_TYPE_SECURITY))
+		{
+			return this.mr.process(message);
+		}
+		
 		if (!type.equals(GSXML.REQUEST_TYPE_PAGE))
 		{
@@ -235,4 +239,5 @@
 		//logger.info(a+" mesa=" + this.converter.getPrettyString(message));
 		// get the page data from the action
+
 		Node action_response = a.process(message);
 
Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/DerbyWrapper.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/DerbyWrapper.java	(revision 25091)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/DerbyWrapper.java	(revision 25092)
@@ -27,4 +27,6 @@
 import java.sql.SQLWarning;
 import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Properties;
 
@@ -35,4 +37,5 @@
 	static final String USERSDB = "usersDB";
 	static final String USERS = "users";
+	static final String ROLES = "roles";
 	private Connection conn = null;
 	private Statement state = null;
@@ -98,11 +101,21 @@
 	}
 
-	public void createDatabase() throws SQLException
-	{
-		conn.setAutoCommit(false);
-		state.execute("create table users (username varchar(40) not null, password varchar(40) not null, groups varchar(500), accountstatus varchar(10), comment varchar(100), primary key(username))");
-		//ystem.out.println("table users created successfully!");
-		state.execute("insert into " + USERS + " values ('admin', 'admin', 'administrator,all-collections-editor', 'true', 'change the password for this account as soon as possible')");
-		conn.commit();
+	public void createDatabase()
+	{
+		try
+		{
+			conn.setAutoCommit(false);
+			state.execute("create table users (username varchar(40) not null, password varchar(40) not null, accountstatus varchar(10), comment varchar(100), primary key(username))");
+			state.execute("create table roles (username varchar(40) not null, role varchar(40) not null, primary key (username, role))");
+			//ystem.out.println("table users created successfully!");
+			state.execute("insert into " + USERS + " values ('admin', 'admin', 'true', 'change the password for this account as soon as possible')");
+			state.execute("insert into " + ROLES + " values ('admin', 'administrator')");
+			state.execute("insert into " + ROLES + " values ('admin', 'all-collections-editor')");
+			conn.commit();
+		}
+		catch(Exception ex)
+		{
+			ex.printStackTrace();
+		}
 	}
 
@@ -110,16 +123,34 @@
 	{
 		UserQueryResult userQueryResult = new UserQueryResult();
-		String sql_list_all_user = "select username, password, groups, accountstatus, comment from " + USERS;
-
+		String sql_list_all_user = "SELECT username, password, accountstatus, comment FROM " + USERS;
+
+		ArrayList<HashMap<String, String>> users = new ArrayList<HashMap<String,String>>();
 		ResultSet rs = state.executeQuery(sql_list_all_user);
 		while (rs.next())
 		{
-			String returned_username = rs.getString("username");
-			String returned_password = rs.getString("password");
-			String returned_groups = rs.getString("groups");
-			String returned_accountstatus = rs.getString("accountstatus");
-			String returned_comment = rs.getString("comment");
-			userQueryResult.addUserTerm(returned_username, returned_password, returned_groups, returned_accountstatus, returned_comment);
-		}
+			HashMap<String, String> user = new HashMap<String, String>();
+			user.put("username", rs.getString("username"));
+			user.put("password", rs.getString("password"));
+			user.put("as", rs.getString("accountstatus"));
+			user.put("comment", rs.getString("comment"));
+			
+			users.add(user);
+		}
+		
+		for(HashMap<String, String> user : users)
+		{
+			ResultSet gs = state.executeQuery("SELECT role FROM roles WHERE username = '" + user.get("username") + "'");
+			String group = "";
+			while(gs.next())
+			{
+				if(!group.equals(""))
+				{
+					group += ",";
+				}
+				group += gs.getString("role");
+			}
+			userQueryResult.addUserTerm(user.get("username"), user.get("password"), group, user.get("as"), user.get("comment"));
+		}
+		
 		if (userQueryResult.getSize() == 0)
 		{
@@ -133,11 +164,19 @@
 	}
 
-	public String addUser(String username, String password, String groups, String accountstatus, String comment) throws SQLException
-	{
-		conn.setAutoCommit(false);
-		String sql_insert_user = "insert into " + USERS + " values ('" + username + "', '" + password + "', '" + groups + "', '" + accountstatus + "', '" + comment + "')";
-		try
-		{
+	public String addUser(String username, String password, String groups, String accountstatus, String comment)
+	{
+		try
+		{
+			conn.setAutoCommit(false);
+			String sql_insert_user = "insert into " + USERS + " values ('" + username + "', '" + password + "', '" + accountstatus + "', '" + comment + "')";
 			state.execute(sql_insert_user);
+			
+			String[] groupArray = groups.split(",");
+			for(String g : groupArray)
+			{
+				String sql_insert_group = "insert into " + ROLES + " values ('" + username + "', '" + g + "')";
+				state.execute(sql_insert_group);
+			}
+			
 			conn.commit();
 		}
@@ -157,14 +196,17 @@
 			return "Error:" + e.getMessage();
 		}
+		
 		return "succeed";
 	}
 
-	public String deleteUser(String del_username) throws SQLException
-	{
-		conn.setAutoCommit(false);
-		String sql_delete_user = "delete from " + USERS + " where username='" + del_username + "'";
-		try
-		{
+	public String deleteUser(String del_username)
+	{
+		try
+		{
+			conn.setAutoCommit(false);
+			String sql_delete_user = "delete from " + USERS + " where username='" + del_username + "'";
+			String sql_delete_groups = "delete from " + ROLES + " where username='" + del_username + "'";
 			state.execute(sql_delete_user);
+			state.execute(sql_delete_groups);
 			conn.commit();
 		}
@@ -192,4 +234,5 @@
 		{
 			state.execute("delete from " + USERS);
+			state.execute("delete from " + ROLES);
 			conn.commit();
 		}
@@ -216,5 +259,5 @@
 
 		conn.setAutoCommit(false);
-		String sql_find_user = "SELECT  username, password, groups, accountstatus, comment FROM " + USERS;
+		String sql_find_user = "SELECT  username, password, accountstatus, comment FROM " + USERS;
 		String append_sql = "";
 
@@ -238,21 +281,38 @@
 			sql_find_user += append_sql;
 		}
+		
+		ArrayList<HashMap<String, String>> users = new ArrayList<HashMap<String,String>>();
 		ResultSet rs = state.executeQuery(sql_find_user);
 		while (rs.next())
 		{
-			String returned_username = rs.getString("username");
-			//System.out.println("returned_username :" + returned_username);
-			String returned_password = rs.getString("password");
-			//System.out.println("returned_password :" + returned_password);
-			String returned_groups = rs.getString("groups");
-			//System.out.println("returned_groups :" + returned_groups);
-			String returned_accountstatus = rs.getString("accountstatus");
-			//System.out.println("returned_accountstatus :" + returned_accountstatus);
-			String returned_comment = rs.getString("comment");
-			//System.out.println("returned_comment :" + returned_comment);
-			userQueryResult.addUserTerm(returned_username, returned_password, returned_groups, returned_accountstatus, returned_comment);
-			//System.out.println(userQueryResult.toString());
+			HashMap<String, String> user = new HashMap<String, String>();
+			user.put("username", rs.getString("username"));
+			user.put("password", rs.getString("password"));
+			user.put("as", rs.getString("accountstatus"));
+			user.put("comment", rs.getString("comment"));
+			
+			users.add(user);
 		}
 		conn.commit();
+		
+		for(HashMap<String, String> user : users)
+		{
+			ResultSet gs = state.executeQuery("SELECT role FROM " + ROLES + " WHERE username = '" + user.get("username") + "'");
+			
+			String group = "";
+			while(gs.next())
+			{
+				if(!group.equals(""))
+				{
+					group += ",";
+				}
+				group += gs.getString("role");
+			}
+			
+			System.out.println("GROUP = " + group);
+			
+			userQueryResult.addUserTerm(user.get("username"), user.get("password"), group, user.get("as"), user.get("comment"));
+		}
+		
 		if (userQueryResult.getSize() > 0)
 		{
@@ -266,23 +326,33 @@
 	}
 
-	public String modifyUserInfo(String username, String new_password, String groups, String accountstatus, String comment) throws SQLException
-	{
-		conn.setAutoCommit(false);
-		String sql_modify_user_info = "update " + USERS + " set ";
-		if (new_password != null && !new_password.equals(""))
-		{
-			sql_modify_user_info += "password='" + new_password + "'";
-		}
-
-		if (groups != null && accountstatus != null && comment != null)
-		{
-			sql_modify_user_info += ", groups='" + groups + "'" + ", accountstatus='" + accountstatus + "'" + ", comment='" + comment + "'";
-		}
-		sql_modify_user_info += " where username='" + username + "'";
-
-		try
-		{
+	public String modifyUserInfo(String username, String new_password, String groups, String accountstatus, String comment)
+	{
+		try
+		{
+			conn.setAutoCommit(false);
+			String sql_modify_user_info = "update " + USERS + " set ";
+			if (new_password != null && !new_password.equals(""))
+			{
+				sql_modify_user_info += "password='" + new_password + "'";
+			}
+	
+			if (accountstatus != null && comment != null)
+			{
+				sql_modify_user_info += ", accountstatus='" + accountstatus + "'" + ", comment='" + comment + "'";
+			}
+			sql_modify_user_info += " where username='" + username + "'";
 			System.out.println(sql_modify_user_info);
 			state.execute(sql_modify_user_info);
+			
+			String sql_delete_groups = "delete from " + ROLES + " where username='" + username + "'";
+			state.execute(sql_delete_groups);
+			
+			String[] groupsArray = groups.split(",");
+			for(String g : groupsArray)
+			{
+				String sql_insert_group = "insert into " + ROLES + " values ('" + username + "', '" + g + "')";
+				state.execute(sql_insert_group);
+			}
+			
 			conn.commit();
 		}
@@ -307,5 +377,5 @@
 	{
 		UserQueryResult userQueryResult = new UserQueryResult();
-		String sql_list_all_user = "select username, password, groups, accountstatus, comment from " + USERS;
+		String sql_list_all_user = "select username, password, accountstatus, comment from " + USERS;
 		ResultSet rs = state.executeQuery(sql_list_all_user);
 
@@ -318,5 +388,14 @@
 			String returned_accountstatus = rs.getString("accountstatus");
 			System.out.println("<enabled>" + returned_accountstatus);
-			String returned_groups = rs.getString("groups");
+			ResultSet groupsSet = state.executeQuery("SELECT role FROM " + ROLES + " WHERE username = '" + returned_username + "'");
+			String returned_groups = "";
+			while(groupsSet.next())
+			{
+				if(!returned_groups.equals(""))
+				{
+					returned_groups += ",";
+				}
+				returned_groups += groupsSet.getString("role");
+			}
 			System.out.println("<groups>" + returned_groups);
 			String returned_password = rot13(rs.getString("password"));
Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/GSXML.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/GSXML.java	(revision 25091)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/GSXML.java	(revision 25092)
@@ -209,4 +209,6 @@
 	// save the format string
 	public static final String REQUEST_TYPE_FORMAT_STRING = "formatString";
+	// check credentials
+	public static final String REQUEST_TYPE_SECURITY = "security";
 
 	// service types
@@ -254,4 +256,14 @@
 	public static final String ERROR = "error";
 
+	//security tags and attributes
+	public static final String SECURITY_ELEM = "security";
+	public static final String SCOPE_ATT = "scope";
+	public static final String DEFAULT_ACCESS_ATT = "default_access";
+	public static final String EXCEPTION_ELEM = "exception";
+	public static final String DOCUMENT_SET_ELEM = "documentSet";
+	public static final String GROUP_ELEM = "group";
+	public static final String MATCH_ELEM = "match";
+	public static final String FIELD_ATT = "field";
+
 	/**
 	 * takes a list of elements, and returns an array of strings of the values
@@ -1090,5 +1102,9 @@
 	private static void xmlNodeToString(StringBuffer sb, Node e, int depth, boolean printText)
 	{
-
+		if(e == null)
+		{
+			return;
+		}
+		
 		for (int i = 0; i < depth; i++)
 			sb.append(' ');
@@ -1224,3 +1240,24 @@
 		}
 	}
+
+	public static ArrayList<String> getGroupsFromSecurityResponse(Element securityResponse)
+	{
+		ArrayList<String> groups = new ArrayList<String>();
+		
+		Element groupList = (Element) GSXML.getChildByTagName(securityResponse, GSXML.GROUP_ELEM + GSXML.LIST_MODIFIER);
+		if(groupList == null)
+		{
+			return groups;
+		}
+		
+		NodeList groupElems = GSXML.getChildrenByTagName(groupList, GSXML.GROUP_ELEM);
+		
+		for(int i = 0; i < groupElems.getLength(); i++)
+		{
+			Element groupElem = (Element) groupElems.item(i);
+			groups.add(groupElem.getAttribute(GSXML.NAME_ATT));
+		}
+		
+		return groups;
+	}
 }
