Merge branch 'master' of git://github.com/f1ori/yacy

pull/1/head
admin 13 years ago
commit a4ac051029

@ -61,10 +61,12 @@ import java.awt.Image;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -74,6 +76,8 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
@ -646,143 +650,227 @@ public final class HTTPDFileHandler {
} }
} }
} }
} else if (((switchboard.getConfigBool("cgi.allow", false)) && // check if CGI execution is allowed in config // old-school CGI execution
(matchesSuffix(path, switchboard.getConfig("cgi.suffixes", null))) && // "right" file extension? } else if ((switchboard.getConfigBool("cgi.allow", false) // check if CGI execution is allowed in config
(path.substring(0, path.indexOf(targetFile.getName())).contains("/CGI-BIN/") || && matchesSuffix(path, switchboard.getConfig("cgi.suffixes", null)) // "right" file extension?
path.substring(0, path.indexOf(targetFile.getName())).contains("/cgi-bin/")) && // file in right directory? && path.substring(0, path.indexOf(targetFile.getName())).toUpperCase().contains("/CGI-BIN/") // file in right directory?
targetFile.exists()) && targetFile.exists())
) { ) {
String mimeType = "text/html"; if (!targetFile.canExecute()) {
int statusCode = 200; HTTPDemon.sendRespondError(
conProp,
out,
-1,
403,
null,
HeaderFramework.http1_1.get(
Integer.toString(403)),
null);
Log.logWarning(
"HTTPD",
"CGI script " + targetFile.getPath()
+ " could not be executed due to "
+ "insufficient access rights.");
} else {
String mimeType = "text/html";
int statusCode = 200;
ProcessBuilder pb; final ProcessBuilder pb =
new ProcessBuilder(assembleCommandFromShebang(targetFile));
pb.directory(targetFile.getParentFile());
final String fileSeparator =
System.getProperty("file.separator", "/");
// set environment variables
final Map<String, String> env = pb.environment();
env.put(
"SERVER_SOFTWARE",
getDefaultHeaders(path).get(HeaderFramework.SERVER));
env.put("SERVER_NAME", sb.peers.mySeed().getName());
env.put("GATEWAY_INTERFACE", "CGI/1.1");
if (httpVersion != null) {
env.put("SERVER_PROTOCOL", httpVersion);
}
env.put("SERVER_PORT", switchboard.getConfig("port", "8090"));
env.put("REQUEST_METHOD", method);
// env.put("PATH_INFO", ""); // TODO: implement
// env.put("PATH_TRANSLATED", ""); // TODO: implement
env.put("SCRIPT_NAME", path);
if (argsString != null) {
env.put("QUERY_STRING", argsString);
}
env.put("REMOTE_ADDR", clientIP);
// env.put("AUTH_TYPE", ""); // TODO: implement
// env.put("REMOTE_USER", ""); // TODO: implement
// env.put("REMOTE_IDENT", ""); // I don't think we need this
env.put(
"DOCUMENT_ROOT",
switchboard.getAppPath().getAbsolutePath()
+ fileSeparator + switchboard.getConfig("htDocsPath", "DATA/HTDOCS"));
if (requestHeader.getContentType() != null) {
env.put("CONTENT_TYPE", requestHeader.getContentType());
}
if (method.equalsIgnoreCase(HeaderFramework.METHOD_POST)
&& body != null) {
env.put(
"CONTENT_LENGTH",
Integer.toString(requestHeader.getContentLength()));
}
pb = new ProcessBuilder(targetFile.getAbsolutePath()); /* add values from request header to environment
* (see: http://hoohoo.ncsa.uiuc.edu/cgi/env.html#headers) */
for (final Map.Entry<String, String> requestHeaderEntry
: requestHeader.entrySet()) {
env.put("HTTP_"
+ requestHeaderEntry.getKey().toUpperCase().replace("-", "_"),
requestHeaderEntry.getValue());
}
final String fileSeparator = System.getProperty("file.separator", "/"); int exitValue = 0;
String cgiBody = null;
final StringBuilder error = new StringBuilder(256);
// set environment variables try {
final Map<String, String> env = pb.environment(); // start execution of script
env.put("SERVER_SOFTWARE", getDefaultHeaders(path).get(HeaderFramework.SERVER)); final Process p = pb.start();
env.put("SERVER_NAME", sb.peers.mySeed().getName());
env.put("GATEWAY_INTERFACE", "CGI/1.1"); final OutputStream os =
if (httpVersion != null) { new BufferedOutputStream(p.getOutputStream());
env.put("SERVER_PROTOCOL", httpVersion);
} if (method.equalsIgnoreCase(
env.put("SERVER_PORT", switchboard.getConfig("port", "8090")); HeaderFramework.METHOD_POST) && body != null) {
env.put("REQUEST_METHOD", method); final byte[] buffer = new byte[1024];
// env.put("PATH_INFO", ""); // TODO: implement int len = requestHeader.getContentLength();
// env.put("PATH_TRANSLATED", ""); // TODO: implement while (len > 0) {
env.put("SCRIPT_NAME", path); body.read(buffer);
if (argsString != null) { len = len - buffer.length;
env.put("QUERY_STRING", argsString); os.write(buffer);
} }
env.put("REMOTE_ADDR", clientIP); }
// env.put("AUTH_TYPE", ""); // TODO: implement
// env.put("REMOTE_USER", ""); // TODO: implement
// env.put("REMOTE_IDENT", ""); // I don't think we need this
env.put("DOCUMENT_ROOT", switchboard.getAppPath().getAbsolutePath() + fileSeparator + switchboard.getConfig("htDocsPath", "DATA/HTDOCS"));
if (requestHeader.getContentType() != null) {
env.put("CONTENT_TYPE", requestHeader.getContentType());
}
if (method.equalsIgnoreCase(HeaderFramework.METHOD_POST) && body != null) {
env.put("CONTENT_LENGTH", Integer.toString(requestHeader.getContentLength()));
}
// add values from request header to environment (see: http://hoohoo.ncsa.uiuc.edu/cgi/env.html#headers) os.close();
for (final Map.Entry<String, String> requestHeaderEntry : requestHeader.entrySet()) {
env.put("HTTP_" + requestHeaderEntry.getKey().toUpperCase().replace("-", "_"), requestHeaderEntry.getValue());
}
int exitValue = 0; try {
String cgiBody = null; p.waitFor();
} catch (final InterruptedException ex) {
try {
// start execution of script
final Process p = pb.start();
final OutputStream os = new BufferedOutputStream(p.getOutputStream());
if (method.equalsIgnoreCase(HeaderFramework.METHOD_POST) && body != null) {
final byte[] buffer = new byte[1024];
int len = requestHeader.getContentLength();
while (len > 0) {
body.read(buffer);
len = len - buffer.length;
os.write(buffer);
} }
}
os.close(); exitValue = p.exitValue();
try { final InputStream is =
p.waitFor(); new BufferedInputStream(p.getInputStream());
} catch (final InterruptedException ex) {
}
exitValue = p.exitValue(); final InputStream es =
new BufferedInputStream(p.getErrorStream());
final InputStream is = new BufferedInputStream(p.getInputStream()); final StringBuilder processOutput =
new StringBuilder(1024);
final StringBuilder StringBuilder = new StringBuilder(1024); while (is.available() > 0) {
processOutput.append((char) is.read());
}
while (is.available() > 0) { while (es.available() > 0) {
StringBuilder.append((char) is.read()); error.append((char) es.read());
} }
final String cgiReturn = StringBuilder.toString(); int indexOfDelimiter = processOutput.indexOf("\n\n", 0);
int indexOfDelimiter = cgiReturn.indexOf("\n\n",0); final String[] cgiHeader;
String[] cgiHeader = new String[0]; if (indexOfDelimiter > -1) {
if (indexOfDelimiter > -1) { cgiHeader =
cgiHeader = cgiReturn.substring(0, indexOfDelimiter).split("\n"); processOutput.substring(
} 0, indexOfDelimiter).split("\n");
cgiBody = cgiReturn.substring(indexOfDelimiter + 1); } else {
cgiHeader = new String[0];
String key; }
String value; cgiBody = processOutput.substring(indexOfDelimiter + 1);
for (final String element : cgiHeader) {
indexOfDelimiter = element.indexOf(':'); String key;
key = element.substring(0, indexOfDelimiter).trim(); String value;
value = element.substring(indexOfDelimiter + 1).trim(); for (final String element : cgiHeader) {
conProp.put(key, value); indexOfDelimiter = element.indexOf(':');
if (key.equals("Cache-Control") && value.equals("no-cache")) { key = element.substring(0, indexOfDelimiter).trim();
nocache = true; value = element.substring(indexOfDelimiter + 1).trim();
} else if (key.equals("Content-type")) { conProp.put(key, value);
mimeType = value; if ("Cache-Control".equals(key)
} else if (key.equals("Status")) { && "no-cache".equals(value)) {
if (key.length() > 2) { nocache = true;
try { } else if ("Content-type".equals(key)) {
statusCode = Integer.parseInt(value.substring(0, 3)); mimeType = value;
} catch (final NumberFormatException ex) { } else if ("Status".equals(key)) {
/* tough luck, we will just have to use 200 as default value */ if (key.length() > 2) {
try {
statusCode =
Integer.parseInt(
value.substring(0, 3));
} catch (final NumberFormatException ex) {
Log.logWarning(
"HTTPD",
"CGI script " + targetFile.getPath()
+ " returned illegal status code \""
+ value + "\".");
}
} }
} }
} }
} catch (final IOException ex) {
exitValue = -1;
} }
} catch (final IOException ex) {
exitValue = -1;
}
/* did the script return an exit value != 0 and still there is supposed to be /* did the script return an exit value != 0
* everything right with the HTTP status? -> change status to 500 since 200 would * and still there is supposed to be
* be a lie * everything right with the HTTP status?
*/ * -> change status to 500 since 200 would
if (exitValue != 0 && statusCode == 200) { * be a lie
statusCode = 500; */
} if (exitValue != 0 && statusCode == 200) {
statusCode = 500;
targetDate = new Date(System.currentTimeMillis()); }
if (exitValue == 0 || (cgiBody != null && !cgiBody.equals(""))) { targetDate = new Date(System.currentTimeMillis());
HTTPDemon.sendRespondHeader(conProp, out, httpVersion, statusCode, null, mimeType, cgiBody.length(), targetDate, null, null, null, null, nocache);
out.write(UTF8.getBytes(cgiBody)); if (exitValue == 0
} else { && cgiBody != null
HTTPDemon.sendRespondError(conProp, out, exitValue, statusCode, null, HeaderFramework.http1_1.get(Integer.toString(statusCode)), null); && !cgiBody.isEmpty()) {
HTTPDemon.sendRespondHeader(
conProp,
out,
httpVersion,
statusCode,
null,
mimeType,
cgiBody.length(),
targetDate,
null,
null,
null,
null,
nocache);
out.write(UTF8.getBytes(cgiBody));
} else {
HTTPDemon.sendRespondError(
conProp,
out,
exitValue,
statusCode,
null,
HeaderFramework.http1_1.get(
Integer.toString(statusCode)),
null);
Log.logWarning(
"HTTPD",
"CGI script " + targetFile.getPath()
+ " returned exit value " + exitValue
+ ", body empty: "
+ (cgiBody == null || cgiBody.isEmpty()));
if (error.length() > 0) {
Log.logWarning("HTTPD", "Reported error: " + error);
}
}
} }
} else if ((targetClass != null) && (path.endsWith(".stream"))) { } else if ((targetClass != null) && (path.endsWith(".stream"))) {
// call rewrite-class // call rewrite-class
requestHeader.put(HeaderFramework.CONNECTION_PROP_CLIENTIP, (String) conProp.get(HeaderFramework.CONNECTION_PROP_CLIENTIP)); requestHeader.put(HeaderFramework.CONNECTION_PROP_CLIENTIP, (String) conProp.get(HeaderFramework.CONNECTION_PROP_CLIENTIP));
@ -1177,6 +1265,29 @@ public final class HTTPDFileHandler {
} }
} }
/**
* Returns a list which contains parts of command
* which is used to start external process for
* CGI scripts.
* @param targetFile file to run
* @return list of parts of command
* @throws IOException if file can not be accessed
*/
private static List<String> assembleCommandFromShebang(
final File targetFile)
throws IOException {
final List<String > ret = new ArrayList<String>();
final BufferedReader br =
new BufferedReader(new FileReader(targetFile), 512);
final String line = br.readLine();
if (line.startsWith("#!")) {
ret.addAll(Arrays.asList(line.substring(2).split(" ")));
}
ret.add(targetFile.getAbsolutePath());
return ret;
}
private static final String appendPath(final String proplist, final String path) { private static final String appendPath(final String proplist, final String path) {
if (proplist.length() == 0) return path; if (proplist.length() == 0) return path;
if (proplist.indexOf(path) >= 0) return proplist; if (proplist.indexOf(path) >= 0) return proplist;

Loading…
Cancel
Save