Index: trunk/src/org/expeditee/auth/Actions.java
===================================================================
--- trunk/src/org/expeditee/auth/Actions.java	(revision 1242)
+++ trunk/src/org/expeditee/auth/Actions.java	(revision 1243)
@@ -1,6 +1,13 @@
 package org.expeditee.auth;
 
+import java.io.File;
 import java.io.FileNotFoundException;
+import java.io.FileWriter;
 import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.security.InvalidKeyException;
 import java.security.KeyFactory;
 import java.security.KeyPair;
@@ -10,9 +17,11 @@
 import java.security.PrivateKey;
 import java.security.PublicKey;
-import java.security.UnrecoverableEntryException;
 import java.security.cert.CertificateException;
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.PKCS8EncodedKeySpec;
+import java.sql.Connection;
+import java.sql.DriverManager;
 import java.sql.SQLException;
+import java.sql.Statement;
 import java.util.Base64;
 import java.util.Collection;
@@ -22,10 +31,18 @@
 import java.util.Optional;
 import java.util.Random;
-
+import java.util.stream.Collectors;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
 import javax.crypto.SecretKey;
 import javax.crypto.spec.SecretKeySpec;
 
+import org.expeditee.agents.ExistingFramesetException;
+import org.expeditee.agents.InvalidFramesetNameException;
 import org.expeditee.auth.Mail.MailEntry;
 import org.expeditee.auth.gui.MailBay;
+import org.expeditee.auth.tags.AuthenticationTag;
+import org.expeditee.auth.tags.Constants;
 import org.expeditee.core.Colour;
 import org.expeditee.gui.DisplayController;
@@ -34,9 +51,30 @@
 import org.expeditee.gui.MessageBay;
 import org.expeditee.items.Item;
+import org.expeditee.items.PermissionPair;
 import org.expeditee.items.Text;
+import org.expeditee.items.UserAppliedPermission;
+import org.expeditee.setting.GenericSetting;
+import org.expeditee.setting.Setting;
+import org.expeditee.setting.TextSetting;
+import org.expeditee.settings.Settings;
 import org.expeditee.settings.UserSettings;
+import org.expeditee.settings.folders.FolderSettings;
+import org.expeditee.settings.identity.secrets.KeyList;
 import org.ngikm.cryptography.CryptographyConstants;
 
 public class Actions implements CryptographyConstants {
+		
+	public static void SendTestMessage(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException, FileNotFoundException, KeyStoreException, CertificateException, ClassNotFoundException, IOException, SQLException {
+		String time = org.expeditee.stats.Formatter.getDateTime();
+		String sender = UserSettings.UserName.get();
+		String topic = "Test Message";
+		String message = "This is a test message.";
+		Map<String, String> options = new HashMap<String, String>();
+		options.put("Neat", "Beep");
+		MailEntry mail = new MailEntry(time, sender, colleagueName, topic, message, options);
+		PublicKey publicKey = Authenticator.getInstance().getPublicKey(colleagueName);
+		Path outbox = Paths.get(FrameIO.PROFILE_PATH).resolve(sender).resolve(sender + "-credentials");
+		Mail.sendMail(mail, publicKey, outbox);
+	}
 	
 	/**
@@ -66,32 +104,65 @@
 	
 	/**
-	 * Log out of current user and navigate to authentication1
-	 */
-	public static void AuthLogout() {
-		UserSettings.Authenticated.set(false);
-		setUser(System.getProperty("user.name"));
-		DisplayController.setCurrentFrame(FrameIO.LoadFrame("authentication1"), true);
-	}
-	
-	/**
 	 * Action used to created a new user account.
 	 * Attempts to use content from text items on frame, will default to java properties if they cannot be found.
 	 * Will fail if it cannot find content from text items on frame and all required java properties are not present.
+	 * @throws SQLException 
+	 * @throws IOException 
+	 * @throws ExistingFramesetException 
+	 * @throws InvalidFramesetNameException 
+	 * @throws ClassNotFoundException 
+	 * @throws FileNotFoundException 
+	 * @throws CertificateException 
+	 * @throws NoSuchAlgorithmException 
+	 * @throws KeyStoreException 
+	 * @throws BadPaddingException 
+	 * @throws IllegalBlockSizeException 
+	 * @throws NoSuchPaddingException 
+	 * @throws InvalidKeySpecException 
+	 * @throws InvalidKeyException 
 	 * @throws Exception 
 	 */
-	public static void AuthCreateAccount() throws Exception {
-		final Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
-		final Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Username, AuthenticationTag.Password, AuthenticationTag.PasswordAgain);
-		if (userdata.isPresent()) { 
-			final Map<AuthenticationTag, String> userData = userdata.get();
-			final String password = userData.get(AuthenticationTag.Password);
-			final String passwordAgain = userData.get(AuthenticationTag.PasswordAgain);
-			if (password.compareTo(passwordAgain) == 0) {
-				createAccount(userData);
-			} else {
-				MessageBay.errorMessage("The passwords provided do not match.");
-			}
+	public static void AuthCreateAccount() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, ClassNotFoundException, InvalidFramesetNameException, ExistingFramesetException, IOException, SQLException, InvalidKeyException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
+		Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
+		Optional<Map<AuthenticationTag, String>> userdata = 
+				AuthenticationTag.fetchUserData(textItems, false, 
+						AuthenticationTag.Username,
+						AuthenticationTag.Password,
+						AuthenticationTag.PasswordAgain, 
+						AuthenticationTag.Email, 
+						AuthenticationTag.EmailAgain);
+		
+		if (userdata.isPresent()) {
+			Map<AuthenticationTag, String> userData = userdata.get();
+			
+			// A profile already existing with 'username' means an account cannot be created with that username.
+			if (FrameIO.LoadProfile(userData.get(AuthenticationTag.Username)) != null) {
+				MessageBay.errorMessage(Constants.ERROR_PROFILE_NAME_PREEXISTS);
+				return;
+			}
+			
+			// The chosen username must be a valid frameset name.
+			if (!FrameIO.isValidFramesetName(userData.get(AuthenticationTag.Username))) {
+				MessageBay.errorMessage(Constants.ERROR_INVALID_USERNAME);
+				return;
+			}
+			
+			// The passwords provided must match
+			if (userData.get(AuthenticationTag.Password).compareTo(userData.get(AuthenticationTag.PasswordAgain)) != 0) {
+				MessageBay.errorMessage(Constants.ERROR_MISMATCH_PASSWORDS);
+				return;
+			}
+			
+			// The emails provided must match
+			if (userData.get(AuthenticationTag.Email).compareTo(userData.get(AuthenticationTag.EmailAgain)) != 0) {
+				MessageBay.errorMessage(Constants.ERROR_MISMATCH_EMAILS);
+				return;
+			}
+			
+			createAccount(userData);
+			login(userData);
+			Authenticator.Authenticated = true;
 		} else {
-			MessageBay.errorMessage("Please enter a username and password ( + repeated password) to create an account."); 
+			MessageBay.errorMessage(Constants.ERROR_INSUFFICIENT_INFORMATION_PROVIDED);
 		}
 	}
@@ -108,7 +179,8 @@
 		if (userdata.isPresent()) { 
 			login(userdata.get());
+			Authenticator.Authenticated = true;
 		}
 		else {
-			MessageBay.errorMessage("Please enter a username and password to log in.");
+			MessageBay.errorMessage(Constants.ERROR_INSUFFICIENT_INFORMATION_PROVIDED);
 		}
 	}
@@ -130,6 +202,6 @@
 		final Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
 		
-		if (!UserSettings.Authenticated.get()) {
-			MessageBay.errorMessage("You must be logged in to change your password.");
+		if (!Authenticator.Authenticated) {
+			MessageBay.errorMessage(Constants.ERROR_MUST_BE_LOGGED_IN);
 		} else {
 			final Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Password, AuthenticationTag.NewPassword, AuthenticationTag.NewPasswordAgain);
@@ -137,5 +209,5 @@
 				final Map<AuthenticationTag, String> userData = userdata.get();
 				if (userData.get(AuthenticationTag.NewPassword).compareTo(userData.get(AuthenticationTag.NewPasswordAgain)) != 0) {
-					MessageBay.errorMessage("The passwords provided do not match.");
+					MessageBay.errorMessage(Constants.ERROR_MISMATCH_PASSWORDS);
 				} else {
 					userData.put(AuthenticationTag.Username, UserSettings.UserName.get());
@@ -143,41 +215,36 @@
 				}
 			} else {
-				MessageBay.errorMessage("Insufficient information provided to complete this action.");
-			}
-		}
-	}
-	
-	/**
-	 * Part of the process to secure an authorised account, the AuthAssociateEmail action associates a supplied email
-	 * with the currently logged in user.  
-	 */
-	public static void AuthAssociateEmail() {
+				MessageBay.errorMessage(Constants.ERROR_INSUFFICIENT_INFORMATION_PROVIDED);
+			}
+		}
+	}
+	
+	public static void AuthGotoAccountManagement() {
+		if (Authenticator.Authenticated) {
+			DisplayController.setCurrentFrame(FrameIO.LoadFrame(Constants.FRAME_MULTIUSER1), false);
+		} else {
+			DisplayController.setCurrentFrame(FrameIO.LoadFrame(Constants.FRAME_AUTHENTICATION1), false);
+		}
+	}
+	
+	public static void AuthShareFrameset() throws IOException {
 		Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
 		
-		if (!UserSettings.Authenticated.get()) {
-			MessageBay.errorMessage("You must be logged in to perform this action.");
-		} else { 
-			Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Email);
-			if (userdata.isPresent()) {
-				Map<AuthenticationTag, String> userData = userdata.get();
-				userData.put(AuthenticationTag.Username, UserSettings.UserName.get());
-				String emailRegex = "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}$";
-				if (!userData.get(AuthenticationTag.Email).toUpperCase().matches(emailRegex)) {
-					MessageBay.errorMessage("Invalid email address supplied.");
-				} else {
-					try {
-						associateEmail(userData);
-						DisplayController.setCurrentFrame(FrameIO.LoadFrame("authentication5"), true);
-					} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | ClassNotFoundException | IOException | SQLException  e) {
-						MessageBay.errorMessage("An unknown error has occured. Details sent to standard error.");
-						e.printStackTrace();
-					}
-				}
-			} else {
-				MessageBay.errorMessage("Insufficient information provided to complete this action.");
-			}
-		}
-	}
-	
+		Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Frameset);
+		if (userdata.isPresent()) {
+			Map<AuthenticationTag, String> userData = userdata.get();
+			FrameIO.SuspendCache();
+			Frame toShare = FrameIO.LoadFrame(userData.get(AuthenticationTag.Frameset) + 1);
+			FrameIO.ResumeCache();
+			
+			if (toShare == null) {
+				MessageBay.errorMessage(Constants.ERROR_INSUFFICIENT_INFORMATION);
+				return;
+			}
+			
+			shareFrameset(toShare);
+		}
+	}
+
 	/**
 	 * Navigation action for progressing the process of recruiting colleagues to assist in password recovery.
@@ -185,7 +252,7 @@
 	 */
 	public static void AuthGotoColleagueSubmissionFrame() {
-		Frame destination = FrameIO.LoadFrame("authentication7");
+		Frame destination = FrameIO.LoadFrame(Constants.FRAME_COLLEAGUE_SUBMISSION_FRAME);
 		DisplayController.setCurrentFrame(destination, true);
-		Collection<Item> toHide = getByData(destination, "ShowOnProgress");
+		Collection<Item> toHide = getByData(destination, Constants.DATA_SHOW_ON_PROGRESS);
 		for (Item i: toHide) {
 			i.setVisible(false);
@@ -204,47 +271,57 @@
 	 * @throws InvalidKeySpecException 
 	 */
-	public static void AuthSubmitPWColleagues() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, IOException, SQLException, InvalidKeySpecException {
-		final Frame currentFrame = DisplayController.getCurrentFrame();
+	public static void AuthSubmitPWColleagues() throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
+		Frame currentFrame = DisplayController.getCurrentFrame();
 		Collection<Text> textItems = currentFrame.getTextItems();
 		
-		if (!UserSettings.Authenticated.get()) {
-			MessageBay.errorMessage("You must be logged in to perform this action.");
-		} else {
-			Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.ColleagueOne, AuthenticationTag.ColleagueTwo);
-			if (userdata.isPresent()) {
-				Map<AuthenticationTag, String> userData = userdata.get();
+		if (!Authenticator.Authenticated) {
+			MessageBay.errorMessage(Constants.ERROR_MUST_BE_LOGGED_IN);
+			return;
+		}
+		
+		Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.ColleagueOne, AuthenticationTag.ColleagueTwo);
+		if (userdata.isPresent()) {
+			Map<AuthenticationTag, String> userData = userdata.get();
+			String colleagueOne = userData.get(AuthenticationTag.ColleagueOne);
+			Path colleagueOnePath = Paths.get(FrameIO.CONTACTS_PATH).resolve(colleagueOne + "-credentials");
+			String colleagueTwo = userData.get(AuthenticationTag.ColleagueTwo);
+			Path colleagueTwoPath = Paths.get(FrameIO.CONTACTS_PATH).resolve(colleagueTwo + "-credentials");
+			if (!colleagueOnePath.toFile().exists()) {
+				MessageBay.errorMessage("Your nominated colleague: " + colleagueOne + " must exist in your contacts.");
+			} else if (!colleagueTwoPath.toFile().exists()) {
+				MessageBay.errorMessage("Your nominated colleague: " + colleagueTwo + " must exist in your contacts.");
+			} else {
 				userData.put(AuthenticationTag.Username, UserSettings.UserName.get());
-				boolean succsess = submitPWColleagues(userData);
-				if (succsess) {
-					Collection<Item> toShow = getByData(currentFrame, "ShowOnProgress");
+				boolean success = submitPWColleagues(userData);
+				if (success) {
+					Collection<Item> toShow = getByData(currentFrame, Constants.DATA_SHOW_ON_PROGRESS);
 					for (Item i: toShow) {
 						i.setVisible(true);
 					}
 					currentFrame.change();
+					MessageBay.displayMessage("-------Messages sent-------");
 				}
 				FrameIO.SaveFrame(currentFrame);
 				DisplayController.requestRefresh(false);
-			} else {
-				MessageBay.errorMessage("Insufficient information provided to complete this action.");
-			}
-		}
-	}
-	
-	public static void AuthSetupPasswordRecovery() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, IOException, SQLException, UnrecoverableEntryException {
-		if (!UserSettings.Authenticated.get()) {
-			MessageBay.errorMessage("You must be logged in to perform this action.");
-		} else if (!Authenticator.getInstance().hasRegisteredEmail(UserSettings.UserName.get())) {
-			Frame registerEmailFrame = FrameIO.LoadFrame("authentication4");
-			DisplayController.setCurrentFrame(registerEmailFrame, true);
-		} else if (!Authenticator.getInstance().hasRequestedColleagues(UserSettings.UserName.get()) && Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) == null) {
-			Frame submitColleaguesFrame = FrameIO.LoadFrame("authentication5");
-			DisplayController.setCurrentFrame(submitColleaguesFrame, true);
-		} else if (Authenticator.getInstance().hasRequestedColleagues(UserSettings.UserName.get()) && Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) == null) {
-			MessageBay.displayMessage("You have already nominated two colleagues to assist you in the process of password recovery and are awaiting their response."
-					+ "  You will be alerted on Expeditee startup when they have both responded.");
-		} else if (Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) != null) {
-			MessageBay.displayMessage("You have completed the Password Recovery Setup process, there is nothing more to do here.");
-		}
-	}
+			}
+		}
+	}
+	
+//	public static void AuthSetupPasswordRecovery() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, IOException, SQLException, UnrecoverableEntryException {
+//		if (!UserSettings.Authenticated.get()) {
+//			MessageBay.errorMessage("You must be logged in to perform this action.");
+//		} else if (!Authenticator.getInstance().hasRegisteredEmail(UserSettings.UserName.get())) {
+//			Frame registerEmailFrame = FrameIO.LoadFrame("authentication4");
+//			DisplayController.setCurrentFrame(registerEmailFrame, true);
+//		} else if (!Authenticator.getInstance().hasRequestedColleagues(UserSettings.UserName.get()) && Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) == null) {
+//			Frame submitColleaguesFrame = FrameIO.LoadFrame("authentication5");
+//			DisplayController.setCurrentFrame(submitColleaguesFrame, true);
+//		} else if (Authenticator.getInstance().hasRequestedColleagues(UserSettings.UserName.get()) && Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) == null) {
+//			MessageBay.displayMessage("You have already nominated two colleagues to assist you in the process of password recovery and are awaiting their response."
+//					+ "  You will be alerted on Expeditee startup when they have both responded.");
+//		} else if (Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) != null) {
+//			MessageBay.displayMessage("You have completed the Password Recovery Setup process, there is nothing more to do here.");
+//		}
+//	}
 	
 	public static void AuthConfirmPasswordColleagueRelationship(String colleagueName) {
@@ -252,5 +329,6 @@
 	}
 	
