From 616e06910051528674165319a1d6d161dff5859c Mon Sep 17 00:00:00 2001 From: clemenso Date: Fri, 27 Mar 2009 17:33:11 +0000 Subject: 1.1-RC6 (pinpad, pinmgmt, secureviewer) git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@323 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../gv/egiz/bku/online/applet/AppletBKUWorker.java | 5 +- .../egiz/bku/online/applet/AppletSecureViewer.java | 79 +-- .../at/gv/egiz/bku/online/applet/BKUApplet.java | 10 +- .../java/at/gv/egiz/bku/gui/PINManagementGUI.java | 26 +- .../at/gv/egiz/bku/gui/PINManagementGUIFacade.java | 9 +- .../java/at/gv/egiz/bku/gui/PINStatusRenderer.java | 2 - .../smccstal/ext/ManagementPINProviderFactory.java | 13 +- .../bku/smccstal/ext/PinpadPINProviderFactory.java | 45 +- .../gv/egiz/bku/gui/ActivationMessages.properties | 6 +- .../egiz/bku/gui/ActivationMessages_en.properties | 6 +- .../main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java | 40 +- .../main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java | 603 +++++++++++++-------- .../java/at/gv/egiz/bku/gui/HashDataViewer.java | 293 ---------- .../at/gv/egiz/bku/gui/SecureViewerDialog.java | 371 +++++++++++++ .../at/gv/egiz/bku/gui/Messages.properties | 3 +- .../at/gv/egiz/bku/gui/Messages_en.properties | 1 + .../src/main/resources/images/ChipperlingLogo.png | Bin 0 -> 4035 bytes .../test/java/at/gv/egiz/bku/gui/BKUGUITest.java | 5 +- .../test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java | 4 +- .../at/gv/egiz/bku/local/stal/BKUGuiProxy.java | 8 + .../at/gv/egiz/bku/local/stal/LocalBKUWorker.java | 3 +- .../gv/egiz/bku/local/stal/LocalSecureViewer.java | 109 ++++ .../bku/local/stal/LocalSignRequestHandler.java | 83 +-- .../gv/egiz/bku/online/conf/defaultConf.properties | 3 + BKUOnline/src/main/resources/log4j.properties | 2 +- BKUOnline/src/main/webapp/SLRequestForm.html | 27 + .../at/gv/egiz/bku/binding/ExpiryRemoverTest.java | 101 ++-- smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java | 130 ++--- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 220 ++------ .../src/main/java/at/gv/egiz/smcc/STARCOSCard.java | 234 +++++--- smcc/src/main/java/at/gv/egiz/smcc/SWCard.java | 49 +- .../main/java/at/gv/egiz/smcc/SignatureCard.java | 15 +- smcc/src/main/java/at/gv/egiz/smcc/ccid/CCID.java | 77 +++ .../java/at/gv/egiz/smcc/ccid/DefaultReader.java | 264 +++++++++ .../at/gv/egiz/smcc/ccid/GemplusGemPCPinpad.java | 65 +++ .../java/at/gv/egiz/smcc/ccid/ReaderFactory.java | 35 ++ .../test/java/at/gv/egiz/smcc/ACOSCardTest.java | 135 +++++ .../test/java/at/gv/egiz/smcc/STARCOSCardTest.java | 267 +++++++++ .../gv/egiz/bku/smccstal/AbstractPINProvider.java | 2 +- .../gv/egiz/bku/smccstal/PINProviderFactory.java | 3 +- .../bku/smccstal/PinpadPINProviderFactory.java | 131 +++-- .../java/at/gv/egiz/bku/smccstal/SecureViewer.java | 11 +- .../gv/egiz/bku/smccstal/SignRequestHandler.java | 14 +- .../bku/smccstal/SoftwarePINProviderFactory.java | 25 +- .../java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java | 7 +- 45 files changed, 2364 insertions(+), 1177 deletions(-) delete mode 100644 BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataViewer.java create mode 100644 BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java create mode 100644 BKUCommonGUI/src/main/resources/images/ChipperlingLogo.png create mode 100644 BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSecureViewer.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/ccid/CCID.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/ccid/DefaultReader.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/ccid/GemplusGemPCPinpad.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/ccid/ReaderFactory.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/ACOSCardTest.java create mode 100644 smcc/src/test/java/at/gv/egiz/smcc/STARCOSCardTest.java diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java index 9b9735f6..e8d8976d 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java @@ -18,6 +18,7 @@ package at.gv.egiz.bku.online.applet; import at.gv.egiz.bku.smccstal.AbstractBKUWorker; import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.smccstal.SignRequestHandler; import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; import at.gv.egiz.stal.SignRequest; @@ -67,8 +68,10 @@ public class AppletBKUWorker extends AbstractBKUWorker implements Runnable { STALPortType stalPort = applet.getSTALPort(); STALTranslator stalTranslator = applet.getSTALTranslator(); + AppletSecureViewer secureViewer = + new AppletSecureViewer(gui, stalPort, sessionId); addRequestHandler(SignRequest.class, - new AppletSecureViewer(stalPort, sessionId)); + new SignRequestHandler(secureViewer)); GetNextRequestResponseType nextRequestResp = stalPort.connect(sessionId); diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletSecureViewer.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletSecureViewer.java index e2551e2d..929cecb1 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletSecureViewer.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletSecureViewer.java @@ -16,17 +16,8 @@ */ package at.gv.egiz.bku.online.applet; +import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.bku.smccstal.SecureViewer; -import java.security.DigestException; -import java.security.MessageDigest; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import at.gv.egiz.bku.smccstal.SignRequestHandler; import at.gv.egiz.stal.HashDataInput; import at.gv.egiz.stal.impl.ByteArrayHashDataInput; import at.gv.egiz.stal.service.GetHashDataInputFault; @@ -34,49 +25,73 @@ import at.gv.egiz.stal.service.STALPortType; import at.gv.egiz.stal.service.types.GetHashDataInputResponseType; import at.gv.egiz.stal.service.types.GetHashDataInputType; import at.gv.egiz.stal.signedinfo.ReferenceType; +import at.gv.egiz.stal.signedinfo.SignedInfoType; +import java.awt.event.ActionListener; +import java.security.DigestException; +import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; /** - * A SignRequesthandler that obtains hashdata inputs from a STAL webservice and - * displays these either within the applet or in a separate frame. - * The internal viewer displays plaintext data only, other mimetypes can be saved to disk. - * The standalone (frame) viewer displays all mimetypes. - * - * (This class depends on STALService and therefore is not part of BKUCommonGUI.) - * + * * @author Clemens Orthacker */ -public class AppletSecureViewer extends SignRequestHandler { +public class AppletSecureViewer implements SecureViewer { private static final Log log = LogFactory.getLog(AppletSecureViewer.class); + + protected BKUGUIFacade gui; protected STALPortType stalPort; protected String sessId; + protected List verifiedDataToBeSigned; - public AppletSecureViewer(STALPortType stalPort, String sessId) { - if (stalPort == null || sessId == null) { + public AppletSecureViewer(BKUGUIFacade gui, STALPortType stalPort, + String sessId) { + if (gui == null) { + throw new NullPointerException("GUI must not be null"); + } + if (stalPort == null) { throw new NullPointerException("STAL port must not be null"); } - this.sessId = sessId; + if (sessId == null) { + throw new NullPointerException("session id must not be null"); + } + this.gui = gui; this.stalPort = stalPort; + this.sessId = sessId; } /** - * TODO don't throw exceptions + * retrieves the data to be signed for * @param signedReferences + * @param okListener + * @param okCommand + * @param cancelListener + * @param cancelCommand * @throws java.security.DigestException * @throws java.lang.Exception */ @Override - public void displayDataToBeSigned(List signedReferences) + public void displayDataToBeSigned(SignedInfoType signedInfo, + ActionListener okListener, String okCommand) throws DigestException, Exception { - - List hdi = getHashDataInput(signedReferences); - List verifiedHashDataInputs = verifyHashDataInput(signedReferences, hdi); - - if (verifiedHashDataInputs.size() > 0) { - gui.showSecureViewer(verifiedHashDataInputs, this, "hashDataDone"); + + if (verifiedDataToBeSigned == null) { + log.info("retrieve data to be signed for dsig:SignedInfo " + + signedInfo.getId()); + List hdi = + getHashDataInput(signedInfo.getReference()); + verifiedDataToBeSigned = verifyHashDataInput(signedInfo.getReference(), + hdi); + } + if (verifiedDataToBeSigned.size() > 0) { + gui.showSecureViewer(verifiedDataToBeSigned, okListener, okCommand); } else { - throw new Exception("No signature data (apart from any QualifyingProperties or a Manifest)"); + throw new Exception("No data to be signed (apart from any QualifyingProperties or a Manifest)"); } } @@ -110,7 +125,7 @@ public class AppletSecureViewer extends SignRequestHandler { } } } - + if (request.getReference().size() < 1) { log.error("No signature data (apart from any QualifyingProperties or a Manifest) for session " + sessId); throw new Exception("No signature data (apart from any QualifyingProperties or a Manifest)"); @@ -187,7 +202,7 @@ public class AppletSecureViewer extends SignRequestHandler { verifiedHashDataInputs.add(new ByteArrayHashDataInput(hdi, signedRefId, mimeType, encoding)); } } - + return verifiedHashDataInputs; } diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java index a4337bbd..0ddb6dc6 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/BKUApplet.java @@ -34,6 +34,7 @@ import at.gv.egiz.bku.gui.BKUGUIFacade; import at.gv.egiz.bku.gui.BKUGUIImpl; import at.gv.egiz.stal.service.STALPortType; import at.gv.egiz.stal.service.STALService; +import java.applet.AppletContext; import java.awt.Container; import javax.xml.namespace.QName; @@ -207,14 +208,19 @@ public class BKUApplet extends JApplet { */ protected void sendRedirect(String sessionId) { try { + AppletContext ctx = getAppletContext(); + if (ctx == null) { + log.error("no applet context (applet might already have been destroyed)"); + return; + } URL redirectURL = getURLParameter(REDIRECT_URL, sessionId); String redirectTarget = getParameter(REDIRECT_TARGET); if (redirectTarget == null) { log.info("Done. Redirecting to " + redirectURL + " ..."); - getAppletContext().showDocument(redirectURL); + ctx.showDocument(redirectURL); } else { log.info("Done. Redirecting to " + redirectURL + " (target=" + redirectTarget + ") ..."); - getAppletContext().showDocument(redirectURL, redirectTarget); + ctx.showDocument(redirectURL, redirectTarget); } } catch (MalformedURLException ex) { log.warn("Failed to redirect: " + ex.getMessage(), ex); diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java index 159dd29d..d1ca6c00 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java @@ -118,18 +118,18 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac pinStatusTable.setDefaultRenderer(PINSpec.class, new PINSpecRenderer()); pinStatusTable.setDefaultRenderer(STATUS.class, new PINStatusRenderer(cardmgmtMessages)); pinStatusTable.setTableHeader(null); - - pinStatusTable.addMouseMotionListener(new MouseMotionAdapter() { - - @Override - public void mouseMoved(MouseEvent e) { - if (pinStatusTable.columnAtPoint(e.getPoint()) == 0) { - pinStatusTable.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - } else { - pinStatusTable.setCursor(Cursor.getDefaultCursor()); - } - } - }); + pinStatusTable.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); +// pinStatusTable.addMouseMotionListener(new MouseMotionAdapter() { +// +// @Override +// public void mouseMoved(MouseEvent e) { +// if (pinStatusTable.columnAtPoint(e.getPoint()) == 0) { +// pinStatusTable.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); +// } else { +// pinStatusTable.setCursor(Cursor.getDefaultCursor()); +// } +// } +// }); final JButton activateButton = new JButton(); activateButton.setFont(activateButton.getFont().deriveFont(activateButton.getFont().getStyle() & ~java.awt.Font.BOLD)); @@ -392,7 +392,7 @@ public class PINManagementGUI extends CardMgmtGUI implements PINManagementGUIFac if (pinpad) { JLabel pinpadLabel = new JLabel(); pinpadLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() & ~Font.BOLD)); - String pinpadPattern = getMessage(MESSAGE_PINPAD); + String pinpadPattern = getMessage(MESSAGE_VERIFYPIN_PINPAD); pinpadLabel.setText(MessageFormat.format(pinpadPattern, new Object[] { pinSpec.getLocalizedName(), pinSize })); diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java index 45313f42..f0cc0a27 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java @@ -40,13 +40,16 @@ public interface PINManagementGUIFacade extends BKUGUIFacade { public static final String MESSAGE_ACTIVATE_SUCCESS = "activate.success"; public static final String MESSAGE_CHANGE_SUCCESS = "change.success"; public static final String MESSAGE_PINMGMT = "pin.mgmt"; - public static final String MESSAGE_PINPAD = "pinpad"; - public static final String MESSAGE_CHANGEPIN_PINPAD = "pinpad.change"; +// public static final String MESSAGE_PINPAD = "pinpad"; public static final String MESSAGE_ACTIVATE_PIN = "activate.pin"; public static final String MESSAGE_CHANGE_PIN = "change.pin"; public static final String MESSAGE_VERIFY_PIN = "verify.pin"; public static final String MESSAGE_UNBLOCK_PIN = "unblock.pin"; - + public static final String MESSAGE_ACTIVATEPIN_PINPAD = "activate.pinpad"; + public static final String MESSAGE_CHANGEPIN_PINPAD = "change.pinpad"; + public static final String MESSAGE_VERIFYPIN_PINPAD = "verify.pinpad"; + public static final String MESSAGE_UNBLOCKPIN_PINPAD = "unblock.pinpad"; + public static final String LABEL_OLD_PIN = "label.old.pin"; public static final String LABEL_NEW_PIN = "label.new.pin"; public static final String LABEL_REPEAT_PIN = "label.repeat.pin"; diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java index 4cb84b77..83ff74f2 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java @@ -22,8 +22,6 @@ import java.awt.Color; import java.awt.Font; import java.util.ResourceBundle; import javax.swing.table.DefaultTableCellRenderer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; /** * diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java index b0dd8766..d635b8df 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/ManagementPINProviderFactory.java @@ -19,6 +19,7 @@ package at.gv.egiz.bku.smccstal.ext; import at.gv.egiz.smcc.ChangePINProvider; import at.gv.egiz.bku.gui.PINManagementGUIFacade; +import at.gv.egiz.smcc.ccid.CCID; import at.gv.egiz.smcc.PINProvider; import at.gv.egiz.smcc.SignatureCard; @@ -33,13 +34,13 @@ public abstract class ManagementPINProviderFactory { public static ManagementPINProviderFactory getInstance(SignatureCard forCard, PINManagementGUIFacade gui) { -// if (forCard.ifdSupportsFeature(SignatureCard.FEATURE_VERIFY_PIN_DIRECT)) { -//// forCard.ifdSupportsFeature(SignatureCard.FEATURE_MODIFY_PIN_DIRECT) -// return new PinpadPINProviderFactory(gui); -// -// } else { + if (forCard.getReader().hasFeature(CCID.FEATURE_VERIFY_PIN_DIRECT)) { +// forCard.ifdSupportsFeature(SignatureCard.FEATURE_MODIFY_PIN_DIRECT) + return new PinpadPINProviderFactory(gui); + + } else { return new SoftwarePINProviderFactory(gui); -// } + } } public abstract PINProvider getVerifyPINProvider(); diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PinpadPINProviderFactory.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PinpadPINProviderFactory.java index 4176e0a9..a9ad5ef8 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PinpadPINProviderFactory.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PinpadPINProviderFactory.java @@ -73,23 +73,6 @@ public class PinpadPINProviderFactory extends ManagementPINProviderFactory { showPinpadPINDialog(retries, spec); retry = true; return null; - -// gui.showPINDialog(type, spec, (retry) ? retries : -1, -// this, "exec", -// this, "back"); -// -// waitForAction(); -// -// if ("exec".equals(action)) { -// gui.showWaitDialog(null); -// retry = true; -// return gui.getPin(); -// } else if ("back".equals(action)) { -// throw new CancelledException(); -// } else { -// log.error("unsupported command " + action); -// throw new CancelledException(); -// } } /** @@ -111,14 +94,38 @@ public class PinpadPINProviderFactory extends ManagementPINProviderFactory { title = BKUGUIFacade.TITLE_RETRY; message = BKUGUIFacade.MESSAGE_RETRIES; params = new Object[]{String.valueOf(retries)}; - } else { - title = BKUGUIFacade.TITLE_SIGN; + } else if (type == DIALOG.VERIFY) { + title = PINManagementGUIFacade.TITLE_VERIFY_PIN; message = BKUGUIFacade.MESSAGE_ENTERPIN_PINPAD; String pinSize = String.valueOf(pinSpec.getMinLength()); if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { pinSize += "-" + pinSpec.getMaxLength(); } params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } else if (type == DIALOG.ACTIVATE) { + title = PINManagementGUIFacade.TITLE_ACTIVATE_PIN; + message = PINManagementGUIFacade.MESSAGE_ACTIVATEPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } else if (type == DIALOG.CHANGE) { + title = PINManagementGUIFacade.TITLE_CHANGE_PIN; + message = PINManagementGUIFacade.MESSAGE_CHANGEPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; + } else { //if (type == DIALOG.UNBLOCK) { + title = PINManagementGUIFacade.TITLE_UNBLOCK_PIN; + message = PINManagementGUIFacade.MESSAGE_UNBLOCKPIN_PINPAD; + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + params = new Object[]{pinSpec.getLocalizedName(), pinSize}; } gui.showMessageDialog(title, message, params); } diff --git a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties index 4ceacb21..c6d219d4 100644 --- a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties +++ b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties @@ -24,12 +24,14 @@ title.change.success=Erfolg # removed message.* prefix to reuse keys as help keys pin.mgmt=Die Karte verf\u00FCgt \u00FCber {0} PINs -pinpad={0} ({1} stellig) am Kartenleser eingeben und best\u00E4tigen. -pinpad.change={0} ({1} stellig) am Kartenleser eingeben und best\u00E4tigen. activate.pin={0} eingeben und best\u00E4tigen change.pin={0} eingeben und best\u00E4tigen unblock.pin=PUK zu {0} eingeben verify.pin={0} eingeben (TODO: Warning not activated) +verify.pinpad={0} ({1} stellig) am Kartenleser eingeben (und best\u00E4tigen). +activate.pinpad={0} ({1} stellig) am Kartenleser eingeben und wiederholen (jeweils best\u00E4tigen). +change.pinpad=Alte {0} ({1} stellig) am Kartenleser eingeben, danach neue {0} eingeben und wiederholen (jeweils best\u00E4tigen). +unblock.pinpad={0} ({1} stellig) am Kartenleser eingeben (und best\u00E4tigen). activate.success={0} wurde erfolgreich aktiviert. change.success={0} wurde erfolgreich ge\u00E4ndert. diff --git a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties index 9178d65c..b4bededf 100644 --- a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties +++ b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties @@ -23,11 +23,13 @@ title.change.success=Success # removed message.* prefix to reuse keys as help keys pin.mgmt=The smartcard has {0} PINs -pinpad=Enter {0} ({1} digits) on pinpad and confirm. -pinpad.change=Enter {0} ({1} digits) on pinpad and confirm. activate.pin=Enter and confirm {0} change.pin=Enter and confirm {0} unblock.pin=Enter PUK for {0} +verify.pinpad=Enter {0} ({1} digits) on cardreader (and confirm). +activate.pinpad=Enter {0} ({1} digits) on cardreader and repeat (confirm in each case). +change.pinpad=Enter old {0} ({1} digits) on cardreader, then enter new {0} and repeat (confirm in each case). +unblock.pinpad=Enter {0} ({1} digits) on cardreader (and confirm). activate.success={0} successfully activated change.success={0} successfully changed diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java index 1043b6a1..4b079428 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java @@ -43,6 +43,7 @@ public interface BKUGUIFacade { public static final String MESSAGES_BUNDLE = "at/gv/egiz/bku/gui/Messages"; public static final String DEFAULT_BACKGROUND = "/images/BackgroundChipperling.png"; + public static final String DEFAULT_ICON = "/images/ChipperlingLogo.png"; public static final String HELP_IMG = "/images/help.png"; public static final String HASHDATA_FONT = "Monospaced"; public static final Color ERROR_COLOR = Color.RED; @@ -58,6 +59,7 @@ public interface BKUGUIFacade { public static final String TITLE_WAIT = "title.wait"; public static final String TITLE_HASHDATA = "title.hashdata"; public static final String WINDOWTITLE_SAVE = "windowtitle.save"; + public static final String WINDOWTITLE_ERROR = "windowtitle.error"; public static final String WINDOWTITLE_SAVEDIR = "windowtitle.savedir"; public static final String WINDOWTITLE_OVERWRITE = "windowtitle.overwrite"; public static final String WINDOWTITLE_VIEWER = "windowtitle.viewer"; @@ -102,42 +104,36 @@ public interface BKUGUIFacade { public enum Style { tiny, simple, advanced }; -// public void init(Container contentPane, Locale locale, Style guiStyle, URL background, ActionListener helpListener); - /** * BKUWorker needs to init signature card with locale * @return */ public Locale getLocale(); -// public void showWelcomeDialog(); - - /** - * - * @param waitMessage if null, a simple 'please wait' text is displayed - */ -// public void showWaitDialog(String waitMessage); - -// public void showInsertCardDialog(ActionListener cancelListener, String actionCommand); - -// public void showCardNotSupportedDialog(ActionListener cancelListener, String actionCommand); - public void showCardPINDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand); -// public void showCardPINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand); - - public void showSignaturePINDialog(PINSpec pinSpec, int numRetries, ActionListener signListener, String signCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand); - -// public void showSignaturePINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand); + public void showSignaturePINDialog(PINSpec pinSpec, int numRetries, + ActionListener signListener, String signCommand, + ActionListener cancelListener, String cancelCommand, + ActionListener viewerListener, String viewerCommand); -// public void showPinpadSignaturePINDialog(PINSpec pinSpec, int retries); + public void showPinpadSignaturePINDialog(PINSpec pinSpec, int numRetries, + ActionListener viewerListener, String viewerCommand); public char[] getPin(); - public void showSecureViewer(List signedReferences, - ActionListener okListener, String okCommand); + /** + * + * @param dataToBeSigned + * @param backListener if list of references hides pin dialog, backListener + * receives an action when user hits 'back' button (i.e. whenever the pin-dialog + * needs to be re-paint) + * @param backCommand + */ + public void showSecureViewer(List dataToBeSigned, + ActionListener backListener, String backCommand); public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams, ActionListener okListener, String okCommand); diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java index 928be249..a7eebbfd 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java @@ -71,6 +71,7 @@ public class BKUGUIImpl implements BKUGUIFacade { } protected HelpMouseListener helpListener; + protected SecureViewerDialog secureViewer; protected Container contentPane; protected ResourceBundle messages; @@ -145,13 +146,16 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public void run() { - log.debug("initializing gui"); + log.debug("initializing gui [" + Thread.currentThread().getName() + "]"); if (renderIconPanel) { initIconPanel(background); initContentPanel(null); } else { - initContentPanel(background); + initContentPanel((background == null) ? + getClass().getResource(DEFAULT_BACKGROUND) : + background + ); } GroupLayout layout = new GroupLayout(contentPane); @@ -159,15 +163,27 @@ public class BKUGUIImpl implements BKUGUIFacade { if (renderIconPanel) { layout.setHorizontalGroup(layout.createSequentialGroup() - .addComponent(iconPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); - layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(iconPanel, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); + .addContainerGap() + .addComponent(iconPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap()); + layout.setVerticalGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(iconPanel, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()); } else { - layout.setHorizontalGroup(layout.createSequentialGroup().addComponent(contentPanel)); - layout.setVerticalGroup(layout.createSequentialGroup().addComponent(contentPanel)); + layout.setHorizontalGroup(layout.createSequentialGroup() + // left border + .addContainerGap() + .addComponent(contentPanel) + .addContainerGap()); + layout.setVerticalGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(contentPanel) + .addContainerGap()); } } }); @@ -178,11 +194,12 @@ public class BKUGUIImpl implements BKUGUIFacade { protected void initIconPanel(URL background) { if (background == null) { - background = getClass().getResource(DEFAULT_BACKGROUND); + background = getClass().getResource(DEFAULT_ICON); } if ("file".equals(background.getProtocol())) { - log.warn("file:// background images not permitted: " + background); - background = getClass().getResource(DEFAULT_BACKGROUND); + log.warn("file:// background images not permitted: " + background + + ", loading default background"); + background = getClass().getResource(DEFAULT_ICON); } log.debug("loading icon panel background " + background); @@ -194,26 +211,24 @@ public class BKUGUIImpl implements BKUGUIFacade { iconPanel.setLayout(iconPanelLayout); iconPanelLayout.setHorizontalGroup( iconPanelLayout.createSequentialGroup() - .addContainerGap() .addComponent(iconLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)); - // no gap here (contentPanel has containerGap) iconPanelLayout.setVerticalGroup( iconPanelLayout.createSequentialGroup() - .addContainerGap() - .addComponent(iconLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); + .addComponent(iconLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)); } protected void initContentPanel(URL background) { +// if (background == null) { +// background = getClass().getResource(DEFAULT_BACKGROUND); +// } if (background == null) { - background = getClass().getResource(DEFAULT_BACKGROUND); - } - if (background == null) { + log.debug("no background image set"); contentPanel = new JPanel(); } else { if ("file".equals(background.getProtocol())) { - log.warn("file:// background images not permitted: " + background); + log.warn("file:// background images not permitted: " + background + + ", loading default background"); background = getClass().getResource(DEFAULT_BACKGROUND); } log.debug("loading background " + background); @@ -257,34 +272,29 @@ public class BKUGUIImpl implements BKUGUIFacade { GroupLayout contentPanelLayout = new GroupLayout(contentPanel); contentPanel.setLayout(contentPanelLayout); - GroupLayout.ParallelGroup horizontalContentInner = contentPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); + // align header, main and button to the right + GroupLayout.ParallelGroup horizontalContent = + contentPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING); //LEADING); + GroupLayout.SequentialGroup verticalContent = + contentPanelLayout.createSequentialGroup(); + if (renderHeaderPanel) { - horizontalContentInner + horizontalContent .addComponent(headerPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE); + verticalContent + .addComponent(headerPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED); + } - horizontalContentInner + horizontalContent .addComponent(mainPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE); - GroupLayout.SequentialGroup horizontalContentOuter = contentPanelLayout.createSequentialGroup(); - if (!renderIconPanel) { - horizontalContentOuter - .addContainerGap(); - } - horizontalContentOuter - .addGroup(horizontalContentInner) - .addContainerGap(); - contentPanelLayout.setHorizontalGroup(horizontalContentOuter); - - GroupLayout.SequentialGroup verticalContent = contentPanelLayout.createSequentialGroup(); - verticalContent.addContainerGap(); - if (renderHeaderPanel) { - verticalContent.addComponent(headerPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED); - } - verticalContent.addComponent(mainPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addContainerGap(); + .addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE); //Short.MAX_VALUE); + verticalContent + .addComponent(mainPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE); + + contentPanelLayout.setHorizontalGroup(horizontalContent); //Outer); contentPanelLayout.setVerticalGroup(verticalContent); } @@ -521,7 +531,7 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public void run() { - log.debug("show card-pin dialog"); + log.debug("show card-pin dialog [" + Thread.currentThread().getName() + "]"); mainPanel.removeAll(); buttonPanel.removeAll(); @@ -653,7 +663,6 @@ public class BKUGUIImpl implements BKUGUIFacade { buttonPanel.setLayout(buttonPanelLayout); GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); GroupLayout.Group buttonVertical; @@ -700,6 +709,128 @@ public class BKUGUIImpl implements BKUGUIFacade { // showSignaturePINDialog(pinSpec, -1, signListener, signCommand, cancelListener, cancelCommand, hashdataListener, hashdataCommand); // } + @Override + public void showPinpadSignaturePINDialog(final PINSpec pinSpec, final int numRetries, +// final ActionListener cancelListener, final String cancelCommand, + final ActionListener hashdataListener, final String hashdataCommand) { + + log.debug("scheduling pinpad signature-pin dialog"); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + log.debug("show pinpad signature-pin dialog [" + Thread.currentThread().getName() + "]"); + + mainPanel.removeAll(); + buttonPanel.removeAll(); + + if (renderHeaderPanel) { + if (numRetries < 0) { + titleLabel.setText(getMessage(TITLE_SIGN)); + } else { + titleLabel.setText(getMessage(TITLE_RETRY)); + } + } + + JLabel infoLabel = new JLabel(); + if (numRetries < 0) { + infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + if (shortText) { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY)); + } else { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); + } + infoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + infoLabel.setForeground(HYPERLINK_COLOR); + infoLabel.addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent me) { + ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand); + hashdataListener.actionPerformed(e); + } + }); + helpListener.setHelpTopic(HELP_SIGNPIN); + } else { + String retryPattern; + if (numRetries < 2) { + retryPattern = getMessage(MESSAGE_LAST_RETRY); + } else { + retryPattern = getMessage(MESSAGE_RETRIES); + } + infoLabel.setText(MessageFormat.format(retryPattern, new Object[]{String.valueOf(numRetries)})); + infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD)); + infoLabel.setForeground(ERROR_COLOR); + helpListener.setHelpTopic(HELP_RETRY); + } + + String pinSize = String.valueOf(pinSpec.getMinLength()); + if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { + pinSize += "-" + pinSpec.getMaxLength(); + } + + String msgPattern = getMessage(MESSAGE_ENTERPIN_PINPAD); + String msg = MessageFormat.format(msgPattern, new Object[] { + pinSpec.getLocalizedName(), pinSize }); + + JLabel msgLabel = new JLabel(); + msgLabel.setFont(msgLabel.getFont().deriveFont(msgLabel.getFont().getStyle() & ~Font.BOLD)); + msgLabel.setText(msg); + + GroupLayout mainPanelLayout = new GroupLayout(mainPanel); + mainPanel.setLayout(mainPanelLayout); + + GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup() + .addComponent(infoLabel); + GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(infoLabel); + + if (!renderHeaderPanel) { + infoHorizontal + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel); + infoVertical + .addComponent(helpLabel); + } + + mainPanelLayout.setHorizontalGroup( + mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(infoHorizontal) + .addComponent(msgLabel)); + + mainPanelLayout.setVerticalGroup( + mainPanelLayout.createSequentialGroup() + .addGroup(infoVertical) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(msgLabel)); + + //no cancel button (cancel via pinpad) +// if (renderCancelButton) { +// JButton cancelButton = new JButton(); +// cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); +// cancelButton.setText(getMessage(BUTTON_CANCEL)); +// cancelButton.setActionCommand(cancelCommand); +// cancelButton.addActionListener(cancelListener); +// +// GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); +// buttonPanel.setLayout(buttonPanelLayout); +// +// GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() +// .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); +// GroupLayout.SequentialGroup buttonVertical = buttonPanelLayout.createSequentialGroup() +// .addComponent(cancelButton); +// +// buttonPanelLayout.setHorizontalGroup(buttonHorizontal); +// buttonPanelLayout.setVerticalGroup(buttonVertical); +// } + + contentPanel.validate(); + } + }); + } + @Override public void showSignaturePINDialog(final PINSpec pinSpec, final int numRetries, final ActionListener signListener, final String signCommand, @@ -717,7 +848,7 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public void run() { - log.debug("show signature-pin dialog"); + log.debug("show signature-pin dialog [" + Thread.currentThread().getName() + "]"); mainPanel.removeAll(); buttonPanel.removeAll(); @@ -730,6 +861,38 @@ public class BKUGUIImpl implements BKUGUIFacade { } } + JLabel infoLabel = new JLabel(); + if (numRetries < 0) { + infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + if (shortText) { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY)); + } else { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); + } + infoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + infoLabel.setForeground(HYPERLINK_COLOR); + infoLabel.addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent me) { + ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand); + hashdataListener.actionPerformed(e); + } + }); + helpListener.setHelpTopic(HELP_SIGNPIN); + } else { + String retryPattern; + if (numRetries < 2) { + retryPattern = getMessage(MESSAGE_LAST_RETRY); + } else { + retryPattern = getMessage(MESSAGE_RETRIES); + } + infoLabel.setText(MessageFormat.format(retryPattern, new Object[]{String.valueOf(numRetries)})); + infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD)); + infoLabel.setForeground(ERROR_COLOR); + helpListener.setHelpTopic(HELP_RETRY); + } + JButton signButton = new JButton(); signButton.setFont(signButton.getFont().deriveFont(signButton.getFont().getStyle() & ~java.awt.Font.BOLD)); signButton.setText(getMessage(BUTTON_SIGN)); @@ -765,46 +928,14 @@ public class BKUGUIImpl implements BKUGUIFacade { } pinsizeLabel.setText(MessageFormat.format(pinsizePattern, new Object[]{pinSize})); - JLabel infoLabel = new JLabel(); - if (numRetries < 0) { - infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); - if (shortText) { - infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY)); - } else { - infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); - } - infoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - infoLabel.setForeground(HYPERLINK_COLOR); - infoLabel.addMouseListener(new MouseAdapter() { - - @Override - public void mouseClicked(MouseEvent me) { - ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand); - hashdataListener.actionPerformed(e); - } - }); - helpListener.setHelpTopic(HELP_SIGNPIN); - } else { - String retryPattern; - if (numRetries < 2) { - retryPattern = getMessage(MESSAGE_LAST_RETRY); - } else { - retryPattern = getMessage(MESSAGE_RETRIES); - } - infoLabel.setText(MessageFormat.format(retryPattern, new Object[]{String.valueOf(numRetries)})); - infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD)); - infoLabel.setForeground(ERROR_COLOR); - helpListener.setHelpTopic(HELP_RETRY); - } - GroupLayout mainPanelLayout = new GroupLayout(mainPanel); mainPanel.setLayout(mainPanelLayout); - + GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup() .addComponent(infoLabel); GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) .addComponent(infoLabel); - + if (!renderHeaderPanel) { infoHorizontal .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) @@ -814,8 +945,8 @@ public class BKUGUIImpl implements BKUGUIFacade { } // align pinfield and pinsize to the right - GroupLayout.ParallelGroup pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING); - GroupLayout.Group pinVertical; + GroupLayout.Group pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING); + GroupLayout.SequentialGroup pinVertical = mainPanelLayout.createSequentialGroup(); if (pinLabelPos == PinLabelPosition.ABOVE) { pinHorizontal @@ -823,20 +954,25 @@ public class BKUGUIImpl implements BKUGUIFacade { .addComponent(signPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE); - pinVertical = mainPanelLayout.createSequentialGroup() + pinVertical .addComponent(signPinLabel) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE); - } else { + .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pinsizeLabel); + } else { // PinLabelPosition.LEFT pinHorizontal .addGroup(mainPanelLayout.createSequentialGroup() .addComponent(signPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE); - pinVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(signPinLabel) - .addComponent(pinField); + pinVertical + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(signPinLabel) + .addComponent(pinField)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pinsizeLabel); } mainPanelLayout.setHorizontalGroup( @@ -848,18 +984,14 @@ public class BKUGUIImpl implements BKUGUIFacade { mainPanelLayout.createSequentialGroup() .addGroup(infoVertical) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pinVertical) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pinsizeLabel)); + .addGroup(pinVertical)); GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); buttonPanel.setLayout(buttonPanelLayout); - GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(signButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); + GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup(); GroupLayout.Group buttonVertical; - + if (renderCancelButton) { JButton cancelButton = new JButton(); cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); @@ -868,17 +1000,19 @@ public class BKUGUIImpl implements BKUGUIFacade { cancelButton.addActionListener(cancelListener); buttonHorizontal + .addComponent(signButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); - buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(signButton) - .addComponent(cancelButton); + .addComponent(cancelButton); } else { + buttonHorizontal + .addComponent(signButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); buttonVertical = buttonPanelLayout.createSequentialGroup() .addComponent(signButton); } - + buttonPanelLayout.setHorizontalGroup(buttonHorizontal); buttonPanelLayout.setVerticalGroup(buttonVertical); @@ -951,7 +1085,7 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public void run() { - log.debug("show message dialog"); + log.debug("show message dialog [" + Thread.currentThread().getName() + "]"); mainPanel.removeAll(); buttonPanel.removeAll(); @@ -1011,7 +1145,6 @@ public class BKUGUIImpl implements BKUGUIFacade { buttonPanelLayout.setHorizontalGroup( buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); buttonPanelLayout.setVerticalGroup( buttonPanelLayout.createSequentialGroup() @@ -1084,68 +1217,69 @@ public class BKUGUIImpl implements BKUGUIFacade { } return null; } + + + //////////////////////////////////////////////////////////////////////////// + // SECURE VIEWER + //////////////////////////////////////////////////////////////////////////// + /** - * TODO handle multiple references in HashDataViewer * @param signedReferences - * @param okListener + * @param backListener gets notified if pin-dialog has to be redrawn + * (signedRefencesList returns via BACK button) * @param okCommand */ @Override - public void showSecureViewer(final List signedReferences, - final ActionListener okListener, - final String okCommand) { - - if (signedReferences == null) { - showErrorDialog(getMessage(ERR_NO_HASHDATA), new Object[] {"No SignedReferences provided"}, okListener, okCommand); - return; - } + public void showSecureViewer(final List dataToBeSigned, + final ActionListener backListener, final String backCommand) { - if (signedReferences.size() == 1) { + if (dataToBeSigned == null) { + showErrorDialog(getMessage(ERR_NO_HASHDATA), + new Object[] {"no signature data provided"}, + backListener, backCommand); + } else if (dataToBeSigned.size() == 1) { try { - log.debug("scheduling hashdata viewer"); + log.debug("scheduling secure viewer"); - SwingUtilities.invokeAndWait(new Runnable() { + SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - ActionListener saveHashDataListener = new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - HashDataInput hdi = signedReferences.get(0); - showSaveHashDataInputDialog(Collections.singletonList(hdi), okListener, okCommand); - } - }; - showHashDataViewer(signedReferences.get(0), saveHashDataListener, "save"); + showSecureViewer(dataToBeSigned.get(0)); } }); - } catch (InterruptedException ex) { - log.error("Failed to display HashDataViewer: " + ex.getMessage()); - } catch (InvocationTargetException ex) { - log.error("Failed to display HashDataViewer: " + ex.getMessage()); + } catch (Exception ex) { //InterruptedException InvocationTargetException + log.error("Failed to display secure viewer: " + ex.getMessage()); + log.trace(ex); + showErrorDialog(ERR_UNKNOWN, null, backListener, backCommand); } } else { - showSignedReferencesListDialog(signedReferences, okListener, okCommand); + showSignedReferencesListDialog(dataToBeSigned, backListener, backCommand); } } /** * has to be called from event dispatcher thread + * This method blocks until the dialog's close button is pressed. * @param hashDataText * @param saveListener * @param saveCommand */ - private void showHashDataViewer(final HashDataInput hashDataInput, final ActionListener saveListener, final String saveCommand) { + private void showSecureViewer(HashDataInput dataToBeSigned) { - log.debug("show hashdata viewer"); - - ActionListener l = helpListener.getActionListener(); - HashDataViewer.showHashDataInput(contentPane, hashDataInput, messages, saveListener, saveCommand, l); + log.debug("show secure viewer [" + Thread.currentThread().getName() + "]"); + if (secureViewer == null) { + secureViewer = new SecureViewerDialog(null, messages, + helpListener.getActionListener()); + } + secureViewer.setContent(dataToBeSigned); + log.trace("show secure viewer returned"); } - private void showSignedReferencesListDialog(final List signedReferences, final ActionListener backListener, final String backCommand) { + private void showSignedReferencesListDialog(final List signedReferences, + final ActionListener backListener, final String backCommand) { log.debug("scheduling signed references list dialog"); @@ -1154,7 +1288,7 @@ public class BKUGUIImpl implements BKUGUIFacade { @Override public void run() { - log.debug("show signed references list dialog"); + log.debug("show signed references list dialog [" + Thread.currentThread().getName() + "]"); mainPanel.removeAll(); buttonPanel.removeAll(); @@ -1202,13 +1336,7 @@ public class BKUGUIImpl implements BKUGUIFacade { int selectionIdx = lsm.getMinSelectionIndex(); if (selectionIdx >= 0) { final HashDataInput selection = signedReferences.get(selectionIdx); - showHashDataViewer(selection, new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - showSaveHashDataInputDialog(Collections.singletonList(selection), null, null); - } - }, "save"); + showSecureViewer(selection); } } }); @@ -1255,9 +1383,8 @@ public class BKUGUIImpl implements BKUGUIFacade { buttonPanel.setLayout(buttonPanelLayout); buttonPanelLayout.setHorizontalGroup(buttonPanelLayout.createSequentialGroup() - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(backButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); - buttonPanelLayout.setVerticalGroup(buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + buttonPanelLayout.setVerticalGroup(buttonPanelLayout.createSequentialGroup() .addComponent(backButton)); contentPanel.validate(); @@ -1266,96 +1393,101 @@ public class BKUGUIImpl implements BKUGUIFacade { } /** - * - * @param signedRefs * @param okListener may be null - * @param okCommand */ - private void showSaveHashDataInputDialog(final List signedRefs, final ActionListener okListener, final String okCommand) { - - log.debug("scheduling save hashdatainput dialog"); - - SwingUtilities.invokeLater(new Runnable() { +// private void showSaveDialog(final List signedRefs, +// final ActionListener okListener, final String okCommand) { +// +// log.debug("scheduling save dialog"); +// +// SwingUtilities.invokeLater(new Runnable() { +// +// @Override +// public void run() { +// +// log.debug("show save dialog"); +// +// String userHome = System.getProperty("user.home"); +// +// JFileChooser fileDialog = new JFileChooser(userHome); +// fileDialog.setMultiSelectionEnabled(false); +// fileDialog.setDialogType(JFileChooser.SAVE_DIALOG); +// fileDialog.setFileHidingEnabled(true); +// if (signedRefs.size() == 1) { +// fileDialog.setDialogTitle(getMessage(WINDOWTITLE_SAVE)); +// fileDialog.setFileSelectionMode(JFileChooser.FILES_ONLY); +// String mimeType = signedRefs.get(0).getMimeType(); +// MimeFilter mimeFilter = new MimeFilter(mimeType, messages); +// fileDialog.setFileFilter(mimeFilter); +// String filename = getMessage(SAVE_HASHDATAINPUT_PREFIX) + MimeFilter.getExtension(mimeType); +// fileDialog.setSelectedFile(new File(userHome, filename)); +// } else { +// fileDialog.setDialogTitle(getMessage(WINDOWTITLE_SAVEDIR)); +// fileDialog.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); +// } +// +// //parent contentPane -> placed over applet +// switch (fileDialog.showSaveDialog(fileDialog)) { +// case JFileChooser.APPROVE_OPTION: +// File f = fileDialog.getSelectedFile(); +// for (HashDataInput hashDataInput : signedRefs) { +// String mimeType = hashDataInput.getMimeType(); +// String id = hashDataInput.getReferenceId(); +// File file; +// if (f.isDirectory()) { +// String filename = getMessage(SAVE_HASHDATAINPUT_PREFIX) + '_' + id + MimeFilter.getExtension(mimeType); +// file = new File(f, filename); +// } else { +// file = f; +// } +// if (file.exists()) { +// String ovrwrt = getMessage(MESSAGE_OVERWRITE); +// int overwrite = JOptionPane.showConfirmDialog(fileDialog, MessageFormat.format(ovrwrt, file), getMessage(WINDOWTITLE_OVERWRITE), JOptionPane.OK_CANCEL_OPTION); +// if (overwrite != JOptionPane.OK_OPTION) { +// continue; +// } +// } +// if (log.isDebugEnabled()) { +// log.debug("writing hashdata input " + id + " (" + mimeType + ") to file " + file); +// } +// FileOutputStream fos = null; +// try { +// fos = new FileOutputStream(file); +// BufferedOutputStream bos = new BufferedOutputStream(fos); +// InputStream hdi = hashDataInput.getHashDataInput(); +// int b; +// while ((b = hdi.read()) != -1) { +// bos.write(b); +// } +// bos.flush(); +// bos.close(); +// } catch (IOException ex) { +// log.error("Failed to write " + file + ": " + ex.getMessage()); +// showErrorDialog(ERR_WRITE_HASHDATA, new Object[] {ex.getMessage()}, null, null); +// ex.printStackTrace(); +// } finally { +// try { +// fos.close(); +// } catch (IOException ex) { +// } +// } +// } +// break; +// case JFileChooser.CANCEL_OPTION : +// log.debug("cancelled save dialog"); +// break; +// } +// if (okListener != null) { +// okListener.actionPerformed(new ActionEvent(fileDialog, ActionEvent.ACTION_PERFORMED, okCommand)); +// } +// } +// }); +// } + + //////////////////////////////////////////////////////////////////////////// + // UTILITY METHODS + //////////////////////////////////////////////////////////////////////////// - @Override - public void run() { - - log.debug("show save hashdatainput dialog"); - - String userHome = System.getProperty("user.home"); - - JFileChooser fileDialog = new JFileChooser(userHome); - fileDialog.setMultiSelectionEnabled(false); - fileDialog.setDialogType(JFileChooser.SAVE_DIALOG); - fileDialog.setFileHidingEnabled(true); - if (signedRefs.size() == 1) { - fileDialog.setDialogTitle(getMessage(WINDOWTITLE_SAVE)); - fileDialog.setFileSelectionMode(JFileChooser.FILES_ONLY); - String mimeType = signedRefs.get(0).getMimeType(); - MimeFilter mimeFilter = new MimeFilter(mimeType, messages); - fileDialog.setFileFilter(mimeFilter); - String filename = getMessage(SAVE_HASHDATAINPUT_PREFIX) + MimeFilter.getExtension(mimeType); - fileDialog.setSelectedFile(new File(userHome, filename)); - } else { - fileDialog.setDialogTitle(getMessage(WINDOWTITLE_SAVEDIR)); - fileDialog.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - } - - //parent contentPane -> placed over applet - switch (fileDialog.showSaveDialog(fileDialog)) { - case JFileChooser.APPROVE_OPTION: - File f = fileDialog.getSelectedFile(); - for (HashDataInput hashDataInput : signedRefs) { - String mimeType = hashDataInput.getMimeType(); - String id = hashDataInput.getReferenceId(); - File file; - if (f.isDirectory()) { - String filename = getMessage(SAVE_HASHDATAINPUT_PREFIX) + '_' + id + MimeFilter.getExtension(mimeType); - file = new File(f, filename); - } else { - file = f; - } - if (file.exists()) { - String ovrwrt = getMessage(MESSAGE_OVERWRITE); - int overwrite = JOptionPane.showConfirmDialog(fileDialog, MessageFormat.format(ovrwrt, file), getMessage(WINDOWTITLE_OVERWRITE), JOptionPane.OK_CANCEL_OPTION); - if (overwrite != JOptionPane.OK_OPTION) { - continue; - } - } - if (log.isDebugEnabled()) { - log.debug("Writing HashDataInput " + id + " (" + mimeType + ") to file " + file); - } - FileOutputStream fos = null; - try { - fos = new FileOutputStream(file); - BufferedOutputStream bos = new BufferedOutputStream(fos); - InputStream hdi = hashDataInput.getHashDataInput(); - int b; - while ((b = hdi.read()) != -1) { - bos.write(b); - } - bos.flush(); - bos.close(); - } catch (IOException ex) { - log.error("Failed to write HashDataInput to file " + file + ": " + ex.getMessage()); - showErrorDialog(ERR_WRITE_HASHDATA, new Object[] {ex.getMessage()}, null, null); - ex.printStackTrace(); - } finally { - try { - fos.close(); - } catch (IOException ex) { - } - } - } - } - log.debug("done saving hashdatainput"); - if (okListener != null) { - okListener.actionPerformed(new ActionEvent(fileDialog, ActionEvent.ACTION_PERFORMED, okCommand)); - } - } - }); - } - private void registerHelpListener(ActionListener helpListener) { if (helpListener != null) { this.helpListener = new HelpMouseListener(helpListener); @@ -1371,6 +1503,11 @@ public class BKUGUIImpl implements BKUGUIFacade { } } + + //////////////////////////////////////////////////////////////////////////// + // INITIALIZERS (MAY BE OVERRIDDEN BY SUBCLASSES) + //////////////////////////////////////////////////////////////////////////// + /** * Called from constructor. * Subclasses may override this method to ensure the message bundle is loaded diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataViewer.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataViewer.java deleted file mode 100644 index 6c097b2a..00000000 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataViewer.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright 2008 Federal Chancellery Austria and - * Graz University of Technology - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package at.gv.egiz.bku.gui; - -import at.gv.egiz.bku.gui.html.RestrictedHTMLEditorKit; -import at.gv.egiz.stal.HashDataInput; -import java.awt.Component; -import java.awt.Container; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Frame; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.Charset; -import java.text.MessageFormat; -import java.util.ResourceBundle; -import javax.swing.GroupLayout; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JEditorPane; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.LayoutStyle; -import javax.swing.text.Document; -import javax.swing.text.EditorKit; -import javax.swing.text.StyledEditorKit; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * - * @author Clemens Orthacker - */ -public class HashDataViewer extends JDialog - implements ActionListener { - - public static final String PLAINTEXT_FONT = "Monospaced"; - protected static final Log log = LogFactory.getLog(HashDataViewer.class); - - private static HashDataViewer dialog; - - protected ResourceBundle messages; - - /** - * - * @param signedReferences currently, only one hashdata input (the first in the list) is displayed - */ - public static void showHashDataInput(HashDataInput hashDataInput, - ResourceBundle messages, - ActionListener saveListener, - String saveCommand, - ActionListener helpListener) { - showHashDataInput(null, hashDataInput, messages, saveListener, saveCommand, helpListener); - } - - /** - * - * @param frameComp owner - */ - public static void showHashDataInput(Component frameComp, - HashDataInput hashDataInput, - ResourceBundle messages, - ActionListener saveListener, - String saveCommand, - ActionListener helpListener) { - - Frame frame = null; - if (frameComp != null) { - JOptionPane.getFrameForComponent(frameComp); - } - dialog = new HashDataViewer(frame, - messages, - hashDataInput, - saveListener, - saveCommand, - helpListener); - dialog.setVisible(true); - } - - private HashDataViewer(Frame frame, - ResourceBundle messages, - HashDataInput hashDataInput, - ActionListener saveListener, - String saveCommand, - ActionListener helpListener) { - super(frame, messages.getString(BKUGUIFacade.WINDOWTITLE_VIEWER), true); - this.messages = messages; - - Charset cs; - if (hashDataInput.getEncoding() == null) { - cs = Charset.forName("UTF-8"); - } else { - try { - cs = Charset.forName(hashDataInput.getEncoding()); - } catch (Exception ex) { - log.debug("charset " + hashDataInput.getEncoding() + " not supported, assuming UTF-8: " + ex.getMessage()); - cs = Charset.forName("UTF-8"); - } - } - - - InputStreamReader isr = new InputStreamReader(hashDataInput.getHashDataInput(), cs); - Reader content = new BufferedReader(isr); - - JPanel hashDataPanel = createViewerPanel(content, - hashDataInput.getMimeType(), - helpListener); - JPanel buttonPanel = createButtonPanel(saveListener, saveCommand); - initContentPane(new Dimension(600, 400), hashDataPanel, buttonPanel); - - pack(); - if (frame != null) { - setLocationRelativeTo(frame); - } else { - setLocationByPlatform(true); - } - } - - private void initContentPane(Dimension preferredSize, JPanel viewerPanel, JPanel buttonPanel) { - Container contentPane = getContentPane(); - contentPane.setPreferredSize(preferredSize); - - GroupLayout mainLayout = new GroupLayout(contentPane); - contentPane.setLayout(mainLayout); - - mainLayout.setHorizontalGroup( - mainLayout.createSequentialGroup().addContainerGap().addGroup( - mainLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addComponent(viewerPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)).addContainerGap()); - mainLayout.setVerticalGroup( - mainLayout.createSequentialGroup() - .addContainerGap() - .addComponent(viewerPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(buttonPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addContainerGap()); - } - - /** - * - * @param messages - * @param content - * @param mimeType defaults to text/plain if null - * @param encoding must be null if document contains charset declaration (e.g. HTML page), otherwise the parser crashes - * @param helpListener may be null - * @return - */ - private JPanel createViewerPanel(Reader content, - String mimeType, - final ActionListener helpListener) { - - if (mimeType == null) { - mimeType = "text/plain"; - } - log.debug("viewer dialog: " + mimeType); - - JEditorPane viewer = new JEditorPane(); - viewer.setEditable(false); - viewer.setContentType(mimeType); - - if ("text/plain".equals(mimeType)) { - viewer.setEditorKit(new StyledEditorKit()); - viewer.setFont(new Font(PLAINTEXT_FONT, viewer.getFont().getStyle(), viewer.getFont().getSize())); -// } else if ("text/html".equals(mimeType)) { -// viewer.setEditorKit(new RestrictedHTMLEditorKit()); - } else if ("application/xhtml+xml".equals(mimeType)) { - viewer.setContentType("text/html"); - } - - EditorKit editorKit = viewer.getEditorKit(); - Document document = editorKit.createDefaultDocument(); -// document.putProperty("IgnoreCharsetDirective", new Boolean(true)); - - try { - viewer.read(content, document); - content.close(); - } catch (Exception ex) { - log.error(ex.getMessage(), ex); - String p = messages.getString(BKUGUIFacade.ERR_VIEWER); - viewer.setText(MessageFormat.format(p, ex.getMessage())); - } - - JScrollPane scrollPane = new JScrollPane(viewer); - scrollPane.setPreferredSize(viewer.getPreferredSize()); - scrollPane.setAlignmentX(LEFT_ALIGNMENT); - viewer.setCaretPosition(0); - - JPanel viewerPanel = new JPanel(); - GroupLayout viewerPanelLayout = new GroupLayout(viewerPanel); - viewerPanel.setLayout(viewerPanelLayout); - - GroupLayout.SequentialGroup infoHorizontal = viewerPanelLayout.createSequentialGroup(); - GroupLayout.ParallelGroup infoVertical = viewerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); - - if ("application/xhtml+xml".equals(mimeType)) { - JLabel viewerLabel = new JLabel(); - viewerLabel.setText(messages.getString(BKUGUIFacade.WARNING_XHTML)); - viewerLabel.setFont(viewerLabel.getFont().deriveFont(viewerLabel.getFont().getStyle() | java.awt.Font.BOLD)); - viewerLabel.setLabelFor(viewer); - - infoHorizontal.addComponent(viewerLabel); - infoVertical.addComponent(viewerLabel); - } - - if (helpListener != null) { - JLabel helpLabel = new JLabel(); - helpLabel.setIcon(new ImageIcon(getClass().getResource(BKUGUIFacade.HELP_IMG))); - helpLabel.getAccessibleContext().setAccessibleName(messages.getString(BKUGUIFacade.ALT_HELP)); - helpLabel.addMouseListener(new MouseAdapter() { - - @Override - public void mouseClicked(MouseEvent arg0) { - ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, BKUGUIFacade.HELP_HASHDATAVIEWER); - helpListener.actionPerformed(e); - } - }); - helpLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - - infoHorizontal - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel); - infoVertical - .addComponent(helpLabel); - } - - viewerPanelLayout.setHorizontalGroup( - viewerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(infoHorizontal) - .addComponent(scrollPane)); - viewerPanelLayout.setVerticalGroup( - viewerPanelLayout.createSequentialGroup() - .addGroup(infoVertical) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(scrollPane)); - - - return viewerPanel; - } - - private JPanel createButtonPanel(ActionListener saveListener, String saveCommand) { - JButton closeButton = new JButton(); - closeButton.setText(messages.getString(BKUGUIFacade.BUTTON_CLOSE)); - closeButton.addActionListener(this); - - JButton saveButton = new JButton(); - saveButton.setText(messages.getString(BKUGUIFacade.BUTTON_SAVE)); - saveButton.setActionCommand(saveCommand); - saveButton.addActionListener(saveListener); - - int buttonSize = closeButton.getPreferredSize().width; - if (saveButton.getPreferredSize().width > buttonSize) { - buttonSize = saveButton.getPreferredSize().width; - } - - JPanel buttonPanel = new JPanel(); - GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); - buttonPanel.setLayout(buttonPanelLayout); - - buttonPanelLayout.setHorizontalGroup( - buttonPanelLayout.createSequentialGroup().addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(saveButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addComponent(closeButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); - buttonPanelLayout.setVerticalGroup( - buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE).addComponent(saveButton).addComponent(closeButton)); - - return buttonPanel; - } - - @Override - public void actionPerformed(ActionEvent e) { - HashDataViewer.dialog.setVisible(false); - } -} diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java new file mode 100644 index 00000000..6a16306b --- /dev/null +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java @@ -0,0 +1,371 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.bku.gui; + +import at.gv.egiz.stal.HashDataInput; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.Charset; +import java.text.MessageFormat; +import java.util.ResourceBundle; +import javax.swing.GroupLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JEditorPane; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.LayoutStyle; +import javax.swing.SwingUtilities; +import javax.swing.text.Document; +import javax.swing.text.EditorKit; +import javax.swing.text.StyledEditorKit; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Clemens Orthacker + */ +public class SecureViewerDialog extends JDialog implements ActionListener { + + public static final String PLAINTEXT_FONT = "Monospaced"; + public static final Dimension VIEWER_DIMENSION = new Dimension(600, 400); + protected static final Log log = LogFactory.getLog(SecureViewerDialog.class); + +// private static SecureViewerDialog dialog; + protected ResourceBundle messages; + protected JEditorPane viewer; + protected JLabel viewerLabel; + protected JScrollPane scrollPane; + protected HashDataInput content; //remember for save dialog + + /** + * Create and display a modal SecureViewer dialog. + * This method blocks until the dialog's close button is pressed. + * + * @param owner, dialog is positioned relative to its owner + * (if null, at default location of native windowing system) + */ +// public static void showDataToBeSigned(HashDataInput dataToBeSigned, +// ResourceBundle messages, +// ActionListener saveListener, String saveCommand, +// ActionListener helpListener) { +// +//// Frame ownerFrame = (owner != null) ? +//// JOptionPane.getFrameForComponent(owner) : +//// null; +// dialog = new SecureViewerDialog(null, messages, +// saveListener, saveCommand, helpListener); +// dialog.setContent(dataToBeSigned); +// dialog.setVisible(true); +// } + public SecureViewerDialog(Frame owner, ResourceBundle messages, +// ActionListener saveListener, String saveCommand, + ActionListener helpListener) { + super(owner, messages.getString(BKUGUIFacade.WINDOWTITLE_VIEWER), true); + this.messages = messages; + + initContentPane(VIEWER_DIMENSION, + createViewerPanel(helpListener), + createButtonPanel()); //saveListener, saveCommand)); + + pack(); + if (owner != null) { + setLocationRelativeTo(owner); + } else { + setLocationByPlatform(true); + } + } + + private void initContentPane(Dimension preferredSize, + JPanel viewerPanel, JPanel buttonPanel) { + Container contentPane = getContentPane(); + contentPane.setPreferredSize(preferredSize); + + GroupLayout mainLayout = new GroupLayout(contentPane); + contentPane.setLayout(mainLayout); + + mainLayout.setHorizontalGroup( + mainLayout.createSequentialGroup().addContainerGap().addGroup( + mainLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addComponent(viewerPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)).addContainerGap()); + mainLayout.setVerticalGroup( + mainLayout.createSequentialGroup().addContainerGap().addComponent(viewerPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED).addComponent(buttonPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addContainerGap()); + } + + /** + * @param helpListener may be null + */ + private JPanel createViewerPanel(final ActionListener helpListener) { + viewer = new JEditorPane(); + viewer.setEditable(false); + + scrollPane = new JScrollPane(); + + JPanel viewerPanel = new JPanel(); + GroupLayout viewerPanelLayout = new GroupLayout(viewerPanel); + viewerPanel.setLayout(viewerPanelLayout); + + GroupLayout.SequentialGroup infoHorizontal = viewerPanelLayout.createSequentialGroup(); + GroupLayout.ParallelGroup infoVertical = viewerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); + + viewerLabel = new JLabel(); + viewerLabel.setFont(viewerLabel.getFont().deriveFont(viewerLabel.getFont().getStyle() | java.awt.Font.BOLD)); +// viewerLabel.setLabelFor(viewer); + + infoHorizontal.addComponent(viewerLabel); + infoVertical.addComponent(viewerLabel); + + if (helpListener != null) { + JLabel helpLabel = new JLabel(); + helpLabel.setIcon(new ImageIcon(getClass().getResource(BKUGUIFacade.HELP_IMG))); + helpLabel.getAccessibleContext().setAccessibleName(messages.getString(BKUGUIFacade.ALT_HELP)); + helpLabel.addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent arg0) { + ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, BKUGUIFacade.HELP_HASHDATAVIEWER); + helpListener.actionPerformed(e); + } + }); + helpLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + + infoHorizontal.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE).addComponent(helpLabel); + infoVertical.addComponent(helpLabel); + } + + viewerPanelLayout.setHorizontalGroup( + viewerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(infoHorizontal).addComponent(scrollPane)); + viewerPanelLayout.setVerticalGroup( + viewerPanelLayout.createSequentialGroup().addGroup(infoVertical).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addComponent(scrollPane)); + + return viewerPanel; + } + + /** + * Sets the hashdataInput to be displayed and makes the dialog visible. + * This method blocks until the dialog's close button is pressed. + * + * @param mimeType defaults to text/plain if null + * @param encoding must be null if document contains charset declaration (e.g. HTML page), otherwise the parser crashes + + * @param hashDataInput + */ + public void setContent(HashDataInput hashDataInput) { + + this.content = null; + + String mimeType = hashDataInput.getMimeType(); + if (mimeType == null) { + mimeType = "text/plain"; + } + log.debug("secure viewer mime type: " + mimeType); + // loads editorkit for text/plain if unrecognized + viewer.setContentType(mimeType); + + if ("text/plain".equals(mimeType)) { + viewer.setEditorKit(new StyledEditorKit()); + viewer.setFont(new Font(PLAINTEXT_FONT, viewer.getFont().getStyle(), viewer.getFont().getSize())); +// } else if ("text/html".equals(mimeType)) { +// viewer.setEditorKit(new RestrictedHTMLEditorKit()); + } else if ("application/xhtml+xml".equals(mimeType)) { + viewer.setContentType("text/html"); + } + + EditorKit editorKit = viewer.getEditorKit(); + Document document = editorKit.createDefaultDocument(); +// document.putProperty("IgnoreCharsetDirective", new Boolean(true)); + + try { + Charset cs = (hashDataInput.getEncoding() == null) ? Charset.forName("UTF-8") : Charset.forName(hashDataInput.getEncoding()); + log.debug("secure viewer encoding: " + cs.toString()); + + InputStreamReader isr = new InputStreamReader(hashDataInput.getHashDataInput(), cs); + Reader contentReader = new BufferedReader(isr); + viewer.read(contentReader, document); + contentReader.close(); + + this.content = hashDataInput; + +// } catch (IllegalCharsetNameException ex) { +// } catch (UnsupportedCharsetException ex) { + } catch (Exception ex) { + log.error(ex.getMessage(), ex); + String p = messages.getString(BKUGUIFacade.ERR_VIEWER); + viewer.setText(MessageFormat.format(p, ex.getMessage())); + } + viewer.setCaretPosition(0); + + scrollPane.setViewportView(viewer); + scrollPane.setPreferredSize(viewer.getPreferredSize()); + scrollPane.setAlignmentX(LEFT_ALIGNMENT); + + if ("application/xhtml+xml".equals(mimeType)) { + viewerLabel.setText(messages.getString(BKUGUIFacade.WARNING_XHTML)); + } else { + viewerLabel.setText(""); + } + + setVisible(true); + } + + private JPanel createButtonPanel() { //ActionListener saveListener, String saveCommand) { + JButton closeButton = new JButton(); + closeButton.setText(messages.getString(BKUGUIFacade.BUTTON_CLOSE)); + closeButton.setActionCommand("close"); + closeButton.addActionListener(this); + + JButton saveButton = new JButton(); + saveButton.setText(messages.getString(BKUGUIFacade.BUTTON_SAVE)); + saveButton.setActionCommand("save"); + saveButton.addActionListener(this); + + int buttonSize = closeButton.getPreferredSize().width; + if (saveButton.getPreferredSize().width > buttonSize) { + buttonSize = saveButton.getPreferredSize().width; + } + + JPanel buttonPanel = new JPanel(); + GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); + buttonPanel.setLayout(buttonPanelLayout); + + buttonPanelLayout.setHorizontalGroup( + buttonPanelLayout.createSequentialGroup().addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(saveButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addComponent(closeButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); + buttonPanelLayout.setVerticalGroup( + buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE).addComponent(saveButton).addComponent(closeButton)); + + return buttonPanel; + } + + @Override + public void actionPerformed(ActionEvent e) { + if ("close".equals(e.getActionCommand())) { +// SecureViewerDialog.dialog.setVisible(false); + log.trace("closing secure viewer"); + setVisible(false); + log.trace("secure viewer closed"); + } else if ("save".equals(e.getActionCommand())) { + log.trace("display secure viewer save dialog"); + showSaveDialog(content, null, null); + log.trace("done secure viewer save"); + } else { + log.warn("unknown action command " + e.getActionCommand()); + } + } + + private void showSaveDialog(final HashDataInput hashDataInput, + final ActionListener okListener, final String okCommand) { + + log.debug("scheduling save dialog [" + Thread.currentThread().getName() + "]"); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + log.debug("show save dialog [" + Thread.currentThread().getName() + "]"); + + String userHome = System.getProperty("user.home"); + + JFileChooser fileDialog = new JFileChooser(userHome); + fileDialog.setMultiSelectionEnabled(false); + fileDialog.setDialogType(JFileChooser.SAVE_DIALOG); + fileDialog.setFileHidingEnabled(true); + fileDialog.setDialogTitle(messages.getString(BKUGUIFacade.WINDOWTITLE_SAVE)); + fileDialog.setFileSelectionMode(JFileChooser.FILES_ONLY); + String mimeType = hashDataInput.getMimeType(); + MimeFilter mimeFilter = new MimeFilter(mimeType, messages); + fileDialog.setFileFilter(mimeFilter); + String filename = messages.getString(BKUGUIFacade.SAVE_HASHDATAINPUT_PREFIX) + + MimeFilter.getExtension(mimeType); + fileDialog.setSelectedFile(new File(userHome, filename)); + + //parent contentPane -> placed over applet + switch (fileDialog.showSaveDialog(fileDialog)) { + case JFileChooser.APPROVE_OPTION: + File file = fileDialog.getSelectedFile(); + String id = hashDataInput.getReferenceId(); + if (file.exists()) { + String msgPattern = messages.getString(BKUGUIFacade.MESSAGE_OVERWRITE); + int overwrite = JOptionPane.showConfirmDialog(fileDialog, + MessageFormat.format(msgPattern, file), + messages.getString(BKUGUIFacade.WINDOWTITLE_OVERWRITE), + JOptionPane.OK_CANCEL_OPTION); + if (overwrite != JOptionPane.OK_OPTION) { + return; + } + } + if (log.isDebugEnabled()) { + log.debug("writing hashdata input " + id + " (" + mimeType + ") to file " + file); + } + FileOutputStream fos = null; + try { + fos = new FileOutputStream(file); + BufferedOutputStream bos = new BufferedOutputStream(fos); + InputStream hdi = hashDataInput.getHashDataInput(); + int b; + while ((b = hdi.read()) != -1) { + bos.write(b); + } + bos.flush(); + bos.close(); + } catch (IOException ex) { + log.error("Failed to write " + file + ": " + ex.getMessage()); + log.debug(ex); + String errPattern = messages.getString(BKUGUIFacade.ERR_WRITE_HASHDATA); + JOptionPane.showMessageDialog(fileDialog, + MessageFormat.format(errPattern, ex.getMessage()), + messages.getString(BKUGUIFacade.WINDOWTITLE_ERROR), + JOptionPane.ERROR_MESSAGE); + } finally { + try { + if (fos != null) { + fos.close(); + } + } catch (IOException ex) { + } + } + break; + case JFileChooser.CANCEL_OPTION: + log.debug("cancelled save dialog"); + break; + } + if (okListener != null) { + okListener.actionPerformed(new ActionEvent(fileDialog, ActionEvent.ACTION_PERFORMED, okCommand)); + } + } + }); + } +} diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties index 6d651b2d..9bfe8fb1 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties @@ -25,6 +25,7 @@ title.retry=Falsche PIN title.wait=Bitte warten title.hashdata=Signaturdaten windowtitle.save=Signaturdaten speichern +windowtitle.error=Fehler windowtitle.savedir=Signaturdaten in Verzeichnis speichern windowtitle.overwrite=Datei \u00FCberschreiben? windowtitle.viewer=Signaturdaten @@ -79,7 +80,7 @@ error.unknown.param=Ein Fehler trat auf: {0} error.unknown=Ein Fehler trat auf error.test=Fehler1 {0} - Fehler2 {1} error.card.locked=B\u00FCrgerkarte ist gesperrt -error.card.notactivated=B\u00FCrgerkartenfunktion ist nicht aktiviert +error.card.notactivated=Die B\u00FCrgerkarte ist nicht aktiviert error.pin.timeout=Zeit\u00FCberschreitung bei Eingabe der PIN error.viewer=Der Inhalt kann nicht dargestellt werden: {0} error.external.link=Externer Link {0} wird nicht ge\u00F6ffnet diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties index 2fb66969..a36f9b83 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties @@ -25,6 +25,7 @@ title.retry=Wrong PIN title.wait=Please wait title.hashdata=Signature data windowtitle.save=Save signature data +windowtitle.error=Error windowtitle.savedir=Save signature data to directory windowtitle.overwrite=Overwrite file? windowtitle.viewer=Signature data diff --git a/BKUCommonGUI/src/main/resources/images/ChipperlingLogo.png b/BKUCommonGUI/src/main/resources/images/ChipperlingLogo.png new file mode 100644 index 00000000..eee4be4f Binary files /dev/null and b/BKUCommonGUI/src/main/resources/images/ChipperlingLogo.png differ diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java index c8cff617..b3eaf8c7 100644 --- a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java +++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java @@ -39,8 +39,9 @@ public class BKUGUITest { public void testBKUGUI() { JFrame testFrame = new JFrame("BKUGUITest"); Container contentPane = testFrame.getContentPane(); - contentPane.setPreferredSize(new Dimension(170, 150)); - BKUGUIFacade gui = new BKUGUIImpl(contentPane, null, BKUGUIFacade.Style.tiny, null, null); +// contentPane.setPreferredSize(new Dimension(170, 150)); + contentPane.setPreferredSize(new Dimension(290, 190)); + BKUGUIFacade gui = new BKUGUIImpl(contentPane, null, BKUGUIFacade.Style.advanced, null, null); BKUGUIWorker worker = new BKUGUIWorker(); worker.init(gui); testFrame.pack(); diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java index 194e18b0..5475a45b 100644 --- a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java +++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java @@ -149,7 +149,9 @@ public class BKUGUIWorker implements Runnable { // // Thread.sleep(2000); // - gui.showSignaturePINDialog(signPinSpec, -1, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); +// gui.showSignaturePINDialog(signPinSpec, -1, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata"); + + gui.showPinpadSignaturePINDialog(signPinSpec, -1, hashdataListener, "hashdata"); // // Thread.sleep(4000); // diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java index 5a0ba84a..3f560967 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/BKUGuiProxy.java @@ -144,4 +144,12 @@ public class BKUGuiProxy implements BKUGUIFacade { showDialog(); delegate.showMessageDialog(titleKey, msgKey); } + + @Override + public void showPinpadSignaturePINDialog(PINSpec pinSpec, int numRetries, + ActionListener viewerListener, String viewerCommand) { + showDialog(); + delegate.showPinpadSignaturePINDialog(pinSpec, numRetries, + viewerListener, viewerCommand); + } } diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalBKUWorker.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalBKUWorker.java index 61cc7c4c..a782de1a 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalBKUWorker.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalBKUWorker.java @@ -37,7 +37,8 @@ public class LocalBKUWorker extends AbstractBKUWorker { public LocalBKUWorker(BKUGUIFacade gui, JDialog container) { super(gui); this.container = container; - addRequestHandler(SignRequest.class, new LocalSignRequestHandler()); + addRequestHandler(SignRequest.class, + new LocalSignRequestHandler(new LocalSecureViewer(gui))); } @Override diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSecureViewer.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSecureViewer.java new file mode 100644 index 00000000..cbe5af7a --- /dev/null +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSecureViewer.java @@ -0,0 +1,109 @@ + +package at.gv.egiz.bku.local.stal; + +import at.gv.egiz.bku.slcommands.impl.DataObjectHashDataInput; +import at.gv.egiz.bku.smccstal.SecureViewer; +import java.io.IOException; +import java.util.ArrayList; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.impl.ByteArrayHashDataInput; +import at.gv.egiz.stal.signedinfo.ReferenceType; +import at.gv.egiz.stal.signedinfo.SignedInfoType; +import java.awt.event.ActionListener; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.Collections; +import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class LocalSecureViewer implements SecureViewer { + + private static final Log log = LogFactory.getLog(LocalSignRequestHandler.class); + private List hashDataInputs = Collections.EMPTY_LIST; + + protected BKUGUIFacade gui; + + public LocalSecureViewer(BKUGUIFacade gui) { + this.gui = gui; + } + + public void setDataToBeSigned(List dataToBeSigned) { + this.hashDataInputs = dataToBeSigned; + } + + /** + * + * @param dsigReferences + * @throws java.lang.Exception + */ + @Override + public void displayDataToBeSigned(SignedInfoType signedInfo, + ActionListener okListener, String okCommand) + throws Exception { + if (signedInfo.getReference().size() == 0) { + log.error("No hashdata input selected to be displayed: null"); + throw new Exception("No HashData Input selected to be displayed"); + } + + ArrayList selectedHashDataInputs = new ArrayList(); + for (ReferenceType dsigRef : signedInfo.getReference()) { + // don't get Manifest, QualifyingProperties, ... + if (dsigRef.getType() == null) { + String dsigRefId = dsigRef.getId(); + if (dsigRefId != null) { + boolean hdiAvailable = false; + for (HashDataInput hashDataInput : hashDataInputs) { + if (dsigRefId.equals(hashDataInput.getReferenceId())) { + log.debug("display hashdata input for dsig:SignedReference " + + dsigRefId); + selectedHashDataInputs.add( + ensureCachedHashDataInput(hashDataInput)); + hdiAvailable = true; + break; + } + } + if (!hdiAvailable) { + log.error("no hashdata input for dsig:SignedReference " + dsigRefId); + throw new Exception( + "No HashDataInput available for dsig:SignedReference " + dsigRefId); + } + } else { + throw new Exception( + "Cannot get HashDataInput for dsig:Reference without Id attribute"); + } + } + } + + if (selectedHashDataInputs.size() < 1) { + log.error("dsig:SignedInfo does not contain a data reference"); + throw new Exception("dsig:SignedInfo does not contain a data reference"); + } + gui.showSecureViewer(selectedHashDataInputs, okListener, okCommand); + } + + + private HashDataInput ensureCachedHashDataInput(HashDataInput hashDataInput) + throws IOException { + if (!(hashDataInput instanceof DataObjectHashDataInput)) { + + log.warn("expected DataObjectHashDataInput for LocalSignRequestHandler, got " + + hashDataInput.getClass().getName()); + + InputStream hdIs = hashDataInput.getHashDataInput(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(hdIs.available()); + int b; + while ((b = hdIs.read()) != -1) { + baos.write(b); + } + hashDataInput = new ByteArrayHashDataInput(baos.toByteArray(), + hashDataInput.getReferenceId(), + hashDataInput.getMimeType(), + hashDataInput.getEncoding()); + } + return hashDataInput; + } + +} diff --git a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java index 531e6591..492b8a05 100644 --- a/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java +++ b/BKULocal/src/main/java/at/gv/egiz/bku/local/stal/LocalSignRequestHandler.java @@ -16,9 +16,7 @@ */ package at.gv.egiz.bku.local.stal; -import at.gv.egiz.bku.slcommands.impl.DataObjectHashDataInput; -import java.io.IOException; -import java.util.ArrayList; +import at.gv.egiz.bku.smccstal.SecureViewer; import java.util.Collections; import java.util.List; @@ -40,9 +38,16 @@ import java.io.InputStream; * @author clemens */ public class LocalSignRequestHandler extends SignRequestHandler { +// implements SecureViewer { private static final Log log = LogFactory.getLog(LocalSignRequestHandler.class); - private List hashDataInputs = Collections.EMPTY_LIST; + + protected LocalSecureViewer secureViewer; + + public LocalSignRequestHandler(LocalSecureViewer secureViewer) { + super(secureViewer); + } + /** * If the request is a SIGN request, it contains a list of DataObjectHashDataInput @@ -53,75 +58,13 @@ public class LocalSignRequestHandler extends SignRequestHandler { */ @SuppressWarnings("unchecked") @Override - public STALResponse handleRequest(STALRequest request) throws InterruptedException { + public STALResponse handleRequest(STALRequest request) + throws InterruptedException { + if (request instanceof SignRequest) { SignRequest signReq = (SignRequest) request; - hashDataInputs = signReq.getHashDataInput(); + secureViewer.setDataToBeSigned(signReq.getHashDataInput()); } return super.handleRequest(request); } - - /** - * - * @param dsigReferences - * @throws java.lang.Exception - */ - @Override - public void displayDataToBeSigned(List dsigReferences) throws Exception { - if (dsigReferences == null || dsigReferences.size() < 1) { - log.error("No hashdata input selected to be displayed: null"); - throw new Exception("No HashData Input selected to be displayed"); - } - - ArrayList selectedHashDataInputs = new ArrayList(); - for (ReferenceType dsigRef : dsigReferences) { - // don't get Manifest, QualifyingProperties, ... - if (dsigRef.getType() == null) { - String dsigRefId = dsigRef.getId(); - if (dsigRefId != null) { - boolean hdiAvailable = false; - for (HashDataInput hashDataInput : hashDataInputs) { - if (dsigRefId.equals(hashDataInput.getReferenceId())) { - log.debug("display hashdata input for dsig:SignedReference " + dsigRefId); - if (!(hashDataInput instanceof DataObjectHashDataInput)) { - log.warn( - "expected DataObjectHashDataInput for LocalSignRequestHandler, got " + hashDataInput.getClass().getName()); - hashDataInput = getByteArrayHashDataInput(hashDataInput); - } - selectedHashDataInputs.add(hashDataInput); - hdiAvailable = true; - break; - } - } - if (!hdiAvailable) { - log.error("no hashdata input for dsig:SignedReference " + dsigRefId); - throw new Exception( - "No HashDataInput available for dsig:SignedReference " + dsigRefId); - } - } else { - throw new Exception( - "Cannot get HashDataInput for dsig:Reference without Id attribute"); - } - } - } - - if (selectedHashDataInputs.size() < 1) { - log.error("dsig:SignedInfo does not contain a data reference"); - throw new Exception("dsig:SignedInfo does not contain a data reference"); - } - gui.showSecureViewer(selectedHashDataInputs, this, "hashDataDone"); - } - - private ByteArrayHashDataInput getByteArrayHashDataInput(HashDataInput hashDataInput) throws IOException { - - InputStream hdIs = hashDataInput.getHashDataInput(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(hdIs.available()); - int b; - while ((b = hdIs.read()) != -1) { - baos.write(b); - } - ByteArrayHashDataInput hdi = new ByteArrayHashDataInput(baos.toByteArray(), hashDataInput.getReferenceId(), hashDataInput.getMimeType(), hashDataInput.getEncoding()); - - return hdi; - } } diff --git a/BKUOnline/src/main/resources/at/gv/egiz/bku/online/conf/defaultConf.properties b/BKUOnline/src/main/resources/at/gv/egiz/bku/online/conf/defaultConf.properties index e2f07481..04c9c7bf 100644 --- a/BKUOnline/src/main/resources/at/gv/egiz/bku/online/conf/defaultConf.properties +++ b/BKUOnline/src/main/resources/at/gv/egiz/bku/online/conf/defaultConf.properties @@ -40,9 +40,12 @@ SSL.sslProtocol=TLS # warning do not set the following property to true # its intended for debugging and testing only SSL.disableAllChecks=false +#SSL.disableHostnameVerification=true # ------------ END SSL Config -------------------- +#UserAgent=citizen-card-environment/1.2 MOCCA/1.0 + ValidateHashDataInputs=true AppletTimeout=300000 diff --git a/BKUOnline/src/main/resources/log4j.properties b/BKUOnline/src/main/resources/log4j.properties index f608c83d..25ea9faa 100644 --- a/BKUOnline/src/main/resources/log4j.properties +++ b/BKUOnline/src/main/resources/log4j.properties @@ -30,7 +30,7 @@ log4j.appender.STDOUT.layout.ConversionPattern=%-5p | %t | %c %x - %m%n log4j.appender.file=org.apache.log4j.RollingFileAppender log4j.appender.file.maxFileSize=500KB log4j.appender.file.maxBackupIndex=9 -log4j.appender.file.File=${catalina.home}/logs/bkuonline.log +log4j.appender.file.File=${catalina.base}/logs/bkuonline.log log4j.appender.file.threshold=trace log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p | %t | %c{1}:%L - %m%n \ No newline at end of file diff --git a/BKUOnline/src/main/webapp/SLRequestForm.html b/BKUOnline/src/main/webapp/SLRequestForm.html index 9ff7b68a..4714e82f 100644 --- a/BKUOnline/src/main/webapp/SLRequestForm.html +++ b/BKUOnline/src/main/webapp/SLRequestForm.html @@ -103,6 +103,33 @@ --> +