Persist applet cookies to /config/saves
The JSObject stand-in kept cookies in memory, so saves were lost when the game restarted. Write them to a file the session manager can sync, with the policy granting only the agent jar access to that directory.
This commit is contained in:
@@ -37,6 +37,6 @@ 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 whose window has
|
||||
a working `document.cookie`, and a policy allowing HTTP requests through the
|
||||
a `document.cookie` that persists to `/config/saves/cookies.txt`, and a policy allowing HTTP requests through the
|
||||
game server's proxy. The same jar (`applet-support/`) is loaded as a Java agent
|
||||
that removes appletviewer's menu bar and status line.
|
||||
|
||||
@@ -1,25 +1,37 @@
|
||||
package netscape.javascript;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/** A document whose cookie member behaves like document.cookie in a browser. */
|
||||
/**
|
||||
* A document whose cookie member behaves like document.cookie in a browser.
|
||||
* Cookies persist to ~/saves/cookies.txt, one name=value pair per line.
|
||||
*/
|
||||
class Document extends JSObject {
|
||||
private final File file = AccessController.doPrivileged(
|
||||
(PrivilegedAction<File>) () -> new File(System.getProperty("user.home"), "saves/cookies.txt"));
|
||||
private final Map<String, String> cookies = new LinkedHashMap<String, String>();
|
||||
|
||||
Document() {
|
||||
for (String line : AccessController.doPrivileged((PrivilegedAction<List<String>>) this::read)) {
|
||||
put(line);
|
||||
}
|
||||
}
|
||||
|
||||
@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();
|
||||
return String.join("; ", lines());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -28,10 +40,44 @@ class Document extends JSObject {
|
||||
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());
|
||||
if (put(String.valueOf(value).split(";", 2)[0])) {
|
||||
AccessController.doPrivileged((PrivilegedAction<Void>) this::write);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean put(String pair) {
|
||||
int eq = pair.indexOf('=');
|
||||
if (eq <= 0) {
|
||||
return false;
|
||||
}
|
||||
cookies.put(pair.substring(0, eq).trim(), pair.substring(eq + 1).trim());
|
||||
return true;
|
||||
}
|
||||
|
||||
private List<String> lines() {
|
||||
List<String> lines = new ArrayList<String>();
|
||||
for (Map.Entry<String, String> cookie : cookies.entrySet()) {
|
||||
lines.add(cookie.getKey() + "=" + cookie.getValue());
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
private List<String> read() {
|
||||
try {
|
||||
return file.isFile() ? Files.readAllLines(file.toPath(), StandardCharsets.UTF_8) : new ArrayList<String>();
|
||||
} catch (IOException e) {
|
||||
System.err.println("Failed to read " + file + ": " + e);
|
||||
return new ArrayList<String>();
|
||||
}
|
||||
}
|
||||
|
||||
private Void write() {
|
||||
try {
|
||||
file.getParentFile().mkdirs();
|
||||
Files.write(file.toPath(), lines(), StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
System.err.println("Failed to write " + file + ": " + e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
grant {
|
||||
permission java.net.URLPermission "http:*", "*:*";
|
||||
};
|
||||
|
||||
grant codeBase "file:/opt/flashpoint/applet-support.jar" {
|
||||
permission java.util.PropertyPermission "user.home", "read";
|
||||
permission java.io.FilePermission "${user.home}${/}saves", "read,write";
|
||||
permission java.io.FilePermission "${user.home}${/}saves${/}-", "read,write";
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user