/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.catalina.servlets;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Serial;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Pattern;

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.UnavailableException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import org.apache.catalina.Globals;
import org.apache.catalina.WebResource;
import org.apache.catalina.WebResourceRoot;
import org.apache.catalina.util.IOTools;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.compat.JrePlatform;
import org.apache.tomcat.util.http.Method;
import org.apache.tomcat.util.res.StringManager;


/**
 * CGI-invoking servlet for web applications, used to execute scripts which comply to the Common Gateway Interface (CGI)
 * specification and are named in the path-info used to invoke this servlet.
 * <p>
 * <i>Note: This code compiles and even works for simple CGI cases. Exhaustive testing has not been done. Please
 * consider it beta quality. Feedback is appreciated to the author (see below).</i>
 * </p>
 * <p>
 * <b>Example</b>:<br>
 * If an instance of this servlet was mapped (using <code>&lt;web-app&gt;/WEB-INF/web.xml</code>) to:
 * </p>
 * <p>
 * <code>
 * &lt;web-app&gt;/cgi-bin/*
 * </code>
 * </p>
 * <p>
 * then the following request:
 * </p>
 * <p>
 * <code>
 * http://localhost:8080/&lt;web-app&gt;/cgi-bin/dir1/script/pathinfo1
 * </code>
 * </p>
 * <p>
 * would result in the execution of the script
 * </p>
 * <p>
 * <code>
 * &lt;web-app-root&gt;/WEB-INF/cgi/dir1/script
 * </code>
 * </p>
 * <p>
 * with the script's <code>PATH_INFO</code> set to <code>/pathinfo1</code>.
 * </p>
 * <p>
 * Recommendation: House all your CGI scripts under <code>&lt;webapp&gt;/WEB-INF/cgi</code>. This will ensure that you
 * do not accidentally expose your cgi scripts' code to the outside world and that your cgis will be cleanly ensconced
 * underneath the WEB-INF (i.e., non-content) area.
 * </p>
 * <p>
 * The default CGI location is mentioned above. You have the flexibility to put CGIs wherever you want, however:
 * </p>
 * <p>
 * The CGI search path will start at webAppRootDir + File.separator + cgiPathPrefix (or webAppRootDir alone if
 * cgiPathPrefix is null).
 * </p>
 * <p>
 * cgiPathPrefix is defined by setting this servlet's cgiPathPrefix init parameter
 * </p>
 * <p>
 * <B>CGI Specification</B>:<br>
 * derived from <a href="http://cgi-spec.golux.com">http://cgi-spec.golux.com</a>. A work-in-progress &amp; expired
 * Internet Draft. Note no actual RFC describing the CGI specification exists. Where the behavior of this servlet
 * differs from the specification cited above, it is either documented here, a bug, or an instance where the
 * specification cited differs from Best Community Practice (BCP). Such instances should be well-documented here. Please
 * email the <a href="https://tomcat.apache.org/lists.html">Tomcat group</a> with amendments.
 * </p>
 * <p>
 * <b>Canonical metavariables</b>:<br>
 * The CGI specification defines the following canonical metavariables: <br>
 * [excerpt from CGI specification]
 *
 * <PRE>
 *  AUTH_TYPE
 *  CONTENT_LENGTH
 *  CONTENT_TYPE
 *  GATEWAY_INTERFACE
 *  PATH_INFO
 *  PATH_TRANSLATED
 *  QUERY_STRING
 *  REMOTE_ADDR
 *  REMOTE_HOST
 *  REMOTE_IDENT
 *  REMOTE_USER
 *  REQUEST_METHOD
 *  SCRIPT_NAME
 *  SERVER_NAME
 *  SERVER_PORT
 *  SERVER_PROTOCOL
 *  SERVER_SOFTWARE
 * </PRE>
 * <p>
 * Metavariables with names beginning with the protocol name (<EM>e.g.</EM>, "HTTP_ACCEPT") are also canonical in their
 * description of request header fields. The number and meaning of these fields may change independently of this
 * specification. (See also section 6.1.5 [of the CGI specification].)
 * </p>
 * [end excerpt]
 * <h2>Implementation notes</h2>
 * <p>
 * <b>standard input handling</b>: If your script accepts standard input, then the client must start sending input
 * within a certain timeout period, otherwise the servlet will assume no input is coming and carry on running the
 * script. The script's the standard input will be closed and handling of any further input from the client is
 * undefined. Most likely it will be ignored. If this behavior becomes undesirable, then this servlet needs to be
 * enhanced to handle threading of the spawned process' stdin, stdout, and stderr (which should not be too hard). <br>
 * If you find your cgi scripts are timing out receiving input, you can set the init parameter
 * <code>stderrTimeout</code> of your webapps' cgi-handling servlet.
 * </p>
 * <p>
 * <b>Metavariable Values</b>: According to the CGI specification, implementations may choose to represent both null or
 * missing values in an implementation-specific manner, but must define that manner. This implementation chooses to
 * always define all required metavariables, but set the value to "" for all metavariables whose value is either null or
 * undefined. PATH_TRANSLATED is the sole exception to this rule, as per the CGI Specification.
 * </p>
 * <p>
 * <b>NPH -- Non-parsed-header implementation</b>: This implementation does not support the CGI NPH concept, whereby
 * server ensures that the data supplied to the script are precisely as supplied by the client and unaltered by the
 * server.
 * </p>
 * <p>
 * The function of a servlet container (including Tomcat) is specifically designed to parse and possible alter
 * CGI-specific variables, and as such makes NPH functionality difficult to support.
 * </p>
 * <p>
 * The CGI specification states that compliant servers MAY support NPH output. It does not state servers MUST support
 * NPH output to be unconditionally compliant. Thus, this implementation maintains unconditional compliance with the
 * specification though NPH support is not present.
 * </p>
 * <p>
 * The CGI specification is located at <a href="http://cgi-spec.golux.com">http://cgi-spec.golux.com</a>.
 * </p>
 * <h3>TODO:</h3>
 * <ul>
 * <li>Support for setting headers (for example, Location headers don't work)
 * <li>Support for collapsing multiple header lines (per RFC 2616)
 * <li>Ensure handling of POST method does not interfere with 2.3 Filters
 * <li>Refactor some debug code out of core
 * <li>Ensure header handling preserves encoding
 * <li>Possibly rewrite CGIRunner.run()?
 * <li>Possibly refactor CGIRunner and CGIEnvironment as non-inner classes?
 * <li>Document handling of cgi stdin when there is no stdin
 * <li>Revisit IOException handling in CGIRunner.run()
 * <li>Better documentation
 * <li>Confirm use of ServletInputStream.available() in CGIRunner.run() is not needed
 * <li>[add more to this TODO list]
 * </ul>
 */
public final class CGIServlet extends HttpServlet {

    private static final Log log = LogFactory.getLog(CGIServlet.class);
    private static final StringManager sm = StringManager.getManager(CGIServlet.class);

    @Serial
    private static final long serialVersionUID = 1L;

    private static final Set<String> DEFAULT_SUPER_METHODS = new HashSet<>();
    private static final Pattern DEFAULT_CMD_LINE_ARGUMENTS_DECODED_PATTERN;
    private static final String ALLOW_ANY_PATTERN = ".*";

