Run applets that use LiveConnect or load images through the proxy
appletviewer has no netscape.javascript.JSObject, so applets that touch JavaScript fail to load, and Java 8 denies applets the URLPermission they need to fetch through an HTTP proxy. Add a JSObject stand-in with a working document.cookie and a policy granting HTTP URL access.
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
FROM eclipse-temurin:8-jdk AS jsobject
|
||||
COPY jsobject /src
|
||||
RUN mkdir /classes && \
|
||||
javac -d /classes $(find /src -name '*.java') && \
|
||||
jar cf /jsobject.jar -C /classes .
|
||||
|
||||
FROM ghcr.io/linuxserver/baseimage-selkies:debiantrixie
|
||||
|
||||
RUN apt-get update && \
|
||||
@@ -12,3 +18,4 @@ RUN apt-get update && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY root/ /
|
||||
COPY --from=jsobject /jsobject.jar /opt/flashpoint/jsobject.jar
|
||||
|
||||
@@ -33,3 +33,8 @@ different game, set `GAME_ID` and recreate the container. The launch log is at
|
||||
the game server, mounts the game's zip through the server's `mountzip` API, and
|
||||
runs the game's application with its HTTP proxy pointed at the game server.
|
||||
Selkies restarts the game when it exits (`RESTART_APP`).
|
||||
|
||||
`appletviewer` lacks two things applets got from the browser's Java plugin, so
|
||||
the image adds them: a `netscape.javascript.JSObject` stand-in (`jsobject/`)
|
||||
whose window has a working `document.cookie`, and a policy allowing HTTP
|
||||
requests through the game server's proxy.
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package netscape.javascript;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/** A document whose cookie member behaves like document.cookie in a browser. */
|
||||
class Document extends JSObject {
|
||||
private final Map<String, String> cookies = new LinkedHashMap<String, String>();
|
||||
|
||||
@Override
|
||||
public Object getMember(String name) throws JSException {
|
||||
if (!name.equals("cookie")) {
|
||||
return super.getMember(name);
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Map.Entry<String, String> cookie : cookies.entrySet()) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append("; ");
|
||||
}
|
||||
sb.append(cookie.getKey()).append('=').append(cookie.getValue());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMember(String name, Object value) throws JSException {
|
||||
if (!name.equals("cookie")) {
|
||||
super.setMember(name, value);
|
||||
return;
|
||||
}
|
||||
String pair = String.valueOf(value).split(";", 2)[0];
|
||||
int eq = pair.indexOf('=');
|
||||
if (eq > 0) {
|
||||
cookies.put(pair.substring(0, eq).trim(), pair.substring(eq + 1).trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package netscape.javascript;
|
||||
|
||||
public class JSException extends RuntimeException {
|
||||
public JSException() {
|
||||
}
|
||||
|
||||
public JSException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package netscape.javascript;
|
||||
|
||||
import java.applet.Applet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Stand-in for the browser's LiveConnect bridge, which appletviewer lacks. The
|
||||
* window holds a document with a working cookie; calls into JavaScript do nothing.
|
||||
*/
|
||||
public class JSObject {
|
||||
private static JSObject window;
|
||||
|
||||
private final Map<String, Object> members = new HashMap<String, Object>();
|
||||
|
||||
protected JSObject() {
|
||||
}
|
||||
|
||||
public static synchronized JSObject getWindow(Applet applet) throws JSException {
|
||||
if (window == null) {
|
||||
window = new JSObject();
|
||||
window.setMember("document", new Document());
|
||||
}
|
||||
return window;
|
||||
}
|
||||
|
||||
public Object call(String methodName, Object[] args) throws JSException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object eval(String s) throws JSException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object getMember(String name) throws JSException {
|
||||
return members.get(name);
|
||||
}
|
||||
|
||||
public void setMember(String name, Object value) throws JSException {
|
||||
members.put(name, value);
|
||||
}
|
||||
|
||||
public void removeMember(String name) throws JSException {
|
||||
members.remove(name);
|
||||
}
|
||||
|
||||
public Object getSlot(int index) throws JSException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setSlot(int index, Object value) throws JSException {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
grant {
|
||||
permission java.net.URLPermission "http:*", "*:*";
|
||||
};
|
||||
@@ -34,6 +34,8 @@ fi
|
||||
echo "Launching $ID: $app $cmd"
|
||||
case ${app,,} in
|
||||
'fpsoftware\startjava.bat' | 'fpsoftware\startjavainbrowser.bat')
|
||||
# Applets expect the browser's JavaScript bridge and a browser-like network policy
|
||||
export JAVA_TOOL_OPTIONS="-Xbootclasspath/a:/opt/flashpoint/jsobject.jar -Djava.security.policy=/opt/flashpoint/applet.policy"
|
||||
FP_PATH=$FP_PATH exec "$FP_PATH/FPSoftware/startJava.sh" "$cmd" ;;
|
||||
*)
|
||||
echo "Unsupported application: $app" >&2; exit 1 ;;
|
||||
|
||||
Reference in New Issue
Block a user