diff --git a/cacert.pem b/cacert.pem new file mode 100644 index 00000000..82d304fd --- /dev/null +++ b/cacert.pem @@ -0,0 +1,79 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 16464111046498525641 (0xe47c45c4252121c9) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=CZ, ST=Vysocina, O=bukova.info, CN=Josef Rokos/emailAddress=rokos@bukova.info + Validity + Not Before: Jun 24 09:59:50 2015 GMT + Not After : Jun 21 09:59:50 2025 GMT + Subject: C=CZ, ST=Vysocina, O=bukova.info, CN=Josef Rokos/emailAddress=rokos@bukova.info + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:bc:fb:64:50:5b:58:03:8c:20:1c:77:d3:50:31: + 94:55:78:d6:05:bb:bc:88:9d:cb:20:b1:8c:ff:ac: + fc:97:1a:b1:9c:29:c4:ac:af:ed:3b:de:93:d5:cf: + 75:3e:d0:05:41:32:bf:12:25:53:60:28:af:ff:3e: + 3c:3a:4c:52:78:3f:b2:78:b9:c6:2f:fc:0e:44:eb: + 65:c3:7f:38:2b:ab:88:37:8c:68:55:69:e3:3d:5e: + 9b:99:25:11:55:06:ab:e8:c1:fa:54:da:5b:e7:9b: + 3e:3f:39:4f:cf:b3:cb:48:cf:96:02:89:0b:7e:24: + c7:00:e9:ce:8d:ea:07:cf:21:f2:89:51:c8:cc:7a: + 04:e4:68:6f:1c:a8:e0:76:18:40:62:ee:2f:bd:13: + 64:b7:1e:2e:18:bb:b1:d4:17:d5:fb:1f:07:59:65: + 46:f0:c4:51:dc:ac:62:ff:31:a8:72:26:a6:1a:88: + 37:23:82:49:9a:02:d2:39:74:98:71:7f:a4:77:52: + 3a:ed:22:2e:99:9c:81:2c:48:16:3c:82:7b:af:2c: + 0d:4b:28:4d:e0:46:7d:b5:b8:ea:3f:e7:5a:5b:4f: + d8:06:b2:a3:86:2f:8b:5b:9c:bc:04:2e:64:b6:e1: + 09:c9:14:6d:54:7e:86:40:7b:66:33:27:33:4a:3d: + 7c:97 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EF:9B:88:5C:07:27:79:EA:60:90:5C:7A:28:45:FB:7F:35:E6:CB:3F + X509v3 Authority Key Identifier: + keyid:EF:9B:88:5C:07:27:79:EA:60:90:5C:7A:28:45:FB:7F:35:E6:CB:3F + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 08:e9:a4:32:cc:35:7c:66:5a:ea:f2:bd:e6:75:78:81:52:11: + 22:27:32:c9:ec:91:6e:51:8a:f1:1e:0f:25:8a:e1:64:ba:e4: + 85:1c:e4:fd:75:f0:26:3d:65:62:16:29:20:4f:5f:d2:66:36: + de:2b:bd:7b:96:71:f6:2c:d1:c5:54:69:89:dd:52:20:49:49: + b1:ac:09:b4:1e:33:59:0d:89:fd:a4:28:7a:70:96:e5:cb:58: + 7e:b9:1d:02:7a:33:ee:ad:6a:ad:2c:3c:5e:7d:cc:f5:72:69: + 51:fd:77:b4:0f:10:fd:9e:c2:1a:04:c5:a9:56:6e:fd:66:9f: + b6:1c:f9:d3:68:f4:4f:8c:6c:67:af:f5:e0:a5:30:67:a6:a7: + 9b:6e:16:89:8a:e5:b4:20:f4:f7:74:f4:9c:ca:5d:c7:2f:e6: + 30:9d:6b:2e:95:29:c1:e7:aa:d7:d6:59:dc:a9:f0:10:40:02: + 66:3f:58:a2:38:8c:89:1a:0b:94:1a:e5:80:49:14:44:f4:06: + b1:11:1a:cd:ef:76:6a:bf:f8:6f:58:9d:af:a3:6b:9a:8e:bb: + 6c:10:d6:d8:4e:73:58:20:0b:99:38:41:d4:22:d4:80:0b:09: + 0d:25:40:3e:66:15:a0:44:4e:d6:59:5a:58:07:e5:4b:62:f1: + e9:ae:b6:7c +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIJAOR8RcQlISHJMA0GCSqGSIb3DQEBBQUAMG4xCzAJBgNV +BAYTAkNaMREwDwYDVQQIDAhWeXNvY2luYTEUMBIGA1UECgwLYnVrb3ZhLmluZm8x +FDASBgNVBAMMC0pvc2VmIFJva29zMSAwHgYJKoZIhvcNAQkBFhFyb2tvc0BidWtv +dmEuaW5mbzAeFw0xNTA2MjQwOTU5NTBaFw0yNTA2MjEwOTU5NTBaMG4xCzAJBgNV +BAYTAkNaMREwDwYDVQQIDAhWeXNvY2luYTEUMBIGA1UECgwLYnVrb3ZhLmluZm8x +FDASBgNVBAMMC0pvc2VmIFJva29zMSAwHgYJKoZIhvcNAQkBFhFyb2tvc0BidWtv +dmEuaW5mbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALz7ZFBbWAOM +IBx301AxlFV41gW7vIidyyCxjP+s/JcasZwpxKyv7Tvek9XPdT7QBUEyvxIlU2Ao +r/8+PDpMUng/sni5xi/8DkTrZcN/OCuriDeMaFVp4z1em5klEVUGq+jB+lTaW+eb +Pj85T8+zy0jPlgKJC34kxwDpzo3qB88h8olRyMx6BORobxyo4HYYQGLuL70TZLce +Lhi7sdQX1fsfB1llRvDEUdysYv8xqHImphqINyOCSZoC0jl0mHF/pHdSOu0iLpmc +gSxIFjyCe68sDUsoTeBGfbW46j/nWltP2Aayo4Yvi1ucvAQuZLbhCckUbVR+hkB7 +ZjMnM0o9fJcCAwEAAaNQME4wHQYDVR0OBBYEFO+biFwHJ3nqYJBceihF+3815ss/ +MB8GA1UdIwQYMBaAFO+biFwHJ3nqYJBceihF+3815ss/MAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADggEBAAjppDLMNXxmWuryveZ1eIFSESInMsnskW5RivEe +DyWK4WS65IUc5P118CY9ZWIWKSBPX9JmNt4rvXuWcfYs0cVUaYndUiBJSbGsCbQe +M1kNif2kKHpwluXLWH65HQJ6M+6taq0sPF59zPVyaVH9d7QPEP2ewhoExalWbv1m +n7Yc+dNo9E+MbGev9eClMGemp5tuFomK5bQg9Pd09JzKXccv5jCday6VKcHnqtfW +Wdyp8BBAAmY/WKI4jIkaC5Qa5YBJFET0BrERGs3vdmq/+G9Yna+ja5qOu2wQ1thO +c1ggC5k4QdQi1IALCQ0lQD5mFaBETtZZWlgH5Uti8emutnw= +-----END CERTIFICATE----- diff --git a/src/main/java/info/bukova/isspst/Constants.java b/src/main/java/info/bukova/isspst/Constants.java index e7fd3fb2..e0a945b1 100644 --- a/src/main/java/info/bukova/isspst/Constants.java +++ b/src/main/java/info/bukova/isspst/Constants.java @@ -168,4 +168,7 @@ public class Constants { public final static int LEN_TEXT = 255; public final static int LEN_DESCRIPTION = 8192; public final static int LEN_RESULT_MESSAGE = 8192; + + public final static String KEY_SIGN_DATA = "SIGN_DATA"; + public final static String KEY_SIGN_GUID = "SIGN_GUID"; } diff --git a/src/main/java/info/bukova/isspst/SessionData.java b/src/main/java/info/bukova/isspst/SessionData.java index 6d0fa7a2..9743550b 100644 --- a/src/main/java/info/bukova/isspst/SessionData.java +++ b/src/main/java/info/bukova/isspst/SessionData.java @@ -5,6 +5,7 @@ import info.bukova.isspst.data.User; import info.bukova.isspst.data.Workgroup; import java.io.Serializable; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -13,16 +14,18 @@ public class SessionData implements Serializable { /** * */ - private static final long serialVersionUID = -764426911263559758L; + private static final long serialVersionUID = -764426911263559759L; private List userCentres; private List userWorkgroups; private User currentUser; private Map> workgroupRoles; private boolean loginFailed; - + private Map properties; + public SessionData() { loginFailed = false; + properties = new HashMap(); } public List getUserCentres() { @@ -65,4 +68,11 @@ public class SessionData implements Serializable { this.loginFailed = loginFailed; } + public void setProperty(String key, Object value) { + properties.put(key, value); + } + + public Object getProperty(String key) { + return properties.get(key); + } } diff --git a/src/main/java/info/bukova/isspst/reporting/SignaturePdfHandler.java b/src/main/java/info/bukova/isspst/reporting/SignaturePdfHandler.java new file mode 100644 index 00000000..2e38ece8 --- /dev/null +++ b/src/main/java/info/bukova/isspst/reporting/SignaturePdfHandler.java @@ -0,0 +1,55 @@ +package info.bukova.isspst.reporting; + +import com.lowagie.text.Rectangle; +import com.lowagie.text.pdf.PdfAnnotation; +import com.lowagie.text.pdf.PdfFormField; +import com.lowagie.text.pdf.PdfName; +import net.sf.jasperreports.engine.JRGenericPrintElement; +import net.sf.jasperreports.engine.JRPropertiesMap; +import net.sf.jasperreports.engine.export.GenericElementHandler; +import net.sf.jasperreports.engine.export.GenericElementHandlerBundle; +import net.sf.jasperreports.engine.export.GenericElementPdfHandler; +import net.sf.jasperreports.engine.export.JRPdfExporter; +import net.sf.jasperreports.engine.export.JRPdfExporterContext; +import net.sf.jasperreports.extensions.ExtensionsRegistry; +import net.sf.jasperreports.extensions.ExtensionsRegistryFactory; +import net.sf.jasperreports.extensions.SingletonExtensionRegistry; + +/** + * @author Pepa Rokos + */ +public class SignaturePdfHandler implements GenericElementPdfHandler, GenericElementHandlerBundle, ExtensionsRegistryFactory { + + @Override + public ExtensionsRegistry createRegistry(String registryId, JRPropertiesMap properties) { + return new SingletonExtensionRegistry(GenericElementHandlerBundle.class, this); + } + + @Override + public void exportElement(JRPdfExporterContext exporterContext, JRGenericPrintElement element) { + PdfFormField field = PdfFormField.createSignature(exporterContext.getPdfWriter()); + field.setFieldName("signature"); + field.setFieldFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_LOCKED); + field.setWidget(new Rectangle(element.getX(), element.getY(), element.getX() + element.getWidth(), element.getY() + element.getHeight()), PdfName.HIGHLIGHT); + exporterContext.getPdfWriter().addAnnotation(field); + } + + @Override + public boolean toExport(JRGenericPrintElement element) { + return true; + } + + @Override + public String getNamespace() { + return "urn:sig:sig"; + } + + @Override + public GenericElementHandler getHandler(String elementName, String exporterKey) { + if (elementName.equals("signature") && exporterKey.equals(JRPdfExporter.PDF_EXPORTER_KEY)) { + return this; + } + + return null; + } +} diff --git a/src/main/java/info/bukova/isspst/signapi/JnlpGenerator.java b/src/main/java/info/bukova/isspst/signapi/JnlpGenerator.java new file mode 100644 index 00000000..26885a32 --- /dev/null +++ b/src/main/java/info/bukova/isspst/signapi/JnlpGenerator.java @@ -0,0 +1,10 @@ +package info.bukova.isspst.signapi; + +/** + * @author Pepa Rokos + */ +public interface JnlpGenerator { + + public byte[] generate(); + +} diff --git a/src/main/java/info/bukova/isspst/signapi/JnlpGeneratorImpl.java b/src/main/java/info/bukova/isspst/signapi/JnlpGeneratorImpl.java new file mode 100644 index 00000000..0b90c001 --- /dev/null +++ b/src/main/java/info/bukova/isspst/signapi/JnlpGeneratorImpl.java @@ -0,0 +1,109 @@ +package info.bukova.isspst.signapi; + +import org.springframework.beans.factory.annotation.Autowired; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.servlet.http.HttpServletRequest; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.ByteArrayOutputStream; + +/** + * @author Pepa Rokos + */ +public class JnlpGeneratorImpl implements JnlpGenerator { + + @Autowired + private HttpServletRequest request; + + @Override + public byte[] generate() { + String sessionId; + + if (request.getParameter("id") != null && !request.getParameter("id").isEmpty()) { + sessionId = request.getParameter("id"); + } else { + sessionId = request.getSession().getId(); + } + + try { + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + + Document document = docBuilder.newDocument(); + Element root = document.createElement("jnlp"); + root.setAttribute("spec", "1.0+"); + + String signerUrl = request.getRequestURL().toString(); + signerUrl = signerUrl.substring(0, signerUrl.indexOf(request.getServletPath())) + "/api/sign"; + + root.setAttribute("codebase", signerUrl); + root.setAttribute("href", "signer.jnlp" + "?id=" + sessionId); + document.appendChild(root); + + Element info = document.createElement("information"); + Element title = document.createElement("title"); + title.appendChild(document.createTextNode("Signer component")); + info.appendChild(title); + Element vendor = document.createElement("vendor"); + vendor.appendChild(document.createTextNode("bukova.info")); + info.appendChild(vendor); + root.appendChild(info); + + Element security = document.createElement("security"); + security.appendChild(document.createElement("all-permissions")); + root.appendChild(security); + + Element resources = document.createElement("resources"); + Element j2se = document.createElement("j2se"); + j2se.setAttribute("version", "1.8+"); + Element jar = document.createElement("jar"); + jar.setAttribute("href", "pdfsigner.jar"); + resources.appendChild(j2se); + resources.appendChild(jar); + root.appendChild(resources); + + Element appDesc = document.createElement("application-desc"); + appDesc.setAttribute("main-class", "info.bukova.pdfsigner.Main"); + Element argUrl = document.createElement("argument"); + argUrl.appendChild(document.createTextNode(signerUrl + "/data")); + appDesc.appendChild(argUrl); + Element argSession = document.createElement("argument"); + argSession.appendChild(document.createTextNode(sessionId)); + appDesc.appendChild(argSession); + root.appendChild(appDesc); + + + System.out.println(signerUrl); + System.out.println(request.getSession().getId()); + + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + DOMSource source = new DOMSource(document); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + StreamResult result = new StreamResult(bos); + + transformer.transform(source, result); + + return bos.toByteArray(); + + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } catch (TransformerConfigurationException e) { + e.printStackTrace(); + } catch (TransformerException e) { + e.printStackTrace(); + } + + return null; + } + +} diff --git a/src/main/java/info/bukova/isspst/signapi/SignData.java b/src/main/java/info/bukova/isspst/signapi/SignData.java new file mode 100644 index 00000000..cf71d69c --- /dev/null +++ b/src/main/java/info/bukova/isspst/signapi/SignData.java @@ -0,0 +1,92 @@ +package info.bukova.isspst.signapi; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author Pepa Rokos + */ +public class SignData implements Serializable { + + private byte[] pdfData; + private byte[] signImg; + private int areaId; + private Date signDate; + private String description; + private String numser; + private boolean signed; + private String signGuid; + private boolean signSuccess; + + public byte[] getPdfData() { + return pdfData; + } + + public void setPdfData(byte[] pdfData) { + this.pdfData = pdfData; + } + + public Date getSignDate() { + return signDate; + } + + public void setSignDate(Date signDate) { + this.signDate = signDate; + } + + public String getNumser() { + return numser; + } + + public void setNumser(String numser) { + this.numser = numser; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public boolean isSigned() { + return signed; + } + + public void setSigned(boolean signed) { + this.signed = signed; + } + + public String getSignGuid() { + return signGuid; + } + + public void setSignGuid(String signGuid) { + this.signGuid = signGuid; + } + + public boolean isSignSuccess() { + return signSuccess; + } + + public void setSignSuccess(boolean signSuccess) { + this.signSuccess = signSuccess; + } + + public byte[] getSignImg() { + return signImg; + } + + public void setSignImg(byte[] signImg) { + this.signImg = signImg; + } + + public int getAreaId() { + return areaId; + } + + public void setAreaId(int areaId) { + this.areaId = areaId; + } +} diff --git a/src/main/java/info/bukova/isspst/signapi/SignUploadResponse.java b/src/main/java/info/bukova/isspst/signapi/SignUploadResponse.java new file mode 100644 index 00000000..d33f38ec --- /dev/null +++ b/src/main/java/info/bukova/isspst/signapi/SignUploadResponse.java @@ -0,0 +1,28 @@ +package info.bukova.isspst.signapi; + +import java.io.Serializable; + +/** + * @author Pepa Rokos + */ +public class SignUploadResponse implements Serializable { + + private boolean ok; + private String errorMessage; + + public boolean isOk() { + return ok; + } + + public void setOk(boolean ok) { + this.ok = ok; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } +} diff --git a/src/main/java/info/bukova/isspst/signapi/SigningController.java b/src/main/java/info/bukova/isspst/signapi/SigningController.java new file mode 100644 index 00000000..92fced72 --- /dev/null +++ b/src/main/java/info/bukova/isspst/signapi/SigningController.java @@ -0,0 +1,133 @@ +package info.bukova.isspst.signapi; + +import info.bukova.isspst.Constants; +import info.bukova.isspst.SessionData; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import javax.servlet.ServletContext; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +/** + * @author Pepa Rokos + */ + +@Controller +public class SigningController { + + @Autowired + private SessionData sessionData; + @Autowired + private JnlpGenerator jnlpGenerator; + @Autowired + private ServletContext context; + + @RequestMapping(value="/sign/data", method= RequestMethod.GET) + public void dataForSign(HttpServletResponse response, HttpServletRequest request) { + SignData data = (SignData) sessionData.getProperty(Constants.KEY_SIGN_DATA); + ObjectOutputStream os = null; + + try { + os = new ObjectOutputStream(response.getOutputStream()); + response.setContentType("application/x-java-serialized-object"); + os.writeObject(data); + os.flush(); + os.close(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (os != null) { + try { + os.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + } + + @RequestMapping(value="/sign/data", method= RequestMethod.POST) + public void signedData(HttpServletRequest request, HttpServletResponse response) { + ObjectInputStream ois = null; + ObjectOutputStream os = null; + String error = null; + + try { + ois = new ObjectInputStream(request.getInputStream()); + SignData data = (SignData) ois.readObject(); + sessionData.setProperty(Constants.KEY_SIGN_DATA, data); + } catch (IOException e) { + e.printStackTrace(); + error = "IO error"; + } catch (ClassNotFoundException e) { + e.printStackTrace(); + error = "Loading error"; + } + + try { + SignUploadResponse resp = new SignUploadResponse(); + + if (error == null) { + resp.setOk(true); + } else { + resp.setOk(false); + resp.setErrorMessage(error); + } + + os = new ObjectOutputStream(response.getOutputStream()); + response.setContentType("application/x-java-serialized-object"); + os.writeObject(resp); + os.flush(); + os.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @RequestMapping(value="/sign/signer.jnlp", method= RequestMethod.GET) + public void jnlp(HttpServletResponse response) { + byte[] data = jnlpGenerator.generate(); + sendByte(response, data, "application/x-java-jnlp-file"); + } + + @RequestMapping(value="/sign/pdfsigner.jar", method= RequestMethod.GET) + public void pdfsigner(HttpServletResponse response) { + File inputJar = new File(context.getRealPath("/WEB-INF/signer/PDFSigner.jar")); + + try { + byte[] data = new byte[(int) inputJar.length()]; + FileInputStream is = new FileInputStream(inputJar); + is.read(data); + sendByte(response, data, "application/java-archive"); + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void sendByte(HttpServletResponse response, byte[] data, String contentType) { + ServletOutputStream os = null; + + try { + os = response.getOutputStream(); + response.setContentType(contentType); + response.setContentLength(data.length); + os.write(data); + os.flush(); + os.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/info/bukova/isspst/ui/main/ApproveDialogVM.java b/src/main/java/info/bukova/isspst/ui/main/ApproveDialogVM.java index 3afe2e8d..123f3549 100644 --- a/src/main/java/info/bukova/isspst/ui/main/ApproveDialogVM.java +++ b/src/main/java/info/bukova/isspst/ui/main/ApproveDialogVM.java @@ -1,19 +1,32 @@ package info.bukova.isspst.ui.main; +import info.bukova.isspst.Constants; +import info.bukova.isspst.SessionData; import info.bukova.isspst.StringUtils; import info.bukova.isspst.data.RequirementBase; +import info.bukova.isspst.reporting.Generator; +import info.bukova.isspst.reporting.GeneratorFactory; +import info.bukova.isspst.reporting.ParamFiller; +import info.bukova.isspst.reporting.Report; +import info.bukova.isspst.reporting.ReportDefinition; +import info.bukova.isspst.services.Service; import info.bukova.isspst.services.requirement.ApproveException; import info.bukova.isspst.services.requirement.RequirementBaseService; +import info.bukova.isspst.signapi.SignData; import info.bukova.isspst.ui.ListViewModel; import org.zkoss.bind.BindUtils; import org.zkoss.bind.annotation.BindingParam; import org.zkoss.bind.annotation.Command; import org.zkoss.bind.annotation.ExecutionArgParam; import org.zkoss.bind.annotation.Init; +import org.zkoss.bind.annotation.NotifyChange; +import org.zkoss.zk.ui.Executions; +import org.zkoss.zk.ui.select.annotation.WireVariable; import org.zkoss.zul.Messagebox; import org.zkoss.zul.Window; import java.util.Date; +import java.util.UUID; /** * @author Pepa Rokos @@ -24,6 +37,16 @@ public class ApproveDialogVM { private RequirementBase requirement; private ListViewModel grid; private Date approveDate; + @WireVariable + private SessionData sessionData; + @WireVariable + private ReportDefinition reportDefinition; + @WireVariable + private GeneratorFactory genFactory; + @WireVariable + private ParamFiller paramFiller; + private boolean signed; + private boolean timer; public Date getApproveDate() { return approveDate; @@ -41,6 +64,9 @@ public class ApproveDialogVM { this.requirement = requirement; this.grid = grid; this.approveDate = new Date(); + + this.signed = false; + this.timer = false; } @Command @@ -57,4 +83,51 @@ public class ApproveDialogVM { } } + @Command + @NotifyChange("timer") + public void signPdf() { + SignData data = new SignData(); + sessionData.setProperty(Constants.KEY_SIGN_DATA, data); + data.setSignGuid(UUID.randomUUID().toString()); + sessionData.setProperty(Constants.KEY_SIGN_GUID, data.getSignGuid()); + + // ToDo: Generovat report + reportDefinition.clear(); + reportDefinition.setSingleObject(requirement); + reportDefinition.setReport(new Report(0, true, "", "tripRequirementApp", false, true, true)); + reportDefinition.setService((Service) service); + + paramFiller.fill(); + Generator gen = genFactory.createGenerator(reportDefinition); + data.setPdfData(gen.generate()); + data.setDescription(requirement.getDescription()); + data.setNumser(requirement.getNumser()); + + timer = true; + + Executions.getCurrent().sendRedirect("/api/sign/signer.jnlp", "signer"); + } + + @Command + @NotifyChange({"signed", "timer"}) + public void onTimer() { + String guid = (String) sessionData.getProperty(Constants.KEY_SIGN_GUID); + SignData data = (SignData) sessionData.getProperty(Constants.KEY_SIGN_DATA); + + if (guid.equals(data.getSignGuid()) && data.isSignSuccess()) { + signed = true; + timer = false; + } else { + signed = false; + } + } + + public boolean isSigned() { + return signed; + } + + public boolean isTimer() { + return timer; + } + } diff --git a/src/main/resources/jasperreports_extension.properties b/src/main/resources/jasperreports_extension.properties new file mode 100644 index 00000000..820c3615 --- /dev/null +++ b/src/main/resources/jasperreports_extension.properties @@ -0,0 +1 @@ +net.sf.jasperreports.extension.registry.factory.sig=info.bukova.isspst.reporting.SignaturePdfHandler \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/reports/tripRequirementApp.jasper b/src/main/webapp/WEB-INF/reports/tripRequirementApp.jasper new file mode 100644 index 00000000..a400206e Binary files /dev/null and b/src/main/webapp/WEB-INF/reports/tripRequirementApp.jasper differ diff --git a/src/main/webapp/WEB-INF/reports/tripRequirementApp.jrxml b/src/main/webapp/WEB-INF/reports/tripRequirementApp.jrxml new file mode 100644 index 00000000..6856b01f --- /dev/null +++ b/src/main/webapp/WEB-INF/reports/tripRequirementApp.jrxml @@ -0,0 +1,356 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <band height="79" splitType="Stretch"> + <image onErrorType="Blank"> + <reportElement uuid="ef1dc796-f5c6-4036-99eb-26e7b6b7abbc" x="0" y="0" width="100" height="79" isRemoveLineWhenBlank="true"> + <printWhenExpression><![CDATA[$P{P_LOGO} != null]]></printWhenExpression> + </reportElement> + <imageExpression><![CDATA[$P{P_LOGO}]]></imageExpression> + </image> + <textField> + <reportElement uuid="3e2074cd-220c-4c9a-b94c-a0a254cc24a6" x="100" y="0" width="471" height="34"/> + <textElement textAlignment="Center"> + <font isBold="true" pdfEncoding="Cp1250"/> + </textElement> + <textFieldExpression><![CDATA[$P{P_MAIN_ADDRESS}]]></textFieldExpression> + </textField> + <staticText> + <reportElement uuid="a7a82c52-e8b8-41cf-b13a-ebc54d30d04f" x="101" y="34" width="470" height="45"/> + <textElement textAlignment="Center" verticalAlignment="Bottom"> + <font size="14" isBold="true" pdfEncoding="Cp1250"/> + </textElement> + <text><![CDATA[CESTOVNÍ PŘÍKAZ +k tuzemské pracovní cestě]]></text> + </staticText> + </band> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/WEB-INF/signer/PDFSigner.jar b/src/main/webapp/WEB-INF/signer/PDFSigner.jar new file mode 100644 index 00000000..d80651f0 Binary files /dev/null and b/src/main/webapp/WEB-INF/signer/PDFSigner.jar differ diff --git a/src/main/webapp/WEB-INF/spring/root-context.xml b/src/main/webapp/WEB-INF/spring/root-context.xml index f95f7678..a1057665 100644 --- a/src/main/webapp/WEB-INF/spring/root-context.xml +++ b/src/main/webapp/WEB-INF/spring/root-context.xml @@ -456,6 +456,8 @@ + + diff --git a/src/main/webapp/main/approveDialog.zul b/src/main/webapp/main/approveDialog.zul index 446e32c2..cd803199 100644 --- a/src/main/webapp/main/approveDialog.zul +++ b/src/main/webapp/main/approveDialog.zul @@ -17,15 +17,20 @@