|
|
@ -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;
|
|
|
|