-	public static void AuthDenyPasswordColleagueRelationship(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
+	public static void AuthDenyPasswordColleagueRelationship(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException, 
+		KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
 		denyPasswordColleagueRelationship(colleagueName);
 	}
@@ -260,5 +338,218 @@
 	}
 	
+	/**
+	 * Create a user account using the specified information in userdata.  Creates and stores user keys.
+	 * @param userdata Should contain username, password and email.
+	 */
+	private static void createAccount(Map<AuthenticationTag, String> userdata) throws InvalidFramesetNameException, ExistingFramesetException, 
+		KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, ClassNotFoundException, IOException, SQLException {
+				
+		// Track progress
+		String message = "Creating new user account...";
+		//Progress progress = MessageBay.displayProgress(message);
+
+		// Extract user details
+		String username = userdata.get(AuthenticationTag.Username);
+		String password = userdata.get(AuthenticationTag.Password);
+		String email = userdata.get(AuthenticationTag.Email);
+		
+		System.out.println(message + "Generating Keys.");
+
+		// Generate keys
+		//	Personal key
+		Random rand = new Random();
+		byte[] keyBytes = new byte[16];
+		rand.nextBytes(keyBytes);
+		SecretKey key = new SecretKeySpec(keyBytes, SymmetricAlgorithm);
+		Authenticator.getInstance().putKey(username, password, key);
+		String personalKey = Base64.getEncoder().encodeToString(key.getEncoded());
+		//	Public and private keys
+		KeyPairGenerator keyGen = KeyPairGenerator.getInstance(AsymmetricAlgorithm);
+		keyGen.initialize(1024);
+		KeyPair keyPair = keyGen.generateKeyPair();
+		String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
+		String privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
+		
+		System.out.println(message + "Creating Profile Frameset.");
+		
+		// Update in memory settings
+		UserSettings.UserName.set(username);
+		UserSettings.ProfileName.set(username);
+		UserSettings.setupDefaultFolders();
+				
+		// Establish the initial settings for the created user.
+		Map<String, Setting> initialSettings = new HashMap<String, Setting>();
+		initialSettings.put(Constants.SETTINGS_AUTH_SECRETS_PERSONAL_KEY, constructTextSetting(Constants.TOOLTIP_SETTING_PERSONAL_KEY, "PersonalKey", personalKey));
+		initialSettings.put(Constants.SETTINGS_AUTH_SECRETS_PRIVATE_KEY, constructTextSetting(Constants.TOOLTIP_SETTING_PRIVATE_KEY, "PrivateKey", privateKey));
+		initialSettings.put(Constants.SETTINGS_AUTH_PUBLIC_KEY, constructTextSetting(Constants.TOOLTIP_SETTING_PUBLIC_KEY, "PublicKey", publicKey));
+		initialSettings.put(Constants.SETTINGS_AUTH_EMAIL, constructGenericSetting(String.class, Constants.TOOLTIP_SETTING_EMAIL, "Email", email, username));
+		initialSettings.put(Constants.SETTINGS_USER_SETTINGS_USER_NAME, constructGenericSetting(String.class, Constants.LABEL_USERNAME, Constants.LABEL_USERNAME, username, username));
+		initialSettings.put(Constants.SETTINGS_USER_SETTINGS_PROFILE_NAME, constructGenericSetting(String.class, Constants.LABEL_PROFILENAME, Constants.LABEL_PROFILENAME, username, username));
+		initialSettings.put("org.expeditee.gui.folders.FolderSettings.FrameDirs", FolderSettings.FrameDirs);
+		initialSettings.put("org.expeditee.gui.folders.FolderSettings.ImageDirs", FolderSettings.ImageDirs);
+						
+		// Create users profile
+		Frame profile = FrameIO.CreateNewProfile(username, initialSettings);
+		int lastNumber = FrameIO.getLastNumber(profile.getFramesetName());
+		for (int i = 1; i <= lastNumber; i++) {
+			Frame f = FrameIO.LoadFrame(profile.getFramesetName() + i);
+			Text titleItem = f.getTitleItem();
+			if (i == 1 && titleItem != null) {
+				titleItem.delete();
+				f.setBackgroundColor(new Colour(1, 1, 0.39f));
+			}
+			f.setOwner(username);
+			f.getAllItems().stream().forEach(item -> item.setOwner(username));
+			f.setChanged(true);
+			f.setEncryptionLabel("Profile");
+			Collection<Item> secretsLink = getByContent(f, "Secrets");
+			Collection<Item> publicKeyItem = getByContent(f, "PublicKey");
+			if (!secretsLink.isEmpty() && !publicKeyItem.isEmpty()) {
+				//Then we are on credentials frame
+				secretsLink.forEach(text -> text.setPermission(new PermissionPair(UserAppliedPermission.full, UserAppliedPermission.none)));
+				f.addToData("MultiuserCredentials");
+			}
+			Text backupPersonalKey = KeyList.PersonalKey.get();
+			Text tempPersonalKey = KeyList.PersonalKey.generateText();
+			tempPersonalKey.setData(personalKey);
+			KeyList.PersonalKey.setSetting(tempPersonalKey);
+			FrameIO.SaveFrame(f);
+			KeyList.PersonalKey.setSetting(backupPersonalKey);
+		}
+				
+		// Create credentials
+		File credentialsDir = new File(profile.getFramesetPath() + username + "-credentials");
+		credentialsDir.mkdir();
+		// 	credentials.inf file.
+		String credentialsPath =  credentialsDir.getAbsolutePath() + File.separator + "credentials.inf";
+		File credentialsFile = new File(credentialsPath);
+		credentialsFile.createNewFile();
+		FileWriter out = new FileWriter(credentialsFile);
+		out.write(Authenticator.CREDENTIALS_FRAME + ".exp");
+		out.flush();
+		out.close();
+		//	outbox
+		Connection c = DriverManager.getConnection("jdbc:sqlite:" + credentialsDir.getAbsolutePath() + File.separator + "expmail.db");
+		Statement createTable = c.createStatement();
+		String sql = "CREATE TABLE EXPMAIL (" +
+				"TIME		TEXT					NOT NULL, " +
+				"SND		TEXT					NOT NULL, " + 
+				"REC		TEXT					NOT NULL, " + 
+				"MSG		TEXT					NOT NULL, " +
+				"MSG2		TEXT					NOT NULL, " + 
+				"OPTS		ARRAY					NOT NULL, " +
+				"OPTSVAL	ARRAY					NOT NULL)";
+		createTable.executeUpdate(sql);
+		createTable.close();
+		c.close();
+		
+		System.out.println(message + "Creating Individual Space.");
+		
+		// Copy private resources to personal area
+		Path personalResources = Paths.get(FrameIO.PARENT_FOLDER).resolve("resources-" + username);
+		personalResources.toFile().mkdir();		
+		File[] globalResourcesToCopy = Paths.get(FrameIO.RESOURCES_PRIVATE).toFile().listFiles();
+		for (File toCopy: globalResourcesToCopy) {
+			Path p = Paths.get(toCopy.getAbsolutePath());
+			if (!p.getFileName().toString().equals(".res") && !p.getFileName().toString().equals("about")) {
+				copyFileTree(p.toAbsolutePath(), personalResources.resolve(p.getFileName()));
+			}
+		}
+		File contactsDir = new File(personalResources.resolve("contacts").toAbsolutePath().toString());
+		contactsDir.mkdir();
+		
+		System.out.println(message + "Done.");
+	}
+	
+	private static void copyFileTree(Path source, Path target) throws IOException {
+		Files.copy(source, target);
+		if (source.toFile().isDirectory()) {
+			File[] files = source.toFile().listFiles();
+			for (File file: files) {
+				Path asPath = Paths.get(file.getAbsolutePath());
+				copyFileTree(asPath, target.resolve(asPath.getFileName()));
+			}
+		}
+	}
+
+	/*
+	 * Function used to authenticate as a specified user (via function arguments).
+	 */
+	private static void login(Map<AuthenticationTag, String> userdata) throws NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException, InvalidKeySpecException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
+		String username = userdata.get(AuthenticationTag.Username);
+		String password = userdata.get(AuthenticationTag.Password);
+		
+		SecretKey personalKey = Authenticator.getInstance().getSecretKey(username, password);
+		if (personalKey == null) {
+			// Incorrect username and password
+			MessageBay.errorMessage("The username + password combination was incorrect.");
+			return;
+		}
+		
+		// Load in and cache the profile frame using the personal key fetched from keystore.
+		// Reset the personal key once finished so that setting parsing can correctly set it.
+		FrameIO.ClearCache();
+		Text personalKeyText = KeyList.PersonalKey.generateText();
+		personalKeyText.setData(Base64.getEncoder().encodeToString(personalKey.getEncoded()));
+		KeyList.PersonalKey.setSetting(personalKeyText);
+		Frame oneFrame = FrameIO.LoadProfile(username);
+		for (int i = 1; i <= FrameIO.getLastNumber(username); i++) {
+			Frame f = FrameIO.LoadFrame(oneFrame.getFramesetName() + i);
+			if (f.getData() != null && f.getData().contains("MultiuserCredentials")) {
+				Authenticator.CREDENTIALS_FRAME = f.getNumber();
+			}
+		}
+				
+		// Parse the settings frame to update the settings datastructure.
+		Text fakeLink = new Text("settings");
+		fakeLink.setLink(oneFrame.getFramesetName() + "2");
+		Settings.parseSettings(fakeLink);
+		
+		// Update default folders.
+		UserSettings.setupDefaultFolders();
+
+		// Check mail
+		MailBay.clear();
+		Authenticator.getInstance().loadMailDatabase();
+		Text keyItem = org.expeditee.settings.identity.secrets.KeyList.PrivateKey.get();
+		if (keyItem.getData() != null) {
+			String keyEncoded = keyItem.getData().get(0);
+			byte[] keyBytes = Base64.getDecoder().decode(keyEncoded);
+			PrivateKey key = KeyFactory.getInstance(AsymmetricAlgorithm).generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
+			List<MailEntry> mailForLoggingInUser = Mail.getEntries(UserSettings.UserName.get(), key);
+			for (MailEntry mail: mailForLoggingInUser) {
+				MailBay.addMessage(mail.timestamp, mail.message, mail.message2, mail.options);
+			}
+		}
+		
+		Collection<Item> usernameFields = getByData(FrameIO.LoadFrame(Constants.FRAME_MULTIUSER1), "txtUsername");
+		usernameFields.forEach(usernameField -> usernameField.setText(username));
+				
+		Frame homeFrame = FrameIO.LoadFrame("home1");
+		DisplayController.setCurrentFrame(homeFrame == null ? oneFrame : homeFrame, false);
+	}	
+
+	/*
+	 * Function to share a specified frameset.
+	 * Currently, this moves the frameset to the 'Shared By Me' directory and then relies on the user to use Google Drive functionality to share it appropriately.
+	 */
+	private static void shareFrameset(Frame toShare) throws IOException {	
+		File destinationDir = new File(FrameIO.SHARED_FRAMESETS_PATH + File.separator + toShare.getFramesetName());
+		File sourceDir = new File(toShare.getFramesetPath());
+		
+		if (destinationDir.exists()) {
+			MessageBay.errorMessage("A frameset by this name already exists.");
+			return;
+		}
+		
+		destinationDir.mkdir();
+		List<Path> files = Files.walk(sourceDir.toPath()).collect(Collectors.toList());
+		Files.move(files.get(0), destinationDir.toPath(), StandardCopyOption.ATOMIC_MOVE);
+		
+		MessageBay.displayMessage("The frameset " + toShare.getFramesetName() + " has been moved to " + destinationDir + ".  Google Drive functionality can now be used to share it with colleagues.");
+	}
+	
 	private static void denyPasswordColleagueRelationship(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
+		String time = org.expeditee.stats.Formatter.getDateTime();
 		String sender = UserSettings.UserName.get();
 		String message = "You have received a reply from " + sender + " reguarding your request for assistance.";
@@ -266,32 +557,32 @@
 		Map<String, String> options = new HashMap<String, String>();
 		options.put("Clear Preview Colleague Nominations", "AuthClearPWColleaguesNominated");
-		MailEntry mail = new MailEntry(sender, colleagueName, message, message2, options);
-		Mail.sendMail(mail, Authenticator.getInstance().getPublicKey(colleagueName));
-	}
-	
-	private static boolean submitPWColleagues(Map<AuthenticationTag, String> userData) throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, IOException, SQLException, InvalidKeySpecException {
-		// Confirm both colleagues exist
+		MailEntry mail = new MailEntry(time, sender, colleagueName, message, message2, options);
+		Mail.sendMail(mail, Authenticator.getInstance().getPublicKey(colleagueName), Paths.get(FrameIO.PROFILE_PATH).resolve(sender).resolve(sender + "-credentials"));
+	}
+	
+	private static boolean submitPWColleagues(Map<AuthenticationTag, String> userData) throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
 		String colleagueOne = userData.get(AuthenticationTag.ColleagueOne);
 		String colleagueTwo = userData.get(AuthenticationTag.ColleagueTwo);
