/*
* Universal Password Manager
* Copyright (C) 2005-2013 Adrian Smith
*
* This file is part of Universal Password Manager.
*
* Universal Password Manager is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Universal Password Manager is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Universal Password Manager; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com._17od.upm.gui;
import java.awt.Container;
import java.awt.Desktop;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.SecureRandom;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import org.apache.commons.validator.routines.UrlValidator;
import com._17od.upm.database.AccountInformation;
import com._17od.upm.util.Preferences;
import com._17od.upm.util.Translator;
import com._17od.upm.util.Util;
public class AccountDialog extends EscapeDialog {
private static final long serialVersionUID = 1L;
private static final char[] ALLOWED_CHARS = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9' };
// Extended CharArray list which include also 24 Escape characters for
// stronger password generation
private static final char[] EXTRA_ALLOWED_CHARS = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2',
'3', '4', '5', '6', '7', '8', '9', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ',', ')', '_', '-',
'+', '=', '|', '/', '<', '>', '.', '?', ';', ':' };
/*
* We will use the (4)four above CharArray lists(UPPERCASE_CHARS,
* LOWERCASE_CHARS, NUMBER_CHARS, ESCAPE_CHARS) to ensure that the generated
* passwords will be more complex. If the user has selected to include
* escape characters to generated passwords and the length of the passwords
* is 4 or above, then we will use some methods in order to generate
* passwords that will have at least 1 lower case + 1 upper case + 1 number
* + 1 escape character. On the other hand, if the user has not selected to
* include escape characters to generated passwords and the length of the
* passwords is at least 3, then we will use methods in order to generate
* passwords that will have at least 1 lower case + 1 upper case + 1 number.
*/
private static final char[] UPPERCASE_CHARS = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
};
private static final char[] LOWERCASE_CHARS = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
};
private static final char[] NUMBER_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
private static final char[] PUNCTUATION_CHARS = { '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ',', ')', '_',
'-', '+', '=', '|', '/', '<', '>', '.', '?', ';', ':' };
private AccountInformation pAccount;
private JTextField userId;
private JPasswordField password;
private JTextArea notes;
private JTextField url;
private JTextField accountName;
private boolean okClicked = false;
private ArrayList existingAccounts;
private JFrame parentWindow;
private boolean accountChanged = false;
private char defaultEchoChar;
public AccountDialog(AccountInformation account, JFrame parentWindow, boolean readOnly,
ArrayList existingAccounts) {
super(parentWindow, true);
boolean addingAccount = false;
//Request focus on Account JDialog when mouse clicked
this.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 1) {
requestFocus();
}
}});
// Set the title based on weather we've been opened in readonly mode and
// weather the
// Account passed in is empty or not
String title = null;
if (readOnly) {
title = Translator.translate("viewAccount");
} else if (!readOnly && account.getAccountName().trim().equals("")) {
title = Translator.translate("addAccount");
addingAccount = true;
} else {
title = Translator.translate("editAccount");
}
setTitle(title);
this.pAccount = account;
this.existingAccounts = existingAccounts;
this.parentWindow = parentWindow;
getContentPane().setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
Container container = getContentPane();
// The AccountName Row
JLabel accountLabel = new JLabel(Translator.translate("account"));
c.gridx = 0;
c.gridy = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.NONE;
container.add(accountLabel, c);
// This panel will hold the Account field and the copy and paste
// buttons.
JPanel accountPanel = new JPanel(new GridBagLayout());
accountName = new JTextField(new String(pAccount.getAccountName()), 20);
if (readOnly) {
accountName.setEditable(false);
}
c.gridx = 0;
c.gridy = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(0, 0, 0, 5);
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.HORIZONTAL;
accountPanel.add(accountName, c);
accountName.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
accountName.selectAll();
}
});
JButton acctCopyButton = new JButton();
acctCopyButton.setIcon(Util.loadImage("copy-icon.png"));
acctCopyButton.setToolTipText("Copy");
acctCopyButton.setEnabled(true);
acctCopyButton.setMargin(new Insets(0, 0, 0, 0));
acctCopyButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
copyTextField(accountName);
}
});
c.gridx = 1;
c.gridy = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(0, 0, 0, 5);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.NONE;
accountPanel.add(acctCopyButton, c);
JButton acctPasteButton = new JButton();
acctPasteButton.setIcon(Util.loadImage("paste-icon.png"));
acctPasteButton.setToolTipText("Paste");
acctPasteButton.setEnabled(!readOnly);
acctPasteButton.setMargin(new Insets(0, 0, 0, 0));
acctPasteButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
pasteToTextField(accountName);
}
});
c.gridx = 2;
c.gridy = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(0, 0, 0, 5);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.NONE;
accountPanel.add(acctPasteButton, c);
c.gridx = 1;
c.gridy = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.HORIZONTAL;
container.add(accountPanel, c);
// Userid Row
JLabel useridLabel = new JLabel(Translator.translate("userid"));
c.gridx = 0;
c.gridy = 1;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.NONE;
container.add(useridLabel, c);
// This panel will hold the User ID field and the copy and paste
// buttons.
JPanel idPanel = new JPanel(new GridBagLayout());
userId = new JTextField(new String(pAccount.getUserId()), 20);
if (readOnly) {
userId.setEditable(false);
}
c.gridx = 0;
c.gridy = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(0, 0, 0, 5);
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.HORIZONTAL;
idPanel.add(userId, c);
userId.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
userId.selectAll();
}
});
JButton idCopyButton = new JButton();
idCopyButton.setIcon(Util.loadImage("copy-icon.png"));
idCopyButton.setToolTipText("Copy");
idCopyButton.setEnabled(true);
idCopyButton.setMargin(new Insets(0, 0, 0, 0));
idCopyButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
copyTextField(userId);
}
});
c.gridx = 1;
c.gridy = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(0, 0, 0, 5);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.NONE;
idPanel.add(idCopyButton, c);
JButton idPasteButton = new JButton();
idPasteButton.setIcon(Util.loadImage("paste-icon.png"));
idPasteButton.setToolTipText("Paste");
idPasteButton.setEnabled(!readOnly);
idPasteButton.setMargin(new Insets(0, 0, 0, 0));
idPasteButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
pasteToTextField(userId);
}
});
c.gridx = 2;
c.gridy = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(0, 0, 0, 5);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.NONE;
idPanel.add(idPasteButton, c);
c.gridx = 1;
c.gridy = 1;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.HORIZONTAL;
container.add(idPanel, c);
// Password Row
JLabel passwordLabel = new JLabel(Translator.translate("password"));
c.gridx = 0;
c.gridy = 2;
c.anchor = GridBagConstraints.FIRST_LINE_START;
c.insets = new Insets(15, 10, 10, 10);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.NONE;
container.add(passwordLabel, c);
// This panel will hold the password, generate password button, copy and
// paste buttons, and hide password checkbox
JPanel passwordPanel = new JPanel(new GridBagLayout());
password = new JPasswordField(new String(pAccount.getPassword()), 20);
// allow CTRL-C on the password field
password.putClientProperty("JPasswordField.cutCopyAllowed", Boolean.TRUE);
password.setEditable(!readOnly);
password.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
password.selectAll();
}
});
c.gridx = 0;
c.gridy = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(0, 0, 0, 5);
c.weightx = 1;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.HORIZONTAL;
passwordPanel.add(password, c);
JButton generateRandomPasswordButton = new JButton(Translator.translate("generate"));
if (readOnly) {
generateRandomPasswordButton.setEnabled(false);
}
generateRandomPasswordButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent actionevent) {
// Get the user's preference about including or not Escape
// Characters to generated passwords
Boolean includeEscapeChars = new Boolean(
Preferences.get(Preferences.ApplicationOptions.INCLUDE_ESCAPE_CHARACTERS, "true"));
int pwLength = Preferences.getInt(Preferences.ApplicationOptions.ACCOUNT_PASSWORD_LENGTH, 8);
String Password;
if ((includeEscapeChars.booleanValue()) && (pwLength > 3)) {
// Verify that the generated password satisfies the criteria
// for strong passwords(including Escape Characters)
do {
Password = GeneratePassword(pwLength, includeEscapeChars.booleanValue());
} while (!(CheckPassStrong(Password, includeEscapeChars.booleanValue())));
} else if (!(includeEscapeChars.booleanValue()) && (pwLength > 2)) {
// Verify that the generated password satisfies the criteria
// for strong passwords(excluding Escape Characters)
do {
Password = GeneratePassword(pwLength, includeEscapeChars.booleanValue());
} while (!(CheckPassStrong(Password, includeEscapeChars.booleanValue())));
} else {
// Else a weak password of 3 or less chars will be produced
Password = GeneratePassword(pwLength, includeEscapeChars.booleanValue());
}
password.setText(Password);
}
});
if (addingAccount) {
generateRandomPasswordButton.doClick();
}
c.gridx = 1;
c.gridy = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(0, 0, 0, 5);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.HORIZONTAL;
passwordPanel.add(generateRandomPasswordButton, c);
JButton pwCopyButton = new JButton();
pwCopyButton.setIcon(Util.loadImage("copy-icon.png"));
pwCopyButton.setToolTipText("Copy");
pwCopyButton.setEnabled(true);
pwCopyButton.setMargin(new Insets(0, 0, 0, 0));
pwCopyButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
copyTextField(password);
}
});
c.gridx = 2;
c.gridy = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(0, 0, 0, 5);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.HORIZONTAL;
passwordPanel.add(pwCopyButton, c);
JButton pwPasteButton = new JButton();
pwPasteButton.setIcon(Util.loadImage("paste-icon.png"));
pwPasteButton.setToolTipText("Paste");
pwPasteButton.setEnabled(!readOnly);
pwPasteButton.setMargin(new Insets(0, 0, 0, 0));
pwPasteButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
pasteToTextField(password);
}
});
c.gridx = 3;
c.gridy = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(0, 0, 0, 5);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.HORIZONTAL;
passwordPanel.add(pwPasteButton, c);
JCheckBox hidePasswordCheckbox = new JCheckBox(Translator.translate("hide"), true);
defaultEchoChar = password.getEchoChar();
hidePasswordCheckbox.setMargin(new Insets(5, 0, 5, 0));
hidePasswordCheckbox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
password.setEchoChar(defaultEchoChar);
} else {
password.setEchoChar((char) 0);
}
}
});
Boolean hideAccountPassword = new Boolean(
Preferences.get(Preferences.ApplicationOptions.ACCOUNT_HIDE_PASSWORD, "true"));
hidePasswordCheckbox.setSelected(hideAccountPassword.booleanValue());
c.gridx = 0;
c.gridy = 1;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(0, 0, 0, 0);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.HORIZONTAL;
passwordPanel.add(hidePasswordCheckbox, c);
c.gridx = 1;
c.gridy = 2;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 1;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.HORIZONTAL;
container.add(passwordPanel, c);
// URL Row
JLabel urlLabel = new JLabel(Translator.translate("url"));
c.gridx = 0;
c.gridy = 3;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.NONE;
container.add(urlLabel, c);
// This panel will hold the URL field and the copy and paste buttons.
JPanel urlPanel = new JPanel(new GridBagLayout());
url = new JTextField(new String(pAccount.getUrl()), 20);
if (readOnly) {
url.setEditable(false);
}
c.gridx = 0;
c.gridy = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(0, 0, 0, 5);
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.HORIZONTAL;
urlPanel.add(url, c);
url.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
url.selectAll();
}
});
final JButton urlLaunchButton = new JButton();
urlLaunchButton.setIcon(Util.loadImage("launch-url-sm.png"));
urlLaunchButton.setToolTipText("Launch URL");
urlLaunchButton.setEnabled(true);
urlLaunchButton.setMargin(new Insets(0, 0, 0, 0));
urlLaunchButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
String urlText = url.getText();
// Check if the selected url is null or emty and inform the user
// via JoptioPane message
if ((urlText == null) || (urlText.length() == 0)) {
JOptionPane.showMessageDialog(urlLaunchButton.getParent(),
Translator.translate("EmptyUrlJoptionpaneMsg"),
Translator.translate("UrlErrorJoptionpaneTitle"), JOptionPane.WARNING_MESSAGE);
// Check if the selected url is a valid formated url(via
// urlIsValid() method) and inform the user via JoptioPane
// message
} else if (!(urlIsValid(urlText))) {
JOptionPane.showMessageDialog(urlLaunchButton.getParent(),
Translator.translate("InvalidUrlJoptionpaneMsg"),
Translator.translate("UrlErrorJoptionpaneTitle"), JOptionPane.WARNING_MESSAGE);
// Call the method LaunchSelectedURL() using the selected
// url as input
} else {
LaunchSelectedURL(urlText);
}
}
});
c.gridx = 1;
c.gridy = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(0, 0, 0, 5);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.NONE;
urlPanel.add(urlLaunchButton, c);
JButton urlCopyButton = new JButton();
urlCopyButton.setIcon(Util.loadImage("copy-icon.png"));
urlCopyButton.setToolTipText("Copy");
urlCopyButton.setEnabled(true);
urlCopyButton.setMargin(new Insets(0, 0, 0, 0));
urlCopyButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
copyTextField(url);
}
});
c.gridx = 2;
c.gridy = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(0, 0, 0, 5);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.NONE;
urlPanel.add(urlCopyButton, c);
JButton urlPasteButton = new JButton();
urlPasteButton.setIcon(Util.loadImage("paste-icon.png"));
urlPasteButton.setToolTipText("Paste");
urlPasteButton.setEnabled(!readOnly);
urlPasteButton.setMargin(new Insets(0, 0, 0, 0));
urlPasteButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
pasteToTextField(url);
}
});
c.gridx = 3;
c.gridy = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(0, 0, 0, 5);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.NONE;
urlPanel.add(urlPasteButton, c);
c.gridx = 1;
c.gridy = 3;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.HORIZONTAL;
container.add(urlPanel, c);
// Notes Row
JLabel notesLabel = new JLabel(Translator.translate("notes"));
c.gridx = 0;
c.gridy = 4;
c.anchor = GridBagConstraints.FIRST_LINE_START;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.NONE;
container.add(notesLabel, c);
// This panel will hold the Notes text area and the copy and paste
// buttons.
JPanel notesPanel = new JPanel(new GridBagLayout());
notes = new JTextArea(new String(pAccount.getNotes()), 10, 20);
if (readOnly) {
notes.setEditable(false);
}
notes.setLineWrap(true); // Enable line wrapping.
notes.setWrapStyleWord(true); // Line wrap at whitespace.
JScrollPane notesScrollPane = new JScrollPane(notes);
c.gridx = 0;
c.gridy = 0;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(0, 0, 0, 5);
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.BOTH;
notesPanel.add(notesScrollPane, c);
JButton notesCopyButton = new JButton();
notesCopyButton.setIcon(Util.loadImage("copy-icon.png"));
notesCopyButton.setToolTipText("Copy");
notesCopyButton.setEnabled(true);
notesCopyButton.setMargin(new Insets(0, 0, 0, 0));
notesCopyButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
copyTextArea(notes);
}
});
c.gridx = 1;
c.gridy = 0;
c.anchor = GridBagConstraints.FIRST_LINE_START;
c.insets = new Insets(0, 0, 0, 5);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.NONE;
notesPanel.add(notesCopyButton, c);
JButton notesPasteButton = new JButton();
notesPasteButton.setIcon(Util.loadImage("paste-icon.png"));
notesPasteButton.setToolTipText("Paste");
notesPasteButton.setEnabled(!readOnly);
notesPasteButton.setMargin(new Insets(0, 0, 0, 0));
notesPasteButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
pasteToTextArea(notes);
}
});
c.gridx = 2;
c.gridy = 0;
c.anchor = GridBagConstraints.FIRST_LINE_START;
c.insets = new Insets(0, 0, 0, 5);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.fill = GridBagConstraints.NONE;
notesPanel.add(notesPasteButton, c);
c.gridx = 1;
c.gridy = 4;
c.anchor = GridBagConstraints.LINE_START;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 1;
c.fill = GridBagConstraints.HORIZONTAL;
container.add(notesPanel, c);
// Seperator Row
JSeparator sep = new JSeparator();
c.gridx = 0;
c.gridy = 5;
c.anchor = GridBagConstraints.PAGE_END;
c.insets = new Insets(0, 0, 0, 0);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 3;
c.fill = GridBagConstraints.HORIZONTAL;
container.add(sep, c);
// Button Row
JPanel buttonPanel = new JPanel();
JButton okButton = new JButton(Translator.translate("ok"));
// Link Enter key to okButton
getRootPane().setDefaultButton(okButton);
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
okButtonAction();
}
});
buttonPanel.add(okButton);
if (!readOnly) {
JButton cancelButton = new JButton(Translator.translate("cancel"));
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
closeButtonAction();
}
});
buttonPanel.add(cancelButton);
}
c.gridx = 0;
c.gridy = 6;
c.anchor = GridBagConstraints.PAGE_END;
c.insets = new Insets(5, 0, 5, 0);
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 3;
c.fill = GridBagConstraints.NONE;
container.add(buttonPanel, c);
} // End AccountDialog constructor
public boolean okClicked() {
return okClicked;
} // End okClicked()
public AccountInformation getAccount() {
return pAccount;
} // End getAccount()
private void okButtonAction() {
// Check if the account name has changed.
if (!pAccount.getAccountName().equals(accountName.getText().trim())) {
accountChanged = true;
}
// [1375397] Ensure that an account with the supplied name doesn't
// already exist.
// By checking 'accountNames' we're checking both visible and filtered
// accounts
//
// Only check if an account with the same name exists if the account
// name has actually changed
if (accountChanged && existingAccounts.indexOf(accountName.getText().trim()) > -1) {
JOptionPane.showMessageDialog(parentWindow,
Translator.translate("accountAlreadyExistsWithName", accountName.getText().trim()),
Translator.translate("accountAlreadyExists"), JOptionPane.ERROR_MESSAGE);
} else {
// Check for changes
if (!pAccount.getUserId().equals(userId.getText())) {
accountChanged = true;
}
if (!pAccount.getPassword().equals(password.getText())) {
accountChanged = true;
}
if (!pAccount.getUrl().equals(url.getText())) {
accountChanged = true;
}
if (!pAccount.getNotes().equals(notes.getText())) {
accountChanged = true;
}
pAccount.setAccountName(accountName.getText().trim());
pAccount.setUserId(userId.getText());
pAccount.setPassword(password.getText());
pAccount.setUrl(url.getText());
pAccount.setNotes(notes.getText());
setVisible(false);
dispose();
okClicked = true;
}
} // End okButtonAction()
public boolean getAccountChanged() {
return accountChanged;
} // End getAccountChanged()
private void closeButtonAction() {
okClicked = false;
setVisible(false);
dispose();
} // End closeButtonAction()
/**
* This method takes as input the user's preferences about password length,
* including or excluding Escape Characters, and randomly generates a
* password. Then, the method returns the generated password as a String.
*
* @param PassLength
* @param InclEscChars
* @return passwordBuffer.toString()
*/
private static String GeneratePassword(int PassLength, boolean InclEscChars) {
SecureRandom random = new SecureRandom();
StringBuffer passwordBuffer = new StringBuffer();
if (InclEscChars) {
for (int i = 0; i < PassLength; i++) {
passwordBuffer.append(EXTRA_ALLOWED_CHARS[random.nextInt(EXTRA_ALLOWED_CHARS.length)]);
}
return passwordBuffer.toString();
} else {
for (int i = 0; i < PassLength; i++) {
passwordBuffer.append(ALLOWED_CHARS[random.nextInt(ALLOWED_CHARS.length)]);
}
return passwordBuffer.toString();
}
} // End GeneratePassword()
/**
* This method returns true if the generated password satisfies the criteria
* of a strong password, including or excluding Escape Characters. If not,
* then returns false.
*
* @param Pass
* @param InclEscChars
* @return true or false, depending on strength criteria.
*/
private static boolean CheckPassStrong(String Pass, boolean InclEscChars) {
if (InclEscChars) {
if ((InclUpperCase(Pass)) && (InclLowerCase(Pass)) && (InclNumber(Pass)) && (InclEscape(Pass))) {
return true;
} else {
return false;
}
} else {
if ((InclUpperCase(Pass)) && (InclLowerCase(Pass)) && (InclNumber(Pass))) {
return true;
} else {
return false;
}
}
} // End CheckPassStrong()
/**
* This method returns true if the generated password contains at least one
* Upper Case character. If not, then the method returns false.
*
* @param GeneratedPass
* @return true or false, depending on existence of one upper case letter.
*/
private static boolean InclUpperCase(String GeneratedPass) {
char[] PassWordArray = GeneratedPass.toCharArray();
boolean find = false;
outerloop: for (int i = 0; i < PassWordArray.length; i++) {
for (int j = 0; j < UPPERCASE_CHARS.length; j++) {
if (PassWordArray[i] == UPPERCASE_CHARS[j]) {
find = true;
break outerloop;
}
}
}
if (find) {
return true;
} else {
return false;
}
} // End InclUpperCase()
/**
* This method returns true if the generated password contains at least one
* Lower Case character. If not, then the method returns false.
*
* @param GeneratedPass
* @return true or false, depending on existence of one lower case letter.
*/
private static boolean InclLowerCase(String GeneratedPass) {
char[] PassWordArray = GeneratedPass.toCharArray();
boolean find = false;
outerloop: for (int i = 0; i < PassWordArray.length; i++) {
for (int j = 0; j < LOWERCASE_CHARS.length; j++) {
if (PassWordArray[i] == LOWERCASE_CHARS[j]) {
find = true;
break outerloop;
}
}
}
if (find) {
return true;
} else {
return false;
}
} // End InclLowerCase()
/**
* This method returns true if the generated password contains at least one
* Number. If not, then the method returns false.
*
* @param GeneratedPass
* @return true or false, depending on existence of one number.
*/
private static boolean InclNumber(String GeneratedPass) {
char[] PassWordArray = GeneratedPass.toCharArray();
boolean find = false;
outerloop: for (int i = 0; i < PassWordArray.length; i++) {
for (int j = 0; j < NUMBER_CHARS.length; j++) {
if (PassWordArray[i] == NUMBER_CHARS[j]) {
find = true;
break outerloop;
}
}
}
if (find) {
return true;
} else {
return false;
}
} // End InclNumber()
/**
* This method returns true if the generated password contains at least one
* Escape character. If not, then the method returns false.
*
* @param GeneratedPass
* @return true or false, depending on existence of one escape character.
*/
private static boolean InclEscape(String GeneratedPass) {
char[] PassWordArray = GeneratedPass.toCharArray();
boolean find = false;
outerloop: for (int i = 0; i < PassWordArray.length; i++) {
for (int j = 0; j < PUNCTUATION_CHARS.length; j++) {
if (PassWordArray[i] == PUNCTUATION_CHARS[j]) {
find = true;
break outerloop;
}
}
}
if (find) {
return true;
} else {
return false;
}
} // End InclEscape()
/**
* This method takes in a JTextField object and then copies the text of that
* text field to the system clipboard.
*
* @param textField
*/
public void copyTextField(JTextField textField) {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
StringSelection selected = new StringSelection(textField.getText());
clipboard.setContents(selected, selected);
}
/**
* This method takes in a JTextArea object and then copies the selected text
* in that text area to the system clipboard.
*
* @param textArea
*/
public void copyTextArea(JTextArea textArea) {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
StringSelection selected = new StringSelection(textArea.getSelectedText());
clipboard.setContents(selected, selected);
}
/**
* This method takes in a JTextField object and then sets the text of that
* text field to the contents of the system clipboard.
*
* @param textField
*/
public void pasteToTextField(JTextField textField) {
String text = "";
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable clipText = clipboard.getContents(null);
if ((clipText != null) && clipText.isDataFlavorSupported(DataFlavor.stringFlavor)) {
try {
text = (String) clipText.getTransferData(DataFlavor.stringFlavor);
} catch (UnsupportedFlavorException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
textField.setText(text);
}
/**
* This method takes in a JTextArea object and then inserts the contents of
* the system clipboard into that text area at the cursor position.
*
* @param textArea
*/
public void pasteToTextArea(JTextArea textArea) {
String text = "";
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable clipText = clipboard.getContents(null);
if ((clipText != null) && clipText.isDataFlavorSupported(DataFlavor.stringFlavor)) {
try {
text = (String) clipText.getTransferData(DataFlavor.stringFlavor);
} catch (UnsupportedFlavorException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
textArea.insert(text, textArea.getCaretPosition());
textArea.requestFocus();
}
/**
* Use com.apache.commons.validator library in order to check the validity
* (proper formating, e.x http://www.url.com) of the given URL.
*
* @param urL
* @return
*/
private boolean urlIsValid(String urL) {
UrlValidator urlValidator = new UrlValidator();
if (urlValidator.isValid(urL)) {
return true;
} else {
return false;
}
}
/**
* Method that get(as input) the selected Account URL and open this URL via
* the default browser of our platform.
*
* @param url
*/
private void LaunchSelectedURL(String url) {
if (Desktop.isDesktopSupported()) {
Desktop desktop = Desktop.getDesktop();
try {
desktop.browse(new URI(url));
} catch (IOException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
} else { // Linux and Mac specific code in order to launch url
Runtime runtime = Runtime.getRuntime();
try {
runtime.exec("xdg-open " + url);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}