Changeset 1243 for trunk/src/org/expeditee/auth/Actions.java
- Timestamp:
- 03/15/19 16:51:32 (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/expeditee/auth/Actions.java
r1231 r1243 1 1 package org.expeditee.auth; 2 2 3 import java.io.File; 3 4 import java.io.FileNotFoundException; 5 import java.io.FileWriter; 4 6 import java.io.IOException; 7 import java.nio.file.Files; 8 import java.nio.file.Path; 9 import java.nio.file.Paths; 10 import java.nio.file.StandardCopyOption; 11 import java.security.InvalidKeyException; 5 12 import java.security.KeyFactory; 6 13 import java.security.KeyPair; … … 10 17 import java.security.PrivateKey; 11 18 import java.security.PublicKey; 12 import java.security.UnrecoverableEntryException;13 19 import java.security.cert.CertificateException; 14 20 import java.security.spec.InvalidKeySpecException; 15 21 import java.security.spec.PKCS8EncodedKeySpec; 22 import java.sql.Connection; 23 import java.sql.DriverManager; 16 24 import java.sql.SQLException; 25 import java.sql.Statement; 17 26 import java.util.Base64; 18 27 import java.util.Collection; … … 22 31 import java.util.Optional; 23 32 import java.util.Random; 24 33 import java.util.stream.Collectors; 34 35 import javax.crypto.BadPaddingException; 36 import javax.crypto.IllegalBlockSizeException; 37 import javax.crypto.NoSuchPaddingException; 25 38 import javax.crypto.SecretKey; 26 39 import javax.crypto.spec.SecretKeySpec; 27 40 41 import org.expeditee.agents.ExistingFramesetException; 42 import org.expeditee.agents.InvalidFramesetNameException; 28 43 import org.expeditee.auth.Mail.MailEntry; 29 44 import org.expeditee.auth.gui.MailBay; 45 import org.expeditee.auth.tags.AuthenticationTag; 46 import org.expeditee.auth.tags.Constants; 30 47 import org.expeditee.core.Colour; 31 48 import org.expeditee.gui.DisplayController; … … 34 51 import org.expeditee.gui.MessageBay; 35 52 import org.expeditee.items.Item; 53 import org.expeditee.items.PermissionPair; 36 54 import org.expeditee.items.Text; 55 import org.expeditee.items.UserAppliedPermission; 56 import org.expeditee.setting.GenericSetting; 57 import org.expeditee.setting.Setting; 58 import org.expeditee.setting.TextSetting; 59 import org.expeditee.settings.Settings; 37 60 import org.expeditee.settings.UserSettings; 61 import org.expeditee.settings.folders.FolderSettings; 62 import org.expeditee.settings.identity.secrets.KeyList; 38 63 import org.ngikm.cryptography.CryptographyConstants; 39 64 40 65 public class Actions implements CryptographyConstants { 66 67 public static void SendTestMessage(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException, FileNotFoundException, KeyStoreException, CertificateException, ClassNotFoundException, IOException, SQLException { 68 String time = org.expeditee.stats.Formatter.getDateTime(); 69 String sender = UserSettings.UserName.get(); 70 String topic = "Test Message"; 71 String message = "This is a test message."; 72 Map<String, String> options = new HashMap<String, String>(); 73 options.put("Neat", "Beep"); 74 MailEntry mail = new MailEntry(time, sender, colleagueName, topic, message, options); 75 PublicKey publicKey = Authenticator.getInstance().getPublicKey(colleagueName); 76 Path outbox = Paths.get(FrameIO.PROFILE_PATH).resolve(sender).resolve(sender + "-credentials"); 77 Mail.sendMail(mail, publicKey, outbox); 78 } 41 79 42 80 /** … … 66 104 67 105 /** 68 * Log out of current user and navigate to authentication169 */70 public static void AuthLogout() {71 UserSettings.Authenticated.set(false);72 setUser(System.getProperty("user.name"));73 DisplayController.setCurrentFrame(FrameIO.LoadFrame("authentication1"), true);74 }75 76 /**77 106 * Action used to created a new user account. 78 107 * Attempts to use content from text items on frame, will default to java properties if they cannot be found. 79 108 * Will fail if it cannot find content from text items on frame and all required java properties are not present. 109 * @throws SQLException 110 * @throws IOException 111 * @throws ExistingFramesetException 112 * @throws InvalidFramesetNameException 113 * @throws ClassNotFoundException 114 * @throws FileNotFoundException 115 * @throws CertificateException 116 * @throws NoSuchAlgorithmException 117 * @throws KeyStoreException 118 * @throws BadPaddingException 119 * @throws IllegalBlockSizeException 120 * @throws NoSuchPaddingException 121 * @throws InvalidKeySpecException 122 * @throws InvalidKeyException 80 123 * @throws Exception 81 124 */ 82 public static void AuthCreateAccount() throws Exception { 83 final Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems(); 84 final Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Username, AuthenticationTag.Password, AuthenticationTag.PasswordAgain); 85 if (userdata.isPresent()) { 86 final Map<AuthenticationTag, String> userData = userdata.get(); 87 final String password = userData.get(AuthenticationTag.Password); 88 final String passwordAgain = userData.get(AuthenticationTag.PasswordAgain); 89 if (password.compareTo(passwordAgain) == 0) { 90 createAccount(userData); 91 } else { 92 MessageBay.errorMessage("The passwords provided do not match."); 93 } 125 public static void AuthCreateAccount() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, ClassNotFoundException, InvalidFramesetNameException, ExistingFramesetException, IOException, SQLException, InvalidKeyException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException { 126 Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems(); 127 Optional<Map<AuthenticationTag, String>> userdata = 128 AuthenticationTag.fetchUserData(textItems, false, 129 AuthenticationTag.Username, 130 AuthenticationTag.Password, 131 AuthenticationTag.PasswordAgain, 132 AuthenticationTag.Email, 133 AuthenticationTag.EmailAgain); 134 135 if (userdata.isPresent()) { 136 Map<AuthenticationTag, String> userData = userdata.get(); 137 138 // A profile already existing with 'username' means an account cannot be created with that username. 139 if (FrameIO.LoadProfile(userData.get(AuthenticationTag.Username)) != null) { 140 MessageBay.errorMessage(Constants.ERROR_PROFILE_NAME_PREEXISTS); 141 return; 142 } 143 144 // The chosen username must be a valid frameset name. 145 if (!FrameIO.isValidFramesetName(userData.get(AuthenticationTag.Username))) { 146 MessageBay.errorMessage(Constants.ERROR_INVALID_USERNAME); 147 return; 148 } 149 150 // The passwords provided must match 151 if (userData.get(AuthenticationTag.Password).compareTo(userData.get(AuthenticationTag.PasswordAgain)) != 0) { 152 MessageBay.errorMessage(Constants.ERROR_MISMATCH_PASSWORDS); 153 return; 154 } 155 156 // The emails provided must match 157 if (userData.get(AuthenticationTag.Email).compareTo(userData.get(AuthenticationTag.EmailAgain)) != 0) { 158 MessageBay.errorMessage(Constants.ERROR_MISMATCH_EMAILS); 159 return; 160 } 161 162 createAccount(userData); 163 login(userData); 164 Authenticator.Authenticated = true; 94 165 } else { 95 MessageBay.errorMessage( "Please enter a username and password ( + repeated password) to create an account.");166 MessageBay.errorMessage(Constants.ERROR_INSUFFICIENT_INFORMATION_PROVIDED); 96 167 } 97 168 } … … 108 179 if (userdata.isPresent()) { 109 180 login(userdata.get()); 181 Authenticator.Authenticated = true; 110 182 } 111 183 else { 112 MessageBay.errorMessage( "Please enter a username and password to log in.");184 MessageBay.errorMessage(Constants.ERROR_INSUFFICIENT_INFORMATION_PROVIDED); 113 185 } 114 186 } … … 130 202 final Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems(); 131 203 132 if (! UserSettings.Authenticated.get()) {133 MessageBay.errorMessage( "You must be logged in to change your password.");204 if (!Authenticator.Authenticated) { 205 MessageBay.errorMessage(Constants.ERROR_MUST_BE_LOGGED_IN); 134 206 } else { 135 207 final Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Password, AuthenticationTag.NewPassword, AuthenticationTag.NewPasswordAgain); … … 137 209 final Map<AuthenticationTag, String> userData = userdata.get(); 138 210 if (userData.get(AuthenticationTag.NewPassword).compareTo(userData.get(AuthenticationTag.NewPasswordAgain)) != 0) { 139 MessageBay.errorMessage( "The passwords provided do not match.");211 MessageBay.errorMessage(Constants.ERROR_MISMATCH_PASSWORDS); 140 212 } else { 141 213 userData.put(AuthenticationTag.Username, UserSettings.UserName.get()); … … 143 215 } 144 216 } else { 145 MessageBay.errorMessage("Insufficient information provided to complete this action."); 146 } 147 } 148 } 149 150 /** 151 * Part of the process to secure an authorised account, the AuthAssociateEmail action associates a supplied email 152 * with the currently logged in user. 153 */ 154 public static void AuthAssociateEmail() { 217 MessageBay.errorMessage(Constants.ERROR_INSUFFICIENT_INFORMATION_PROVIDED); 218 } 219 } 220 } 221 222 public static void AuthGotoAccountManagement() { 223 if (Authenticator.Authenticated) { 224 DisplayController.setCurrentFrame(FrameIO.LoadFrame(Constants.FRAME_MULTIUSER1), false); 225 } else { 226 DisplayController.setCurrentFrame(FrameIO.LoadFrame(Constants.FRAME_AUTHENTICATION1), false); 227 } 228 } 229 230 public static void AuthShareFrameset() throws IOException { 155 231 Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems(); 156 232 157 if (!UserSettings.Authenticated.get()) { 158 MessageBay.errorMessage("You must be logged in to perform this action."); 159 } else { 160 Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Email); 161 if (userdata.isPresent()) { 162 Map<AuthenticationTag, String> userData = userdata.get(); 163 userData.put(AuthenticationTag.Username, UserSettings.UserName.get()); 164 String emailRegex = "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}$"; 165 if (!userData.get(AuthenticationTag.Email).toUpperCase().matches(emailRegex)) { 166 MessageBay.errorMessage("Invalid email address supplied."); 167 } else { 168 try { 169 associateEmail(userData); 170 DisplayController.setCurrentFrame(FrameIO.LoadFrame("authentication5"), true); 171 } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | ClassNotFoundException | IOException | SQLException e) { 172 MessageBay.errorMessage("An unknown error has occured. Details sent to standard error."); 173 e.printStackTrace(); 174 } 175 } 176 } else { 177 MessageBay.errorMessage("Insufficient information provided to complete this action."); 178 } 179 } 180 } 181 233 Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Frameset); 234 if (userdata.isPresent()) { 235 Map<AuthenticationTag, String> userData = userdata.get(); 236 FrameIO.SuspendCache(); 237 Frame toShare = FrameIO.LoadFrame(userData.get(AuthenticationTag.Frameset) + 1); 238 FrameIO.ResumeCache(); 239 240 if (toShare == null) { 241 MessageBay.errorMessage(Constants.ERROR_INSUFFICIENT_INFORMATION); 242 return; 243 } 244 245 shareFrameset(toShare); 246 } 247 } 248 182 249 /** 183 250 * Navigation action for progressing the process of recruiting colleagues to assist in password recovery. … … 185 252 */ 186 253 public static void AuthGotoColleagueSubmissionFrame() { 187 Frame destination = FrameIO.LoadFrame( "authentication7");254 Frame destination = FrameIO.LoadFrame(Constants.FRAME_COLLEAGUE_SUBMISSION_FRAME); 188 255 DisplayController.setCurrentFrame(destination, true); 189 Collection<Item> toHide = getByData(destination, "ShowOnProgress");256 Collection<Item> toHide = getByData(destination, Constants.DATA_SHOW_ON_PROGRESS); 190 257 for (Item i: toHide) { 191 258 i.setVisible(false); … … 204 271 * @throws InvalidKeySpecException 205 272 */ 206 public static void AuthSubmitPWColleagues() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, IOException, SQLException, InvalidKeySpecException {207 finalFrame currentFrame = DisplayController.getCurrentFrame();273 public static void AuthSubmitPWColleagues() throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException { 274 Frame currentFrame = DisplayController.getCurrentFrame(); 208 275 Collection<Text> textItems = currentFrame.getTextItems(); 209 276 210 if (!UserSettings.Authenticated.get()) { 211 MessageBay.errorMessage("You must be logged in to perform this action."); 212 } else { 213 Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.ColleagueOne, AuthenticationTag.ColleagueTwo); 214 if (userdata.isPresent()) { 215 Map<AuthenticationTag, String> userData = userdata.get(); 277 if (!Authenticator.Authenticated) { 278 MessageBay.errorMessage(Constants.ERROR_MUST_BE_LOGGED_IN); 279 return; 280 } 281 282 Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.ColleagueOne, AuthenticationTag.ColleagueTwo); 283 if (userdata.isPresent()) { 284 Map<AuthenticationTag, String> userData = userdata.get(); 285 String colleagueOne = userData.get(AuthenticationTag.ColleagueOne); 286 Path colleagueOnePath = Paths.get(FrameIO.CONTACTS_PATH).resolve(colleagueOne + "-credentials"); 287 String colleagueTwo = userData.get(AuthenticationTag.ColleagueTwo); 288 Path colleagueTwoPath = Paths.get(FrameIO.CONTACTS_PATH).resolve(colleagueTwo + "-credentials"); 289 if (!colleagueOnePath.toFile().exists()) { 290 MessageBay.errorMessage("Your nominated colleague: " + colleagueOne + " must exist in your contacts."); 291 } else if (!colleagueTwoPath.toFile().exists()) { 292 MessageBay.errorMessage("Your nominated colleague: " + colleagueTwo + " must exist in your contacts."); 293 } else { 216 294 userData.put(AuthenticationTag.Username, UserSettings.UserName.get()); 217 boolean succ sess = submitPWColleagues(userData);218 if (succ sess) {219 Collection<Item> toShow = getByData(currentFrame, "ShowOnProgress");295 boolean success = submitPWColleagues(userData); 296 if (success) { 297 Collection<Item> toShow = getByData(currentFrame, Constants.DATA_SHOW_ON_PROGRESS); 220 298 for (Item i: toShow) { 221 299 i.setVisible(true); 222 300 } 223 301 currentFrame.change(); 302 MessageBay.displayMessage("-------Messages sent-------"); 224 303 } 225 304 FrameIO.SaveFrame(currentFrame); 226 305 DisplayController.requestRefresh(false); 227 } else { 228 MessageBay.errorMessage("Insufficient information provided to complete this action."); 229 } 230 } 231 } 232 233 public static void AuthSetupPasswordRecovery() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, IOException, SQLException, UnrecoverableEntryException { 234 if (!UserSettings.Authenticated.get()) { 235 MessageBay.errorMessage("You must be logged in to perform this action."); 236 } else if (!Authenticator.getInstance().hasRegisteredEmail(UserSettings.UserName.get())) { 237 Frame registerEmailFrame = FrameIO.LoadFrame("authentication4"); 238 DisplayController.setCurrentFrame(registerEmailFrame, true); 239 } else if (!Authenticator.getInstance().hasRequestedColleagues(UserSettings.UserName.get()) && Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) == null) { 240 Frame submitColleaguesFrame = FrameIO.LoadFrame("authentication5"); 241 DisplayController.setCurrentFrame(submitColleaguesFrame, true); 242 } else if (Authenticator.getInstance().hasRequestedColleagues(UserSettings.UserName.get()) && Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) == null) { 243 MessageBay.displayMessage("You have already nominated two colleagues to assist you in the process of password recovery and are awaiting their response." 244 + " You will be alerted on Expeditee startup when they have both responded."); 245 } else if (Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) != null) { 246 MessageBay.displayMessage("You have completed the Password Recovery Setup process, there is nothing more to do here."); 247 } 248 } 306 } 307 } 308 } 309 310 // public static void AuthSetupPasswordRecovery() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, IOException, SQLException, UnrecoverableEntryException { 311 // if (!UserSettings.Authenticated.get()) { 312 // MessageBay.errorMessage("You must be logged in to perform this action."); 313 // } else if (!Authenticator.getInstance().hasRegisteredEmail(UserSettings.UserName.get())) { 314 // Frame registerEmailFrame = FrameIO.LoadFrame("authentication4"); 315 // DisplayController.setCurrentFrame(registerEmailFrame, true); 316 // } else if (!Authenticator.getInstance().hasRequestedColleagues(UserSettings.UserName.get()) && Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) == null) { 317 // Frame submitColleaguesFrame = FrameIO.LoadFrame("authentication5"); 318 // DisplayController.setCurrentFrame(submitColleaguesFrame, true); 319 // } else if (Authenticator.getInstance().hasRequestedColleagues(UserSettings.UserName.get()) && Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) == null) { 320 // MessageBay.displayMessage("You have already nominated two colleagues to assist you in the process of password recovery and are awaiting their response." 321 // + " You will be alerted on Expeditee startup when they have both responded."); 322 // } else if (Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) != null) { 323 // MessageBay.displayMessage("You have completed the Password Recovery Setup process, there is nothing more to do here."); 324 // } 325 // } 249 326 250 327 public static void AuthConfirmPasswordColleagueRelationship(String colleagueName) { … … 252 329 } 253 330 254 public static void AuthDenyPasswordColleagueRelationship(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException { 331 public static void AuthDenyPasswordColleagueRelationship(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException, 332 KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException { 255 333 denyPasswordColleagueRelationship(colleagueName); 256 334 } … … 260 338 } 261 339 340 /** 341 * Create a user account using the specified information in userdata. Creates and stores user keys. 342 * @param userdata Should contain username, password and email. 343 */ 344 private static void createAccount(Map<AuthenticationTag, String> userdata) throws InvalidFramesetNameException, ExistingFramesetException, 345 KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, ClassNotFoundException, IOException, SQLException { 346 347 // Track progress 348 String message = "Creating new user account..."; 349 //Progress progress = MessageBay.displayProgress(message); 350 351 // Extract user details 352 String username = userdata.get(AuthenticationTag.Username); 353 String password = userdata.get(AuthenticationTag.Password); 354 String email = userdata.get(AuthenticationTag.Email); 355 356 System.out.println(message + "Generating Keys."); 357 358 // Generate keys 359 // Personal key 360 Random rand = new Random(); 361 byte[] keyBytes = new byte[16]; 362 rand.nextBytes(keyBytes); 363 SecretKey key = new SecretKeySpec(keyBytes, SymmetricAlgorithm); 364 Authenticator.getInstance().putKey(username, password, key); 365 String personalKey = Base64.getEncoder().encodeToString(key.getEncoded()); 366 // Public and private keys 367 KeyPairGenerator keyGen = KeyPairGenerator.getInstance(AsymmetricAlgorithm); 368 keyGen.initialize(1024); 369 KeyPair keyPair = keyGen.generateKeyPair(); 370 String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded()); 371 String privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded()); 372 373 System.out.println(message + "Creating Profile Frameset."); 374 375 // Update in memory settings 376 UserSettings.UserName.set(username); 377 UserSettings.ProfileName.set(username); 378 UserSettings.setupDefaultFolders(); 379 380 // Establish the initial settings for the created user. 381 Map<String, Setting> initialSettings = new HashMap<String, Setting>(); 382 initialSettings.put(Constants.SETTINGS_AUTH_SECRETS_PERSONAL_KEY, constructTextSetting(Constants.TOOLTIP_SETTING_PERSONAL_KEY, "PersonalKey", personalKey)); 383 initialSettings.put(Constants.SETTINGS_AUTH_SECRETS_PRIVATE_KEY, constructTextSetting(Constants.TOOLTIP_SETTING_PRIVATE_KEY, "PrivateKey", privateKey)); 384 initialSettings.put(Constants.SETTINGS_AUTH_PUBLIC_KEY, constructTextSetting(Constants.TOOLTIP_SETTING_PUBLIC_KEY, "PublicKey", publicKey)); 385 initialSettings.put(Constants.SETTINGS_AUTH_EMAIL, constructGenericSetting(String.class, Constants.TOOLTIP_SETTING_EMAIL, "Email", email, username)); 386 initialSettings.put(Constants.SETTINGS_USER_SETTINGS_USER_NAME, constructGenericSetting(String.class, Constants.LABEL_USERNAME, Constants.LABEL_USERNAME, username, username)); 387 initialSettings.put(Constants.SETTINGS_USER_SETTINGS_PROFILE_NAME, constructGenericSetting(String.class, Constants.LABEL_PROFILENAME, Constants.LABEL_PROFILENAME, username, username)); 388 initialSettings.put("org.expeditee.gui.folders.FolderSettings.FrameDirs", FolderSettings.FrameDirs); 389 initialSettings.put("org.expeditee.gui.folders.FolderSettings.ImageDirs", FolderSettings.ImageDirs); 390 391 // Create users profile 392 Frame profile = FrameIO.CreateNewProfile(username, initialSettings); 393 int lastNumber = FrameIO.getLastNumber(profile.getFramesetName()); 394 for (int i = 1; i <= lastNumber; i++) { 395 Frame f = FrameIO.LoadFrame(profile.getFramesetName() + i); 396 Text titleItem = f.getTitleItem(); 397 if (i == 1 && titleItem != null) { 398 titleItem.delete(); 399 f.setBackgroundColor(new Colour(1, 1, 0.39f)); 400 } 401 f.setOwner(username); 402 f.getAllItems().stream().forEach(item -> item.setOwner(username)); 403 f.setChanged(true); 404 f.setEncryptionLabel("Profile"); 405 Collection<Item> secretsLink = getByContent(f, "Secrets"); 406 Collection<Item> publicKeyItem = getByContent(f, "PublicKey"); 407 if (!secretsLink.isEmpty() && !publicKeyItem.isEmpty()) { 408 //Then we are on credentials frame 409 secretsLink.forEach(text -> text.setPermission(new PermissionPair(UserAppliedPermission.full, UserAppliedPermission.none))); 410 f.addToData("MultiuserCredentials"); 411 } 412 Text backupPersonalKey = KeyList.PersonalKey.get(); 413 Text tempPersonalKey = KeyList.PersonalKey.generateText(); 414 tempPersonalKey.setData(personalKey); 415 KeyList.PersonalKey.setSetting(tempPersonalKey); 416 FrameIO.SaveFrame(f); 417 KeyList.PersonalKey.setSetting(backupPersonalKey); 418 } 419 420 // Create credentials 421 File credentialsDir = new File(profile.getFramesetPath() + username + "-credentials"); 422 credentialsDir.mkdir(); 423 // credentials.inf file. 424 String credentialsPath = credentialsDir.getAbsolutePath() + File.separator + "credentials.inf"; 425 File credentialsFile = new File(credentialsPath); 426 credentialsFile.createNewFile(); 427 FileWriter out = new FileWriter(credentialsFile); 428 out.write(Authenticator.CREDENTIALS_FRAME + ".exp"); 429 out.flush(); 430 out.close(); 431 // outbox 432 Connection c = DriverManager.getConnection("jdbc:sqlite:" + credentialsDir.getAbsolutePath() + File.separator + "expmail.db"); 433 Statement createTable = c.createStatement(); 434 String sql = "CREATE TABLE EXPMAIL (" + 435 "TIME TEXT NOT NULL, " + 436 "SND TEXT NOT NULL, " + 437 "REC TEXT NOT NULL, " + 438 "MSG TEXT NOT NULL, " + 439 "MSG2 TEXT NOT NULL, " + 440 "OPTS ARRAY NOT NULL, " + 441 "OPTSVAL ARRAY NOT NULL)"; 442 createTable.executeUpdate(sql); 443 createTable.close(); 444 c.close(); 445 446 System.out.println(message + "Creating Individual Space."); 447 448 // Copy private resources to personal area 449 Path personalResources = Paths.get(FrameIO.PARENT_FOLDER).resolve("resources-" + username); 450 personalResources.toFile().mkdir(); 451 File[] globalResourcesToCopy = Paths.get(FrameIO.RESOURCES_PRIVATE).toFile().listFiles(); 452 for (File toCopy: globalResourcesToCopy) { 453 Path p = Paths.get(toCopy.getAbsolutePath()); 454 if (!p.getFileName().toString().equals(".res") && !p.getFileName().toString().equals("about")) { 455 copyFileTree(p.toAbsolutePath(), personalResources.resolve(p.getFileName())); 456 } 457 } 458 File contactsDir = new File(personalResources.resolve("contacts").toAbsolutePath().toString()); 459 contactsDir.mkdir(); 460 461 System.out.println(message + "Done."); 462 } 463 464 private static void copyFileTree(Path source, Path target) throws IOException { 465 Files.copy(source, target); 466 if (source.toFile().isDirectory()) { 467 File[] files = source.toFile().listFiles(); 468 for (File file: files) { 469 Path asPath = Paths.get(file.getAbsolutePath()); 470 copyFileTree(asPath, target.resolve(asPath.getFileName())); 471 } 472 } 473 } 474 475 /* 476 * Function used to authenticate as a specified user (via function arguments). 477 */ 478 private static void login(Map<AuthenticationTag, String> userdata) throws NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException, InvalidKeySpecException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException { 479 String username = userdata.get(AuthenticationTag.Username); 480 String password = userdata.get(AuthenticationTag.Password); 481 482 SecretKey personalKey = Authenticator.getInstance().getSecretKey(username, password); 483 if (personalKey == null) { 484 // Incorrect username and password 485 MessageBay.errorMessage("The username + password combination was incorrect."); 486 return; 487 } 488 489 // Load in and cache the profile frame using the personal key fetched from keystore. 490 // Reset the personal key once finished so that setting parsing can correctly set it. 491 FrameIO.ClearCache(); 492 Text personalKeyText = KeyList.PersonalKey.generateText(); 493 personalKeyText.setData(Base64.getEncoder().encodeToString(personalKey.getEncoded())); 494 KeyList.PersonalKey.setSetting(personalKeyText); 495 Frame oneFrame = FrameIO.LoadProfile(username); 496 for (int i = 1; i <= FrameIO.getLastNumber(username); i++) { 497 Frame f = FrameIO.LoadFrame(oneFrame.getFramesetName() + i); 498 if (f.getData() != null && f.getData().contains("MultiuserCredentials")) { 499 Authenticator.CREDENTIALS_FRAME = f.getNumber(); 500 } 501 } 502 503 // Parse the settings frame to update the settings datastructure. 504 Text fakeLink = new Text("settings"); 505 fakeLink.setLink(oneFrame.getFramesetName() + "2"); 506 Settings.parseSettings(fakeLink); 507 508 // Update default folders. 509 UserSettings.setupDefaultFolders(); 510 511 // Check mail 512 MailBay.clear(); 513 Authenticator.getInstance().loadMailDatabase(); 514 Text keyItem = org.expeditee.settings.identity.secrets.KeyList.PrivateKey.get(); 515 if (keyItem.getData() != null) { 516 String keyEncoded = keyItem.getData().get(0); 517 byte[] keyBytes = Base64.getDecoder().decode(keyEncoded); 518 PrivateKey key = KeyFactory.getInstance(AsymmetricAlgorithm).generatePrivate(new PKCS8EncodedKeySpec(keyBytes)); 519 List<MailEntry> mailForLoggingInUser = Mail.getEntries(UserSettings.UserName.get(), key); 520 for (MailEntry mail: mailForLoggingInUser) { 521 MailBay.addMessage(mail.timestamp, mail.message, mail.message2, mail.options); 522 } 523 } 524 525 Collection<Item> usernameFields = getByData(FrameIO.LoadFrame(Constants.FRAME_MULTIUSER1), "txtUsername"); 526 usernameFields.forEach(usernameField -> usernameField.setText(username)); 527 528 Frame homeFrame = FrameIO.LoadFrame("home1"); 529 DisplayController.setCurrentFrame(homeFrame == null ? oneFrame : homeFrame, false); 530 } 531 532 /* 533 * Function to share a specified frameset. 534 * 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. 535 */ 536 private static void shareFrameset(Frame toShare) throws IOException { 537 File destinationDir = new File(FrameIO.SHARED_FRAMESETS_PATH + File.separator + toShare.getFramesetName()); 538 File sourceDir = new File(toShare.getFramesetPath()); 539 540 if (destinationDir.exists()) { 541 MessageBay.errorMessage("A frameset by this name already exists."); 542 return; 543 } 544 545 destinationDir.mkdir(); 546 List<Path> files = Files.walk(sourceDir.toPath()).collect(Collectors.toList()); 547 Files.move(files.get(0), destinationDir.toPath(), StandardCopyOption.ATOMIC_MOVE); 548 549 MessageBay.displayMessage("The frameset " + toShare.getFramesetName() + " has been moved to " + destinationDir + ". Google Drive functionality can now be used to share it with colleagues."); 550 } 551 262 552 private static void denyPasswordColleagueRelationship(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException { 553 String time = org.expeditee.stats.Formatter.getDateTime(); 263 554 String sender = UserSettings.UserName.get(); 264 555 String message = "You have received a reply from " + sender + " reguarding your request for assistance."; … … 266 557 Map<String, String> options = new HashMap<String, String>(); 267 558 options.put("Clear Preview Colleague Nominations", "AuthClearPWColleaguesNominated"); 268 MailEntry mail = new MailEntry(sender, colleagueName, message, message2, options); 269 Mail.sendMail(mail, Authenticator.getInstance().getPublicKey(colleagueName)); 270 } 271 272 private static boolean submitPWColleagues(Map<AuthenticationTag, String> userData) throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, IOException, SQLException, InvalidKeySpecException { 273 // Confirm both colleagues exist 559 MailEntry mail = new MailEntry(time, sender, colleagueName, message, message2, options); 560 Mail.sendMail(mail, Authenticator.getInstance().getPublicKey(colleagueName), Paths.get(FrameIO.PROFILE_PATH).resolve(sender).resolve(sender + "-credentials")); 561 } 562 563 private static boolean submitPWColleagues(Map<AuthenticationTag, String> userData) throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException { 274 564 String colleagueOne = userData.get(AuthenticationTag.ColleagueOne); 275 565 String colleagueTwo = userData.get(AuthenticationTag.ColleagueTwo); 276 PublicKey colleagueOneKey = null;277 PublicKey colleagueTwoKey = null;278 if ( !FrameIO.canAccessFrameset(colleagueOne) && FrameIO.canAccessFrameset(colleagueTwo)) {279 MessageBay.errorMessage(" At least one of the colleagues you specified does not have a Expeditee profile.");566 PublicKey colleagueOneKey = Authenticator.getInstance().getPublicKey(colleagueOne); 567 PublicKey colleagueTwoKey = Authenticator.getInstance().getPublicKey(colleagueTwo); 568 if (colleagueOneKey == null) { 569 MessageBay.errorMessage("Unable to get public key for colleague: " + colleagueOne); 280 570 return false; 281 } else if ((colleagueOneKey = Authenticator.getInstance().getPublicKey(colleagueOne)) == null || 282 (colleagueTwoKey = Authenticator.getInstance().getPublicKey(colleagueTwo)) == null) { 283 MessageBay.errorMessage("At least one of the colleagues you specified is not set up to be authorised."); 571 } else if (colleagueTwoKey == null) { 572 MessageBay.errorMessage("Unable to get public key for colleague: " + colleagueTwo); 284 573 return false; 285 574 } else { 286 String sender = UserSettings.UserName.get(); 287 String message = "You have received a request for cooperation from your colleague " + sender; 288 String message2 = "\"I would like to receive your help if I happen to forget my password.\""; 575 String time = org.expeditee.stats.Formatter.getDateTime(); 576 String sender = userData.get(AuthenticationTag.Username); 577 String topic = "You have received a request for cooperation from your colleague " + sender; 578 String message = "Should " + sender + " forget their password, they would like your help recoverying it."; 289 579 Map<String, String> arguments = new HashMap<String, String>(); 290 arguments.put("I Agree To Assist " + sender + " If They Forget Their Password" , "AuthConfirmPasswordColleagueRelationship " + sender); 291 arguments.put("I Wish To Excuse Myself From This Responsibility", "AuthDenyPasswordColleagueRelationship " + sender); 292 MailEntry mail = new MailEntry(sender, colleagueOne, message, message2, arguments); 293 Mail.sendMail(mail, colleagueOneKey); 294 mail = new MailEntry(sender, colleagueTwo, message, message2, arguments); 295 Mail.sendMail(mail, colleagueTwoKey); 580 arguments.put("I agree to assist " + sender + " if they loose access to their account.", "AuthConfirmPasswordColleagueRelationship " + sender); 581 arguments.put("I wish to excuse myself from this responsibility.", "AuthDenyPasswordColleagueRelationship " + sender); 582 MailEntry mail = new MailEntry(time, sender, colleagueOne, topic, message, arguments); 583 Path outbox = Paths.get(FrameIO.PROFILE_PATH).resolve(sender).resolve(sender + "-credentials"); 584 Mail.sendMail(mail, colleagueOneKey, outbox); 585 mail = new MailEntry(time, sender, colleagueTwo, topic, message, arguments); 586 Mail.sendMail(mail, colleagueTwoKey, outbox); 296 587 Authenticator.getInstance().markRequestedColleagues(UserSettings.UserName.get()); 297 588 return true; … … 299 590 } 300 591 301 /* 302 * Function used to authenticate as a specified user (via function arguments). 303 */ 304 private static void login(final Map<AuthenticationTag, String> userdata) throws Exception { 305 final String username = userdata.get(AuthenticationTag.Username); 306 final String password = userdata.get(AuthenticationTag.Password); 307 308 final SecretKey personalKey = Authenticator.getInstance().getSecretKey(username, password); 309 if (personalKey == null) { 310 // Incorrect username and password 311 MessageBay.errorMessage("The username + password combination was incorrect."); 312 } else { 313 // Proceed with login process. 314 org.expeditee.settings.auth.secrets.KeyList.PersonalKey.setSetting(new Text(Base64.getEncoder().encodeToString(personalKey.getEncoded()))); 315 setUser(username); 316 MessageBay.displayMessage("Logged in as: " + UserSettings.UserName.get()); 317 318 // Set Public Key and private key in settings datastructure 319 String profileName = UserSettings.ProfileName.get(); 320 int lastNumber = FrameIO.getLastNumber(profileName); 321 for (int i = 1; i <= lastNumber; i++) { 322 Frame frame = FrameIO.LoadFrame(profileName + i); 323 if (frame == null) { 324 continue; 325 } 326 Collection<Item> items = frame.getAllItems(); 327 boolean foundPublic = false; 328 boolean foundPrivate = false; 329 for (Item item: items) { 330 if (item.getText().compareTo("PublicKey") == 0) { 331 org.expeditee.settings.auth.KeyList.PublicKey.set((Text) item); 332 foundPublic = true; 333 } else if (item.getText().compareTo("PrivateKey") == 0) { 334 org.expeditee.settings.auth.secrets.KeyList.PrivateKey.set((Text) item); 335 foundPrivate = true; 336 } 337 } 338 if (foundPublic && foundPrivate) { break; } 339 } 340 341 // Check mail 342 MailBay.clear(); 343 Authenticator.getInstance().loadMailDatabase(); 344 Text keyItem = org.expeditee.settings.auth.secrets.KeyList.PrivateKey.get(); 345 if (keyItem.getData() != null) { 346 String keyEncoded = keyItem.getData().get(0); 347 byte[] keyBytes = Base64.getDecoder().decode(keyEncoded); 348 PrivateKey key = KeyFactory.getInstance(AsymmetricAlgorithm).generatePrivate(new PKCS8EncodedKeySpec(keyBytes)); 349 List<MailEntry> mailForLoggingInUser = Mail.getEntries(UserSettings.UserName.get(), key); 350 for (MailEntry mail: mailForLoggingInUser) { 351 MailBay.addMessage(mail.message, mail.message2, mail.options); 352 } 353 } 354 355 UserSettings.Authenticated.set(true); 356 // navigate to logged in profile 357 DisplayController.setCurrentFrame(loadProfile(username), false); 358 } 359 } 360 361 /* 362 * Creates an account from specified user data. 363 */ 364 private static void createAccount(final Map<AuthenticationTag, String> userdata) throws Exception { 365 String username = userdata.get(AuthenticationTag.Username); 366 String password = userdata.get(AuthenticationTag.Password); 367 if (FrameIO.LoadProfile(username) != null) { 368 MessageBay.errorMessage("A Expeditee profile with this username already exists, please choose another."); 369 } else { 370 // generate the newly created user a profile frame using the specialized default frame as a blueprint 371 String defaultBackup = UserSettings.DEFAULT_PROFILE_NAME; 372 UserSettings.DEFAULT_PROFILE_NAME = "multiusermodedefault"; 373 Frame profile = FrameIO.CreateNewProfile(username); 374 UserSettings.DEFAULT_PROFILE_NAME = defaultBackup; 375 376 // perform necessary changes to generated frame: remove default title, set background color, set custom title 377 profile.getTitleItem().delete(); 378 profile.setBackgroundColor(new Colour(1, 1, 0.39f)); 379 getByData(profile, "txtUsername").stream().forEach(i -> i.setText(username)); 380 getByText(profile, "“If Aphroditē be the godess of love").stream().forEach(i -> i.setWidth(300)); 381 getByText(profile, "Sleek like Aphroditē, Wise like Athēnâ.").stream().forEach(i -> i.setWidth(300)); 382 383 // update ownership 384 int lastNumber = FrameIO.getLastNumber(profile.getFramesetName()); 385 for (int i = 1; i <= lastNumber; i++) { 386 Frame frame = FrameIO.LoadFrame(profile.getFramesetName() + i); 387 frame.setOwner(username); 388 frame.setEncryptionLabel("Profile"); 389 Collection<Item> items = frame.getAllItems(); 390 for (Item item: items) { 391 String newText = item.getText().replace("authadmin", username); 392 item.setText(newText); 393 } 394 } 395 396 // generate and store personal, public and private keys 397 String backupUser = UserSettings.UserName.get(); 398 setUser(username); 399 UserSettings.Authenticated.set(true); 400 401 // personal key 402 Random rand = new Random(); 403 byte[] keyBytes = new byte[16]; 404 rand.nextBytes(keyBytes); 405 SecretKey key = new SecretKeySpec(keyBytes, SymmetricAlgorithm); 406 Authenticator.getInstance().putKey(username, password, key); 407 org.expeditee.settings.auth.secrets.KeyList.PersonalKey.setSetting(new Text(Base64.getEncoder().encodeToString(key.getEncoded()))); 408 409 // public+private key pair 410 KeyPairGenerator keyGen = KeyPairGenerator.getInstance(AsymmetricAlgorithm); 411 keyGen.initialize(1024); 412 KeyPair keyPair = keyGen.generateKeyPair(); 413 414 org.expeditee.settings.auth.secrets.KeyList.PrivateKey.setSetting(new Text(Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded()))); 415 org.expeditee.settings.auth.KeyList.PublicKey.setSetting(new Text(Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded()))); 416 417 // ensure save of keys 418 lastNumber = FrameIO.getLastNumber(profile.getFramesetName()); 419 for (int i = 1; i <= lastNumber; i++) { 420 Frame frame = FrameIO.LoadFrame(profile.getFramesetName() + i); 421 frame.setChanged(true); 422 FrameIO.SaveFrame(frame); 423 } 424 setUser(backupUser); 425 UserSettings.Authenticated.set(false); 426 427 // proceed to log into new account. 428 login(userdata); 429 } 592 593 private static TextSetting constructTextSetting(String tooltip, String text, String data) { 594 return new TextSetting(tooltip, text) { 595 @Override 596 public Text generateText() { 597 Text t = new Text(text); 598 t.setData(data); 599 return t; 600 } 601 }; 602 } 603 604 private static <T> GenericSetting<T> constructGenericSetting(Class<T> type, String tooltip, String name, T value, String frameset) { 605 return new GenericSetting<T>(type, tooltip, name, value) { 606 @Override 607 public Text generateRepresentation(String name, String frameset) { 608 Text t = new Text(name + ": " + value); 609 return t; 610 } 611 }; 430 612 } 431 613 … … 446 628 } 447 629 } 448 449 private static void associateEmail(Map<AuthenticationTag, String> userdata) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, ClassNotFoundException, IOException, SQLException { 450 Authenticator.getInstance().putEmail( 451 userdata.get(AuthenticationTag.Username), 452 userdata.get(AuthenticationTag.Email)); 453 } 454 455 private static void setUser(final String username) { 456 UserSettings.UserName.set(username); 457 UserSettings.ProfileName.set(username); 458 UserSettings.HomeFrame.set(username + "1"); 459 UserSettings.UserName.setDefault(username); 460 UserSettings.ProfileName.setDefault(username); 461 UserSettings.HomeFrame.setDefault(username + "1"); 462 } 463 464 private static Frame loadProfile(final String username) throws Exception { 465 final Frame frameOne = FrameIO.LoadProfile(username); 466 if (frameOne != null) { 467 return frameOne; 468 } else { 469 final Frame profile = FrameIO.CreateNewProfile(username); 470 for (int i = 0; i < FrameIO.getLastNumber(profile.getFramesetName()); i++) { 471 final Frame frame = FrameIO.LoadFrame(profile.getFramesetName() + i); 472 final Collection<Text> textItems = frame.getTextItems(); 473 for (final Text t: textItems) { 474 if (t.getText().startsWith("User name:")) { 475 t.setText("User name: " + UserSettings.UserName.get()); 476 } else if (t.getText().startsWith("Profile name:")) { 477 t.setText("Profile name: " + UserSettings.ProfileName.get()); 478 } 479 } 480 FrameIO.ForceSaveFrame(frame); 481 } 482 return profile; 483 } 484 } 485 486 // public static void AuthRecoverPasswordStage1() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException { 487 // final Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems(); 488 // final Optional<Text> txtUsername = textItems.stream().filter(t -> t.getData() != null && t.getData().contains("txtUsername")).findFirst(); 489 // final Optional<Text> txtRecoveryEmail = textItems.stream().filter(t -> t.getData() != null && t.getData().contains("txtRecoveryEmail")).findFirst(); 490 // final String username = txtUsername.isPresent() ? txtUsername.get().getText() : System.getProperty("user.name"); 491 // final String email = txtRecoveryEmail.isPresent() ? txtRecoveryEmail.get().getText() : System.getProperty("user.recoveryemail"); 492 // if (areAllPresent(new String[] { username, email })) { 493 // // generate intergalactic number 494 // final String intergalacticNumber = Authenticator.getInstance().newIntergalacticNumber(username, email); 495 // 630 496 631 // // establish properties 497 632 // final String from = "[email protected]"; … … 515 650 // }; 516 651 // }); 517 // 518 // try { 652 519 653 // // construct email message 520 654 // final MimeMessage message = new MimeMessage(session); … … 526 660 // // send email message 527 661 // Transport.send(message); 528 // } catch (final MessagingException e) { 529 // e.printStackTrace(); 530 // } 531 // 532 // FrameUtils.DisplayFrame("4", false, true); 533 // } else { 534 // MessageBay.errorMessage("To recover a lost password please fill in all the provided fields."); 535 // } 536 // } 537 // 538 // public static void AuthRecoverPasswordStage2() throws NoSuchAlgorithmException, KeyStoreException, CertificateException, FileNotFoundException, IOException { 539 // final Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems(); 540 // final Optional<Text> txtUsername = textItems.stream().filter(t -> t.getData() != null && t.getData().contains("txtUsername")).findFirst(); 541 // final Optional<Text> txtRecoveryEmail = textItems.stream().filter(t -> t.getData() != null && t.getData().contains("txtRecoveryEmail")).findFirst(); 542 // final Optional<Text> txtIntergalacticNumber = textItems.stream().filter(t -> t.getData() != null && t.getData().contains("txtIntergalacticNumber")).findFirst(); 543 // final String username = txtUsername.isPresent() ? txtUsername.get().getText() : System.getProperty("user.name"); 544 // final String email = txtRecoveryEmail.isPresent() ? txtRecoveryEmail.get().getText() : System.getProperty("user.recoveryemail"); 545 // final String intergalacticNumber = txtIntergalacticNumber.isPresent() ? txtIntergalacticNumber.get().getText() : System.getProperty("user.intergalacticnumber"); 546 // if (areAllPresent(new String[] { username, email, intergalacticNumber })) { 547 // // confirm intergalactic number matches what is stored 548 // final boolean intergalaticNumberMatches = Authenticator.getInstance().confirmIntergalaticNumber(username, email, intergalacticNumber); 549 // if (intergalaticNumberMatches) { 550 // final Frame changePasswordFrame = FrameIO.LoadFrame("5"); 551 // final Optional<Text> actionNewPassword = changePasswordFrame.getTextItems().stream().filter(t -> t.getAction().contains("AuthNewPassword")).findFirst(); 552 // if (actionNewPassword.isPresent()) { 553 // actionNewPassword.get().setData(intergalacticNumber); 554 // } 555 // FrameUtils.DisplayFrame("5", false, true); 556 // } 557 // } else { 558 // MessageBay.errorMessage("To recover a lost password please fill in all the provided fields."); 559 // } 560 // } 662 561 663 562 664 public static void TickBox(final Text item) { … … 569 671 570 672 /* 571 * Gets all items on a specified frame that contain the specified text.572 */573 private static Collection<Item> getByText(final Frame frame, final String text) {574 final Collection<Item> allItems = frame.getAllItems();575 allItems.removeIf(i -> i.getText() == null || !i.getText().contains(text));576 return allItems;577 }578 579 /*580 673 * Gets all items on a specified frame that contain the specified data. 581 674 */ 582 p rivatestatic Collection<Item> getByData(final Frame frame, final String data) {675 public static Collection<Item> getByData(final Frame frame, final String data) { 583 676 final Collection<Item> allItems = frame.getAllItems(); 584 677 allItems.removeIf(i -> i.getData() == null || !i.hasData(data)); 585 678 return allItems; 586 679 } 680 681 public static Collection<Item> getByContent(final Frame frame, final String content) { 682 final Collection<Item> allItems = frame.getAllItems(); 683 allItems.removeIf(i -> i.getText().compareTo(content) != 0); 684 return allItems; 685 } 587 686 }
Note:
See TracChangeset
for help on using the changeset viewer.