-		PublicKey colleagueOneKey = null;
-		PublicKey colleagueTwoKey = null;
-		if (!FrameIO.canAccessFrameset(colleagueOne) && FrameIO.canAccessFrameset(colleagueTwo)) {
-			MessageBay.errorMessage("At least one of the colleagues you specified does not have a Expeditee profile.");
+		PublicKey colleagueOneKey = Authenticator.getInstance().getPublicKey(colleagueOne);
+		PublicKey colleagueTwoKey = Authenticator.getInstance().getPublicKey(colleagueTwo);
+		if (colleagueOneKey == null) {
+			MessageBay.errorMessage("Unable to get public key for colleague: " + colleagueOne);
 			return false;
-		} else if ((colleagueOneKey = Authenticator.getInstance().getPublicKey(colleagueOne)) == null || 
-				(colleagueTwoKey = Authenticator.getInstance().getPublicKey(colleagueTwo)) == null) {
-			MessageBay.errorMessage("At least one of the colleagues you specified is not set up to be authorised.");
+		} else if (colleagueTwoKey == null) {
+			MessageBay.errorMessage("Unable to get public key for colleague: " + colleagueTwo);
 			return false;
 		} else {
-			String sender = UserSettings.UserName.get();
-			String message = "You have received a request for cooperation from your colleague " + sender;
-			String message2 = "\"I would like to receive your help if I happen to forget my password.\"";
+			String time = org.expeditee.stats.Formatter.getDateTime();
+			String sender = userData.get(AuthenticationTag.Username);
+			String topic = "You have received a request for cooperation from your colleague " + sender;
+			String message = "Should " + sender + " forget their password, they would like your help recoverying it.";
 			Map<String, String> arguments = new HashMap<String, String>();
-			arguments.put("I Agree To Assist " + sender + " If They Forget Their Password" , "AuthConfirmPasswordColleagueRelationship " + sender);
-			arguments.put("I Wish To Excuse Myself From This Responsibility", "AuthDenyPasswordColleagueRelationship " + sender);
-			MailEntry mail = new MailEntry(sender, colleagueOne, message, message2, arguments);
-			Mail.sendMail(mail, colleagueOneKey);
-			mail = new MailEntry(sender, colleagueTwo, message, message2, arguments);
-			Mail.sendMail(mail, colleagueTwoKey);
+			arguments.put("I agree to assist " + sender + " if they loose access to their account.", "AuthConfirmPasswordColleagueRelationship " + sender);
+			arguments.put("I wish to excuse myself from this responsibility.", "AuthDenyPasswordColleagueRelationship " + sender);
+			MailEntry mail = new MailEntry(time, sender, colleagueOne, topic, message, arguments);
+			Path outbox = Paths.get(FrameIO.PROFILE_PATH).resolve(sender).resolve(sender + "-credentials");
+			Mail.sendMail(mail, colleagueOneKey, outbox);
+			mail = new MailEntry(time, sender, colleagueTwo, topic, message, arguments);
+			Mail.sendMail(mail, colleagueTwoKey, outbox);
 			Authenticator.getInstance().markRequestedColleagues(UserSettings.UserName.get());
 			return true;
@@ -299,133 +590,24 @@
 	}
 
-	/*
-	 * Function used to authenticate as a specified user (via function arguments).
-	 */
-	private static void login(final Map<AuthenticationTag, String> userdata) throws Exception {
-		final String username = userdata.get(AuthenticationTag.Username);
-		final String password = userdata.get(AuthenticationTag.Password);
-		
-		final SecretKey personalKey = Authenticator.getInstance().getSecretKey(username, password);
-		if (personalKey == null) {
-			// Incorrect username and password
-			MessageBay.errorMessage("The username + password combination was incorrect.");
-		} else {
-			// Proceed with login process.
-			org.expeditee.settings.auth.secrets.KeyList.PersonalKey.setSetting(new Text(Base64.getEncoder().encodeToString(personalKey.getEncoded())));
-			setUser(username);
-			MessageBay.displayMessage("Logged in as: " + UserSettings.UserName.get());
-			
-			// Set Public Key and private key in settings datastructure
-			String profileName = UserSettings.ProfileName.get();
-			int lastNumber = FrameIO.getLastNumber(profileName);
-			for (int i = 1; i <= lastNumber; i++) {
-				Frame frame = FrameIO.LoadFrame(profileName + i);
-				if (frame == null) {
-					continue;
-				}
-				Collection<Item> items = frame.getAllItems();
-				boolean foundPublic = false;
-				boolean foundPrivate = false;
-				for (Item item: items) {
-					if (item.getText().compareTo("PublicKey") == 0) {
-						org.expeditee.settings.auth.KeyList.PublicKey.set((Text) item);
-						foundPublic = true;
-					} else if (item.getText().compareTo("PrivateKey") == 0) {
-						org.expeditee.settings.auth.secrets.KeyList.PrivateKey.set((Text) item);
-						foundPrivate = true;
-					}
-				}
-				if (foundPublic && foundPrivate) { break; }
-			}
-						
-			// Check mail
-			MailBay.clear();
-			Authenticator.getInstance().loadMailDatabase();
-			Text keyItem = org.expeditee.settings.auth.secrets.KeyList.PrivateKey.get();
-			if (keyItem.getData() != null) {
-				String keyEncoded = keyItem.getData().get(0);
-				byte[] keyBytes = Base64.getDecoder().decode(keyEncoded);
-				PrivateKey key = KeyFactory.getInstance(AsymmetricAlgorithm).generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
-				List<MailEntry> mailForLoggingInUser = Mail.getEntries(UserSettings.UserName.get(), key);
-				for (MailEntry mail: mailForLoggingInUser) {
-					MailBay.addMessage(mail.message, mail.message2, mail.options);
-				}
-			}
-			
-			UserSettings.Authenticated.set(true);
-			// navigate to logged in profile
-			DisplayController.setCurrentFrame(loadProfile(username), false);
-		}
-	}
-	
-	/*
-	 * Creates an account from specified user data.
-	 */
-	private static void createAccount(final Map<AuthenticationTag, String> userdata) throws Exception {
-		String username = userdata.get(AuthenticationTag.Username);
-		String password = userdata.get(AuthenticationTag.Password);
-		if (FrameIO.LoadProfile(username) != null) {
-			MessageBay.errorMessage("A Expeditee profile with this username already exists, please choose another.");
-		} else {				
-			// generate the newly created user a profile frame using the specialized default frame as a blueprint
-			String defaultBackup = UserSettings.DEFAULT_PROFILE_NAME;
-			UserSettings.DEFAULT_PROFILE_NAME = "multiusermodedefault";
-			Frame profile = FrameIO.CreateNewProfile(username);
-			UserSettings.DEFAULT_PROFILE_NAME = defaultBackup;
-			
-			// perform necessary changes to generated frame: remove default title, set background color, set custom title 
-			profile.getTitleItem().delete();
-			profile.setBackgroundColor(new Colour(1, 1, 0.39f));
-			getByData(profile, "txtUsername").stream().forEach(i -> i.setText(username));
-			getByText(profile, "“If Aphroditē be the godess of love").stream().forEach(i -> i.setWidth(300));
-			getByText(profile, "Sleek like Aphroditē, Wise like Athēnâ.").stream().forEach(i -> i.setWidth(300));
-			
-			// update ownership
-			int lastNumber = FrameIO.getLastNumber(profile.getFramesetName());
-			for (int i = 1; i <= lastNumber; i++) {
-				Frame frame = FrameIO.LoadFrame(profile.getFramesetName() + i);
-				frame.setOwner(username);
-				frame.setEncryptionLabel("Profile");
-				Collection<Item> items = frame.getAllItems();
-				for (Item item: items) {
-					String newText = item.getText().replace("authadmin", username);
-					item.setText(newText);
-				}
-			}
-			
-			// generate and store personal, public and private keys
-			String backupUser = UserSettings.UserName.get();
-			setUser(username);
-			UserSettings.Authenticated.set(true);
-			
-			// personal key
-			Random rand = new Random();
-			byte[] keyBytes = new byte[16];
-			rand.nextBytes(keyBytes);
-			SecretKey key = new SecretKeySpec(keyBytes, SymmetricAlgorithm);
-			Authenticator.getInstance().putKey(username, password, key);
-			org.expeditee.settings.auth.secrets.KeyList.PersonalKey.setSetting(new Text(Base64.getEncoder().encodeToString(key.getEncoded())));
-			
-			// public+private key pair
-			KeyPairGenerator keyGen = KeyPairGenerator.getInstance(AsymmetricAlgorithm);
-			keyGen.initialize(1024);
-			KeyPair keyPair = keyGen.generateKeyPair();
-			
-			org.expeditee.settings.auth.secrets.KeyList.PrivateKey.setSetting(new Text(Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded())));
-			org.expeditee.settings.auth.KeyList.PublicKey.setSetting(new Text(Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded())));
-			
-			// ensure save of keys
-			lastNumber = FrameIO.getLastNumber(profile.getFramesetName());
-			for (int i = 1; i <= lastNumber; i++) {
-				Frame frame = FrameIO.LoadFrame(profile.getFramesetName() + i);
-				frame.setChanged(true);
-				FrameIO.SaveFrame(frame);
-			}
-			setUser(backupUser);
-			UserSettings.Authenticated.set(false);
-			
-			// proceed to log into new account.
-			login(userdata);
-		}
+		
+	private static TextSetting constructTextSetting(String tooltip, String text, String data) {
+		return new TextSetting(tooltip, text) {
+			@Override
+			public Text generateText() {
+				Text t = new Text(text);
+				t.setData(data);
+				return t;
+			}
+		};
+	}
+
+	private static <T> GenericSetting<T> constructGenericSetting(Class<T> type, String tooltip, String name, T value, String frameset) {
+		return new GenericSetting<T>(type, tooltip, name, value) {
+			@Override
+			public Text generateRepresentation(String name, String frameset) {
+				Text t = new Text(name + ": " + value);
+				return t;
+			}
+		};
 	}
 	
