org.panbox.desktop.common.gui.PairNewDeviceDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.panbox.desktop.common.gui.PairNewDeviceDialog.java

Source

/*
 * 
 *               Panbox - encryption for cloud storage 
 *      Copyright (C) 2014-2015 by Fraunhofer SIT and Sirrix AG 
 *
 * 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/>.
 * 
 * Additonally, third party code may be provided with notices and open source
 * licenses from communities and third parties that govern the use of those
 * portions, and any licenses granted hereunder do not alter any rights and
 * obligations you may have under such open source licenses, however, the
 * disclaimer of warranty and limitation of liability provisions of the GPLv3 
 * will apply to all the product.
 * 
 */
package org.panbox.desktop.common.gui;

import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import ezvcard.util.org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.panbox.Settings;
import org.panbox.core.crypto.randomness.SecureRandomWrapper;
import org.panbox.core.exception.RandomDataGenerationException;
import org.panbox.core.pairing.PAKCorePairingHandler;
import org.panbox.core.pairing.PairingInformation;
import org.panbox.core.pairing.PairingNotificationReceiver;
import org.panbox.core.pairing.bluetooth.BluetoothPairingInformation;
import org.panbox.core.pairing.network.NetworkPairingInformation;
import org.panbox.desktop.common.PanboxClient;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.net.InetAddress;
import java.text.MessageFormat;
import java.util.*;
import java.util.Timer;

public class PairNewDeviceDialog extends javax.swing.JDialog implements PairingNotificationReceiver {

    private static final long serialVersionUID = -6493970152852384445L;

    protected static final Logger logger = Logger.getLogger("org.panbox");

    private static ResourceBundle bundle = ResourceBundle.getBundle("org.panbox.desktop.common.gui.Messages",
            Settings.getInstance().getLocale());

    private final PanboxClient client;
    private final PairingInformation pInfo;
    private Timer timer;
    private TimerTask refreshTimeout;
    private int timeout;
    private String pairingPassword = null;

