cgiservlet.java

来自「业界著名的tomcat服务器的最新6.0的源代码。」· Java 代码 · 共 1,727 行 · 第 1/5 页

JAVA
1,727
字号
        }



    } //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 constuctor.
     *
     * </p>
     * <p>
     *
     * The input and output streams can be set by the <code>setInput</code>
     * and <code>setResponse</code> methods, respectively.
     * </p>
     *
     * @version   $Revision: 505743 $, $Date: 2007-02-10 19:55:08 +0100 (sam., 10 févr. 2007) $
     */

    protected class CGIRunner {

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

        /** command line parameters to be passed to the invoked script */
        private ArrayList 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;




        /**
         *  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      Hashtable 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
         *                  paramters as strings
         */
        protected CGIRunner(String command, Hashtable env, File wd,
                            ArrayList 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
         */
        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 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
         *
         */
        protected 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 CGI 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>
         *
         * @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(this.getClass().getName()
                                      + ": not ready to run.");
            }

            if (debug >= 1 ) {
                log("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;
            InputStream cgiOutput = null;
            BufferedReader commandsStdErr = null;
            BufferedOutputStream commandsStdIn = null;
            Process proc = null;
            int bufRead = -1;

            //create query arguments
            StringBuffer cmdAndArgs = new StringBuffer();
            if (command.indexOf(" ") < 0) {
                cmdAndArgs.append(command);
            } else {
                // Spaces used as delimiter, so need to use quotes
                cmdAndArgs.append("\"");
                cmdAndArgs.append(command);
                cmdAndArgs.append("\"");
            }

            for (int i=0; i < params.size(); i++) {
                cmdAndArgs.append(" ");
                String param = (String) params.get(i);
                if (param.indexOf(" ") < 0) {
                    cmdAndArgs.append(param);
                } else {
                    // Spaces used as delimiter, so need to use quotes
                    cmdAndArgs.append("\"");
                    cmdAndArgs.append(param);
                    cmdAndArgs.append("\"");
                }
            }

            StringBuffer command = new StringBuffer(cgiExecutable);
            command.append(" ");
            command.append(cmdAndArgs.toString());
            cmdAndArgs = command;

            try {
                rt = Runtime.getRuntime();
                proc = rt.exec(cmdAndArgs.toString(), hashToStringArray(env), wd);
    
                String sContentLength = (String) 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://developer.java.sun.com/developer/
                 *                               bugParade/bugs/4223650.html
                 */

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

                new Thread() {
                    public void run () {
                        sendToLog(stdErrRdr) ;
                    } ;
                }.start() ;

                InputStream cgiHeaderStream =
                    new HTTPHeaderInputStream(proc.getInputStream());
                BufferedReader cgiHeaderReader =
                    new BufferedReader(new InputStreamReader(cgiHeaderStream));
            
                while (isRunning) {
                    try {
                        //set headers
                        String line = null;
                        while (((line = cgiHeaderReader.readLine()) != null)
                               && !("".equals(line))) {
                            if (debug >= 2) {
                                log("runCGI: addHeader(\"" + line + "\")");
                            }
                            if (line.startsWith("HTTP")) {
                                response.setStatus(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")) {
                                    response.setStatus(getSCFromCGIStatusHeader(value));
                                } else {
                                    response.addHeader(header , value);
                                }
                            } else {
                                log("runCGI: bad header line \"" + line + "\"");
   

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?