/** * */ package at.knowcenter.wag.egov.egiz.web.servlets; import java.io.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Properties; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileItemFactory; 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.framework.SignatorException; import at.gv.egiz.pdfas.framework.SignatorFactory; import at.gv.egiz.pdfas.framework.signator.Signator; import at.gv.egiz.pdfas.web.SignSessionInformation; import at.gv.egiz.pdfas.web.VerifySessionInformation; import at.gv.egiz.pdfas.web.helper.SessionHelper; import at.gv.egiz.pdfas.web.helper.SignServletHelper; import at.gv.egiz.pdfas.web.helper.SigningTimeHelper; import at.gv.egiz.pdfas.web.helper.TempDirHelper; import at.knowcenter.wag.egov.egiz.PdfASID; import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; import at.knowcenter.wag.egov.egiz.exceptions.InvalidIDException; import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; import at.knowcenter.wag.egov.egiz.exceptions.SignatorFactoryException; import at.knowcenter.wag.egov.egiz.exceptions.SignatureException; import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder; import at.knowcenter.wag.egov.egiz.sig.SignatureResponse; import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorChooser; import at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector; import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper; import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection; import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler; import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandlerFactory; import at.knowcenter.wag.egov.egiz.web.FormFields; import at.knowcenter.wag.egov.egiz.web.LocalRequest; import at.knowcenter.wag.egov.egiz.web.LocalRequestHelper; import at.knowcenter.wag.egov.egiz.web.SessionAttributes; /** * @author wprinz * */ public class DataURLServlet extends HttpServlet { /** * SVUID. */ private static final long serialVersionUID = -5846618335843762752L; /** * The log. */ private static Log log = LogFactory.getLog(DataURLServlet.class); protected void dispatch(HttpServletRequest request, HttpServletResponse response, String resource) throws ServletException, IOException { dispatch(request, response, resource, getServletContext()); } protected static void dispatch(HttpServletRequest request, HttpServletResponse response, String resource, ServletContext context) throws ServletException, IOException { response.setContentType("text/html"); response.setCharacterEncoding("UTF-8"); RequestDispatcher disp = context.getRequestDispatcher(resource); disp.forward(request, response); } protected void dispatchToResults(List results, HttpServletRequest request, HttpServletResponse response, String backToListURL) throws ServletException, IOException { request.setAttribute("results", results); request.setAttribute("btlurl", backToListURL); dispatch(request, response, "/jsp/results.jsp"); } protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } private static void temporaryRedirect(String redirectURL, HttpServletResponse response) throws IOException { String encodedRedirect = response.encodeRedirectURL(redirectURL); response.addHeader("Location", encodedRedirect); response.setContentType("text/xml"); response.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT); String nop = ""; PrintWriter pw = response.getWriter(); response.setCharacterEncoding("UTF-8"); response.setContentLength(nop.getBytes("UTF-8").length); log.debug("Redirecting via NullOperationRequest to " + encodedRedirect + "."); pw.println(nop); pw.flush(); pw.close(); } /** * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { log.debug("Data URL is accessed."); //$NON-NLS-1$ try { Object sessionObject = SessionHelper.getSession(request); // obsolete since EncodingFilter is set in web.xml checkRequestCharacterEncoding(request); if (sessionObject instanceof SignSessionInformation) { SignSessionInformation si = (SignSessionInformation)sessionObject; processSign(request, response, si); } else { VerifySessionInformation si = (VerifySessionInformation) sessionObject; processVerify(request, response, si); } } catch (PresentableException e) { log.error(e.getMessage(), e); SignServlet.prepareDispatchToErrorPage(e, request); dispatch(request, response, "/jsp/error.jsp"); } log.debug("DataURL access finished."); //$NON-NLS-1$ } protected void checkRequestCharacterEncoding(HttpServletRequest request) throws UnsupportedEncodingException { if (request.getCharacterEncoding() == null || request.getCharacterEncoding().length() <= 0) //$NON-NLS-1$ { log.info("The BKU didn't set a character encoding for the request."); //$NON-NLS-1$ log.info("Manually setting character encoding to UTF-8"); //$NON-NLS-1$ request.setCharacterEncoding("UTF-8"); //$NON-NLS-1$ } } protected boolean isNullResponse(String xml_response) { return xml_response != null && xml_response.indexOf("NullOperationResponse") != -1; } private static String retrieveXMLResponse(HttpServletRequest request) throws ServletException { log.debug("Trying to fetch XMLResponse..."); String xml_response = null; if (ServletFileUpload.isMultipartContent(request)) { log.debug("Response is multipart."); FileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); try { List items = upload.parseRequest(request); Iterator iter = items.iterator(); while (iter.hasNext()) { FileItem item = (FileItem) iter.next(); if (item.isFormField() && "XMLResponse".equals(item.getFieldName())) { log.debug("XMLResponse part found."); xml_response = item.getString(); break; } } } catch (FileUploadException e) { throw new ServletException(e); } } else { xml_response = request.getParameter("XMLResponse"); } log.debug("XMLResponse = " + xml_response); return xml_response; } protected void processSign(HttpServletRequest request, HttpServletResponse response, SignSessionInformation si) throws ServletException, IOException, ConnectorException, SignatorException, SignatorFactoryException, SignatureException { log.trace("processSign"); String xml_response = retrieveXMLResponse(request); Properties response_properties = BKUHelper.getBKUProperties(request); String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties); log.debug("BKU identifier: \"" + bkuIdentifier + "\""); try { SignatureLayoutHandlerFactory.verifyBKUSupport(bkuIdentifier); } catch (SettingsException e) { throw new ConnectorException(e.getErrorCode(), e.getMessage()); } if (isNullResponse(xml_response)) { log.debug("Received a NullOperationResponse -> answering with the first request."); //$NON-NLS-1$ assert si.outputAvailable == false; assert si.response_properties == null; log.debug("There are still requests to be performed -> answering with request."); //$NON-NLS-1$ LocalRequest local_request = si.localRequest; String request_string = local_request.getRequestString(); log.debug("request = " + request_string); response.setContentType("text/xml"); response.setCharacterEncoding("UTF-8"); response.getWriter().println(request_string); } else if (xml_response != null) { log.debug("Received a normal response -> storing the response."); //$NON-NLS-1$ response_properties.setProperty(BKUPostConnection.RESPONSE_STRING_KEY, xml_response); si.response_properties = response_properties; log.debug("All requests have been processed -> processing the responses."); //$NON-NLS-1$ // Sign if (!si.outputAvailable) { LocalConnector c = ConnectorChooser.chooseLocalConnectorForSign(si.connector, si.type, "loc ref content not needed here"); //$NON-NLS-1$ si.si.setSignSignatureObject(c.analyzeSignResponse(si.response_properties)); // workaround for invalid signing time SigningTimeHelper.checkSigningTimeAgainstHostTime(si.si); PdfASID algorithm = FormFields.translateSignatureModeToPdfASID(si.mode); Signator signator = SignatorFactory.createSignator(algorithm); si.output = TempDirHelper.createTempDataSink(si.filename + "_signed.pdf"); signator.finishSign(si.si, si.output); si.outputAvailable = true; } if (si.output.getMimeType().equals("text/xml") && si.outputAvailable) { // For "detached" signatures, the return value (data sink) is the response xml, // but when passed through the BKU it is interpreted as another request // which will generate a return code 1501 // Then PDF-AS would answer with the response as well generating // another 1501 and so forth. // Therefor return it as TXT. response.setContentType("text/plain"); response.setCharacterEncoding("UTF-8"); response.getWriter().println("Das detached XML kann nicht direkt durch die BKU geschliffen werden, weil diese es als Request interpretieren würde. Daher das XML als Text:"); response.getWriter().println(si.si.getSignSignatureObject().response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY)); } else { // tzefferer: If PDF-AS has been called by an external web-application, we do not // redirect to download.jsp but return the sign-response immediately if (si.exappinf != null) { log.debug("Entering external application interface mode. Skipping redirection to download page."); SignServletHelper.returnSignResponse(si, request, response); // Not needed due to redirection of returnSignResponse. // Just to clarify that there must not be any code after returnSignResponse. return; } else { log.debug("Preparing download page."); HttpSession session = request.getSession(true); log.debug("Putting signed document into session (" + session.getId() + ")."); session.setAttribute(SessionAttributes.SIGNED_PDF_DOCUMENT, si); String downloadURL = response.encodeRedirectURL(LocalRequestHelper.getLocalContextAddress(request, response) + "/ProvidePDF"); log.debug("Creating download URL \"" + downloadURL + "\"."); session.setAttribute(SessionAttributes.DOWNLOAD_URL_FOR_SIGNED_PDF_DOCUMENT, downloadURL); Cookie cookie = new Cookie("JSESSIONID", session.getId()); response.addCookie(cookie); temporaryRedirect(response.encodeRedirectURL(LocalRequestHelper.getLocalContextAddress(request, response) + "/jsp/download.jsp") , response); // Not needed due to temporaryRedirect. // Just to clarify that there must not be any code after temporaryRedirect. return; } // do not insert any code within this else block ! } } else { log.debug("No XMLResponse found. Do nothing."); } } protected void processVerify(HttpServletRequest request, HttpServletResponse response, VerifySessionInformation si) throws ServletException, IOException, ConnectorException, InvalidIDException { log.trace("processVerify"); String xml_response = request.getParameter("XMLResponse"); //$NON-NLS-1$ log.debug("xml_response = " + xml_response); //$NON-NLS-1$ if (isNullResponse(xml_response)) { log.debug("Received a NullOperationResponse -> answering with the first request."); //$NON-NLS-1$ assert si.currentLocalOperation.current_operation == 0; } else { log.debug("Recieved a normal response -> storing the response."); //$NON-NLS-1$ Properties response_properties = new Properties(); response_properties.setProperty(BKUPostConnection.RESPONSE_STRING_KEY, xml_response); si.currentLocalOperation.finishCurrentOperation(response_properties); } if (!si.currentLocalOperation.isFinished()) { log.debug("There are still requests to be performed -> answering with request #" + si.currentLocalOperation.current_operation); //$NON-NLS-1$ LocalRequest local_request = si.currentLocalOperation.getCurrentLocalRequest(); String request_string = local_request.getRequestString(); response.setContentType("text/xml"); response.setCharacterEncoding("UTF-8"); response.getWriter().println(request_string); } else { log.debug("All requests have been processed -> processing the responses."); //$NON-NLS-1$ List results = new ArrayList(); for (int i = 0; i < si.currentLocalOperation.response_properties.length; i++) { SignatureHolder sh = (SignatureHolder) si.currentLocalOperation.holders_to_be_verified.get(i); PdfASID sig_kz = sh.getSignatureObject().getKZ(); String sig_id = sh.getSignatureObject().getSignationIds(); LocalConnector c = ConnectorChooser.chooseLocalConnectorForVerify(si.connector, sig_kz, sig_id, si.type, "loc ref content not needed here"); //$NON-NLS-1$ SignatureResponse sig_resp = c.analyzeVerifyResponse(si.currentLocalOperation.response_properties[i]); results.add(sig_resp); } si.currentLocalOperation = null; URL btlURL = new URL(LocalRequestHelper.getLocalContextAddress(request, response) + "/jsp/verifylist.jsp"); String backToListURL = response.encodeURL(btlURL.toString()); dispatchToResults(results, request, response, backToListURL); } } }