@@ -446,52 +628,5 @@
 		}
 	}
-	
-	private static void associateEmail(Map<AuthenticationTag, String> userdata) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, ClassNotFoundException, IOException, SQLException {
-		Authenticator.getInstance().putEmail(
-				userdata.get(AuthenticationTag.Username), 
-				userdata.get(AuthenticationTag.Email));
-	}
-
-	private static void setUser(final String username) {
-		UserSettings.UserName.set(username);
-		UserSettings.ProfileName.set(username);
-		UserSettings.HomeFrame.set(username + "1");
-		UserSettings.UserName.setDefault(username);
-		UserSettings.ProfileName.setDefault(username);
-		UserSettings.HomeFrame.setDefault(username + "1");
-	}
-	
-	private static Frame loadProfile(final String username) throws Exception {
-		final Frame frameOne = FrameIO.LoadProfile(username);
-		if (frameOne != null) { 
-			return frameOne;
-		} else {
-			final Frame profile = FrameIO.CreateNewProfile(username);
-			for (int i = 0; i < FrameIO.getLastNumber(profile.getFramesetName()); i++) {
-				final Frame frame = FrameIO.LoadFrame(profile.getFramesetName() + i);
-				final Collection<Text> textItems = frame.getTextItems();
-				for (final Text t: textItems) {
-					if (t.getText().startsWith("User name:")) {
-						t.setText("User name: " + UserSettings.UserName.get());
-					} else if (t.getText().startsWith("Profile name:")) {
-						t.setText("Profile name: " + UserSettings.ProfileName.get());
-					}
-				}
-				FrameIO.ForceSaveFrame(frame);
-			}
-			return profile;
-		}
-	}
-
-//	public static void AuthRecoverPasswordStage1() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
-//		final Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
-//		final Optional<Text> txtUsername = textItems.stream().filter(t -> t.getData() != null && t.getData().contains("txtUsername")).findFirst();
-//		final Optional<Text> txtRecoveryEmail = textItems.stream().filter(t -> t.getData() != null && t.getData().contains("txtRecoveryEmail")).findFirst();
-//		final String username = txtUsername.isPresent() ? txtUsername.get().getText() : System.getProperty("user.name");
-//		final String email = txtRecoveryEmail.isPresent() ? txtRecoveryEmail.get().getText() : System.getProperty("user.recoveryemail");
-//		if (areAllPresent(new String[] { username, email })) {
-//			// generate intergalactic number
-//			final String intergalacticNumber = Authenticator.getInstance().newIntergalacticNumber(username, email);
-//
+
 //			// establish properties
 //			final String from = "noreply@expeditee.com";
