From 68a4ec52a92659ae6cebe4f04eb082a13dcc1bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sat, 10 Dec 2022 14:50:14 +0100 Subject: [PATCH] Added #1181 Remembering choice of loading assets via importassets tag --- CHANGELOG.md | 2 + .../CustomConfigurationKeys.java | 1 + src/com/jpexs/decompiler/flash/gui/Main.java | 148 +++++++++++++----- .../decompiler/flash/gui/MainFrameMenu.java | 2 +- .../decompiler/flash/gui/MainFrameRibbon.java | 2 +- .../jpexs/decompiler/flash/gui/MainPanel.java | 46 +++--- 6 files changed, 138 insertions(+), 63 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fbe41bb0..94960a37c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file. - Option to mute frame sounds - Experimental option to fix conflation artifacts in antialising (slow) - Option to disable autoplay of sounds (DefineSound) +- [#1181] Remembering choice of loading assets via importassets tag ### Fixed - [#1897] Close menu button without selecting specific item @@ -2724,6 +2725,7 @@ All notable changes to this project will be documented in this file. [#1676]: https://www.free-decompiler.com/flash/issues/1676 [#1697]: https://www.free-decompiler.com/flash/issues/1697 [#1893]: https://www.free-decompiler.com/flash/issues/1893 +[#1181]: https://www.free-decompiler.com/flash/issues/1181 [#1897]: https://www.free-decompiler.com/flash/issues/1897 [#1006]: https://www.free-decompiler.com/flash/issues/1006 [#1888]: https://www.free-decompiler.com/flash/issues/1888 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/CustomConfigurationKeys.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/CustomConfigurationKeys.java index ad454f502..78c40211a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/CustomConfigurationKeys.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/CustomConfigurationKeys.java @@ -9,4 +9,5 @@ public class CustomConfigurationKeys { public static final String KEY_LAST_SELECTED_PATH_TAGLIST = "lastSelectedPath.taglist"; public static final String KEY_CHARSET = "charset"; public static final String KEY_LIBRARY = "library"; + public static final String KEY_LOADED_IMPORT_ASSETS = "loadedImportAssets"; } diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index cfe06a3b1..e45341ddb 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -134,6 +134,7 @@ import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.Logger; import java.util.logging.SimpleFormatter; +import java.util.regex.Pattern; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; @@ -150,6 +151,8 @@ import org.pushingpixels.substance.api.SubstanceLookAndFeel; */ public class Main { + public static final String IMPORT_ASSETS_SEPARATOR = "{*sep*}"; + protected static ProxyFrame proxyFrame; private static List sourceInfos = new ArrayList<>(); @@ -212,8 +215,6 @@ public class Main { public static CancellableWorker deobfuscatePCodeWorker = null; public static CancellableWorker swfPrepareWorker = null; - - public static boolean isSwfAir(Openable openable) { SwfSpecificCustomConfiguration conf = Configuration.getSwfSpecificCustomConfiguration(openable.getShortPathTitle()); if (conf != null) { @@ -999,6 +1000,24 @@ public class Main { String fileKey = shortName == null ? "" : new File(shortName).getName(); SwfSpecificCustomConfiguration conf = Configuration.getSwfSpecificCustomConfiguration(fileKey); String charset = conf == null ? Charset.defaultCharset().name() : conf.getCustomData(CustomConfigurationKeys.KEY_CHARSET, Charset.defaultCharset().name()); + List loadedUrls = new ArrayList<>(); + List loadedStatus = new ArrayList<>(); + + Map configuredImportAssets = new HashMap<>(); + if (conf != null) { + String impAssetsStr = conf.getCustomData(CustomConfigurationKeys.KEY_LOADED_IMPORT_ASSETS, ""); + if (impAssetsStr != null && !impAssetsStr.isEmpty()) { + String[] parts = (impAssetsStr + IMPORT_ASSETS_SEPARATOR).split(Pattern.quote(IMPORT_ASSETS_SEPARATOR)); + for (String s : parts) { + if (!s.isEmpty()) { + String urlPlusStatus[] = (s + "|").split(Pattern.quote("|")); + String url = urlPlusStatus[0]; + String status = urlPlusStatus[1]; + configuredImportAssets.put(url, status); + } + } + } + } SWF swf = new SWF(is, file, fileTitle, new ProgressListener() { @Override @@ -1008,50 +1027,75 @@ public class Main { }, Configuration.parallelSpeedUp.get(), false, true, new UrlResolver() { @Override public SWF resolveUrl(final String url) { + loadedUrls.add(url); + File selFile = null; int opt = -1; - if (!(yestoall || notoall)) { - opt = ViewMessages.showOptionDialog(getDefaultMessagesComponent(), AppStrings.translate("message.imported.swf").replace("%url%", url), AppStrings.translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, yesno, AppStrings.translate("button.yes")); - if (opt == 2) { - yestoall = true; + + if (configuredImportAssets.containsKey(url)) { + String statusStr = configuredImportAssets.get(url); + if (statusStr.equals("NO")) { + loadedStatus.add("NO"); + return null; } - if (opt == 3) { - notoall = true; + if (statusStr.startsWith("CUSTOM:")) { + selFile = new File(statusStr.substring("CUSTOM:".length())); + } + } else { + if (!(yestoall || notoall)) { + opt = ViewMessages.showOptionDialog(getDefaultMessagesComponent(), AppStrings.translate("message.imported.swf").replace("%url%", url), AppStrings.translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, yesno, AppStrings.translate("button.yes")); + if (opt == 2) { + yestoall = true; + } + if (opt == 3) { + notoall = true; + } + } + + if (yestoall) { + opt = 0; // yes + } else if (notoall) { + opt = 1; // no + } + + if (opt == 1) //no + { + loadedStatus.add("NO"); + return null; } } - if (yestoall) { - opt = 0; // yes - } else if (notoall) { - opt = 1; // no - } - - if (opt == 1) //no - { - return null; - } - - if (url.startsWith("http://") || url.startsWith("https://")) { + if (selFile == null && (url.startsWith("http://") || url.startsWith("https://"))) { try { URL u = new URL(url); - return open(u.openStream(), null, url); //? + SWF ret = open(u.openStream(), null, url); //? + loadedStatus.add("YES"); + return ret; } catch (Exception ex) { //ignore } } else { - File swf = new File(new File(file).getParentFile(), url); + File swf = selFile != null ? selFile : new File(new File(file).getParentFile(), url); if (swf.exists()) { try { - return open(new FileInputStream(swf), swf.getAbsolutePath(), swf.getName()); + SWF ret = open(new FileInputStream(swf), swf.getAbsolutePath(), swf.getName()); + if (selFile != null) { + loadedStatus.add("CUSTOM:" + selFile.getAbsolutePath()); + } else { + loadedStatus.add("YES"); + } + return ret; } catch (Exception ex) { //ignore } } // try .gfx if .swf failed - if (url.endsWith(".swf")) { + if (selFile == null && url.endsWith(".swf")) { File gfx = new File(new File(file).getParentFile(), url.substring(0, url.length() - 4) + ".gfx"); if (gfx.exists()) { try { - return open(new FileInputStream(gfx), gfx.getAbsolutePath(), gfx.getName()); + SWF ret = open(new FileInputStream(gfx), gfx.getAbsolutePath(), gfx.getName()); + loadedStatus.add("YES"); + return ret; } catch (Exception ex) { //ignore } @@ -1120,11 +1164,13 @@ public class Main { File selFile = Helper.fixDialogFile(fc.getSelectedFile()); try { ret.setVal(open(new FileInputStream(selFile), selFile.getAbsolutePath(), selFile.getName())); + loadedStatus.add("CUSTOM:" + selFile.getAbsolutePath()); break; - } catch (Exception ex) { + } catch (Exception ex) { //ignore; } } else { + loadedStatus.add("NO"); break; } } @@ -1133,6 +1179,21 @@ public class Main { return ret.getVal(); } }, charset); + + if (!loadedUrls.isEmpty()) { + SwfSpecificCustomConfiguration cc2 = Configuration.getOrCreateSwfSpecificCustomConfiguration(swf.getShortPathTitle()); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < loadedUrls.size(); i++) { + if (i > 0) { + sb.append(IMPORT_ASSETS_SEPARATOR); + } + sb.append(loadedUrls.get(i)); + sb.append("|"); + sb.append(loadedStatus.get(i)); + } + cc2.setCustomData(CustomConfigurationKeys.KEY_LOADED_IMPORT_ASSETS, sb.toString()); + } + return swf; } @@ -1165,7 +1226,7 @@ public class Main { } result.sourceInfo = sourceInfo; - + boolean hasVideoStreams = false; for (Openable openable : result) { @@ -1181,13 +1242,13 @@ public class Main { int height = (int) ((swf.displayRect.Ymax - swf.displayRect.Ymin) / SWF.unitDivisor); logger.log(Level.INFO, "Width: {0}", width); logger.log(Level.INFO, "Height: {0}", height); - - for (Tag t: swf.getTags()) { + + for (Tag t : swf.getTags()) { if (t instanceof DefineVideoStreamTag) { hasVideoStreams = true; } } - + swf.addEventListener(new EventListener() { @Override public void handleExportingEvent(String type, int index, int count, Object data) { @@ -1233,14 +1294,14 @@ public class Main { }); } } - + if (hasVideoStreams && !DefineVideoStreamTag.displayAvailable()) { View.execInEventDispatchLater(new Runnable() { @Override public void run() { - ViewMessages.showMessageDialog(getDefaultMessagesComponent(), AppStrings.translate("message.video.installvlc").replace("%file%", sourceInfo.getFileTitleOrName()), AppStrings.translate("message.warning"), JOptionPane.WARNING_MESSAGE, Configuration.warningVideoVlc); + ViewMessages.showMessageDialog(getDefaultMessagesComponent(), AppStrings.translate("message.video.installvlc").replace("%file%", sourceInfo.getFileTitleOrName()), AppStrings.translate("message.warning"), JOptionPane.WARNING_MESSAGE, Configuration.warningVideoVlc); } - + }); } @@ -1558,7 +1619,7 @@ public class Main { } if (mainFrame != null) { mainFrame.setVisible(false); - mainFrame.getPanel().closeAll(false); + mainFrame.getPanel().closeAll(false, false); mainFrame.dispose(); mainFrame = null; } @@ -1630,7 +1691,7 @@ public class Main { if (newFileDialog.showDialog() == AppDialog.OK_OPTION) { if (mainFrame != null && !Configuration.openMultipleFiles.get()) { sourceInfos.clear(); - mainFrame.getPanel().closeAll(false); + mainFrame.getPanel().closeAll(false, false); mainFrame.setVisible(false); Helper.freeMem(); } @@ -1684,7 +1745,7 @@ public class Main { if (mainFrame != null && !Configuration.openMultipleFiles.get()) { sourceInfos.clear(); - mainFrame.getPanel().closeAll(false); + mainFrame.getPanel().closeAll(false, false); mainFrame.setVisible(false); Helper.freeMem(); reloadIndices = null; @@ -1736,6 +1797,13 @@ public class Main { public static void reloadFile(OpenableList swf) { View.checkAccess(); + for (Openable o : swf.items) { + SwfSpecificCustomConfiguration cc = Configuration.getSwfSpecificCustomConfiguration(o.getShortPathTitle()); + if (cc != null) { + cc.setCustomData(CustomConfigurationKeys.KEY_LOADED_IMPORT_ASSETS, ""); + } + } + openFile(swf.sourceInfo, null, sourceInfos.indexOf(swf.sourceInfo)); } @@ -1751,10 +1819,10 @@ public class Main { } } - public static boolean closeAll() { + public static boolean closeAll(boolean onExit) { View.checkAccess(); - boolean closeResult = mainFrame.getPanel().closeAll(true); + boolean closeResult = mainFrame.getPanel().closeAll(true, onExit); if (closeResult) { sourceInfos.clear(); System.gc(); @@ -2090,8 +2158,6 @@ public class Main { return null; } - - private static void initGui() { if (GraphicsEnvironment.isHeadless()) { System.err.println("Error: Your system does not support Graphic User Interface"); @@ -2100,7 +2166,7 @@ public class Main { System.setProperty("sun.java2d.d3d", "false"); System.setProperty("sun.java2d.noddraw", "true"); - + if (System.getProperty("sun.java2d.uiScale") == null) { //it was not set by commandline, etc. System.setProperty("sun.java2d.uiScale", "" + Configuration.uiScale.get()); } diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java index b0fe06506..cb57b765e 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java @@ -308,7 +308,7 @@ public abstract class MainFrameMenu implements MenuBuilder { } if (openable != null) { - boolean result = Main.closeAll(); + boolean result = Main.closeAll(false); if (result) { openable = null; Timer timer = new Timer(); diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbon.java b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbon.java index 767a4365d..b567d1759 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbon.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbon.java @@ -157,7 +157,7 @@ public final class MainFrameRibbon extends AppRibbonFrame { } - boolean closeResult = panel.closeAll(true); + boolean closeResult = panel.closeAll(true, true); if (closeResult) { Main.exit(); } diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index d58c523f1..f041a166e 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -322,7 +322,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se private final JPanel displayPanel; public FolderPreviewPanel folderPreviewPanel; - + public FolderListPanel folderListPanel; private boolean isWelcomeScreen = true; @@ -330,9 +330,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se private static final String CARDPREVIEWPANEL = "Preview card"; private static final String CARDFOLDERPREVIEWPANEL = "Folder preview card"; - - private static final String CARDFOLDERLISTPANEL = "Folder list card"; + private static final String CARDFOLDERLISTPANEL = "Folder list card"; private static final String CARDEMPTYPANEL = "Empty card"; @@ -672,8 +671,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se public boolean isClipboardCut() { return clipboardCut; - } - + } + public boolean checkEdited() { if (abcPanel != null && abcPanel.isEditing()) { abcPanel.tryAutoSave(); @@ -698,8 +697,6 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se private class MyTreeSelectionModel extends DefaultTreeSelectionModel { - - @Override public void addSelectionPath(TreePath path) { if (checkEdited()) { @@ -885,7 +882,6 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se return folderListCard; } - private JPanel createDumpPreviewCard() { JPanel dumpViewCard = new JPanel(new BorderLayout()); dumpViewPanel = new DumpViewPanel(dumpTree); @@ -1416,7 +1412,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se return false; } - public boolean closeAll(boolean showCloseConfirmation) { + public boolean closeAll(boolean showCloseConfirmation, boolean onExit) { View.checkAccess(); if (showCloseConfirmation && isModified()) { @@ -1456,6 +1452,12 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se for (SWF swf : swfsToClose) { swf.clearTagSwfs(); + if (!onExit) { + SwfSpecificCustomConfiguration cc = Configuration.getSwfSpecificCustomConfiguration(swf.getShortPathTitle()); + if (cc != null) { + cc.setCustomData(CustomConfigurationKeys.KEY_LOADED_IMPORT_ASSETS, ""); + } + } } refreshTree(); @@ -1510,6 +1512,10 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se for (SWF swf : swfsToClose) { Main.searchResultsStorage.destroySwf(swf); pinsPanel.removeOpenable(swf); + SwfSpecificCustomConfiguration cc = Configuration.getSwfSpecificCustomConfiguration(swf.getShortPathTitle()); + if (cc != null) { + cc.setCustomData(CustomConfigurationKeys.KEY_LOADED_IMPORT_ASSETS, ""); + } } openables.remove(openableList); @@ -1924,7 +1930,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se ScriptExportSettings scriptExportSettings = new ScriptExportSettings(export.getValue(ScriptExportMode.class), singleScriptFile, false); String singleFileName = Path.combine(scriptsFolder, openable.getShortFileName() + scriptExportSettings.getFileExtension()); - try (FileTextWriter writer = scriptExportSettings.singleFile ? new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(singleFileName)) : null) { + try ( FileTextWriter writer = scriptExportSettings.singleFile ? new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(singleFileName)) : null) { scriptExportSettings.singleFileWriter = writer; if (swf.isAS3()) { ret.addAll(new AS3ScriptExporter().exportActionScript3(swf, handler, scriptsFolder, as3scripts, scriptExportSettings, parallel, evl)); @@ -2031,7 +2037,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se ScriptExportSettings scriptExportSettings = new ScriptExportSettings(export.getValue(ScriptExportMode.class), singleScriptFile, false); String singleFileName = Path.combine(scriptsFolder, swf.getShortFileName() + scriptExportSettings.getFileExtension()); - try (FileTextWriter writer = scriptExportSettings.singleFile ? new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(singleFileName)) : null) { + try ( FileTextWriter writer = scriptExportSettings.singleFile ? new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(singleFileName)) : null) { scriptExportSettings.singleFileWriter = writer; swf.exportActionScript(handler, scriptsFolder, scriptExportSettings, parallel, evl); } @@ -2148,7 +2154,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se ScriptExportSettings scriptExportSettings = new ScriptExportSettings(exportMode, singleScriptFile, false); String singleFileName = Path.combine(scriptsFolder, swf.getShortFileName() + scriptExportSettings.getFileExtension()); - try (FileTextWriter writer = scriptExportSettings.singleFile ? new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(singleFileName)) : null) { + try ( FileTextWriter writer = scriptExportSettings.singleFile ? new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(singleFileName)) : null) { scriptExportSettings.singleFileWriter = writer; swf.exportActionScript(handler, scriptsFolder, scriptExportSettings, parallel, evl); } @@ -3552,7 +3558,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (selectedFile != null) { File selfile = Helper.fixDialogFile(selectedFile); try { - try (FileInputStream fis = new FileInputStream(selfile)) { + try ( FileInputStream fis = new FileInputStream(selfile)) { new SwfXmlImporter().importSwf(swf, fis); } swf.clearAllCache(); @@ -4625,9 +4631,9 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se return; } boolean internalViewer = !isAdobeFlashPlayerEnabled(); - - boolean isVideoButNotDrawable = (treeItem instanceof DefineVideoStreamTag) && (!DefineVideoStreamTag.displayAvailable()); - + + boolean isVideoButNotDrawable = (treeItem instanceof DefineVideoStreamTag) && (!DefineVideoStreamTag.displayAvailable()); + if (treeItem instanceof SWF) { SWF swf = (SWF) treeItem; if (internalViewer) { @@ -4674,7 +4680,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (treeItem instanceof ShapeTag) { previewPanel.setImageReplaceButtonVisible(false, false, !((Tag) treeItem).isReadOnly(), false); } - previewPanel.showImagePanel(timelined, tag.getSwf(), -1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), treeItem instanceof ShapeTag, !Configuration.playFrameSounds.get(), (treeItem instanceof DefineSpriteTag)||(treeItem instanceof ButtonTag)); + previewPanel.showImagePanel(timelined, tag.getSwf(), -1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), treeItem instanceof ShapeTag, !Configuration.playFrameSounds.get(), (treeItem instanceof DefineSpriteTag) || (treeItem instanceof ButtonTag)); } else if (treeItem instanceof Frame && internalViewer) { Frame fn = (Frame) treeItem; SWF swf = (SWF) fn.getOpenable(); @@ -5042,7 +5048,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se case TagTreeModel.FOLDER_MOVIES: for (Tag tag : timelined.getTags()) { if (tag instanceof DefineVideoStreamTag) { - folderPreviewItems.add(tag); + folderPreviewItems.add(tag); } if (tag instanceof DefineSpriteTag) { addFolderPreviewItems(folderPreviewItems, folderName, (DefineSpriteTag) tag); @@ -5110,9 +5116,9 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se folderPreviewPanel.setItems(folderPreviewItems); showCard(CARDFOLDERPREVIEWPANEL); } - + private void showFolderList(TreePath path) { - List items = new ArrayList<>(getCurrentTree().getFullModel().getAllChildren((TreeItem)path.getLastPathComponent())); + List items = new ArrayList<>(getCurrentTree().getFullModel().getAllChildren((TreeItem) path.getLastPathComponent())); folderListPanel.setItems(path, items); showCard(CARDFOLDERLISTPANEL); }