    static {
        DEFAULT_SUPER_METHODS.add(Method.HEAD);
        DEFAULT_SUPER_METHODS.add(Method.OPTIONS);
        DEFAULT_SUPER_METHODS.add(Method.TRACE);

        if (JrePlatform.IS_WINDOWS) {
            DEFAULT_CMD_LINE_ARGUMENTS_DECODED_PATTERN = Pattern.compile("[\\w\\Q-.\\/:\\E]+");
        } else {
            // No restrictions
            DEFAULT_CMD_LINE_ARGUMENTS_DECODED_PATTERN = null;
        }

    }


    /**
     * The CGI search path will start at webAppRootDir + File.separator + cgiPathPrefix (or webAppRootDir alone if
     * cgiPathPrefix is null)
     */
    private String cgiPathPrefix = null;

    /** the executable to use with the script */
    private String cgiExecutable = "perl";

    /** additional arguments for the executable */
    private List<String> cgiExecutableArgs = null;

    /** the encoding to use for parameters */
    private String parameterEncoding = System.getProperty("file.encoding", "UTF-8");

    /* The HTTP methods this Servlet will pass to the CGI script */
    private final Set<String> cgiMethods = new HashSet<>();
    private boolean cgiMethodsAll = false;

    private transient WebResourceRoot resources = null;


    /**
     * The time (in milliseconds) to wait for the reading of stderr to complete before terminating the CGI process.
     */
    private long stderrTimeout = 2000;

    /**
     * The regular expression used to select HTTP headers to be passed to the CGI process as environment variables. The
     * name of the environment variable will be the name of the HTTP header converter to upper case, prefixed with
     * <code>HTTP_</code> and with all <code>-</code> characters converted to <code>_</code>.
     */
    private Pattern envHttpHeadersPattern =
            Pattern.compile("ACCEPT[-0-9A-Z]*|CACHE-CONTROL|COOKIE|HOST|IF-[-0-9A-Z]*|REFERER|USER-AGENT");

    /** object used to ensure multiple threads don't try to expand same file */
    private static final Object expandFileLock = new Object();

    /** the shell environment variables to be passed to the CGI script */
    private final Map<String,String> shellEnv = new HashMap<>();

    /**
     * Enable creation of script command line arguments from query-string. See
     * https://tools.ietf.org/html/rfc3875#section-4.4 4.4. The Script Command Line
     */
    private boolean enableCmdLineArguments = false;

    /**
     * Limits the encoded form of individual command line arguments. By default, values are limited to those allowed by
     * the RFC. See https://tools.ietf.org/html/rfc3875#section-4.4 Uses \Q...\E to avoid individual quoting.
     */
    private Pattern cmdLineArgumentsEncodedPattern = Pattern.compile("[\\w\\Q%;/?:@&,$-.!~*'()\\E]+");

    /**
     * Limits the decoded form of individual command line arguments. Default varies by platform.
     */
    private Pattern cmdLineArgumentsDecodedPattern = DEFAULT_CMD_LINE_ARGUMENTS_DECODED_PATTERN;


    /**
     * {@inheritDoc}
     * <p>
     * Sets instance variables.
     */
    @Override
    public void init(ServletConfig config) throws ServletException {

        super.init(config);

        // Set our properties from the initialization parameters
        cgiPathPrefix = getServletConfig().getInitParameter("cgiPathPrefix");
        boolean passShellEnvironment =
                Boolean.parseBoolean(getServletConfig().getInitParameter("passShellEnvironment"));

        if (passShellEnvironment) {
            shellEnv.putAll(System.getenv());
        }

        Enumeration<String> e = config.getInitParameterNames();
        while (e.hasMoreElements()) {
            String initParamName = e.nextElement();
            if (initParamName.startsWith("environment-variable-")) {
                if (initParamName.length() == 21) {
                    throw new ServletException(sm.getString("cgiServlet.emptyEnvVarName"));
                }
                shellEnv.put(initParamName.substring(21), config.getInitParameter(initParamName));
            }
        }

        if (getServletConfig().getInitParameter("executable") != null) {
            cgiExecutable = getServletConfig().getInitParameter("executable");
        }

        if (getServletConfig().getInitParameter("executable-arg-1") != null) {
            List<String> args = new ArrayList<>();
            for (int i = 1;; i++) {
                String arg = getServletConfig().getInitParameter("executable-arg-" + i);
                if (arg == null) {
                    break;
                }
                args.add(arg);
            }
            cgiExecutableArgs = args;
        }

        if (getServletConfig().getInitParameter("parameterEncoding") != null) {
            parameterEncoding = getServletConfig().getInitParameter("parameterEncoding");
        }

        if (getServletConfig().getInitParameter("stderrTimeout") != null) {
            stderrTimeout = Long.parseLong(getServletConfig().getInitParameter("stderrTimeout"));
        }

        if (getServletConfig().getInitParameter("envHttpHeaders") != null) {
            envHttpHeadersPattern = Pattern.compile(getServletConfig().getInitParameter("envHttpHeaders"));
        }

        if (getServletConfig().getInitParameter("enableCmdLineArguments") != null) {
            enableCmdLineArguments = Boolean.parseBoolean(config.getInitParameter("enableCmdLineArguments"));
        }

        if (getServletConfig().getInitParameter("cgiMethods") != null) {
            String paramValue = getServletConfig().getInitParameter("cgiMethods");
            paramValue = paramValue.trim();
            if ("*".equals(paramValue)) {
                cgiMethodsAll = true;
            } else {
                String[] methods = paramValue.split(",");
                for (String method : methods) {
                    String trimmedMethod = method.trim();
                    cgiMethods.add(trimmedMethod);
                }
            }
        } else {
            cgiMethods.add(Method.GET);
            cgiMethods.add(Method.POST);
        }

        if (getServletConfig().getInitParameter("cmdLineArgumentsEncoded") != null) {
            cmdLineArgumentsEncodedPattern =
                    Pattern.compile(getServletConfig().getInitParameter("cmdLineArgumentsEncoded"));
        }

        String value = getServletConfig().getInitParameter("cmdLineArgumentsDecoded");
        if (ALLOW_ANY_PATTERN.equals(value)) {
            // Optimisation for case where anything is allowed
            cmdLineArgumentsDecodedPattern = null;
        } else if (value != null) {
            cmdLineArgumentsDecodedPattern = Pattern.compile(value);
        }

        // Load the web resources
        resources = (WebResourceRoot) getServletContext().getAttribute(Globals.RESOURCES_ATTR);

        if (resources == null) {
            throw new UnavailableException(sm.getString("cgiServlet.noResources"));
        }
    }


