mirror of
https://github.com/mitb-archive/filebot
synced 2024-12-24 00:38:52 -05:00
* remove "sandbox" feature which isn't used and probably wouldn't work that well anyhow
This commit is contained in:
parent
dc6cc5e9c1
commit
86cb93c040
@ -14,7 +14,6 @@ import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.AccessController;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.MissingResourceException;
|
||||
@ -27,7 +26,6 @@ import javax.script.SimpleBindings;
|
||||
import net.sourceforge.filebot.Analytics;
|
||||
import net.sourceforge.filebot.MediaTypes;
|
||||
import net.sourceforge.filebot.StandardRenameAction;
|
||||
import net.sourceforge.filebot.cli.ScriptShell.Script;
|
||||
import net.sourceforge.filebot.cli.ScriptShell.ScriptProvider;
|
||||
import net.sourceforge.filebot.web.CachedResource;
|
||||
|
||||
@ -88,7 +86,7 @@ public class ArgumentProcessor {
|
||||
Bindings bindings = new SimpleBindings();
|
||||
bindings.put("args", args.getFiles(false));
|
||||
|
||||
DefaultScriptProvider scriptProvider = new DefaultScriptProvider(args.trustScript);
|
||||
DefaultScriptProvider scriptProvider = new DefaultScriptProvider();
|
||||
URI script = scriptProvider.getScriptLocation(args.script);
|
||||
|
||||
if (!scriptProvider.isInlineScheme(script.getScheme())) {
|
||||
@ -105,7 +103,7 @@ public class ArgumentProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
ScriptShell shell = new ScriptShell(cli, args, AccessController.getContext(), scriptProvider);
|
||||
ScriptShell shell = new ScriptShell(scriptProvider, args.bindings);
|
||||
shell.runScript(script, bindings);
|
||||
}
|
||||
|
||||
@ -124,14 +122,8 @@ public class ArgumentProcessor {
|
||||
|
||||
public static class DefaultScriptProvider implements ScriptProvider {
|
||||
|
||||
private final boolean trustRemoteScript;
|
||||
|
||||
private URI baseScheme;
|
||||
|
||||
public DefaultScriptProvider(boolean trustRemoteScript) {
|
||||
this.trustRemoteScript = trustRemoteScript;
|
||||
}
|
||||
|
||||
public void setBaseScheme(URI baseScheme) {
|
||||
this.baseScheme = baseScheme;
|
||||
}
|
||||
@ -145,19 +137,14 @@ public class ArgumentProcessor {
|
||||
}
|
||||
|
||||
public boolean isInlineScheme(String scheme) {
|
||||
return "g".equals(scheme) || "system".equals(scheme);
|
||||
return "g".equals(scheme);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getScriptLocation(String input) throws Exception {
|
||||
try {
|
||||
return new URL(input).toURI();
|
||||
} catch (Exception _) {
|
||||
// system:in
|
||||
if (input.equals("system:in")) {
|
||||
return new URI("system", "in", null);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
// g:println 'hello world'
|
||||
if (input.startsWith("g:")) {
|
||||
return new URI("g", input.substring(2), null);
|
||||
@ -185,31 +172,18 @@ public class ArgumentProcessor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Script fetchScript(URI uri) throws IOException {
|
||||
public String fetchScript(URI uri) throws IOException {
|
||||
if (uri.getScheme().equals("file")) {
|
||||
return new Script(readAll(new InputStreamReader(new FileInputStream(new File(uri)), "UTF-8")), true);
|
||||
}
|
||||
|
||||
if (uri.getScheme().equals("system")) {
|
||||
return new Script(readAll(new InputStreamReader(System.in)), true);
|
||||
return readAll(new InputStreamReader(new FileInputStream(new File(uri)), "UTF-8"));
|
||||
}
|
||||
|
||||
if (uri.getScheme().equals("g")) {
|
||||
return new Script(uri.getSchemeSpecificPart(), true);
|
||||
return uri.getSchemeSpecificPart();
|
||||
}
|
||||
|
||||
// remote script
|
||||
String url;
|
||||
boolean trusted;
|
||||
|
||||
String resolver = getResourceTemplate(uri.getScheme());
|
||||
if (resolver != null) {
|
||||
url = String.format(resolver, uri.getSchemeSpecificPart());
|
||||
trusted = true;
|
||||
} else {
|
||||
url = uri.toString();
|
||||
trusted = trustRemoteScript;
|
||||
}
|
||||
String url = (resolver != null) ? String.format(resolver, uri.getSchemeSpecificPart()) : uri.toString();
|
||||
|
||||
// fetch remote script only if modified
|
||||
CachedResource<String> script = new CachedResource<String>(url, String.class, CachedResource.ONE_DAY) {
|
||||
@ -219,7 +193,7 @@ public class ArgumentProcessor {
|
||||
return Charset.forName("UTF-8").decode(data).toString();
|
||||
}
|
||||
};
|
||||
return new Script(script.get(), trusted);
|
||||
return script.get();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,8 @@ import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.security.AccessController;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -164,10 +164,10 @@ public class GroovyPad extends JFrame {
|
||||
|
||||
protected ScriptShell createScriptShell() {
|
||||
try {
|
||||
DefaultScriptProvider scriptProvider = new DefaultScriptProvider(true);
|
||||
DefaultScriptProvider scriptProvider = new DefaultScriptProvider();
|
||||
scriptProvider.setBaseScheme(new URI("fn", "%s", null));
|
||||
|
||||
return new ScriptShell(new CmdlineOperations(), ArgumentBean.parse(new String[0]), AccessController.getContext(), scriptProvider);
|
||||
return new ScriptShell(scriptProvider, new HashMap<String, Object>());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@ -232,15 +232,15 @@ public class GroovyPad extends JFrame {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
result = shell.evaluate(script, new SimpleBindings(), true);
|
||||
result = shell.evaluate(script, new SimpleBindings());
|
||||
|
||||
// print result and make sure to flush Groovy output
|
||||
SimpleBindings binding = new SimpleBindings();
|
||||
binding.put("result", result);
|
||||
if (result != null) {
|
||||
shell.evaluate("print('Result: '); println(result);", binding, true);
|
||||
shell.evaluate("print('Result: '); println(result);", binding);
|
||||
} else {
|
||||
shell.evaluate("println();", binding, true);
|
||||
shell.evaluate("println();", binding);
|
||||
}
|
||||
} catch (ScriptException e) {
|
||||
while (e.getCause() instanceof ScriptException) {
|
||||
|
@ -2,35 +2,18 @@ package net.sourceforge.filebot.cli;
|
||||
|
||||
import groovy.lang.GroovyClassLoader;
|
||||
|
||||
import java.awt.AWTPermission;
|
||||
import java.io.File;
|
||||
import java.io.FilePermission;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.management.ManagementPermission;
|
||||
import java.lang.reflect.ReflectPermission;
|
||||
import java.net.SocketPermission;
|
||||
import java.net.URI;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.Permissions;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.PropertyPermission;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.ScriptContext;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptException;
|
||||
import javax.script.SimpleBindings;
|
||||
import javax.script.SimpleScriptContext;
|
||||
|
||||
import net.sourceforge.filebot.format.ExpressionFormat;
|
||||
import net.sourceforge.filebot.format.PrivilegedInvocation;
|
||||
|
||||
import org.codehaus.groovy.control.CompilerConfiguration;
|
||||
import org.codehaus.groovy.control.customizers.ImportCustomizer;
|
||||
@ -42,16 +25,26 @@ public class ScriptShell {
|
||||
private final ScriptEngine engine;
|
||||
private final ScriptProvider scriptProvider;
|
||||
|
||||
public ScriptShell(CmdlineInterface cli, ArgumentBean args, AccessControlContext acc, ScriptProvider scriptProvider) throws ScriptException {
|
||||
public ScriptShell(ScriptProvider scriptProvider, Map<String, ?> globals) throws ScriptException {
|
||||
this.engine = createScriptEngine();
|
||||
this.scriptProvider = scriptProvider;
|
||||
|
||||
// setup bindings
|
||||
Bindings bindings = engine.createBindings();
|
||||
bindings.putAll(globals);
|
||||
|
||||
// bind API objects
|
||||
// TODO remove
|
||||
bindings.put("_cli", new CmdlineOperations());
|
||||
bindings.put("_shell", this);
|
||||
|
||||
// setup script context
|
||||
ScriptContext context = new SimpleScriptContext();
|
||||
context.setBindings(initializeBindings(cli, args, acc), ScriptContext.GLOBAL_SCOPE);
|
||||
context.setBindings(bindings, ScriptContext.GLOBAL_SCOPE);
|
||||
engine.setContext(context);
|
||||
|
||||
// import additional functions into the shell environment
|
||||
// TODO remove
|
||||
engine.eval(new InputStreamReader(ExpressionFormat.class.getResourceAsStream("ExpressionFormat.lib.groovy")));
|
||||
engine.eval(new InputStreamReader(ScriptShell.class.getResourceAsStream("ScriptShell.lib.groovy")));
|
||||
}
|
||||
@ -74,22 +67,22 @@ public class ScriptShell {
|
||||
return new GroovyScriptEngineImpl(classLoader);
|
||||
}
|
||||
|
||||
public Object evaluate(final String script, final Bindings bindings) throws Throwable {
|
||||
try {
|
||||
return engine.eval(script, bindings);
|
||||
} catch (Throwable e) {
|
||||
while (e.getClass() == ScriptException.class && e.getCause() != null) {
|
||||
e = e.getCause();
|
||||
}
|
||||
throw StackTraceUtils.deepSanitize(e); // make Groovy stacktrace human-readable
|
||||
}
|
||||
}
|
||||
|
||||
public static interface ScriptProvider {
|
||||
|
||||
public URI getScriptLocation(String input) throws Exception;
|
||||
|
||||
public Script fetchScript(URI uri) throws Exception;
|
||||
}
|
||||
|
||||
public static class Script {
|
||||
|
||||
public final String code;
|
||||
public final boolean trusted;
|
||||
|
||||
public Script(String code, boolean trusted) {
|
||||
this.code = code;
|
||||
this.trusted = trusted;
|
||||
}
|
||||
public String fetchScript(URI uri) throws Exception;
|
||||
}
|
||||
|
||||
public Object runScript(String input, Bindings bindings) throws Throwable {
|
||||
@ -97,90 +90,7 @@ public class ScriptShell {
|
||||
}
|
||||
|
||||
public Object runScript(URI resource, Bindings bindings) throws Throwable {
|
||||
Script script = scriptProvider.fetchScript(resource);
|
||||
return evaluate(script.code, bindings, script.trusted);
|
||||
}
|
||||
|
||||
public Object evaluate(final String script, final Bindings bindings, boolean trustScript) throws Throwable {
|
||||
try {
|
||||
if (trustScript) {
|
||||
return engine.eval(script, bindings);
|
||||
}
|
||||
|
||||
try {
|
||||
return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
|
||||
|
||||
@Override
|
||||
public Object run() throws ScriptException {
|
||||
return engine.eval(script, bindings);
|
||||
}
|
||||
}, getSandboxAccessControlContext());
|
||||
} catch (PrivilegedActionException e) {
|
||||
throw e.getException();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
while (e.getClass() == ScriptException.class && e.getCause() != null) {
|
||||
e = e.getCause();
|
||||
}
|
||||
throw StackTraceUtils.deepSanitize(e); // make Groovy stack human-readable
|
||||
}
|
||||
}
|
||||
|
||||
protected Bindings initializeBindings(CmdlineInterface cli, ArgumentBean args, AccessControlContext acc) {
|
||||
Bindings bindings = new SimpleBindings();
|
||||
|
||||
// bind external parameters
|
||||
if (args.bindings != null) {
|
||||
for (Entry<String, String> it : args.bindings.entrySet()) {
|
||||
bindings.put(it.getKey(), it.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
// bind API objects
|
||||
bindings.put("_cli", PrivilegedInvocation.newProxy(CmdlineInterface.class, cli, acc));
|
||||
bindings.put("_script", args.script);
|
||||
bindings.put("_args", args);
|
||||
bindings.put("_shell", this);
|
||||
|
||||
Map<String, String> defines = new LinkedHashMap<String, String>();
|
||||
if (args.bindings != null) {
|
||||
for (Entry<String, String> it : args.bindings.entrySet()) {
|
||||
defines.put(it.getKey(), it.getValue());
|
||||
}
|
||||
}
|
||||
bindings.put("_def", defines);
|
||||
|
||||
return bindings;
|
||||
}
|
||||
|
||||
protected AccessControlContext getSandboxAccessControlContext() {
|
||||
Permissions permissions = new Permissions();
|
||||
|
||||
permissions.add(new RuntimePermission("createClassLoader"));
|
||||
permissions.add(new RuntimePermission("accessClassInPackage.*"));
|
||||
permissions.add(new RuntimePermission("modifyThread"));
|
||||
permissions.add(new FilePermission("<<ALL FILES>>", "read"));
|
||||
permissions.add(new SocketPermission("*", "connect"));
|
||||
permissions.add(new PropertyPermission("*", "read"));
|
||||
permissions.add(new RuntimePermission("getenv.*"));
|
||||
permissions.add(new RuntimePermission("getFileSystemAttributes"));
|
||||
permissions.add(new ManagementPermission("monitor"));
|
||||
|
||||
// write permissions for temp and cache folders
|
||||
permissions.add(new FilePermission(new File(System.getProperty("ehcache.disk.store.dir")).getAbsolutePath() + File.separator + "-", "write, delete"));
|
||||
permissions.add(new FilePermission(new File(System.getProperty("java.io.tmpdir")).getAbsolutePath() + File.separator + "-", "write, delete"));
|
||||
|
||||
// AWT / Swing permissions
|
||||
permissions.add(new AWTPermission("accessEventQueue"));
|
||||
permissions.add(new AWTPermission("toolkitModality"));
|
||||
permissions.add(new AWTPermission("showWindowWithoutWarningBanner"));
|
||||
|
||||
// this is probably a security problem but nevermind
|
||||
permissions.add(new RuntimePermission("accessDeclaredMembers"));
|
||||
permissions.add(new ReflectPermission("suppressAccessChecks"));
|
||||
permissions.add(new RuntimePermission("modifyThread"));
|
||||
|
||||
return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, permissions) });
|
||||
return evaluate(scriptProvider.fetchScript(resource), bindings);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
scriptBaseClass: net.sourceforge.filebot.cli.ScriptShellBaseClass
|
||||
starImport: net.sourceforge.filebot, net.sourceforge.filebot.util, net.sourceforge.filebot.web, net.sourceforge.filebot.media, net.sourceforge.filebot.mediainfo, net.sourceforge.filebot.hash, net.sourceforge.filebot.similarity, groovy.io, groovy.xml, groovy.json, org.jsoup, java.nio.file, java.nio.file.attribute, java.util.regex
|
||||
starImport: net.sourceforge.filebot, net.sourceforge.filebot.hash, net.sourceforge.filebot.media, net.sourceforge.filebot.mediainfo, net.sourceforge.filebot.similarity, net.sourceforge.filebot.subtitle, net.sourceforge.filebot.torrent, net.sourceforge.filebot.web, net.sourceforge.filebot.util, groovy.io, groovy.xml, groovy.json, org.jsoup, java.nio.file, java.nio.file.attribute, java.util.regex
|
||||
starStaticImport: net.sourceforge.filebot.WebServices, net.sourceforge.filebot.media.MediaDetection, java.nio.file.Files
|
@ -1,10 +1,12 @@
|
||||
package net.sourceforge.filebot.cli;
|
||||
|
||||
import static net.sourceforge.filebot.Settings.*;
|
||||
import static net.sourceforge.filebot.cli.CLILogging.*;
|
||||
import groovy.lang.Closure;
|
||||
import groovy.lang.Script;
|
||||
|
||||
import java.io.Console;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.sourceforge.filebot.MediaTypes;
|
||||
@ -30,6 +32,16 @@ public abstract class ScriptShellBaseClass extends Script {
|
||||
return null;
|
||||
}
|
||||
|
||||
// define global variable: _args
|
||||
public ArgumentBean get_args() {
|
||||
return getApplicationArguments();
|
||||
}
|
||||
|
||||
// define global variable: _def
|
||||
public Map<String, String> get_def() {
|
||||
return getApplicationArguments().bindings;
|
||||
}
|
||||
|
||||
// define global variable: _system
|
||||
public AssociativeScriptObject get_system() {
|
||||
return new AssociativeScriptObject(System.getProperties());
|
||||
|
Loading…
Reference in New Issue
Block a user