at.gv.egiz.pdfas.web.servlets.ExternSignServlet.java Source code

Java tutorial

Introduction

Here is the source code for at.gv.egiz.pdfas.web.servlets.ExternSignServlet.java

Source

/*******************************************************************************
 * <copyright> Copyright 2014 by E-Government Innovation Center EGIZ, Graz, Austria </copyright>
 * 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
 * that you distribute must include a readable copy of the "NOTICE" text file.
 ******************************************************************************/
package at.gv.egiz.pdfas.web.servlets;

import java.io.File;
import java.io.IOException;
import java.util.List;

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.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import at.gv.egiz.pdfas.common.exceptions.PDFASError;
import at.gv.egiz.pdfas.common.exceptions.PdfAsException;
import at.gv.egiz.pdfas.common.exceptions.PdfAsSettingsException;
import at.gv.egiz.pdfas.common.exceptions.PdfAsSettingsValidationException;
import at.gv.egiz.pdfas.common.settings.ISettings;
import at.gv.egiz.pdfas.lib.api.PdfAsFactory;
import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter.SignatureVerificationLevel;
import at.gv.egiz.pdfas.web.config.WebConfiguration;
import at.gv.egiz.pdfas.web.exception.PdfAsWebException;
import at.gv.egiz.pdfas.web.filter.UserAgentFilter;
import at.gv.egiz.pdfas.web.helper.DigestHelper;
import at.gv.egiz.pdfas.web.helper.PdfAsHelper;
import at.gv.egiz.pdfas.web.helper.PdfAsParameterExtractor;
import at.gv.egiz.pdfas.web.helper.RemotePDFFetcher;
import at.gv.egiz.pdfas.web.stats.StatisticEvent;
import at.gv.egiz.pdfas.web.stats.StatisticEvent.Operation;
import at.gv.egiz.pdfas.web.stats.StatisticEvent.Source;
import at.gv.egiz.pdfas.web.stats.StatisticEvent.Status;
import at.gv.egiz.pdfas.web.stats.StatisticFrontend;

/**
 * Servlet implementation class Sign
 */
