/* * Kontalk Java client * Copyright (C) 2016 Kontalk Devteam <devteam@kontalk.org> * * 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 org.kontalk.system; import java.io.IOException; import java.util.Observable; import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.kontalk.client.EndpointServer; import org.kontalk.client.PrivateKeyReceiver; import org.kontalk.crypto.PGPUtils; import org.kontalk.misc.Callback; import org.kontalk.misc.KonException; import org.kontalk.model.Account; import org.kontalk.util.EncodingUtils; /** * Import and set user account from various sources. * @author Alexander Bikadorov {@literal <bikaejkb@mail.tu-berlin.de>} */ public final class AccountImporter extends Observable implements Callback.Handler<String>{ private static final Logger LOGGER = Logger.getLogger(AccountImporter.class.getName()); private static final String PRIVATE_KEY_FILENAME = "kontalk-private.asc"; private final Account mAccount; private char[] mPassword = null; private boolean mAborted = false; AccountImporter(Account account) { mAccount = account; } public void fromZipFile(String zipFilePath, char[] password) { // read key files byte[] privateKeyData; try (ZipFile zipFile = new ZipFile(zipFilePath)) { privateKeyData = readBytesFromZip(zipFile, PRIVATE_KEY_FILENAME); } catch (IOException ex) { LOGGER.log(Level.WARNING, "can't open zip archive: ", ex); this.changed(new KonException(KonException.Error.IMPORT_ARCHIVE, ex)); return; } catch (KonException ex) { this.changed(ex); return; } this.set(privateKeyData, password); } // note: with disarming if needed private static byte[] readBytesFromZip(ZipFile zipFile, String filename) throws KonException { ZipEntry zipEntry = zipFile.getEntry(filename); byte[] bytes; try { bytes = PGPUtils.mayDisarm(zipFile.getInputStream(zipEntry)); } catch (IOException ex) { LOGGER.log(Level.WARNING, "can't read key file from archive: ", ex); throw new KonException(KonException.Error.IMPORT_READ_FILE, ex); } return bytes; } // TODO unused public void fromServer(String host, int port, boolean validateCertificate, String token, char[] password) { mPassword = password; // send private key request EndpointServer server = new EndpointServer(host, port); PrivateKeyReceiver receiver = new PrivateKeyReceiver(this); mAborted = false; receiver.sendRequest(server, validateCertificate, token); // wait for response... continue with handle callback } public void abort() { // receiver will always terminate after some time, just ignore response mAborted = true; } @Override public void handle(Callback<String> callback) { if (mAborted) return; if (callback.exception.isPresent()) { this.changed(callback.exception); return; } this.set(EncodingUtils.base64ToBytes(callback.value), mPassword); } private void set(byte[] privateKeyData, char[] password) { try { mAccount.setAccount(privateKeyData, password); } catch (KonException ex) { this.changed(ex); return; } // report success this.changed(null); } private void changed(Object arg) { this.setChanged(); this.notifyObservers(arg); } }