@@ -515,6 +650,5 @@
 //				};
 //			});
-//
-//			try {
+
 //				// construct email message
 //				final MimeMessage message = new MimeMessage(session);
@@ -526,37 +660,5 @@
 //				// send email message
 //				Transport.send(message);
-//			} catch (final MessagingException e) {
-//				e.printStackTrace();
-//			}
-//			
-//			FrameUtils.DisplayFrame("4", false, true);
-//		} else {
-//			MessageBay.errorMessage("To recover a lost password please fill in all the provided fields.");
-//		}
-//	}
-//	
-//	public static void AuthRecoverPasswordStage2() throws NoSuchAlgorithmException, KeyStoreException, CertificateException, FileNotFoundException, IOException {
-//		final Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
-//		final Optional<Text> txtUsername = textItems.stream().filter(t -> t.getData() != null && t.getData().contains("txtUsername")).findFirst();
-//		final Optional<Text> txtRecoveryEmail = textItems.stream().filter(t -> t.getData() != null && t.getData().contains("txtRecoveryEmail")).findFirst();
-//		final Optional<Text> txtIntergalacticNumber = textItems.stream().filter(t -> t.getData() != null && t.getData().contains("txtIntergalacticNumber")).findFirst();
-//		final String username = txtUsername.isPresent() ? txtUsername.get().getText() : System.getProperty("user.name");
-//		final String email = txtRecoveryEmail.isPresent() ? txtRecoveryEmail.get().getText() : System.getProperty("user.recoveryemail");
-//		final String intergalacticNumber = txtIntergalacticNumber.isPresent() ? txtIntergalacticNumber.get().getText() : System.getProperty("user.intergalacticnumber");
-//		if (areAllPresent(new String[] { username, email, intergalacticNumber })) {
-//			// confirm intergalactic number matches what is stored
-//			final boolean intergalaticNumberMatches = Authenticator.getInstance().confirmIntergalaticNumber(username, email, intergalacticNumber);
-//			if (intergalaticNumberMatches) { 
-//				final Frame changePasswordFrame = FrameIO.LoadFrame("5");
-//				final Optional<Text> actionNewPassword = changePasswordFrame.getTextItems().stream().filter(t -> t.getAction().contains("AuthNewPassword")).findFirst();
-//				if (actionNewPassword.isPresent()) {
-//					actionNewPassword.get().setData(intergalacticNumber);
-//				}
-//				FrameUtils.DisplayFrame("5", false, true);
-//			}
-//		} else {
-//			MessageBay.errorMessage("To recover a lost password please fill in all the provided fields.");
-//		}
-//	}
+
 
 	public static void TickBox(final Text item) {
@@ -569,19 +671,16 @@
 	
 	/*
-	 *  Gets all items on a specified frame that contain the specified text.
-	 */
-	private static Collection<Item> getByText(final Frame frame, final String text) {
-		final Collection<Item> allItems = frame.getAllItems();
-		allItems.removeIf(i -> i.getText() == null || !i.getText().contains(text));
-		return allItems;
-	}
-	
-	/*
 	 * Gets all items on a specified frame that contain the specified data.
 	 */
-	private static Collection<Item> getByData(final Frame frame, final String data) {
+	public static Collection<Item> getByData(final Frame frame, final String data) {
 		final Collection<Item> allItems = frame.getAllItems();
 		allItems.removeIf(i -> i.getData() == null || !i.hasData(data));
 		return allItems;
 	}
+	
+	public static Collection<Item> getByContent(final Frame frame, final String content) {
+		final Collection<Item> allItems = frame.getAllItems();
+		allItems.removeIf(i -> i.getText().compareTo(content) != 0);
+		return allItems;
+	}
 }
Index: trunk/src/org/expeditee/auth/AuthenticationTag.java
===================================================================
--- trunk/src/org/expeditee/auth/AuthenticationTag.java	(revision 1242)
+++ 	(revision )
@@ -1,52 +1,0 @@
-package org.expeditee.auth;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-
-import org.expeditee.items.Text;
-
-public enum AuthenticationTag {
-	Username ("txtUsername", System.getProperty("user.name")), 
-	Password ("txtPassword", System.getProperty("user.password")), 
-	PasswordAgain ("txtPasswordAgain", System.getProperty("user.password.again")), 
-	NewPassword ("txtNewPassword", System.getProperty("user.new.password")), 
-	NewPasswordAgain ("txtNewPasswordAgain", System.getProperty("user.new.password.again")), 
-	Email ("txtEmail", System.getProperty("user.email")), 
-	ColleagueOne ("txtColleagueOne", System.getProperty("user.colleague.one")), 
-	ColleagueTwo ("txtColleagueTwo", System.getProperty("user.colleague.two"));
-	
-	public String val;
-	public String def;
-
-	private AuthenticationTag(final String tag, final String def) {
-		this.val = tag;
-		this.def = def;		
-	}
-	
-	public static Optional<Map<AuthenticationTag, String>> fetchUserData(Collection<Text> from, boolean useDefaults, AuthenticationTag... tags) {
-		final Map<AuthenticationTag, String> fetchedData = new HashMap<AuthenticationTag, String>();
-		
-		for (AuthenticationTag tag: tags) {
-			for (Text canditate: from) {
-				// use the canditate if it exists
-				if (canditate.hasData(tag.val)) {
-					fetchedData.put(tag, canditate.getText());
-					break;
-				}
-				// otherwise try use the default
-				String property = tag.def;
-				if (property != null && !property.isEmpty()) { 
-					fetchedData.put(tag, useDefaults ? property : null); 
-				}
-			}
-		}
-		
-		if (fetchedData.entrySet().size() == tags.length) {
-			return Optional.of(fetchedData);
-		} else { 
-			return Optional.empty();
-		}
-	}
-}
Index: trunk/src/org/expeditee/auth/Authenticator.java
===================================================================
--- trunk/src/org/expeditee/auth/Authenticator.java	(revision 1242)
+++ trunk/src/org/expeditee/auth/Authenticator.java	(revision 1243)
@@ -5,8 +5,8 @@
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
-import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.Writer;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.security.KeyFactory;
 import java.security.KeyStore;
@@ -22,7 +22,7 @@
 import java.sql.Connection;
 import java.sql.DriverManager;
+import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.sql.Statement;
 import java.util.Arrays;
 import java.util.Base64;
@@ -30,4 +30,5 @@
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Scanner;
 import java.util.stream.Stream;
 
@@ -36,4 +37,5 @@
 
 import org.expeditee.actions.Actions;
+import org.expeditee.auth.tags.Constants;
 import org.expeditee.core.Dimension;
 import org.expeditee.core.Point;
@@ -50,9 +52,11 @@
 import org.expeditee.gui.FrameUtils;
 import org.expeditee.gui.MessageBay;
+import org.expeditee.io.ExpReader;
+import org.expeditee.items.Item;
 import org.expeditee.items.ItemUtils;
 import org.expeditee.items.Text;
 import org.expeditee.settings.Settings;
 import org.expeditee.settings.UserSettings;
-import org.expeditee.settings.auth.secrets.KeyList;
+import org.expeditee.settings.identity.secrets.KeyList;
 import org.ngikm.cryptography.CryptographyConstants;
 
@@ -60,7 +64,10 @@
 	
 	// The frame number of the frame containing the current authenticated users public key.
-	public static final int PUBLIC_KEY_FRAME = 4;
+	public static int CREDENTIALS_FRAME = 13;
+	
+	public static boolean Authenticated = false;
 	
 	private final KeyStore keyStore = KeyStore.getInstance(KeystoreType);
+		
 	private static final byte[] TRUE = "yes".getBytes();
 	private static final byte[] FALSE = "no".getBytes();
@@ -82,5 +89,5 @@
 
 		// draw the window
-		final GraphicsManager g = EcosystemManager.getGraphicsManager();
+		GraphicsManager g = EcosystemManager.getGraphicsManager();
 		g.setWindowLocation(new Point(50, 50));
 		DisplayController.Init();
@@ -98,10 +105,10 @@
 		
 		// navigate to authentication frame
-		final Frame authFrame = FrameIO.LoadFrame("authentication1");
+		Frame authFrame = FrameIO.LoadFrame("authentication1");
 		DisplayController.setCurrentFrame(authFrame, true);
 		
 		// set initial values
-		final Stream<Text> usernameItemsStream = authFrame.getTextItems().stream().filter(t -> t.getData() != null && t.getData().contains("txtUsername"));
-		final Stream<Text> passwordItemsStream = authFrame.getTextItems().stream().filter(t -> t.getData() != null && t.getData().contains("txtPassword"));
+		Stream<Text> usernameItemsStream = authFrame.getTextItems().stream().filter(t -> t.getData() != null && t.getData().contains("txtUsername"));
+		Stream<Text> passwordItemsStream = authFrame.getTextItems().stream().filter(t -> t.getData() != null && t.getData().contains("txtPassword"));
 		usernameItemsStream.forEach(txtUsername -> txtUsername.setText(System.getProperty("user.name", "")));
 		passwordItemsStream.forEach(txtPassword -> txtPassword.setText(System.getProperty("user.password", "")));
@@ -109,40 +116,38 @@
 		MessageBay.warningMessages(org.expeditee.actions.Actions.Init());
 		
-		// ensure database
+		// class load database classes
 		Class.forName("org.sqlite.JDBC");
-		if (!mailDatabaseExists()) { 
-			createMailDatabase();
-		}
-	}
-	
-	private void createMailDatabase() throws ClassNotFoundException, SQLException {
-		Connection c = DriverManager.getConnection("jdbc:sqlite:" + FrameIO.PARENT_FOLDER + "/expmail.db");
-		Statement createTable = c.createStatement();
-		String sql = "CREATE TABLE EXPMAIL (" + 
-				"SND		TEXT					NOT NULL, " + 
-				"REC		TEXT					NOT NULL, " + 
-				"MSG		TEXT					NOT NULL, " +
-				"MSG2		TEXT					NOT NULL, " + 
-				"OPTS		ARRAY					NOT NULL, " +
-				"OPTSVAL	ARRAY					NOT NULL)";
-		createTable.executeUpdate(sql);
-		createTable.close();
-		c.close();
-	}
-	
-	final void loadMailDatabase() throws SQLException {
-		Connection c = DriverManager.getConnection("jdbc:sqlite:" + FrameIO.PARENT_FOLDER + "/expmail.db");
-		Statement query = c.createStatement();
-		ResultSet results = query.executeQuery("SELECT * FROM EXPMAIL");
-		Mail.clear();
-		while (results.next()) {
-			String from = results.getString("snd");
-			String to = results.getString("rec");
-			String msg = results.getString("msg");
-			String msg2 = results.getString("msg2");
-			String[] opts = results.getString("opts").split(",");
+	}
+		
+	private void loadKeystore()
+			throws IOException, NoSuchAlgorithmException, CertificateException, FileNotFoundException {
+		final File keyStoreFile = new File(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME);
+		if (!keyStoreFile.exists()) { 
+			keyStore.load(null, Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
+		} else {
+			try (final InputStream in = new FileInputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME)) {
+				keyStore.load(in, Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
+			}
+		}
+	}
+	
+	final void loadMailFromDirectory(Path contactDir) throws SQLException {
+		// Load in all mail.
+		Connection c = DriverManager.getConnection("jdbc:sqlite:" + contactDir.resolve("expmail.db"));
+		String sql = "SELECT * FROM EXPMAIL";
+		PreparedStatement query = c.prepareStatement(sql);
+		ResultSet allMail = query.executeQuery();
+
+		// Construct all mail objects using content from database.
+		while(allMail.next()) {
+			String timestamp = allMail.getString("time");
+			String from = allMail.getString("snd");
+			String to = allMail.getString("rec");
+			String msg = allMail.getString("msg");
+			String msg2 = allMail.getString("msg2");
+			String[] opts = allMail.getString("opts").split(",");
 			opts[0] = opts[0].replace("[", "");
 			opts[opts.length - 1] = opts[opts.length - 1].replace("]", "");
-			String[] optsVal = results.getString("optsval").split(",");
+			String[] optsVal = allMail.getString("optsval").split(",");
 			optsVal[0] = optsVal[0].replace("[", "");
 			optsVal[optsVal.length - 1] = optsVal[optsVal.length - 1].replace("]", "");
@@ -155,24 +160,20 @@
 			}
 			
-			Mail.addEntry(new Mail.MailEntry(from, to, msg, msg2, options));
-		}
-		results.close();
+			Mail.addEntry(new Mail.MailEntry(timestamp, from, to, msg, msg2, options));
+		}
+		
+		// Disconnect from database.
+		allMail.close();
 		query.close();
 		c.close();
 	}
 	