    /**
     * Logs important Servlet API and container information.
     *
     * @param req HttpServletRequest object used as source of information
     */
    private void printServletEnvironment(HttpServletRequest req) {

        // Document the properties from ServletRequest
        log.trace("ServletRequest Properties");
        Enumeration<String> attrs = req.getAttributeNames();
        while (attrs.hasMoreElements()) {
            String attr = attrs.nextElement();
            log.trace("Request Attribute: " + attr + ": [ " + req.getAttribute(attr) + "]");
        }
        log.trace("Character Encoding: [" + req.getCharacterEncoding() + "]");
        log.trace("Content Length: [" + req.getContentLengthLong() + "]");
        log.trace("Content Type: [" + req.getContentType() + "]");
        Enumeration<Locale> locales = req.getLocales();
        while (locales.hasMoreElements()) {
            Locale locale = locales.nextElement();
            log.trace("Locale: [" + locale + "]");
        }
        Enumeration<String> params;
        try {
            params = req.getParameterNames();
            while (params.hasMoreElements()) {
                String param = params.nextElement();
                for (String value : req.getParameterValues(param)) {
                    log.trace("Request Parameter: " + param + ":  [" + value + "]");
                }
            }
        } catch (IllegalStateException ise) {
            if (log.isTraceEnabled()) {
                log.trace("Request Parameters: [Invalid]", ise);
            }
        }
        log.trace("Protocol: [" + req.getProtocol() + "]");
        log.trace("Remote Address: [" + req.getRemoteAddr() + "]");
        log.trace("Remote Host: [" + req.getRemoteHost() + "]");
        log.trace("Scheme: [" + req.getScheme() + "]");
        log.trace("Secure: [" + req.isSecure() + "]");
        log.trace("Server Name: [" + req.getServerName() + "]");
        log.trace("Server Port: [" + req.getServerPort() + "]");

        // Document the properties from HttpServletRequest
        log.trace("HttpServletRequest Properties");
        log.trace("Auth Type: [" + req.getAuthType() + "]");
        log.trace("Context Path: [" + req.getContextPath() + "]");
        Cookie[] cookies = req.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                log.trace("Cookie: " + cookie.getName() + ": [" + cookie.getValue() + "]");
            }
        }
        Enumeration<String> headers = req.getHeaderNames();
        while (headers.hasMoreElements()) {
            String header = headers.nextElement();
            log.trace("HTTP Header: " + header + ": [" + req.getHeader(header) + "]");
        }
        log.trace("Method: [" + req.getMethod() + "]");
        log.trace("Path Info: [" + req.getPathInfo() + "]");
        log.trace("Path Translated: [" + req.getPathTranslated() + "]");
        log.trace("Query String: [" + req.getQueryString() + "]");
        log.trace("Remote User: [" + req.getRemoteUser() + "]");
        log.trace("Requested Session ID: [" + req.getRequestedSessionId() + "]");
        log.trace("Requested Session ID From Cookie: [" + req.isRequestedSessionIdFromCookie() + "]");
        log.trace("Requested Session ID From URL: [" + req.isRequestedSessionIdFromURL() + "]");
        log.trace("Requested Session ID Valid: [" + req.isRequestedSessionIdValid() + "]");
        log.trace("Request URI: [" + req.getRequestURI() + "]");
        log.trace("Servlet Path: [" + req.getServletPath() + "]");
        log.trace("User Principal: [" + req.getUserPrincipal() + "]");

        // Process the current session (if there is one)
        HttpSession session = req.getSession(false);
        if (session != null) {

            // Document the session properties
            log.trace("HttpSession Properties");
            log.trace("ID: [" + session.getId() + "]");
            log.trace("Creation Time: [" + new Date(session.getCreationTime()) + "]");
            log.trace("Last Accessed Time: [" + new Date(session.getLastAccessedTime()) + "]");
            log.trace("Max Inactive Interval: [" + session.getMaxInactiveInterval() + "]");

            // Document the session attributes
            attrs = session.getAttributeNames();
            while (attrs.hasMoreElements()) {
                String attr = attrs.nextElement();
                log.trace("Session Attribute: " + attr + ": [" + session.getAttribute(attr) + "]");
            }
        }

        // Document the servlet configuration properties
        log.trace("ServletConfig Properties");
        log.trace("Servlet Name: [" + getServletConfig().getServletName() + "]");

        // Document the servlet configuration initialization parameters
        params = getServletConfig().getInitParameterNames();
        while (params.hasMoreElements()) {
            String param = params.nextElement();
            String value = getServletConfig().getInitParameter(param);
            log.trace("Servlet Init Param: " + param + ": [" + value + "]");
        }

        // Document the servlet context properties
        log.trace("ServletContext Properties");
        log.trace("Major Version: [" + getServletContext().getMajorVersion() + "]");
        log.trace("Minor Version: [" + getServletContext().getMinorVersion() + "]");
        log.trace("Real Path for '/': [" + getServletContext().getRealPath("/") + "]");
        log.trace("Server Info: [" + getServletContext().getServerInfo() + "]");

        // Document the servlet context initialization parameters
        log.trace("ServletContext Initialization Parameters");
        params = getServletContext().getInitParameterNames();
        while (params.hasMoreElements()) {
            String param = params.nextElement();
            String value = getServletContext().getInitParameter(param);
            log.trace("Servlet Context Init Param: " + param + ": [" + value + "]");
        }

        // Document the servlet context attributes
        log.trace("ServletContext Attributes");
        attrs = getServletContext().getAttributeNames();
        while (attrs.hasMoreElements()) {
            String attr = attrs.nextElement();
            log.trace("Servlet Context Attribute: " + attr + ": [" + getServletContext().getAttribute(attr) + "]");
        }
    }


    @Override
    protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

        String method = req.getMethod();
        if (cgiMethodsAll || cgiMethods.contains(method)) {
            doGet(req, res);
        } else if (DEFAULT_SUPER_METHODS.contains(method)) {
            // If the CGI servlet is explicitly configured to handle one of
            // these methods it will be handled in the previous condition
            super.service(req, res);
        } else {
            // Unsupported method
            res.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
        }
    }


    /**
     * Provides CGI Gateway service.
     *
     * @param req HttpServletRequest passed in by servlet container
     * @param res HttpServletResponse passed in by servlet container
     *
     * @exception ServletException if a servlet-specific exception occurs
     * @exception IOException      if a read/write exception occurs
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

        CGIEnvironment cgiEnv = new CGIEnvironment(req, getServletContext());

        if (cgiEnv.isValid()) {
            CGIRunner cgi = new CGIRunner(cgiEnv.getCommand(), cgiEnv.getEnvironment(), cgiEnv.getWorkingDirectory(),
                    cgiEnv.getParameters());

            if (Method.POST.equals(req.getMethod())) {
                cgi.setInput(req.getInputStream());
            }
            cgi.setResponse(res);
            cgi.run();
        } else {
            res.sendError(404);
        }

        if (log.isTraceEnabled()) {
            String[] cgiEnvLines = cgiEnv.toString().split(System.lineSeparator());
            for (String cgiEnvLine : cgiEnvLines) {
                log.trace(cgiEnvLine);
            }

            printServletEnvironment(req);
        }
    }


    @Override
    protected void doOptions(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        // Note: This method will never be called if cgiMethods is "*" so that
        // case does not need to be handled here.
        Set<String> allowedMethods = new HashSet<>();
        allowedMethods.addAll(cgiMethods);
        allowedMethods.addAll(DEFAULT_SUPER_METHODS);

        StringBuilder headerValue = new StringBuilder();

        for (String method : allowedMethods) {
            headerValue.append(method);
            headerValue.append(',');
        }

        // Remove trailing comma
        headerValue.deleteCharAt(headerValue.length() - 1);

        res.setHeader("allow", headerValue.toString());
    }


    /*
     * Behaviour depends on the status code.
     *
     * Status < 400 - Calls setStatus. Returns false. CGI servlet will provide the response body.
     *
     * Status >= 400 - Calls sendError(status), returns true. Standard error page mechanism will provide the response
     * body.
     */
    private boolean setStatus(HttpServletResponse response, int status) throws IOException {
        if (status >= HttpServletResponse.SC_BAD_REQUEST) {
            response.sendError(status);
            return true;
        } else {
            response.setStatus(status);
            return false;
        }
    }


    /**
     * Encapsulates the CGI environment and rules to derive that environment from the servlet container and request
     * information.
     */
    protected class CGIEnvironment {


        /** context of the enclosing servlet */
        private ServletContext context = null;

        /** context path of enclosing servlet */
        private String contextPath = null;

        /** servlet URI of the enclosing servlet */
        private String servletPath = null;

        /** pathInfo for the current request */
        private String pathInfo = null;

        /** tempdir for context - used to expand scripts in unexpanded wars */
        private File tmpDir = null;

        /** derived cgi environment */
        private Map<String,String> env = null;

        /** cgi command to be invoked */
        private String command = null;

        /** cgi command's desired working directory */
        private final File workingDirectory;

        /** cgi command's command line parameters */
        private final ArrayList<String> cmdLineParameters = new ArrayList<>();

        /** whether or not this object is valid or not */
        private final boolean valid;


        /**
         * Creates a CGIEnvironment and derives the necessary environment, query parameters, working directory, cgi
         * command, etc.
         *
         * @param req     HttpServletRequest for information provided by the Servlet API
         * @param context ServletContext for information provided by the Servlet API
         *
         * @throws IOException an IO error occurred
         */
        protected CGIEnvironment(HttpServletRequest req, ServletContext context) throws IOException {
            setupFromContext(context);
            boolean valid = setupFromRequest(req);

            if (valid) {
                valid = setCGIEnvironment(req);
            }

            if (valid) {
                workingDirectory = new File(command.substring(0, command.lastIndexOf(File.separator)));
            } else {
                workingDirectory = null;
            }

            this.valid = valid;
        }


        /**
         * Uses the ServletContext to set some CGI variables
         *
         * @param context ServletContext for information provided by the Servlet API
         */
        protected void setupFromContext(ServletContext context) {
            this.context = context;
            this.tmpDir = (File) context.getAttribute(ServletContext.TEMPDIR);
        }


        /**
         * Uses the HttpServletRequest to set most CGI variables
         *
         * @param req HttpServletRequest for information provided by the Servlet API
         *
         * @return true if the request was parsed without error, false if there was a problem
         *
         * @throws UnsupportedEncodingException Unknown encoding
         */
        protected boolean setupFromRequest(HttpServletRequest req) throws UnsupportedEncodingException {

            boolean isIncluded = req.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null;

            // Look to see if this request is an include
            if (isIncluded) {
                this.contextPath = (String) req.getAttribute(RequestDispatcher.INCLUDE_CONTEXT_PATH);
                this.servletPath = (String) req.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH);
                this.pathInfo = (String) req.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO);
            } else {
                this.contextPath = req.getContextPath();
                this.servletPath = req.getServletPath();
                this.pathInfo = req.getPathInfo();
            }
            // If getPathInfo() returns null, must be using extension mapping
            // In this case, pathInfo should be same as servletPath
            if (this.pathInfo == null) {
                this.pathInfo = this.servletPath;
            }

            // If the request method is GET, POST or HEAD and the query string
            // does not contain an unencoded "=" this is an indexed query.
            // The parsed query string becomes the command line parameters
            // for the cgi command.
            if (enableCmdLineArguments && (Method.GET.equals(req.getMethod()) || Method.POST.equals(req.getMethod()) ||
                    Method.HEAD.equals(req.getMethod()))) {
                String qs;
                if (isIncluded) {
                    qs = (String) req.getAttribute(RequestDispatcher.INCLUDE_QUERY_STRING);
                } else {
                    qs = req.getQueryString();
                }
                if (qs != null && qs.indexOf('=') == -1) {
                    StringTokenizer qsTokens = new StringTokenizer(qs, "+");
                    while (qsTokens.hasMoreTokens()) {
                        String encodedArgument = qsTokens.nextToken();
                        if (!cmdLineArgumentsEncodedPattern.matcher(encodedArgument).matches()) {
                            if (log.isDebugEnabled()) {
                                log.debug(sm.getString("cgiServlet.invalidArgumentEncoded", encodedArgument,
                                        cmdLineArgumentsEncodedPattern.toString()));
                            }
                            return false;
                        }

                        String decodedArgument = URLDecoder.decode(encodedArgument, parameterEncoding);
                        if (cmdLineArgumentsDecodedPattern != null &&
                                !cmdLineArgumentsDecodedPattern.matcher(decodedArgument).matches()) {
                            if (log.isDebugEnabled()) {
                                log.debug(sm.getString("cgiServlet.invalidArgumentDecoded", decodedArgument,
                                        cmdLineArgumentsDecodedPattern.toString()));
                            }
                            return false;
                        }

                        cmdLineParameters.add(decodedArgument);
                    }
                }
            }

            return true;
        }


        /**
         * Resolves core information about the cgi script.
         * <p>
         * Example URI:
         * </p>
         *
         * <PRE>
         *  /servlet/cgigateway/dir1/realCGIscript/pathinfo1
         * </PRE>
         * <ul>
         * <LI><b>path</b> = $CATALINA_HOME/mywebapp/dir1/realCGIscript
         * <LI><b>scriptName</b> = /servlet/cgigateway/dir1/realCGIscript
         * <LI><b>cgiName</b> = /dir1/realCGIscript
         * <LI><b>name</b> = realCGIscript
         * </ul>
         * <p>
         * CGI search algorithm: search the real path below &lt;my-webapp-root&gt; and find the first non-directory in
         * the getPathTranslated("/"), reading/searching from left-to-right.
         * </p>
         * <p>
         * The CGI search path will start at webAppRootDir + File.separator + cgiPathPrefix (or webAppRootDir alone if
         * cgiPathPrefix is null).
         * </p>
         * <p>
         * cgiPathPrefix is defined by setting this servlet's cgiPathPrefix init parameter
         * </p>
         *
         * @param contextPath   String as from HttpServletRequest.getContextPath()
         * @param servletPath   String as from HttpServletRequest.getServletPath()
         * @param pathInfo      String from HttpServletRequest.getPathInfo()
         * @param cgiPathPrefix subdirectory of webAppRootDir below which the web app's CGIs may be stored; can be null.
         *                          The CGI search path will start at webAppRootDir + File.separator + cgiPathPrefix (or
         *                          webAppRootDir alone if cgiPathPrefix is null). cgiPathPrefix is defined by setting
         *                          the servlet's cgiPathPrefix init parameter.
         *
         * @return
         *             <ul>
         *             <li><code>path</code> - full file-system path to valid cgi script, or null if no cgi was found
         *             <li><code>scriptName</code> - CGI variable SCRIPT_NAME; the full URL path to valid cgi script or
         *             null if no cgi was found
         *             <li><code>cgiName</code> - servlet pathInfo fragment corresponding to the cgi script itself, or
         *             null if not found
         *             <li><code>name</code> - simple name (no directories) of the cgi script, or null if no cgi was
         *             found
         *             </ul>
         */
        protected String[] findCGI(String contextPath, String servletPath, String pathInfo, String cgiPathPrefix) {

            StringBuilder cgiPath = new StringBuilder();
            StringBuilder urlPath = new StringBuilder();

            WebResource cgiScript = null;

            if (cgiPathPrefix == null || cgiPathPrefix.isEmpty()) {
                cgiPath.append(servletPath);
            } else {
                cgiPath.append('/');
                cgiPath.append(cgiPathPrefix);
            }
            urlPath.append(servletPath);

            StringTokenizer pathWalker = new StringTokenizer(pathInfo, "/");

            while (pathWalker.hasMoreElements() && (cgiScript == null || !cgiScript.isFile())) {
                String urlSegment = pathWalker.nextToken();
                cgiPath.append('/');
                cgiPath.append(urlSegment);
                urlPath.append('/');
                urlPath.append(urlSegment);
                if (log.isTraceEnabled()) {
                    log.trace(sm.getString("cgiServlet.find.location", cgiPath.toString()));
                }
                cgiScript = resources.getResource(cgiPath.toString());
            }

            // No script was found
            if (cgiScript == null || !cgiScript.isFile()) {
                return new String[] { null, null, null, null };
            }

            // Set-up return values
            String path = null;
            String scriptName = null;
            String cgiName = null;
            String name = null;

            path = cgiScript.getCanonicalPath();
            if (path == null) {
                /*
                 * The script doesn't exist directly on the file system. It might be located in an archive or similar.
                 * Such scripts are extracted to the web application's temporary file location.
                 */
                File tmpCgiFile = new File(tmpDir + cgiPath.toString());
                if (!tmpCgiFile.exists()) {

                    // Create directories
                    File parent = tmpCgiFile.getParentFile();
                    if (!parent.mkdirs() && !parent.isDirectory()) {
                        log.warn(sm.getString("cgiServlet.expandCreateDirFail", parent.getAbsolutePath()));
                        return new String[] { null, null, null, null };
                    }

                    try (InputStream is = cgiScript.getInputStream()) {
                        synchronized (expandFileLock) {
                            // Check if file was created by concurrent request
                            if (!tmpCgiFile.exists()) {
                                try {
                                    Files.copy(is, tmpCgiFile.toPath());
                                } catch (IOException ioe) {
                                    log.warn(sm.getString("cgiServlet.expandFail", cgiScript.getURL(),
                                            tmpCgiFile.getAbsolutePath()), ioe);
                                    if (tmpCgiFile.exists()) {
                                        if (!tmpCgiFile.delete()) {
                                            log.warn(sm.getString("cgiServlet.expandDeleteFail",
                                                    tmpCgiFile.getAbsolutePath()));
                                        }
                                    }
                                    return new String[] { null, null, null, null };
                                }
                                if (log.isDebugEnabled()) {
                                    log.debug(sm.getString("cgiServlet.expandOk", cgiScript.getURL(),
                                            tmpCgiFile.getAbsolutePath()));
                                }
                            }
                        }
                    } catch (IOException ioe) {
                        log.warn(sm.getString("cgiServlet.expandCloseFail", cgiScript.getURL()), ioe);
                    }
                }
                path = tmpCgiFile.getAbsolutePath();
            }

            scriptName = urlPath.toString();
            cgiName = scriptName.substring(servletPath.length());
            name = scriptName.substring(scriptName.lastIndexOf('/') + 1);

            if (log.isTraceEnabled()) {
                log.trace(sm.getString("cgiServlet.find.found", name, path, scriptName, cgiName));
            }

            return new String[] { path, scriptName, cgiName, name };
        }


        /**
         * Constructs the CGI environment to be supplied to the invoked CGI script; relies heavily on Servlet API
         * methods and findCGI
         *
         * @param req request associated with the CGI Invocation
         *
         * @return true if environment was set OK, false if there was a problem and no environment was set
         *
         * @throws IOException an IO error occurred
         */
        protected boolean setCGIEnvironment(HttpServletRequest req) throws IOException {

            /*
             * This method is slightly ugly; c'est la vie.
             * "You cannot stop [ugliness], you can only hope to contain [it]" (apologies to Marv Albert regarding MJ)
             */

            // Add the shell environment variables (if any)
            Map<String,String> envp = new HashMap<>(shellEnv);

            // Add the CGI environment variables
            String sPathInfoOrig;
            String sPathInfoCGI;
            String sPathTranslatedCGI = null;
            String sCGIFullPath;
            String sCGIScriptName;
            String sCGIFullName;
            String sCGIName;
            String[] sCGINames;


            sPathInfoOrig = this.pathInfo;
            sPathInfoOrig = sPathInfoOrig == null ? "" : sPathInfoOrig;

            sCGINames = findCGI(contextPath, servletPath, sPathInfoOrig, cgiPathPrefix);

            sCGIFullPath = sCGINames[0];
            sCGIScriptName = sCGINames[1];
            sCGIFullName = sCGINames[2];
            sCGIName = sCGINames[3];

            if (sCGIFullPath == null || sCGIScriptName == null || sCGIFullName == null || sCGIName == null) {
                return false;
            }

            envp.put("SERVER_SOFTWARE", "TOMCAT");

            envp.put("SERVER_NAME", nullsToBlanks(req.getServerName()));

            envp.put("GATEWAY_INTERFACE", "CGI/1.1");

            envp.put("SERVER_PROTOCOL", nullsToBlanks(req.getProtocol()));

            int port = req.getServerPort();
            Integer iPort = (port == 0 ? Integer.valueOf(-1) : Integer.valueOf(port));
            envp.put("SERVER_PORT", iPort.toString());

            envp.put("REQUEST_METHOD", nullsToBlanks(req.getMethod()));

            envp.put("REQUEST_URI", nullsToBlanks(req.getRequestURI()));


            /*-
             * PATH_INFO should be determined by using sCGIFullName:
             * 1) Let sCGIFullName not end in a "/" (see method findCGI)
             * 2) Let sCGIFullName equal the pathInfo fragment which
             *    corresponds to the actual cgi script.
             * 3) Thus, PATH_INFO = request.getPathInfo().substring(
             *                      sCGIFullName.length())
             *
             * (see method findCGI, where the real work is done)
             *
             */
            if (pathInfo == null || (pathInfo.substring(sCGIFullName.length()).isEmpty())) {
                sPathInfoCGI = "";
            } else {
                sPathInfoCGI = pathInfo.substring(sCGIFullName.length());
            }
            envp.put("PATH_INFO", sPathInfoCGI);


            /*-
             * PATH_TRANSLATED must be determined after PATH_INFO (and the
             * implied real cgi-script) has been taken into account.
             *
             * The following example demonstrates:
             *
             * servlet info   = /servlet/cgigw/dir1/dir2/cgi1/trans1/trans2
             * cgifullpath    = /servlet/cgigw/dir1/dir2/cgi1
             * path_info      = /trans1/trans2
             * webAppRootDir  = servletContext.getRealPath("/")
             *
             * path_translated = servletContext.getRealPath("/trans1/trans2")
             *
             * That is, PATH_TRANSLATED = webAppRootDir + sPathInfoCGI
             * (unless sPathInfoCGI is null or blank), then the CGI
             * specification dictates that the PATH_TRANSLATED metavariable
             * SHOULD NOT be defined.
             *
             */
            if (!sPathInfoCGI.isEmpty()) {
                sPathTranslatedCGI = context.getRealPath(sPathInfoCGI);
            }
            if (sPathTranslatedCGI == null || sPathTranslatedCGI.isEmpty()) {
                // NOOP
            } else {
                envp.put("PATH_TRANSLATED", nullsToBlanks(sPathTranslatedCGI));
            }


            envp.put("SCRIPT_NAME", nullsToBlanks(sCGIScriptName));

            envp.put("QUERY_STRING", nullsToBlanks(req.getQueryString()));

            envp.put("REMOTE_HOST", nullsToBlanks(req.getRemoteHost()));

            envp.put("REMOTE_ADDR", nullsToBlanks(req.getRemoteAddr()));

            envp.put("AUTH_TYPE", nullsToBlanks(req.getAuthType()));

            envp.put("REMOTE_USER", nullsToBlanks(req.getRemoteUser()));

            envp.put("REMOTE_IDENT", ""); // not necessary for full compliance

            envp.put("CONTENT_TYPE", nullsToBlanks(req.getContentType()));


            /*
             * Note CGI spec says CONTENT_LENGTH must be NULL ("") or undefined if there is no content, so we cannot put
             * 0 or -1 in as per the Servlet API spec.
             */
            long contentLength = req.getContentLengthLong();
            String sContentLength = (contentLength <= 0 ? "" : Long.toString(contentLength));
            envp.put("CONTENT_LENGTH", sContentLength);


            Enumeration<String> headers = req.getHeaderNames();
            String header;
            while (headers.hasMoreElements()) {
                header = headers.nextElement().toUpperCase(Locale.ENGLISH);
                // REMIND: rewrite multiple headers as if received as single
                // REMIND: change character set
                // REMIND: I forgot what the previous REMIND means
                if (envHttpHeadersPattern.matcher(header).matches()) {
                    envp.put("HTTP_" + header.replace('-', '_'), req.getHeader(header));
                }
            }

            File fCGIFullPath = new File(sCGIFullPath);
            command = fCGIFullPath.getCanonicalPath();

            envp.put("X_TOMCAT_SCRIPT_PATH", command); // for kicks

            envp.put("SCRIPT_FILENAME", command); // for PHP

            this.env = envp;

            return true;
        }

        /**
         * Returns important CGI environment information in a multi-line text format.
         *
         * @return CGI environment info
         */
        @Override
        public String toString() {

            StringBuilder sb = new StringBuilder();

            sb.append("CGIEnvironment Info:");
            sb.append(System.lineSeparator());

            if (isValid()) {
                sb.append("Validity: [true]");
                sb.append(System.lineSeparator());

                sb.append("Environment values:");
                sb.append(System.lineSeparator());
                for (Entry<String,String> entry : env.entrySet()) {
                    sb.append("  ");
                    sb.append(entry.getKey());
                    sb.append(": [");
                    sb.append(blanksToString(entry.getValue(), "will be set to blank"));
                    sb.append(']');
                    sb.append(System.lineSeparator());
                }

                sb.append("Derived Command :[");
                sb.append(nullsToBlanks(command));
                sb.append(']');
                sb.append(System.lineSeparator());


                sb.append("Working Directory: [");
                if (workingDirectory != null) {
                    sb.append(workingDirectory.toString());
                }
                sb.append(']');
                sb.append(System.lineSeparator());

                sb.append("Command Line Params:");
                sb.append(System.lineSeparator());
                for (String param : cmdLineParameters) {
                    sb.append("  [");
                    sb.append(param);
                    sb.append(']');
                    sb.append(System.lineSeparator());
                }
            } else {
                sb.append("Validity: [false]");
                sb.append(System.lineSeparator());
                sb.append("CGI script not found or not specified.");
                sb.append(System.lineSeparator());
                sb.append("Check the HttpServletRequest pathInfo property to see if it is what ");
                sb.append(System.lineSeparator());
                sb.append("you meant it to be. You must specify an existent and executable file ");
                sb.append(System.lineSeparator());
                sb.append("as part of the path-info.");
                sb.append(System.lineSeparator());
            }

            return sb.toString();
        }


        /**
         * Gets derived command string
         *
         * @return command string
         */
        protected String getCommand() {
            return command;
        }


        /**
         * Gets derived CGI working directory
         *
         * @return working directory
         */
        protected File getWorkingDirectory() {
            return workingDirectory;
        }


        /**
         * Gets derived CGI environment
         *
         * @return CGI environment
         */
        protected Map<String,String> getEnvironment() {
            return env;
        }


        /**
         * Gets derived CGI query parameters
         *
         * @return CGI query parameters
         */
        protected ArrayList<String> getParameters() {
            return cmdLineParameters;
        }


        /**
         * Gets validity status
         *
         * @return true if this environment is valid, false otherwise
         */
        protected boolean isValid() {
            return valid;
        }


        /**
         * Converts null strings to blank strings ("")
         *
         * @param s string to be converted if necessary
         *
         * @return a non-null string, either the original or the empty string ("") if the original was <code>null</code>
         */
        protected String nullsToBlanks(String s) {
            return nullsToString(s, "");
        }


        /**
         * Converts null strings to another string
         *
         * @param couldBeNull string to be converted if necessary
         * @param subForNulls string to return instead of a null string
         *
         * @return a non-null string, either the original or the substitute string if the original was <code>null</code>
         */
        protected String nullsToString(String couldBeNull, String subForNulls) {
            return (couldBeNull == null ? subForNulls : couldBeNull);
        }


        /**
         * Converts blank strings to another string
         *
         * @param couldBeBlank string to be converted if necessary
         * @param subForBlanks string to return instead of a blank string
         *
         * @return a non-null string, either the original or the substitute string if the original was <code>null</code>
         *             or empty ("")
         */
        protected String blanksToString(String couldBeBlank, String subForBlanks) {
            return (couldBeBlank == null || couldBeBlank.isEmpty()) ? subForBlanks : couldBeBlank;
        }


    } // class CGIEnvironment


    /**
     * Encapsulates the knowledge of how to run a CGI script, given the script's desired environment and (optionally)
     * input/output streams
     * <p>
     * Exposes a <code>run</code> method used to actually invoke the CGI.
     * </p>
     * <p>
     * The CGI environment and settings are derived from the information passed to the constructor.
     * </p>
     * <p>
     * The input and output streams can be set by the <code>setInput</code> and <code>setResponse</code> methods,
     * respectively.
     * </p>
     */
    protected class CGIRunner {

        /** script/command to be executed */
        private final String command;

        /** environment used when invoking the cgi script */
        private final Map<String,String> env;

        /** working directory used when invoking the cgi script */
        private final File wd;

        /** command line parameters to be passed to the invoked script */
        private final ArrayList<String> params;

        /** stdin to be passed to cgi script */
        private InputStream stdin = null;

        /** response object used to set headers & get output stream */
        private HttpServletResponse response = null;

        /** boolean tracking whether this object has enough info to run() */
        private boolean readyToRun = false;


        /**
         * Creates a CGIRunner and initializes its environment, working directory, and query parameters. <BR>
         * Input/output streams (optional) are set using the <code>setInput</code> and <code>setResponse</code> methods,
         * respectively.
         *
         * @param command string full path to command to be executed
         * @param env     Map with the desired script environment
         * @param wd      File with the script's desired working directory
         * @param params  ArrayList with the script's query command line parameters as strings
         */
        protected CGIRunner(String command, Map<String,String> env, File wd, ArrayList<String> params) {
            this.command = command;
            this.env = env;
            this.wd = wd;
            this.params = params;
            updateReadyStatus();
        }


        /**
         * Checks and sets ready status
         */
        protected void updateReadyStatus() {
            readyToRun = command != null && env != null && wd != null && params != null && response != null;
        }


        /**
         * Gets ready status
         *
         * @return false if not ready (<code>run</code> will throw an exception), true if ready
         */
        protected boolean isReady() {
            return readyToRun;
        }


        /**
         * Sets HttpServletResponse object used to set headers and send output to
         *
         * @param response HttpServletResponse to be used
         */
        protected void setResponse(HttpServletResponse response) {
            this.response = response;
            updateReadyStatus();
        }


        /**
         * Sets standard input to be passed on to the invoked cgi script
         *
         * @param stdin InputStream to be used
         */
        protected void setInput(InputStream stdin) {
            this.stdin = stdin;
            updateReadyStatus();
        }


        /**
         * Converts a Map to a String array by converting each key/value pair in the Map to a String in the form
         * "key=value" (key + "=" + map.get(key).toString())
         *
         * @param map Map to convert
         *
         * @return converted string array
         *
         * @exception NullPointerException if a hash key has a null value
         */
        protected String[] mapToStringArray(Map<String,?> map) throws NullPointerException {
            List<String> list = new ArrayList<>(map.size());
            for (Entry<String,?> entry : map.entrySet()) {
                list.add(entry.getKey() + "=" + entry.getValue().toString());
            }
            return list.toArray(new String[0]);
        }


        /**
         * Executes a CGI script with the desired environment, current working directory, and input/output streams
         * <p>
         * This implements the following CGI specification recommendations:
         * </p>
         * <UL>
         * <LI>Servers SHOULD provide the "<code>query</code>" component of the script-URI as command-line arguments to
         * scripts if it does not contain any unencoded "=" characters and the command-line arguments can be generated
         * in an unambiguous manner.
         * <LI>Servers SHOULD set the AUTH_TYPE metavariable to the value of the "<code>auth-scheme</code>" token of the
         * "<code>Authorization</code>" if it was supplied as part of the request header. See
         * <code>getCGIEnvironment</code> method.
         * <LI>Where applicable, servers SHOULD set the current working directory to the directory in which the script
         * is located before invoking it.
         * <LI>Server implementations SHOULD define their behavior for the following cases:
         * <ul>
         * <LI><u>Allowed characters in pathInfo</u>: This implementation does not allow ASCII NUL nor any character
         * which cannot be URL-encoded according to internet standards;
         * <LI><u>Allowed characters in path segments</u>: This implementation does not allow non-terminal NULL segments
         * in the path -- IOExceptions may be thrown;
         * <LI><u>"<code>.</code>" and "<code>..</code>" path segments</u>: This implementation does not allow
         * "<code>.</code>" and "<code>..</code>" in the path, and such characters will result in an IOException being
         * thrown (this should never happen since Tomcat normalises the requestURI before determining the contextPath,
         * servletPath and pathInfo);
         * <LI><u>Implementation limitations</u>: This implementation does not impose any limitations except as
         * documented above. This implementation may be limited by the servlet container used to house this
         * implementation. In particular, all the primary CGI variable values are derived either directly or indirectly
         * from the container's implementation of the Servlet API methods.
         * </ul>
         * </UL>
         *
         * @exception IOException if problems during reading/writing occur
         *
         * @see java.lang.Runtime#exec(String[] command, String[] envp, File dir)
         */
        protected void run() throws IOException {

            /*
             * REMIND: this method feels too big; should it be re-written?
             */

            if (!isReady()) {
                throw new IOException(sm.getString("cgiServlet.notReady"));
            }

            if (log.isTraceEnabled()) {
                log.trace("envp: [" + env + "], command: [" + command + "]");
            }

            if ((command.contains(File.separator + "." + File.separator)) ||
                    (command.contains(File.separator + "..")) || (command.contains(".." + File.separator))) {
                throw new IOException(sm.getString("cgiServlet.invalidCommand", command));
            }

            Runtime rt;
            BufferedReader cgiHeaderReader = null;
            InputStream cgiOutput = null;
            BufferedReader commandsStdErr;
            Thread errReaderThread = null;
            BufferedOutputStream commandsStdIn;
            Process proc = null;
            int bufRead = -1;

            List<String> cmdAndArgs = new ArrayList<>();
            if (!cgiExecutable.isEmpty()) {
                cmdAndArgs.add(cgiExecutable);
            }
            if (cgiExecutableArgs != null) {
                cmdAndArgs.addAll(cgiExecutableArgs);
            }
            cmdAndArgs.add(command);
            cmdAndArgs.addAll(params);

            try {
                rt = Runtime.getRuntime();
                proc = rt.exec(cmdAndArgs.toArray(new String[0]), mapToStringArray(env), wd);

                String sContentLength = env.get("CONTENT_LENGTH");

                if (!"".equals(sContentLength)) {
                    commandsStdIn = new BufferedOutputStream(proc.getOutputStream());
                    IOTools.flow(stdin, commandsStdIn);
                    commandsStdIn.flush();
                    commandsStdIn.close();
                }

                /*
                 * we want to wait for the process to exit, Process.waitFor() is useless in our situation; see
                 * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4223650
                 */

                boolean isRunning = true;
                commandsStdErr = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
                final BufferedReader stdErrRdr = commandsStdErr;

                errReaderThread = new Thread(() -> sendToLog(stdErrRdr));
                errReaderThread.start();

                InputStream cgiHeaderStream = new HTTPHeaderInputStream(proc.getInputStream());
                cgiHeaderReader = new BufferedReader(new InputStreamReader(cgiHeaderStream));

                // Need to be careful here. If sendError() is called the
                // response body should be provided by the standard error page
                // process. But, if the output of the CGI process isn't read
                // then that process can hang.
                boolean skipBody = false;

                while (isRunning) {
                    try {
                        // set headers
                        String line;
                        while (((line = cgiHeaderReader.readLine()) != null) && !line.isEmpty()) {
                            if (log.isTraceEnabled()) {
                                log.trace("addHeader(\"" + line + "\")");
                            }
                            if (line.startsWith("HTTP")) {
                                skipBody = setStatus(response, getSCFromHttpStatusLine(line));
                            } else if (line.indexOf(':') >= 0) {
                                String header = line.substring(0, line.indexOf(':')).trim();
                                String value = line.substring(line.indexOf(':') + 1).trim();
                                if (header.equalsIgnoreCase("status")) {
                                    skipBody = setStatus(response, getSCFromCGIStatusHeader(value));
                                } else {
                                    response.addHeader(header, value);
                                }
                            } else {
                                log.info(sm.getString("cgiServlet.runBadHeader", line));
                            }
                        }

                        // write output
                        byte[] bBuf = new byte[2048];

                        OutputStream out = response.getOutputStream();
                        cgiOutput = proc.getInputStream();

                        try {
                            while (!skipBody && (bufRead = cgiOutput.read(bBuf)) != -1) {
                                if (log.isTraceEnabled()) {
                                    log.trace("output " + bufRead + " bytes of data");
                                }
                                out.write(bBuf, 0, bufRead);
                            }
                        } finally {
                            // Attempt to consume any leftover byte if something bad happens,
                            // such as a socket disconnect on the servlet side; otherwise, the
                            // external process could hang
                            if (bufRead != -1) {
                                while ((bufRead = cgiOutput.read(bBuf)) != -1) {
                                    // NOOP - just read the data
                                }
                            }
                        }

                        proc.exitValue(); // Throws exception if alive

                        isRunning = false;

                    } catch (IllegalThreadStateException e) {
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException ignored) {
                            // Ignore
                        }
                    }
                } // replacement for Process.waitFor()

            } catch (IOException ioe) {
                log.warn(sm.getString("cgiServlet.runFail"), ioe);
                throw ioe;
            } finally {
                // Close the header reader
                if (cgiHeaderReader != null) {
                    try {
                        cgiHeaderReader.close();
                    } catch (IOException ioe) {
                        log.warn(sm.getString("cgiServlet.runHeaderReaderFail"), ioe);
                    }
                }
                // Close the output stream if used
                if (cgiOutput != null) {
                    try {
                        cgiOutput.close();
                    } catch (IOException ioe) {
                        log.warn(sm.getString("cgiServlet.runOutputStreamFail"), ioe);
                    }
                }
                // Make sure the error stream reader has finished
                if (errReaderThread != null) {
                    try {
                        errReaderThread.join(stderrTimeout);
                    } catch (InterruptedException e) {
                        log.warn(sm.getString("cgiServlet.runReaderInterrupt"), e);
                    }
                }
                if (proc != null) {
                    proc.destroy();
                }
            }
        }

        /**
         * Parses the Status-Line and extracts the status code.
         *
         * @param line The HTTP Status-Line (RFC2616, section 6.1)
         *
         * @return The extracted status code or the code representing an internal error if a valid status code cannot be
         *             extracted.
         */
        private int getSCFromHttpStatusLine(String line) {
            int statusStart = line.indexOf(' ') + 1;

            if (statusStart < 1 || line.length() < statusStart + 3) {
                // Not a valid HTTP Status-Line
                log.warn(sm.getString("cgiServlet.runInvalidStatus", line));
                return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
            }

            String status = line.substring(statusStart, statusStart + 3);

            int statusCode;
            try {
                statusCode = Integer.parseInt(status);
            } catch (NumberFormatException nfe) {
                // Not a valid status code
                log.warn(sm.getString("cgiServlet.runInvalidStatus", status));
                return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
            }

            return statusCode;
        }

        /**
         * Parses the CGI Status Header value and extracts the status code.
         *
         * @param value The CGI Status value of the form <code>
         *             digit digit digit SP reason-phrase</code>
         *
         * @return The extracted status code or the code representing an internal error if a valid status code cannot be
         *             extracted.
         */
        private int getSCFromCGIStatusHeader(String value) {
            if (value.length() < 3) {
                // Not a valid status value
                log.warn(sm.getString("cgiServlet.runInvalidStatus", value));
                return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
            }

            String status = value.substring(0, 3);

            int statusCode;
            try {
                statusCode = Integer.parseInt(status);
            } catch (NumberFormatException nfe) {
                // Not a valid status code
                log.warn(sm.getString("cgiServlet.runInvalidStatus", status));
                return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
            }

            return statusCode;
        }

        private void sendToLog(BufferedReader rdr) {
            String line;
            int lineCount = 0;
            try {
                while ((line = rdr.readLine()) != null) {
                    log.warn(sm.getString("cgiServlet.runStdErr", line));
                    lineCount++;
                }
            } catch (IOException ioe) {
                log.warn(sm.getString("cgiServlet.runStdErrFail"), ioe);
            } finally {
                try {
                    rdr.close();
                } catch (IOException ioe) {
                    log.warn(sm.getString("cgiServlet.runStdErrFail"), ioe);
                }
            }
            if (lineCount > 0) {
                log.warn(sm.getString("cgiServlet.runStdErrCount", Integer.valueOf(lineCount)));
            }
        }
    } // class CGIRunner

    /**
     * This is an input stream specifically for reading HTTP headers. It reads up to and including the two blank lines
     * terminating the headers. It allows the content to be read using bytes or characters as appropriate.
     */
    protected static class HTTPHeaderInputStream extends InputStream {
        private static final int STATE_CHARACTER = 0;
        private static final int STATE_FIRST_CR = 1;
        private static final int STATE_FIRST_LF = 2;
        private static final int STATE_SECOND_CR = 3;
        private static final int STATE_HEADER_END = 4;

        private final InputStream input;
        private int state;

        HTTPHeaderInputStream(InputStream theInput) {
            input = theInput;
            state = STATE_CHARACTER;
        }

        /**
         * @see java.io.InputStream#read()
         */
        @Override
        public int read() throws IOException {
            if (state == STATE_HEADER_END) {
                return -1;
            }

            int i = input.read();

            /*
             * Update the state
             * State machine looks like this
             * @formatter:off
             *
             *    -------->--------
             *   |      (CR)       |
             *   |                 |
             *  CR1--->---         |
             *   |        |        |
             *   ^(CR)    |(LF)    |
             *   |        |        |
             * CHAR--->--LF1--->--EOH
             *      (LF)  |  (LF)  |
             *            |(CR)    ^(LF)
             *            |        |
             *          (CR2)-->---
             *
             * @formatter:on
             */
            if (i == 10) {
                // LF
                switch (state) {
                    case STATE_CHARACTER:
                        state = STATE_FIRST_LF;
                        break;
                    case STATE_FIRST_CR:
                        state = STATE_FIRST_LF;
                        break;
                    case STATE_FIRST_LF:
                    case STATE_SECOND_CR:
                        state = STATE_HEADER_END;
                        break;
                }

            } else if (i == 13) {
                // CR
                switch (state) {
                    case STATE_CHARACTER:
                        state = STATE_FIRST_CR;
                        break;
                    case STATE_FIRST_CR:
                        state = STATE_HEADER_END;
                        break;
                    case STATE_FIRST_LF:
                        state = STATE_SECOND_CR;
                        break;
                }

            } else {
                state = STATE_CHARACTER;
            }

            return i;
        }
    } // class HTTPHeaderInputStream

} // class CGIServlet
