/*
* @author Dirk Bergstrom
*
* Keyring Desktop Client - Easy password management on your phone or desktop.
* Copyright (C) 2009-2010, Dirk Bergstrom, keyring@otisbean.com
*
* Adapted from KeyringEditor v1.1
* Copyright 2006 Markus Griessnig
* http://www.ict.tuwien.ac.at/keyring/
* Markus graciously gave his assent to release the modified code under the GPLv3.
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.otisbean.keyring.gui;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.Vector;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import com.otisbean.keyring.KeyringException;
import com.otisbean.keyring.converters.Converter;
/**
* This dialog allows the user to convert a database to different keyring database formats.
*/
public class ImportDialog extends JDialog implements ActionListener, PropertyChangeListener {
private static final long serialVersionUID = 1L;
// ----------------------------------------------------------------
// variables
// ----------------------------------------------------------------
/**
* Reference to the Gui frame
*/
private Frame frame;
private JComboBox cboFormat;
private JPasswordField inPassword;
private JPasswordField outPassword;
private Vector<String> format;
private JOptionPane optionPane;
private String btnString1 = "Select File to Import";
private String btnString2 = "Cancel";
private Editor editor;
/**
* True if button "Cancel" pressed, otherwise false
*/
private boolean cancelled = false;
// ----------------------------------------------------------------
// constructor
// ----------------------------------------------------------------
/**
* Default constructor generates Dialog.
*
* @param frame Reference to the Gui frame
* @param ring Reference to class Ring
* @param fromFormat Database format of the loaded database
*/
public ImportDialog(Frame frame, Editor editor) {
super(frame, "Import Database", true);
this.frame = frame;
this.editor = editor;
// TODO move format choices to Converter
format = new Vector<String>();
format.add("Keyring for PalmOS");
format.add("CodeWallet");
format.add("eWallet");
format.add("CSV");
cboFormat = new JComboBox(format);
cboFormat.setModel(new DefaultComboBoxModel(format));
// FIXME need to toggle inPassword input based on format
inPassword = new JPasswordField(20);
outPassword = new JPasswordField(20);
// labels
String msgString1 = "Format: ";
String msgString2 = "Password for import file: ";
String msgString3 = "Password for new database: ";
Object[] array = {msgString1, cboFormat, msgString2, inPassword,
msgString3, outPassword};
Object[] options = {btnString1, btnString2};
// generate dialog
optionPane = new JOptionPane(array,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.YES_NO_OPTION,
null,
options,
options[0]);
setContentPane(optionPane);
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
/*
* Instead of directly closing the window,
* we're going to change the JOptionPane's
* value property.
*/
optionPane.setValue(new Integer(JOptionPane.CLOSED_OPTION));
}
});
addComponentListener(new ComponentAdapter() {
public void componentShown(ComponentEvent ce) {
inPassword.requestFocusInWindow();
}
});
//Register an event handler that puts the text into the option pane.
//allCategories.addActionListener(this);
//Register an event handler that reacts to option pane state changes.
optionPane.addPropertyChangeListener(this);
}
// ----------------------------------------------------------------
// public ---------------------------------------------------------
// ----------------------------------------------------------------
/**
* This method returns status of variable cancelled.
*
* @return variable cancelled
*/
public boolean getCancelled() {
return cancelled;
}
/**
* This method is empty.
*
* @param e the ActionEvent to process
*/
public void actionPerformed(ActionEvent e) {
}
/**
* This method processes the pressed button.
* If button is OK database is converted to selected keyring database format and
* encrypted with new password and selected cryptographic function.
* Otherwise variable cancelled is set to true.
*
* @param e the PropertyChangeEvent to process
*/
public void propertyChange(PropertyChangeEvent e) {
String prop = e.getPropertyName();
if (isVisible()
&& (e.getSource() == optionPane)
&& (JOptionPane.VALUE_PROPERTY.equals(prop) ||
JOptionPane.INPUT_VALUE_PROPERTY.equals(prop))) {
Object value = optionPane.getValue();
if(value == JOptionPane.UNINITIALIZED_VALUE) {
//ignore reset
return;
}
String type = null;
int typeIndex = cboFormat.getSelectedIndex();
// TODO move typeIndex decoding into Converter
switch(typeIndex) {
case 0: type = "keyring"; break;
case 1: type = "codewallet"; break;
case 2: type = "ewallet"; break;
case 3: type = "csv"; break;
}
Converter converter;
try {
converter = Converter.getConverter(type);
} catch (KeyringException e1) {
throw new RuntimeException("Unknown/unsupported conversion type '" + type + "' selected.");
}
//Reset the JOptionPane's value.
//If you don't do this, then if the user
//presses the same button next time, no
//property change event will be fired.
optionPane.setValue(JOptionPane.UNINITIALIZED_VALUE);
if(btnString1.equals(value)) {
// check for empty passwords
if (outPassword.getPassword().length == 0) {
JOptionPane.showMessageDialog(ImportDialog.this,
"New database password required\n",
"Error", JOptionPane.ERROR_MESSAGE);
cancelled = true;
outPassword.requestFocusInWindow();
return;
}
if (converter.needsInputFilePassword &&
inPassword.getPassword().length == 0) {
JOptionPane.showMessageDialog(ImportDialog.this,
"Import password required\n",
"Error", JOptionPane.ERROR_MESSAGE);
cancelled = true;
inPassword.requestFocusInWindow();
return;
}
// ok
JFileChooser chooser = new JFileChooser();
chooser.setDialogTitle("Select File to Import");
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
chooser.setCurrentDirectory(editor.previousDirectory);
chooser.setMultiSelectionEnabled(false);
int returnVal = chooser.showOpenDialog(this.frame);
if(returnVal == JFileChooser.APPROVE_OPTION) {
try {
File selectedFile = chooser.getSelectedFile();
String importFilename = selectedFile.getCanonicalPath();
// convert database
// FIXME need to be more secure with passwords
editor.setRing(converter.convert(importFilename,
new String(inPassword.getPassword()),
new String(outPassword.getPassword())));
}
catch(Exception ex) {
// cancel
cancelled = true;
JOptionPane.showMessageDialog(frame,
"Convert database: " + ex.getMessage(),
"Error",
JOptionPane.ERROR_MESSAGE);
ex.printStackTrace(System.err);
}
}
else {
// cancel
cancelled = true;
}
}
else {
// cancel
cancelled = true;
}
clearAndHide();
}
}
// ----------------------------------------------------------------
// private --------------------------------------------------------
// ----------------------------------------------------------------
/**
* This method hides the dialog.
*/
private void clearAndHide() {
inPassword.setText(null);
setVisible(false);
}
}