-	private boolean mailDatabaseExists() {
-		final File file = new File(FrameIO.PARENT_FOLDER + "/expmail.db");
-		return file.exists();
-	}
-		
-	private void loadKeystore()
-			throws IOException, NoSuchAlgorithmException, CertificateException, FileNotFoundException {
-		final File keyStoreFile = new File(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME);
-		if (!keyStoreFile.exists()) { 
-			keyStore.load(null, "ExpediteeAuthPassword".toCharArray());
-		} else {
-			try (final InputStream in = new FileInputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME)) {
-				keyStore.load(in, "ExpediteeAuthPassword".toCharArray());
+	final void loadMailDatabase() throws SQLException {
+		Path contactsPath = Paths.get(FrameIO.CONTACTS_PATH);
+		File[] contacts = contactsPath.toFile().listFiles();
+		for (int i = 0; i < contacts.length; i++) {
+			if (contacts[i].isDirectory()) {
+				Path contact = Paths.get(contacts[i].getAbsolutePath());
+				loadMailFromDirectory(contact);
 			}
 		}
@@ -195,31 +196,5 @@
 		final KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(password.toCharArray());
 		keyStore.setEntry(label, entry, entryPassword);
-		keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), "ExpediteeAuthPassword".toCharArray());
-	}
-	
-	final void putEmail(String username, String email) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
-		// Establish location of email file
-		String emailFilePath = FrameIO.PROFILE_PATH + username + File.separator + username + ".email";
-		File emailFile = new File(emailFilePath);
-		
-		// Delete old version if it exists.
-		if (emailFile.exists()) { 
-			emailFile.delete();
-		}
-		
-		// Write email to file
-		emailFile.createNewFile();
-		Writer w = new FileWriter(emailFile);
-		w.write(email);
-		w.flush();
-		w.close();
-		
-		// TODO: set rights on file to be read only by 'owner' once installed on drive.
-	}
-	
-	final boolean hasRegisteredEmail(String username) throws KeyStoreException {
-		String emailFilePath = FrameIO.PROFILE_PATH + username + File.separator + username + ".email";
-		File emailFile = new File(emailFilePath);
-		return emailFile.exists();
+		keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
 	}
 	
@@ -232,5 +207,5 @@
 			} else if (entry.getSecretKey().getEncoded() == TRUE) {
 				keyStore.deleteEntry(email + username);
-				keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), "ExpediteeAuthPassword".toCharArray());
+				keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
 				return true;
 			} else { return false; }
@@ -251,22 +226,36 @@
 		final KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(intergalacticNumber.toCharArray());
 		keyStore.setEntry(email + username, entry, entryPassword);
-		keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), "ExpediteeAuthPassword".toCharArray());
+		keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
 		
 		return intergalacticNumber;
 	}
 	
