/*
 * 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.util;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import javax.servlet.http.HttpServletResponse;

/**
     * 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 constuctor.
     *
     * </p>
     * <p>
     *
     * The input and output streams can be set by the <code>setInput</code>
     * and <code>setResponse</code> methods, respectively.
     * </p>
     *
     * @author    Martin Dengler [root@martindengler.com]
     * @version   $Revision$, $Date$
     * @deprecated
     */
public class ProcessHelper {

    private static org.apache.commons.logging.Log log=
        org.apache.commons.logging.LogFactory.getLog( ProcessHelper.class );
    
    /** script/command to be executed */
    private String command = null;

    /** environment used when invoking the cgi script */
    private Hashtable env = null;

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

    /** query parameters to be passed to the invoked script */
    private Hashtable params = null;

    /** 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;

    /** the debugging detail level for this instance. */
    private int debug = 0;

    /** the time in ms to wait for the client to send us CGI input data */
    private int iClientInputTimeout;

    /**
     *  Creates a ProcessHelper 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      Hashtable with the desired script environment
     * @param  wd       File with the script's desired working directory
     * @param  params   Hashtable with the script's query parameters
     */
    public ProcessHelper(
        String command,
        Hashtable env,
        File wd,
        Hashtable params) {
        this.command = command;
        this.env = env;
        this.wd = wd;
        this.params = params;
        updateReadyStatus();
    }

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

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

    /**
     * Sets HttpServletResponse object used to set headers and send
     * output to
     *
     * @param  response   HttpServletResponse to be used
     *
     */
    public 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
     *
     */
    public void setInput(InputStream stdin) {
        this.stdin = stdin;
        updateReadyStatus();
    }

    /**
     * Converts a Hashtable to a String array by converting each
     * key/value pair in the Hashtable to a String in the form
     * "key=value" (hashkey + "=" + hash.get(hashkey).toString())
     *
     * @param  h   Hashtable to convert
     *
     * @return     converted string array
     *
     * @exception  NullPointerException   if a hash key has a null value
     *
     */
    private String[] hashToStringArray(Hashtable h)
        throws NullPointerException {
        Vector v = new Vector();
        Enumeration e = h.keys();
        while (e.hasMoreElements()) {
            String k = e.nextElement().toString();
            v.add(k + "=" + h.get(k));
        }
        String[] strArr = new String[v.size()];
        v.copyInto(strArr);
        return strArr;
    }

    /**
     * Executes a process script with the desired environment, current working
     * directory, and input/output streams
     *
     * <p>
     * This implements the following CGI specification recommedations:
     * <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 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 the path, and such characters
     *             will result in an IOException being thrown;
     *     <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>
     * </p>
     *
     * For more information, see java.lang.Runtime#exec(String command, 
     * String[] envp, File dir)
     *
     * @exception IOException if problems during reading/writing occur
     *
     */
    public void run() throws IOException {

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

        if (!isReady()) {
            throw new IOException(
                this.getClass().getName() + ": not ready to run.");
        }

        if (log.isDebugEnabled()) {
            log.debug("runCGI(envp=[" + env + "], command=" + command + ")");
        }

        if ((command.indexOf(File.separator + "." + File.separator) >= 0)
            || (command.indexOf(File.separator + "..") >= 0)
            || (command.indexOf(".." + File.separator) >= 0)) {
            throw new IOException(
                this.getClass().getName()
                    + "Illegal Character in CGI command "
                    + "path ('.' or '..') detected.  Not "
                    + "running CGI ["
                    + command
                    + "].");
        }

        /* original content/structure of this section taken from
         * http://developer.java.sun.com/developer/
         *                               bugParade/bugs/4216884.html
         * with major modifications by Martin Dengler
         */
        Runtime rt = null;
        BufferedReader commandsStdOut = null;
        BufferedReader commandsStdErr = null;
        BufferedOutputStream commandsStdIn = null;
        Process proc = null;
        byte[] bBuf = new byte[1024];
        char[] cBuf = new char[1024];
        int bufRead = -1;

        //create query arguments
        Enumeration paramNames = params.keys();
        StringBuffer cmdAndArgs = new StringBuffer(command);
        if (paramNames != null && paramNames.hasMoreElements()) {
            cmdAndArgs.append(" ");
            while (paramNames.hasMoreElements()) {
                String k = (String) paramNames.nextElement();
                String v = params.get(k).toString();
                if ((k.indexOf("=") < 0) && (v.indexOf("=") < 0)) {
                    cmdAndArgs.append(k);
                    cmdAndArgs.append("=");
                    v = java.net.URLEncoder.encode(v);
                    cmdAndArgs.append(v);
                    cmdAndArgs.append(" ");
                }
            }
        }

        String postIn = getPostInput(params);
        int contentLength =
            (postIn.length() + System.getProperty("line.separator").length());
        if ("POST".equals(env.get("REQUEST_METHOD"))) {
            env.put("CONTENT_LENGTH", new Integer(contentLength));
        }

        rt = Runtime.getRuntime();
        proc = rt.exec(cmdAndArgs.toString(), hashToStringArray(env), wd);

        /*
         * provide input to cgi
         * First  -- parameters
         * Second -- any remaining input
         */
        commandsStdIn = new BufferedOutputStream(proc.getOutputStream());
        if (log.isDebugEnabled()) {
            log.debug("runCGI stdin=[" + stdin + "], qs=" + env.get("QUERY_STRING"));
        }
        if ("POST".equals(env.get("REQUEST_METHOD"))) {
            if (log.isDebugEnabled()) {
                log.debug("runCGI: writing ---------------\n");
                log.debug(postIn);
                log.debug(
                    "runCGI: new content_length="
                        + contentLength
                        + "---------------\n");
            }
            commandsStdIn.write(postIn.getBytes());
        }
        if (stdin != null) {
            //REMIND: document this
            /* assume if nothing is available after a time, that nothing is
             * coming...
             */
            if (stdin.available() <= 0) {
                if (log.isDebugEnabled()) {
                    log.debug(
                        "runCGI stdin is NOT available ["
                            + stdin.available()
                            + "]");
                }
                try {
                    Thread.sleep(iClientInputTimeout);
                } catch (InterruptedException ignored) {
                }
            }
            if (stdin.available() > 0) {
                if (log.isDebugEnabled()) {
                    log.debug(
                        "runCGI stdin IS available ["
                            + stdin.available()
                            + "]");
                }
                bBuf = new byte[1024];
                bufRead = -1;
                try {
                    while ((bufRead = stdin.read(bBuf)) != -1) {
                        if (log.isDebugEnabled()) {
                            log.debug(
                                "runCGI: read ["
                                    + bufRead
                                    + "] bytes from stdin");
                        }
                        commandsStdIn.write(bBuf, 0, bufRead);
                    }
                    if (log.isDebugEnabled()) {
                        log.debug("runCGI: DONE READING from stdin");
                    }
                } catch (IOException ioe) {
                    log.error("runCGI: couldn't write all bytes.", ioe);
                }
            }
        }
        commandsStdIn.flush();
        commandsStdIn.close();

        /* we want to wait for the process to exit,  Process.waitFor()
         * is useless in our situation; see
         * http://developer.java.sun.com/developer/
         *                               bugParade/bugs/4223650.html
         */

        boolean isRunning = true;
        commandsStdOut =
            new BufferedReader(new InputStreamReader(proc.getInputStream()));
        commandsStdErr =
            new BufferedReader(new InputStreamReader(proc.getErrorStream()));
        BufferedWriter servletContainerStdout = null;

        try {
            if (response.getOutputStream() != null) {
                servletContainerStdout =
                    new BufferedWriter(
                        new OutputStreamWriter(response.getOutputStream()));
            }
        } catch (IOException ignored) {
            //NOOP: no output will be written
        }

        while (isRunning) {

            try {
                //read stderr first
                cBuf = new char[1024];
                while ((bufRead = commandsStdErr.read(cBuf)) != -1) {
                    if (servletContainerStdout != null) {
                        servletContainerStdout.write(cBuf, 0, bufRead);
                    }
                }

                //set headers
                String line = null;
                while (((line = commandsStdOut.readLine()) != null)
                    && !("".equals(line))) {
                    if (log.isDebugEnabled()) {
                        log.debug("runCGI: addHeader(\"" + line + "\")");
                    }
                    if (line.startsWith("HTTP")) {
                        //TODO: should set status codes (NPH support)
                        /*
                         * response.setStatus(getStatusCode(line));
                         */
                    } else {
                        response.addHeader(
                            line.substring(0, line.indexOf(":")).trim(),
                            line.substring(line.indexOf(":") + 1).trim());
                    }
                }

                //write output
                cBuf = new char[1024];
                while ((bufRead = commandsStdOut.read(cBuf)) != -1) {
                    if (servletContainerStdout != null) {
                        if (log.isDebugEnabled()) {
                            log.debug("runCGI: write(\"" + new String(cBuf) + "\")");
                        }
                        servletContainerStdout.write(cBuf, 0, bufRead);
                    }
                }

                if (servletContainerStdout != null) {
                    servletContainerStdout.flush();
                }

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

                isRunning = false;

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

    }

    /**
     * Gets a string for input to a POST cgi script
     *
     * @param  params   Hashtable of query parameters to be passed to
     *                  the CGI script
     * @return          for use as input to the CGI script
     */

    protected String getPostInput(Hashtable params) {
        String lineSeparator = System.getProperty("line.separator");
        Enumeration paramNames = params.keys();
        StringBuffer postInput = new StringBuffer("");
        StringBuffer qs = new StringBuffer("");
        if (paramNames != null && paramNames.hasMoreElements()) {
            while (paramNames.hasMoreElements()) {
                String k = (String) paramNames.nextElement();
                String v = params.get(k).toString();
                if ((k.indexOf("=") < 0) && (v.indexOf("=") < 0)) {
                    postInput.append(k);
                    qs.append(k);
                    postInput.append("=");
                    qs.append("=");
                    postInput.append(v);
                    qs.append(v);
                    postInput.append(lineSeparator);
                    qs.append("&");
                }
            }
        }
        qs.append(lineSeparator);
        return qs.append(postInput).toString();
    }

    public int getIClientInputTimeout() {
        return iClientInputTimeout;
    }

    public void setIClientInputTimeout(int iClientInputTimeout) {
        this.iClientInputTimeout = iClientInputTimeout;
    }
}