public class ExternSignServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    public static final String PDF_AS_WEB_CONF = "pdf-as-web.conf";

    private static final String UPLOAD_PDF_DATA = "pdf-file";
    private static final String UPLOAD_DIRECTORY = "upload";

    private static final Logger logger = LoggerFactory.getLogger(ExternSignServlet.class);

    /**
     * Default constructor.
        
     */
    public ExternSignServlet() {
        String webconfig = System.getProperty(PDF_AS_WEB_CONF);

        if (webconfig == null) {
            logger.error("No web configuration provided! Please specify: " + PDF_AS_WEB_CONF);
            throw new RuntimeException("No web configuration provided! Please specify: " + PDF_AS_WEB_CONF);
        }

        WebConfiguration.configure(webconfig);
        PdfAsHelper.init();

        try {
            PdfAsFactory.validateConfiguration((ISettings) PdfAsHelper.getPdfAsConfig());
        } catch (PdfAsSettingsValidationException e) {
            // TODO Auto-generated catch block
            logger.error(e.getLocalizedMessage(), e.getCause());
            //e.printStackTrace();
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        //PdfAsHelper.regenerateSession(request);

        logger.debug("Get signing request");

        String errorUrl = PdfAsParameterExtractor.getInvokeErrorURL(request);
        PdfAsHelper.setErrorURL(request, response, errorUrl);

        StatisticEvent statisticEvent = new StatisticEvent();
        statisticEvent.setStartNow();
        statisticEvent.setSource(Source.WEB);
        statisticEvent.setOperation(Operation.SIGN);
        statisticEvent.setUserAgent(UserAgentFilter.getUserAgent());

        try {
            // Mandatory Parameters on Get Request:
            String invokeUrl = PdfAsParameterExtractor.getInvokeURL(request);
            PdfAsHelper.setInvokeURL(request, response, invokeUrl);

            String invokeTarget = PdfAsParameterExtractor.getInvokeTarget(request);
            PdfAsHelper.setInvokeTarget(request, response, invokeTarget);

            String pdfUrl = PdfAsParameterExtractor.getPdfUrl(request);

            if (pdfUrl == null) {
                throw new PdfAsWebException("No PDF URL given! Use POST request to sign without PDF URL.");
            }

            byte[] pdfData = RemotePDFFetcher.fetchPdfFile(pdfUrl);
            doSignature(request, response, pdfData, statisticEvent);
        } catch (Exception e) {
            logger.error("Signature failed", e);
            statisticEvent.setStatus(Status.ERROR);
            statisticEvent.setException(e);
            if (e instanceof PDFASError) {
                statisticEvent.setErrorCode(((PDFASError) e).getCode());
            }
            statisticEvent.setEndNow();
            statisticEvent.setTimestampNow();
            StatisticFrontend.getInstance().storeEvent(statisticEvent);
            statisticEvent.setLogged(true);

            PdfAsHelper.setSessionException(request, response, e.getMessage(), e);
            PdfAsHelper.gotoError(getServletContext(), request, response);
        }
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        //PdfAsHelper.regenerateSession(request);

        logger.debug("Post signing request");

        String errorUrl = PdfAsParameterExtractor.getInvokeErrorURL(request);
        PdfAsHelper.setErrorURL(request, response, errorUrl);

        StatisticEvent statisticEvent = new StatisticEvent();
        statisticEvent.setStartNow();
        statisticEvent.setSource(Source.WEB);
        statisticEvent.setOperation(Operation.SIGN);
        statisticEvent.setUserAgent(UserAgentFilter.getUserAgent());

        try {
            byte[] filecontent = null;

            // checks if the request actually contains upload file
            if (!ServletFileUpload.isMultipartContent(request)) {
                // No Uploaded data!
                if (PdfAsParameterExtractor.getPdfUrl(request) != null) {
                    doGet(request, response);
                    return;
                } else {
                    throw new PdfAsWebException("No Signature data defined!");
                }
            } else {
                // configures upload settings
                DiskFileItemFactory factory = new DiskFileItemFactory();
                factory.setSizeThreshold(WebConfiguration.getFilesizeThreshold());
                factory.setRepository(new File(System.getProperty("java.io.tmpdir")));

                ServletFileUpload upload = new ServletFileUpload(factory);
                upload.setFileSizeMax(WebConfiguration.getMaxFilesize());
                upload.setSizeMax(WebConfiguration.getMaxRequestsize());

                // constructs the directory path to store upload file
                String uploadPath = getServletContext().getRealPath("") + File.separator + UPLOAD_DIRECTORY;
                // creates the directory if it does not exist
                File uploadDir = new File(uploadPath);
                if (!uploadDir.exists()) {
                    uploadDir.mkdir();
                }

                List<?> formItems = upload.parseRequest(request);
                logger.debug(formItems.size() + " Items in form data");
                if (formItems.size() < 1) {
                    // No Uploaded data!
                    // Try do get
                    // No Uploaded data!
                    if (PdfAsParameterExtractor.getPdfUrl(request) != null) {
                        doGet(request, response);
                        return;
                    } else {
                        throw new PdfAsWebException("No Signature data defined!");
                    }
                } else {
                    for (int i = 0; i < formItems.size(); i++) {
                        Object obj = formItems.get(i);
                        if (obj instanceof FileItem) {
                            FileItem item = (FileItem) obj;
                            if (item.getFieldName().equals(UPLOAD_PDF_DATA)) {
                                filecontent = item.get();
                                try {
                                    File f = new File(item.getName());
                                    String name = f.getName();
                                    logger.debug("Got upload: " + item.getName());
                                    if (name != null) {
                                        if (!(name.endsWith(".pdf") || name.endsWith(".PDF"))) {
                                            name += ".pdf";
                                        }

                                        logger.debug("Setting Filename in session: " + name);
                                        PdfAsHelper.setPDFFileName(request, name);
                                    }
                                } catch (Throwable e) {
                                    logger.warn("In resolving filename", e);
                                }
                                if (filecontent.length < 10) {
                                    filecontent = null;
                                } else {
                                    logger.debug("Found pdf Data! Size: " + filecontent.length);
                                }
                            } else {
                                request.setAttribute(item.getFieldName(), item.getString());
                                logger.debug("Setting " + item.getFieldName() + " = " + item.getString());
                            }
                        } else {
                            logger.debug(obj.getClass().getName() + " - " + obj.toString());
                        }
                    }
                }
            }

            if (filecontent == null) {
                if (PdfAsParameterExtractor.getPdfUrl(request) != null) {
                    filecontent = RemotePDFFetcher.fetchPdfFile(PdfAsParameterExtractor.getPdfUrl(request));
                }
            }

            if (filecontent == null) {
                Object sourceObj = request.getAttribute("source");
                if (sourceObj != null) {
                    String source = sourceObj.toString();
                    if (source.equals("internal")) {
                        request.setAttribute("FILEERR", true);
                        request.getRequestDispatcher("index.jsp").forward(request, response);

                        statisticEvent.setStatus(Status.ERROR);
                        statisticEvent.setException(new Exception("No file uploaded"));
                        statisticEvent.setEndNow();
                        statisticEvent.setTimestampNow();
                        StatisticFrontend.getInstance().storeEvent(statisticEvent);
                        statisticEvent.setLogged(true);

                        return;
                    }
                }
                throw new PdfAsException("No Signature data available");
            }

            doSignature(request, response, filecontent, statisticEvent);
        } catch (Exception e) {
            logger.error("Signature failed", e);
            statisticEvent.setStatus(Status.ERROR);
            statisticEvent.setException(e);
            if (e instanceof PDFASError) {
                statisticEvent.setErrorCode(((PDFASError) e).getCode());
            }
            statisticEvent.setEndNow();
            statisticEvent.setTimestampNow();
            StatisticFrontend.getInstance().storeEvent(statisticEvent);
            statisticEvent.setLogged(true);

            PdfAsHelper.setSessionException(request, response, e.getMessage(), e);
            PdfAsHelper.gotoError(getServletContext(), request, response);
        }
    }

    protected void doSignature(HttpServletRequest request, HttpServletResponse response, byte[] pdfData,
            StatisticEvent statisticEvent) throws Exception {
        if (pdfData == null) {
            throw new PdfAsException("No Signature data available");
        }

        if (pdfData[0] != 0x25 || pdfData[1] != 0x50 || pdfData[2] != 0x44 || pdfData[3] != 0x46) {
            throw new PdfAsWebException("Received data is not a valid PDF-Document");
        }

        // Get Connector
        String connector = PdfAsParameterExtractor.getConnector(request);

        String transactionId = PdfAsParameterExtractor.getTransactionId(request);

        statisticEvent.setFilesize(pdfData.length);
        statisticEvent.setProfileId(null);
        statisticEvent.setDevice(connector);

        String invokeUrl = PdfAsParameterExtractor.getInvokeURL(request);
        PdfAsHelper.setInvokeURL(request, response, invokeUrl);

        SignatureVerificationLevel lvl = PdfAsParameterExtractor.getVerificationLevel(request);
        PdfAsHelper.setVerificationLevel(request, lvl);

        String qrcodeContent = PdfAsParameterExtractor.getQRCodeContent(request);
        PdfAsHelper.setQRCodeContent(request, qrcodeContent);

        String invokeTarget = PdfAsParameterExtractor.getInvokeTarget(request);
        PdfAsHelper.setInvokeTarget(request, response, invokeTarget);

        String errorUrl = PdfAsParameterExtractor.getInvokeErrorURL(request);
        PdfAsHelper.setErrorURL(request, response, errorUrl);

        String locale = PdfAsParameterExtractor.getLocale(request);
        PdfAsHelper.setLocale(request, response, locale);

        String filename = PdfAsParameterExtractor.getFilename(request);
        if (filename != null) {
            logger.debug("Setting Filename in session: " + filename);
            PdfAsHelper.setPDFFileName(request, filename);
        }

        String pdfDataHash = DigestHelper.getHexEncodedHash(pdfData);

        PdfAsHelper.setSignatureDataHash(request, pdfDataHash);
        logger.debug("Storing signatures data hash: " + pdfDataHash);

        logger.debug("Starting signature creation with: " + connector);

        //IPlainSigner signer;
        if (connector.equals("bku") || connector.equals("onlinebku") || connector.equals("mobilebku")) {
            // start asynchronous signature creation

            if (connector.equals("bku")) {
                if (WebConfiguration.getLocalBKUURL() == null) {
                    throw new PdfAsWebException("Invalid connector bku is not supported");
                }
            }
            if (connector.equals("mobilebku")) {
                if (WebConfiguration.getHandyBKUURL() == null) {
                    throw new PdfAsWebException("Invalid connector mobilebku is not supported");
                }
            }

            PdfAsHelper.setStatisticEvent(request, response, statisticEvent);

            PdfAsHelper.startSignature(request, response, getServletContext(), pdfData, connector,
                    PdfAsHelper.buildPosString(request, response), transactionId,
                    PdfAsParameterExtractor.getSigType(request),
                    PdfAsParameterExtractor.getPreProcessorMap(request),
                    PdfAsParameterExtractor.getOverwriteMap(request));
            return;
        } else if (connector.equals("jks") || connector.equals("moa")) {
            // start synchronous signature creation

            if (connector.equals("jks")) {

                String keyIdentifier = PdfAsParameterExtractor.getKeyIdentifier(request);

                boolean ksEnabled = false;

                if (keyIdentifier != null) {
                    ksEnabled = WebConfiguration.getKeystoreEnabled(keyIdentifier);
                } else {
                    ksEnabled = WebConfiguration.getKeystoreDefaultEnabled();
                }

                if (!ksEnabled) {
                    if (keyIdentifier != null) {
                        throw new PdfAsWebException(
                                "JKS connector [" + keyIdentifier + "] disabled or not existing.");
                    } else {
                        throw new PdfAsWebException("DEFAULT JKS connector disabled.");
                    }
                }
            }

            if (connector.equals("moa")) {
                if (!WebConfiguration.getMOASSEnabled()) {
                    throw new PdfAsWebException("Invalid connector moa is not supported");
                }
            }

            byte[] pdfSignedData = PdfAsHelper.synchornousSignature(request, response, pdfData);
            PdfAsHelper.setSignedPdf(request, response, pdfSignedData);

            statisticEvent.setStatus(Status.OK);
            statisticEvent.setEndNow();
            statisticEvent.setTimestampNow();
            StatisticFrontend.getInstance().storeEvent(statisticEvent);
            statisticEvent.setLogged(true);

            PdfAsHelper.gotoProvidePdf(getServletContext(), request, response);
            return;
        } else {
            throw new PdfAsWebException("Invalid connector (bku | moa | jks)");
        }

    }

}