    public PairNewDeviceDialog(JFrame parent, PanboxClient client, PairingInformation pInfo) {
        super(parent, true);
        initComponents();

        this.client = client;
        this.pInfo = pInfo;

        pairingModeSelectionComboBoxActionPerformed(new ActionEvent(this, 0, "init"));

        setVisible(true);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed"
    // desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        pairingPanel = new javax.swing.JPanel();
        pairingQrCodePanel = new javax.swing.JPanel();
        pairingPasswordField = new javax.swing.JTextField();
        pairingModeSelectionComboBox = new javax.swing.JComboBox<>();
        cancelPairingButton = new javax.swing.JButton();
        statusInfoLabel = new javax.swing.JLabel();
        qrCode = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle(bundle.getString("client.deviceList.devicepairing.title"));
        setResizable(false);

        pairingPanel.setMaximumSize(new java.awt.Dimension(390, 330));
        pairingPanel.setMinimumSize(new java.awt.Dimension(390, 330));

        pairingQrCodePanel.setLayout(new java.awt.GridLayout(1, 1));
        pairingQrCodePanel.add(qrCode);

        pairingPasswordField.setText("");
        pairingPasswordField.setEditable(false);

        pairingModeSelectionComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(
                new String[] { bundle.getString("client.deviceList.devicepairing.slave"),
                        bundle.getString("client.deviceList.devicepairing.master") }));
        pairingModeSelectionComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                pairingModeSelectionComboBoxActionPerformed(evt);
            }
        });

        statusInfoLabel.setText("");

        javax.swing.GroupLayout pairingPanelLayout = new javax.swing.GroupLayout(pairingPanel);
        pairingPanel.setLayout(pairingPanelLayout);
        pairingPanelLayout.setHorizontalGroup(pairingPanelLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(pairingPanelLayout.createSequentialGroup().addContainerGap()
                        .addGroup(pairingPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(pairingModeSelectionComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        Short.MAX_VALUE)
                                .addComponent(pairingQrCodePanel, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(pairingPasswordField, javax.swing.GroupLayout.DEFAULT_SIZE, 354,
                                        Short.MAX_VALUE))
                        .addContainerGap()));
        pairingPanelLayout.setVerticalGroup(pairingPanelLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(pairingPanelLayout.createSequentialGroup().addContainerGap()
                        .addComponent(pairingQrCodePanel, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(pairingPasswordField, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(pairingModeSelectionComboBox, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap(331, Short.MAX_VALUE)));

        cancelPairingButton.setText(bundle.getString("client.cancel"));
        cancelPairingButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelPairingButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup().addContainerGap()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(pairingPanel, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addGroup(layout.createSequentialGroup()
                                        .addComponent(statusInfoLabel, javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                        .addComponent(cancelPairingButton)))
                        .addContainerGap()));
        layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup().addContainerGap()
                        .addComponent(pairingPanel, javax.swing.GroupLayout.DEFAULT_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(cancelPairingButton).addComponent(statusInfoLabel))
                        .addContainerGap()));

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void pairingModeSelectionComboBoxActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_pairingDeviceSelectionComboBoxActionPerformed
        stopRefreshTimer();
        client.stopDevicePairing();

        char[] keyPassword = null;

        if (evt != null && !evt.getActionCommand().equals("init") && isMasterPairing()) {
            keyPassword = PasswordEnterDialog.invoke(PasswordEnterDialog.PermissionType.DEVICE);
            if (keyPassword == null || keyPassword.length == 0) {
                JOptionPane.showMessageDialog(null, bundle.getString("PairNewDeviceDialog.cantPairWithEmptyPW"));
            }
        }

        generateNewPasswordAndUpdateDialog();
        startNewRefreshTimer();
        if (isMasterPairing()) {
            // Master will be paired!
            client.runMasterPairingOnPairingHandle(pInfo, pairingPassword, this, keyPassword);
        } else {
            // Slave will be paired!
            client.runSlavePairingOnPairingHandle(pInfo, pairingPassword, this);
        }
        if (keyPassword != null) {
            Arrays.fill(keyPassword, (char) 0);
        }
    }// GEN-LAST:event_pairingDeviceSelectionComboBoxActionPerformed

    private void cancelPairingButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_cancelPairingButtonActionPerformed
        this.dispose();
    }// GEN-LAST:event_cancelPairingButtonActionPerformed

    private void generateNewPasswordAndUpdateDialog() {
        try {
            SecureRandomWrapper secureRandom = SecureRandomWrapper.getInstance();
            byte[] password = new byte[16];
            secureRandom.nextBytes(password);
            pairingPassword = Base64.encodeBase64String(password);
            String addrStr = null;
            if (pInfo instanceof NetworkPairingInformation) {
                NetworkPairingInformation npi = (NetworkPairingInformation) pInfo;
                addrStr = ((InetAddress) npi.getPairingAddress()).getHostAddress();
            } else if (pInfo instanceof BluetoothPairingInformation) {
                BluetoothPairingInformation bpi = (BluetoothPairingInformation) pInfo;
                addrStr = bpi.getPairingAddress().toString(); // String address
            }

            pairingPasswordField.setText(addrStr + ":" + pairingPassword);

            BitMatrix matrix;
            com.google.zxing.Writer writer = new QRCodeWriter();
            matrix = writer.encode(pairingPasswordField.getText(), com.google.zxing.BarcodeFormat.QR_CODE, 330,
                    330);
            BufferedImage qrCodeImage = MatrixToImageWriter.toBufferedImage(matrix);
            qrCode.setIcon(new ImageIcon(qrCodeImage));
        } catch (WriterException e) {
            logger.fatal("PairNewDeviceDialog : Could not create the QR-Code from zxing library.", e);
        } catch (RandomDataGenerationException e) {
            logger.fatal("PairNewDeviceDialog : Could not obtain secure random from RNG for pairing password.", e);
        }
    }

    private boolean isMasterPairing() {
        if (pairingModeSelectionComboBox.getSelectedItem()
                .equals(bundle.getObject("client.deviceList.devicepairing.master"))) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void dispose() {
        super.dispose();
        client.stopDevicePairing();
        stopRefreshTimer();
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton cancelPairingButton;
    private javax.swing.JComboBox<String> pairingModeSelectionComboBox;
    private javax.swing.JPanel pairingPanel;
    private javax.swing.JTextField pairingPasswordField;
    private javax.swing.JPanel pairingQrCodePanel;
    private javax.swing.JLabel qrCode;
    private javax.swing.JLabel statusInfoLabel;

    // End of variables declaration//GEN-END:variables

    @Override
    public void inform(PairingResult result) {
        logger.info("PairNewDeviceDialog : Received result from pairing: " + result);
        this.dispose();
        switch (result) {
        case SUCCESS:
            JOptionPane.showMessageDialog(null,
                    bundle.getString("client.deviceList.devicepairing.resultmsg.success"));
            break;
        case TIMEOUT:
            JOptionPane.showMessageDialog(null,
                    bundle.getString("client.deviceList.devicepairing.resultmsg.timeout"));
            break;
        case FAILED:
            JOptionPane.showMessageDialog(null,
                    bundle.getString("client.deviceList.devicepairing.resultmsg.failed"));
            break;
        case QUITEFAILED:
            // no message since error message has been shown already.
            break;
        default:
            break;
        }
    }

    private void startNewRefreshTimer() {
        logger.debug("PairNewDeviceDialog : startNewRefreshTimer : Starting new refresh timeout timer.");
        timeout = PAKCorePairingHandler.PAIRING_TIMEOUT / 1000;
        refreshTimeout = new TimerTask() {

            @Override
            public void run() {
                logger.debug("Timeout timer started... Left: " + timeout + " seconds.");
                MessageFormat formatter = new MessageFormat("", Settings.getInstance().getLocale());
                formatter.applyPattern(bundle.getString("client.deviceList.devicepairing.timeoutstatusbar"));
                statusInfoLabel.setText(formatter.format(new Object[] { timeout }));
                statusInfoLabel.invalidate();
                timeout--;
            }
        };
        timer = new Timer();
        timer.schedule(refreshTimeout, new Date(), 1000);
    }

    private void stopRefreshTimer() {
        if (timer != null) {
            logger.debug("PairNewDeviceDialog : stopRefreshTimer : timer will be stopped NOW.");
            timer.cancel();
            statusInfoLabel.setText("");
            statusInfoLabel.invalidate();
        } else {
            logger.debug("PairNewDeviceDialog : stopRefreshTimer : timer is already stopped.");
        }
    }
}