/* * Kontalk Java client * Copyright (C) 2016 Kontalk Devteam <[email protected]> * * 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.client; import java.io.IOException; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.util.SuccessCallback; import org.jivesoftware.smackx.iqregister.packet.Registration; import org.jivesoftware.smackx.xdata.Form; import org.jivesoftware.smackx.xdata.FormField; import org.jivesoftware.smackx.xdata.packet.DataForm; import org.kontalk.misc.Callback; /** * Send request and listen to response for private data over * 'jabber:iq:register' namespace. * * Temporary server connection is established when requesting key. * * TODO not used * * @author Alexander Bikadorov {@literal <[email protected]>} */ public final class PrivateKeyReceiver implements SuccessCallback<IQ> { private static final Logger LOGGER = Logger.getLogger(PrivateKeyReceiver.class.getName()); private static final String FORM_TYPE_VALUE = "http://kontalk.org/protocol/register#privatekey"; private static final String FORM_TOKEN_VAR = "token"; private final Callback.Handler<String> mHandler; private KonConnection mConn = null; public PrivateKeyReceiver(Callback.Handler<String> handler) { mHandler = handler; } public void sendRequest(EndpointServer server, boolean validateCertificate, final String registrationToken) { // create connection mConn = new KonConnection(server, validateCertificate); Thread thread = new Thread("Private Key Request") { @Override public void run() { PrivateKeyReceiver.this.sendRequestAsync(registrationToken); } }; thread.setDaemon(true); thread.start(); } private void sendRequestAsync(String registrationToken) { // connect try { mConn.connect(); } catch (XMPPException | SmackException | IOException | InterruptedException ex) { LOGGER.log(Level.WARNING, "can't connect to "+mConn.getServer(), ex); mHandler.handle(new Callback<>(ex)); return; } Registration iq = new Registration(); iq.setType(IQ.Type.set); iq.setTo(mConn.getXMPPServiceDomain()); Form form = new Form(DataForm.Type.submit); // form type field FormField type = new FormField(FormField.FORM_TYPE); type.setType(FormField.Type.hidden); type.addValue(FORM_TYPE_VALUE); form.addField(type); // token field FormField fieldKey = new FormField(FORM_TOKEN_VAR); fieldKey.setLabel("Registration token"); fieldKey.setType(FormField.Type.text_single); fieldKey.addValue(registrationToken); form.addField(fieldKey); iq.addExtension(form.getDataFormToSend()); mConn.sendIqRequestAsync(iq) .onSuccess(this) .onError(exception -> mHandler.handle(new Callback<>(exception))); } @Override public void onSuccess(IQ packet) { LOGGER.info("response: "+packet); mConn.disconnect(); if (!(packet instanceof IQ)) { LOGGER.warning("response not an IQ packet"); finish(null); return; } IQ iq = (IQ) packet; if (iq.getType() != IQ.Type.result) { LOGGER.warning("ignoring response with IQ type: "+iq.getType()); this.finish(null); return; } DataForm response = iq.getExtension(DataForm.ELEMENT, DataForm.NAMESPACE); if (response == null) { this.finish(null); return; } String token = null; List<FormField> fields = response.getFields(); for (FormField field : fields) { if ("token".equals(field.getVariable())) { token = field.getValues().get(0).toString(); break; } } this.finish(token); } private void finish(String token) { mHandler.handle(token == null ? new Callback<>() : new Callback<>(token)); } }