/** * Copyright 2011 multibit.org * * Licensed under the MIT license (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://opensource.org/licenses/mit-license.php * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.multibit.viewsystem.swing.view.panels; import com.google.bitcoin.crypto.KeyCrypterException; import org.bitcoinj.wallet.Protos.Wallet.EncryptionType; import org.multibit.controller.Controller; import org.multibit.controller.bitcoin.BitcoinController; import org.multibit.crypto.KeyCrypterOpenSSL; import org.multibit.file.PrivateKeyAndDate; import org.multibit.file.PrivateKeysHandler; import org.multibit.file.PrivateKeysHandlerException; import org.multibit.model.bitcoin.BitcoinModel; import org.multibit.model.bitcoin.WalletBusyListener; import org.multibit.model.core.CoreModel; import org.multibit.utils.ImageLoader; import org.multibit.viewsystem.DisplayHint; import org.multibit.viewsystem.View; import org.multibit.viewsystem.Viewable; import org.multibit.viewsystem.swing.ColorAndFontConstants; import org.multibit.viewsystem.swing.MultiBitFrame; import org.multibit.viewsystem.swing.action.HelpContextAction; import org.multibit.viewsystem.swing.action.ImportPrivateKeysSubmitAction; import org.multibit.viewsystem.swing.view.PrivateKeyFileFilter; import org.multibit.viewsystem.swing.view.components.*; import javax.swing.*; import javax.swing.filechooser.FileFilter; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.nio.CharBuffer; import java.text.DateFormat; import java.util.Collection; import java.util.Date; import java.util.Locale; /** * The import private keys view. */ public class ImportPrivateKeysPanel extends JPanel implements Viewable, WalletBusyListener { private static final long serialVersionUID = 444992294329957705L; private final Controller controller; private final BitcoinController bitcoinController; private MultiBitFrame mainFrame; private MultiBitLabel walletFilenameLabel; private MultiBitLabel walletDescriptionLabel; private MultiBitButton chooseFilenameButton; private String chooseFilenameButtonText; private JFileChooser fileChooser; private MultiBitLabel outputFilenameLabel; private MultiBitLabel messageLabel1; private MultiBitLabel messageLabel2; private String outputFilename; private MultiBitLabel passwordInfoLabel; private JPasswordField passwordField1; private MultiBitLabel passwordPromptLabel1; private MultiBitButton unlockButton; private JPasswordField passwordField2; private MultiBitLabel passwordPromptLabel2; private JPasswordField walletPasswordField; private MultiBitLabel walletPasswordPromptLabel; private JLabel numberOfKeysLabel; private JLabel replayDateLabel; private ImportPrivateKeysSubmitAction importPrivateKeysSubmitAction; private KeyCrypterOpenSSL encrypterDecrypter; public FileFilter multiBitFileChooser; //public FileFilter myWalletPlainFileChooser; //public FileFilter myWalletEncryptedFileChooser; private Font adjustedFont; /** * Creates a new {@link ImportPrivateKeysPanel}. */ public ImportPrivateKeysPanel(BitcoinController bitcoinController, MultiBitFrame mainFrame) { this.bitcoinController = bitcoinController; this.controller = this.bitcoinController; this.mainFrame = mainFrame; setBackground(ColorAndFontConstants.VERY_LIGHT_BACKGROUND_COLOR); applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); outputFilename = ""; initUI(); walletBusyChange(this.bitcoinController.getModel().getActivePerWalletModelData().isBusy()); this.bitcoinController.registerWalletBusyListener(this); enableImportFilePasswordPanel(false); passwordField1.setText(""); passwordField2.setText(""); boolean walletPasswordRequired = false; if (this.bitcoinController.getModel().getActiveWallet() != null && this.bitcoinController.getModel().getActiveWallet().getEncryptionType() == EncryptionType.ENCRYPTED_SCRYPT_AES) { walletPasswordRequired = true; } enableWalletPassword(walletPasswordRequired); encrypterDecrypter = new KeyCrypterOpenSSL(); multiBitFileChooser = new PrivateKeyFileFilter(controller); //myWalletPlainFileChooser = new MyWalletPlainKeyFileFilter(); //myWalletEncryptedFileChooser = new MyWalletEncryptedKeyFileFilter(); } private void initUI() { setLayout(new BorderLayout()); JPanel mainPanel = new JPanel(); mainPanel.setMinimumSize(new Dimension(550, 160)); mainPanel.setLayout(new GridBagLayout()); mainPanel.setOpaque(false); mainPanel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); String[] keys = new String[] { "resetTransactionsPanel.walletDescriptionLabel", "resetTransactionsPanel.walletFilenameLabel", "showExportPrivateKeysPanel.passwordPrompt", "showExportPrivateKeysPanel.repeatPasswordPrompt", "showImportPrivateKeysPanel.numberOfKeys.text", "showImportPrivateKeysPanel.replayDate.text" }; int stentWidth = MultiBitTitledPanel.calculateStentWidthForKeys(controller.getLocaliser(), keys, this) + ExportPrivateKeysPanel.STENT_DELTA; GridBagConstraints constraints = new GridBagConstraints(); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 0; constraints.gridy = 0; constraints.gridwidth = 2; constraints.weightx = 1; constraints.weighty = 1; constraints.anchor = GridBagConstraints.LINE_START; JPanel walletPanel = createWalletPanel(stentWidth); mainPanel.add(walletPanel, constraints); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 0; constraints.gridy = 1; constraints.gridwidth = 2; constraints.weightx = 1; constraints.weighty = 1; constraints.anchor = GridBagConstraints.LINE_START; JPanel filenamePanel = createFilenamePanel(stentWidth); mainPanel.add(filenamePanel, constraints); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 0; constraints.gridy = 2; constraints.gridwidth = 2; constraints.weightx = 1; constraints.weighty = 0.2; constraints.anchor = GridBagConstraints.LINE_START; JPanel passwordPanel = createPasswordPanel(stentWidth); mainPanel.add(passwordPanel, constraints); JLabel filler1 = new JLabel(); filler1.setOpaque(false); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 0; constraints.gridy = 3; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 1; constraints.weighty = 0.1; constraints.anchor = GridBagConstraints.CENTER; mainPanel.add(filler1, constraints); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 0; constraints.gridy = 4; constraints.gridwidth = 1; constraints.weightx = 0.4; constraints.weighty = 0.06; constraints.anchor = GridBagConstraints.LINE_START; JPanel buttonPanel = createButtonPanel(); mainPanel.add(buttonPanel, constraints); messageLabel1 = new MultiBitLabel(""); messageLabel1.setOpaque(false); messageLabel1.setBorder(BorderFactory.createEmptyBorder(0, 30, 0, 0)); messageLabel1.setHorizontalAlignment(JLabel.LEADING); messageLabel1.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 0; constraints.gridy = 5; constraints.gridwidth = 3; constraints.weightx = 1; constraints.weighty = 0.06; constraints.anchor = GridBagConstraints.LINE_START; mainPanel.add(messageLabel1, constraints); messageLabel2 = new MultiBitLabel(""); messageLabel2.setOpaque(false); messageLabel2.setBorder(BorderFactory.createEmptyBorder(0, 30, 0, 0)); messageLabel2.setHorizontalAlignment(JLabel.LEADING); messageLabel2.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 0; constraints.gridy = 6; constraints.gridwidth = 3; constraints.weightx = 1; constraints.weighty = 0.06; constraints.anchor = GridBagConstraints.LINE_START; mainPanel.add(messageLabel2, constraints); Action helpAction; if (ComponentOrientation.LEFT_TO_RIGHT == ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())) { helpAction = new HelpContextAction(controller, ImageLoader.HELP_CONTENTS_BIG_ICON_FILE, "multiBitFrame.helpMenuText", "multiBitFrame.helpMenuTooltip", "multiBitFrame.helpMenuText", HelpContentsPanel.HELP_IMPORTING_PRIVATE_KEYS_URL); } else { helpAction = new HelpContextAction(controller, ImageLoader.HELP_CONTENTS_BIG_RTL_ICON_FILE, "multiBitFrame.helpMenuText", "multiBitFrame.helpMenuTooltip", "multiBitFrame.helpMenuText", HelpContentsPanel.HELP_IMPORTING_PRIVATE_KEYS_URL); } HelpButton helpButton = new HelpButton(helpAction, controller); helpButton.setText(""); String tooltipText = HelpContentsPanel.createMultilineTooltipText(new String[] { controller.getLocaliser().getString( "multiBitFrame.helpMenuTooltip") }); helpButton.setToolTipText(tooltipText); helpButton.setHorizontalAlignment(SwingConstants.LEADING); helpButton.setBorder(BorderFactory.createEmptyBorder(0, AbstractTradePanel.HELP_BUTTON_INDENT, AbstractTradePanel.HELP_BUTTON_INDENT, AbstractTradePanel.HELP_BUTTON_INDENT)); helpButton.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 0; constraints.gridy = 7; constraints.weightx = 1; constraints.weighty = 0.1; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.anchor = GridBagConstraints.BASELINE_LEADING; mainPanel.add(helpButton, constraints); JLabel filler2 = new JLabel(); filler2.setOpaque(false); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 0; constraints.gridy = 8; constraints.gridwidth = 1; constraints.weightx = 1; constraints.weighty = 100; constraints.anchor = GridBagConstraints.CENTER; mainPanel.add(filler2, constraints); JScrollPane mainScrollPane = new JScrollPane(mainPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); mainScrollPane.setBorder(BorderFactory.createEmptyBorder()); mainScrollPane.getViewport().setBackground(ColorAndFontConstants.VERY_LIGHT_BACKGROUND_COLOR); mainScrollPane.getViewport().setOpaque(true); mainScrollPane.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); mainScrollPane.getHorizontalScrollBar().setUnitIncrement(CoreModel.SCROLL_INCREMENT); mainScrollPane.getVerticalScrollBar().setUnitIncrement(CoreModel.SCROLL_INCREMENT); add(mainScrollPane, BorderLayout.CENTER); } private JPanel createWalletPanel(int stentWidth) { MultiBitTitledPanel inputWalletPanel = new MultiBitTitledPanel(controller.getLocaliser().getString( "showImportPrivateKeysPanel.wallet.title"), ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); GridBagConstraints constraints = new GridBagConstraints(); MultiBitTitledPanel.addLeftJustifiedTextAtIndent( controller.getLocaliser().getString("showImportPrivateKeysPanel.wallet.text"), 3, inputWalletPanel); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 1; constraints.gridy = 4; constraints.weightx = 0.3; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; inputWalletPanel.add(MultiBitTitledPanel.createStent(stentWidth, ExportPrivateKeysPanel.STENT_HEIGHT), constraints); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 2; constraints.gridy = 5; constraints.weightx = 0.05; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.CENTER; inputWalletPanel.add(MultiBitTitledPanel.createStent(MultiBitTitledPanel.SEPARATION_BETWEEN_NAME_VALUE_PAIRS), constraints); MultiBitLabel walletDescriptionLabelLabel = new MultiBitLabel(controller.getLocaliser().getString( "resetTransactionsPanel.walletDescriptionLabel")); walletDescriptionLabelLabel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 1; constraints.gridy = 5; constraints.weightx = 0.5; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_END; inputWalletPanel.add(walletDescriptionLabelLabel, constraints); walletDescriptionLabel = new MultiBitLabel(this.bitcoinController.getModel().getActivePerWalletModelData().getWalletDescription()); walletDescriptionLabel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 3; constraints.gridy = 5; constraints.weightx = 0.5; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; inputWalletPanel.add(walletDescriptionLabel, constraints); MultiBitLabel walletFilenameLabelLabel = new MultiBitLabel(controller.getLocaliser().getString( "resetTransactionsPanel.walletFilenameLabel")); walletFilenameLabelLabel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 1; constraints.gridy = 6; constraints.weightx = 0.5; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_END; inputWalletPanel.add(walletFilenameLabelLabel, constraints); walletFilenameLabel = new MultiBitLabel(this.bitcoinController.getModel().getActiveWalletFilename()); walletFilenameLabel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 3; constraints.gridy = 6; constraints.weightx = 0.5; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; inputWalletPanel.add(walletFilenameLabel, constraints); JPanel filler3 = new JPanel(); filler3.setOpaque(false); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 1; constraints.gridy = 7; constraints.weightx = 0.3; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; inputWalletPanel.add(filler3, constraints); walletPasswordPromptLabel = new MultiBitLabel(controller.getLocaliser().getString("showExportPrivateKeysPanel.walletPasswordPrompt")); walletPasswordPromptLabel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 1; constraints.gridy = 8; constraints.weightx = 0.3; constraints.weighty = 0.1; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_END; inputWalletPanel.add(walletPasswordPromptLabel, constraints); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 2; constraints.gridy = 8; constraints.weightx = 0.05; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.CENTER; inputWalletPanel.add(MultiBitTitledPanel.createStent(MultiBitTitledPanel.SEPARATION_BETWEEN_NAME_VALUE_PAIRS), constraints); walletPasswordField = new JPasswordField(24); walletPasswordField.setMinimumSize(new Dimension(200, 20)); walletPasswordField.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 3; constraints.gridy = 8; constraints.weightx = 0.3; constraints.weighty = 0.6; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; inputWalletPanel.add(walletPasswordField, constraints); JPanel filler4 = new JPanel(); filler4.setOpaque(false); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 1; constraints.gridy = 9; constraints.weightx = 0.3; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; inputWalletPanel.add(filler4, constraints); return inputWalletPanel; } private JPanel createFilenamePanel(int stentWidth) { MultiBitTitledPanel outputFilenamePanel = new MultiBitTitledPanel(controller.getLocaliser().getString( "showImportPrivateKeysPanel.filename.title"), ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); MultiBitTitledPanel.addLeftJustifiedTextAtIndent(" ", 1, outputFilenamePanel); GridBagConstraints constraints = new GridBagConstraints(); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 0; constraints.gridy = 2; constraints.weightx = 0.3; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; outputFilenamePanel.add(MultiBitTitledPanel.getIndentPanel(1), constraints); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 1; constraints.gridy = 3; constraints.weightx = 0.3; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; outputFilenamePanel.add(MultiBitTitledPanel.createStent(stentWidth, ExportPrivateKeysPanel.STENT_HEIGHT), constraints); chooseFilenameButtonText = ""; String chooseFilenameButtonText1 = controller.getLocaliser().getString("showImportPrivateKeysPanel.filename.text"); String chooseFilenameButtonText2 = controller.getLocaliser().getString("showImportPrivateKeysPanel.filename.text.2"); // If the second term is localised, use that, otherwise the first. if (controller.getLocaliser().getLocale().equals(Locale.ENGLISH)) { chooseFilenameButtonText = chooseFilenameButtonText2; } else { if (!"Import from ...".equals(chooseFilenameButtonText2)) { chooseFilenameButtonText = chooseFilenameButtonText2; } else { chooseFilenameButtonText = chooseFilenameButtonText1; } } chooseFilenameButton = new MultiBitButton(chooseFilenameButtonText); chooseFilenameButton.setToolTipText(HelpContentsPanel.createTooltipText(controller.getLocaliser().getString("showImportPrivateKeysPanel.filename.tooltip"))); chooseFilenameButton.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); final MultiBitButton finalChooseFilenameButton = chooseFilenameButton; chooseFilenameButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { chooseFile(finalChooseFilenameButton); } }); MultiBitLabel walletFilenameLabelLabel = new MultiBitLabel(controller.getLocaliser().getString( "resetTransactionsPanel.walletFilenameLabel")); walletFilenameLabelLabel.setHorizontalAlignment(JLabel.TRAILING); walletFilenameLabelLabel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 1; constraints.gridy = 4; constraints.weightx = 0.5; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_END; outputFilenamePanel.add(walletFilenameLabelLabel, constraints); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 2; constraints.gridy = 5; constraints.weightx = 0.05; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.CENTER; outputFilenamePanel.add(MultiBitTitledPanel.createStent(MultiBitTitledPanel.SEPARATION_BETWEEN_NAME_VALUE_PAIRS), constraints); outputFilenameLabel = new MultiBitLabel(outputFilename); outputFilenameLabel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 3; constraints.gridy = 4; constraints.weightx = 0.5; constraints.weighty = 0.3; constraints.gridwidth = 2; constraints.anchor = GridBagConstraints.LINE_START; outputFilenamePanel.add(outputFilenameLabel, constraints); JPanel filler0 = new JPanel(); filler0.setOpaque(false); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 5; constraints.gridy = 4; constraints.weightx = 100; constraints.weighty = 1; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_END; outputFilenamePanel.add(filler0, constraints); JPanel filler2 = new JPanel(); filler2.setOpaque(false); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 1; constraints.gridy = 5; constraints.weightx = 0.3; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; outputFilenamePanel.add(filler2, constraints); MultiBitLabel numberOfKeysLabelLabel = new MultiBitLabel(controller.getLocaliser().getString( "showImportPrivateKeysPanel.numberOfKeys.text")); numberOfKeysLabelLabel.setToolTipText(HelpContentsPanel.createTooltipText(controller.getLocaliser() .getString("showImportPrivateKeysPanel.numberOfKeys.tooltip"))); numberOfKeysLabelLabel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 1; constraints.gridy = 6; constraints.weightx = 0.5; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_END; outputFilenamePanel.add(numberOfKeysLabelLabel, constraints); JPanel filler3 = new JPanel(); filler3.setOpaque(false); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 2; constraints.gridy = 6; constraints.weightx = 0.1; constraints.weighty = 0.1; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; outputFilenamePanel.add(filler3, constraints); numberOfKeysLabel = new MultiBitLabel(" "); numberOfKeysLabel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 3; constraints.gridy = 6; constraints.weightx = 0.5; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; outputFilenamePanel.add(numberOfKeysLabel, constraints); MultiBitLabel replayDateLabelLabel = new MultiBitLabel(controller.getLocaliser().getString( "showImportPrivateKeysPanel.replayDate.text")); replayDateLabelLabel.setToolTipText(HelpContentsPanel.createTooltipText(controller.getLocaliser().getString("showImportPrivateKeysPanel.replayDate.tooltip"))); replayDateLabelLabel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 1; constraints.gridy = 7; constraints.weightx = 0.5; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_END; outputFilenamePanel.add(replayDateLabelLabel, constraints); replayDateLabel = new MultiBitLabel(" "); replayDateLabel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 3; constraints.gridy = 7; constraints.weightx = 0.5; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; outputFilenamePanel.add(replayDateLabel, constraints); JPanel filler4 = new JPanel(); filler4.setOpaque(false); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 1; constraints.gridy = 8; constraints.weightx = 0.3; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; outputFilenamePanel.add(filler4, constraints); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 3; constraints.gridy = 9; constraints.weightx = 0.5; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; outputFilenamePanel.add(chooseFilenameButton, constraints); JPanel filler5 = new JPanel(); filler5.setOpaque(false); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 1; constraints.gridy = 10; constraints.weightx = 0.3; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; outputFilenamePanel.add(filler5, constraints); return outputFilenamePanel; } private JPanel createPasswordPanel(int stentWidth) { // Do/do not password protect radios. MultiBitTitledPanel passwordProtectPanel = new MultiBitTitledPanel(controller.getLocaliser().getString( "showImportPrivateKeysPanel.password.title"), ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); GridBagConstraints constraints = new GridBagConstraints(); passwordInfoLabel = MultiBitTitledPanel.addLeftJustifiedTextAtIndent( controller.getLocaliser().getString("showImportPrivateKeysPanel.enterPassword"), 3, passwordProtectPanel); passwordInfoLabel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 1; constraints.gridy = 4; constraints.weightx = 0.3; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; passwordProtectPanel.add(MultiBitTitledPanel.createStent(stentWidth, ExportPrivateKeysPanel.STENT_HEIGHT), constraints); passwordPromptLabel1 = new MultiBitLabel(controller.getLocaliser().getString("showExportPrivateKeysPanel.passwordPrompt")); passwordPromptLabel1.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 1; constraints.gridy = 5; constraints.weightx = 0.3; constraints.weighty = 0.1; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_END; passwordProtectPanel.add(passwordPromptLabel1, constraints); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 2; constraints.gridy = 5; constraints.weightx = 0.05; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.CENTER; passwordProtectPanel.add(MultiBitTitledPanel.createStent(MultiBitTitledPanel.SEPARATION_BETWEEN_NAME_VALUE_PAIRS), constraints); passwordField1 = new JPasswordField(24); passwordField1.setMinimumSize(new Dimension(200, 20)); passwordField1.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 3; constraints.gridy = 5; constraints.weightx = 0.3; constraints.weighty = 0.6; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; passwordProtectPanel.add(passwordField1, constraints); passwordPromptLabel2 = new MultiBitLabel(controller.getLocaliser().getString("showImportPrivateKeysPanel.secondPassword")); passwordPromptLabel2.setVisible(false); passwordPromptLabel2.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 1; constraints.gridy = 6; constraints.weightx = 0.3; constraints.weighty = 0.1; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_END; passwordProtectPanel.add(passwordPromptLabel2, constraints); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 2; constraints.gridy = 6; constraints.weightx = 0.05; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.CENTER; passwordProtectPanel.add(MultiBitTitledPanel.createStent(MultiBitTitledPanel.SEPARATION_BETWEEN_NAME_VALUE_PAIRS), constraints); passwordField2 = new JPasswordField(24); passwordField2.setMinimumSize(new Dimension(200, 20)); passwordField2.setVisible(false); passwordField2.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 3; constraints.gridy = 6; constraints.weightx = 0.3; constraints.weighty = 0.6; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; passwordProtectPanel.add(passwordField2, constraints); JLabel filler3 = new JLabel(); filler3.setMinimumSize(new Dimension(3, 3)); filler3.setMaximumSize(new Dimension(3, 3)); filler3.setPreferredSize(new Dimension(3, 3)); filler3.setOpaque(false); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 1; constraints.gridy = 7; constraints.weightx = 0.1; constraints.weighty = 0.1; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.anchor = GridBagConstraints.CENTER; passwordProtectPanel.add(filler3, constraints); unlockButton = new MultiBitButton(controller.getLocaliser().getString("showImportPrivateKeysPanel.unlock.text")); unlockButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { setMessageText1(" "); try { readInImportFileAndUpdateDetails(); } catch (KeyCrypterException ede) { setMessageText1(controller.getLocaliser().getString("importPrivateKeysSubmitAction.privateKeysUnlockFailure", new Object[] { ede.getMessage() })); } } }); unlockButton.setToolTipText(HelpContentsPanel.createTooltipText(controller.getLocaliser().getString("showImportPrivateKeysPanel.unlock.tooltip"))); unlockButton.setEnabled(false); unlockButton.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 3; constraints.gridy = 8; constraints.weightx = 0.3; constraints.weighty = 0.6; constraints.gridwidth = 3; constraints.anchor = GridBagConstraints.LINE_START; passwordProtectPanel.add(unlockButton, constraints); JPanel filler5 = new JPanel(); filler5.setOpaque(false); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 1; constraints.gridy = 9; constraints.weightx = 0.3; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; passwordProtectPanel.add(filler3, constraints); return passwordProtectPanel; } private JPanel createButtonPanel() { JPanel buttonPanel = new JPanel(); buttonPanel.setOpaque(false); FlowLayout flowLayout = new FlowLayout(); flowLayout.setAlignment(FlowLayout.LEADING); buttonPanel.setLayout(flowLayout); buttonPanel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); importPrivateKeysSubmitAction = new ImportPrivateKeysSubmitAction(this.bitcoinController, mainFrame, this, ImageLoader.createImageIcon(ImageLoader.IMPORT_PRIVATE_KEYS_ICON_FILE), walletPasswordField, passwordField1, passwordField2); MultiBitButton submitButton = new MultiBitButton(importPrivateKeysSubmitAction, controller); submitButton.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); buttonPanel.add(submitButton); return buttonPanel; } @Override public void displayView(DisplayHint displayHint) { // If it is a wallet transaction change no need to update. if (DisplayHint.WALLET_TRANSACTIONS_HAVE_CHANGED == displayHint) { return; } walletFilenameLabel.setText(this.bitcoinController.getModel().getActiveWalletFilename()); walletDescriptionLabel.setText(this.bitcoinController.getModel().getActivePerWalletModelData().getWalletDescription()); boolean walletPasswordRequired = false; if (this.bitcoinController.getModel().getActiveWallet() != null && this.bitcoinController.getModel().getActiveWallet().getEncryptionType() == EncryptionType.ENCRYPTED_SCRYPT_AES) { walletPasswordRequired = true; } enableWalletPassword(walletPasswordRequired); walletBusyChange(this.bitcoinController.getModel().getActivePerWalletModelData().isBusy()); if (outputFilename == null || "".equals(outputFilename)) { outputFilenameLabel.setText(controller.getLocaliser().getString("showImportPrivateKeysPanel.noFileSelected")); } messageLabel1.setText(" "); messageLabel2.setText(" "); } @Override public void navigateAwayFromView() { } private void chooseFile(MultiBitButton callingButton) { JFileChooser.setDefaultLocale(controller.getLocaliser().getLocale()); fileChooser = new JFileChooser(); fileChooser.setLocale(controller.getLocaliser().getLocale()); fileChooser.setDialogTitle(chooseFilenameButtonText); adjustedFont = FontSizer.INSTANCE.getAdjustedDefaultFont(); if (adjustedFont != null) { setFileChooserFont(new Container[] {fileChooser}); } fileChooser.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); fileChooser.addChoosableFileFilter(multiBitFileChooser); //fileChooser.addChoosableFileFilter(myWalletPlainFileChooser); //fileChooser.addChoosableFileFilter(myWalletEncryptedFileChooser); fileChooser.setAcceptAllFileFilterUsed(false); fileChooser.setFileFilter(multiBitFileChooser); if (outputFilename != null && !"".equals(outputFilename)) { fileChooser.setCurrentDirectory(new File(outputFilename)); fileChooser.setSelectedFile(new File(outputFilename)); } else { if (this.bitcoinController.getModel().getActiveWalletFilename() != null) { fileChooser.setCurrentDirectory(new File(this.bitcoinController.getModel().getActiveWalletFilename())); } String defaultFileName = fileChooser.getCurrentDirectory().getAbsoluteFile() + File.separator + controller.getLocaliser().getString("saveWalletAsView.untitled") + "." + BitcoinModel.PRIVATE_KEY_FILE_EXTENSION; fileChooser.setSelectedFile(new File(defaultFileName)); } try { callingButton.setEnabled(false); mainFrame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); fileChooser.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); int returnVal = fileChooser.showOpenDialog(mainFrame); if (returnVal == JFileChooser.APPROVE_OPTION) { numberOfKeysLabel.setText(" "); replayDateLabel.setText(" "); passwordField1.setText(""); File file = fileChooser.getSelectedFile(); if (file != null) { outputFilename = file.getAbsolutePath(); outputFilenameLabel.setText(outputFilename); if (multiBitFileChooser.accept(file)) { try { String firstLine = readFirstLineInFile(file); if (firstLine != null && firstLine.startsWith(encrypterDecrypter.getOpenSSLMagicText())) { // File is encrypted. enableImportFilePasswordPanel(true); passwordField1.requestFocusInWindow(); } else { // File is not encrypted. enableImportFilePasswordPanel(false); readInImportFileAndUpdateDetails(); } } catch (IOException e) { setMessageText1(controller.getLocaliser().getString( "importPrivateKeysSubmitAction.privateKeysImportFailure", new Object[] { e.getClass().getName() + " " + e.getMessage() })); } catch (KeyCrypterException e) { // TODO User may not have entered a password yet so // password incorrect is ok at this stage. // Other errors indicate a more general problem with // the // import. setMessageText1(controller.getLocaliser().getString( "importPrivateKeysSubmitAction.privateKeysImportFailure", new Object[] { e.getClass().getName() + " " + e.getMessage() })); } } } } } finally { mainFrame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); callingButton.setEnabled(true); } } private void enableSecondPasswordPanel(boolean enablePanel) { passwordField2.setEnabled(enablePanel); passwordPromptLabel2.setEnabled(enablePanel); passwordField2.setVisible(enablePanel); passwordPromptLabel2.setVisible(enablePanel); } private void enableImportFilePasswordPanel(boolean enableImportFilePanel) { if (enableImportFilePanel) { // Enable the import file password panel. passwordPromptLabel1.setEnabled(true); passwordField1.setEnabled(true); unlockButton.setEnabled(true); passwordInfoLabel.setForeground(Color.BLACK); } else { // Disable the import file password panel. passwordPromptLabel1.setEnabled(false); passwordField1.setEnabled(false); unlockButton.setEnabled(false); passwordInfoLabel.setForeground(Color.GRAY); } } private void enableWalletPassword(boolean enableWalletPassword) { if (enableWalletPassword) { // Enable the wallet password. walletPasswordField.setEnabled(true); walletPasswordPromptLabel.setEnabled(true); } else { // Disable the wallet password. walletPasswordField.setEnabled(false); walletPasswordPromptLabel.setEnabled(false); } } /** * Read in the import file and show the file details. * @throws KeyCrypterException * @throws PrivateKeysHandlerException */ private void readInImportFileAndUpdateDetails() throws PrivateKeysHandlerException, KeyCrypterException { // Update number of keys and earliest date. try { File file = new File(outputFilename); if (multiBitFileChooser.accept(file)) { // Read in contents of file. setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); PrivateKeysHandler privateKeysHandler = new PrivateKeysHandler(this.bitcoinController.getModel().getNetworkParameters()); Collection<PrivateKeyAndDate> privateKeyAndDates = privateKeysHandler.readInPrivateKeys(new File(outputFilename), CharBuffer.wrap(passwordField1.getPassword())); numberOfKeysLabel.setText("" + privateKeyAndDates.size()); Date replayDate = privateKeysHandler.calculateReplayDate(privateKeyAndDates, this.bitcoinController.getModel() .getActiveWallet()); if (replayDate == null) { replayDateLabel.setText(controller.getLocaliser().getString( "showImportPrivateKeysPanel.thereWereMissingKeyDates")); } else { replayDateLabel.setText(DateFormat.getDateInstance(DateFormat.MEDIUM, controller.getLocaliser().getLocale()) .format(replayDate)); } setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } } finally { setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } } public void requestSecondPassword() { enableSecondPasswordPanel(true); setMessageText1(controller.getLocaliser().getString("importPrivateKeysSubmitAction.enterTheSecondPassword")); } public String getOutputFilename() { return outputFilename; } public void clearPasswords() { walletPasswordField.setText(""); passwordField1.setText(""); if (passwordField2 != null) { passwordField2.setText(""); } } public void setMessageText1(String message1) { if (messageLabel1 != null) { messageLabel1.setText(message1); } } public String getMessageText1() { if (messageLabel1 != null) { return messageLabel1.getText(); } else { return ""; } } public void setMessageText2(String message2) { if (messageLabel2 != null) { messageLabel2.setText(message2); } } public String getMessageText2() { if (messageLabel2 != null) { return messageLabel2.getText(); } else { return ""; } } private String readFirstLineInFile(File file) throws IOException { BufferedReader reader = new BufferedReader(new FileReader(file)); return reader.readLine(); } @Override public Icon getViewIcon() { return ImageLoader.createImageIcon(ImageLoader.IMPORT_PRIVATE_KEYS_ICON_FILE); } @Override public String getViewTitle() { return controller.getLocaliser().getString("showImportPrivateKeysAction.text"); } @Override public String getViewTooltip() { return controller.getLocaliser().getString("showImportPrivateKeysAction.tooltip"); } @Override public View getViewId() { return View.SHOW_IMPORT_PRIVATE_KEYS_VIEW; } // Used in testing. public MultiBitButton getUnlockButton() { return unlockButton; } public ImportPrivateKeysSubmitAction getImportPrivateKeysSubmitAction() { return importPrivateKeysSubmitAction; } public void setOutputFilename(String outputFilename) { this.outputFilename = outputFilename; } public void setImportFilePassword(CharSequence password) { passwordField1.setText(password.toString()); } public void setWalletPassword(CharSequence password) { walletPasswordField.setText(password.toString()); } public boolean isWalletPasswordFieldEnabled() { return walletPasswordField.isEnabled(); } @Override public void walletBusyChange(boolean newWalletIsBusy) { // Update the enable status of the action to match the wallet busy status. if (this.bitcoinController.getModel().getActivePerWalletModelData().isBusy()) { // Wallet is busy with another operation that may change the private keys - Action is disabled. importPrivateKeysSubmitAction.putValue(Action.SHORT_DESCRIPTION, HelpContentsPanel.createTooltipText(controller.getLocaliser().getString("multiBitSubmitAction.walletIsBusy", new Object[]{controller.getLocaliser().getString(this.bitcoinController.getModel().getActivePerWalletModelData().getBusyTaskKey())}))); importPrivateKeysSubmitAction.setEnabled(false); } else { // Enable importPrivateKeysSubmitAction.putValue(Action.SHORT_DESCRIPTION, HelpContentsPanel.createTooltipText(controller.getLocaliser().getString("importPrivateKeysSubmitAction.tooltip"))); importPrivateKeysSubmitAction.setEnabled(true); } } private void setFileChooserFont(Component[] comp) { for (int x = 0; x < comp.length; x++) { if (comp[x] instanceof Container) setFileChooserFont(((Container) comp[x]).getComponents()); try { comp[x].setFont(adjustedFont); } catch (Exception e) { }// do nothing } } }