diff options
Diffstat (limited to 'pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java')
-rw-r--r-- | pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java | 371 |
1 files changed, 243 insertions, 128 deletions
diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java index 401d3e68..bf45745d 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/PDFData.java @@ -3,19 +3,19 @@ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a * joint initiative of the Federal Chancellery Austria and Graz University of * Technology. - * + * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * http://www.osor.eu/eupl/ - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. - * + * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works @@ -23,147 +23,262 @@ ******************************************************************************/ package at.gv.egiz.pdfas.web.servlets; -import java.io.*; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Iterator; +import java.util.List; +import java.util.zip.Deflater; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import at.gv.egiz.pdfas.web.config.WebConfiguration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - +import at.gv.egiz.pdfas.api.processing.SignedDocument; import at.gv.egiz.pdfas.api.ws.PDFASVerificationResponse; +import at.gv.egiz.pdfas.web.config.WebConfiguration; import at.gv.egiz.pdfas.web.helper.PdfAsHelper; import at.gv.egiz.pdfas.web.helper.PdfAsParameterExtractor; import at.gv.egiz.pdfas.web.stats.StatisticEvent; import at.gv.egiz.pdfas.web.stats.StatisticEvent.Status; import at.gv.egiz.pdfas.web.stats.StatisticFrontend; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.OutputStream; +import lombok.extern.slf4j.Slf4j; /** * Servlet implementation class PDFData */ +@Slf4j public class PDFData extends HttpServlet { - private static final long serialVersionUID = 1L; - - private static final Logger logger = LoggerFactory.getLogger(PDFData.class); - - /** - * @see HttpServlet#HttpServlet() - */ - public PDFData() { - super(); - } - - /** - * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse - * response) - */ - protected void doGet(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - this.process(request, response); - } - - /** - * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse - * response) - */ - protected void doPost(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - this.process(request, response); - } - - protected void process(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - byte[] signedData = PdfAsHelper.getSignedPdf(request, response); - - StatisticEvent statisticEvent = PdfAsHelper.getStatisticEvent(request, - response); - - String plainPDFDigest = PdfAsParameterExtractor.getOrigDigest(request); - - if (signedData != null) { - - if(WebConfiguration.isKeepSignedDocument()) { - if(PdfAsHelper.isSignedDataExpired(request, response)) { - logger.info("Destroying expired signed data in session"); - request.getSession().invalidate(); - PdfAsHelper.setSessionException(request, response, - "No signed pdf document available.", null); - PdfAsHelper.gotoError(getServletContext(), request, response); - return; - } - } - - if (plainPDFDigest != null) { - String signatureDataHash = PdfAsHelper - .getSignatureDataHash(request); - if (!plainPDFDigest.equalsIgnoreCase(signatureDataHash)) { - logger.warn("Digest Hash mismatch!"); - logger.warn("Requested digest: " + plainPDFDigest); - logger.warn("Saved digest: " + signatureDataHash); - - PdfAsHelper.setSessionException(request, response, - "Signature Data digest do not match!", null); - PdfAsHelper.gotoError(getServletContext(), request, - response); - return; - } - } - response.setHeader("Content-Disposition", "inline;filename=" - + PdfAsHelper.getPDFFileName(request)); - String pdfCert = PdfAsHelper.getSignerCertificate(request); - if (pdfCert != null) { - response.setHeader("Signer-Certificate", pdfCert); - } - - if (statisticEvent != null) { - if (!statisticEvent.isLogged()) { - statisticEvent.setStatus(Status.OK); - - statisticEvent.setEndNow(); - statisticEvent.setTimestampNow(); - StatisticFrontend.getInstance().storeEvent(statisticEvent); - statisticEvent.setLogged(true); - } - } - - PDFASVerificationResponse resp = PdfAsHelper - .getPDFASVerificationResponse(request); - if (resp != null) { - response.setHeader("CertificateCheckCode", - String.valueOf(resp.getCertificateCode())); - response.setHeader("ValueCheckCode", - String.valueOf(resp.getValueCode())); - } - response.setContentType("application/pdf"); - OutputStream os = response.getOutputStream(); - os.write(signedData); - os.close(); - - // When data is collected destroy session! - if(!WebConfiguration.isKeepSignedDocument()) { - logger.debug("Destroying signed data in session : {}", request.getSession().getId()); - request.getSession().invalidate(); - } else { - logger.debug("Keeping signed data in session : {}", request.getSession().getId()); - } - } else { - logger.info("No signed pdf document available."); - PdfAsHelper.setSessionException(request, response, - "No signed pdf document available.", null); - PdfAsHelper.gotoError(getServletContext(), request, response); - } - } + private static final long serialVersionUID = 1L; + + /** + * @see HttpServlet#HttpServlet() + */ + public PDFData() { + super(); + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse + * response) + */ + @Override + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + this.process(request, response); + } + + /** + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse + * response) + */ + @Override + protected void doPost(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + this.process(request, response); + } + + protected void process(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + + if (PdfAsHelper.getPdfSigningResponse(request).getSignedPdfs().isEmpty()) { + log.info("No signed pdf document available."); + PdfAsHelper.setSessionException(request, response, + "No signed pdf document available.", null); + PdfAsHelper.gotoError(getServletContext(), request, response); + + } else if (PdfAsHelper.getPdfSigningResponse(request).getSignedPdfs().size() == 1) { + buildSingleFileResult(request, response, + PdfAsHelper.getPdfSigningResponse(request).getSignedPdfs().get(0)); + + } else { + buildMultipleFileResult(request, response, PdfAsHelper.getPdfSigningResponse(request).getSignedPdfs()); + + } + + } + + private void buildMultipleFileResult(HttpServletRequest request, HttpServletResponse response, + List<SignedDocument> signedPdfs) throws IOException, ServletException { + + final StatisticEvent statisticEvent = PdfAsHelper.getStatisticEvent(request,response); + + // check if some files are expired + if (WebConfiguration.isKeepSignedDocument()) { + if (signedPdfs.stream() + .filter(el -> isSignedDataExpired(el)) + .findFirst().isPresent()) { + log.info("Destroying expired signed data in session"); + request.getSession().invalidate(); + PdfAsHelper.setSessionException(request, response, + "No signed pdf document available.", null); + PdfAsHelper.gotoError(getServletContext(), request, response); + return; + } + } + + // package files into ZIP + byte[] zippedFiles = packageSignedPdfsIntoZip(signedPdfs); + + // write static log + if (statisticEvent != null) { + if (!statisticEvent.isLogged()) { + statisticEvent.setStatus(Status.OK); + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + } + } + + // build response + response.setHeader("Content-Disposition", "inline;filename=multiple_documents.zip"); + response.setContentType("application/zip"); + final OutputStream os = response.getOutputStream(); + + os.write(zippedFiles); + os.close(); + + // When data is collected destroy session! + if (!WebConfiguration.isKeepSignedDocument()) { + log.debug("Destroying signed data in session : {}", request.getSession().getId()); + request.getSession().invalidate(); + } else { + log.debug("Keeping signed data in session : {}", request.getSession().getId()); + } + + } + + private byte[] packageSignedPdfsIntoZip(List<SignedDocument> signedPdfs) throws IOException { + ByteArrayOutputStream baOut = new ByteArrayOutputStream(); + + try { + ZipOutputStream zos = new ZipOutputStream(baOut); + zos.setLevel(Deflater.BEST_COMPRESSION); + zos.setMethod(Deflater.DEFLATED); + + Iterator<SignedDocument> it = signedPdfs.iterator(); + while (it.hasNext()) { + SignedDocument entry = it.next(); + if (entry.getOutputData() != null) { + log.debug("Compressing file {}.", entry.getFileName()); + ZipEntry oze = new ZipEntry(entry.getFileName()); + zos.putNextEntry(oze); + zos.write(entry.getOutputData()); + zos.closeEntry(); + + } else { + log.warn("Ignore entry with name: {} because it's empty", entry.getFileName()); + + } + } + zos.closeEntry(); + zos.finish(); + zos.close(); + + return baOut.toByteArray(); + + } finally { + baOut.close(); + + } + + } + + private void buildSingleFileResult(HttpServletRequest request, HttpServletResponse response, SignedDocument signedFile) throws ServletException, IOException { + final byte[] signedData = signedFile.getOutputData(); + + final StatisticEvent statisticEvent = PdfAsHelper.getStatisticEvent(request, + response); + + final String plainPDFDigest = PdfAsParameterExtractor.getOrigDigest(request); + + if (signedData != null) { + + if (WebConfiguration.isKeepSignedDocument()) { + if (isSignedDataExpired(signedFile)) { + log.info("Destroying expired signed data in session"); + request.getSession().invalidate(); + PdfAsHelper.setSessionException(request, response, + "No signed pdf document available.", null); + PdfAsHelper.gotoError(getServletContext(), request, response); + return; + } + } + + if (plainPDFDigest != null) { + final String signatureDataHash = PdfAsHelper + .getSignatureDataHash(request); + if (!plainPDFDigest.equalsIgnoreCase(signatureDataHash)) { + log.warn("Digest Hash mismatch!"); + log.warn("Requested digest: " + plainPDFDigest); + log.warn("Saved digest: " + signatureDataHash); + + PdfAsHelper.setSessionException(request, response, + "Signature Data digest do not match!", null); + PdfAsHelper.gotoError(getServletContext(), request, + response); + return; + } + } + response.setHeader("Content-Disposition", "inline;filename=" + + PdfAsHelper.getPDFFileName(request)); + final String pdfCert = signedFile.getSignerCertificate(); + if (pdfCert != null) { + response.setHeader("Signer-Certificate", pdfCert); + } + + if (statisticEvent != null) { + if (!statisticEvent.isLogged()) { + statisticEvent.setStatus(Status.OK); + + statisticEvent.setEndNow(); + statisticEvent.setTimestampNow(); + StatisticFrontend.getInstance().storeEvent(statisticEvent); + statisticEvent.setLogged(true); + } + } + + final PDFASVerificationResponse resp = signedFile.getVerificationResponse(); + if (resp != null) { + response.setHeader("CertificateCheckCode", + String.valueOf(resp.getCertificateCode())); + response.setHeader("ValueCheckCode", + String.valueOf(resp.getValueCode())); + } + response.setContentType("application/pdf"); + final OutputStream os = response.getOutputStream(); + os.write(signedData); + os.close(); + + // When data is collected destroy session! + if (!WebConfiguration.isKeepSignedDocument()) { + log.debug("Destroying signed data in session : {}", request.getSession().getId()); + request.getSession().invalidate(); + } else { + log.debug("Keeping signed data in session : {}", request.getSession().getId()); + } + } else { + log.info("No signed pdf document available."); + PdfAsHelper.setSessionException(request, response, + "No signed pdf document available.", null); + PdfAsHelper.gotoError(getServletContext(), request, response); + + } + + } + + private static boolean isSignedDataExpired(SignedDocument signedFile) { + final long now = System.currentTimeMillis(); + final long validUntil = signedFile.getSigningTimestamp() + 300000; + + log.debug("Checking signed data valid until {} now is {}", validUntil, now); + return validUntil < now; + + } + } |