📄 cgiservlet.java
字号:
} //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>
*
* @author Martin Dengler [root@martindengler.com]
* @version $Revision: 1.14 $, $Date: 2004/01/26 19:47:39 $
*/
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;
/** 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;
/**
* 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 Hashtable with the script's query parameters
*
* @param res HttpServletResponse object for setting headers
* based on CGI script output
*
*/
protected CGIRunner(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
*/
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;
BufferedReader commandsStdOut = null;
BufferedReader commandsStdErr = null;
BufferedOutputStream commandsStdIn = null;
Process proc = null;
int bufRead = -1;
//create query arguments
Enumeration paramNames = params.keys();
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("\"");
}
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)) {
StringBuffer arg = new StringBuffer(k);
arg.append("=");
v = java.net.URLEncoder.encode(v);
arg.append(v);
if (arg.toString().indexOf(" ") < 0) {
cmdAndArgs.append(arg);
} else {
// Spaces used as delimiter, so need to use quotes
cmdAndArgs.append("\"");
cmdAndArgs.append(arg);
cmdAndArgs.append("\"");
}
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));
}*/
//if (command.endsWith(".pl") || command.endsWith(".cgi")) {
StringBuffer command = new StringBuffer(cgiExecutable);
command.append(" ");
command.append(cmdAndArgs.toString());
cmdAndArgs = command;
//}
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 (debug >= 2 ) {
log("runCGI stdin=[" + stdin + "], qs="
+ env.get("QUERY_STRING"));
}
if ("POST".equals(env.get("REQUEST_METHOD"))) {
if (debug >= 2) {
log("runCGI: writing ---------------\n");
log(postIn);
log("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 (debug >= 2 ) {
log("runCGI stdin is NOT available ["
+ stdin.available() + "]");
}
try {
Thread.currentThread().sleep(iClientInputTimeout);
} catch (InterruptedException ignored) {
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -