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:
2026-10-11 00:07:06 -07:00
parent b0751fdbb1
commit dca48bce51
7 changed files with 117 additions and 0 deletions
+7
View File
@@ -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
+5
View File
@@ -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 ;;