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

pull/1/head
admin 14 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,25 +650,44 @@ 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())
) { ) {
if (!targetFile.canExecute()) {
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"; String mimeType = "text/html";
int statusCode = 200; int statusCode = 200;
ProcessBuilder pb; final ProcessBuilder pb =
new ProcessBuilder(assembleCommandFromShebang(targetFile));
pb = new ProcessBuilder(targetFile.getAbsolutePath()); pb.directory(targetFile.getParentFile());
final String fileSeparator = System.getProperty("file.separator", "/"); final String fileSeparator =
System.getProperty("file.separator", "/");
// set environment variables // set environment variables
final Map<String, String> env = pb.environment(); final Map<String, String> env = pb.environment();
env.put("SERVER_SOFTWARE", getDefaultHeaders(path).get(HeaderFramework.SERVER)); env.put(
"SERVER_SOFTWARE",
getDefaultHeaders(path).get(HeaderFramework.SERVER));
env.put("SERVER_NAME", sb.peers.mySeed().getName()); env.put("SERVER_NAME", sb.peers.mySeed().getName());
env.put("GATEWAY_INTERFACE", "CGI/1.1"); env.put("GATEWAY_INTERFACE", "CGI/1.1");
if (httpVersion != null) { if (httpVersion != null) {
@ -672,39 +695,52 @@ public final class HTTPDFileHandler {
} }
env.put("SERVER_PORT", switchboard.getConfig("port", "8090")); env.put("SERVER_PORT", switchboard.getConfig("port", "8090"));
env.put("REQUEST_METHOD", method); env.put("REQUEST_METHOD", method);
// env.put("PATH_INFO", ""); // TODO: implement // env.put("PATH_INFO", ""); // TODO: implement
// env.put("PATH_TRANSLATED", ""); // TODO: implement // env.put("PATH_TRANSLATED", ""); // TODO: implement
env.put("SCRIPT_NAME", path); env.put("SCRIPT_NAME", path);
if (argsString != null) { if (argsString != null) {
env.put("QUERY_STRING", argsString); env.put("QUERY_STRING", argsString);
} }
env.put("REMOTE_ADDR", clientIP); env.put("REMOTE_ADDR", clientIP);
// env.put("AUTH_TYPE", ""); // TODO: implement // env.put("AUTH_TYPE", ""); // TODO: implement
// env.put("REMOTE_USER", ""); // TODO: implement // env.put("REMOTE_USER", ""); // TODO: implement
// env.put("REMOTE_IDENT", ""); // I don't think we need this // env.put("REMOTE_IDENT", ""); // I don't think we need this
env.put("DOCUMENT_ROOT", switchboard.getAppPath().getAbsolutePath() + fileSeparator + switchboard.getConfig("htDocsPath", "DATA/HTDOCS")); env.put(
"DOCUMENT_ROOT",
switchboard.getAppPath().getAbsolutePath()
+ fileSeparator + switchboard.getConfig("htDocsPath", "DATA/HTDOCS"));
if (requestHeader.getContentType() != null) { if (requestHeader.getContentType() != null) {
env.put("CONTENT_TYPE", requestHeader.getContentType()); env.put("CONTENT_TYPE", requestHeader.getContentType());
} }
if (method.equalsIgnoreCase(HeaderFramework.METHOD_POST) && body != null) { if (method.equalsIgnoreCase(HeaderFramework.METHOD_POST)
env.put("CONTENT_LENGTH", Integer.toString(requestHeader.getContentLength())); && 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) /* add values from request header to environment
for (final Map.Entry<String, String> requestHeaderEntry : requestHeader.entrySet()) { * (see: http://hoohoo.ncsa.uiuc.edu/cgi/env.html#headers) */
env.put("HTTP_" + requestHeaderEntry.getKey().toUpperCase().replace("-", "_"), requestHeaderEntry.getValue()); for (final Map.Entry<String, String> requestHeaderEntry
: requestHeader.entrySet()) {
env.put("HTTP_"
+ requestHeaderEntry.getKey().toUpperCase().replace("-", "_"),
requestHeaderEntry.getValue());
} }
int exitValue = 0; int exitValue = 0;
String cgiBody = null; String cgiBody = null;
final StringBuilder error = new StringBuilder(256);
try { try {
// start execution of script // start execution of script
final Process p = pb.start(); final Process p = pb.start();
final OutputStream os = new BufferedOutputStream(p.getOutputStream()); final OutputStream os =
new BufferedOutputStream(p.getOutputStream());
if (method.equalsIgnoreCase(HeaderFramework.METHOD_POST) && body != null) { if (method.equalsIgnoreCase(
HeaderFramework.METHOD_POST) && body != null) {
final byte[] buffer = new byte[1024]; final byte[] buffer = new byte[1024];
int len = requestHeader.getContentLength(); int len = requestHeader.getContentLength();
while (len > 0) { while (len > 0) {
@ -724,21 +760,33 @@ public final class HTTPDFileHandler {
exitValue = p.exitValue(); exitValue = p.exitValue();
final InputStream is = new BufferedInputStream(p.getInputStream()); final InputStream is =
new BufferedInputStream(p.getInputStream());
final StringBuilder StringBuilder = new StringBuilder(1024); final InputStream es =
new BufferedInputStream(p.getErrorStream());
final StringBuilder processOutput =
new StringBuilder(1024);
while (is.available() > 0) { while (is.available() > 0) {
StringBuilder.append((char) is.read()); processOutput.append((char) is.read());
}
while (es.available() > 0) {
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 = cgiReturn.substring(0, indexOfDelimiter).split("\n"); cgiHeader =
processOutput.substring(
0, indexOfDelimiter).split("\n");
} else {
cgiHeader = new String[0];
} }
cgiBody = cgiReturn.substring(indexOfDelimiter + 1); cgiBody = processOutput.substring(indexOfDelimiter + 1);
String key; String key;
String value; String value;
@ -747,16 +795,23 @@ public final class HTTPDFileHandler {
key = element.substring(0, indexOfDelimiter).trim(); key = element.substring(0, indexOfDelimiter).trim();
value = element.substring(indexOfDelimiter + 1).trim(); value = element.substring(indexOfDelimiter + 1).trim();
conProp.put(key, value); conProp.put(key, value);
if (key.equals("Cache-Control") && value.equals("no-cache")) { if ("Cache-Control".equals(key)
&& "no-cache".equals(value)) {
nocache = true; nocache = true;
} else if (key.equals("Content-type")) { } else if ("Content-type".equals(key)) {
mimeType = value; mimeType = value;
} else if (key.equals("Status")) { } else if ("Status".equals(key)) {
if (key.length() > 2) { if (key.length() > 2) {
try { try {
statusCode = Integer.parseInt(value.substring(0, 3)); statusCode =
Integer.parseInt(
value.substring(0, 3));
} catch (final NumberFormatException ex) { } catch (final NumberFormatException ex) {
/* tough luck, we will just have to use 200 as default value */ Log.logWarning(
"HTTPD",
"CGI script " + targetFile.getPath()
+ " returned illegal status code \""
+ value + "\".");
} }
} }
} }
@ -765,8 +820,10 @@ public final class HTTPDFileHandler {
exitValue = -1; 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
* everything right with the HTTP status?
* -> change status to 500 since 200 would
* be a lie * be a lie
*/ */
if (exitValue != 0 && statusCode == 200) { if (exitValue != 0 && statusCode == 200) {
@ -775,14 +832,45 @@ public final class HTTPDFileHandler {
targetDate = new Date(System.currentTimeMillis()); targetDate = new Date(System.currentTimeMillis());
if (exitValue == 0 || (cgiBody != null && !cgiBody.equals(""))) { if (exitValue == 0
HTTPDemon.sendRespondHeader(conProp, out, httpVersion, statusCode, null, mimeType, cgiBody.length(), targetDate, null, null, null, null, nocache); && cgiBody != null
&& !cgiBody.isEmpty()) {
HTTPDemon.sendRespondHeader(
conProp,
out,
httpVersion,
statusCode,
null,
mimeType,
cgiBody.length(),
targetDate,
null,
null,
null,
null,
nocache);
out.write(UTF8.getBytes(cgiBody)); out.write(UTF8.getBytes(cgiBody));
} else { } else {
HTTPDemon.sendRespondError(conProp, out, exitValue, statusCode, null, HeaderFramework.http1_1.get(Integer.toString(statusCode)), null); 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