-	final PublicKey getPublicKey(String username) throws InvalidKeySpecException, NoSuchAlgorithmException {
-		Frame withTargetPublic = FrameIO.LoadFrame(username + Authenticator.PUBLIC_KEY_FRAME);
-		Collection<Text> textItems = withTargetPublic.getTextItems(); 
-		textItems.removeIf(t -> !t.getText().startsWith("PublicKey"));
-		
-		if (textItems.isEmpty()) {
+	final PublicKey getPublicKey(String username) throws InvalidKeySpecException, NoSuchAlgorithmException, FileNotFoundException {
+		// load in frame with public key on it.
+		String credentialsFramesetPath = FrameIO.CONTACTS_PATH + username + "-credentials" + File.separator;
+		if (!new File(credentialsFramesetPath).exists()) {
 			return null;
-		} else {
-			String keyEncoded = textItems.stream().findFirst().get().getData().get(0);
-			byte[] keyBytes = Base64.getDecoder().decode(keyEncoded);
-			PublicKey key = KeyFactory.getInstance(AsymmetricAlgorithm).generatePublic(new X509EncodedKeySpec(keyBytes));
-			return key;
-		}
+		}
+		Scanner in = new Scanner(new File(credentialsFramesetPath + "credentials.inf"));
+		String credentialsFrameNumber = in.nextLine().replace(ExpReader.EXTENTION, "");
+		in.close();
+		Frame frame = FrameIO.LoadFrame(username + "-credentials" + credentialsFrameNumber, FrameIO.CONTACTS_PATH);
+		if (frame == null) {
+			return null;
+		}
+		
+		// obtain public key from frame
+		Collection<Item> canditates = org.expeditee.auth.Actions.getByContent(frame, "PublicKey");
+		String keyEncoded = "";
+		for (Item i: canditates) {
+			if (i.getData() != null) {
+				keyEncoded = i.getData().get(0);
+			}
+		}
+		if (keyEncoded.isEmpty()) {
+			return null;
+		}
+		byte[] keyBytes = Base64.getDecoder().decode(keyEncoded);
+		return KeyFactory.getInstance(AsymmetricAlgorithm).generatePublic(new X509EncodedKeySpec(keyBytes));
 	}
 	
@@ -275,5 +264,5 @@
 		KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
 		keyStore.setEntry(username + "colleaguesRequested", entry, entryPassword);
-		keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), "ExpediteeAuthPassword".toCharArray());
+		keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
 	}
 	
@@ -282,5 +271,5 @@
 		KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
 		keyStore.setEntry(username + "colleaguesRequested", entry, entryPassword);
-		keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), "ExpediteeAuthPassword".toCharArray());
+		keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
 	}
 	
@@ -296,24 +285,24 @@
 	}
 	
