diff --git a/source/net/filebot/format/ExpressionFormat.java b/source/net/filebot/format/ExpressionFormat.java index 5b55df50..b81ef1f1 100644 --- a/source/net/filebot/format/ExpressionFormat.java +++ b/source/net/filebot/format/ExpressionFormat.java @@ -13,7 +13,9 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ExecutionException; +import javax.lang.model.SourceVersion; import javax.script.Bindings; import javax.script.Compilable; import javax.script.CompiledScript; @@ -33,38 +35,6 @@ import groovy.lang.MissingPropertyException; public class ExpressionFormat extends Format { - private static ScriptEngine engine; - private static Map scriptletCache = new HashMap(); - - protected static ScriptEngine createScriptEngine() { - CompilerConfiguration config = new CompilerConfiguration(); - - // include default functions - ImportCustomizer imports = new ImportCustomizer(); - imports.addStaticStars(ExpressionFormatFunctions.class.getName()); - config.addCompilationCustomizers(imports); - - GroovyClassLoader classLoader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader(), config); - return new GroovyScriptEngineImpl(classLoader); - } - - protected static synchronized ScriptEngine getGroovyScriptEngine() throws ScriptException { - if (engine == null) { - engine = createScriptEngine(); - } - return engine; - } - - protected static synchronized CompiledScript compileScriptlet(String expression) throws ScriptException { - Compilable engine = (Compilable) getGroovyScriptEngine(); - CompiledScript scriptlet = scriptletCache.get(expression); - if (scriptlet == null) { - scriptlet = engine.compile(expression); - scriptletCache.put(expression, scriptlet); - } - return scriptlet; - } - private final String expression; private final Object[] compilation; @@ -230,21 +200,87 @@ public class ExpressionFormat extends Format { return lastException; } + @Override + public Object parseObject(String source, ParsePosition pos) { + throw new UnsupportedOperationException(); + } + private Object[] secure(Object[] compilation) { for (int i = 0; i < compilation.length; i++) { - Object snipped = compilation[i]; + Object snippet = compilation[i]; - if (snipped instanceof CompiledScript) { - compilation[i] = new SecureCompiledScript((CompiledScript) snipped); + // simple expressions like {n} can't contain any malicious code + if (snippet instanceof Variable) { + continue; + } + + if (snippet instanceof CompiledScript) { + compilation[i] = new SecureCompiledScript((CompiledScript) snippet); } } return compilation; } - @Override - public Object parseObject(String source, ParsePosition pos) { - throw new UnsupportedOperationException(); + private static ScriptEngine engine; + private static Map scriptletCache = new HashMap(); + + protected static ScriptEngine createScriptEngine() { + CompilerConfiguration config = new CompilerConfiguration(); + + // include default functions + ImportCustomizer imports = new ImportCustomizer(); + imports.addStaticStars(ExpressionFormatFunctions.class.getName()); + config.addCompilationCustomizers(imports); + + GroovyClassLoader classLoader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader(), config); + return new GroovyScriptEngineImpl(classLoader); + } + + protected static synchronized ScriptEngine getGroovyScriptEngine() throws ScriptException { + if (engine == null) { + engine = createScriptEngine(); + } + return engine; + } + + protected static synchronized CompiledScript compileScriptlet(String expression) throws ScriptException { + // simple expressions like {n} don't need to be interpreted by the script engine + if (SourceVersion.isIdentifier(expression)) { + return new Variable(expression); + } + + CompiledScript scriptlet = scriptletCache.get(expression); + if (scriptlet == null) { + Compilable engine = (Compilable) getGroovyScriptEngine(); + scriptlet = engine.compile(expression); + scriptletCache.put(expression, scriptlet); + } + return scriptlet; + } + + private static class Variable extends CompiledScript { + + private String name; + + public Variable(String name) { + this.name = name; + } + + @Override + public Object eval(ScriptContext context) throws ScriptException { + try { + return context.getAttribute(name); + } catch (Throwable t) { + throw new ScriptException(new ExecutionException(t)); + } + } + + @Override + public ScriptEngine getEngine() { + return null; + } + } }