From f28e41626ff941a684f428596d9a462876bf8f58 Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Mon, 27 Feb 2017 22:11:59 +0800 Subject: [PATCH] Refactor ExpressionFormat into generic ExpressionFormat (used by -mediainfo and -list calls) and ExpressionFileFormat (used when generating output paths) that performs all the file path validation logic (strip spaces, don't allow /\ in binding values, etc) --- source/net/filebot/cli/ArgumentBean.java | 5 +++ source/net/filebot/cli/ArgumentProcessor.java | 2 +- source/net/filebot/cli/CmdlineInterface.java | 3 +- source/net/filebot/cli/CmdlineOperations.java | 3 +- .../net/filebot/cli/ScriptShellBaseClass.java | 7 +--- .../filebot/format/ExpressionFileFormat.java | 42 +++++++++++++++++++ .../net/filebot/format/ExpressionFormat.java | 28 ++----------- .../ui/rename/ExpressionFormatter.java | 8 ++-- .../net/filebot/ui/rename/FormatDialog.java | 9 ++-- source/net/filebot/ui/rename/Preset.java | 5 ++- .../net/filebot/ui/rename/PresetEditor.java | 4 +- source/net/filebot/ui/rename/RenamePanel.java | 4 +- 12 files changed, 74 insertions(+), 46 deletions(-) create mode 100644 source/net/filebot/format/ExpressionFileFormat.java diff --git a/source/net/filebot/cli/ArgumentBean.java b/source/net/filebot/cli/ArgumentBean.java index b50b434b..6a50f702 100644 --- a/source/net/filebot/cli/ArgumentBean.java +++ b/source/net/filebot/cli/ArgumentBean.java @@ -31,6 +31,7 @@ import net.filebot.Language; import net.filebot.StandardRenameAction; import net.filebot.WebServices; import net.filebot.format.ExpressionFileFilter; +import net.filebot.format.ExpressionFileFormat; import net.filebot.format.ExpressionFilter; import net.filebot.format.ExpressionFormat; import net.filebot.hash.HashType; @@ -216,6 +217,10 @@ public class ArgumentBean { return format == null ? null : new ExpressionFormat(format); } + public ExpressionFileFormat getExpressionFileFormat() throws Exception { + return format == null ? null : new ExpressionFileFormat(format); + } + public ExpressionFilter getExpressionFilter() throws Exception { return filter == null ? null : new ExpressionFilter(filter); } diff --git a/source/net/filebot/cli/ArgumentProcessor.java b/source/net/filebot/cli/ArgumentProcessor.java index 9799a2a1..99f73b71 100644 --- a/source/net/filebot/cli/ArgumentProcessor.java +++ b/source/net/filebot/cli/ArgumentProcessor.java @@ -80,7 +80,7 @@ public class ArgumentProcessor { } if (args.rename) { - cli.rename(files, args.getRenameAction(), args.getConflictAction(), args.getAbsoluteOutputFolder(), args.getExpressionFormat(), args.getDatasource(), args.getSearchQuery(), args.getSortOrder(), args.getExpressionFilter(), args.getLanguage().getLocale(), args.isStrict()); + cli.rename(files, args.getRenameAction(), args.getConflictAction(), args.getAbsoluteOutputFolder(), args.getExpressionFileFormat(), args.getDatasource(), args.getSearchQuery(), args.getSortOrder(), args.getExpressionFilter(), args.getLanguage().getLocale(), args.isStrict()); } if (args.check) { diff --git a/source/net/filebot/cli/CmdlineInterface.java b/source/net/filebot/cli/CmdlineInterface.java index 4faca6cf..60acfbc3 100644 --- a/source/net/filebot/cli/CmdlineInterface.java +++ b/source/net/filebot/cli/CmdlineInterface.java @@ -11,6 +11,7 @@ import java.util.stream.Stream; import net.filebot.Language; import net.filebot.RenameAction; +import net.filebot.format.ExpressionFileFormat; import net.filebot.format.ExpressionFilter; import net.filebot.format.ExpressionFormat; import net.filebot.hash.HashType; @@ -22,7 +23,7 @@ import net.filebot.web.SortOrder; public interface CmdlineInterface { - List rename(Collection files, RenameAction action, ConflictAction conflict, File output, ExpressionFormat format, Datasource db, String query, SortOrder order, ExpressionFilter filter, Locale locale, boolean strict) throws Exception; + List rename(Collection files, RenameAction action, ConflictAction conflict, File output, ExpressionFileFormat format, Datasource db, String query, SortOrder order, ExpressionFilter filter, Locale locale, boolean strict) throws Exception; List rename(Map rename, RenameAction action, ConflictAction conflict) throws Exception; diff --git a/source/net/filebot/cli/CmdlineOperations.java b/source/net/filebot/cli/CmdlineOperations.java index 226ab081..ecb21109 100644 --- a/source/net/filebot/cli/CmdlineOperations.java +++ b/source/net/filebot/cli/CmdlineOperations.java @@ -44,6 +44,7 @@ import net.filebot.RenameAction; import net.filebot.StandardRenameAction; import net.filebot.archive.Archive; import net.filebot.archive.FileMapper; +import net.filebot.format.ExpressionFileFormat; import net.filebot.format.ExpressionFilter; import net.filebot.format.ExpressionFormat; import net.filebot.format.MediaBindingBean; @@ -85,7 +86,7 @@ import net.filebot.web.VideoHashSubtitleService; public class CmdlineOperations implements CmdlineInterface { @Override - public List rename(Collection files, RenameAction action, ConflictAction conflict, File output, ExpressionFormat format, Datasource db, String query, SortOrder order, ExpressionFilter filter, Locale locale, boolean strict) throws Exception { + public List rename(Collection files, RenameAction action, ConflictAction conflict, File output, ExpressionFileFormat format, Datasource db, String query, SortOrder order, ExpressionFilter filter, Locale locale, boolean strict) throws Exception { // movie mode if (db instanceof MovieIdentificationService) { return renameMovie(files, action, conflict, output, format, (MovieIdentificationService) db, query, filter, locale, strict); diff --git a/source/net/filebot/cli/ScriptShellBaseClass.java b/source/net/filebot/cli/ScriptShellBaseClass.java index 1c0b12a2..60dedf98 100644 --- a/source/net/filebot/cli/ScriptShellBaseClass.java +++ b/source/net/filebot/cli/ScriptShellBaseClass.java @@ -219,11 +219,8 @@ public abstract class ScriptShellBaseClass extends Script { public String getMediaInfo(File file, String format) throws Exception { ExpressionFormat formatter = new ExpressionFormat(format); - Object o = xattr.getMetaInfo(file); - File f = file.getCanonicalFile(); - try { - return formatter.format(new MediaBindingBean(o, f)); + return formatter.format(new MediaBindingBean(xattr.getMetaInfo(file), file)); } catch (SuppressedThrowables e) { debug.finest(format("%s => %s", format, e.getMessage())); } @@ -342,7 +339,7 @@ public abstract class ScriptShellBaseClass extends Script { try { if (files.size() > 0) { - return getCLI().rename(files, args.getRenameAction(), args.getConflictAction(), args.getAbsoluteOutputFolder(), args.getExpressionFormat(), args.getDatasource(), args.getSearchQuery(), args.getSortOrder(), args.getExpressionFilter(), args.getLanguage().getLocale(), args.isStrict()); + return getCLI().rename(files, args.getRenameAction(), args.getConflictAction(), args.getAbsoluteOutputFolder(), args.getExpressionFileFormat(), args.getDatasource(), args.getSearchQuery(), args.getSortOrder(), args.getExpressionFilter(), args.getLanguage().getLocale(), args.isStrict()); } if (map.size() > 0) { diff --git a/source/net/filebot/format/ExpressionFileFormat.java b/source/net/filebot/format/ExpressionFileFormat.java new file mode 100644 index 00000000..9e78b495 --- /dev/null +++ b/source/net/filebot/format/ExpressionFileFormat.java @@ -0,0 +1,42 @@ +package net.filebot.format; + +import static net.filebot.similarity.Normalization.*; +import static net.filebot.util.FileUtilities.*; + +import javax.script.Bindings; +import javax.script.ScriptException; + +public class ExpressionFileFormat extends ExpressionFormat { + + public ExpressionFileFormat(String expression) throws ScriptException { + super(expression); + } + + @Override + public Bindings getBindings(Object value) { + return new ExpressionBindings(value) { + + @Override + public Object get(Object key) { + return normalizeBindingValue(super.get(key)); + } + }; + } + + protected Object normalizeBindingValue(Object value) { + // if the binding value is a String, then remove illegal characters (that would insert accidental directory separators) + if (value instanceof CharSequence) { + return replacePathSeparators(value.toString(), " "); + } + + // if the binding value is an Object, just leave it + return value; + } + + @Override + protected String normalizeResult(CharSequence value) { + // normalize unicode space characters and remove newline characters + return normalizePathSeparators(replaceSpace(value, " ").trim()); + } + +} diff --git a/source/net/filebot/format/ExpressionFormat.java b/source/net/filebot/format/ExpressionFormat.java index f9d3f971..846ebe37 100644 --- a/source/net/filebot/format/ExpressionFormat.java +++ b/source/net/filebot/format/ExpressionFormat.java @@ -1,9 +1,6 @@ package net.filebot.format; -import static net.filebot.similarity.Normalization.*; import static net.filebot.util.ExceptionUtilities.*; -import static net.filebot.util.FileUtilities.*; -import static net.filebot.util.RegularExpressions.*; import java.security.AccessController; import java.text.FieldPosition; @@ -66,7 +63,7 @@ public class ExpressionFormat extends Format { if (c == open) { if (level == 0) { if (token.length() > 0) { - compilation.add(NEWLINE.matcher(token).replaceAll("")); + compilation.add(token.toString()); token.setLength(0); } } else { @@ -124,13 +121,7 @@ public class ExpressionFormat extends Format { } public Bindings getBindings(Object value) { - return new ExpressionBindings(value) { - - @Override - public Object get(Object key) { - return normalizeBindingValue(super.get(key)); - } - }; + return new ExpressionBindings(value); } @Override @@ -183,26 +174,15 @@ public class ExpressionFormat extends Format { } protected Object normalizeBindingValue(Object value) { - // if the binding value is a String, remove illegal characters - if (value instanceof CharSequence) { - return replacePathSeparators((CharSequence) value, " ").trim(); - } - - // if the binding value is an Object, just leave it return value; } protected CharSequence normalizeExpressionValue(Object value) { - if (value == null) { - return null; - } - - return normalizePathSeparators(value.toString()); + return value == null ? null : value.toString(); } protected String normalizeResult(CharSequence value) { - // normalize unicode space characters and remove newline characters - return replaceSpace(value, " ").trim(); + return value.toString(); } protected Throwable normalizeExpressionException(ScriptException exception) { diff --git a/source/net/filebot/ui/rename/ExpressionFormatter.java b/source/net/filebot/ui/rename/ExpressionFormatter.java index cd1faf12..0e463beb 100644 --- a/source/net/filebot/ui/rename/ExpressionFormatter.java +++ b/source/net/filebot/ui/rename/ExpressionFormatter.java @@ -12,14 +12,14 @@ import java.util.logging.Level; import javax.script.ScriptException; import net.filebot.ApplicationFolder; -import net.filebot.format.ExpressionFormat; +import net.filebot.format.ExpressionFileFormat; import net.filebot.format.MediaBindingBean; import net.filebot.similarity.Match; class ExpressionFormatter implements MatchFormatter { private final String expression; - private ExpressionFormat format; + private ExpressionFileFormat format; private Format preview; private Class target; @@ -34,7 +34,7 @@ class ExpressionFormatter implements MatchFormatter { this.target = target; } - public ExpressionFormatter(ExpressionFormat format, Format preview, Class target) { + public ExpressionFormatter(ExpressionFileFormat format, Format preview, Class target) { this(format.getExpression(), preview, target); // use compiled format expression right away @@ -60,7 +60,7 @@ class ExpressionFormatter implements MatchFormatter { public synchronized String format(Match match, boolean extension, Map context) throws ScriptException { // lazy initialize script engine if (format == null) { - format = new ExpressionFormat(expression); + format = new ExpressionFileFormat(expression); } // evaluate the expression using the given bindings diff --git a/source/net/filebot/ui/rename/FormatDialog.java b/source/net/filebot/ui/rename/FormatDialog.java index ce9e5083..df20cb5e 100644 --- a/source/net/filebot/ui/rename/FormatDialog.java +++ b/source/net/filebot/ui/rename/FormatDialog.java @@ -61,6 +61,7 @@ import net.filebot.ResourceManager; import net.filebot.Settings; import net.filebot.UserFiles; import net.filebot.format.BindingException; +import net.filebot.format.ExpressionFileFormat; import net.filebot.format.ExpressionFormat; import net.filebot.format.MediaBindingBean; import net.filebot.format.SuppressedThrowables; @@ -87,7 +88,7 @@ import net.miginfocom.swing.MigLayout; public class FormatDialog extends JDialog { private boolean submit = false; - private ExpressionFormat format; + private ExpressionFileFormat format; private Mode mode; private boolean locked = false; @@ -398,7 +399,7 @@ public class FormatDialog extends JDialog { // bind text to preview addPropertyChangeListener("sample", evt -> { newSwingWorker(() -> { - return new ExpressionFormat(format).format(sample); + return new ExpressionFileFormat(format).format(sample); }, s -> { formatExample.setText(s); }).execute(); @@ -449,7 +450,7 @@ public class FormatDialog extends JDialog { private void checkFormatInBackground() { try { // check syntax in foreground - ExpressionFormat format = new ExpressionFormat(editor.getText().trim()); + ExpressionFileFormat format = new ExpressionFileFormat(editor.getText().trim()); // activate delayed to avoid flickering when formatting takes only a couple of milliseconds Timer progressIndicatorTimer = invokeLater(400, () -> progressIndicator.setVisible(true)); @@ -666,7 +667,7 @@ public class FormatDialog extends JDialog { protected final Action approveFormatAction = newAction("Use Format", ResourceManager.getIcon("dialog.continue"), evt -> { try { // check syntax - format = new ExpressionFormat(editor.getText().trim()); + format = new ExpressionFileFormat(editor.getText().trim()); if (format.getExpression().isEmpty()) { throw new ScriptException("Expression is empty"); diff --git a/source/net/filebot/ui/rename/Preset.java b/source/net/filebot/ui/rename/Preset.java index d7cb28ba..a8f453c1 100644 --- a/source/net/filebot/ui/rename/Preset.java +++ b/source/net/filebot/ui/rename/Preset.java @@ -15,6 +15,7 @@ import net.filebot.CachedResource.Transform; import net.filebot.Language; import net.filebot.StandardRenameAction; import net.filebot.format.ExpressionFileFilter; +import net.filebot.format.ExpressionFileFormat; import net.filebot.format.ExpressionFilter; import net.filebot.format.ExpressionFormat; import net.filebot.media.XattrMetaInfoProvider; @@ -60,8 +61,8 @@ public class Preset { return getInputFolder() == null ? null : getValue(includes, expression -> new ExpressionFileFilter(expression)); } - public ExpressionFormat getFormat() { - return getValue(format, ExpressionFormat::new); + public ExpressionFileFormat getFormat() { + return getValue(format, ExpressionFileFormat::new); } public String getMatchMode() { diff --git a/source/net/filebot/ui/rename/PresetEditor.java b/source/net/filebot/ui/rename/PresetEditor.java index 6aea299f..11b5ef23 100644 --- a/source/net/filebot/ui/rename/PresetEditor.java +++ b/source/net/filebot/ui/rename/PresetEditor.java @@ -37,8 +37,8 @@ import net.filebot.ResourceManager; import net.filebot.StandardRenameAction; import net.filebot.UserFiles; import net.filebot.WebServices; +import net.filebot.format.ExpressionFileFormat; import net.filebot.format.ExpressionFilter; -import net.filebot.format.ExpressionFormat; import net.filebot.format.MediaBindingBean; import net.filebot.mac.MacAppUtilities; import net.filebot.ui.HeaderPanel; @@ -181,7 +181,7 @@ public class PresetEditor extends JDialog { String name = presetNameHeader.getTitleLabel().getText(); File path = inheritRadio.isSelected() ? null : new File(pathInput.getText()); ExpressionFilter includes = inheritRadio.isSelected() ? null : new ExpressionFilter(filterEditor.getText()); - ExpressionFormat format = formatEditor.getText().trim().isEmpty() ? null : new ExpressionFormat(formatEditor.getText()); + ExpressionFileFormat format = formatEditor.getText().trim().isEmpty() ? null : new ExpressionFileFormat(formatEditor.getText()); Datasource database = ((Datasource) providerCombo.getSelectedItem()); SortOrder sortOrder = sortOrderCombo.isEnabled() ? ((SortOrder) sortOrderCombo.getSelectedItem()) : null; String matchMode = matchModeCombo.isEnabled() ? (String) matchModeCombo.getSelectedItem() : null; diff --git a/source/net/filebot/ui/rename/RenamePanel.java b/source/net/filebot/ui/rename/RenamePanel.java index 6fd80fa8..39c1a235 100644 --- a/source/net/filebot/ui/rename/RenamePanel.java +++ b/source/net/filebot/ui/rename/RenamePanel.java @@ -64,7 +64,7 @@ import net.filebot.Settings; import net.filebot.StandardRenameAction; import net.filebot.UserFiles; import net.filebot.WebServices; -import net.filebot.format.ExpressionFormat; +import net.filebot.format.ExpressionFileFormat; import net.filebot.format.MediaBindingBean; import net.filebot.mac.MacAppUtilities; import net.filebot.media.MetaAttributes; @@ -741,7 +741,7 @@ public class RenamePanel extends JComponent { @Override public void actionPerformed(ActionEvent evt) { SwingWorker worker = newSwingWorker(() -> { - ExpressionFormat format = preset.getFormat(); + ExpressionFileFormat format = preset.getFormat(); if (format != null && preset.getDatasource() != null) { switch (Mode.getMode(preset.getDatasource())) {