diff --git a/source/net/sourceforge/filebot/cli/CmdlineOperations.java b/source/net/sourceforge/filebot/cli/CmdlineOperations.java index 205ff090..36c11f51 100644 --- a/source/net/sourceforge/filebot/cli/CmdlineOperations.java +++ b/source/net/sourceforge/filebot/cli/CmdlineOperations.java @@ -170,24 +170,26 @@ public class CmdlineOperations implements CmdlineInterface { // fetch episode data Set episodes = fetchEpisodeSet(db, seriesNames, sortOrder, locale, strict); + if (episodes.size() == 0) { + CLILogger.warning("Failed to fetch episode data: " + seriesNames); + continue; + } + // filter episodes if (filter != null) { CLILogger.fine(String.format("Apply Filter: {%s}", filter.getExpression())); for (Iterator itr = episodes.iterator(); itr.hasNext();) { Episode episode = itr.next(); if (filter.matches(new MediaBindingBean(episode, null))) { - CLILogger.finest(String.format("Exclude [%s]", episode)); + CLILogger.finest(String.format("Include [%s]", episode)); + } else { itr.remove(); } } } - if (episodes.size() > 0) { - matches.addAll(matchEpisodes(filter(batch, VIDEO_FILES), episodes, strict)); - matches.addAll(matchEpisodes(filter(batch, SUBTITLE_FILES), episodes, strict)); - } else { - CLILogger.warning("Failed to fetch episode data: " + seriesNames); - } + matches.addAll(matchEpisodes(filter(batch, VIDEO_FILES), episodes, strict)); + matches.addAll(matchEpisodes(filter(batch, SUBTITLE_FILES), episodes, strict)); } } diff --git a/source/net/sourceforge/filebot/format/ExpressionFilter.java b/source/net/sourceforge/filebot/format/ExpressionFilter.java index c4e46bed..0faa42a4 100644 --- a/source/net/sourceforge/filebot/format/ExpressionFilter.java +++ b/source/net/sourceforge/filebot/format/ExpressionFilter.java @@ -11,6 +11,7 @@ import javax.script.CompiledScript; import javax.script.ScriptContext; import javax.script.ScriptEngine; import javax.script.ScriptException; +import javax.script.SimpleBindings; import javax.script.SimpleScriptContext; import org.codehaus.groovy.jsr223.GroovyScriptEngineFactory; @@ -20,12 +21,18 @@ public class ExpressionFilter { private final String expression; - private final CompiledScript script; + private final CompiledScript userScript; + private final CompiledScript asBooleanScript; + + private Throwable lastException; public ExpressionFilter(String expression) throws ScriptException { this.expression = expression; - this.script = new SecureCompiledScript(((Compilable) initScriptEngine()).compile(expression)); // sandboxed script + + Compilable engine = (Compilable) initScriptEngine(); + this.userScript = new SecureCompiledScript(engine.compile(expression)); // sandboxed script + this.asBooleanScript = engine.compile("value as Boolean"); } @@ -34,6 +41,11 @@ public class ExpressionFilter { } + public Throwable getLastException() { + return lastException; + } + + protected ScriptEngine initScriptEngine() throws ScriptException { // use Groovy script engine ScriptEngine engine = new GroovyScriptEngineFactory().getScriptEngine(); @@ -48,6 +60,8 @@ public class ExpressionFilter { public boolean matches(Bindings bindings) throws ScriptException { + this.lastException = null; + // use privileged bindings so we are not restricted by the script sandbox Bindings priviledgedBindings = PrivilegedInvocation.newProxy(Bindings.class, bindings, AccessController.getContext()); @@ -56,12 +70,19 @@ public class ExpressionFilter { context.setBindings(priviledgedBindings, ScriptContext.GLOBAL_SCOPE); try { - Object value = script.eval(context); - if (value instanceof Boolean) { - return (Boolean) value; + // evaluate user script + Object value = userScript.eval(context); + + // convert value to boolean + Bindings valueBinding = new SimpleBindings(); + valueBinding.put("value", value); + Object result = asBooleanScript.eval(valueBinding); + if (result instanceof Boolean) { + return (Boolean) result; } } catch (Throwable e) { // ignore any and all scripting exceptions + this.lastException = e; } return false; diff --git a/website/cli.html b/website/cli.html index db7cafad..d0f69a11 100644 --- a/website/cli.html +++ b/website/cli.html @@ -198,6 +198,11 @@ conflict resolution override | skip | fail + + --filter + episode include rules + filter expression (e.g. "y > 2000") + -get-subtitles fetch subtitles @@ -234,7 +239,7 @@ -check - create/check verification file + create/check sfv file folder or sfv file