/* * Copyright (c) 2006 by Know-Center, Graz, Austria * * This software is the confidential and proprietary information of Know-Center, * Graz, Austria. You shall not disclose such Confidential Information and shall * use it only in accordance with the terms of the license agreement you entered * into with Know-Center. * * KNOW-CENTER MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT. KNOW-CENTER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. * * $Id: Verify.java,v 1.7 2006/10/11 07:39:13 wprinz Exp $ */ package at.knowcenter.wag.egov.egiz.web.servlets; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import at.gv.egiz.pdfas.exceptions.ErrorCode; import at.gv.egiz.pdfas.framework.config.SettingsHelper; import at.gv.egiz.pdfas.framework.input.DataSource; import at.gv.egiz.pdfas.framework.input.ExtractionStage; import at.gv.egiz.pdfas.framework.input.PdfDataSource; import at.gv.egiz.pdfas.framework.input.TextDataSource; import at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters; import at.gv.egiz.pdfas.web.VerifySessionInformation; import at.gv.egiz.pdfas.web.helper.TempDirHelper; import at.knowcenter.wag.egov.egiz.PdfAS; import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException; import at.knowcenter.wag.egov.egiz.pdf.NoSignatureHolder; import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder; import at.knowcenter.wag.egov.egiz.sig.ConnectorFactory; import at.knowcenter.wag.egov.egiz.sig.SignatureResponse; import at.knowcenter.wag.egov.egiz.web.FormFields; import at.knowcenter.wag.egov.egiz.web.LocalRequestHelper; import at.knowcenter.wag.egov.egiz.web.SessionAttributes; /** * This method is the verify servlet for the pdf-as web application. It takes * get and post requests fill out jsp templates and give the user feedback about * the results of the verify process. * * @author wlackner * @author wprinz */ public class VerifyServlet extends HttpServlet { /** * SVUID. */ private static final long serialVersionUID = 309198792358636766L; /** * The log. */ private static Log log = LogFactory.getLog(SignServlet.class); protected void dispatch(HttpServletRequest request, HttpServletResponse response, String resource) throws ServletException, IOException { response.setContentType("text/html"); //$NON-NLS-1$ response.setCharacterEncoding("UTF-8"); //$NON-NLS-1$ RequestDispatcher disp = getServletContext().getRequestDispatcher(resource); disp.forward(request, response); } protected void dispatchToResults(List results, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setAttribute("results", results); //$NON-NLS-1$ dispatch(request, response, "/jsp/results.jsp"); //$NON-NLS-1$ } /** * Processes the verify upload. * * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // for performance measurement long startTime = 0; long fileSize = 0; if (log.isInfoEnabled()) { startTime = System.currentTimeMillis(); } try { UploadedData ud = retrieveUploadedDataFromRequest(request); VerifySessionInformation si = new VerifySessionInformation(); si.connector = ud.sig_app; si.application = "verify"; si.mode = null; si.inputDataSource = ud.dataSource; si.type = null; // si.user_name = null; // si.user_password = null; // List signature_holders = extractSignatureHoldersFromFile(ud.file_name, // ud.file_data); List signature_holders = extractSignatureHolders(ud.dataSource); TempDirHelper.storeTextSignatureHoldersIfApplicable(signature_holders, "_textholder.utf8.txt"); si.signature_holders = signature_holders; request.getSession().setAttribute(SessionAttributes.ATTRIBUTE_SESSION_INFORMATION, si); if (ud.preview) { dispatch(request, response, "/jsp/verifylist.jsp"); // VerifyPreview.formatPreview(signature_holders, connector, request, // response); } else { if (ConnectorFactory.isConnectorLocal(si.connector)) { String dispatch_to = LocalRequestHelper.processLocalVerify(si, si.signature_holders, request, response); dispatch(request, response, dispatch_to); return; } String host = request.getServerName(); // TODO still required for old communication with MOA-SS/SP URL loc_ref_URL = new URL(LocalRequestHelper.getLocalContextAddress(request, response) + "/RetrieveSignatureData"); String loc_ref_url = response.encodeURL(loc_ref_URL.toString()); List results = PdfAS.verifySignatureHoldersWeb(signature_holders, si, loc_ref_url); dispatchToResults(results, request, response); // for performance measurement if (log.isInfoEnabled()) { long endTime = System.currentTimeMillis(); String toReport = "VERIFY;"+ ud.file_name + ";"+ 0 + ";" + (endTime - startTime) + ";" + debugVerifyResults(results); log.info(toReport); } } } catch (FileUploadException e) { request.setAttribute("error", "Fehler beim Upload der Daten"); request.setAttribute("cause", "Beim Upload der Daten ist ein Fehler aufgetreten."); dispatch(request, response, "/jsp/error_verify.jsp"); } catch (PresentableException e) { log.error(e.getMessage(), e); SignServlet.prepareDispatchToErrorPage(e, request); dispatch(request, response, "/jsp/error_verify.jsp"); } } protected UploadedData retrieveUploadedDataFromRequest(HttpServletRequest request) throws ServletException, UnsupportedEncodingException, FileUploadException, PDFDocumentException { DiskFileItemFactory fif = new DiskFileItemFactory(); fif.setRepository(SettingsReader.getTemporaryDirectory()); ServletFileUpload sfu = new ServletFileUpload(fif); List items = sfu.parseRequest(request); FileItem upload_fi = null; FileItem connector_fi = null; // FileItem mode_fi = null; FileItem preview_fi = null; String characterEncoding = request.getCharacterEncoding(); log.debug("request character encoding = " + characterEncoding); { Iterator it = items.iterator(); while (it.hasNext()) { FileItem item = (FileItem) it.next(); log.debug("item = " + item.getFieldName()); //$NON-NLS-1$ if (item.isFormField()) { String item_string = item.getString("UTF-8"); //$NON-NLS-1$ log.debug(" form field string = " + item_string); //$NON-NLS-1$ } else { log.debug(" filename = " + item.getName()); //$NON-NLS-1$ log.debug(" filesize = " + item.getSize()); //$NON-NLS-1$ } if (item.getFieldName().equals(FormFields.FIELD_UPLOAD)) { upload_fi = item; continue; } if (item.getFieldName().equals(FormFields.FIELD_CONNECTOR)) { connector_fi = item; continue; } // if (item.getFieldName().equals(FormFields.FIELD_MODE)) // { // mode_fi = item; // continue; // } if (item.getFieldName().equals(FormFields.FIELD_PREVIEW)) { preview_fi = item; continue; } throw new ServletException("unrecognized POST data."); //$NON-NLS-1$ } } if (upload_fi == null || connector_fi == null || /* mode_fi == null || */preview_fi == null) { throw new ServletException("Unsufficient data provided in request."); //$NON-NLS-1$ } String connector = connector_fi.getString("UTF-8"); //$NON-NLS-1$ // String mode = mode_fi.getString("UTF-8"); // if (!mode.equals(FormFields.VALUE_MODE_BINARY) && // !mode.equals(FormFields.VALUE_MODE_TEXTUAL)) // { // throw new ServletException("The mode '" + mode + "' is unrecognized."); // } String preview_str = preview_fi.getString("UTF-8"); //$NON-NLS-1$ if (!preview_str.equals(FormFields.VALUE_TRUE) && !preview_str.equals(FormFields.VALUE_FALSE)) { throw new ServletException("The preview '" + preview_str + "' is unrecognized."); //$NON-NLS-1$//$NON-NLS-2$ } boolean preview = false; if (preview_str.equals(FormFields.VALUE_TRUE)) { preview = true; } // process the request DataSource dataSource = convertUploadToDataSource(upload_fi); UploadedData ud = new UploadedData(); ud.preview = preview; ud.sig_app = connector; ud.file_name = upload_fi.getName(); ud.dataSource = dataSource; // ud.file_data = document_bytes; return ud; } protected DataSource convertUploadToDataSource(FileItem upload_fi) throws PDFDocumentException { log.debug("file content type =" + upload_fi.getContentType()); //$NON-NLS-1$ log.debug("file size = " + upload_fi.getSize()); //$NON-NLS-1$ if (upload_fi.getSize() <= 0) { throw new PDFDocumentException(250, "The document is empty."); //$NON-NLS-1$ } // TR: do not check MIME-type of incoming file - might vary depending on the browser used if ((upload_fi.getContentType() != null ) && ((upload_fi.getContentType().startsWith("application/pdf") || upload_fi.getContentType().startsWith("application/x-download") ))) { try { String fileNameSuffix = TempDirHelper.extractFileNameSuffix(upload_fi.getName()); PdfDataSource pdfDataSource = TempDirHelper.placePdfIntoTempDir(upload_fi.getInputStream(), fileNameSuffix); return pdfDataSource; } catch (IOException e) { throw new PDFDocumentException(201, "The document could not be placed in the temp dir.", e); //$NON-NLS-1$ } // byte[] document_bytes = upload_fi.get(); } try { String fileNameSuffix = TempDirHelper.extractFileNameSuffix(upload_fi.getName()); String text = new String(upload_fi.get(), "UTF-8"); //$NON-NLS-1$ TextDataSource textDataSource = TempDirHelper.placeTextIntoTempDir(text, fileNameSuffix); return textDataSource; } catch (IOException e) { throw new PDFDocumentException(201, e); } } protected List extractSignatureHolders(DataSource dataSource) throws PresentableException { VerificationFilterParameters parameters = SettingsHelper.readVerificationFilterParametersFromSettings(); ExtractionStage es = new ExtractionStage(); List signature_holders = es.extractSignatureHolders(dataSource, parameters); // filter out NoSignatureHolders that are possibly present due to the direct call method extractSignatureHolders() List filtered_signature_holders = new ArrayList(); Iterator it = signature_holders.iterator(); while(it.hasNext()) { SignatureHolder current = (SignatureHolder) it.next(); if(!(current instanceof NoSignatureHolder)) { filtered_signature_holders.add(current); } } if (filtered_signature_holders.size() == 0) { throw new PDFDocumentException(ErrorCode.DOCUMENT_NOT_SIGNED, "PDF document not signed."); //$NON-NLS-1$ } return filtered_signature_holders; } // TODO obsolete method - remove // protected List extractSignatureHoldersFromFile(String file_name, byte[] // data) throws UnsupportedEncodingException, PresentableException // { // VerificationFilterParameters parameters = new // VerificationFilterParametersImpl(false, false, true); // ExtractionStage es = new ExtractionStage(); // // VerificationFilter vf = new VerificationFilter(); // List signature_holders = null; // // String extension = extractExtension(file_name); // // String raw_text = null; // if (file_name == null || (extension != null && extension.equals("txt"))) // //$NON-NLS-1$ // { // raw_text = new String(data, "UTF-8"); //$NON-NLS-1$ // // signature_holders = es.extractSignatureHolders(new // TextDataSourceImpl(raw_text), parameters); // // signature_holders = vf.extractSignaturesFromPlainText(raw_text); // } // else // { // signature_holders = es.extractSignatureHolders(new // ByteArrayPdfDataSourceImpl(data), parameters); // // // signature_holders = vf.extractSignaturesFromPdf(data); // } // // if (signature_holders.size() == 0) // { // throw new PDFDocumentException(206, "PDF document not signed."); // //$NON-NLS-1$ // } // // return signature_holders; // } /** * Extracts the extension from a file name string. * *

* The extension of a file name is whatever text follows the last '.'. *

* * @param file_name * The file name. * @return Returns the extension. If the file name ends with the '.', then an * empty string is returned. If the file name doesn't contain any '.' * or file_name is null, null is returned. */ public static String extractExtension(String file_name) { if (file_name == null) { return null; } int dot_index = file_name.lastIndexOf('.'); if (dot_index < 0) { return null; } return file_name.substring(dot_index + 1); } protected static class UploadedData { protected boolean preview = false; protected String sig_app = null; protected String file_name = null; protected DataSource dataSource = null; // protected byte[] file_data = null; } /** * Formats the verification results for debugging. Returns 0 if no error occurs or the sum of all error-codes. * * @param results * * @param writer * The output sink to write the formatted text to. * @throws SettingNotFoundException * Forwarded exception. */ protected static int debugVerifyResults(List results) throws SettingNotFoundException { int toreturn = 0; Iterator it = results.iterator(); while (it.hasNext()) { SignatureResponse result = (SignatureResponse) it.next(); toreturn += Integer.valueOf(result.getSignatureCheckCode()).intValue(); } return toreturn; } public boolean isPDF(byte[] data) { final byte[] PDF_MAGIC_NUMBER = { (byte) 0x25, (byte) 0x50, (byte) 0x44, (byte) 0x46 }; // %PDF if (data == null || data.length < PDF_MAGIC_NUMBER.length) { return false; } byte[] documentHeader = new byte[PDF_MAGIC_NUMBER.length]; System.arraycopy(data, 0, documentHeader, 0, documentHeader.length); return Arrays.equals(documentHeader, PDF_MAGIC_NUMBER); } }