📄 cgiservlet.java
字号:
/*
* 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.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.UnavailableException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.catalina.Globals;
import org.apache.catalina.util.IOTools;
/**
* 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><web-app>/WEB-INF/web.xml</code>) to:
* </p>
* <p>
* <code>
* <web-app>/cgi-bin/*
* </code>
* </p>
* <p>
* then the following request:
* </p>
* <p>
* <code>
* http://localhost:8080/<web-app>/cgi-bin/dir1/script/pathinfo1
* </code>
* </p>
* <p>
* would result in the execution of the script
* </p>
* <p>
* <code>
* <web-app-root>/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><webapp>/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 & 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="mailto:tomcat-dev@jakarta.apache.org">Jakarta Tomcat group [tomcat-dev@jakarta.apache.org]</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]
*
* </p>
* <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></code> of your webapps' cgi-handling servlet
* to be
* </p>
* <p>
*
* <b>Metavariable Values</b>: According to the CGI specificion,
* 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 preceisely 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>
* <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> Make checking for "." and ".." in servlet & cgi PATH_INFO less
* draconian
* <li> [add more to this TODO list]
* </ul>
* </p>
*
* @author Martin T Dengler [root@martindengler.com]
* @author Amy Roh
* @version $Revision: 505743 $, $Date: 2007-02-10 19:55:08 +0100 (sam., 10 févr. 2007) $
* @since Tomcat 4.0
*
*/
public final class CGIServlet extends HttpServlet {
/* some vars below copied from Craig R. McClanahan's InvokerServlet */
/** the debugging detail level for this servlet. */
private int debug = 0;
/**
* 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";
/** the encoding to use for parameters */
private String parameterEncoding = System.getProperty("file.encoding",
"UTF-8");
/** object used to ensure multiple threads don't try to expand same file */
static Object expandFileLock = new Object();
/** the shell environment variables to be passed to the CGI script */
static Hashtable shellEnv = new Hashtable();
/**
* Sets instance variables.
* <P>
* Modified from Craig R. McClanahan's InvokerServlet
* </P>
*
* @param config a <code>ServletConfig</code> object
* containing the servlet's
* configuration and initialization
* parameters
*
* @exception ServletException if an exception has occurred that
* interferes with the servlet's normal
* operation
*/
public void init(ServletConfig config) throws ServletException {
super.init(config);
// Verify that we were not accessed using the invoker servlet
String servletName = getServletConfig().getServletName();
if (servletName == null)
servletName = "";
if (servletName.startsWith("org.apache.catalina.INVOKER."))
throw new UnavailableException
("Cannot invoke CGIServlet through the invoker");
// Set our properties from the initialization parameters
if (getServletConfig().getInitParameter("debug") != null)
debug = Integer.parseInt(getServletConfig().getInitParameter("debug"));
cgiPathPrefix = getServletConfig().getInitParameter("cgiPathPrefix");
boolean passShellEnvironment =
Boolean.valueOf(getServletConfig().getInitParameter("passShellEnvironment")).booleanValue();
if (passShellEnvironment) {
try {
shellEnv.putAll(getShellEnvironment());
} catch (IOException ioe) {
ServletException e = new ServletException(
"Unable to read shell environment variables", ioe);
throw e;
}
}
if (getServletConfig().getInitParameter("executable") != null) {
cgiExecutable = getServletConfig().getInitParameter("executable");
}
if (getServletConfig().getInitParameter("parameterEncoding") != null) {
parameterEncoding = getServletConfig().getInitParameter("parameterEncoding");
}
}
/**
* Prints out important Servlet API and container information
*
* <p>
* Copied from SnoopAllServlet by Craig R. McClanahan
* </p>
*
* @param out ServletOutputStream as target of the information
* @param req HttpServletRequest object used as source of information
* @param res HttpServletResponse object currently not used but could
* provide future information
*
* @exception IOException if a write operation exception occurs
*
*/
protected void printServletEnvironment(ServletOutputStream out,
HttpServletRequest req, HttpServletResponse res) throws IOException {
// Document the properties from ServletRequest
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -