org.kapott.hbci.comm.CommPinTan.java Source code

Java tutorial

Introduction

Here is the source code for org.kapott.hbci.comm.CommPinTan.java

Source

/*  $Id: CommPinTan.java,v 1.1 2011/05/04 22:37:50 willuhn Exp $
    
This file is part of HBCI4Java
Copyright (C) 2001-2008  Stefan Palme
    
HBCI4Java 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 2 of the License, or
(at your option) any later version.
    
HBCI4Java 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package org.kapott.hbci.comm;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.kapott.hbci.callback.HBCICallback;
import org.kapott.hbci.exceptions.CanNotParseMessageException;
import org.kapott.hbci.exceptions.HBCI_Exception;
import org.kapott.hbci.exceptions.ParseErrorException;
import org.kapott.hbci.manager.HBCIUtils;
import org.kapott.hbci.protocol.Message;
import org.kapott.hbci.rewrite.Rewrite;
import org.kapott.hbci.status.HBCIMsgStatus;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

@Slf4j
public final class CommPinTan {

    public final static String ENCODING = "ISO-8859-1";
    /**
     * Timeout fuer HTTP connect in Millisekunden.
     */
    private final static int HTTP_CONNECT_TIMEOUT = 60 * 1000;
    /**
     * Timeout fuer HTTP Read in Millisekunden.
     */
    private final static int HTTP_READ_TIMEOUT = 5 * HTTP_CONNECT_TIMEOUT;
    private HBCICallback callback;
    private URL url;
    private HttpURLConnection conn;

    public CommPinTan(String host, HBCICallback callback) {
        this.callback = callback;

        try {
            log.info("connect: " + host);
            this.url = new URL(host);
        } catch (Exception e) {
            throw new HBCI_Exception(HBCIUtils.getLocMsg("EXCMSG_CONNERR"), e);
        }
    }

    public CommPinTan withProxy(String proxyHost, String proxyUser, String proxyPass) {
        if (proxyHost != null) {
            String[] proxyData = proxyHost.split(":");
            if (proxyData.length == 2) {
                log.info("HTTPS connections will be made using proxy " + proxyData[0] + "(Port " + proxyData[1]
                        + ")");

                Properties sysProps = System.getProperties();
                sysProps.put("https.proxyHost", proxyData[0]);
                sysProps.put("https.proxyPort", proxyData[1]);

                log.debug("initializing HBCI4Java proxy authentication callback");
                Authenticator.setDefault(new PinTanProxyAuthenticator(proxyUser, proxyPass));
            }
        }
        return this;
    }

    public Message pingpong(Message message, String messageName, List<Rewrite> rewriters, HBCIMsgStatus msgStatus) {
        log.debug("---------------- request ----------------");
        String rawMsg = message.toString(0);
        if (log.isTraceEnabled()) {
            Arrays.stream(rawMsg.split("'")).forEach(s -> log.trace(s));
        }

        // ausgehende nachricht versenden
        callback.status(HBCICallback.STATUS_MSG_SEND, null);
        callback.status(HBCICallback.STATUS_MSG_RAW_SEND, rawMsg);
        ping(message);

        // nachricht empfangen
        callback.status(HBCICallback.STATUS_MSG_RECV, null);
        rawMsg = pong();
        callback.status(HBCICallback.STATUS_MSG_RAW_RECV, rawMsg);

        log.debug("---------------- response ----------------");
        if (log.isTraceEnabled()) {
            Arrays.stream(rawMsg.split("'")).forEach(s -> log.trace(s));
        }

        Message responseMessage;
        try {
            // alle rewriter fr verschlsselte nachricht durchlaufen
            for (Rewrite rewriter1 : rewriters) {
                rawMsg = rewriter1.incomingCrypted(rawMsg, msgStatus, messageName);
            }
            // versuche, nachricht als verschlsselte nachricht zu parsen
            callback.status(HBCICallback.STATUS_MSG_PARSE, "CryptedRes");
            try {
                log.debug("trying to parse message as crypted message");
                responseMessage = new Message("CryptedRes", rawMsg, message.getDocument(), Message.DONT_CHECK_SEQ,
                        true);
            } catch (ParseErrorException e) {
                // wenn das schiefgeht...
                log.debug("message seems not to be encrypted; tring to parse it as " + message.getName()
                        + "Res message");

                // alle rewriter durchlaufen, um nachricht evtl. als unverschlsselte rawMsg zu parsen
                //                message.set("_origSignedMsg", st);
                for (Rewrite rewriter1 : rewriters) {
                    rawMsg = rewriter1.incomingClearText(rawMsg);
                }

                log.trace(rawMsg);
                // versuch, nachricht als unverschlsselte rawMsg zu parsen
                callback.status(HBCICallback.STATUS_MSG_PARSE, message.getName() + "Res");
                responseMessage = new Message(message.getName() + "Res", rawMsg, message.getDocument(),
                        Message.CHECK_SEQ, true);
            }
        } catch (Exception ex) {
            throw new CanNotParseMessageException(HBCIUtils.getLocMsg("EXCMSG_CANTPARSE"), rawMsg, ex);
        }

        return responseMessage;
    }

    private void ping(Message msg) {
        try {
            byte[] b = Base64.encodeBase64(msg.toString(0).getBytes(ENCODING));

            conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(HTTP_CONNECT_TIMEOUT);
            conn.setReadTimeout(HTTP_READ_TIMEOUT);
            conn.setDoOutput(true);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type", "application/octet-stream");
            conn.setFixedLengthStreamingMode(b.length);

            conn.connect();
            OutputStream out = conn.getOutputStream();
            out.write(b);
            out.flush();
            out.close();
        } catch (Exception e) {
            HBCI_Exception he = new HBCI_Exception(HBCIUtils.getLocMsg("EXCMSG_SENDERR"), e);
            he.setFatal(true); // Abbruch. Auch dann, wenn es ein anonymer BPD-Abruf war
            throw he;
        }
    }

    private String pong() {
        try {
            byte[] b = new byte[1024];
            StringBuilder ret = new StringBuilder();

            int msgsize = conn.getContentLength();
            int num;

            InputStream i = conn.getInputStream();

            while (msgsize != 0 && (num = i.read(b)) > 0) {
                ret.append(new String(b, 0, num, ENCODING));
                msgsize -= num;
            }

            conn.disconnect();
            return new String(Base64.decodeBase64(ret.toString()), ENCODING);
        } catch (Exception e) {
            // Die hier marieren wir nicht als fatal - ich meine mich zu erinnern,
            // dass es Banken gibt, die einen anonymen BPD-Abruf mit einem HTTP-Fehlercode quittieren
            throw new HBCI_Exception(HBCIUtils.getLocMsg("EXCMSG_RECVERR"), e);
        }
    }

}