Index: unk/src/org/expeditee/auth/Authenticator.java
===================================================================
--- /trunk/src/org/expeditee/auth/Authenticator.java	(revision 1281)
+++ 	(revision )
@@ -1,484 +1,0 @@
-package org.expeditee.auth;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.security.KeyFactory;
-import java.security.KeyStore;
-import java.security.KeyStore.SecretKeyEntry;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.UnrecoverableEntryException;
-import java.security.cert.CertificateException;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.X509EncodedKeySpec;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
-import java.util.Base64;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.Set;
-import java.util.stream.Stream;
-
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
-
-import org.expeditee.actions.Actions;
-import org.expeditee.auth.tags.Constants;
-import org.expeditee.core.Dimension;
-import org.expeditee.core.Point;
-import org.expeditee.gio.EcosystemManager;
-import org.expeditee.gio.GraphicsManager;
-import org.expeditee.gio.InputManager;
-import org.expeditee.gio.InputManager.WindowEventListener;
-import org.expeditee.gio.InputManager.WindowEventType;
-import org.expeditee.gio.gesture.StandardGestureActions;
-import org.expeditee.gui.Browser;
-import org.expeditee.gui.DisplayController;
-import org.expeditee.gui.Frame;
-import org.expeditee.gui.FrameIO;
-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.identity.secrets.KeyList;
-import org.expeditee.stats.Formatter;
-import org.ngikm.cryptography.CryptographyConstants;
-
-public final class Authenticator extends Browser implements CryptographyConstants {
-	
-	// The frame number of the frame containing the current authenticated users public key.
-	public static int CREDENTIALS_FRAME = -1;
-	public static final String ADMINACCOUNT = "authadmin";
-	
-	public static boolean Authenticated = false;
-	
-	private KeyStore keyStore = KeyStore.getInstance(KeystoreType);
-		
-	private static final byte[] TRUE = "yes".getBytes();
-	private static final byte[] FALSE = "no".getBytes();
-	private static final String KEYSTOREFILENAME = "keystore.ks" + File.separator;
-		
-	private static Authenticator instance;
-	
-	public static Authenticator getInstance() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, IOException, ClassNotFoundException, SQLException {
-		if (instance == null) { instance = new Authenticator(); } 
-		return instance;
-	}
-	
-	private Authenticator() throws KeyStoreException, FileNotFoundException, IOException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, SQLException {
-		super("Authentication");
-		UserSettings.setupDefaultFolders();
-			
-		// initialise keystore and actions
-		loadKeystore();
-		Actions.LoadMethods(org.expeditee.auth.Actions.class);
-		Actions.LoadMethods(org.expeditee.auth.sharing.Actions.class);
-
-		// Does the account Authentication.ADMINACCOUNT exist?
-		// If not then we have get the user to assign a password to it.
-		if (!keyStore.containsAlias(Authenticator.ADMINACCOUNT)) {
-			new File(FrameIO.PARENT_FOLDER).mkdirs();
-			protectAdmin();
-		}
-		
-		// draw the window
-		GraphicsManager g = EcosystemManager.getGraphicsManager();
-		g.setWindowLocation(new Point(50, 50));
-		DisplayController.Init();
-		g.setWindowSize(new Dimension(UserSettings.InitialWidth.get(), UserSettings.InitialHeight.get()));
-		setInputManagerWindowRoutines();
-		
-		// Load documentation and start pages
-		FrameUtils.extractResources(false);
-
-		// Load fonts before loading any frames so the items on the frames will be able to access their fonts
-		Text.InitFonts();
-		
-		// initialing settings does not require a user profile established
-		Settings.Init();
-		
-		// navigate to authentication frame
-		Frame authFrame = FrameIO.LoadFrame("authentication1");
-		DisplayController.setCurrentFrame(authFrame, true);
-		
-		// set initial values
-		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("startinguser.name", "")));
-		passwordItemsStream.forEach(txtPassword -> { txtPassword.setText(""); txtPassword.invalidateAll(); });
-						
-		MessageBay.warningMessages(org.expeditee.actions.Actions.Init());
-		
-		// class load database classes
-		Class.forName("org.sqlite.JDBC");
-		_theBrowser = this;
-	}
-
-	private void protectAdmin() throws KeyStoreException, NoSuchAlgorithmException, CertificateException,
-			FileNotFoundException, IOException {
-		// Fetch desired password
-		Scanner in = new Scanner(System.in);
-		System.out.println("No administrative password set.");
-		boolean passwordIsSet = false;
-		
-		for (int i = 0; i < 3; i++) {
-			System.out.print("Please enter it now: ");
-			System.out.flush();
-			String password = in.nextLine();
-			System.out.print("And again: ");
-			System.out.flush();
-			if (in.nextLine().equals(password)) {
-				// Register account.
-				putKey(ADMINACCOUNT, password, new SecretKeySpec("null".getBytes(), AsymmetricAlgorithm));
-				in.close();
-				passwordIsSet = true;
-				break;
-			} else {
-				System.out.println("Mismatched passwords, let's try that again.");
-			}
-		}
-		
-		if (!passwordIsSet) {
-			System.out.println("Failed to set an admin password.  Exiting Expeditee.");
-			System.exit(1);
-		}
-	}
-		
-	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 loadMailFromFile(Path dbFile) throws SQLException {
-		// Load in all mail.
-		Connection c = DriverManager.getConnection("jdbc:sqlite:" + dbFile.toAbsolutePath().toString());
-		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 = allMail.getString("optsval").split(",");
-			optsVal[0] = optsVal[0].replace("[", "");
-			optsVal[optsVal.length - 1] = optsVal[optsVal.length - 1].replace("]", "");
-			
-			Map<String, String> options = new HashMap<String, String>();
-			for (int i = 0, o = 0; i < opts.length && o < optsVal.length; i++, o++) {
-				String key = opts[i].trim();
-				String val = optsVal[o].trim();
-				options.put(key, val);
-			}
-			
-			Mail.addEntry(new Mail.MailEntry(timestamp, from, to, msg, msg2, options));
-		}
-		
-		// Disconnect from database.
-		allMail.close();
-		query.close();
-		c.close();
-	}
-	
-	final void loadMailDatabase() throws SQLException, FileNotFoundException, ParseException {
-		Path deadDropPath = Paths.get(FrameIO.DEAD_DROPS_PATH);
-		for (File connectionDir: deadDropPath.toFile().listFiles()) {
-			if (connectionDir.isDirectory()) {
-				Path deaddropforcontactPath = Paths.get(connectionDir.getAbsolutePath());
-				Path dbFile = deaddropforcontactPath.resolve(UserSettings.UserName.get() + ".db");
-				if (dbFile.toFile().exists()) {
-					loadMailFromFile(dbFile);
-				}
-				Path timestamp = deaddropforcontactPath.resolve(UserSettings.UserName.get() + ".last-accessed");
-				try(FileWriter out = new FileWriter(timestamp.toFile())) {
-					out.write(Formatter.getDateTime() + System.getProperty("line.separator"));
-				} catch (IOException e) {
-					e.printStackTrace();
-				}
-				clearOldMailFromDatabase(deaddropforcontactPath);
-			}
-		}
-	}
-	
-	private void clearOldMailFromDatabase(Path directory) throws FileNotFoundException, ParseException, SQLException {
-		File[] files = directory.toFile().listFiles(new FileFilter() {
-			@Override
-			public boolean accept(File file) {
-				return !file.getName().startsWith(UserSettings.UserName.get());
-			}
-		});
-		
-		File dbFile = null;
-		File lastAccessedFile = null;
-		for (File file: files) {
-			if (file.getName().endsWith(".db")) {
-				dbFile = file;
-			} else {
-				lastAccessedFile = file;
-			}
-		}
-		
-		if (dbFile == null || lastAccessedFile == null) {
-			System.err.println("Failed to clear old messages from database file.");
-			return; // Not the end of the world if we cannot clear out old messages.
-		}
-		
-		SimpleDateFormat format = new SimpleDateFormat("ddMMMyyyy[HH:mm]");
-		Date timestamp = null;
-		try(Scanner in = new Scanner(lastAccessedFile)) {
-			timestamp = format.parse(in.nextLine());
-		} catch (ParseException e) {
-			System.err.println("Failed to clear old messages from database file.");
-			return; // Not the end of the world if we cannot clear out old messages.
-		}
-		
-		Connection c = DriverManager.getConnection("jdbc:sqlite:" + dbFile.getAbsolutePath());
-		String sql = "SELECT * FROM EXPMAIL";
-		PreparedStatement query = c.prepareStatement(sql);
-		ResultSet allMail = query.executeQuery();
-		Set<String> oldTimestamps = new HashSet<String>();
-		
-		while (allMail.next()) {
-			String time = allMail.getString("time");
-			Date messageTimestamp = format.parse(time);
-			if (timestamp.after(messageTimestamp)) {
-				oldTimestamps.add(time);
-			}
-		}
-		
-		if (oldTimestamps.isEmpty()) {
-			return;
-		}
-		
-		for(String oldTimestamp: oldTimestamps) {
-			System.out.println("Deleting message with timestamp: " + oldTimestamp);
-			sql = "DELETE FROM EXPMAIL WHERE time='" + oldTimestamp + "'";
-			query = c.prepareStatement(sql);
-			query.executeUpdate();
-		}		
-	}
-	 
-	final SecretKey getSecretKey(final String label, final String password) throws NoSuchAlgorithmException, KeyStoreException {	
-		
-		char[] password_ca = password.toCharArray();
-		
-		SecretKey secret_key;
-		try {
-			secret_key = (SecretKey) keyStore.getKey(label, password_ca);			
-		} catch (final UnrecoverableEntryException e) {
-			return null;
-		}
-		
-		return secret_key;
-	}
-	
-	final void putKey(final String label, final String password, final SecretKey key) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
-		final KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(key);
-		final KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(password.toCharArray());
-		keyStore.setEntry(label, entry, entryPassword);
-		keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
-	}
-	
-	final boolean confirmIntergalaticNumber(final String username, final String email, final String intergalacticNumber) throws NoSuchAlgorithmException, KeyStoreException, CertificateException, FileNotFoundException, IOException {
-		try {
-			final KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(intergalacticNumber.toCharArray());
-			final KeyStore.SecretKeyEntry entry = (SecretKeyEntry) keyStore.getEntry(email + username, entryPassword);
-			if (entry == null) { 
-				return false;
-			} else if (entry.getSecretKey().getEncoded() == TRUE) {
-				keyStore.deleteEntry(email + username);
-				keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
-				return true;
-			} else { return false; }
-		} catch (final UnrecoverableEntryException e) {
-			return false;
-		}
-	}
-	
-	final String newIntergalacticNumber(final String username, final String email) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
-		// generate intergalactic number
-		final SecureRandom rand = new SecureRandom();
-		final byte[] intergalacticNumberBytes = new byte[20];
-		rand.nextBytes(intergalacticNumberBytes);
-		final String intergalacticNumber = Base64.getEncoder().encodeToString(intergalacticNumberBytes);
-		
-		// store intergalactic number
-		final KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(new SecretKeySpec(TRUE, SymmetricAlgorithm));
-		final KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(intergalacticNumber.toCharArray());
-		keyStore.setEntry(email + username, entry, entryPassword);
-		keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
-		
-		return intergalacticNumber;
-	}
-	
-	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;
-		}
-		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));
-	}
-	
-	final void markRequestedColleagues(String username) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
-		KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(new SecretKeySpec(TRUE, SymmetricAlgorithm));
-		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), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
-	}
-	
-	final void clearRequestedColleagues(String username) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
-		KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(new SecretKeySpec(FALSE, SymmetricAlgorithm));
-		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), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
-	}
-	
-	final boolean hasRequestedColleagues(String username) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException {
-		String alias = username + "colleaguesRequested";
-		if (!keyStore.containsAlias(alias)) {
-			return false;
-		} else {
-			KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
-			KeyStore.SecretKeyEntry entry = (SecretKeyEntry) keyStore.getEntry(alias, entryPassword);
-			return Arrays.equals(entry.getSecretKey().getEncoded(), TRUE);
-		}
-	}
-	
-//	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()	{
-		InputManager manager = EcosystemManager.getInputManager();
-		
-	    // Refresh the layout when the window resizes
-		manager.addWindowEventListener(new WindowEventListener() {
-			@Override
-			public void onWindowEvent(WindowEventType type)
-			{
-				if (type != WindowEventType.WINDOW_RESIZED) {
-					return;
-				}
-				DisplayController.refreshWindowSize();
-				FrameIO.RefreshCacheImages();
-				for (Frame frame : DisplayController.getFrames()) {
-					if (frame != null) {
-						ItemUtils.Justify(frame);
-						frame.refreshSize();
-					}
-				}
-				DisplayController.requestRefresh(false);
-			}
-		});
-		
-		manager.addWindowEventListener(new WindowEventListener() {
-			@Override
-			public void onWindowEvent(WindowEventType type)
-			{
-				if (type != WindowEventType.MOUSE_EXITED_WINDOW) {
-					return;
-				}
-				StandardGestureActions.mouseExitedWindow();
-			}
-		});
-		
-		manager.addWindowEventListener(new WindowEventListener() {
-			@Override
-			public void onWindowEvent(WindowEventType type)
-			{
-				if (type != WindowEventType.MOUSE_ENTERED_WINDOW) {
-					return;
-				}
-				StandardGestureActions.mouseEnteredWindow();
-			}
-		});
-		
-		manager.addWindowEventListener(new WindowEventListener() {
-			@Override
-			public void onWindowEvent(WindowEventType type)
-			{
-				if (type != WindowEventType.WINDOW_CLOSED) {
-					return;
-				}
-				if (Browser._theBrowser != null) {
-					Browser._theBrowser.exit();
-				}
-			}
-		});
-	}
-}
Index: /trunk/src/org/expeditee/auth/AuthenticatorBrowser.java
===================================================================
--- /trunk/src/org/expeditee/auth/AuthenticatorBrowser.java	(revision 1282)
+++ /trunk/src/org/expeditee/auth/AuthenticatorBrowser.java	(revision 1282)
@@ -0,0 +1,484 @@
+package org.expeditee.auth;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.KeyFactory;
+import java.security.KeyStore;
+import java.security.KeyStore.SecretKeyEntry;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.UnrecoverableEntryException;
+import java.security.cert.CertificateException;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.expeditee.actions.Actions;
+import org.expeditee.auth.tags.Constants;
+import org.expeditee.core.Dimension;
+import org.expeditee.core.Point;
+import org.expeditee.gio.EcosystemManager;
+import org.expeditee.gio.GraphicsManager;
+import org.expeditee.gio.InputManager;
+import org.expeditee.gio.InputManager.WindowEventListener;
+import org.expeditee.gio.InputManager.WindowEventType;
+import org.expeditee.gio.gesture.StandardGestureActions;
+import org.expeditee.gui.Browser;
+import org.expeditee.gui.DisplayController;
+import org.expeditee.gui.Frame;
+import org.expeditee.gui.FrameIO;
+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.identity.secrets.KeyList;
+import org.expeditee.stats.Formatter;
+import org.ngikm.cryptography.CryptographyConstants;
+
+public final class AuthenticatorBrowser extends Browser implements CryptographyConstants {
+	
+	// The frame number of the frame containing the current authenticated users public key.
+	public static int CREDENTIALS_FRAME = -1;
+	public static final String ADMINACCOUNT = "authadmin";
+	
+	public static boolean Authenticated = false;
+	
+	private KeyStore keyStore = KeyStore.getInstance(KeystoreType);
+		
+	private static final byte[] TRUE = "yes".getBytes();
+	private static final byte[] FALSE = "no".getBytes();
+	private static final String KEYSTOREFILENAME = "keystore.ks" + File.separator;
+		
+	private static AuthenticatorBrowser instance;
+	
+	public static AuthenticatorBrowser getInstance() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, IOException, ClassNotFoundException, SQLException {
+		if (instance == null) { instance = new AuthenticatorBrowser(); } 
+		return instance;
+	}
+	
+	private AuthenticatorBrowser() throws KeyStoreException, FileNotFoundException, IOException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, SQLException {
+		super("Authentication");
+		UserSettings.setupDefaultFolders();
+			
+		// initialise keystore and actions
+		loadKeystore();
+		Actions.LoadMethods(org.expeditee.auth.Actions.class);
+		Actions.LoadMethods(org.expeditee.auth.sharing.Actions.class);
+
+		// Does the account Authentication.ADMINACCOUNT exist?
+		// If not then we have get the user to assign a password to it.
+		if (!keyStore.containsAlias(AuthenticatorBrowser.ADMINACCOUNT)) {
+			new File(FrameIO.PARENT_FOLDER).mkdirs();
+			protectAdmin();
+		}
+		
+		// draw the window
+		GraphicsManager g = EcosystemManager.getGraphicsManager();
+		g.setWindowLocation(new Point(50, 50));
+		DisplayController.Init();
+		g.setWindowSize(new Dimension(UserSettings.InitialWidth.get(), UserSettings.InitialHeight.get()));
+		setInputManagerWindowRoutines();
+		
+		// Load documentation and start pages
+		FrameUtils.extractResources(false);
+
+		// Load fonts before loading any frames so the items on the frames will be able to access their fonts
+		Text.InitFonts();
+		
+		// initialing settings does not require a user profile established
+		Settings.Init();
+		
+		// navigate to authentication frame
+		Frame authFrame = FrameIO.LoadFrame("authentication1");
+		DisplayController.setCurrentFrame(authFrame, true);
+		
+		// set initial values
+		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("startinguser.name", "")));
+		passwordItemsStream.forEach(txtPassword -> { txtPassword.setText(""); txtPassword.invalidateAll(); });
+						
+		MessageBay.warningMessages(org.expeditee.actions.Actions.Init());
+		
+		// class load database classes
+		Class.forName("org.sqlite.JDBC");
+	}
+
+	private void protectAdmin() throws KeyStoreException, NoSuchAlgorithmException, CertificateException,
+			FileNotFoundException, IOException {
+		// Fetch desired password
+		Scanner in = new Scanner(System.in);
+		System.out.println("No administrative password set.");
+		boolean passwordIsSet = false;
+		
+		for (int i = 0; i < 3; i++) {
+			System.out.print("Please enter it now: ");
+			System.out.flush();
+			String password = in.nextLine();
+			System.out.print("And again: ");
+			System.out.flush();
+			if (in.nextLine().equals(password)) {
+				// Register account.
+				putKey(ADMINACCOUNT, password, new SecretKeySpec("null".getBytes(), AsymmetricAlgorithm));
+				in.close();
+				passwordIsSet = true;
+				break;
+			} else {
+				System.out.println("Mismatched passwords, let's try that again.");
+			}
+		}
+		
+		if (!passwordIsSet) {
+			System.out.println("Failed to set an admin password.  Exiting Expeditee.");
+			System.exit(1);
+		}
+	}
+		
+	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 loadMailFromFile(Path dbFile) throws SQLException {
+		// Load in all mail.
+		Connection c = DriverManager.getConnection("jdbc:sqlite:" + dbFile.toAbsolutePath().toString());
+		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 = allMail.getString("optsval").split(",");
+			optsVal[0] = optsVal[0].replace("[", "");
+			optsVal[optsVal.length - 1] = optsVal[optsVal.length - 1].replace("]", "");
+			
+			Map<String, String> options = new HashMap<String, String>();
+			for (int i = 0, o = 0; i < opts.length && o < optsVal.length; i++, o++) {
+				String key = opts[i].trim();
+				String val = optsVal[o].trim();
+				options.put(key, val);
+			}
+			
+			Mail.addEntry(new Mail.MailEntry(timestamp, from, to, msg, msg2, options));
+		}
+		
+		// Disconnect from database.
+		allMail.close();
+		query.close();
+		c.close();
+	}
+	
+	final void loadMailDatabase() throws SQLException, FileNotFoundException, ParseException {
+		Path deadDropPath = Paths.get(FrameIO.DEAD_DROPS_PATH);
+		for (File connectionDir: deadDropPath.toFile().listFiles()) {
+			if (connectionDir.isDirectory()) {
+				Path deaddropforcontactPath = Paths.get(connectionDir.getAbsolutePath());
+				Path dbFile = deaddropforcontactPath.resolve(UserSettings.UserName.get() + ".db");
+				if (dbFile.toFile().exists()) {
+					loadMailFromFile(dbFile);
+				}
+				clearOldMailFromDatabase(deaddropforcontactPath);
+			}
+		}
+	}
+
+	final void updateLastReadMailTime(Path deaddropforcontactPath) {
+		Path timestamp = deaddropforcontactPath.resolve(UserSettings.UserName.get() + ".last-accessed");
+		try(FileWriter out = new FileWriter(timestamp.toFile())) {
+			out.write(Formatter.getDateTime() + System.getProperty("line.separator"));
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+	
+	private void clearOldMailFromDatabase(Path directory) throws FileNotFoundException, ParseException, SQLException {
+		File[] files = directory.toFile().listFiles(new FileFilter() {
+			@Override
+			public boolean accept(File file) {
+				return !file.getName().startsWith(UserSettings.UserName.get());
+			}
+		});
+		
+		File dbFile = null;
+		File lastAccessedFile = null;
+		for (File file: files) {
+			if (file.getName().endsWith(".db")) {
+				dbFile = file;
+			} else {
+				lastAccessedFile = file;
+			}
+		}
+		
+		if (dbFile == null || lastAccessedFile == null) {
+			return; // Not the end of the world if we cannot clear out old messages, these files may not be present yet if the others are recently new.
+		}
+		
+		SimpleDateFormat format = new SimpleDateFormat("ddMMMyyyy[HH:mm]");
+		Date timestamp = null;
+		try(Scanner in = new Scanner(lastAccessedFile)) {
+			timestamp = format.parse(in.nextLine());
+		} catch (ParseException e) {
+			return; // Not the end of the world if we cannot clear out old messages, the database might be empty.
+		}
+		
+		Connection c = DriverManager.getConnection("jdbc:sqlite:" + dbFile.getAbsolutePath());
+		String sql = "SELECT * FROM EXPMAIL";
+		PreparedStatement query = c.prepareStatement(sql);
+		ResultSet allMail = query.executeQuery();
+		Set<String> oldTimestamps = new HashSet<String>();
+		
+		while (allMail.next()) {
+			String time = allMail.getString("time");
+			Date messageTimestamp = format.parse(time);
+			if (timestamp.after(messageTimestamp)) {
+				oldTimestamps.add(time);
+			}
+		}
+		
+		if (oldTimestamps.isEmpty()) {
+			return;
+		}
+		
+		for(String oldTimestamp: oldTimestamps) {
+			System.out.println("Deleting message with timestamp: " + oldTimestamp);
+			sql = "DELETE FROM EXPMAIL WHERE time='" + oldTimestamp + "'";
+			query = c.prepareStatement(sql);
+			query.executeUpdate();
+		}		
+	}
+	 
+	final SecretKey getSecretKey(final String label, final String password) throws NoSuchAlgorithmException, KeyStoreException {	
+		
+		char[] password_ca = password.toCharArray();
+		
+		SecretKey secret_key;
+		try {
+			secret_key = (SecretKey) keyStore.getKey(label, password_ca);			
+		} catch (final UnrecoverableEntryException e) {
+			return null;
+		}
+		
+		return secret_key;
+	}
+	
+	final void putKey(final String label, final String password, final SecretKey key) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
+		final KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(key);
+		final KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(password.toCharArray());
+		keyStore.setEntry(label, entry, entryPassword);
+		keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
+	}
+	
+	final boolean confirmIntergalaticNumber(final String username, final String email, final String intergalacticNumber) throws NoSuchAlgorithmException, KeyStoreException, CertificateException, FileNotFoundException, IOException {
+		try {
+			final KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(intergalacticNumber.toCharArray());
+			final KeyStore.SecretKeyEntry entry = (SecretKeyEntry) keyStore.getEntry(email + username, entryPassword);
+			if (entry == null) { 
+				return false;
+			} else if (entry.getSecretKey().getEncoded() == TRUE) {
+				keyStore.deleteEntry(email + username);
+				keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
+				return true;
+			} else { return false; }
+		} catch (final UnrecoverableEntryException e) {
+			return false;
+		}
+	}
+	
+	final String newIntergalacticNumber(final String username, final String email) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
+		// generate intergalactic number
+		final SecureRandom rand = new SecureRandom();
+		final byte[] intergalacticNumberBytes = new byte[20];
+		rand.nextBytes(intergalacticNumberBytes);
+		final String intergalacticNumber = Base64.getEncoder().encodeToString(intergalacticNumberBytes);
+		
+		// store intergalactic number
+		final KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(new SecretKeySpec(TRUE, SymmetricAlgorithm));
+		final KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(intergalacticNumber.toCharArray());
+		keyStore.setEntry(email + username, entry, entryPassword);
+		keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
+		
+		return intergalacticNumber;
+	}
+	
+	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;
+		}
+		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));
+	}
+	
+	final void markRequestedColleagues(String username) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
+		KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(new SecretKeySpec(TRUE, SymmetricAlgorithm));
+		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), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
+	}
+	
+	final void clearRequestedColleagues(String username) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
+		KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(new SecretKeySpec(FALSE, SymmetricAlgorithm));
+		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), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
+	}
+	
+	final boolean hasRequestedColleagues(String username) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException {
+		String alias = username + "colleaguesRequested";
+		if (!keyStore.containsAlias(alias)) {
+			return false;
+		} else {
+			KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
+			KeyStore.SecretKeyEntry entry = (SecretKeyEntry) keyStore.getEntry(alias, entryPassword);
+			return Arrays.equals(entry.getSecretKey().getEncoded(), TRUE);
+		}
+	}
+	
+//	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()	{
+		InputManager manager = EcosystemManager.getInputManager();
+		
+	    // Refresh the layout when the window resizes
+		manager.addWindowEventListener(new WindowEventListener() {
+			@Override
+			public void onWindowEvent(WindowEventType type)
+			{
+				if (type != WindowEventType.WINDOW_RESIZED) {
+					return;
+				}
+				DisplayController.refreshWindowSize();
+				FrameIO.RefreshCacheImages();
+				for (Frame frame : DisplayController.getFrames()) {
+					if (frame != null) {
+						ItemUtils.Justify(frame);
+						frame.refreshSize();
+					}
+				}
+				DisplayController.requestRefresh(false);
+			}
+		});
+		
+		manager.addWindowEventListener(new WindowEventListener() {
+			@Override
+			public void onWindowEvent(WindowEventType type)
+			{
+				if (type != WindowEventType.MOUSE_EXITED_WINDOW) {
+					return;
+				}
+				StandardGestureActions.mouseExitedWindow();
+			}
+		});
+		
+		manager.addWindowEventListener(new WindowEventListener() {
+			@Override
+			public void onWindowEvent(WindowEventType type)
+			{
+				if (type != WindowEventType.MOUSE_ENTERED_WINDOW) {
+					return;
+				}
+				StandardGestureActions.mouseEnteredWindow();
+			}
+		});
+		
+		manager.addWindowEventListener(new WindowEventListener() {
+			@Override
+			public void onWindowEvent(WindowEventType type)
+			{
+				if (type != WindowEventType.WINDOW_CLOSED) {
+					return;
+				}
+				if (Browser._theBrowser != null) {
+					Browser._theBrowser.exit();
+				}
+			}
+		});
+	}
+}
Index: /trunk/src/org/expeditee/gui/Browser.java
===================================================================
--- /trunk/src/org/expeditee/gui/Browser.java	(revision 1281)
+++ /trunk/src/org/expeditee/gui/Browser.java	(revision 1282)
@@ -32,4 +32,5 @@
 import org.expeditee.actions.Simple;
 import org.expeditee.agents.mail.MailSession;
+import org.expeditee.auth.AuthenticatorBrowser;
 import org.expeditee.core.BlockingRunnable;
 import org.expeditee.core.Colour;
@@ -204,15 +205,15 @@
 		if (Boolean.getBoolean("auth")) {
 			try {
-				org.expeditee.auth.Authenticator.getInstance();
-				_initComplete = true;
-				return;
+				_theBrowser = AuthenticatorBrowser.getInstance();
 			} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException | ClassNotFoundException | SQLException e) {
 				e.printStackTrace();
 			}
-		}
-		_theBrowser = new Browser();
+		} else {
+			_theBrowser = new Browser();
+		}		
 
 		EcosystemManager.getGraphicsManager().requestFocus();
 		
+		// Java's way of getting access to internet.  Authenticating the user with their proxy username and password.
 		Authenticator.setDefault(proxyAuth);
 		