-	final void putColleagues(String username, String[] colleagues) throws KeyStoreException {
-		String alias = username + "colleagues";
-		final SecretKeySpec secretKeySpec = new SecretKeySpec((colleagues[0] + System.getProperty("line.separator") + colleagues[1]).getBytes(), SymmetricAlgorithm);
-		KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(secretKeySpec);
-		KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
-		keyStore.setEntry(alias, entry, entryPassword);
-	}
-	
-	final String[] getColleagues(String username) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException {
-		String alias = username + "colleagues";
-		if (!keyStore.containsAlias(alias)) {
-			return null;
-		} else {
-			KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
-			KeyStore.SecretKeyEntry entry = (SecretKeyEntry) keyStore.getEntry(alias, entryPassword);
-			byte[] colleaguesEncoded = entry.getSecretKey().getEncoded();
-			String colleagues = new String(colleaguesEncoded);
-			return colleagues.split(System.getProperty("line.separator"));
-		}
-	}
+//	final void putColleagues(String username, String[] colleagues) throws KeyStoreException {
+//		String alias = username + "colleagues";
+//		final SecretKeySpec secretKeySpec = new SecretKeySpec((colleagues[0] + System.getProperty("line.separator") + colleagues[1]).getBytes(), SymmetricAlgorithm);
+//		KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(secretKeySpec);
+//		KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
+//		keyStore.setEntry(alias, entry, entryPassword);
+//	}
+//	
+//	final String[] getColleagues(String username) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException {
+//		String alias = username + "colleagues";
+//		if (!keyStore.containsAlias(alias)) {
+//			return null;
+//		} else {
+//			KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
+//			KeyStore.SecretKeyEntry entry = (SecretKeyEntry) keyStore.getEntry(alias, entryPassword);
+//			byte[] colleaguesEncoded = entry.getSecretKey().getEncoded();
+//			String colleagues = new String(colleaguesEncoded);
+//			return colleagues.split(System.getProperty("line.separator"));
+//		}
+//	}
 	
 	private static void setInputManagerWindowRoutines()	{
Index: trunk/src/org/expeditee/auth/EncryptedExpReader.java
===================================================================
--- trunk/src/org/expeditee/auth/EncryptedExpReader.java	(revision 1242)
+++ trunk/src/org/expeditee/auth/EncryptedExpReader.java	(revision 1243)
@@ -23,5 +23,5 @@
 import org.expeditee.io.ExpReader;
 import org.expeditee.items.Text;
-import org.expeditee.settings.auth.secrets.KeyList;
+import org.expeditee.settings.identity.secrets.KeyList;
 import org.ngikm.cryptography.CryptographyConstants;
 
@@ -31,7 +31,5 @@
 	static final String ENCRYPTED_EXP_FLAG = "EncryptedExp";
 	private SecretKey personalKey;
-	//private List<SecretKey> multiKey;
 	private boolean accessDenied = false;
-	//private boolean usePersonalKey;
 
 	public EncryptedExpReader(final String frameName) throws UnsupportedEncodingException {
@@ -49,9 +47,4 @@
 		try {
 			BufferedReader reader = new EncryptedLineReader(new BufferedReader(new FileReader(fullpath)));
-			//if (usePersonalKey) {
-			//	reader = new EncryptedProfileLineReader(new BufferedReader(new FileReader(fullpath)));
-			//} else {
-			//	reader = new EncryptedLineReader(new BufferedReader(new FileReader(fullpath)));
-			//}
 			String next = "";
 			// First read the header lines until we get the version number
@@ -76,9 +69,4 @@
 		Reader in = new InputStreamReader(new FileInputStream(fullPath), "UTF-8");
 		return readFrame(new EncryptedLineReader(in));
-		//if (usePersonalKey) {
-		//	return readFrame(new EncryptedProfileLineReader(new BufferedReader(in)));
-		//} else {
-		//	return readFrame(new EncryptedLineReader(new BufferedReader(in)));
-		//}
 	}
 	
Index: trunk/src/org/expeditee/auth/EncryptedExpWriter.java
===================================================================
--- trunk/src/org/expeditee/auth/EncryptedExpWriter.java	(revision 1242)
+++ trunk/src/org/expeditee/auth/EncryptedExpWriter.java	(revision 1243)
@@ -6,4 +6,5 @@
 import java.util.Arrays;
 import java.util.Base64;
+import java.util.List;
 
 import javax.crypto.BadPaddingException;
@@ -16,5 +17,5 @@
 import org.expeditee.io.ExpWriter;
 import org.expeditee.items.Text;
-import org.expeditee.settings.auth.secrets.KeyList;
+import org.expeditee.settings.identity.secrets.KeyList;
 import org.ngikm.cryptography.CryptographyConstants;
 
@@ -28,6 +29,9 @@
 			// obtain personal key
 			Text text = KeyList.PersonalKey.get();
-			byte[] keyBytes = Base64.getDecoder().decode(text.getData().get(0));
-			key = new SecretKeySpec(keyBytes, SymmetricAlgorithm);
+			List<String> data = text.getData();
+			if (data != null && !data.isEmpty()) {
+				byte[] keyBytes = Base64.getDecoder().decode(data.get(0));
+				key = new SecretKeySpec(keyBytes, SymmetricAlgorithm);
+			}
 			label = "Profile";
 		} else {
Index: trunk/src/org/expeditee/auth/Mail.java
===================================================================
--- trunk/src/org/expeditee/auth/Mail.java	(revision 1242)
+++ trunk/src/org/expeditee/auth/Mail.java	(revision 1243)
@@ -1,4 +1,5 @@
 package org.expeditee.auth;
 
+import java.nio.file.Path;
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
@@ -21,5 +22,4 @@
 import javax.crypto.NoSuchPaddingException;
 
-import org.expeditee.gui.FrameIO;
 import org.ngikm.cryptography.CryptographyConstants;
 
@@ -39,9 +39,11 @@
 	}
 	
-	public static void sendMail(MailEntry mail, PublicKey key) {
+	public static void sendMail(MailEntry mail, PublicKey key, Path outbox) {
 		try {
 			Cipher cipher = Cipher.getInstance(AsymmetricAlgorithm + AsymmetricAlgorithmParameters);
 			
 			// encrypt the necessary parts of the message
+			cipher.init(Cipher.ENCRYPT_MODE, key);
+			String time = Base64.getEncoder().encodeToString(cipher.doFinal(mail.timestamp.getBytes()));
 			cipher.init(Cipher.ENCRYPT_MODE, key);
 			String sender = Base64.getEncoder().encodeToString(cipher.doFinal(mail.sender.getBytes()));
@@ -63,15 +65,16 @@
 			
 			// write to mail database
-			Connection c = DriverManager.getConnection("jdbc:sqlite:" + FrameIO.PARENT_FOLDER + "/expmail.db");
-			String sql = "INSERT INTO EXPMAIL (SND,REC,MSG,MSG2,OPTS,OPTSVAL) VALUES (?, ?, ?, ?, ?, ?);";
+			Connection c = DriverManager.getConnection("jdbc:sqlite:" + outbox.resolve("expmail.db"));
+			String sql = "INSERT INTO EXPMAIL (TIME,SND,REC,MSG,MSG2,OPTS,OPTSVAL) VALUES (?, ?, ?, ?, ?, ?, ?);";
 			PreparedStatement statement = c.prepareStatement(sql);
-			statement.setString(1, sender);
-			statement.setString(2, rec);
-			statement.setString(3, message);
-			statement.setString(4, message2);
+			statement.setString(1, time);
+			statement.setString(2, sender);
+			statement.setString(3, rec);
+			statement.setString(4, message);
+			statement.setString(5, message2);
 			String opts = Arrays.toString(options.keySet().toArray());
-			statement.setString(5, opts);
+			statement.setString(6, opts);
 			String optsval = Arrays.toString(options.values().toArray());
-			statement.setString(6, optsval);
+			statement.setString(7, optsval);
 			statement.execute();
 			statement.close();
@@ -105,5 +108,7 @@
 			
 			// add an unencrypted version of the message to the return list
-			if (receiverDecrypted.compareTo(name) == 0) {
+			if (receiverDecrypted.compareToIgnoreCase(name) == 0) {
+				c.init(Cipher.DECRYPT_MODE, key);
+				String timestamp = new String(c.doFinal(Base64.getDecoder().decode(mail.timestamp)));
 				c.init(Cipher.DECRYPT_MODE, key);
 				String sender = new String(c.doFinal(Base64.getDecoder().decode(mail.sender)));
@@ -123,5 +128,5 @@
 				
 				//String arguments = new String(c.doFinal(Base64.getDecoder().decode(mail.args)));
-				filtered.add(new MailEntry(sender, receiverDecrypted, message, message2, options));
+				filtered.add(new MailEntry(timestamp, sender, receiverDecrypted, message, message2, options));
 			}
 		}
@@ -134,4 +139,5 @@
 	 */
 	public static class MailEntry {
+		public String timestamp;
 		public String sender;
 		public String receiver;
@@ -140,5 +146,6 @@
 		public Map<String, String> options;
 		
-		public MailEntry(String sender, String rec, String message, String message2, Map<String, String> options) {
+		public MailEntry(String timestamp, String sender, String rec, String message, String message2, Map<String, String> options) {
+			this.timestamp = timestamp;
 			this.sender = sender;
 			this.receiver = rec;
Index: trunk/src/org/expeditee/auth/gui/MailBay.java
===================================================================
--- trunk/src/org/expeditee/auth/gui/MailBay.java	(revision 1242)
+++ trunk/src/org/expeditee/auth/gui/MailBay.java	(revision 1243)
@@ -88,5 +88,5 @@
 	 * @return
 	 */
-	public synchronized static Text addMessage(String message, String message2, Map<String, String> options) {
+	public synchronized static Text addMessage(String timestamp, String message, String message2, Map<String, String> options) {
 		// Invalidate whole area
 		DisplayController.invalidateArea(DisplayController.getMessageBayPaintArea());
@@ -113,4 +113,5 @@
 		_previewMessages.add(t);
 		_messages.add(t);
+		_creator.addText(timestamp, Colour.BLACK, null, null, false);
 		for (Text line: mail.getMessage()) {
 			_creator.addItem(line.copy(), false);
Index: trunk/src/org/expeditee/auth/tags/AuthenticationTag.java
===================================================================
--- trunk/src/org/expeditee/auth/tags/AuthenticationTag.java	(revision 1243)
+++ trunk/src/org/expeditee/auth/tags/AuthenticationTag.java	(revision 1243)
@@ -0,0 +1,58 @@
+package org.expeditee.auth.tags;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+import org.expeditee.items.Text;
+
+public enum AuthenticationTag {
+	Username ("txtUsername", System.getProperty("user.name")), 
+	Password ("txtPassword", System.getProperty("user.password")), 
+	PasswordAgain ("txtPasswordAgain", System.getProperty("user.password.again")), 
+	NewPassword ("txtNewPassword", System.getProperty("user.new.password")), 
+	NewPasswordAgain ("txtNewPasswordAgain", System.getProperty("user.new.password.again")), 
+	Email ("txtEmail", System.getProperty("user.email")), 
+	EmailAgain ("txtEmailAgain", System.getProperty("user.email.again")),
+	ColleagueOne ("txtColleagueOne", System.getProperty("user.colleague.one")), 
+	ColleagueTwo ("txtColleagueTwo", System.getProperty("user.colleague.two")), 
+	Frameset ("txtFrameset", System.getProperty("user.toshare.frameset")); 
+	
+	public String val;
+	public String def;
+
+	private AuthenticationTag(String tag, String def) {
+		this.val = tag;
+		this.def = def;		
+	}
+	
+	public static Optional<Map<AuthenticationTag, String>> fetchUserData(Collection<Text> from, boolean useDefaults, AuthenticationTag... tags) {
+		final Map<AuthenticationTag, String> fetchedData = new HashMap<AuthenticationTag, String>();
+		
+		for (AuthenticationTag tag: tags) {
+			for (Text canditate: from) {
+				// use the canditate if it exists
+				if (canditate.hasData(tag.val)) {
+					if (tag.val.equals("txtUsername")) {
+						fetchedData.put(tag, canditate.getText().toLowerCase());
+					} else {
+						fetchedData.put(tag, canditate.getText());
+					}
+					break;
+				}
+				// otherwise try use the default
+				String property = tag.def;
+				if (property != null && !property.isEmpty()) { 
+					fetchedData.put(tag, useDefaults ? property : null); 
+				}
+			}
+		}
+		
+		if (fetchedData.entrySet().size() == tags.length) {
+			return Optional.of(fetchedData);
+		} else { 
+			return Optional.empty();
+		}
+	}
+}
Index: trunk/src/org/expeditee/auth/tags/Constants.java
===================================================================
--- trunk/src/org/expeditee/auth/tags/Constants.java	(revision 1243)
+++ trunk/src/org/expeditee/auth/tags/Constants.java	(revision 1243)
@@ -0,0 +1,30 @@
+package org.expeditee.auth.tags;
+
+public class Constants {
+
+	public static final String ERROR_INVALID_USERNAME = "The provided username must begin and end with a letter and contain only letters and numbers inbetween, please choose another.";
+	public static final String ERROR_INSUFFICIENT_INFORMATION = "Insufficient information provided to complete this action.";
+	public static final String ERROR_MUST_BE_LOGGED_IN = "You must be logged in to perform this action.";
+	public static final String ERROR_INSUFFICIENT_INFORMATION_PROVIDED = "Please fill out all the supplied text boxes.";
+	public static final String ERROR_MISMATCH_EMAILS = "The provided emails do not match, please fix this and try again.";
+	public static final String ERROR_MISMATCH_PASSWORDS = "The provided passwords do not match, please fix this and try again.";
+	public static final String ERROR_PROFILE_NAME_PREEXISTS = "A Expeditee profile with this username already exists, please choose another.";
+	public static final String CREDENTIALS_KEYSTORE_PASSWORD = "ExpediteeAuthPassword";
+	public static final String LABEL_PROFILENAME = "Profilename";
+	public static final String LABEL_USERNAME = "Username";
+	public static final String TOOLTIP_SETTING_EMAIL = "Your public-facing email address.";
+	public static final String TOOLTIP_SETTING_PUBLIC_KEY = "The RSA key used to decrypt things encrypted with your RSA public key.";
+	public static final String TOOLTIP_SETTING_PRIVATE_KEY = "The RSA key used to decrypt things encrypted with your RSA public key - do not share with anyone!";
+	public static final String TOOLTIP_SETTING_PERSONAL_KEY = "The AES key used to secure your profile frame - do not share with anyone!";
+	public static final String SETTINGS_USER_SETTINGS_PROFILE_NAME = "settings.UserSettings.ProfileName";
+	public static final String SETTINGS_USER_SETTINGS_USER_NAME = "settings.UserSettings.UserName";
+	public static final String SETTINGS_AUTH_EMAIL = "settings.identity.Email";
+	public static final String SETTINGS_AUTH_PUBLIC_KEY = "settings.identity.PublicKey";
+	public static final String SETTINGS_AUTH_SECRETS_PRIVATE_KEY = "settings.identity.secrets.PrivateKey";
+	public static final String SETTINGS_AUTH_SECRETS_PERSONAL_KEY = "settings.identity.secrets.PersonalKey";
+	public static final String DATA_SHOW_ON_PROGRESS = "ShowOnProgress";
+	public static final String FRAME_COLLEAGUE_SUBMISSION_FRAME = "authentication7";
+	public static final String FRAME_AUTHENTICATION1 = "authentication1";
+	public static final String FRAME_MULTIUSER1 = "multiuser1";
+
+}
Index: trunk/src/org/expeditee/auth/tags/GenerationTag.java
===================================================================
--- trunk/src/org/expeditee/auth/tags/GenerationTag.java	(revision 1243)
+++ trunk/src/org/expeditee/auth/tags/GenerationTag.java	(revision 1243)
@@ -0,0 +1,18 @@
+package org.expeditee.auth.tags;
+
+public interface GenerationTag {
+	public String DesiredWidth300 = "W300";
+	public String UsernameTextBox = "txtUsername";
+	
+	public interface Settings {
+		public String UsernameLabeledProfileName = "lblUsernameLabeledProfile";
+		public String UsernameLabeledUserName = "lblUsernameLabeledUser";
+		public String Email = "lblEmail";
+	}
+	
+	public interface Keys {
+		public String PersonalKey = "lblPersonalKey";
+		public String PublicKey = "lblPublicKey";
+		public String PrivateKey = "lblPrivateKey";
+	}
+}
