/* $Id: InfoPointConnector.java,v 1.1 2011/05/04 22:37:46 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.manager; import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; import java.util.Enumeration; import java.util.List; import java.util.Properties; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.kapott.hbci.callback.HBCICallback; import org.kapott.hbci.comm.Comm; import org.kapott.hbci.passport.HBCIPassportInternal; import org.w3c.dom.Document; import org.w3c.dom.Element; // TODO: auch r�ckmeldungen vom InfoPoint-Server entgegennehmen und auswerten public class InfoPointConnector { private URL url; public InfoPointConnector() { String _url=HBCIUtils.getParam("infoPoint.url", "http://hbci4java.kapott.org/infoPoint"); HBCIUtils.log("configuring InfoPointer-Server with "+_url, HBCIUtils.LOG_INFO); try { this.url=new URL(_url); } catch (MalformedURLException e) { throw new RuntimeException(e); } } private Element properties2XML(Document doc, String elemName, Properties props) { Element elem=doc.createElement(elemName); for (Enumeration e=props.keys(); e.hasMoreElements(); ) { String key=(String)e.nextElement(); Element paramElem=doc.createElement("param"); paramElem.setAttribute("name", key); paramElem.setAttribute("value", props.getProperty(key)); elem.appendChild(paramElem); } return elem; } private String prepareXMLDocument(String xmlType, Properties passportData, Properties msgData) { try { DocumentBuilderFactory fac=DocumentBuilderFactory.newInstance(); fac.setIgnoringComments(true); fac.setValidating(false); DocumentBuilder builder=fac.newDocumentBuilder(); Document doc=builder.newDocument(); // xml-dokument zusammenbauen Element rootElem=doc.createElement(xmlType); doc.appendChild(rootElem); // passport data Element passElem=properties2XML(doc, "passport", passportData); rootElem.appendChild(passElem); // sent message data Properties sentData=new Properties(); for (Enumeration e=msgData.keys(); e.hasMoreElements(); ) { String key=(String)e.nextElement(); if (key.startsWith("orig_")) { if (key.indexOf(".ProcPrep.")!=-1) { String value=msgData.getProperty(key); if (key.endsWith(".lang")) { sentData.setProperty("language", value); } else if (key.endsWith(".prodName")) { sentData.setProperty("productName", value); } else if (key.endsWith(".prodVersion")) { sentData.setProperty("productVersion", value); } } } } Element sentElem=properties2XML(doc, "sent", sentData); rootElem.appendChild(sentElem); // received message data // extract BPD from original message String msg_st=msgData.getProperty("_msg"); int len=msg_st.length(); int startpos=msg_st.indexOf("'HIBPA:")+1; int posi=startpos; char prevDelimiter='\''; List<String> bpdSegCodes=Arrays.asList(new String[] {"HIBPA", "HIKOM", "HISHV", "HIKPV"}); String bpd_st=""; while (true) { int delimpos=HBCIUtilsInternal.getPosiOfNextDelimiter(msg_st,posi); if (prevDelimiter=='\'') { // wir sind gerade beim beginn eines neuen segmentes, also // den segcode ueberpruefen, ob wir tatsaechlich noch innerhalb // der BPD sind String segCode=msg_st.substring(posi,delimpos); if (!bpdSegCodes.contains(segCode)) { // segcode ist kein einfaches bpd-segment, kann also // hoechstens noch ein parameter-segment sein, das ebenfalls // zu den BPD gehoeren wuerde if (!(segCode.length()==6 && segCode.charAt(1)=='I' && segCode.charAt(5)=='S')) { // auch kein parameter-segment, also sind die BPD bereits zu ende bpd_st=msg_st.substring(startpos, posi); break; } } } // jetzt den gerade gefundenen delimiter merken // und posi erh�hen if (delimpos<len) { prevDelimiter=msg_st.charAt(delimpos); posi=delimpos+1; } else { HBCIUtils.log("reached end of msg without finding the end of BPD - message seems to be broken", HBCIUtils.LOG_ERR); bpd_st=msg_st.substring(startpos); break; } } // create BPD element Element bpdElem=doc.createElement("bpd"); bpdElem.setAttribute("encoding","base64"); rootElem.appendChild(bpdElem); // store BPD in element String bpd_encoded=HBCIUtils.encodeBase64(bpd_st.getBytes(Comm.ENCODING)); bpdElem.appendChild(doc.createTextNode(bpd_encoded)); // create XML string TransformerFactory tfac=TransformerFactory.newInstance(); Transformer trans=tfac.newTransformer(); trans.setOutputProperty(OutputKeys.METHOD, "xml"); trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); trans.setOutputProperty(OutputKeys.ENCODING, Comm.ENCODING); trans.setOutputProperty(OutputKeys.INDENT, "yes"); Source source=new DOMSource(doc); ByteArrayOutputStream xmlStream=new ByteArrayOutputStream(); Result target=new StreamResult(xmlStream); trans.transform(source, target); return xmlStream.toString(Comm.ENCODING); } catch (Exception e) { throw new RuntimeException(e); } } private void sendDataToServer(HBCIPassportInternal passport, String data) { StringBuffer retData=new StringBuffer(data); HBCIUtilsInternal.getCallback().callback( passport, HBCICallback.NEED_INFOPOINT_ACK, HBCIUtilsInternal.getLocMsg("CALLB_INFOPOINT_ACK"), HBCICallback.TYPE_BOOLEAN, retData); if (retData.length()==0) { HBCIUtils.log("sending data about successfully received BPD to InfoPoint server", HBCIUtils.LOG_INFO); HBCIUtilsInternal.getCallback().status( passport, HBCICallback.STATUS_SEND_INFOPOINT_DATA, data); HttpURLConnection conn=null; try { conn=(HttpURLConnection)url.openConnection(); conn.setDoOutput(true); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "text/xml"); conn.connect(); // send data OutputStream out=conn.getOutputStream(); out.write(data.getBytes("ISO-8859-1")); out.flush(); conn.getResponseCode(); // TODO: response code und -daten werden ignoriert conn.disconnect(); } catch (Exception e) { HBCIUtils.log(e); } } else { HBCIUtils.log("data NOT sent because of missing user confirmation", HBCIUtils.LOG_INFO); } } private Properties preparePassportData(HBCIPassportInternal passport) { Properties passportData=new Properties(); passportData.setProperty("type", passport.getPassportTypeName()); passportData.setProperty("country", passport.getCountry()); passportData.setProperty("blz", passport.getBLZ()); passportData.setProperty("host", passport.getHost()); passportData.setProperty("filter", passport.getFilterType()); String version=passport.getHBCIVersion(); passportData.setProperty("hbciVersion", version.equals("plus")?"220":version); return passportData; } public void sendBPD(HBCIPassportInternal passport, Properties msgData) { Properties passportData=preparePassportData(passport); String xmlData=prepareXMLDocument("bpdReceived", passportData, msgData); sendDataToServer(passport,xmlData); } public void sendPublicKeys(HBCIPassportInternal passport, Properties msgData) { /* TODO: activate this later Properties passportData=preparePassportData(passport); String xmlData=prepareXMLDocument("keysReceived", passportData, msgData); sendDataToServer(passport,xmlData); */ } }