diff --git a/CHANGELOG.md b/CHANGELOG.md index 06b84241d..2036363cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ All notable changes to this project will be documented in this file. - [#1680] Pinning items - Indices in brackets for items with same name (like two subsequent DoAction tags) - Flattened ActionScript packages (one row per package instead package tree), can be turned off in settings +- Opening ABC file format (*.abc) ### Fixed - [#1869] Replace references now replaces all references, not just PlaceObject diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/BinarySWFBundle.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/BinarySWFBundle.java index 50ba2fda4..b77a4c882 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/BinarySWFBundle.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/BinarySWFBundle.java @@ -31,7 +31,7 @@ import java.util.Set; * * @author JPEXS */ -public class BinarySWFBundle implements SWFBundle { +public class BinarySWFBundle implements Bundle { private final SWFSearch search; @@ -55,7 +55,7 @@ public class BinarySWFBundle implements SWFBundle { } @Override - public SeekableInputStream getSWF(String key) { + public SeekableInputStream getOpenable(String key) { if (!key.startsWith("[")) { return null; } @@ -75,7 +75,7 @@ public class BinarySWFBundle implements SWFBundle { public Map getAll() { Map ret = new LinkedHashMap<>(); for (String key : getKeys()) { - ret.put(key, getSWF(key)); + ret.put(key, getOpenable(key)); } return ret; } @@ -91,7 +91,7 @@ public class BinarySWFBundle implements SWFBundle { } @Override - public boolean putSWF(String key, InputStream is) { + public boolean putOpenable(String key, InputStream is) { throw new UnsupportedOperationException("Save not supported for this type of bundle"); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFBundle.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/Bundle.java similarity index 86% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFBundle.java rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/Bundle.java index 565a62571..12824fee1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFBundle.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/Bundle.java @@ -26,13 +26,13 @@ import java.util.Set; * * @author JPEXS */ -public interface SWFBundle { +public interface Bundle { public int length(); public Set getKeys(); - public SeekableInputStream getSWF(String key) throws IOException; + public SeekableInputStream getOpenable(String key) throws IOException; public Map getAll() throws IOException; @@ -40,5 +40,5 @@ public interface SWFBundle { public boolean isReadOnly(); - public boolean putSWF(String key, InputStream is) throws IOException; + public boolean putOpenable(String key, InputStream is) throws IOException; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DecompilerPool.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DecompilerPool.java index c47de120f..13f1bff19 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DecompilerPool.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DecompilerPool.java @@ -16,6 +16,7 @@ */ package com.jpexs.decompiler.flash; +import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.abc.types.ConvertData; import com.jpexs.decompiler.flash.abc.types.ScriptInfo; @@ -26,6 +27,7 @@ import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.helpers.HighlightedText; import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.helpers.ImmediateFuture; import java.util.ArrayList; import java.util.List; @@ -48,7 +50,7 @@ public class DecompilerPool { private final ThreadPoolExecutor executor; - private Map>> swfToFutures = new WeakHashMap<>(); + private Map>> openableToFutures = new WeakHashMap<>(); public DecompilerPool() { int threadCount = Configuration.getParallelThreadCount(); @@ -105,7 +107,8 @@ public class DecompilerPool { pack.toSource(writer, script == null ? null : script.traits.traits, new ConvertData(), ScriptExportMode.AS, parallel, false); HighlightedText result = new HighlightedText(writer); - SWF swf = pack.getSwf(); + Openable openable = pack.getOpenable(); + SWF swf = (openable instanceof SWF) ? (SWF) openable : ((ABC)openable).getSwf(); if (swf != null) { swf.as3Cache.put(pack, result); } @@ -155,10 +158,10 @@ public class DecompilerPool { public HighlightedText decompile(ASMSource src, ActionList actions) throws InterruptedException { Future future = submitTask(src, actions, null); SWF swf = src.getSwf(); - if (!swfToFutures.containsKey(swf)) { - swfToFutures.put(swf, new ArrayList<>()); + if (!openableToFutures.containsKey(swf)) { + openableToFutures.put(swf, new ArrayList<>()); } - swfToFutures.get(swf).add(future); + openableToFutures.get(swf).add(future); try { return future.get(); } catch (InterruptedException ex) { @@ -167,7 +170,7 @@ public class DecompilerPool { } catch (ExecutionException ex) { Logger.getLogger(DecompilerPool.class.getName()).log(Level.SEVERE, null, ex); } finally { - List> futures = swfToFutures.get(swf); + List> futures = openableToFutures.get(swf); if (futures != null) { futures.remove(future); } @@ -179,11 +182,11 @@ public class DecompilerPool { public HighlightedText decompile(ScriptPack pack) throws InterruptedException { Future future = submitTask(pack, null); - SWF swf = pack.getSwf(); - if (!swfToFutures.containsKey(swf)) { - swfToFutures.put(swf, new ArrayList<>()); + Openable openable = pack.getOpenable(); + if (!openableToFutures.containsKey(openable)) { + openableToFutures.put(openable, new ArrayList<>()); } - swfToFutures.get(swf).add(future); + openableToFutures.get(openable).add(future); try { return future.get(); } catch (InterruptedException ex) { @@ -192,7 +195,7 @@ public class DecompilerPool { } catch (ExecutionException ex) { Logger.getLogger(DecompilerPool.class.getName()).log(Level.SEVERE, null, ex); } finally { - List> futures = swfToFutures.get(swf); + List> futures = openableToFutures.get(openable); if (futures != null) { futures.remove(future); } @@ -208,7 +211,7 @@ public class DecompilerPool { } public void destroySwf(SWF swf){ - List> futures = swfToFutures.get(swf); + List> futures = openableToFutures.get(swf); if(futures!=null){ for(Future future:futures){ future.cancel(true); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFSourceInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/OpenableSourceInfo.java similarity index 75% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFSourceInfo.java rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/OpenableSourceInfo.java index 5af85af0c..f1c79f75c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFSourceInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/OpenableSourceInfo.java @@ -28,7 +28,7 @@ import java.io.InputStream; * * @author JPEXS */ -public class SWFSourceInfo { +public class OpenableSourceInfo { private final InputStream inputStream; @@ -39,8 +39,10 @@ public class SWFSourceInfo { private final boolean detectBundle; private boolean empty = false; + + private OpenableSourceKind kind; - public SWFSourceInfo(String fileTitle) { + public OpenableSourceInfo(String fileTitle) { this(null, null, fileTitle, false); empty = true; } @@ -49,16 +51,31 @@ public class SWFSourceInfo { return empty; } - public SWFSourceInfo(InputStream inputStream, String file, String fileTitle) { + public OpenableSourceInfo(InputStream inputStream, String file, String fileTitle) { this(inputStream, file, fileTitle, true); } - public SWFSourceInfo(InputStream inputStream, String file, String fileTitle, boolean detectBundle) { + public OpenableSourceInfo(InputStream inputStream, String file, String fileTitle, boolean detectBundle) { this.inputStream = inputStream; this.file = file; this.fileTitle = fileTitle; this.detectBundle = detectBundle; + detectKind(); } + public OpenableSourceKind getKind() { + return kind; + } + + private void detectKind() { + if (isBundle()) { + kind = OpenableSourceKind.BUNDLE; + } else if (this.file != null && this.file.endsWith(".abc")) { + kind = OpenableSourceKind.ABC; + } else { + kind = OpenableSourceKind.SWF; + } + } + public InputStream getInputStream() { return inputStream; } @@ -69,6 +86,7 @@ public class SWFSourceInfo { public void setFile(String file) { this.file = file; + detectKind(); } public String getFileTitle() { @@ -95,12 +113,12 @@ public class SWFSourceInfo { return false; } String extension = Path.getExtension(fileObj); - return (detectBundle) && (extension == null || !(extension.equals(".swf") || extension.equals(".gfx"))); + return (detectBundle) && (extension == null || !(extension.equals(".swf") || extension.equals(".gfx") || extension.equals(".abc"))); } return false; } - public SWFBundle getBundle(boolean noCheck, SearchMode searchMode) throws IOException { + public Bundle getBundle(boolean noCheck, SearchMode searchMode) throws IOException { if (!isBundle()) { return null; } @@ -111,7 +129,7 @@ public class SWFSourceInfo { case ".swc": return new SWC(new File(file)); case ".zip": - return new ZippedSWFBundle(new File(file)); + return new ZippedBundle(new File(file)); case ".iggy": return new IggySwfBundle(new File(file)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/OpenableSourceKind.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/OpenableSourceKind.java new file mode 100644 index 000000000..647895436 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/OpenableSourceKind.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2010-2022 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash; + +/** + * + * @author JPEXS + */ +public enum OpenableSourceKind { + ABC, SWF, BUNDLE +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWC.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWC.java index 13b803b96..4761bdbbe 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWC.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWC.java @@ -31,7 +31,7 @@ import org.xml.sax.helpers.DefaultHandler; * * @author JPEXS */ -public class SWC extends ZippedSWFBundle { +public class SWC extends ZippedBundle { public SWC(InputStream is) throws IOException { super(is); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index e2ab216df..6864071a4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -140,7 +140,8 @@ import com.jpexs.decompiler.flash.timeline.FrameScript; import com.jpexs.decompiler.flash.timeline.TagScript; import com.jpexs.decompiler.flash.timeline.Timeline; import com.jpexs.decompiler.flash.timeline.Timelined; -import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.decompiler.flash.treeitems.Openable; +import com.jpexs.decompiler.flash.treeitems.OpenableList; import com.jpexs.decompiler.flash.treeitems.TreeItem; import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.MATRIX; @@ -212,7 +213,7 @@ import java.util.zip.InflaterInputStream; * * @author JPEXS */ -public final class SWF implements SWFContainerItem, Timelined { +public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Default version of SWF file format @@ -290,7 +291,7 @@ public final class SWF implements SWFContainerItem, Timelined { public boolean gfx = false; @Internal - public SWFList swfList; + public OpenableList openableList; @Internal private String file; @@ -456,8 +457,8 @@ public final class SWF implements SWFContainerItem, Timelined { abcList = null; } - if (swfList != null) { - swfList.swfs.clear(); + if (openableList != null) { + openableList.items.clear(); } clearScriptCache(); @@ -979,12 +980,13 @@ public final class SWF implements SWFContainerItem, Timelined { * @param os OutputStream to save SWF in * @throws IOException */ + @Override public void saveTo(OutputStream os) throws IOException { checkCharset(); byte[] uncompressedData = saveToByteArray(); compress(new ByteArrayInputStream(uncompressedData), os, compression, lzmaProperties); } - + public void saveTo(OutputStream os, boolean gfx) throws IOException { checkCharset(); byte[] uncompressedData = saveToByteArray(gfx); @@ -1186,6 +1188,7 @@ public final class SWF implements SWFContainerItem, Timelined { isModified = value; } + @Override public void clearModified() { for (Tag tag : getTags()) { if (tag.isModified()) { @@ -1501,7 +1504,7 @@ public final class SWF implements SWFContainerItem, Timelined { } @Override - public SWF getSwf() { + public SWF getOpenable() { return this; } @@ -1514,6 +1517,7 @@ public final class SWF implements SWFContainerItem, Timelined { return result; } + @Override public String getFile() { return file; } @@ -1523,6 +1527,7 @@ public final class SWF implements SWFContainerItem, Timelined { * * @return file title */ + @Override public String getFileTitle() { if (fileTitle != null) { return fileTitle; @@ -1530,6 +1535,7 @@ public final class SWF implements SWFContainerItem, Timelined { return file; } + @Override public String getTitleOrShortFileName() { if (fileTitle != null) { return fileTitle; @@ -1537,6 +1543,7 @@ public final class SWF implements SWFContainerItem, Timelined { return new File(file).getName(); } + @Override public String getShortFileName() { return new File(getTitleOrShortFileName()).getName(); } @@ -1547,13 +1554,14 @@ public final class SWF implements SWFContainerItem, Timelined { * * @return */ + @Override public String getShortPathTitle() { if (binaryData != null) { return binaryData.getSwf().getShortPathTitle() + "/DefineBinaryData (" + binaryData.getCharacterId() + ")"; } - if (swfList != null) { - if (swfList.isBundle()) { - return swfList.name + "/" + getTitleOrShortFileName(); + if (openableList != null) { + if (openableList.isBundle()) { + return openableList.name + "/" + getTitleOrShortFileName(); } } return getTitleOrShortFileName(); @@ -1565,18 +1573,20 @@ public final class SWF implements SWFContainerItem, Timelined { * * @return */ + @Override public String getFullPathTitle() { if (binaryData != null) { return binaryData.getSwf().getFullPathTitle() + "/DefineBinaryData (" + binaryData.getCharacterId() + ")"; } - if (swfList != null) { - if (swfList.isBundle()) { - return swfList.sourceInfo.getFileTitleOrName() + "/" + getFileTitle(); + if (openableList != null) { + if (openableList.isBundle()) { + return openableList.sourceInfo.getFileTitleOrName() + "/" + getFileTitle(); } } return getFileTitle(); } + @Override public void setFile(String file) { this.file = file; fileTitle = null; @@ -1584,8 +1594,8 @@ public final class SWF implements SWFContainerItem, Timelined { public Date getFileModificationDate() { try { - if (swfList != null && swfList.sourceInfo != null) { - String fileName = swfList.sourceInfo.getFile(); + if (openableList != null && openableList.sourceInfo != null) { + String fileName = openableList.sourceInfo.getFile(); if (fileName != null) { long lastModified = new File(fileName).lastModified(); if (lastModified > 0) { @@ -2014,7 +2024,7 @@ public final class SWF implements SWFContainerItem, Timelined { } } - TagScript tagScript = new TagScript(treeItem.getSwf(), resultTag, subNodes); + TagScript tagScript = new TagScript((SWF) treeItem.getOpenable(), resultTag, subNodes); return tagScript; } @@ -2882,7 +2892,8 @@ public final class SWF implements SWFContainerItem, Timelined { public static void uncache(ScriptPack pack) { if (pack != null) { - SWF swf = pack.getSwf(); + Openable openable = pack.getOpenable(); + SWF swf = (openable instanceof SWF) ? (SWF) openable : ((ABC)openable).getSwf(); if (swf != null) { swf.as3Cache.remove(pack); } @@ -2913,7 +2924,8 @@ public final class SWF implements SWFContainerItem, Timelined { public static boolean isCached(ScriptPack pack) { if (pack != null) { - SWF swf = pack.getSwf(); + Openable openable = pack.getOpenable(); + SWF swf = (openable instanceof SWF) ? (SWF) openable : ((ABC)openable).getSwf(); if (swf != null) { return swf.as3Cache.isCached(pack); } @@ -2946,7 +2958,8 @@ public final class SWF implements SWFContainerItem, Timelined { public static HighlightedText getFromCache(ScriptPack pack) { if (pack != null) { - SWF swf = pack.getSwf(); + Openable openable = pack.getOpenable(); + SWF swf = (openable instanceof SWF) ? (SWF) openable : ((ABC)openable).getSwf(); if (swf != null) { return swf.as3Cache.get(pack); } @@ -3006,7 +3019,8 @@ public final class SWF implements SWFContainerItem, Timelined { } public static HighlightedText getCached(ScriptPack pack) throws InterruptedException { - SWF swf = pack.getSwf(); + Openable openable = pack.getOpenable(); + SWF swf = (openable instanceof SWF) ? (SWF) openable : ((ABC)openable).getSwf(); HighlightedText res; if (swf != null) { res = swf.as3Cache.get(pack); @@ -3036,7 +3050,8 @@ public final class SWF implements SWFContainerItem, Timelined { } public static Future getCachedFuture(ScriptPack pack, ScriptDecompiledListener listener) throws InterruptedException { - SWF swf = pack.getSwf(); + Openable openable = pack.getOpenable(); + SWF swf = (openable instanceof SWF) ? (SWF) openable : ((ABC)openable).getSwf(); HighlightedText res; if (swf != null) { res = swf.as3Cache.get(pack); @@ -3418,7 +3433,7 @@ public final class SWF implements SWFContainerItem, Timelined { return (DefineSpriteTag) treeItem; } - return treeItem.getSwf(); + return (SWF) treeItem.getOpenable(); //?? } public void packCharacterIds() { @@ -4148,4 +4163,14 @@ public final class SWF implements SWFContainerItem, Timelined { public void setFrameCount(int frameCount) { this.frameCount = frameCount; } + + @Override + public void setOpenableList(OpenableList openableList) { + this.openableList = openableList; + } + + @Override + public OpenableList getOpenableList() { + return openableList; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ZippedSWFBundle.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ZippedBundle.java similarity index 92% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ZippedSWFBundle.java rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ZippedBundle.java index d0a33dcc6..e74d46613 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ZippedSWFBundle.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ZippedBundle.java @@ -38,7 +38,7 @@ import java.util.zip.ZipOutputStream; * * @author JPEXS */ -public class ZippedSWFBundle implements SWFBundle { +public class ZippedBundle implements Bundle { protected Set keySet = new HashSet<>(); @@ -48,15 +48,15 @@ public class ZippedSWFBundle implements SWFBundle { protected File filename; - public ZippedSWFBundle(InputStream is) throws IOException { + public ZippedBundle(InputStream is) throws IOException { this(is, null); } - public ZippedSWFBundle(File filename) throws IOException { + public ZippedBundle(File filename) throws IOException { this(null, filename); } - protected ZippedSWFBundle(InputStream is, File filename) throws IOException { + protected ZippedBundle(InputStream is, File filename) throws IOException { initBundle(is, filename); } @@ -90,7 +90,7 @@ public class ZippedSWFBundle implements SWFBundle { } @Override - public SeekableInputStream getSWF(String key) throws IOException { + public SeekableInputStream getOpenable(String key) throws IOException { if (!keySet.contains(key)) { return null; } @@ -118,7 +118,7 @@ public class ZippedSWFBundle implements SWFBundle { public Map getAll() throws IOException { Map ret = new HashMap<>(); for (String key : getKeys()) { // cache everything first - ret.put(key, getSWF(key)); + ret.put(key, getOpenable(key)); } return ret; } @@ -134,7 +134,7 @@ public class ZippedSWFBundle implements SWFBundle { } @Override - public boolean putSWF(String key, InputStream swfIs) throws IOException { + public boolean putOpenable(String key, InputStream swfIs) throws IOException { if (this.isReadOnly()) { return false; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java index d1d4abb15..a96e4a5bf 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java @@ -66,9 +66,12 @@ import com.jpexs.decompiler.flash.importers.As3ScriptReplaceException; import com.jpexs.decompiler.flash.importers.As3ScriptReplacerInterface; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.treeitems.Openable; +import com.jpexs.decompiler.flash.treeitems.OpenableList; import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.helpers.utf8.Utf8PrintWriter; +import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; @@ -85,7 +88,7 @@ import java.util.logging.Logger; * * @author JPEXS */ -public class ABC { +public class ABC implements Openable { public ABCVersion version = new ABCVersion(46, 16); @@ -118,18 +121,38 @@ public class ABC { /* Map from multiname index of namespace value to namespace name**/ private Map namespaceMap; + + private String file; + + private String fileTitle; + + private OpenableList openableList; + + private boolean isOpenable = false; public ABC(ABCContainerTag tag) { this.parentTag = tag; this.deobfuscation = null; } - public SWF getSwf() { + @Override + public Openable getOpenable() { + if (isOpenable) { + return this; + } return parentTag.getSwf(); } + public SWF getSwf() { + return parentTag.getSwf(); + } + public List getAbcTags() { - return getSwf().getAbcList(); + Openable openable = getOpenable(); + if (openable instanceof SWF) { + return ((SWF) openable).getAbcList(); + } + return new ArrayList<>(); } public int addMethodBody(MethodBody body) { @@ -481,7 +504,15 @@ public class ABC { } public ABC(ABCInputStream ais, SWF swf, ABCContainerTag tag) throws IOException { + this(ais, swf, tag, null, null); + } + public ABC(ABCInputStream ais, SWF swf, ABCContainerTag tag, String file, String fileTitle) throws IOException { this.parentTag = tag; + this.file = file; + this.fileTitle = fileTitle; + if (file != null) { + isOpenable = true; + } int minor_version = ais.readU16("minor_version"); int major_version = ais.readU16("major_version"); version = new ABCVersion(major_version, minor_version); @@ -2116,4 +2147,96 @@ public class ABC { deobfuscation = null; abcMethodIndexing = null; } + + @Override + public String getFile() { + return file; + } + + @Override + public String getFileTitle() { + if (fileTitle != null) { + return fileTitle; + } + return file; + } + + @Override + public String getTitleOrShortFileName() { + if (fileTitle != null) { + return fileTitle; + } + return new File(file).getName(); + } + + @Override + public String getShortPathTitle() { + if (openableList != null) { + if (openableList.isBundle()) { + return openableList.name + "/" + getTitleOrShortFileName(); + } + } + return getTitleOrShortFileName(); + } + + @Override + public String getShortFileName() { + return new File(getTitleOrShortFileName()).getName(); + } + + @Override + public String getFullPathTitle() { + if (openableList != null) { + if (openableList.isBundle()) { + return openableList.sourceInfo.getFileTitleOrName() + "/" + getFileTitle(); + } + } + return getFileTitle(); + } + + @Override + public boolean isModified() { + return getSwf().isModified(); //?? + } + + @Override + public void setOpenableList(OpenableList openableList) { + this.openableList = openableList; + getSwf().setOpenableList(openableList); //dummySwf + } + + @Override + public OpenableList getOpenableList() { + return openableList; + } + + @Override + public String toString() { + return getTitleOrShortFileName(); + } + + @Override + public void saveTo(OutputStream os) throws IOException { + saveToStream(os); + } + + @Override + public void setFile(String file) { + this.file = file; + fileTitle = null; + } + + @Override + public void clearModified() { + getSwf().clearModified(); + List allAbcs = new ArrayList<>(); + allAbcs.add(this); + List packs = getScriptPacks(null, allAbcs); + for(ScriptPack pack : packs) { + if (pack.isModified()) { + pack.clearModified(); + } + } + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java index 2c5f2555b..399eb930c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java @@ -44,6 +44,7 @@ import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; import com.jpexs.decompiler.flash.search.MethodId; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.treeitems.AS3ClassTreeItem; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.ScopeStack; import com.jpexs.helpers.CancellableWorker; @@ -93,8 +94,8 @@ public class ScriptPack extends AS3ClassTreeItem { public boolean scriptInitializerIsEmpty = false; @Override - public SWF getSwf() { - return abc.getSwf(); + public Openable getOpenable() { + return abc.getOpenable(); } public ClassPath getClassPath() { @@ -356,6 +357,13 @@ public class ScriptPack extends AS3ClassTreeItem { } return abc.script_info.get(scriptIndex).isModified(); } + + public void clearModified() { + if (scriptIndex >= abc.script_info.size()) { + return; + } + abc.script_info.get(scriptIndex).setModified(false); + } /** * Injects debugfile, debugline instructions into the code diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java index 71fe62f45..6748885a9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java @@ -2619,7 +2619,7 @@ public class ActionScript3Parser { } SWC swc = new SWC(new FileInputStream(Configuration.getPlayerSWC())); - SWF swf = new SWF(swc.getSWF("library.swf"), true); + SWF swf = new SWF(swc.getOpenable("library.swf"), true); playerGlobalAbcIndex = new AbcIndexing(swf); } if (airGlobalAbcIndex == null) { @@ -2627,7 +2627,7 @@ public class ActionScript3Parser { return; } SWC swc = new SWC(new FileInputStream(Configuration.getAirSWC())); - SWF swf = new SWF(swc.getSWF("library.swf"), true); + SWF swf = new SWF(swc.getOpenable("library.swf"), true); airGlobalAbcIndex = new AbcIndexing(swf); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/dumpview/DumpInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/dumpview/DumpInfo.java index 61ce6a1c9..5b442be68 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/dumpview/DumpInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/dumpview/DumpInfo.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.TagStub; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.flash.treeitems.TreeItem; import java.io.IOException; import java.util.ArrayList; @@ -147,13 +148,13 @@ public class DumpInfo implements TreeItem { } @Override - public SWF getSwf() { + public Openable getOpenable() { Tag tag = tagToResolve != null ? tagToResolve : resolvedTag; if (tag != null) { - return tag.getSwf(); + return tag.getOpenable(); } - return DumpInfoSwfNode.getSwfNode(this).getSwf(); + return DumpInfoSwfNode.getSwfNode(this).getOpenable(); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/dumpview/DumpInfoSwfNode.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/dumpview/DumpInfoSwfNode.java index a4b9dfa10..8d80f4a1d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/dumpview/DumpInfoSwfNode.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/dumpview/DumpInfoSwfNode.java @@ -17,6 +17,7 @@ package com.jpexs.decompiler.flash.dumpview; import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.treeitems.Openable; /** * @@ -24,16 +25,20 @@ import com.jpexs.decompiler.flash.SWF; */ public class DumpInfoSwfNode extends DumpInfo { - private final SWF swf; + private final Openable openable; - public DumpInfoSwfNode(SWF swf, String name, String type, Object value, long startByte, long lengthBytes) { + public DumpInfoSwfNode(Openable openable, String name, String type, Object value, long startByte, long lengthBytes) { super(name, type, value, startByte, lengthBytes); - this.swf = swf; + this.openable = openable; } @Override + public Openable getOpenable() { + return openable; + } + public SWF getSwf() { - return swf; + return (SWF) openable; } public static DumpInfoSwfNode getSwfNode(DumpInfo dumpInfo) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/PreviewExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/PreviewExporter.java index f4ac3a03a..0048c6474 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/PreviewExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/PreviewExporter.java @@ -247,7 +247,7 @@ public class PreviewExporter { } public SWFHeader exportSwf(OutputStream os, TreeItem treeItem, Color backgroundColor, int fontPageNum, boolean showControls) throws IOException, ActionParseException { - SWF swf = treeItem.getSwf(); + SWF swf = (SWF) treeItem.getOpenable(); int frameCount = 1; float frameRate = swf.frameRate; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/MxmlcAs3ScriptReplacer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/MxmlcAs3ScriptReplacer.java index 307f5d47f..2a81f8fc1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/MxmlcAs3ScriptReplacer.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/MxmlcAs3ScriptReplacer.java @@ -33,6 +33,7 @@ import com.jpexs.decompiler.flash.importers.As3ScriptReplaceExceptionItem; import com.jpexs.decompiler.flash.importers.As3ScriptReplacerInterface; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.helpers.Helper; import java.io.ByteArrayInputStream; @@ -263,7 +264,9 @@ public class MxmlcAs3ScriptReplacer extends MxmlcRunner implements As3ScriptRepl swcFile = new File(pkgDir, "out.swc"); //Make copy without the old script - SWF swfCopy = recompileSWF(pack.getSwf()); + Openable openable = pack.getOpenable(); + SWF swf = (openable instanceof SWF) ? (SWF) openable : ((ABC)openable).getSwf(); + SWF swfCopy = recompileSWF(swf); List modAbcs = new ArrayList<>(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggySwfBundle.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggySwfBundle.java index bf8b14438..65ed6eb3f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggySwfBundle.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/IggySwfBundle.java @@ -17,7 +17,6 @@ package com.jpexs.decompiler.flash.iggy.conversion; import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFBundle; import com.jpexs.decompiler.flash.iggy.IggyFile; import com.jpexs.helpers.Helper; import com.jpexs.helpers.MemoryInputStream; @@ -30,12 +29,13 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.TreeSet; +import com.jpexs.decompiler.flash.Bundle; /** * * @author JPEXS */ -public class IggySwfBundle implements SWFBundle { +public class IggySwfBundle implements Bundle { private IggyFile iggyFile; @@ -83,7 +83,7 @@ public class IggySwfBundle implements SWFBundle { } @Override - public SeekableInputStream getSWF(String key) throws IOException { + public SeekableInputStream getOpenable(String key) throws IOException { SWF swf = IggyToSwfConvertor.getSwf(iggyFile); ByteArrayOutputStream baos = new ByteArrayOutputStream(); swf.saveTo(baos); @@ -95,7 +95,7 @@ public class IggySwfBundle implements SWFBundle { public Map getAll() throws IOException { Map ret = new HashMap<>(); for (String key : getKeys()) { - ret.put(key, getSWF(key)); + ret.put(key, getOpenable(key)); } return ret; } @@ -111,7 +111,7 @@ public class IggySwfBundle implements SWFBundle { } @Override - public boolean putSWF(String key, InputStream is) throws IOException { + public boolean putOpenable(String key, InputStream is) throws IOException { try { SWF swf = new SWF(is, false, false); SwfToIggyConvertor.updateIggy(iggyFile.getSwf(), swf); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS3ScriptImporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS3ScriptImporter.java index 139275e50..70c69e29d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS3ScriptImporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS3ScriptImporter.java @@ -16,9 +16,12 @@ */ package com.jpexs.decompiler.flash.importers; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.exporters.settings.ScriptExportSettings; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.helpers.Helper; import java.io.File; import java.io.IOException; @@ -51,7 +54,9 @@ public class AS3ScriptImporter { try { File file = pack.getExportFile(scriptsFolder, new ScriptExportSettings(ScriptExportMode.AS, false, false)); if (file.exists()) { - pack.getSwf().informListeners("importing_as", file.getAbsolutePath()); + Openable openable = pack.getOpenable(); + SWF swf = (openable instanceof SWF) ? (SWF) openable : ((ABC)openable).getSwf(); + swf.informListeners("importing_as", file.getAbsolutePath()); String fileName = file.getAbsolutePath(); String txt = Helper.readTextFile(fileName); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/ABCSearchResult.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/ABCSearchResult.java index d95f449fc..7f2cee129 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/ABCSearchResult.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/ABCSearchResult.java @@ -22,12 +22,14 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.ClassPath; import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.treeitems.Openable; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; +import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -56,7 +58,7 @@ public class ABCSearchResult implements Serializable, ScriptSearchResult { private static final int SERIAL_VERSION_MINOR = 0; @SuppressWarnings("unchecked") - public ABCSearchResult(SWF swf, InputStream is) throws IOException, ScriptNotFoundException { + public ABCSearchResult(Openable openable, InputStream is) throws IOException, ScriptNotFoundException { ObjectInputStream ois = new ObjectInputStream(is); int versionMajor = ois.read(); ois.read(); //minor @@ -78,7 +80,19 @@ public class ABCSearchResult implements Serializable, ScriptSearchResult { this.classIndex = ois.readInt(); this.traitId = ois.readInt(); boolean packFound = false; - for (ScriptPack pack : swf.getAS3Packs()) { + + List packs; + + if (openable instanceof SWF) { + packs = ((SWF)openable).getAS3Packs(); + } else { + ABC abc = (ABC)openable; + List allAbcs = new ArrayList<>(); + allAbcs.add(abc); + packs = abc.getScriptPacks(null, allAbcs); + } + + for (ScriptPack pack : packs) { if (cp.equals(pack.getClassPath()) && traitIndices.equals(pack.traitIndices)) { this.scriptPack = pack; packFound = true; @@ -176,7 +190,7 @@ public class ABCSearchResult implements Serializable, ScriptSearchResult { } @Override - public SWF getSWF() { - return scriptPack.getSwf(); + public Openable getOpenable() { + return scriptPack.getOpenable(); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/ActionScriptSearch.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/ActionScriptSearch.java index 276c3b7f8..b180fd564 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/ActionScriptSearch.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/ActionScriptSearch.java @@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.helpers.HighlightedText; import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.flash.treeitems.Openable; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -121,20 +122,27 @@ public class ActionScriptSearch { return null; } - public List searchAs3(final SWF swf, final String txt, boolean ignoreCase, boolean regexp, boolean pcode, ScriptSearchListener listener, List scope) { + public List searchAs3(final Openable openable, final String txt, boolean ignoreCase, boolean regexp, boolean pcode, ScriptSearchListener listener, List scope) { // todo: pcode seach if (txt != null && !txt.isEmpty()) { List ignoredClasses = new ArrayList<>(); List ignoredNss = new ArrayList<>(); - if (Configuration._ignoreAdditionalFlexClasses.get()) { - swf.getFlexMainClass(ignoredClasses, ignoredNss); + if (Configuration._ignoreAdditionalFlexClasses.get() && (openable instanceof SWF)) { + ((SWF)openable).getFlexMainClass(ignoredClasses, ignoredNss); } final List found = Collections.synchronizedList(new ArrayList<>()); final List fscope; if (scope == null) { - fscope = swf.getAS3Packs(); + if (openable instanceof SWF) { + fscope = ((SWF)openable).getAS3Packs(); + } else { + ABC abc = (ABC)openable; + List allAbcs = new ArrayList<>(); + allAbcs.add(abc); + fscope = abc.getScriptPacks(null, allAbcs); + } } else { fscope = scope; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/ActionSearchResult.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/ActionSearchResult.java index 7f887a3d5..26ff40146 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/ActionSearchResult.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/ActionSearchResult.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.search; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.flash.treeitems.Openable; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; @@ -87,7 +88,7 @@ public class ActionSearchResult implements ScriptSearchResult { } @Override - public SWF getSWF() { + public Openable getOpenable() { return src.getSwf(); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/SearchResult.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/SearchResult.java index 50e99890c..854185983 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/SearchResult.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/SearchResult.java @@ -17,11 +17,12 @@ package com.jpexs.decompiler.flash.search; import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.treeitems.Openable; /** * * @author JPEXS */ public interface SearchResult { - public SWF getSWF(); + public Openable getOpenable(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/Tag.java index 9785d41c8..cb849deb0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/Tag.java @@ -39,6 +39,7 @@ import com.jpexs.decompiler.flash.tags.gfx.DefineSubImage; import com.jpexs.decompiler.flash.tags.gfx.ExporterInfo; import com.jpexs.decompiler.flash.tags.gfx.FontTextureInfo; import com.jpexs.decompiler.flash.timeline.Timelined; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.helpers.ByteArrayRange; @@ -156,6 +157,10 @@ public abstract class Tag implements NeedsCharacters, Exportable, Serializable { } @Override + public Openable getOpenable() { + return swf; + } + public SWF getSwf() { return swf; } @@ -648,6 +653,9 @@ public abstract class Tag implements NeedsCharacters, Exportable, Serializable { for (int i = 0; i < needed3.size(); i++) { int characterId = needed3.get(i); + if (swf == null) { + return; + } if (swf.getCharacters().containsKey(characterId)) { Set needed4 = new LinkedHashSet<>(); CharacterTag character = swf.getCharacter(characterId); @@ -670,6 +678,9 @@ public abstract class Tag implements NeedsCharacters, Exportable, Serializable { } for (Integer characterId : needed3) { + if (swf == null) { + return; + } if (swf.getCharacters().containsKey(characterId)) { needed.add(characterId); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonAction.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonAction.java index f7aa078d9..fe4201bc6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonAction.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonAction.java @@ -25,6 +25,7 @@ import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.tags.DefineButtonTag; import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.Helper; import java.util.ArrayList; @@ -181,8 +182,8 @@ public class ButtonAction implements ASMSource { } @Override - public SWF getSwf() { - return buttonTag.getSwf(); + public Openable getOpenable() { + return buttonTag.getOpenable(); } @Override @@ -199,6 +200,11 @@ public class ButtonAction implements ASMSource { public Tag getTag() { return buttonTag; } + + @Override + public SWF getSwf() { + return (SWF) getOpenable(); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/AS2Package.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/AS2Package.java index 276470010..5eac7ab32 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/AS2Package.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/AS2Package.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.timeline; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.flash.treeitems.TreeItem; import java.util.ArrayList; import java.util.List; @@ -59,7 +60,7 @@ public class AS2Package implements TreeItem { @Override - public SWF getSwf() { + public Openable getOpenable() { return swf; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/AS3Package.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/AS3Package.java index f467657a7..2550186d9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/AS3Package.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/AS3Package.java @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.abc.ClassPath; import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.treeitems.AS3ClassTreeItem; +import com.jpexs.decompiler.flash.treeitems.Openable; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -32,7 +33,7 @@ import java.util.TreeMap; */ public class AS3Package extends AS3ClassTreeItem { - private final SWF swf; + private final Openable openable; public String packageName; @@ -48,10 +49,10 @@ public class AS3Package extends AS3ClassTreeItem { private boolean defaultPackage; - public AS3Package(String packageName, SWF swf, boolean flat, boolean defaultPackage) { + public AS3Package(String packageName, Openable openable, boolean flat, boolean defaultPackage) { super(packageName, "", null); this.flat = flat; - this.swf = swf; + this.openable = openable; this.packageName = packageName; this.defaultPackage = defaultPackage; } @@ -63,8 +64,8 @@ public class AS3Package extends AS3ClassTreeItem { @Override - public SWF getSwf() { - return swf; + public Openable getOpenable() { + return openable; } public List getSubPackages() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Frame.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Frame.java index 5282b8c86..3897698b2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Frame.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Frame.java @@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.tags.base.ASMSourceContainer; import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.Exportable; import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.flash.treeitems.TreeItem; import com.jpexs.decompiler.flash.types.RGB; import com.jpexs.decompiler.flash.types.RGBA; @@ -87,7 +88,7 @@ public class Frame implements TreeItem, Exportable { } @Override - public SWF getSwf() { + public Openable getOpenable() { return timeline.swf; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/FrameScript.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/FrameScript.java index ee956d95a..e2c475724 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/FrameScript.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/FrameScript.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.timeline; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.tags.base.Exportable; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.flash.treeitems.TreeItem; /** @@ -40,7 +41,7 @@ public class FrameScript implements TreeItem, Exportable { } @Override - public SWF getSwf() { + public Openable getOpenable() { return swf; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/TagScript.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/TagScript.java index 8ab4e0a87..fa2169f3d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/TagScript.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/TagScript.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.timeline; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.Exportable; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.flash.treeitems.TreeItem; import java.util.List; import java.util.Objects; @@ -50,7 +51,7 @@ public class TagScript implements TreeItem, Exportable { } @Override - public SWF getSwf() { + public Openable getOpenable() { return swf; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/FolderItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/FolderItem.java index 44704cf9e..9623dab48 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/FolderItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/FolderItem.java @@ -45,7 +45,7 @@ public class FolderItem implements TreeItem { } @Override - public SWF getSwf() { + public Openable getOpenable() { return swf; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/HeaderItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/HeaderItem.java index 4bef6f620..bf16deaf4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/HeaderItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/HeaderItem.java @@ -34,7 +34,7 @@ public class HeaderItem implements TreeItem { } @Override - public SWF getSwf() { + public Openable getOpenable() { return swf; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/Openable.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/Openable.java new file mode 100644 index 000000000..0a33cabe4 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/Openable.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2010-2022 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.treeitems; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * @author JPEXS + */ +public interface Openable extends TreeItem { + public String getFileTitle(); + + public String getShortPathTitle(); + + public String getShortFileName(); + + public String getFile(); + + public String getTitleOrShortFileName(); + + public String getFullPathTitle(); + + public void setOpenableList(OpenableList openableList); + + public OpenableList getOpenableList(); + + public void saveTo(OutputStream os) throws IOException; + + public void setFile(String file); + + public void clearModified(); +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/SWFList.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/OpenableList.java similarity index 58% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/SWFList.java rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/OpenableList.java index f69ac60b1..0c34a2070 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/SWFList.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/OpenableList.java @@ -17,35 +17,35 @@ package com.jpexs.decompiler.flash.treeitems; import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFBundle; import com.jpexs.decompiler.flash.SWFContainerItem; -import com.jpexs.decompiler.flash.SWFSourceInfo; +import com.jpexs.decompiler.flash.OpenableSourceInfo; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; +import com.jpexs.decompiler.flash.Bundle; /** * * @author JPEXS */ -public class SWFList implements List, SWFContainerItem { +public class OpenableList implements List, SWFContainerItem { public String name; - public SWFBundle bundle; + public Bundle bundle; - public SWFSourceInfo sourceInfo; + public OpenableSourceInfo sourceInfo; - public List swfs = new ArrayList<>(); + public List items = new ArrayList<>(); public boolean isBundle() { return bundle != null; } @Override - public SWF getSwf() { + public Openable getOpenable() { throw new UnsupportedOperationException("Not supported."); } @@ -54,131 +54,131 @@ public class SWFList implements List, SWFContainerItem { if (isBundle()) { return name; } else { - return swfs.get(0).getFileTitle(); + return items.get(0).getFileTitle(); } } @Override - public Iterator iterator() { - return swfs.iterator(); + public Iterator iterator() { + return items.iterator(); } @Override public int size() { - return swfs.size(); + return items.size(); } @Override public boolean isEmpty() { - return swfs.isEmpty(); + return items.isEmpty(); } @Override public boolean contains(Object o) { - return swfs.contains(o); + return items.contains(o); } @Override public Object[] toArray() { - return swfs.toArray(); + return items.toArray(); } @Override public T[] toArray(T[] ts) { - return swfs.toArray(ts); + return items.toArray(ts); } @Override - public boolean add(SWF e) { - return swfs.add(e); + public boolean add(Openable e) { + return items.add(e); } @Override public boolean remove(Object o) { - return swfs.remove(o); + return items.remove(o); } @Override public boolean containsAll(Collection clctn) { - return swfs.containsAll(clctn); + return items.containsAll(clctn); } @Override - public boolean addAll(Collection clctn) { - return swfs.addAll(clctn); + public boolean addAll(Collection clctn) { + return items.addAll(clctn); } @Override public boolean removeAll(Collection clctn) { - return swfs.removeAll(clctn); + return items.removeAll(clctn); } @Override public boolean retainAll(Collection clctn) { - return swfs.retainAll(clctn); + return items.retainAll(clctn); } @Override public void clear() { - swfs.clear(); + items.clear(); } @Override - public boolean addAll(int i, Collection clctn) { - return swfs.addAll(i, clctn); + public boolean addAll(int i, Collection clctn) { + return items.addAll(i, clctn); } @Override - public SWF get(int i) { - if (i < 0 || i >= swfs.size()) { + public Openable get(int i) { + if (i < 0 || i >= items.size()) { return null; } - return swfs.get(i); + return items.get(i); } @Override - public SWF set(int i, SWF e) { - return swfs.set(i, e); + public Openable set(int i, Openable e) { + return items.set(i, e); } @Override - public void add(int i, SWF e) { - swfs.add(i, e); + public void add(int i, Openable e) { + items.add(i, e); } @Override - public SWF remove(int i) { - return swfs.remove(i); + public Openable remove(int i) { + return items.remove(i); } @Override public int indexOf(Object o) { - return swfs.indexOf(0); + return items.indexOf(0); } @Override public int lastIndexOf(Object o) { - return swfs.lastIndexOf(o); + return items.lastIndexOf(o); } @Override - public ListIterator listIterator() { - return swfs.listIterator(); + public ListIterator listIterator() { + return items.listIterator(); } @Override - public ListIterator listIterator(int i) { - return swfs.listIterator(i); + public ListIterator listIterator(int i) { + return items.listIterator(i); } @Override - public List subList(int i, int i1) { - return swfs.subList(i, i1); + public List subList(int i, int i1) { + return items.subList(i, i1); } @Override public boolean isModified() { - for (SWF s : swfs) { + for (Openable s : items) { if (s.isModified()) { return true; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/TreeItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/TreeItem.java index f661e3ae0..6dd18d522 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/TreeItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/TreeItem.java @@ -24,7 +24,7 @@ import com.jpexs.decompiler.flash.SWF; */ public interface TreeItem { - public SWF getSwf(); + public Openable getOpenable(); public boolean isModified(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/BUTTONCONDACTION.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/BUTTONCONDACTION.java index b3a2c3c15..ff2ad7c1a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/BUTTONCONDACTION.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/BUTTONCONDACTION.java @@ -27,6 +27,7 @@ import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.flash.types.annotations.Conditional; import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit; import com.jpexs.decompiler.flash.types.annotations.Internal; @@ -92,6 +93,12 @@ public class BUTTONCONDACTION implements ASMSource, Serializable, HasSwfAndTag { actionBytes = sis.readByteRangeEx(condActionSize <= 0 ? sis.available() : condActionSize - 4, "actionBytes", DumpInfoSpecialType.ACTION_BYTES, sis.getPos()); } + + @Override + public Openable getOpenable() { + return swf; + } + @Override public SWF getSwf() { return swf; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/BUTTONRECORD.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/BUTTONRECORD.java index e807bafa8..a0466657c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/BUTTONRECORD.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/BUTTONRECORD.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.tags.DefineButton2Tag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.ButtonTag; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.flash.treeitems.TreeItem; import com.jpexs.decompiler.flash.types.annotations.Conditional; import com.jpexs.decompiler.flash.types.annotations.EnumValue; @@ -153,6 +154,11 @@ public class BUTTONRECORD implements Serializable, TreeItem, HasSwfAndTag, HasCh public SWF getSwf() { return swf; } + + @Override + public Openable getOpenable() { + return swf; + } public void setModified(boolean value) { modified = value; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java index 42a63dcec..e15ef2bdd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java @@ -27,6 +27,7 @@ import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.flash.types.annotations.Conditional; import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit; import com.jpexs.decompiler.flash.types.annotations.Internal; @@ -172,10 +173,16 @@ public class CLIPACTIONRECORD implements ASMSource, Serializable, HasSwfAndTag { this.parentClipActions = parentClipActions; } + @Override + public Openable getOpenable() { + return swf; + } + @Override public SWF getSwf() { return swf; } + /** * Events to which this handler applies diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java index ece0527ed..ab84f38c5 100644 --- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java +++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java @@ -22,9 +22,8 @@ import com.jpexs.decompiler.flash.EventListener; import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; import com.jpexs.decompiler.flash.ReadOnlyTagList; import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFBundle; import com.jpexs.decompiler.flash.SWFCompression; -import com.jpexs.decompiler.flash.SWFSourceInfo; +import com.jpexs.decompiler.flash.OpenableSourceInfo; import com.jpexs.decompiler.flash.SearchMode; import com.jpexs.decompiler.flash.SwfOpenException; import com.jpexs.decompiler.flash.ValueTooLargeException; @@ -147,7 +146,7 @@ import com.jpexs.decompiler.flash.tags.base.SoundTag; import com.jpexs.decompiler.flash.tags.base.TextImportErrorHandler; import com.jpexs.decompiler.flash.tags.base.TextTag; import com.jpexs.decompiler.flash.timeline.Timelined; -import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.decompiler.flash.treeitems.OpenableList; import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.sound.SoundFormat; @@ -216,6 +215,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; +import com.jpexs.decompiler.flash.Bundle; /** * @@ -2009,11 +2009,11 @@ public class CommandLineArgumentParser { File[] files = new File(folder).listFiles(getSwfFilter()); for (File file : files) { - SWFSourceInfo sourceInfo = new SWFSourceInfo(null, file.getAbsolutePath(), file.getName()); + OpenableSourceInfo sourceInfo = new OpenableSourceInfo(null, file.getAbsolutePath(), file.getName()); try { SWF swf = new SWF(new FileInputStream(file), sourceInfo.getFile(), sourceInfo.getFileTitle(), Configuration.parallelSpeedUp.get(), charset); - swf.swfList = new SWFList(); - swf.swfList.sourceInfo = sourceInfo; + swf.openableList = new OpenableList(); + swf.openableList.sourceInfo = sourceInfo; boolean found = false; for (Tag tag : swf.getTags()) { if (tag.getId() == tagId) { @@ -2051,11 +2051,11 @@ public class CommandLineArgumentParser { File[] files = new File(folder).listFiles(getSwfFilter()); for (File file : files) { - SWFSourceInfo sourceInfo = new SWFSourceInfo(null, file.getAbsolutePath(), file.getName()); + OpenableSourceInfo sourceInfo = new OpenableSourceInfo(null, file.getAbsolutePath(), file.getName()); try { SWF swf = new SWF(new FileInputStream(file), sourceInfo.getFile(), sourceInfo.getFileTitle(), Configuration.parallelSpeedUp.get(), charset); - swf.swfList = new SWFList(); - swf.swfList.sourceInfo = sourceInfo; + swf.openableList = new OpenableList(); + swf.openableList.sourceInfo = sourceInfo; boolean found = false; for (Tag tag : swf.getTags()) { if (tag instanceof JPEGTablesTag) { @@ -2231,7 +2231,7 @@ public class CommandLineArgumentParser { System.out.println("Start exporting " + inFile.getName()); } - SWFSourceInfo sourceInfo = new SWFSourceInfo(null, inFile.getAbsolutePath(), inFile.getName()); + OpenableSourceInfo sourceInfo = new OpenableSourceInfo(null, inFile.getAbsolutePath(), inFile.getName()); SWF swf; try { swf = new SWF(new StdInAwareFileInputStream(inFile), sourceInfo.getFile(), sourceInfo.getFileTitle(), Configuration.parallelSpeedUp.get(), charset); @@ -2241,8 +2241,8 @@ public class CommandLineArgumentParser { continue; } - swf.swfList = new SWFList(); - swf.swfList.sourceInfo = sourceInfo; + swf.openableList = new OpenableList(); + swf.openableList.sourceInfo = sourceInfo; String outDir = outDirBase.getAbsolutePath(); if (!singleFile) { outDir = Path.combine(outDir, inFile.getName()); @@ -2705,12 +2705,12 @@ public class CommandLineArgumentParser { } try { - SWFSourceInfo sourceInfo = new SWFSourceInfo(null, fileName, null); + OpenableSourceInfo sourceInfo = new OpenableSourceInfo(null, fileName, null); if (!sourceInfo.isBundle()) { System.err.println("Error: should be a bundle. (ZIP or non SWF binary file)"); System.exit(1); } - SWFBundle bundle = sourceInfo.getBundle(noCheck, mode); + Bundle bundle = sourceInfo.getBundle(noCheck, mode); List> streamsToExtract = new ArrayList<>(); for (Map.Entry streamEntry : bundle.getAll().entrySet()) { InputStream stream = streamEntry.getValue(); @@ -3652,8 +3652,8 @@ public class CommandLineArgumentParser { boolean result = true; for (String fileName : fileNames) { try { - SWFSourceInfo sourceInfo = new SWFSourceInfo(null, fileName, null); - Main.parseSWF(sourceInfo); + OpenableSourceInfo sourceInfo = new OpenableSourceInfo(null, fileName, null); + Main.parseOpenable(sourceInfo); } catch (Exception ex) { logger.log(Level.SEVERE, null, ex); result = false; @@ -3816,12 +3816,12 @@ public class CommandLineArgumentParser { detectBundle = false; break; default: - SWFBundle bundle; + Bundle bundle; String sfile = a; File file = new File(sfile); try { - SWFSourceInfo sourceInfo = new SWFSourceInfo(null, sfile, sfile, detectBundle); + OpenableSourceInfo sourceInfo = new OpenableSourceInfo(null, sfile, sfile, detectBundle); bundle = sourceInfo.getBundle(false, SearchMode.ALL); logger.log(Level.INFO, "Load file: {0}", sourceInfo.getFile()); @@ -3977,8 +3977,8 @@ public class CommandLineArgumentParser { try { Configuration.dumpTags.set(true); Configuration.parallelSpeedUp.set(false); - SWFSourceInfo sourceInfo = new SWFSourceInfo(null, args.pop(), null); - Main.parseSWF(sourceInfo); + OpenableSourceInfo sourceInfo = new OpenableSourceInfo(null, args.pop(), null); + Main.parseOpenable(sourceInfo); } catch (Exception ex) { logger.log(Level.SEVERE, null, ex); System.exit(1); diff --git a/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java index 64ba75647..35a5cba8a 100644 --- a/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/FolderPreviewPanel.java @@ -266,7 +266,7 @@ public class FolderPreviewPanel extends JPanel { private synchronized void renderImageTask(final int index, final TreeItem treeItem) { executor.submit(() -> { - cachedPreviews.put(index, renderImage(treeItem.getSwf(), treeItem)); + cachedPreviews.put(index, renderImage((SWF)treeItem.getOpenable(), treeItem)); if (!repaintQueued) { repaintQueued = true; View.execInEventDispatchLater(() -> { diff --git a/src/com/jpexs/decompiler/flash/gui/LoadFromCacheFrame.java b/src/com/jpexs/decompiler/flash/gui/LoadFromCacheFrame.java index 8eafbcb4c..64c2939e7 100644 --- a/src/com/jpexs/decompiler/flash/gui/LoadFromCacheFrame.java +++ b/src/com/jpexs/decompiler/flash/gui/LoadFromCacheFrame.java @@ -19,7 +19,7 @@ package com.jpexs.decompiler.flash.gui; import com.jpexs.browsers.cache.CacheEntry; import com.jpexs.browsers.cache.CacheImplementation; import com.jpexs.browsers.cache.CacheReader; -import com.jpexs.decompiler.flash.SWFSourceInfo; +import com.jpexs.decompiler.flash.OpenableSourceInfo; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.helpers.Helper; import com.jpexs.helpers.ReReadableInputStream; @@ -226,7 +226,7 @@ public class LoadFromCacheFrame extends AppFrame { CacheEntry en = list.getSelectedValue(); if (en != null) { ReReadableInputStream str = new ReReadableInputStream(en.getResponseDataStream()); - SWFSourceInfo sourceInfo = new SWFSourceInfo(str, null, entryToFileName(en)); + OpenableSourceInfo sourceInfo = new OpenableSourceInfo(str, null, entryToFileName(en)); Main.openFile(sourceInfo); } } diff --git a/src/com/jpexs/decompiler/flash/gui/LoadFromMemoryFrame.java b/src/com/jpexs/decompiler/flash/gui/LoadFromMemoryFrame.java index 93c293e8c..23a3ed9ae 100644 --- a/src/com/jpexs/decompiler/flash/gui/LoadFromMemoryFrame.java +++ b/src/com/jpexs/decompiler/flash/gui/LoadFromMemoryFrame.java @@ -16,7 +16,7 @@ */ package com.jpexs.decompiler.flash.gui; -import com.jpexs.decompiler.flash.SWFSourceInfo; +import com.jpexs.decompiler.flash.OpenableSourceInfo; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.helpers.Helper; import com.jpexs.helpers.ReReadableInputStream; @@ -164,7 +164,7 @@ public class LoadFromMemoryFrame extends AppFrame { return; } str.mark(Integer.MAX_VALUE); - SWFSourceInfo sourceInfo = new SWFSourceInfo(str, null, swf.process + " [" + (index + 1) + "]"); + OpenableSourceInfo sourceInfo = new OpenableSourceInfo(str, null, swf.process + " [" + (index + 1) + "]"); Main.openFile(sourceInfo); } } diff --git a/src/com/jpexs/decompiler/flash/gui/LoadingDialog.java b/src/com/jpexs/decompiler/flash/gui/LoadingDialog.java index bb9e57217..650a81611 100644 --- a/src/com/jpexs/decompiler/flash/gui/LoadingDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/LoadingDialog.java @@ -45,7 +45,7 @@ public class LoadingDialog extends AppDialog { private final JProgressBar progressBar = new JProgressBar(0, 100); - public void setWroker(CancellableWorker worker) { + public void setWorker(CancellableWorker worker) { this.worker = worker; } diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index 3651d2417..78710b81f 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -28,8 +28,7 @@ import com.jpexs.debugger.flash.messages.in.InCallFunction; import com.jpexs.decompiler.flash.ApplicationInfo; import com.jpexs.decompiler.flash.EventListener; import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFBundle; -import com.jpexs.decompiler.flash.SWFSourceInfo; +import com.jpexs.decompiler.flash.OpenableSourceInfo; import com.jpexs.decompiler.flash.SearchMode; import com.jpexs.decompiler.flash.SwfOpenException; import com.jpexs.decompiler.flash.UrlResolver; @@ -54,7 +53,7 @@ import com.jpexs.decompiler.flash.tags.ShowFrameTag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.FontTag; import com.jpexs.decompiler.flash.tags.base.ImportTag; -import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.decompiler.flash.treeitems.OpenableList; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.RGB; import com.jpexs.helpers.Cache; @@ -133,6 +132,13 @@ import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.filechooser.FileFilter; import org.pushingpixels.substance.api.SubstanceLookAndFeel; +import com.jpexs.decompiler.flash.Bundle; +import com.jpexs.decompiler.flash.OpenableSourceKind; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.ABCInputStream; +import com.jpexs.decompiler.flash.tags.DoABC2Tag; +import com.jpexs.decompiler.flash.treeitems.Openable; +import com.jpexs.helpers.MemoryInputStream; /** * Main executable class @@ -143,7 +149,7 @@ public class Main { protected static ProxyFrame proxyFrame; - private static List sourceInfos = new ArrayList<>(); + private static List sourceInfos = new ArrayList<>(); public static LoadingDialog loadingDialog; @@ -202,11 +208,10 @@ public class Main { public static CancellableWorker importWorker = null; public static CancellableWorker deobfuscatePCodeWorker = null; public static CancellableWorker swfPrepareWorker = null; - + public static final int LIBRARY_AIR = 0; public static final int LIBRARY_FLASH = 1; - public static boolean isSwfAir(SWF swf) { SwfSpecificCustomConfiguration conf = Configuration.getSwfSpecificCustomConfiguration(swf.getShortPathTitle()); if (conf != null) { @@ -216,7 +221,7 @@ public class Main { } return false; } - + //This method makes file watcher to shut up during our own file saving public static void startSaving(File savedFile) { savedFiles.add(savedFile); @@ -845,11 +850,11 @@ public class Main { } } - public static SWFList parseSWF(SWFSourceInfo sourceInfo) throws Exception { - SWFList result = new SWFList(); + public static OpenableList parseOpenable(OpenableSourceInfo sourceInfo) throws Exception { + OpenableList result = new OpenableList(); InputStream inputStream = sourceInfo.getInputStream(); - SWFBundle bundle = null; + Bundle bundle = null; FileInputStream fis = null; if (inputStream == null) { inputStream = new BufferedInputStream(fis = new FileInputStream(sourceInfo.getFile())); @@ -887,7 +892,7 @@ public class Main { final CancellableWorker worker = this; String fileKey = fname + "/" + streamEntry.getKey(); SwfSpecificCustomConfiguration conf = Configuration.getSwfSpecificCustomConfiguration(fileKey); - + String charset = conf == null ? Charset.defaultCharset().name() : conf.getCustomData(CustomConfigurationKeys.KEY_CHARSET, Charset.defaultCharset().name()); SWF swf = new SWF(stream, null, streamEntry.getKey(), new ProgressListener() { @Override @@ -898,7 +903,7 @@ public class Main { return swf; } }; - loadingDialog.setWroker(worker); + loadingDialog.setWorker(worker); worker.execute(); try { @@ -910,163 +915,197 @@ public class Main { } else { InputStream fInputStream = inputStream; - final String[] yesno = new String[]{AppStrings.translate("button.yes"), AppStrings.translate("button.no"), AppStrings.translate("button.yes.all"), AppStrings.translate("button.no.all")}; + CancellableWorker worker = null; + + if (sourceInfo.getKind() == OpenableSourceKind.ABC) { + CancellableWorker abcWorker = new CancellableWorker() { + private ABC open(InputStream is, String file, String fileTitle) throws IOException, InterruptedException { + SWF dummySwf = new SWF(); + dummySwf.setFileTitle(fileTitle != null ? fileTitle : file); + FileAttributesTag fileAttributes = new FileAttributesTag(dummySwf); + fileAttributes.actionScript3 = true; + dummySwf.addTag(fileAttributes); + fileAttributes.setTimelined(dummySwf); + DoABC2Tag doABC2Tag = new DoABC2Tag(dummySwf); + dummySwf.addTag(doABC2Tag); + doABC2Tag.setTimelined(dummySwf); + dummySwf.clearModified(); + startWork(AppStrings.translate("work.reading.abc"), this); + return new ABC(new ABCInputStream(new MemoryInputStream(Helper.readFile(file))), dummySwf, doABC2Tag, file, fileTitle); + } + + @Override + protected ABC doInBackground() throws Exception { + return open(fInputStream, sourceInfo.getFile(), sourceInfo.getFileTitle()); + } - CancellableWorker worker = new CancellableWorker() { - private boolean yestoall = false; + @Override + protected void done() { + stopWork(); + } + + }; + worker = abcWorker; + } else if (sourceInfo.getKind() == OpenableSourceKind.SWF) { + final String[] yesno = new String[]{AppStrings.translate("button.yes"), AppStrings.translate("button.no"), AppStrings.translate("button.yes.all"), AppStrings.translate("button.no.all")}; - private boolean notoall = false; + CancellableWorker swfWorker = new CancellableWorker() { + private boolean yestoall = false; - private SWF open(InputStream is, String file, String fileTitle) throws IOException, InterruptedException { - final CancellableWorker worker = this; - String shortName = fileTitle != null ? fileTitle : file; - 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()); + private boolean notoall = false; - SWF swf = new SWF(is, file, fileTitle, new ProgressListener() { - @Override - public void progress(int p) { - startWork(AppStrings.translate("work.reading.swf"), p, worker); - } - }, Configuration.parallelSpeedUp.get(), false, true, new UrlResolver() { - @Override - public SWF resolveUrl(final String url) { - 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 (opt == 3) { - notoall = true; - } + private SWF open(InputStream is, String file, String fileTitle) throws IOException, InterruptedException { + final CancellableWorker worker = this; + String shortName = fileTitle != null ? fileTitle : file; + 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()); + + SWF swf = new SWF(is, file, fileTitle, new ProgressListener() { + @Override + public void progress(int p) { + startWork(AppStrings.translate("work.reading.swf"), p, worker); } - - if (yestoall) { - opt = 0; // yes - } else if (notoall) { - opt = 1; // no - } - - if (opt == 1) //no - { - return null; - } - - if (url.startsWith("http://") || url.startsWith("https://")) { - try { - URL u = new URL(url); - return open(u.openStream(), null, url); //? - } catch (Exception ex) { - //ignore + }, Configuration.parallelSpeedUp.get(), false, true, new UrlResolver() { + @Override + public SWF resolveUrl(final String url) { + 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 (opt == 3) { + notoall = true; + } } - } else { - File swf = new File(new File(file).getParentFile(), url); - if (swf.exists()) { + + if (yestoall) { + opt = 0; // yes + } else if (notoall) { + opt = 1; // no + } + + if (opt == 1) //no + { + return null; + } + + if (url.startsWith("http://") || url.startsWith("https://")) { try { - return open(new FileInputStream(swf), swf.getAbsolutePath(), swf.getName()); + URL u = new URL(url); + return open(u.openStream(), null, url); //? } catch (Exception ex) { //ignore } - } - // try .gfx if .swf failed - if (url.endsWith(".swf")) { - File gfx = new File(new File(file).getParentFile(), url.substring(0, url.length() - 4) + ".gfx"); - if (gfx.exists()) { + } else { + File swf = new File(new File(file).getParentFile(), url); + if (swf.exists()) { try { - return open(new FileInputStream(gfx), gfx.getAbsolutePath(), gfx.getName()); + return open(new FileInputStream(swf), swf.getAbsolutePath(), swf.getName()); } catch (Exception ex) { //ignore } } - } - } - Reference ret = new Reference<>(null); - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - - while (JOptionPane.YES_OPTION == ViewMessages.showConfirmDialog(getDefaultMessagesComponent(), AppStrings.translate("message.imported.swf.manually").replace("%url%", url), AppStrings.translate("error"), JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE)) { - - JFileChooser fc = new JFileChooser(); - fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get())); - FileFilter allSupportedFilter = new FileFilter() { - private final String[] supportedExtensions = new String[]{".swf", ".gfx"}; - - @Override - public boolean accept(File f) { - String name = f.getName().toLowerCase(Locale.ENGLISH); - for (String ext : supportedExtensions) { - if (name.endsWith(ext)) { - return true; - } - } - return f.isDirectory(); - } - - @Override - public String getDescription() { - String exts = Helper.joinStrings(supportedExtensions, "*%s", "; "); - return AppStrings.translate("filter.supported") + " (" + exts + ")"; - } - }; - fc.setFileFilter(allSupportedFilter); - FileFilter swfFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase(Locale.ENGLISH).endsWith(".swf")) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate("filter.swf"); - } - }; - fc.addChoosableFileFilter(swfFilter); - - FileFilter gfxFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase(Locale.ENGLISH).endsWith(".gfx")) || (f.isDirectory()); - } - - @Override - public String getDescription() { - return AppStrings.translate("filter.gfx"); - } - }; - fc.addChoosableFileFilter(gfxFilter); - fc.setAcceptAllFileFilterUsed(false); - int returnVal = fc.showOpenDialog(getDefaultMessagesComponent()); - if (returnVal == JFileChooser.APPROVE_OPTION) { - Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath()); - File selFile = Helper.fixDialogFile(fc.getSelectedFile()); + // try .gfx if .swf failed + if (url.endsWith(".swf")) { + File gfx = new File(new File(file).getParentFile(), url.substring(0, url.length() - 4) + ".gfx"); + if (gfx.exists()) { try { - ret.setVal(open(new FileInputStream(selFile), selFile.getAbsolutePath(), selFile.getName())); - break; + return open(new FileInputStream(gfx), gfx.getAbsolutePath(), gfx.getName()); } catch (Exception ex) { - //ignore; + //ignore } - } else { - break; } } } - }); - return ret.getVal(); - } - }, charset); - return swf; - } + Reference ret = new Reference<>(null); + View.execInEventDispatch(new Runnable() { + @Override + public void run() { - @Override - public SWF doInBackground() throws Exception { - return open(fInputStream, sourceInfo.getFile(), sourceInfo.getFileTitle()); - } - }; + while (JOptionPane.YES_OPTION == ViewMessages.showConfirmDialog(getDefaultMessagesComponent(), AppStrings.translate("message.imported.swf.manually").replace("%url%", url), AppStrings.translate("error"), JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE)) { + + JFileChooser fc = new JFileChooser(); + fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get())); + FileFilter allSupportedFilter = new FileFilter() { + private final String[] supportedExtensions = new String[]{".swf", ".gfx"}; + + @Override + public boolean accept(File f) { + String name = f.getName().toLowerCase(Locale.ENGLISH); + for (String ext : supportedExtensions) { + if (name.endsWith(ext)) { + return true; + } + } + return f.isDirectory(); + } + + @Override + public String getDescription() { + String exts = Helper.joinStrings(supportedExtensions, "*%s", "; "); + return AppStrings.translate("filter.supported") + " (" + exts + ")"; + } + }; + fc.setFileFilter(allSupportedFilter); + FileFilter swfFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase(Locale.ENGLISH).endsWith(".swf")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.swf"); + } + }; + fc.addChoosableFileFilter(swfFilter); + + FileFilter gfxFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase(Locale.ENGLISH).endsWith(".gfx")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.gfx"); + } + }; + fc.addChoosableFileFilter(gfxFilter); + fc.setAcceptAllFileFilterUsed(false); + int returnVal = fc.showOpenDialog(getDefaultMessagesComponent()); + if (returnVal == JFileChooser.APPROVE_OPTION) { + Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath()); + File selFile = Helper.fixDialogFile(fc.getSelectedFile()); + try { + ret.setVal(open(new FileInputStream(selFile), selFile.getAbsolutePath(), selFile.getName())); + break; + } catch (Exception ex) { + //ignore; + } + } else { + break; + } + } + } + }); + return ret.getVal(); + } + }, charset); + return swf; + } + + @Override + public SWF doInBackground() throws Exception { + return open(fInputStream, sourceInfo.getFile(), sourceInfo.getFileTitle()); + } + }; + worker = swfWorker; + } if (loadingDialog != null) { - loadingDialog.setWroker(worker); + loadingDialog.setWorker(worker); } worker.execute(); @@ -1087,67 +1126,72 @@ public class Main { } result.sourceInfo = sourceInfo; - for (SWF swf : result) { - logger.log(Level.INFO, ""); - logger.log(Level.INFO, "== File information =="); - logger.log(Level.INFO, "Size: {0}", Helper.formatFileSize(swf.fileSize)); - logger.log(Level.INFO, "Flash version: {0}", swf.version); - int width = (int) ((swf.displayRect.Xmax - swf.displayRect.Xmin) / SWF.unitDivisor); - 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 (Openable openable : result) { - swf.swfList = result; - swf.addEventListener(new EventListener() { - @Override - public void handleExportingEvent(String type, int index, int count, Object data) { - String text = AppStrings.translate("work.exporting"); - if (type != null && type.length() > 0) { - text += " " + type; + openable.setOpenableList(result); + + if (openable instanceof SWF) { + SWF swf = (SWF) openable; + logger.log(Level.INFO, ""); + logger.log(Level.INFO, "== File information =="); + logger.log(Level.INFO, "Size: {0}", Helper.formatFileSize(swf.fileSize)); + logger.log(Level.INFO, "Flash version: {0}", swf.version); + int width = (int) ((swf.displayRect.Xmax - swf.displayRect.Xmin) / SWF.unitDivisor); + 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); + + swf.addEventListener(new EventListener() { + @Override + public void handleExportingEvent(String type, int index, int count, Object data) { + String text = AppStrings.translate("work.exporting"); + if (type != null && type.length() > 0) { + text += " " + type; + } + + continueWork(text + " " + index + "/" + count + " " + data); } - continueWork(text + " " + index + "/" + count + " " + data); - } + @Override + public void handleExportedEvent(String type, int index, int count, Object data) { + String text = AppStrings.translate("work.exported"); + if (type != null && type.length() > 0) { + text += " " + type; + } - @Override - public void handleExportedEvent(String type, int index, int count, Object data) { - String text = AppStrings.translate("work.exported"); - if (type != null && type.length() > 0) { - text += " " + type; + continueWork(text + " " + index + "/" + count + " " + data); } - continueWork(text + " " + index + "/" + count + " " + data); - } - - @Override - public void handleEvent(String event, Object data) { - if (event.equals("exporting") || event.equals("exported")) { - throw new Error("Event is not supported by this handler."); + @Override + public void handleEvent(String event, Object data) { + if (event.equals("exporting") || event.equals("exported")) { + throw new Error("Event is not supported by this handler."); + } + if (event.equals("getVariables")) { + continueWork(AppStrings.translate("work.gettingvariables") + "..." + (String) data); + } + if (event.equals("deobfuscate")) { + continueWork(AppStrings.translate("work.deobfuscating") + "..." + (String) data); + } + if (event.equals("deobfuscate_pcode")) { + startWork(AppStrings.translate("work.deobfuscating_pcode") + "..." + (String) data, deobfuscatePCodeWorker); + } + if (event.equals("rename")) { + continueWork(AppStrings.translate("work.renaming") + "..." + (String) data); + } + if (event.equals("importing_as")) { + startWork(AppStrings.translate("work.importing_as") + "..." + (String) data, importWorker); + } } - if (event.equals("getVariables")) { - continueWork(AppStrings.translate("work.gettingvariables") + "..." + (String) data); - } - if (event.equals("deobfuscate")) { - continueWork(AppStrings.translate("work.deobfuscating") + "..." + (String) data); - } - if (event.equals("deobfuscate_pcode")) { - startWork(AppStrings.translate("work.deobfuscating_pcode") + "..." + (String) data, deobfuscatePCodeWorker); - } - if (event.equals("rename")) { - continueWork(AppStrings.translate("work.renaming") + "..." + (String) data); - } - if (event.equals("importing_as")) { - startWork(AppStrings.translate("work.importing_as") + "..." + (String) data, importWorker); - } - } - }); + }); + } } return result; } - public static void saveFile(SWF swf, String outfile) throws IOException { - saveFile(swf, outfile, SaveFileMode.SAVE, null); + public static void saveFile(Openable openable, String outfile) throws IOException { + saveFile(openable, outfile, SaveFileMode.SAVE, null); } public static void saveFileToExe(SWF swf, ExeExportMode exeExportMode, File tmpFile) throws IOException { @@ -1206,22 +1250,22 @@ public class Main { } } - public static void saveFile(SWF swf, String outfile, SaveFileMode mode, ExeExportMode exeExportMode) throws IOException { + public static void saveFile(Openable openable, String outfile, SaveFileMode mode, ExeExportMode exeExportMode) throws IOException { File savedFile = new File(outfile); startSaving(savedFile); - if (mode == SaveFileMode.SAVEAS && swf.swfList != null /*SWF in binarydata has null*/ && !swf.swfList.isBundle()) { - swf.setFile(outfile); - swf.swfList.sourceInfo.setFile(outfile); + if (mode == SaveFileMode.SAVEAS && openable.getOpenableList() != null /*SWF in binarydata has null*/ && !openable.getOpenableList().isBundle()) { + openable.setFile(outfile); + openable.getOpenableList().sourceInfo.setFile(outfile); } File outfileF = new File(outfile); File tmpFile = new File(outfile + ".tmp"); try { if (mode == SaveFileMode.EXE) { - saveFileToExe(swf, exeExportMode, tmpFile); + saveFileToExe((SWF)openable, exeExportMode, tmpFile); } else { try ( FileOutputStream fos = new FileOutputStream(tmpFile); BufferedOutputStream bos = new BufferedOutputStream(fos)) { - swf.saveTo(bos); + openable.saveTo(bos); } } } catch (Throwable t) { @@ -1249,39 +1293,39 @@ public class Main { private static class OpenFileWorker extends SwingWorker { - private final SWFSourceInfo[] sourceInfos; + private final OpenableSourceInfo[] sourceInfos; private final Runnable executeAfterOpen; private final int[] reloadIndices; - public OpenFileWorker(SWFSourceInfo sourceInfo) { + public OpenFileWorker(OpenableSourceInfo sourceInfo) { this(sourceInfo, -1); } - public OpenFileWorker(SWFSourceInfo sourceInfo, int reloadIndex) { + public OpenFileWorker(OpenableSourceInfo sourceInfo, int reloadIndex) { this(sourceInfo, null, reloadIndex); } - public OpenFileWorker(SWFSourceInfo sourceInfo, Runnable executeAfterOpen) { + public OpenFileWorker(OpenableSourceInfo sourceInfo, Runnable executeAfterOpen) { this(sourceInfo, executeAfterOpen, -1); } - public OpenFileWorker(SWFSourceInfo sourceInfo, Runnable executeAfterOpen, int reloadIndex) { - this.sourceInfos = new SWFSourceInfo[]{sourceInfo}; + public OpenFileWorker(OpenableSourceInfo sourceInfo, Runnable executeAfterOpen, int reloadIndex) { + this.sourceInfos = new OpenableSourceInfo[]{sourceInfo}; this.executeAfterOpen = executeAfterOpen; this.reloadIndices = new int[]{reloadIndex}; } - public OpenFileWorker(SWFSourceInfo[] sourceInfos) { + public OpenFileWorker(OpenableSourceInfo[] sourceInfos) { this(sourceInfos, null, null); } - public OpenFileWorker(SWFSourceInfo[] sourceInfos, Runnable executeAfterOpen) { + public OpenFileWorker(OpenableSourceInfo[] sourceInfos, Runnable executeAfterOpen) { this(sourceInfos, executeAfterOpen, null); } - public OpenFileWorker(SWFSourceInfo[] sourceInfos, Runnable executeAfterOpen, int[] reloadIndices) { + public OpenFileWorker(OpenableSourceInfo[] sourceInfos, Runnable executeAfterOpen, int[] reloadIndices) { this.sourceInfos = sourceInfos; this.executeAfterOpen = executeAfterOpen; int[] indices = new int[sourceInfos.length]; @@ -1295,13 +1339,14 @@ public class Main { protected Object doInBackground() throws Exception { boolean first = true; SWF firstSWF = null; + Openable firstOpenable = null; for (int index = 0; index < sourceInfos.length; index++) { - SWFSourceInfo sourceInfo = sourceInfos[index]; - SWFList swfs = null; + OpenableSourceInfo sourceInfo = sourceInfos[index]; + OpenableList openables = null; try { Main.startWork(AppStrings.translate("work.reading.swf") + "...", null); try { - swfs = parseSWF(sourceInfo); + openables = parseOpenable(sourceInfo); } catch (ExecutionException ex) { Throwable cause = ex.getCause(); if (cause instanceof SwfOpenException) { @@ -1324,11 +1369,14 @@ public class Main { continue; } - final SWFList swfs1 = swfs; + final OpenableList openables1 = openables; final boolean first1 = first; first = false; - if (firstSWF == null && swfs1.size() > 0) { - firstSWF = swfs1.get(0); + if (firstOpenable == null && openables1.size() > 0) { + firstOpenable = openables1.get(0); + } + if (firstSWF == null && openables1.size() > 0 && (openables1.get(0) instanceof SWF)) { + firstSWF = (SWF) openables1.get(0); } final int findex = index; @@ -1337,9 +1385,9 @@ public class Main { Main.startWork(AppStrings.translate("work.creatingwindow") + "...", null); ensureMainFrame(); if (reloadIndices[findex] > -1) { - mainFrame.getPanel().loadSwfAtPos(swfs1, reloadIndices[findex]); + mainFrame.getPanel().loadSwfAtPos(openables1, reloadIndices[findex]); } else { - mainFrame.getPanel().load(swfs1, first1); + mainFrame.getPanel().load(openables1, first1); } }); } catch (Exception ex) { @@ -1351,6 +1399,7 @@ public class Main { shouldCloseWhenClosingLoadingDialog = false; final SWF fswf = firstSWF; + final Openable fopenable = firstOpenable; View.execInEventDispatch(() -> { if (mainFrame != null) { mainFrame.setVisible(true); @@ -1358,18 +1407,18 @@ public class Main { Main.stopWork(); - if (mainFrame != null && Configuration.gotoMainClassOnStartup.get()) { + if (mainFrame != null && Configuration.gotoMainClassOnStartup.get() && fswf != null) { mainFrame.getPanel().gotoDocumentClass(fswf); } - if (mainFrame != null && fswf != null) { - SwfSpecificConfiguration swfConf = Configuration.getSwfSpecificConfiguration(fswf.getShortPathTitle()); + if (mainFrame != null && fopenable != null) { + SwfSpecificConfiguration swfConf = Configuration.getSwfSpecificConfiguration(fopenable.getShortPathTitle()); String resourcesPathStr = null; String tagListPathStr = null; if (swfConf != null) { resourcesPathStr = swfConf.lastSelectedPath; } - SwfSpecificCustomConfiguration swfCustomConf = Configuration.getSwfSpecificCustomConfiguration(fswf.getShortPathTitle()); + SwfSpecificCustomConfiguration swfCustomConf = Configuration.getSwfSpecificCustomConfiguration(fopenable.getShortPathTitle()); if (swfCustomConf != null) { resourcesPathStr = swfCustomConf.getCustomData(CustomConfigurationKeys.KEY_LAST_SELECTED_PATH_RESOURCES, resourcesPathStr); tagListPathStr = swfCustomConf.getCustomData(CustomConfigurationKeys.KEY_LAST_SELECTED_PATH_TAGLIST, null); @@ -1406,7 +1455,7 @@ public class Main { sourceInfos.remove(i); } } - SWFSourceInfo[] sourceInfosCopy = new SWFSourceInfo[sourceInfos.size()]; + OpenableSourceInfo[] sourceInfosCopy = new OpenableSourceInfo[sourceInfos.size()]; sourceInfos.toArray(sourceInfosCopy); sourceInfos.clear(); openFile(sourceInfosCopy); @@ -1472,7 +1521,7 @@ public class Main { return OpenFileResult.NOT_FOUND; } swfFile = file.getCanonicalPath(); - SWFSourceInfo sourceInfo = new SWFSourceInfo(null, swfFile, fileTitle); + OpenableSourceInfo sourceInfo = new OpenableSourceInfo(null, swfFile, fileTitle); OpenFileResult openResult = openFile(sourceInfo); return openResult; } catch (IOException ex) { @@ -1481,31 +1530,31 @@ public class Main { } } - public static OpenFileResult openFile(SWFSourceInfo sourceInfo) { + public static OpenFileResult openFile(OpenableSourceInfo sourceInfo) { View.checkAccess(); - return openFile(new SWFSourceInfo[]{sourceInfo}); + return openFile(new OpenableSourceInfo[]{sourceInfo}); } - public static OpenFileResult openFile(SWFSourceInfo sourceInfo, Runnable executeAfterOpen) { + public static OpenFileResult openFile(OpenableSourceInfo sourceInfo, Runnable executeAfterOpen) { View.checkAccess(); - return openFile(new SWFSourceInfo[]{sourceInfo}, executeAfterOpen); + return openFile(new OpenableSourceInfo[]{sourceInfo}, executeAfterOpen); } - public static OpenFileResult openFile(SWFSourceInfo sourceInfo, Runnable executeAfterOpen, int reloadIndex) { + public static OpenFileResult openFile(OpenableSourceInfo sourceInfo, Runnable executeAfterOpen, int reloadIndex) { View.checkAccess(); - return openFile(new SWFSourceInfo[]{sourceInfo}, executeAfterOpen, new int[]{reloadIndex}); + return openFile(new OpenableSourceInfo[]{sourceInfo}, executeAfterOpen, new int[]{reloadIndex}); } - public static OpenFileResult openFile(SWFSourceInfo[] newSourceInfos) { + public static OpenFileResult openFile(OpenableSourceInfo[] newSourceInfos) { View.checkAccess(); return openFile(newSourceInfos, null); } - public static OpenFileResult openFile(SWFSourceInfo[] newSourceInfos, Runnable executeAfterOpen) { + public static OpenFileResult openFile(OpenableSourceInfo[] newSourceInfos, Runnable executeAfterOpen) { View.checkAccess(); return openFile(newSourceInfos, executeAfterOpen, null); @@ -1524,9 +1573,9 @@ public class Main { } String ext = newFileDialog.isGfx() ? "gfx" : "swf"; String fileTitle = AppStrings.translate("new.filename") + "." + ext; - SWFSourceInfo sourceInfo = new SWFSourceInfo(fileTitle); + OpenableSourceInfo sourceInfo = new OpenableSourceInfo(fileTitle); sourceInfos.add(sourceInfo); - SWFList list = new SWFList(); + OpenableList list = new OpenableList(); list.sourceInfo = sourceInfo; SWF swf = new SWF(); swf.setFile(null); @@ -1559,7 +1608,7 @@ public class Main { swf.frameCount = 1; swf.hasEndTag = true; list.add(swf); - swf.swfList = list; + swf.openableList = list; mainFrame.getPanel().load(list, true); //select first frame @@ -1567,7 +1616,7 @@ public class Main { } } - public static OpenFileResult openFile(SWFSourceInfo[] newSourceInfos, Runnable executeAfterOpen, int[] reloadIndices) { + public static OpenFileResult openFile(OpenableSourceInfo[] newSourceInfos, Runnable executeAfterOpen, int[] reloadIndices) { View.checkAccess(); if (mainFrame != null && !Configuration.openMultipleFiles.get()) { @@ -1581,7 +1630,7 @@ public class Main { loadingDialog.setVisible(true); for (int i = 0; i < newSourceInfos.length; i++) { - SWFSourceInfo si = newSourceInfos[i]; + OpenableSourceInfo si = newSourceInfos[i]; String fileName = si.getFile(); if (fileName != null) { Configuration.addRecentFile(fileName); @@ -1614,14 +1663,14 @@ public class Main { return OpenFileResult.OK; } - public static void closeFile(SWFList swf) { + public static void closeFile(OpenableList openableList) { View.checkAccess(); - sourceInfos.remove(swf.sourceInfo); - mainFrame.getPanel().close(swf); + sourceInfos.remove(openableList.sourceInfo); + mainFrame.getPanel().close(openableList); } - public static void reloadFile(SWFList swf) { + public static void reloadFile(OpenableList swf) { View.checkAccess(); openFile(swf.sourceInfo, null, sourceInfos.indexOf(swf.sourceInfo)); @@ -1629,7 +1678,7 @@ public class Main { public static void reloadFile(File file) { for (int i = 0; i < sourceInfos.size(); i++) { - SWFSourceInfo info = sourceInfos.get(i); + OpenableSourceInfo info = sourceInfos.get(i); if (info.getFile() == null) { continue; } @@ -1655,15 +1704,15 @@ public class Main { return closeResult; } - public static boolean saveFileDialog(SWF swf, final SaveFileMode mode) { + public static boolean saveFileDialog(Openable openable, final SaveFileMode mode) { JFileChooser fc = new JFileChooser(); fc.setCurrentDirectory(new File(Configuration.lastSaveDir.get())); String ext = ".swf"; switch (mode) { case SAVE: case SAVEAS: - if (swf.getFile() != null) { - ext = Path.getExtension(swf.getFile()); + if (openable.getFile() != null) { + ext = Path.getExtension(openable.getFile()); } break; case EXE: @@ -1695,6 +1744,18 @@ public class Main { } }; + FileFilter abcFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase(Locale.ENGLISH).endsWith(".abc")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.abc"); + } + }; + ExeExportMode exeExportMode = null; if (mode == SaveFileMode.EXE) { exeExportMode = Configuration.exeExportMode.get(); @@ -1734,12 +1795,14 @@ public class Main { } }; fc.setFileFilter(exeFilter); - } else if (swf.gfx) { + } else if ((openable instanceof SWF) && ((SWF)openable).gfx) { fc.addChoosableFileFilter(swfFilter); fc.setFileFilter(gfxFilter); - } else { + } else if (openable instanceof SWF) { fc.setFileFilter(swfFilter); fc.addChoosableFileFilter(gfxFilter); + } else if (openable instanceof ABC) { + fc.setFileFilter(abcFilter); } final String extension = ext; fc.setAcceptAllFileFilterUsed(false); @@ -1752,15 +1815,15 @@ public class Main { if (!fileName.toLowerCase(Locale.ENGLISH).endsWith(extension)) { fileName += extension; } - swf.gfx = false; + ((SWF)openable).gfx = false; } if (selFilter == gfxFilter) { if (!fileName.toLowerCase(Locale.ENGLISH).endsWith(".gfx")) { fileName += ".gfx"; } - swf.gfx = true; + ((SWF)openable).gfx = true; } - Main.saveFile(swf, fileName, mode, exeExportMode); + Main.saveFile(openable, fileName, mode, exeExportMode); Configuration.lastSaveDir.set(file.getParentFile().getAbsolutePath()); return true; } catch (Exception | OutOfMemoryError | StackOverflowError ex) { @@ -1814,7 +1877,7 @@ public class Main { } fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get())); FileFilter allSupportedFilter = new FileFilter() { - private final String[] supportedExtensions = new String[]{".swf", ".gfx", ".swc", ".zip", ".iggy"}; + private final String[] supportedExtensions = new String[]{".swf", ".gfx", ".swc", ".zip", ".iggy", ".abc"}; @Override public boolean accept(File f) { @@ -1885,6 +1948,19 @@ public class Main { } }; fc.addChoosableFileFilter(iggyFilter); + + FileFilter abcFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase(Locale.ENGLISH).endsWith(".abc")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return AppStrings.translate("filter.abc"); + } + }; + fc.addChoosableFileFilter(abcFilter); FileFilter zipFilter = new FileFilter() { @Override @@ -2031,7 +2107,7 @@ public class Main { continue; } - for (SWFSourceInfo info : sourceInfos) { + for (OpenableSourceInfo info : sourceInfos) { final String infoFile = info.getFile(); if (infoFile != null && new File(infoFile).equals(fullPath)) { View.execInEventDispatchLater(new Runnable() { @@ -2074,7 +2150,7 @@ public class Main { @Override public void onLoaderBytes(String clientId, byte[] data) { String hash = md5(data); - for (SWFList sl : Main.getMainFrame().getPanel().getSwfs()) { + for (OpenableList sl : Main.getMainFrame().getPanel().getSwfs()) { for (int s = 0; s < sl.size(); s++) { String t = sl.get(s).getFileTitle(); if (t == null) { @@ -2095,7 +2171,7 @@ public class Main { View.execInEventDispatch(new Runnable() { @Override public void run() { - openFile(new SWFSourceInfo(null, tfile, titleWithHash)); + openFile(new OpenableSourceInfo(null, tfile, titleWithHash)); } }); } catch (IOException ex) { @@ -2445,10 +2521,10 @@ public class Main { } } } - SWFSourceInfo[] sourceInfos = new SWFSourceInfo[exfiles.size()]; + OpenableSourceInfo[] sourceInfos = new OpenableSourceInfo[exfiles.size()]; for (int i = 0; i < exfiles.size(); i++) { String extitle = extitles.get(i); - sourceInfos[i] = new SWFSourceInfo(null, exfiles.get(i), extitle == null || extitle.isEmpty() ? null : extitle); + sourceInfos[i] = new OpenableSourceInfo(null, exfiles.get(i), extitle == null || extitle.isEmpty() ? null : extitle); } if (sourceInfos.length > 0) { openingFiles = true; @@ -2559,7 +2635,7 @@ public class Main { searchResultsStorage.save(); } catch (IOException ex) { //ignore - } + } Configuration.saveConfig(); if (mainFrame != null && mainFrame.getPanel() != null) { mainFrame.getPanel().unloadFlashPlayer(); diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java index fc750d410..d2ae46edb 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java @@ -19,8 +19,7 @@ package com.jpexs.decompiler.flash.gui; import com.jpexs.debugger.flash.DebuggerCommands; import com.jpexs.decompiler.flash.ApplicationInfo; import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFBundle; -import com.jpexs.decompiler.flash.SWFSourceInfo; +import com.jpexs.decompiler.flash.OpenableSourceInfo; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.configuration.ConfigurationItemChangeListener; import com.jpexs.decompiler.flash.console.ContextMenuTools; @@ -28,7 +27,7 @@ import com.jpexs.decompiler.flash.gui.debugger.DebuggerTools; import com.jpexs.decompiler.flash.gui.helpers.CheckResources; import com.jpexs.decompiler.flash.search.ScriptSearchResult; import com.jpexs.decompiler.flash.tags.ABCContainerTag; -import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.decompiler.flash.treeitems.OpenableList; import com.jpexs.decompiler.flash.treeitems.TreeItem; import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.Cache; @@ -65,6 +64,8 @@ import javax.swing.JDialog; import javax.swing.JEditorPane; import javax.swing.JFrame; import javax.swing.JOptionPane; +import com.jpexs.decompiler.flash.Bundle; +import com.jpexs.decompiler.flash.treeitems.Openable; /** * @@ -76,7 +77,7 @@ public abstract class MainFrameMenu implements MenuBuilder { private KeyEventDispatcher keyEventDispatcher; - private SWF swf; + private Openable openable; private ConfigurationItemChangeListener configListenerAutoDeobfuscate; @@ -131,18 +132,18 @@ public abstract class MainFrameMenu implements MenuBuilder { return true; } - private boolean saveSwf(SWF swf) { + private boolean saveOpenable(Openable openable) { boolean saved = false; - if (swf != null) { - if (swf.swfList != null && swf.swfList.isBundle()) { - File savedFile = new File(swf.swfList.sourceInfo.getFile()); + if (openable != null) { + if (openable.getOpenableList() != null && openable.getOpenableList().isBundle()) { + File savedFile = new File(openable.getOpenableList().sourceInfo.getFile()); Main.startSaving(savedFile); - SWFBundle bundle = swf.swfList.bundle; + Bundle bundle = openable.getOpenableList().bundle; if (!bundle.isReadOnly()) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { - swf.saveTo(baos); - saved = bundle.putSWF(swf.getFileTitle(), new ByteArrayInputStream(baos.toByteArray())); + openable.saveTo(baos); + saved = bundle.putOpenable(openable.getFileTitle(), new ByteArrayInputStream(baos.toByteArray())); } catch (IOException ex) { Logger.getLogger(MainFrameMenu.class.getName()).log(Level.SEVERE, "Cannot save SWF", ex); } @@ -150,29 +151,30 @@ public abstract class MainFrameMenu implements MenuBuilder { ViewMessages.showMessageDialog(mainFrame.getWindow(), translate("error.readonly.cannotSave"), translate("error"), JOptionPane.ERROR_MESSAGE); } Main.stopSaving(savedFile); - } else if (swf.binaryData != null) { + } else if ((openable instanceof SWF) && ((SWF)openable).binaryData != null) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { - swf.saveTo(baos); + openable.saveTo(baos); + SWF swf = (SWF) openable; swf.binaryData.binaryData = new ByteArrayRange(baos.toByteArray()); swf.binaryData.setModified(true); - saved = saveSwf(swf.binaryData.getSwf()); //save parent swf + saved = saveOpenable(swf.binaryData.getSwf()); //save parent swf } catch (IOException ex) { Logger.getLogger(MainFrameMenu.class.getName()).log(Level.SEVERE, "Cannot save SWF", ex); } - } else if (swf.getFile() == null) { - saved = saveAs(swf, SaveFileMode.SAVEAS); + } else if (openable.getFile() == null) { + saved = saveAs(openable, SaveFileMode.SAVEAS); } else { try { - Main.saveFile(swf, swf.getFile()); + Main.saveFile(openable, openable.getFile()); saved = true; } catch (Exception | OutOfMemoryError | StackOverflowError ex) { Main.handleSaveError(ex); } } if (saved) { - swf.clearModified(); - mainFrame.getPanel().refreshTree(swf); + openable.clearModified(); + mainFrame.getPanel().refreshTree(openable); } } return saved; @@ -186,7 +188,7 @@ public abstract class MainFrameMenu implements MenuBuilder { if (Main.isWorking()) { return false; } - return saveSwf(swf); + return saveOpenable(openable); } protected boolean saveAsActionPerformed(ActionEvent evt) { @@ -194,11 +196,11 @@ public abstract class MainFrameMenu implements MenuBuilder { return false; } - if (swf != null) { - if (saveAs(swf, SaveFileMode.SAVEAS)) { - if (swf.swfList != null) { //binarydata won't clear modified on saveas - if (!isSwfReadOnly(swf)) { - swf.clearModified(); + if (openable != null) { + if (saveAs(openable, SaveFileMode.SAVEAS)) { + if (openable.getOpenableList() != null) { //binarydata won't clear modified on saveas + if (!isSwfReadOnly(openable)) { + openable.clearModified(); } } } @@ -209,15 +211,15 @@ public abstract class MainFrameMenu implements MenuBuilder { return false; } - private boolean isSwfReadOnly(SWF swf) { - return swf.swfList != null && swf.swfList.bundle != null && swf.swfList.bundle.isReadOnly(); + private boolean isSwfReadOnly(Openable openable) { + return openable.getOpenableList() != null && openable.getOpenableList().bundle != null && openable.getOpenableList().bundle.isReadOnly(); } - private boolean saveAs(SWF swf, SaveFileMode mode) { + private boolean saveAs(Openable openable, SaveFileMode mode) { View.checkAccess(); - if (Main.saveFileDialog(swf, mode)) { - updateComponents(swf); + if (Main.saveFileDialog(openable, mode)) { + updateComponents(openable); return true; } return false; @@ -228,8 +230,8 @@ public abstract class MainFrameMenu implements MenuBuilder { return; } - if (swf != null) { - saveAs(swf, SaveFileMode.EXE); + if (openable != null) { + saveAs(openable, SaveFileMode.EXE); } } @@ -238,11 +240,11 @@ public abstract class MainFrameMenu implements MenuBuilder { return; } - if (swf == null) { + if (openable == null) { return; } - Main.closeFile(swf.swfList); - swf = null; + Main.closeFile(openable.getOpenableList()); + openable = null; Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override @@ -257,10 +259,10 @@ public abstract class MainFrameMenu implements MenuBuilder { return false; } - if (swf != null) { + if (openable != null) { boolean result = Main.closeAll(); if (result) { - swf = null; + openable = null; Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override @@ -280,7 +282,7 @@ public abstract class MainFrameMenu implements MenuBuilder { return; } - mainFrame.getPanel().importText(swf); + mainFrame.getPanel().importText((SWF) openable); } protected void importScriptActionPerformed(ActionEvent evt) { @@ -288,28 +290,28 @@ public abstract class MainFrameMenu implements MenuBuilder { return; } - mainFrame.getPanel().importScript(swf); + mainFrame.getPanel().importScript((SWF) openable); } protected void importImagesActionPerformed(ActionEvent evt) { if (Main.isWorking()) { return; } - mainFrame.getPanel().importImage(swf); + mainFrame.getPanel().importImage((SWF) openable); } protected void importShapesActionPerformed(ActionEvent evt) { if (Main.isWorking()) { return; } - mainFrame.getPanel().importShape(swf, false); + mainFrame.getPanel().importShape((SWF) openable, false); } protected void importShapesNoFillActionPerformed(ActionEvent evt) { if (Main.isWorking()) { return; } - mainFrame.getPanel().importShape(swf, true); + mainFrame.getPanel().importShape((SWF) openable, true); } protected void importSymbolClassActionPerformed(ActionEvent evt) { @@ -317,7 +319,7 @@ public abstract class MainFrameMenu implements MenuBuilder { return; } - mainFrame.getPanel().importSymbolClass(swf); + mainFrame.getPanel().importSymbolClass((SWF) openable); } protected boolean exportAllActionPerformed(ActionEvent evt) { @@ -339,7 +341,7 @@ public abstract class MainFrameMenu implements MenuBuilder { protected boolean export(boolean onlySelected) { View.checkAccess(); - if (swf != null) { + if (openable != null) { mainFrame.getPanel().export(onlySelected); return true; } @@ -352,7 +354,7 @@ public abstract class MainFrameMenu implements MenuBuilder { return; } - mainFrame.getPanel().exportFla(swf); + mainFrame.getPanel().exportFla((SWF) openable); } protected void importXmlActionPerformed(ActionEvent evt) { @@ -386,8 +388,8 @@ public abstract class MainFrameMenu implements MenuBuilder { protected boolean search(ActionEvent evt, Boolean searchInText) { View.checkAccess(); - if (swf != null) { - mainFrame.getPanel().searchInActionScriptOrText(searchInText, swf, false); + if (openable != null) { + mainFrame.getPanel().searchInActionScriptOrText(searchInText, openable, false); return true; } @@ -395,7 +397,7 @@ public abstract class MainFrameMenu implements MenuBuilder { } protected boolean replaceActionPerformed(ActionEvent evt) { - if (swf != null) { + if (openable != null) { mainFrame.getPanel().replaceText(); return true; } @@ -421,7 +423,7 @@ public abstract class MainFrameMenu implements MenuBuilder { return; } - mainFrame.getPanel().renameOneIdentifier(swf); + mainFrame.getPanel().renameOneIdentifier((SWF) openable); } protected void renameColliding(ActionEvent evt) { @@ -431,7 +433,7 @@ public abstract class MainFrameMenu implements MenuBuilder { return; } - mainFrame.getPanel().renameColliding(swf); + mainFrame.getPanel().renameColliding(openable); } protected void renameInvalidIdentifiers(ActionEvent evt) { @@ -441,7 +443,7 @@ public abstract class MainFrameMenu implements MenuBuilder { return; } - mainFrame.getPanel().renameIdentifiers(swf); + mainFrame.getPanel().renameIdentifiers(openable); } protected void deobfuscationActionPerformed(ActionEvent evt) { @@ -463,7 +465,7 @@ public abstract class MainFrameMenu implements MenuBuilder { } protected void switchDebugger() { - DebuggerTools.switchDebugger(swf); + DebuggerTools.switchDebugger((SWF) openable); } protected void debuggerShowLogActionPerformed(ActionEvent evt) { @@ -471,7 +473,7 @@ public abstract class MainFrameMenu implements MenuBuilder { } protected void debuggerInjectLoader(ActionEvent evt) { - DebuggerTools.injectDebugLoader(swf); + DebuggerTools.injectDebugLoader((SWF) openable); refreshDecompiled(); } @@ -480,7 +482,7 @@ public abstract class MainFrameMenu implements MenuBuilder { rtd.setVisible(true); if (rtd.getValue() != null) { String fname = rtd.getValue(); - DebuggerTools.replaceTraceCalls(swf, fname); + DebuggerTools.replaceTraceCalls((SWF) openable, fname); mainFrame.getPanel().refreshDecompiled(); Configuration.lastDebuggerReplaceFunction.set(rtd.getValue()); } @@ -499,11 +501,17 @@ public abstract class MainFrameMenu implements MenuBuilder { } protected void removeNonScripts() { - mainFrame.getPanel().removeNonScripts(swf); + if (openable instanceof SWF) { + return; + } + mainFrame.getPanel().removeNonScripts((SWF) openable); } protected void removeExceptSelected() { - mainFrame.getPanel().removeExceptSelected(swf); + if (openable instanceof SWF) { + return; + } + mainFrame.getPanel().removeExceptSelected((SWF) openable); } protected void refreshDecompiled() { @@ -602,14 +610,17 @@ public abstract class MainFrameMenu implements MenuBuilder { } protected boolean reloadActionPerformed(ActionEvent evt) { - if (swf != null) { + if (openable != null) { if (!Configuration.showCloseConfirmation.get() || ViewMessages.showConfirmDialog(Main.getDefaultMessagesComponent(), translate("message.confirm.reload"), translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) { - if (swf.swfList == null) { - if (swf.binaryData != null) { - mainFrame.getPanel().loadFromBinaryTag(swf.binaryData); + if (openable.getOpenableList() == null) { + if (openable instanceof SWF) { + SWF swf = (SWF) openable; + if (swf.binaryData != null) { + mainFrame.getPanel().loadFromBinaryTag(swf.binaryData); + } } } else { - Main.reloadFile(swf.swfList); + Main.reloadFile(openable.getOpenableList()); } } } @@ -617,7 +628,7 @@ public abstract class MainFrameMenu implements MenuBuilder { } protected boolean reloadAllActionPerformed(ActionEvent evt) { - if (swf != null) { + if (openable != null) { if (!Configuration.showCloseConfirmation.get() || ViewMessages.showConfirmDialog(Main.getDefaultMessagesComponent(), translate("message.confirm.reloadAll"), translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) { Main.reloadApp(); } @@ -769,39 +780,47 @@ public abstract class MainFrameMenu implements MenuBuilder { } public void updateComponents() { - updateComponents(swf); + updateComponents(openable); } - public void updateComponents(SWF swf) { - this.swf = swf; + public void updateComponents(Openable openable) { + this.openable = openable; boolean isRunning = Main.isRunning(); boolean isDebugRunning = Main.isDebugRunning(); boolean isDebugPaused = Main.isDebugPaused(); boolean isRunningOrDebugging = isRunning || isDebugRunning; - boolean swfSelected = swf != null; + SWF swf = (openable instanceof SWF) ? (SWF) openable : null; + boolean openableSelected = openable != null; + boolean swfSelected = openable instanceof SWF; boolean isWorking = Main.isWorking(); List abcList = swf != null ? swf.getAbcList() : null; - boolean hasAbc = swfSelected && abcList != null && !abcList.isEmpty(); + boolean hasAbc = openableSelected && abcList != null && !abcList.isEmpty(); boolean hasDebugger = hasAbc && DebuggerTools.hasDebugger(swf); MainPanel mainPanel = mainFrame.getPanel(); boolean swfLoaded = mainPanel != null ? !mainPanel.getSwfs().isEmpty() : false; - boolean swfIsNew = swfSelected && swf.swfList != null && swf.swfList.sourceInfo.isEmpty(); + boolean swfIsNew = openableSelected && openable.getOpenableList() != null && openable.getOpenableList().sourceInfo.isEmpty(); boolean allSameSwf = true; if (mainPanel != null) { List items = mainPanel.getCurrentTree().getSelected(); SWF firstSwf = null; for (TreeItem item : items) { - if (item instanceof SWFList) { + if (item instanceof OpenableList) { allSameSwf = false; break; } if (firstSwf == null) { - firstSwf = item.getSwf(); + Openable fopenable = item.getOpenable(); + if (fopenable instanceof SWF) { + firstSwf = (SWF) fopenable; + } else { + allSameSwf = false; + break; + } } else { - if (item.getSwf() != firstSwf) { + if (item.getOpenable() != firstSwf) { allSameSwf = false; break; } @@ -811,39 +830,39 @@ public abstract class MainFrameMenu implements MenuBuilder { setMenuEnabled("_/open", !isWorking); setMenuEnabled("/file/open", !isWorking); - setMenuEnabled("_/save", swfSelected && !isWorking); - setMenuEnabled("/file/save", swfSelected && !isWorking); - setMenuEnabled("_/saveAs", swfSelected && !isWorking); - setMenuEnabled("/file/saveAs", swfSelected && !isWorking); + setMenuEnabled("_/save", openableSelected && !isWorking); + setMenuEnabled("/file/save", openableSelected && !isWorking); + setMenuEnabled("_/saveAs", openableSelected && !isWorking); + setMenuEnabled("/file/saveAs", openableSelected && !isWorking); setMenuEnabled("/file/saveAsExe", swfSelected && !isWorking); - setMenuEnabled("_/close", swfSelected && !isWorking); - setMenuEnabled("/file/close", swfSelected && !isWorking); + setMenuEnabled("_/close", openableSelected && !isWorking); + setMenuEnabled("/file/close", openableSelected && !isWorking); setMenuEnabled("_/closeAll", swfLoaded && !isWorking); setMenuEnabled("/file/closeAll", swfLoaded && !isWorking); - setMenuEnabled("/file/reload", swfSelected && !swfIsNew && !isWorking); + setMenuEnabled("/file/reload", openableSelected && !swfIsNew && !isWorking); - setMenuEnabled("/file/export", swfSelected); - setMenuEnabled("_/exportAll", swfSelected && !isWorking); - setMenuEnabled("/file/export/exportAll", swfSelected && !isWorking); + setMenuEnabled("/file/export", openableSelected); + setMenuEnabled("_/exportAll", openableSelected && !isWorking); + setMenuEnabled("/file/export/exportAll", openableSelected && !isWorking); setMenuEnabled("_/exportFla", swfSelected && !isWorking); - setMenuEnabled("/file/export/exportFla", allSameSwf && swfSelected && !isWorking); - setMenuEnabled("_/exportSelected", swfSelected && !isWorking); - setMenuEnabled("/file/export/exportSelected", swfSelected && !isWorking); + setMenuEnabled("/file/export/exportFla", allSameSwf && openableSelected && !isWorking); + setMenuEnabled("_/exportSelected", openableSelected && !isWorking); + setMenuEnabled("/file/export/exportSelected", openableSelected && !isWorking); setMenuEnabled("/file/export/exportXml", swfSelected && !isWorking); - setMenuEnabled("/file/import", swfSelected); + setMenuEnabled("/file/import", openableSelected); setMenuEnabled("/file/import/importText", allSameSwf && swfSelected && !isWorking); setMenuEnabled("/file/import/importScript", allSameSwf && swfSelected && !isWorking); setMenuEnabled("/file/import/importOther", allSameSwf && swfSelected && !isWorking); setMenuEnabled("/file/import/importXml", allSameSwf && swfSelected && !isWorking); - setMenuEnabled("/tools/deobfuscation", swfSelected); + setMenuEnabled("/tools/deobfuscation", openableSelected); setMenuEnabled("/tools/deobfuscation/renameOneIdentifier", swfSelected && !isWorking); setMenuEnabled("/tools/deobfuscation/renameInvalidIdentifiers", swfSelected && !isWorking); setMenuEnabled("/tools/deobfuscation/renameColliding", swfSelected && !isWorking); setMenuEnabled("/tools/deobfuscation/deobfuscation", hasAbc); - setMenuEnabled("/tools/search", swfSelected); + setMenuEnabled("/tools/search", openableSelected); setMenuEnabled("/tools/replace", swfSelected); setMenuEnabled("/tools/timeline", swfSelected); setMenuEnabled("/tools/showProxy", !isWorking); @@ -880,9 +899,9 @@ public abstract class MainFrameMenu implements MenuBuilder { StringBuilder titleBuilder = new StringBuilder(); titleBuilder.append(ApplicationInfo.applicationVerName); - if (Configuration.displayFileName.get() && swf != null) { + if (Configuration.displayFileName.get() && openable != null) { titleBuilder.append(" - "); - titleBuilder.append(swf.getFullPathTitle()); + titleBuilder.append(openable.getFullPathTitle()); } mainFrame.setTitle(titleBuilder.toString()); @@ -1212,12 +1231,12 @@ public abstract class MainFrameMenu implements MenuBuilder { addMenuItem("/debug/openTestSwfs", "Open test SWFs", "continue16", e -> { String path; - SWFSourceInfo[] sourceInfos = new SWFSourceInfo[2]; + OpenableSourceInfo[] sourceInfos = new OpenableSourceInfo[2]; String mainPath = Main.class.getProtectionDomain().getCodeSource().getLocation().getPath(); path = mainPath + "\\..\\..\\libsrc\\ffdec_lib\\testdata\\as2\\as2.swf"; - sourceInfos[0] = new SWFSourceInfo(null, path, null); + sourceInfos[0] = new OpenableSourceInfo(null, path, null); path = mainPath + "\\..\\..\\libsrc\\ffdec_lib\\testdata\\as3\\as3.swf"; - sourceInfos[1] = new SWFSourceInfo(null, path, null); + sourceInfos[1] = new OpenableSourceInfo(null, path, null); Main.openFile(sourceInfos); }, PRIORITY_MEDIUM, null, true, null, false); addMenuItem("/debug/createNewSwf", "Create new SWF", "continue16", e -> { @@ -1229,7 +1248,7 @@ public abstract class MainFrameMenu implements MenuBuilder { Logger.getLogger(MainFrameMenu.class.getName()).log(Level.SEVERE, null, ex); } - Main.openFile(new SWFSourceInfo(new ByteArrayInputStream(baos.toByteArray()), "new.swf", "New SWF")); + Main.openFile(new OpenableSourceInfo(new ByteArrayInputStream(baos.toByteArray()), "new.swf", "New SWF")); }, PRIORITY_MEDIUM, null, true, null, false); finishMenu("/debug"); } @@ -1303,7 +1322,7 @@ public abstract class MainFrameMenu implements MenuBuilder { SWF swf = Main.getMainFrame().getPanel().getCurrentSwf(); if (swf != null) { - List indices = Main.searchResultsStorage.getIndicesForSwf(swf); + List indices = Main.searchResultsStorage.getIndicesForOpenable(swf); int j = 0; for (int i = 0; i < indices.size(); i++) { final int fi = indices.get(i); @@ -1320,7 +1339,7 @@ public abstract class MainFrameMenu implements MenuBuilder { } else { sr = new SearchResultsDialog<>(Main.getDefaultDialogsOwner(), searched, Main.searchResultsStorage.isIgnoreCaseAt(fi), Main.searchResultsStorage.isRegExpAt(fi), listeners); } - sr.setResults(Main.searchResultsStorage.getSearchResultsAt(mainFrame.getPanel().getAllSwfs(), fi)); + sr.setResults(Main.searchResultsStorage.getSearchResultsAt(mainFrame.getPanel().getAllOpenablesAndSwfs(), fi)); sr.setVisible(true); Main.getMainFrame().getPanel().searchResultsDialogs.add(sr); }; @@ -1337,7 +1356,7 @@ public abstract class MainFrameMenu implements MenuBuilder { protected void clearRecentSearchesForCurrentSwfActionPerformed(ActionEvent evt) { if (ViewMessages.showConfirmDialog(Main.getDefaultMessagesComponent(), translate("message.confirm.recentSearches.clear"), translate("message.confirm"), JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) { - Main.searchResultsStorage.clearForSwf(swf); + Main.searchResultsStorage.clearForOpenable(openable); } } @@ -1381,17 +1400,17 @@ public abstract class MainFrameMenu implements MenuBuilder { } public boolean runActionPerformed(ActionEvent evt) { - Main.run(swf); + Main.run((SWF) openable); return true; } public boolean debugActionPerformed(ActionEvent evt) { - Main.runDebug(swf, false); + Main.runDebug((SWF) openable, false); return true; } public boolean debugPCodeActionPerformed(ActionEvent evt) { - Main.runDebug(swf, true); + Main.runDebug((SWF) openable, true); return true; } diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbon.java b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbon.java index e584a1854..767a4365d 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbon.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbon.java @@ -18,7 +18,7 @@ package com.jpexs.decompiler.flash.gui; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel; -import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.decompiler.flash.treeitems.OpenableList; import com.jpexs.helpers.Helper; import java.awt.BorderLayout; import java.awt.Color; @@ -129,7 +129,7 @@ public final class MainFrameRibbon extends AppRibbonFrame { StringBuilder sbt = new StringBuilder(); boolean first = true; - for (SWFList swf : panel.getSwfs()) { + for (OpenableList swf : panel.getSwfs()) { if (!first) { sb.append(File.pathSeparator); sbt.append(File.pathSeparator); diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java index e31ce77ac..906187e58 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java @@ -17,8 +17,10 @@ package com.jpexs.decompiler.flash.gui; import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.search.ScriptSearchResult; +import com.jpexs.decompiler.flash.treeitems.Openable; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; @@ -170,8 +172,9 @@ public class MainFrameRibbonMenu extends MainFrameMenu { String groupName = translate("menu.recentSearches"); searchHistoryPanel.addButtonGroup(groupName); - SWF swf = Main.getMainFrame().getPanel().getCurrentSwf(); - List indices = Main.searchResultsStorage.getIndicesForSwf(swf); + Openable openable = Main.getMainFrame().getPanel().getCurrentOpenable(); + SWF swf = (openable instanceof SWF) ? (SWF) openable : ((ABC)openable).getSwf(); + List indices = Main.searchResultsStorage.getIndicesForOpenable(openable); int height = 0; height = searchHistoryPanel.getInsets().top + searchHistoryPanel.getInsets().bottom + 6/*groupInset top*/ + new JLabel(groupName).getPreferredSize().height + 4 /*layoutGap*/; @@ -196,7 +199,7 @@ public class MainFrameRibbonMenu extends MainFrameMenu { } else { sr = new SearchResultsDialog<>(Main.getDefaultDialogsOwner(), searched, Main.searchResultsStorage.isIgnoreCaseAt(fi), Main.searchResultsStorage.isRegExpAt(fi), listeners); } - sr.setResults(Main.searchResultsStorage.getSearchResultsAt(Main.getMainFrame().getPanel().getAllSwfs(), fi)); + sr.setResults(Main.searchResultsStorage.getSearchResultsAt(Main.getMainFrame().getPanel().getAllOpenablesAndSwfs(), fi)); sr.setVisible(true); Main.getMainFrame().getPanel().searchResultsDialogs.add(sr); }); diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 830b57ac4..2160c3ef6 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -22,8 +22,7 @@ import com.jpexs.decompiler.flash.DecompilerPool; import com.jpexs.decompiler.flash.EventListener; import com.jpexs.decompiler.flash.ReadOnlyTagList; import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SWFBundle; -import com.jpexs.decompiler.flash.SWFSourceInfo; +import com.jpexs.decompiler.flash.OpenableSourceInfo; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.RenameType; import com.jpexs.decompiler.flash.abc.ScriptPack; @@ -170,7 +169,7 @@ import com.jpexs.decompiler.flash.timeline.Timeline; import com.jpexs.decompiler.flash.timeline.Timelined; import com.jpexs.decompiler.flash.treeitems.FolderItem; import com.jpexs.decompiler.flash.treeitems.HeaderItem; -import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.decompiler.flash.treeitems.OpenableList; import com.jpexs.decompiler.flash.treeitems.TreeItem; import com.jpexs.decompiler.flash.types.BUTTONRECORD; import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA; @@ -281,6 +280,8 @@ import javax.swing.plaf.basic.BasicTreeUI; import javax.swing.tree.DefaultTreeSelectionModel; import javax.swing.tree.TreePath; import jsyntaxpane.DefaultSyntaxKit; +import com.jpexs.decompiler.flash.Bundle; +import com.jpexs.decompiler.flash.treeitems.Openable; /** * @@ -290,7 +291,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se private final MainFrame mainFrame; - private final ObservableList swfs; + private final ObservableList openables; private final JPanel welcomePanel; @@ -451,20 +452,20 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } public void moveSwfListUpDown(TreeItem item, boolean up) { - SWFList swfList = null; + OpenableList swfList = null; if (item instanceof SWF) { SWF swf = (SWF) item; - if (swf.swfList != null && !swf.swfList.isBundle() && swf.swfList.size() == 1) { - swfList = swf.swfList; + if (swf.openableList != null && !swf.openableList.isBundle() && swf.openableList.size() == 1) { + swfList = swf.openableList; } else { return; } - } else if (item instanceof SWFList) { - swfList = (SWFList) item; + } else if (item instanceof OpenableList) { + swfList = (OpenableList) item; } else { return; } - int index = swfs.indexOf(swfList); + int index = openables.indexOf(swfList); List> expandedTagTree = View.getExpandedNodes(tagTree); List> expandedTagListTree = View.getExpandedNodes(tagListTree); @@ -473,12 +474,12 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (index <= 0) { return; } - swfs.move(index, index - 1); + openables.move(index, index - 1); } else { - if (index < 0 || index >= swfs.size() - 1) { + if (index < 0 || index >= openables.size() - 1) { return; } - swfs.move(index, index + 2); + openables.move(index, index + 2); } View.expandTreeNodes(tagTree, expandedTagTree); View.expandTreeNodes(tagListTree, expandedTagListTree); @@ -552,7 +553,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se WeakReference ref = orderedClipboard.get(i); TreeItem item = ref.get(); if (item != null) { - if (item.getSwf() == null) { + if (item.getOpenable() == null) { orderedClipboard.remove(i); clipboard.remove(item); } @@ -836,7 +837,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se mainFrame.setTitle(ApplicationInfo.applicationVerName); setLayout(new BorderLayout()); - swfs = new ObservableList<>(); + openables = new ObservableList<>(); detailPanel = new JPanel(); detailPanel.setLayout(new CardLayout()); @@ -1107,7 +1108,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se updateUi(); - this.swfs.addCollectionChangedListener((e) -> { + this.openables.addCollectionChangedListener((e) -> { AbstractTagTreeModel ttm = tagTree.getModel(); if (ttm != null) { if (getCurrentSwf() == null) { @@ -1119,8 +1120,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (e.getAction() == CollectionChangedAction.RESET) { tagTree.expandFirstLevelNodes(); } else if (e.getAction() == CollectionChangedAction.ADD) { - SWFList list = e.getNewItem(); - if (!list.isBundle() && list.swfs.size() == 1) { + OpenableList list = e.getNewItem(); + if (!list.isBundle() && list.items.size() == 1) { tagTree.expandPath(tagTree.getModel().getTreePath(list.get(0))); } else { tagTree.expandPath(tagTree.getModel().getTreePath(e.getNewItem())); @@ -1140,8 +1141,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (e.getAction() == CollectionChangedAction.RESET) { tagListTree.expandFirstLevelNodes(); } else if (e.getAction() == CollectionChangedAction.ADD) { - SWFList list = e.getNewItem(); - if (!list.isBundle() && list.swfs.size() == 1) { + OpenableList list = e.getNewItem(); + if (!list.isBundle() && list.items.size() == 1) { tagListTree.expandPath(tagListTree.getModel().getTreePath(list.get(0))); } else { tagListTree.expandPath(tagListTree.getModel().getTreePath(e.getNewItem())); @@ -1160,15 +1161,17 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (e.getAction() == CollectionChangedAction.RESET) { dumpTree.expandFirstLevelNodes(); } else if (e.getAction() == CollectionChangedAction.ADD) { - SWFList list = e.getNewItem(); - for (SWF dswf : list) { - dumpTree.expandSwfNode(dswf); + OpenableList list = e.getNewItem(); + for (Openable dopenable : list) { + if (dopenable instanceof SWF) { + dumpTree.expandSwfNode((SWF) dopenable); + } } } } } - if (swfs.isEmpty()) { + if (openables.isEmpty()) { tagTree.setUI(new BasicTreeUI() { { setHashColor(Color.gray); @@ -1211,12 +1214,18 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } public void resetAllTimelines() { - List swfsLists = new ArrayList<>(swfs); + List openableLists = new ArrayList<>(openables); List allSwfs = new ArrayList<>(); - for (SWFList swfList : swfsLists) { - allSwfs.addAll(swfList); - for (SWF swf : swfList) { - Main.populateSwfs(swf, allSwfs); + for (OpenableList openableList : openableLists) { + for (Openable openable : openableList) { + if (openable instanceof SWF) { + allSwfs.add((SWF) openable); + } + } + for (Openable openable : openableList) { + if (openable instanceof SWF) { + Main.populateSwfs((SWF) openable, allSwfs); + } } } for (SWF swf : allSwfs) { @@ -1224,28 +1233,30 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } } - public void loadSwfAtPos(SWFList newSwfs, int index) { + public void loadSwfAtPos(OpenableList newSwfs, int index) { View.checkAccess(); - SWFList oldSwfList = swfs.get(index); + OpenableList oldSwfList = openables.get(index); List allSwfs = new ArrayList<>(); - for (SWF s : oldSwfList.swfs) { - allSwfs.add(s); - Main.populateSwfs(s, allSwfs); + for (Openable o : oldSwfList.items) { + if (o instanceof SWF) { + allSwfs.add((SWF) o); + Main.populateSwfs((SWF) o, allSwfs); + } } List> expandedNodes = View.getExpandedNodes(tagTree); previewPanel.clear(); - swfs.set(index, newSwfs); + openables.set(index, newSwfs); for (SWF s : allSwfs) { s.clearTagSwfs(); Main.searchResultsStorage.destroySwf(s); } - SWF swf = newSwfs.size() > 0 ? newSwfs.get(0) : null; - if (swf != null) { - updateUi(swf); + Openable openable = newSwfs.size() > 0 ? newSwfs.get(0) : null; + if (openable != null) { + updateUi(openable); } gcClipboard(); @@ -1255,16 +1266,16 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se pinsPanel.load(); } - public void load(SWFList newSwfs, boolean first) { + public void load(OpenableList newOpenables, boolean first) { View.checkAccess(); List> expandedNodes = View.getExpandedNodes(getCurrentTree()); previewPanel.clear(); - swfs.add(newSwfs); - SWF swf = newSwfs.size() > 0 ? newSwfs.get(0) : null; - if (swf != null) { - updateUi(swf); + openables.add(newOpenables); + Openable openable = newOpenables.size() > 0 ? newOpenables.get(0) : null; + if (openable != null) { + updateUi(openable); } gcClipboard(); @@ -1294,35 +1305,38 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se return actionPanel; } - private void updateUi(final SWF swf) { + private void updateUi(final Openable openable) { View.checkAccess(); - List abcList = swf.getAbcList(); - - boolean hasAbc = !abcList.isEmpty(); - - if (hasAbc) { - getABCPanel().setAbc(abcList.get(0).getABC()); - } - if (isWelcomeScreen) { showContentPanelCard(SPLIT_PANE1); isWelcomeScreen = false; } + SWF swf = null; + if (openable instanceof SWF) { + swf = (SWF) openable; + List abcList = swf.getAbcList(); - mainMenu.updateComponents(swf); + boolean hasAbc = !abcList.isEmpty(); + + if (hasAbc) { + getABCPanel().setAbc(abcList.get(0).getABC()); + } + } + mainMenu.updateComponents(openable); if (taskThread != null) { taskThread.interrupt(); } - if (Configuration._debugMode.get()) { + if (Configuration._debugMode.get() && swf != null) { + final SWF fSwf = swf; Thread t = new Thread() { @Override public void run() { while (!Thread.currentThread().isInterrupted()) { - DecompilerPool d = swf.getDecompilerPool(); - statusPanel.setStatus(swf.getFileTitle() + " " + d.getStat()); + DecompilerPool d = fSwf.getDecompilerPool(); + statusPanel.setStatus(fSwf.getFileTitle() + " " + d.getStat()); try { Thread.sleep(100); @@ -1341,7 +1355,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se private void updateUi() { View.checkAccess(); - if (!isWelcomeScreen && swfs.isEmpty()) { + if (!isWelcomeScreen && openables.isEmpty()) { showContentPanelCard(WELCOME_PANEL); isWelcomeScreen = true; closeTagTreeSearch(); @@ -1353,7 +1367,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se showView(getCurrentView()); } - private boolean closeConfirmation(SWFList swfList) { + private boolean closeConfirmation(OpenableList swfList) { View.checkAccess(); String message = swfList == null @@ -1364,9 +1378,9 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } public boolean isModified() { - for (SWFList swfList : swfs) { - for (SWF swf : swfList) { - if (swf.isModified()) { + for (OpenableList openableList : openables) { + for (Openable openable : openableList) { + if (openable.isModified()) { return true; } } @@ -1379,7 +1393,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se View.checkAccess(); if (showCloseConfirmation && isModified()) { - boolean closeConfirmResult = closeConfirmation(swfs.size() == 1 ? swfs.get(0) : null); + boolean closeConfirmResult = closeConfirmation(openables.size() == 1 ? openables.get(0) : null); if (!closeConfirmResult) { return false; } @@ -1387,23 +1401,29 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se clearPins(); - List swfsLists = new ArrayList<>(swfs); + List swfsLists = new ArrayList<>(openables); for (SearchResultsDialog sr : searchResultsDialogs) { sr.setVisible(false); } searchResultsDialogs.clear(); - swfs.clear(); + openables.clear(); oldItem = null; clear(); updateUi(); List swfsToClose = new ArrayList<>(); - for (SWFList swfList : swfsLists) { - swfsToClose.addAll(swfList); - for (SWF swf : swfList) { - Main.populateSwfs(swf, swfsToClose); + for (OpenableList openableList : swfsLists) { + for (Openable openable : openableList) { + if (openable instanceof SWF) { + swfsToClose.add((SWF) openable); + } + } + for (Openable openable : openableList) { + if (openable instanceof SWF) { + Main.populateSwfs((SWF) openable, swfsToClose); + } } } @@ -1420,27 +1440,33 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se return true; } - public boolean close(SWFList swfList) { + public boolean close(OpenableList openableList) { View.checkAccess(); boolean modified = false; - for (SWF swf : swfList) { - if (swf.isModified()) { + for (Openable openable : openableList) { + if (openable.isModified()) { modified = true; } } if (modified) { - boolean closeConfirmResult = closeConfirmation(swfList); + boolean closeConfirmResult = closeConfirmation(openableList); if (!closeConfirmResult) { return false; } } List swfsToClose = new ArrayList<>(); - swfsToClose.addAll(swfList); - for (SWF swf : swfList) { - Main.populateSwfs(swf, swfsToClose); + for (Openable openable : openableList) { + if (openable instanceof SWF) { + swfsToClose.add((SWF) openable); + } + } + for (Openable openable : openableList) { + if (openable instanceof SWF) { + Main.populateSwfs((SWF) openable, swfsToClose); + } } for (int i = 0; i < searchResultsDialogs.size(); i++) { @@ -1456,10 +1482,10 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } for (SWF swf : swfsToClose) { Main.searchResultsStorage.destroySwf(swf); - pinsPanel.removeSwf(swf); + pinsPanel.removeOpenable(swf); } - swfs.remove(swfList); + openables.remove(openableList); oldItem = null; clear(); updateUi(); @@ -1488,9 +1514,9 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se @SuppressWarnings("unchecked") List droppedFiles = (List) dtde.getTransferable().getTransferData(DataFlavor.javaFileListFlavor); if (!droppedFiles.isEmpty()) { - SWFSourceInfo[] sourceInfos = new SWFSourceInfo[droppedFiles.size()]; + OpenableSourceInfo[] sourceInfos = new OpenableSourceInfo[droppedFiles.size()]; for (int i = 0; i < droppedFiles.size(); i++) { - sourceInfos[i] = new SWFSourceInfo(null, droppedFiles.get(i).getAbsolutePath(), null); + sourceInfos[i] = new OpenableSourceInfo(null, droppedFiles.get(i).getAbsolutePath(), null); } Main.openFile(sourceInfos, null); } @@ -1604,7 +1630,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se for (int i = 0; i < tm.getChildCount(root); i++) { // first level node can be SWF and SWFBundle TreeItem node = tm.getChild(root, i); - if (node instanceof SWFBundle) { + if (node instanceof Bundle) { for (int j = 0; j < tm.getChildCount(node); j++) { // child of SWFBundle should be SWF SWF swfNode = (SWF) tm.getChild(node, j); @@ -1638,16 +1664,23 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se List ret = new ArrayList<>(); List sel = getSelection(null); - Set usedSwfs = new HashSet<>(); + Set usedOpenables = new HashSet<>(); for (TreeItem d : sel) { - SWF selectedNodeSwf = d.getSwf(); - if (!usedSwfs.contains(selectedNodeSwf)) { - usedSwfs.add(selectedNodeSwf); + Openable selectedNodeOpenable = d.getOpenable(); + if (!usedOpenables.contains(selectedNodeOpenable)) { + usedOpenables.add(selectedNodeOpenable); } } Map usedSwfsIds = new HashMap<>(); - for (SWF swf : usedSwfs) { + for (Openable openable : usedOpenables) { + + SWF swf = null; + if (openable instanceof SWF) { + swf = (SWF) openable; + } else { + swf = ((ABC)openable).getSwf(); + } List as3scripts = new ArrayList<>(); List images = new ArrayList<>(); List shapes = new ArrayList<>(); @@ -1664,9 +1697,9 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se List symbolNames = new ArrayList<>(); for (TreeItem d : sel) { - SWF selectedNodeSwf = d.getSwf(); + Openable selectedNodeSwf = d.getOpenable(); - if (selectedNodeSwf != swf) { + if (selectedNodeSwf != openable) { continue; } @@ -1749,8 +1782,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } String selFile2; - if (usedSwfs.size() > 1) { - selFile2 = selFile + File.separator + Helper.getNextId(swf.getTitleOrShortFileName(), usedSwfsIds); + if (usedOpenables.size() > 1) { + selFile2 = selFile + File.separator + Helper.getNextId(openable.getTitleOrShortFileName(), usedSwfsIds); } else { selFile2 = selFile; } @@ -1844,7 +1877,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()); + String singleFileName = Path.combine(scriptsFolder, openable.getShortFileName() + scriptExportSettings.getFileExtension()); try ( FileTextWriter writer = scriptExportSettings.singleFile ? new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(singleFileName)) : null) { scriptExportSettings.singleFileWriter = writer; if (swf.isAS3()) { @@ -2077,31 +2110,31 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } } - public List getSwfs() { - return swfs; + public List getSwfs() { + return openables; } - public SWFList getCurrentSwfList() { + public OpenableList getCurrentSwfList() { SWF swf = getCurrentSwf(); if (swf == null) { return null; } - return swf.swfList; + return swf.openableList; } - public SWF getCurrentSwf() { - if (swfs == null || swfs.isEmpty()) { + public Openable getCurrentOpenable() { + if (openables == null || openables.isEmpty()) { return null; } if (treePanelMode == TreePanelMode.TAG_TREE) { TreeItem treeNode = (TreeItem) tagTree.getLastSelectedPathComponent(); - if (treeNode == null || treeNode instanceof SWFList) { + if (treeNode == null || treeNode instanceof OpenableList) { return null; } - return treeNode.getSwf(); + return treeNode.getOpenable(); } else if (treePanelMode == TreePanelMode.DUMP_TREE) { DumpInfo dumpInfo = (DumpInfo) dumpTree.getLastSelectedPathComponent(); @@ -2109,18 +2142,26 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se return null; } - return DumpInfoSwfNode.getSwfNode(dumpInfo).getSwf(); + return DumpInfoSwfNode.getSwfNode(dumpInfo).getOpenable(); } else if (treePanelMode == TreePanelMode.TAGLIST_TREE) { TreeItem treeNode = (TreeItem) tagListTree.getLastSelectedPathComponent(); - if (treeNode == null || treeNode instanceof SWFList) { + if (treeNode == null || treeNode instanceof OpenableList) { return null; } - return treeNode.getSwf(); + return treeNode.getOpenable(); } return null; } + + public SWF getCurrentSwf() { + Openable openable = getCurrentOpenable(); + if (openable instanceof SWF) { + return (SWF) openable; + } + return null; + } public AbstractTagTree getCurrentTree() { if (currentView == VIEW_RESOURCES) { @@ -2141,7 +2182,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } if (treeItem instanceof Timelined) { Timelined t = (Timelined) treeItem; - Frame f = tagTree.getModel().getFrame(treeItem.getSwf(), t, frame); + Frame f = tagTree.getModel().getFrame((SWF)treeItem.getOpenable(), t, frame); if (f != null) { setTagTreeSelectedNode(getCurrentTree(), f); } @@ -2270,24 +2311,45 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } private void clearAllScriptCache() { - for (SWFList swfList : swfs) { - for (SWF swf : swfList) { - swf.clearScriptCache(); + for (OpenableList openableList : openables) { + for (Openable openable : openableList) { + if (openable instanceof SWF) { + ((SWF) openable).clearScriptCache(); + } } } } public Set getAllSwfs() { List allSwfs = new ArrayList<>(); - for (SWFList slist : getSwfs()) { - for (SWF s : slist.swfs) { - allSwfs.add(s); - Main.populateSwfs(s, allSwfs); + for (OpenableList slist : getSwfs()) { + for (Openable o : slist.items) { + if (o instanceof SWF) { + allSwfs.add((SWF) o); + Main.populateSwfs((SWF) o, allSwfs); + } } } return new LinkedHashSet<>(allSwfs); } + public Set getAllOpenablesAndSwfs() { + List allOpenables = new ArrayList<>(); + for (OpenableList slist : getSwfs()) { + for (Openable o : slist.items) { + allOpenables.add((SWF) o); + if (o instanceof SWF) { + List subSwfs = new ArrayList<>(); + Main.populateSwfs((SWF) o, subSwfs); + for (SWF swf : subSwfs) { + allOpenables.add(swf); + } + } + } + } + return new LinkedHashSet<>(allOpenables); + } + private List getAllSelected() { if (currentView == VIEW_RESOURCES) { return tagTree.getAllSelected(); @@ -2308,25 +2370,31 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se return new ArrayList<>(); } - public void searchInActionScriptOrText(Boolean searchInText, SWF swf, boolean useSelection) { + public void searchInActionScriptOrText(Boolean searchInText, Openable openable, boolean useSelection) { View.checkAccess(); - - Map> scopeAs3 = new LinkedHashMap<>(); + + /*if (!(openable instanceof SWF)) { //FIXME for ABCs + return; + }*/ + + SWF swf = (openable instanceof SWF) ? (SWF) openable : ((ABC) openable).getSwf(); + + Map> scopeAs3 = new LinkedHashMap<>(); Map> swfToAllASMSourceMap = new HashMap<>(); Map> scopeAs12 = new LinkedHashMap<>(); - Set swfsUsed = new LinkedHashSet<>(); + Set openablesUsed = new LinkedHashSet<>(); List allItems = getAllSelected(); for (TreeItem t : allItems) { if (t instanceof ScriptPack) { ScriptPack sp = (ScriptPack) t; - SWF s = sp.getSwf(); + Openable s = sp.getOpenable(); //Fixme for ABCs if (!scopeAs3.containsKey(s)) { scopeAs3.put(s, new ArrayList<>()); } scopeAs3.get(s).add(sp); - swfsUsed.add(s); + openablesUsed.add(s); } ASMSource as = null; if (t instanceof ASMSource) { @@ -2357,7 +2425,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se scopeAs12.put(s, new LinkedHashMap<>()); } scopeAs12.get(s).put(asId, as); - swfsUsed.add(s); + openablesUsed.add(s); } } @@ -2374,7 +2442,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se selected = AppDialog.translateForDialog("scope.selection.items", SearchDialog.class).replace("%count%", "" + items.size()); } - SearchDialog searchDialog = new SearchDialog(getMainFrame().getWindow(), false, selected, useSelection); + SearchDialog searchDialog = new SearchDialog(getMainFrame().getWindow(), false, selected, useSelection, openable instanceof ABC); if (searchInText != null) { if (searchInText) { searchDialog.searchInTextsRadioButton.setSelected(true); @@ -2391,25 +2459,44 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se scopeAs3.clear(); scopeAs12.clear(); if (swf.isAS3()) { - scopeAs3.put(swf, swf.getAS3Packs()); + List packs = new ArrayList<>(); + if (openable instanceof SWF) { + packs = ((SWF)openable).getAS3Packs(); + } else { + ABC abc = (ABC) openable; + List allAbcs = new ArrayList<>(); + allAbcs.add(abc); + packs = abc.getScriptPacks(null, allAbcs); + } + scopeAs3.put(openable, packs); } else { - scopeAs12.put(swf, swf.getASMs(false)); + scopeAs12.put((SWF)openable, swf.getASMs(false)); } - swfsUsed.clear(); - swfsUsed.add(swf); + openablesUsed.clear(); + openablesUsed.add(openable); } if (searchDialog.getCurrentScope() == SearchDialog.SCOPE_ALL_FILES) { - Set allSwfs = getAllSwfs(); + Set allOpenables = getAllOpenablesAndSwfs(); - for (SWF s : allSwfs) { - if (s.isAS3()) { - scopeAs3.put(s, s.getAS3Packs()); + for (Openable s : allOpenables) { + SWF ss = (s instanceof SWF) ? (SWF) s : ((ABC)s).getSwf(); + if (ss.isAS3()) { + List packs = new ArrayList<>(); + if (s instanceof SWF) { + packs = ((SWF)s).getAS3Packs(); + } else { + ABC abc = (ABC) s; + List allAbcs = new ArrayList<>(); + allAbcs.add(abc); + packs = abc.getScriptPacks(null, allAbcs); + } + scopeAs3.put(s, packs); } else { - scopeAs12.put(s, s.getASMs(false)); + scopeAs12.put(ss, ss.getASMs(false)); } } - swfsUsed.clear(); - swfsUsed.addAll(allSwfs); + openablesUsed.clear(); + openablesUsed.addAll(allOpenables); } if (!scopeAs3.isEmpty()) { @@ -2431,7 +2518,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se protected Void doInBackground() throws Exception { List fResult = new ArrayList<>(); - for (SWF s : swfsUsed) { + for (Openable s : openablesUsed) { if (scopeAs3.containsKey(s)) { List abcResult = getABCPanel().search(s, txt, ignoreCase, regexp, pCodeSearch, this, scopeAs3.get(s)); fResult.addAll(abcResult); @@ -2440,10 +2527,10 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } } if (scopeAs12.containsKey(s)) { - List actionResult = getActionPanel().search(s, txt, ignoreCase, regexp, pCodeSearch, this, scopeAs12.get(s)); + List actionResult = getActionPanel().search((SWF) s, txt, ignoreCase, regexp, pCodeSearch, this, scopeAs12.get(s)); fResult.addAll(actionResult); if (!actionResult.isEmpty()) { - Main.searchResultsStorage.addActionResults(s, txt, ignoreCase, regexp, actionResult); + Main.searchResultsStorage.addActionResults((SWF) s, txt, ignoreCase, regexp, actionResult); } } } @@ -2515,7 +2602,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } public void replaceText() { - SearchDialog replaceDialog = new SearchDialog(getMainFrame().getWindow(), true, null, false); + SearchDialog replaceDialog = new SearchDialog(getMainFrame().getWindow(), true, null, false, false); if (replaceDialog.showDialog() == AppDialog.OK_OPTION) { final String txt = replaceDialog.searchField.getText(); if (!txt.isEmpty()) { @@ -2644,18 +2731,25 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se updateClassesList(); } - public void renameColliding(final SWF swf) { + public void renameColliding(final Openable openable) { View.checkAccess(); + SWF swf = null; + if (openable instanceof SWF) { + swf = (SWF) openable; + } + //FIXME for ABCs + if (swf == null) { return; } + final SWF fswf = swf; if (confirmExperimental()) { new CancellableWorker() { @Override protected Integer doInBackground() throws Exception { AbcMultiNameCollisionFixer fixer = new AbcMultiNameCollisionFixer(); - return fixer.fixCollisions(swf); + return fixer.fixCollisions(fswf); } @Override @@ -2670,8 +2764,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se int cnt = get(); Main.stopWork(); ViewMessages.showMessageDialog(MainPanel.this, translate("message.rename.renamed").replace("%count%", Integer.toString(cnt))); - swf.assignClassesToSymbols(); - swf.clearScriptCache(); + fswf.assignClassesToSymbols(); + fswf.clearScriptCache(); if (abcPanel != null) { abcPanel.reload(); } @@ -3302,11 +3396,18 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se Set swfs = new LinkedHashSet<>(); for (TreeItem item : sel) { - if (item instanceof SWFList) { - SWFList list = (SWFList) item; - swfs.addAll(list); + if (item instanceof OpenableList) { + OpenableList list = (OpenableList) item; + for (Openable openable : list) { + if (openable instanceof SWF) { + swfs.add((SWF) openable); + } + } } else { - swfs.add(item.getSwf()); + Openable openable = item.getOpenable(); + if (openable instanceof SWF) { + swfs.add((SWF) openable); + } } } @@ -3333,11 +3434,18 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se Set swfs = new LinkedHashSet<>(); for (TreeItem item : sel) { - if (item instanceof SWFList) { - SWFList list = (SWFList) item; - swfs.addAll(list); + if (item instanceof OpenableList) { + OpenableList list = (OpenableList) item; + for (Openable openable : list) { + if (openable instanceof SWF) { + swfs.add((SWF) openable); + } + } } else { - swfs.add(item.getSwf()); + Openable openable = item.getOpenable(); + if (openable instanceof SWF) { + swfs.add((SWF) openable); + } } } @@ -3366,11 +3474,18 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se Set swfs = new LinkedHashSet<>(); for (TreeItem item : sel) { - if (item instanceof SWFList) { - SWFList list = (SWFList) item; - swfs.addAll(list); + if (item instanceof OpenableList) { + OpenableList list = (OpenableList) item; + for (Openable openable : list) { + if (openable instanceof SWF) { + swfs.add((SWF) openable); + } + } } else { - swfs.add(item.getSwf()); + Openable openable = item.getOpenable(); + if (openable instanceof SWF) { + swfs.add((SWF) openable); + } } } if (swfs.size() > 1) { @@ -3396,12 +3511,21 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } } - public void renameIdentifiers(final SWF swf) { + public void renameIdentifiers(final Openable openable) { View.checkAccess(); + SWF swf = null; + + if (openable instanceof SWF) { + swf = (SWF) openable; + } + //FIXME for ABCs + if (swf == null) { return; } + + final SWF fswf = swf; if (confirmExperimental()) { RenameDialog renameDialog = new RenameDialog(Main.getDefaultDialogsOwner()); if (renameDialog.showRenameDialog() == AppDialog.OK_OPTION) { @@ -3409,7 +3533,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se new CancellableWorker() { @Override protected Integer doInBackground() throws Exception { - int cnt = swf.deobfuscateIdentifiers(renameType); + int cnt = fswf.deobfuscateIdentifiers(renameType); return cnt; } @@ -3425,8 +3549,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se int cnt = get(); Main.stopWork(); ViewMessages.showMessageDialog(MainPanel.this, translate("message.rename.renamed").replace("%count%", Integer.toString(cnt))); - swf.assignClassesToSymbols(); - swf.clearScriptCache(); + fswf.assignClassesToSymbols(); + fswf.clearScriptCache(); if (abcPanel != null) { abcPanel.reload(); } @@ -3576,10 +3700,10 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se tagListTree.updateSwfs(new SWF[0]); if (treeItem != null) { - SWF swf = treeItem.getSwf(); + SWF swf = (SWF)treeItem.getOpenable(); //should be SWF if (swf != null) { SWF treeItemSwf = swf.getRootSwf(); - if (this.swfs.contains(treeItemSwf.swfList)) { + if (this.openables.contains(treeItemSwf.openableList)) { setTagTreeSelectedNode(getCurrentTree(), treeItem); } } @@ -3589,11 +3713,11 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se pinsPanel.refresh(); } - public void refreshTree(SWF swf) { - refreshTree(new SWF[]{swf}); + public void refreshTree(Openable openable) { + refreshTree(new Openable[]{openable}); } - public void refreshTree(SWF[] swfs) { + public void refreshTree(Openable[] openables) { clear(); showCard(CARDEMPTYPANEL); TreeItem treeItem = null; @@ -3601,14 +3725,20 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se treeItem = getCurrentTree().getCurrentTreeItem(); } - tagTree.updateSwfs(swfs); - tagListTree.updateSwfs(swfs); + tagTree.updateSwfs(openables); + tagListTree.updateSwfs(openables); if (treeItem != null) { - SWF swf = treeItem.getSwf(); - if (swf != null) { + Openable openable = treeItem.getOpenable(); + + if (openable instanceof SWF) { + SWF swf = (SWF) openable; SWF treeItemSwf = swf.getRootSwf(); - if (this.swfs.contains(treeItemSwf.swfList)) { + if (this.openables.contains(treeItemSwf.openableList)) { + setTagTreeSelectedNode(getCurrentTree(), treeItem); + } + } else { + if (this.openables.contains(openable.getOpenableList())) { setTagTreeSelectedNode(getCurrentTree(), treeItem); } } @@ -4045,18 +4175,18 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se return; } - if (!(treeItem instanceof SWFList)) { - SWF swf = treeItem.getSwf(); - if (swfs.isEmpty()) { + if (!(treeItem instanceof OpenableList)) { + Openable openable = treeItem.getOpenable(); + if (openables.isEmpty()) { // show welcome panel after closing swfs updateUi(); } else { - if (swf == null && swfs.get(0) != null) { - swf = swfs.get(0).get(0); + if (openable == null && openables.get(0) != null) { + openable = openables.get(0).get(0); } - if (swf != null) { - updateUi(swf); + if (openable != null) { + updateUi(openable); } } } else { @@ -4207,7 +4337,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se switch (view) { case VIEW_DUMP: if (dumpTree.getModel() == null) { - DumpTreeModel dtm = new DumpTreeModel(swfs); + DumpTreeModel dtm = new DumpTreeModel(openables); dumpTree.setModel(dtm); dumpTree.expandFirstLevelNodes(); } @@ -4215,13 +4345,13 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se case VIEW_RESOURCES: case VIEW_TAGLIST: if (tagTree.getModel() == null) { - TagTreeModel ttm = new TagTreeModel(swfs, Configuration.tagTreeShowEmptyFolders.get()); + TagTreeModel ttm = new TagTreeModel(openables, Configuration.tagTreeShowEmptyFolders.get()); tagTree.setModel(ttm); tagTree.expandFirstLevelNodes(); } if (tagListTree.getModel() == null) { - TagListTreeModel ttm = new TagListTreeModel(swfs); + TagListTreeModel ttm = new TagListTreeModel(openables); tagListTree.setModel(ttm); tagListTree.expandFirstLevelNodes(); } @@ -4464,7 +4594,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se previewPanel.showImagePanel(timelined, tag.getSwf(), -1, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), treeItem instanceof ShapeTag); } else if (treeItem instanceof Frame && internalViewer) { Frame fn = (Frame) treeItem; - SWF swf = fn.getSwf(); + SWF swf = (SWF) fn.getOpenable(); previewPanel.showImagePanel(fn.timeline.timelined, swf, fn.frame, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false); } else if (treeItem instanceof ShowFrameTag) { SWF swf; @@ -4598,14 +4728,14 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } // save last selected node to config - if (treeItem != null && !(treeItem instanceof SWFList)) { - SWF swf = treeItem.getSwf(); - if (swf != null) { - swf = swf.getRootSwf(); + if (treeItem != null && !(treeItem instanceof OpenableList)) { + Openable openable = treeItem.getOpenable(); + if (openable != null && (openable instanceof SWF)) { + openable = ((SWF)openable).getRootSwf(); } - if (swf != null) { - SwfSpecificCustomConfiguration swfCustomConf = Configuration.getOrCreateSwfSpecificCustomConfiguration(swf.getShortPathTitle()); + if (openable != null) { + SwfSpecificCustomConfiguration swfCustomConf = Configuration.getOrCreateSwfSpecificCustomConfiguration(openable.getShortPathTitle()); swfCustomConf.setCustomData(CustomConfigurationKeys.KEY_LAST_SELECTED_PATH_RESOURCES, tagTree.getSelectionPathString()); swfCustomConf.setCustomData(CustomConfigurationKeys.KEY_LAST_SELECTED_PATH_TAGLIST, tagListTree.getSelectionPathString()); } @@ -4655,7 +4785,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se showCard(CARDACTIONSCRIPT3PANEL); } else if (treeItem instanceof Tag) { Tag tag = (Tag) treeItem; - TagInfo tagInfo = new TagInfo(treeItem.getSwf()); + TagInfo tagInfo = new TagInfo((SWF)treeItem.getOpenable()); tag.getTagInfo(tagInfo); Set needed; @@ -4700,7 +4830,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se frame.getNeededCharacters(needed); if (!needed.isEmpty()) { - TagInfo tagInfo = new TagInfo(treeItem.getSwf()); + TagInfo tagInfo = new TagInfo((SWF)treeItem.getOpenable()); tagInfo.addInfo("general", "neededCharacters", Helper.joinStrings(needed, ", ")); tagInfoPanel.setTagInfos(tagInfo); showDetail(DETAILCARDTAGINFO); @@ -4712,7 +4842,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } if (treeItem instanceof HeaderItem) { - headerPanel.load(((HeaderItem) treeItem).getSwf()); + headerPanel.load((SWF)((HeaderItem) treeItem).getOpenable()); showCard(CARDHEADER); } else if (treeItem instanceof FolderItem) { showFolderPreview((FolderItem) treeItem); @@ -5207,11 +5337,14 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se Map> missingNeededCharacters = new WeakHashMap<>(); Map> neededCharacters = new WeakHashMap<>(); - List swfsLists = new ArrayList<>(swfs); - for (SWFList swfList : swfsLists) { - for (SWF swf : swfList) { - calculateMissingNeededCharacters(neededCharacters, missingNeededCharacters, swf); - } + List swfsLists = new ArrayList<>(openables); + for (OpenableList swfList : swfsLists) { + for (Openable openable : swfList) { + if (openable instanceof SWF) { + calculateMissingNeededCharacters(neededCharacters, missingNeededCharacters, (SWF) openable); + //TODO: how about SubSWFs??? + } + } } this.neededCharacters = neededCharacters; this.missingNeededCharacters = missingNeededCharacters; diff --git a/src/com/jpexs/decompiler/flash/gui/PinsPanel.java b/src/com/jpexs/decompiler/flash/gui/PinsPanel.java index ba8645c96..a0fbb089e 100644 --- a/src/com/jpexs/decompiler/flash/gui/PinsPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/PinsPanel.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.gui.tagtree.TreeRoot; import com.jpexs.decompiler.flash.timeline.TagScript; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.flash.treeitems.TreeItem; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -355,11 +356,11 @@ public class PinsPanel extends JPanel { rebuild(); } - public void removeSwf(SWF swf) { + public void removeOpenable(Openable openable) { for (int i = 0; i < items.size(); i++) { TreeItem item = items.get(i); - SWF itemSwf = item.getSwf(); - if (itemSwf == swf || itemSwf == null) { + Openable itemOpenable = item.getOpenable(); + if (itemOpenable == openable || itemOpenable == null) { String tagTreePath = mainPanel.tagTree.getItemPathString(item); if (tagTreePath == null) { diff --git a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java index 5f4f3c96a..fe2c03a1c 100644 --- a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java @@ -787,7 +787,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel } } else if (treeItem instanceof Frame) { Frame fn = (Frame) treeItem; - SWF sourceSwf = fn.getSwf(); + SWF sourceSwf = (SWF) fn.getOpenable(); if (fn.timeline.timelined == sourceSwf) { SetBackgroundColorTag setBgColorTag = sourceSwf.getBackgroundColor(); if (setBgColorTag != null) { @@ -825,7 +825,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel } } else if (treeItem instanceof Frame) { Frame fn = (Frame) treeItem; - SWF sourceSwf = fn.getSwf(); + SWF sourceSwf = (SWF) fn.getOpenable(); if (fn.timeline.timelined == sourceSwf) { SetBackgroundColorTag setBgColorTag = sourceSwf.getBackgroundColor(); if (setBgColorTag != null) { diff --git a/src/com/jpexs/decompiler/flash/gui/SearchDialog.java b/src/com/jpexs/decompiler/flash/gui/SearchDialog.java index f587663d6..7e2cfe5af 100644 --- a/src/com/jpexs/decompiler/flash/gui/SearchDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/SearchDialog.java @@ -78,7 +78,7 @@ public class SearchDialog extends AppDialog { } } - public SearchDialog(Window owner, boolean replace, String selection, boolean selectionFirst) { + public SearchDialog(Window owner, boolean replace, String selection, boolean selectionFirst, boolean currentAbc) { super(owner); setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE); ignoreCaseCheckBox.setSelected(true); @@ -111,7 +111,7 @@ public class SearchDialog extends AppDialog { if (selection != null) { scopeItems.add(translate("scope.selection").replace("%selection%", selection)); } - scopeItems.add(translate("scope.currentFile")); + scopeItems.add(translate(currentAbc ? "scope.currentFile.abc" : "scope.currentFile")); scopeItems.add(translate("scope.allFiles")); panField.add(new JLabel(translate("label.scope"))); scopeComboBox = new JComboBox<>(scopeItems.toArray(new String[scopeItems.size()])); diff --git a/src/com/jpexs/decompiler/flash/gui/SearchResultsDialog.java b/src/com/jpexs/decompiler/flash/gui/SearchResultsDialog.java index 93f2bbc03..3d1cd5b2a 100644 --- a/src/com/jpexs/decompiler/flash/gui/SearchResultsDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/SearchResultsDialog.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.gui; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.search.SearchResult; +import com.jpexs.decompiler.flash.treeitems.Openable; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Component; @@ -86,7 +87,7 @@ public class SearchResultsDialog extends AppDialog { private String text; private final boolean ignoreCase; - private Map> swfToResults = new LinkedHashMap<>(); + private Map> openableToResults = new LinkedHashMap<>(); public SearchResultsDialog(Window owner, String text, boolean ignoreCase, boolean regExp, List> listeners) { super(owner); @@ -388,30 +389,30 @@ public class SearchResultsDialog extends AppDialog { } public void setResults(List results) { - swfToResults.clear(); + openableToResults.clear(); for (E e : results) { - if (!swfToResults.containsKey(e.getSWF())) { - swfToResults.put(e.getSWF(), new ArrayList<>()); + if (!openableToResults.containsKey(e.getOpenable())) { + openableToResults.put(e.getOpenable(), new ArrayList<>()); } - swfToResults.get(e.getSWF()).add(e); + openableToResults.get(e.getOpenable()).add(e); } updateModel(); } private void updateModel() { - boolean showSwfTitles = swfToResults.size() > 1; + boolean showSwfTitles = openableToResults.size() > 1; if (showSwfTitles) { BasicTreeNode rootNode = new BasicTreeNode("root"); List swfNodes = new ArrayList<>(); - for (SWF s : swfToResults.keySet()) { + for (Openable s : openableToResults.keySet()) { BasicTreeNode swfNode = new BasicTreeNode(s); if (showSwfTitles) { rootNode.addChild(swfNode); swfNode.setParent(rootNode); swfNodes.add(swfNode); } - for (SearchResult r : swfToResults.get(s)) { + for (SearchResult r : openableToResults.get(s)) { BasicTreeNode rNode = new BasicTreeNode(r); if (showSwfTitles) { swfNode.addChild(rNode); @@ -430,8 +431,8 @@ public class SearchResultsDialog extends AppDialog { } else { DefaultListModel model = (DefaultListModel) resultsList.getModel(); model.clear(); - if (!swfToResults.isEmpty()) { - List elements = swfToResults.get(swfToResults.keySet().iterator().next()); + if (!openableToResults.isEmpty()) { + List elements = openableToResults.get(openableToResults.keySet().iterator().next()); for (SearchResult e : elements) { model.addElement(e); } @@ -442,12 +443,12 @@ public class SearchResultsDialog extends AppDialog { } public void removeSwf(SWF swf) { - swfToResults.remove(swf); + openableToResults.remove(swf); updateModel(); } public boolean isEmpty() { - return swfToResults.isEmpty(); + return openableToResults.isEmpty(); } private void gotoButtonActionPerformed(ActionEvent evt) { @@ -460,7 +461,7 @@ public class SearchResultsDialog extends AppDialog { @SuppressWarnings("unchecked") private void gotoElement() { - if (swfToResults.size() > 1) { + if (openableToResults.size() > 1) { BasicTreeNode selection = (BasicTreeNode) resultsTree.getLastSelectedPathComponent(); if (selection.getData() instanceof SearchResult) { for (SearchListener listener : listeners) { diff --git a/src/com/jpexs/decompiler/flash/gui/SearchResultsStorage.java b/src/com/jpexs/decompiler/flash/gui/SearchResultsStorage.java index 1cbffb7b8..922fffcf1 100644 --- a/src/com/jpexs/decompiler/flash/gui/SearchResultsStorage.java +++ b/src/com/jpexs/decompiler/flash/gui/SearchResultsStorage.java @@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.search.ABCSearchResult; import com.jpexs.decompiler.flash.search.ActionSearchResult; import com.jpexs.decompiler.flash.search.ScriptNotFoundException; import com.jpexs.decompiler.flash.search.ScriptSearchResult; +import com.jpexs.decompiler.flash.treeitems.Openable; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -57,7 +58,7 @@ public class SearchResultsStorage { return Configuration.getFFDecHome() + SEARCH_RESULTS_FILE; } - List swfIds = new ArrayList<>(); + List openableIds = new ArrayList<>(); List searchedValues = new ArrayList<>(); List isRegExp = new ArrayList<>(); List isIgnoreCase = new ArrayList<>(); @@ -71,28 +72,28 @@ public class SearchResultsStorage { currentGroupId++; } - public static String getSwfId(SWF swf) { + public static String getOpenableId(Openable swf) { - SWF s = swf; + Openable s = swf; String binaryDataSuffix = ""; - while (s.binaryData != null) { - binaryDataSuffix += "|binaryData[" + s.binaryData.getCharacterId() + "]"; - s = s.binaryData.getSwf(); + while ((s instanceof SWF) && ((SWF)s).binaryData != null) { + binaryDataSuffix += "|binaryData[" + ((SWF)s).binaryData.getCharacterId() + "]"; + s = ((SWF)s).binaryData.getSwf(); } - if (s.swfList != null) { + if (s.getOpenableList() != null) { String fileInsideTitle = s.getFile() == null ? s.getFileTitle() : ""; if (fileInsideTitle != null && !"".equals(fileInsideTitle)) { fileInsideTitle = "|" + fileInsideTitle; } - return s.swfList.sourceInfo.getFile() + fileInsideTitle + binaryDataSuffix; + return s.getOpenableList().sourceInfo.getFile() + fileInsideTitle + binaryDataSuffix; } return "**NONE**"; } public int getCount() { - return swfIds.size(); + return openableIds.size(); } public String getSearchedValueAt(int index) { @@ -122,12 +123,12 @@ public class SearchResultsStorage { return false; } - public List getIndicesForSwf(SWF swf) { - String swfId = getSwfId(swf); + public List getIndicesForOpenable(Openable swf) { + String swfId = getOpenableId(swf); List res = new ArrayList<>(); Set foundGroups = new LinkedHashSet<>(); - for (int i = 0; i < swfIds.size(); i++) { - if (swfIds.get(i).equals(swfId)) { + for (int i = 0; i < openableIds.size(); i++) { + if (openableIds.get(i).equals(swfId)) { foundGroups.add(groups.get(i)); } } @@ -135,29 +136,29 @@ public class SearchResultsStorage { } @SuppressWarnings("unchecked") - public List getSearchResultsAt(Set allSwfs, int index) { + public List getSearchResultsAt(Set allOpenables, int index) { List result = new ArrayList<>(); - Map swfIdToSwf = new HashMap<>(); - for (SWF s : allSwfs) { - swfIdToSwf.put(getSwfId(s), s); + Map openableIdToOpenable = new HashMap<>(); + for (Openable o : allOpenables) { + openableIdToOpenable.put(getOpenableId(o), o); } for (int j = 0; j < data.size(); j++) { if (groups.get(j) == index) { - if (!swfIdToSwf.containsKey(swfIds.get(j))) { + if (!openableIdToOpenable.containsKey(openableIds.get(j))) { continue; } if (unpackedData.get(j) != null) { List unpacked = unpackedData.get(j); for (ScriptSearchResult sr : unpacked) { - if (allSwfs.contains(sr.getSWF())) { + if (allOpenables.contains(sr.getOpenable())) { result.add(sr); } } continue; } - SWF swf = swfIdToSwf.get(swfIds.get(j)); + Openable openable = openableIdToOpenable.get(openableIds.get(j)); byte[] itemData = data.get(j); List currentResults = new ArrayList<>(); try { @@ -170,10 +171,10 @@ public class SearchResultsStorage { ByteArrayInputStream bais = new ByteArrayInputStream(resultData.get(i)); if (kind == DATA_ABC) { - currentResults.add(new ABCSearchResult(swf, bais)); + currentResults.add(new ABCSearchResult(openable, bais)); } if (kind == DATA_ACTION) { - currentResults.add(new ActionSearchResult(swf, bais)); + currentResults.add(new ActionSearchResult((SWF) openable, bais)); } } catch (ScriptNotFoundException | IOException ex) { ex.printStackTrace(); @@ -201,7 +202,7 @@ public class SearchResultsStorage { if (major != SERIAL_VERSION_MAJOR) { //incompatible version return; } - swfIds = (List) ois.readObject(); + openableIds = (List) ois.readObject(); searchedValues = (List) ois.readObject(); isIgnoreCase = (List) ois.readObject(); isRegExp = (List) ois.readObject(); @@ -231,7 +232,7 @@ public class SearchResultsStorage { ObjectOutputStream oos = new ObjectOutputStream(fos)) { oos.write(SERIAL_VERSION_MAJOR); oos.write(SERIAL_VERSION_MINOR); - oos.writeObject(swfIds); + oos.writeObject(openableIds); oos.writeObject(searchedValues); oos.writeObject(isIgnoreCase); oos.writeObject(isRegExp); @@ -240,8 +241,8 @@ public class SearchResultsStorage { } } - public void addABCResults(SWF swf, String searchedString, boolean ignoreCase, boolean regExp, List results) { - swfIds.add(getSwfId(swf)); + public void addABCResults(Openable openable, String searchedString, boolean ignoreCase, boolean regExp, List results) { + openableIds.add(getOpenableId(openable)); searchedValues.add(searchedString); isIgnoreCase.add(ignoreCase); isRegExp.add(regExp); @@ -268,7 +269,7 @@ public class SearchResultsStorage { } public void addActionResults(SWF swf, String searchedString, boolean ignoreCase, boolean regExp, List results) { - swfIds.add(getSwfId(swf)); + openableIds.add(getOpenableId(swf)); searchedValues.add(searchedString); isIgnoreCase.add(ignoreCase); isRegExp.add(regExp); @@ -293,7 +294,7 @@ public class SearchResultsStorage { } public void clear() { - swfIds.clear(); + openableIds.clear(); searchedValues.clear(); isIgnoreCase.clear(); isRegExp.clear(); @@ -302,11 +303,11 @@ public class SearchResultsStorage { unpackedData.clear(); } - public void clearForSwf(SWF swf) { - String swfId = getSwfId(swf); - for (int i = 0; i < swfIds.size(); i++) { - if (swfIds.get(i).equals(swfId)) { - swfIds.remove(i); + public void clearForOpenable(Openable openable) { + String swfId = getOpenableId(openable); + for (int i = 0; i < openableIds.size(); i++) { + if (openableIds.get(i).equals(swfId)) { + openableIds.remove(i); searchedValues.remove(i); isIgnoreCase.remove(i); isRegExp.remove(i); @@ -339,9 +340,9 @@ public class SearchResultsStorage { } public void destroySwf(SWF swf) { - String swfId = getSwfId(swf); - for (int i = 0; i < swfIds.size(); i++) { - if (swfIds.get(i).equals(swfId)) { + String swfId = getOpenableId(swf); + for (int i = 0; i < openableIds.size(); i++) { + if (openableIds.get(i).equals(swfId)) { unpackedData.set(i, null); } } diff --git a/src/com/jpexs/decompiler/flash/gui/TreeNodeType.java b/src/com/jpexs/decompiler/flash/gui/TreeNodeType.java index 5df6cdc84..af0ae91a1 100644 --- a/src/com/jpexs/decompiler/flash/gui/TreeNodeType.java +++ b/src/com/jpexs/decompiler/flash/gui/TreeNodeType.java @@ -63,5 +63,6 @@ public enum TreeNodeType { REMOVE_OBJECT, SCALING_GRID, END, - ERROR + ERROR, + ABC } diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java index 80536855d..5052c345a 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java @@ -84,6 +84,7 @@ import com.jpexs.decompiler.flash.search.ScriptSearchListener; import com.jpexs.decompiler.flash.search.ScriptSearchResult; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.flash.treeitems.TreeItem; import com.jpexs.helpers.CancellableWorker; import com.jpexs.helpers.Helper; @@ -208,13 +209,13 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener search(final SWF swf, final String txt, boolean ignoreCase, boolean regexp, boolean pcode, CancellableWorker worker, List scope) { + public List search(final Openable openable, final String txt, boolean ignoreCase, boolean regexp, boolean pcode, CancellableWorker worker, List scope) { if (txt != null && !txt.isEmpty()) { searchPanel.setOptions(ignoreCase, regexp); String workText = AppStrings.translate("work.searching"); String decAdd = AppStrings.translate("work.decompiling"); - return new ActionScriptSearch().searchAs3(swf, txt, ignoreCase, regexp, pcode, new ScriptSearchListener() { + return new ActionScriptSearch().searchAs3(openable, txt, ignoreCase, regexp, pcode, new ScriptSearchListener() { @Override public void onDecompile(int pos, int total, String name) { Main.startWork(workText + " \"" + txt + "\", " + decAdd + " - (" + pos + "/" + total + ") " + name + "... ", worker); diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ClassesListTreeModel.java b/src/com/jpexs/decompiler/flash/gui/abc/ClassesListTreeModel.java index e9df98dba..fe82be14d 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ClassesListTreeModel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ClassesListTreeModel.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.gui.abc; import com.jpexs.decompiler.flash.AppResources; import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; @@ -25,6 +26,7 @@ import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.gui.AppStrings; import com.jpexs.decompiler.flash.timeline.AS3Package; import com.jpexs.decompiler.flash.treeitems.AS3ClassTreeItem; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.graph.DottedChain; import java.util.ArrayList; import java.util.List; @@ -40,7 +42,7 @@ import javax.swing.tree.TreePath; */ public class ClassesListTreeModel extends AS3ClassTreeItem implements TreeModel { - private final SWF swf; + private final Openable openable; private List list; @@ -58,18 +60,36 @@ public class ClassesListTreeModel extends AS3ClassTreeItem implements TreeModel super(null, null, null); this.flat = flat; root = new AS3Package(null, swf, flat, false); - this.swf = swf; + this.openable = swf; this.list = swf.getAS3Packs(); setFilter(null); } + + public ClassesListTreeModel(ABC abc, boolean flat) { + super(null, null, null); + this.flat = flat; + root = new AS3Package(null, abc, flat, false); + this.openable = abc; + List allAbcs = new ArrayList<>(); + allAbcs.add(abc); + this.list = abc.getScriptPacks(null, allAbcs); + setFilter(null); + } @Override - public SWF getSwf() { - return swf; + public Openable getOpenable() { + return openable; } public final void update() { - this.list = swf.getAS3Packs(); + if (openable instanceof SWF) { + this.list = ((SWF)openable).getAS3Packs(); + } else if (openable instanceof ABC) { + ABC abc = (ABC) openable; + List allAbcs = new ArrayList<>(); + allAbcs.add(abc); + this.list = abc.getScriptPacks(null, allAbcs); + } TreeModelEvent event = new TreeModelEvent(this, new TreePath(root)); for (TreeModelListener listener : listeners) { listener.treeStructureChanged(event); @@ -81,8 +101,10 @@ public class ClassesListTreeModel extends AS3ClassTreeItem implements TreeModel List ignoredClasses = new ArrayList<>(); List ignoredNss = new ArrayList<>(); - if (Configuration._ignoreAdditionalFlexClasses.get()) { - getSwf().getFlexMainClass(ignoredClasses, ignoredNss); + if (Configuration._ignoreAdditionalFlexClasses.get()) { + if (openable instanceof SWF) { + ((SWF)openable).getFlexMainClass(ignoredClasses, ignoredNss); + } } filter = (filter == null || filter.isEmpty()) ? null : filter.toLowerCase(Locale.ENGLISH); @@ -124,7 +146,7 @@ public class ClassesListTreeModel extends AS3ClassTreeItem implements TreeModel } AS3Package pkg = root.getSubPackage(fullName); if (pkg == null) { - pkg = new AS3Package(fullName, swf, true, defaultPackage); + pkg = new AS3Package(fullName, openable, true, defaultPackage); root.addSubPackage(pkg); } return pkg; @@ -134,7 +156,7 @@ public class ClassesListTreeModel extends AS3ClassTreeItem implements TreeModel String pathElement = packageStr.get(i); AS3Package pkg = parent.getSubPackage(pathElement); if (pkg == null) { - pkg = new AS3Package(pathElement, swf, false, false); + pkg = new AS3Package(pathElement, openable, false, false); parent.addSubPackage(pkg); } @@ -238,11 +260,11 @@ public class ClassesListTreeModel extends AS3ClassTreeItem implements TreeModel return false; } - return swf.equals(((ClassesListTreeModel) obj).swf); + return openable.equals(((ClassesListTreeModel) obj).openable); } @Override public int hashCode() { - return ClassesListTreeModel.class.hashCode() ^ swf.hashCode(); + return ClassesListTreeModel.class.hashCode() ^ openable.hashCode(); } } diff --git a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java index 566be47f9..b071f70d8 100644 --- a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java +++ b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java @@ -626,7 +626,7 @@ public class DumpTree extends JTree { return null; } long address = range.getPos(); - return searchTimelinedForTag(item.getSwf(), address); + return searchTimelinedForTag((SWF) item.getOpenable(), address); } public Timelined getTimelinedForItem(TreeItem item) { @@ -674,7 +674,7 @@ public class DumpTree extends JTree { for (DumpInfo sd : d.getChildInfos()) { if (sd instanceof DumpInfoSwfNode) { DumpInfoSwfNode si = (DumpInfoSwfNode) sd; - if (si.getSwf() == item.getSwf()) { + if (si.getSwf() == item.getOpenable()) { DumpInfo di = si; while (model.getChildCount(di) > 0) { boolean found = false; diff --git a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTreeModel.java b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTreeModel.java index 5452fb378..eb869b3fe 100644 --- a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTreeModel.java +++ b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTreeModel.java @@ -18,7 +18,8 @@ package com.jpexs.decompiler.flash.gui.dumpview; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.dumpview.DumpInfo; -import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.decompiler.flash.treeitems.Openable; +import com.jpexs.decompiler.flash.treeitems.OpenableList; import java.util.ArrayList; import java.util.List; import javax.swing.event.TreeModelEvent; @@ -36,20 +37,23 @@ public final class DumpTreeModel implements TreeModel { private final List listeners = new ArrayList<>(); - private final List swfs; + private final List openables; - public DumpTreeModel(List swfs) { - this.swfs = swfs; + public DumpTreeModel(List openables) { + this.openables = openables; root = new DumpInfo("root", "", null, 0, 0); updateSwfs(); } public void updateSwfs() { root.getChildInfos().clear(); - for (SWFList swfList : swfs) { - for (SWF swf : swfList) { - swf.dumpInfo.name = swf.getFileTitle(); - root.getChildInfos().add(swf.dumpInfo); + for (OpenableList openableList : openables) { + for (Openable openable : openableList) { + if (openable instanceof SWF) { + SWF swf = (SWF) openable; + swf.dumpInfo.name = swf.getFileTitle(); + root.getChildInfos().add(swf.dumpInfo); + } } } diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/abc16.png b/src/com/jpexs/decompiler/flash/gui/graphics/abc16.png new file mode 100644 index 000000000..5861fdc0d Binary files /dev/null and b/src/com/jpexs/decompiler/flash/gui/graphics/abc16.png differ diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index 6c823de20..a189e59a3 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -978,4 +978,8 @@ contextmenu.unpin.others = Unpin others menu.tools.otherTools.clearPinnedItems = Clear pinned items -menu.settings.flattenASPackages = Flatten ActionScript packages \ No newline at end of file +menu.settings.flattenASPackages = Flatten ActionScript packages + +work.reading.abc = Reading ABC + +filter.abc = ActionScript 3 bytecode files (*.abc) \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties index 00555236c..9a9b18e0d 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties @@ -950,4 +950,8 @@ contextmenu.unpin.others = Odepnout ostatn\u00ed menu.tools.otherTools.clearPinnedItems = Vymazat p\u0159ipnut\u00e9 polo\u017eky -menu.settings.flattenASPackages = Zplo\u0161tit bal\u00ed\u010dky ActionScriptu \ No newline at end of file +menu.settings.flattenASPackages = Zplo\u0161tit bal\u00ed\u010dky ActionScriptu + +work.reading.abc = \u010cten\u00ed ABC + +filter.abc = ActionScript 3 bytecode soubory (*.abc) \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/SearchDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/SearchDialog.properties index cb9d1077f..d057dbd5f 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/SearchDialog.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/SearchDialog.properties @@ -36,4 +36,7 @@ label.scope = Scope: scope.currentFile = Current SWF scope.selection = Selection (%selection%) scope.allFiles = All opened SWFs -scope.selection.items = %count% items \ No newline at end of file +scope.selection.items = %count% items + +#after 16.3.1 +scope.currentFile.abc = Current ABC \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/SearchDialog_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/SearchDialog_cs.properties index dde7c5eb5..b14f5a7e4 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/SearchDialog_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/SearchDialog_cs.properties @@ -35,4 +35,7 @@ label.scope = Rozsah: scope.currentFile = Aktu\u00e1ln\u00ed SWF scope.selection = V\u00fdb\u011br (%selection%) scope.allFiles = V\u0161echny otev\u0159en\u00e9 SWF -scope.selection.items = %count% polo\u017eek \ No newline at end of file +scope.selection.items = %count% polo\u017eek + +#after 16.3.1 +scope.currentFile.abc = Nyn\u011bj\u0161\u00ed ABC \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTree.java b/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTree.java index 3212644e2..4eda30f93 100644 --- a/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTree.java +++ b/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTree.java @@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.tags.DoInitActionTag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.timeline.Frame; import com.jpexs.decompiler.flash.timeline.Timelined; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.flash.treeitems.TreeItem; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; @@ -58,8 +59,8 @@ public class TagListTree extends AbstractTagTree { } @Override - public List getSelection(SWF swf) { - return getSelection(swf, getAllSelected()); + public List getSelection(Openable openable) { + return getSelection(openable, getAllSelected()); } @Override diff --git a/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTreeCellRenderer.java b/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTreeCellRenderer.java index 70e92d5e8..ec4f68730 100644 --- a/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTreeCellRenderer.java +++ b/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTreeCellRenderer.java @@ -23,7 +23,7 @@ import com.jpexs.decompiler.flash.gui.tagtree.AbstractTagTreeModel; import com.jpexs.decompiler.flash.gui.tagtree.TagTree; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.timeline.Frame; -import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.decompiler.flash.treeitems.OpenableList; import com.jpexs.decompiler.flash.treeitems.TreeItem; import java.awt.AlphaComposite; import java.awt.Color; @@ -84,7 +84,7 @@ public class TagListTreeCellRenderer extends DefaultTreeCellRenderer { val = (TreeItem) value; } - if (val != null && !(val instanceof SWFList) && val.getSwf() == null) { + if (val != null && !(val instanceof OpenableList) && val.getOpenable()== null) { // SWF was closed value = null; } diff --git a/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTreeModel.java b/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTreeModel.java index 6c8c80733..81ab66cb8 100644 --- a/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTreeModel.java +++ b/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTreeModel.java @@ -28,7 +28,8 @@ import com.jpexs.decompiler.flash.tags.base.ButtonTag; import com.jpexs.decompiler.flash.timeline.Frame; import com.jpexs.decompiler.flash.timeline.Timelined; import com.jpexs.decompiler.flash.treeitems.HeaderItem; -import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.decompiler.flash.treeitems.Openable; +import com.jpexs.decompiler.flash.treeitems.OpenableList; import com.jpexs.decompiler.flash.treeitems.TreeItem; import java.util.ArrayList; import java.util.HashMap; @@ -46,11 +47,11 @@ public class TagListTreeModel extends AbstractTagTreeModel { private final TagListTreeRoot root = new TagListTreeRoot(); - private List swfs; + private List swfs; private Map swfHeaders = new HashMap<>(); - public TagListTreeModel(List swfs) { + public TagListTreeModel(List swfs) { this.swfs = swfs; } @@ -80,13 +81,13 @@ public class TagListTreeModel extends AbstractTagTreeModel { TreeItem parentNode = (TreeItem) parent; if (parentNode == root) { - SWFList swfList = swfs.get(index); + OpenableList swfList = swfs.get(index); if (!swfList.isBundle()) { return swfList.get(0); } return swfList; - } else if (parentNode instanceof SWFList) { - return ((SWFList) parentNode).swfs.get(index); + } else if (parentNode instanceof OpenableList) { + return ((OpenableList) parentNode).items.get(index); } else if (parentNode instanceof SWF) { if (index == 0) { return getSwfHeader((SWF) parentNode); @@ -118,8 +119,8 @@ public class TagListTreeModel extends AbstractTagTreeModel { TreeItem parentNode = (TreeItem) parent; if (parentNode == root) { return swfs.size(); - } else if (parentNode instanceof SWFList) { - return ((SWFList) parentNode).swfs.size(); + } else if (parentNode instanceof OpenableList) { + return ((OpenableList) parentNode).items.size(); } else if (parentNode instanceof SWF) { return ((SWF) parentNode).getTimeline().getFrameCount() + 1; } else if (parentNode instanceof HeaderItem) { @@ -156,12 +157,12 @@ public class TagListTreeModel extends AbstractTagTreeModel { TreeItem parentNode = (TreeItem) parent; if (parentNode == root) { - SWFList swfList = child instanceof SWFList - ? (SWFList) child - : ((SWF) child).swfList; - return swfs.indexOf(swfList); - } else if (parentNode instanceof SWFList) { - return ((SWFList) parentNode).swfs.indexOf(child); + OpenableList openableListswfList = child instanceof OpenableList + ? (OpenableList) child + : ((Openable) child).getOpenableList(); + return swfs.indexOf(openableListswfList); + } else if (parentNode instanceof OpenableList) { + return ((OpenableList) parentNode).items.indexOf(child); } else if (parentNode instanceof SWF) { HeaderItem header = getSwfHeader((SWF) parentNode); @@ -210,7 +211,7 @@ public class TagListTreeModel extends AbstractTagTreeModel { List toRemove = new ArrayList<>(); for (SWF swf : swfHeaders.keySet()) { SWF swf2 = swf.getRootSwf(); - if (swf2 != null && !swfs.contains(swf2.swfList)) { + if (swf2 != null && !swfs.contains(swf2.openableList)) { toRemove.add(swf); } } @@ -274,15 +275,15 @@ public class TagListTreeModel extends AbstractTagTreeModel { TreeItem parentNode = (TreeItem) parent; if (parentNode == root) { List result = new ArrayList<>(swfs.size()); - for (SWFList swfList : swfs) { + for (OpenableList swfList : swfs) { if (!swfList.isBundle()) { result.add(swfList.get(0)); } result.add(swfList); } return result; - } else if (parentNode instanceof SWFList) { - return ((SWFList) parentNode).swfs; + } else if (parentNode instanceof OpenableList) { + return ((OpenableList) parentNode).items; } else if (parentNode instanceof SWF) { List ret = new ArrayList<>(); ret.add(getSwfHeader((SWF)parentNode)); diff --git a/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTreeRoot.java b/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTreeRoot.java index fa1b82bac..08be5b51a 100644 --- a/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTreeRoot.java +++ b/src/com/jpexs/decompiler/flash/gui/taglistview/TagListTreeRoot.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.gui.taglistview; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.gui.tagtree.TreeRoot; +import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.flash.treeitems.TreeItem; /** @@ -27,7 +28,7 @@ import com.jpexs.decompiler.flash.treeitems.TreeItem; public class TagListTreeRoot implements TreeItem, TreeRoot{ @Override - public SWF getSwf() { + public Openable getOpenable() { return null; } diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/AbstractTagTree.java b/src/com/jpexs/decompiler/flash/gui/tagtree/AbstractTagTree.java index e47d63c2a..3d3f0e26e 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/AbstractTagTree.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/AbstractTagTree.java @@ -18,7 +18,8 @@ package com.jpexs.decompiler.flash.gui.tagtree; import com.jpexs.decompiler.flash.SWC; import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.ZippedSWFBundle; +import com.jpexs.decompiler.flash.ZippedBundle; +import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; @@ -88,7 +89,8 @@ import com.jpexs.decompiler.flash.timeline.FrameScript; import com.jpexs.decompiler.flash.timeline.TagScript; import com.jpexs.decompiler.flash.treeitems.FolderItem; import com.jpexs.decompiler.flash.treeitems.HeaderItem; -import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.decompiler.flash.treeitems.Openable; +import com.jpexs.decompiler.flash.treeitems.OpenableList; import com.jpexs.decompiler.flash.treeitems.TreeItem; import com.jpexs.decompiler.flash.types.BUTTONCONDACTION; import com.jpexs.decompiler.flash.types.BUTTONRECORD; @@ -332,10 +334,10 @@ public abstract class AbstractTagTree extends JTree { return TreeNodeType.FLASH; } - if (t instanceof SWFList) { - SWFList slist = (SWFList) t; + if (t instanceof OpenableList) { + OpenableList slist = (OpenableList) t; if (slist.isBundle()) { - if (slist.bundle.getClass() == ZippedSWFBundle.class) { + if (slist.bundle.getClass() == ZippedBundle.class) { return TreeNodeType.BUNDLE_ZIP; } else if (slist.bundle.getClass() == SWC.class) { return TreeNodeType.BUNDLE_SWC; @@ -382,6 +384,10 @@ public abstract class AbstractTagTree extends JTree { if (t instanceof FolderItem) { return TreeNodeType.FOLDER; } + + if (t instanceof ABC) { + return TreeNodeType.ABC; + } return TreeNodeType.FOLDER; } @@ -493,15 +499,15 @@ public abstract class AbstractTagTree extends JTree { return !getSelection(mainPanel.getCurrentSwf()).isEmpty(); } - public abstract List getSelection(SWF swf); + public abstract List getSelection(Openable openable); - public static List getSelection(SWF swf, List sel) { + public static List getSelection(Openable openable, List sel) { List ret = new ArrayList<>(); for (TreeItem d : sel) { - if (d instanceof SWFList) { + if (d instanceof OpenableList) { continue; } - if (swf != null && d.getSwf() != swf) { + if (openable != null && d.getOpenable() != openable) { continue; } @@ -574,7 +580,7 @@ public abstract class AbstractTagTree extends JTree { return ret; } - public void updateSwfs(SWF[] swfs) { + public void updateSwfs(Openable[] openables) { AbstractTagTreeModel ttm = getModel(); if (ttm != null) { List> expandedNodes = View.getExpandedNodes(this); diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java index 71a4596e1..e81b854a3 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTree.java @@ -88,7 +88,8 @@ import com.jpexs.decompiler.flash.tags.gfx.DefineExternalImage2; import com.jpexs.decompiler.flash.tags.gfx.DefineSubImage; import com.jpexs.decompiler.flash.treeitems.AS3ClassTreeItem; import com.jpexs.decompiler.flash.treeitems.FolderItem; -import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.decompiler.flash.treeitems.Openable; +import com.jpexs.decompiler.flash.treeitems.OpenableList; import com.jpexs.decompiler.flash.treeitems.TreeItem; import java.awt.AlphaComposite; import java.awt.Color; @@ -154,7 +155,7 @@ public class TagTree extends AbstractTagTree { boolean hasFocus) { TreeItem val = (TreeItem) value; - if (val != null && !(val instanceof SWFList) && val.getSwf() == null) { + if (val != null && !(val instanceof OpenableList) && val.getOpenable() == null) { // SWF was closed value = null; } @@ -307,7 +308,7 @@ public class TagTree extends AbstractTagTree { } @Override - public List getSelection(SWF swf) { + public List getSelection(Openable openable) { List sel; if (mainPanel.folderPreviewPanel.selectedItems.isEmpty()) { sel = getAllSelected(); @@ -319,7 +320,7 @@ public class TagTree extends AbstractTagTree { getAllSubs(treeItem, sel); } } - return getSelection(swf, sel); + return getSelection(openable, sel); } public List getTagsWithType(List list, TreeNodeType type) { diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java index ac327e81f..c5f367fdc 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java @@ -76,7 +76,8 @@ import com.jpexs.decompiler.flash.timeline.Timelined; import com.jpexs.decompiler.flash.treeitems.AS3ClassTreeItem; import com.jpexs.decompiler.flash.treeitems.FolderItem; import com.jpexs.decompiler.flash.treeitems.HeaderItem; -import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.decompiler.flash.treeitems.Openable; +import com.jpexs.decompiler.flash.treeitems.OpenableList; import com.jpexs.decompiler.flash.treeitems.TreeItem; import com.jpexs.decompiler.flash.types.BUTTONCONDACTION; import com.jpexs.decompiler.flash.types.BUTTONRECORD; @@ -529,7 +530,7 @@ public class TagTreeContextMenu extends JPopupMenu { AbstractTagTree tree = getTree(); - final List swfs = mainPanel.getSwfs(); + final List swfs = mainPanel.getSwfs(); boolean canRemove = true; boolean allDoNotHaveDependencies = true; @@ -659,13 +660,13 @@ public class TagTreeContextMenu extends JPopupMenu { boolean allSelectedIsSwf = true; for (TreeItem item : items) { - if (!(item instanceof SWF) && !(item instanceof SWFList)) { + if (!(item instanceof SWF) && !(item instanceof OpenableList)) { allSelectedIsSwf = false; break; } else if (item instanceof SWF) { SWF swf = (SWF) item; // Do not allow to close SWF in bundle - if (swf.swfList != null && swf.swfList.isBundle()) { + if (swf.openableList != null && swf.openableList.isBundle()) { allSelectedIsSwf = false; } } @@ -674,13 +675,19 @@ public class TagTreeContextMenu extends JPopupMenu { boolean allSelectedIsInTheSameSwf = true; SWF singleSwf = null; for (TreeItem item : items) { - if (item instanceof SWFList) { + if (item instanceof OpenableList) { allSelectedIsInTheSameSwf = false; break; } if (singleSwf == null) { - singleSwf = item.getSwf(); - } else if (singleSwf != item.getSwf()) { + Openable singleOpenable = item.getOpenable(); + if (singleOpenable instanceof SWF) { + singleSwf = (SWF) singleOpenable; + } else { + allSelectedIsInTheSameSwf = false; + break; + } + } else if (singleSwf != item.getOpenable()) { allSelectedIsInTheSameSwf = false; break; } @@ -933,12 +940,12 @@ public class TagTreeContextMenu extends JPopupMenu { } if (firstItem instanceof SWF) { SWF firstSwf = (SWF) firstItem; - if (firstSwf.swfList != null && !firstSwf.swfList.isBundle() && firstSwf.swfList.size() == 1) { + if (firstSwf.openableList != null && !firstSwf.openableList.isBundle() && firstSwf.openableList.size() == 1) { moveUpMenuItem.setVisible(true); moveDownMenuItem.setVisible(true); } } - if (firstItem instanceof SWFList) { + if (firstItem instanceof OpenableList) { moveUpMenuItem.setVisible(true); moveDownMenuItem.setVisible(true); } @@ -993,7 +1000,7 @@ public class TagTreeContextMenu extends JPopupMenu { copyTagToWithDependenciesMenu.setVisible(true); } if (allSelectedIsInTheSameSwf && allSelectedIsTag && swfs.size() > 1) { - for (SWFList targetSwfList : swfs) { + for (OpenableList targetSwfList : swfs) { if ((targetSwfList.size() == 1) && (targetSwfList.get(0) == singleSwf)) { continue; } @@ -1238,7 +1245,7 @@ public class TagTreeContextMenu extends JPopupMenu { Logger.getLogger(TagTreeContextMenu.class.getName()).log(Level.SEVERE, null, ex); } - SWF swf = item.getSwf(); + SWF swf = (SWF) item.getOpenable(); Timelined selectedTimelined = null; Tag selectedTag = null; boolean selectNext = false; @@ -1251,7 +1258,7 @@ public class TagTreeContextMenu extends JPopupMenu { selectedTag = frame.allInnerTags.get(frame.allInnerTags.size() - 1); } } else if (item instanceof FolderItem) { - selectedTimelined = item.getSwf(); + selectedTimelined = (SWF) item.getOpenable(); } else if (item instanceof SWF) { selectedTimelined = (SWF) item; } @@ -1280,7 +1287,7 @@ public class TagTreeContextMenu extends JPopupMenu { private void addTagBeforeActionPerformed(ActionEvent evt, TreeItem item, Class cl) { try { - SWF swf = item.getSwf(); + SWF swf = (SWF) item.getOpenable(); Tag t = (Tag) cl.getDeclaredConstructor(SWF.class).newInstance(new Object[]{swf}); Timelined timelined = null; @@ -1319,7 +1326,7 @@ public class TagTreeContextMenu extends JPopupMenu { private void addTagAfterActionPerformed(ActionEvent evt, TreeItem item, Class cl) { try { - SWF swf = item.getSwf(); + SWF swf = (SWF) item.getOpenable(); Tag t = (Tag) cl.getDeclaredConstructor(SWF.class).newInstance(new Object[]{swf}); Timelined timelined = null; @@ -1438,7 +1445,7 @@ public class TagTreeContextMenu extends JPopupMenu { return; } - SWF swf = itemr.getSwf(); + SWF swf = (SWF) itemr.getOpenable(); CharacterTag characterTag = (CharacterTag) itemr; int characterId = characterTag.getCharacterId(); ReplaceCharacterDialog replaceCharacterDialog = new ReplaceCharacterDialog(Main.getDefaultDialogsOwner()); @@ -1455,7 +1462,7 @@ public class TagTreeContextMenu extends JPopupMenu { return; } - SWF swf = itemr.getSwf(); + SWF swf = (SWF) itemr.getOpenable(); CharacterTag characterTag = (CharacterTag) itemr; int characterId = characterTag.getCharacterId(); ReplaceCharacterDialog replaceCharacterDialog = new ReplaceCharacterDialog(Main.getDefaultDialogsOwner()); @@ -1515,7 +1522,7 @@ public class TagTreeContextMenu extends JPopupMenu { } HasCharacterId hasCharacterId = (HasCharacterId) itemj; - mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), itemj.getSwf().getCharacter(hasCharacterId.getCharacterId())); + mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), ((SWF) itemj.getOpenable()).getCharacter(hasCharacterId.getCharacterId())); } private void expandRecursiveActionPerformed(ActionEvent evt) { @@ -1540,11 +1547,21 @@ public class TagTreeContextMenu extends JPopupMenu { String preselected = ""; if (sel.get(0) instanceof ClassesListTreeModel) { ClassesListTreeModel cl = (ClassesListTreeModel) sel.get(0); - swf = cl.getSwf(); + Openable openable = cl.getOpenable(); + if (openable instanceof SWF) { + swf = (SWF) openable; + } else { + swf = ((ABC)openable).getSwf(); + } } if (sel.get(0) instanceof AS3Package) { AS3Package pkg = (AS3Package) sel.get(0); - swf = pkg.getSwf(); + Openable openable = pkg.getOpenable(); + if (openable instanceof SWF) { + swf = (SWF) openable; + } else { + swf = ((ABC)openable).getSwf(); + } TreePath tp = tree.getSelectionPaths()[0]; Object[] path = tp.getPath(); for (int p = path.length - 1; p >= 0; p--) { @@ -1649,7 +1666,7 @@ public class TagTreeContextMenu extends JPopupMenu { if (sel.get(0) instanceof FolderItem) { FolderItem folder = (FolderItem) sel.get(0); - SWF swf = folder.getSwf(); + SWF swf = (SWF) folder.getOpenable(); AddScriptDialog addScriptDialog = new AddScriptDialog(Main.getDefaultDialogsOwner(), swf); if (addScriptDialog.showDialog() == JOptionPane.OK_OPTION) { @@ -2275,8 +2292,10 @@ public class TagTreeContextMenu extends JPopupMenu { ScriptPack sp = (ScriptPack) item; sp.delete(sp.abc, true); abcsToPack.add(sp.abc); - swfsToClearCache.add(sp.getSwf()); - for (ABCContainerTag ct : sp.getSwf().getAbcList()) { + Openable openable = sp.getOpenable(); + SWF swf = (openable instanceof SWF) ? (SWF) openable : ((ABC)openable).getSwf(); + swfsToClearCache.add(swf); + for (ABCContainerTag ct : swf.getAbcList()) { if (ct.getABC() == sp.abc) { ((Tag) ct).setModified(true); break; @@ -2377,10 +2396,10 @@ public class TagTreeContextMenu extends JPopupMenu { swf.clearTagSwfs(); mainPanel.refreshTree(); } else { - Main.closeFile(swf.swfList); + Main.closeFile(swf.openableList); } - } else if (item instanceof SWFList) { - Main.closeFile((SWFList) item); + } else if (item instanceof OpenableList) { + Main.closeFile((OpenableList) item); } } } @@ -2394,7 +2413,7 @@ public class TagTreeContextMenu extends JPopupMenu { try { for (TreeItem item : items) { - SWF swf = item.getSwf(); + SWF swf = (SWF)item.getOpenable(); swfs.add(swf); if (item instanceof Tag) { @@ -2591,7 +2610,7 @@ public class TagTreeContextMenu extends JPopupMenu { frame = (Frame) item; timelined = frame.timeline.timelined; } else if (item instanceof FolderItem) { //frames folder - timelined = item.getSwf(); + timelined = (SWF) item.getOpenable(); } else { timelined = (Timelined) item; } @@ -2646,16 +2665,18 @@ public class TagTreeContextMenu extends JPopupMenu { addFrames(false); //this works because timeline is selected, no frame } - private void addCopyMoveToMenusSwfList(int kind, SWF singleSwf, SWFList targetSwfList, JMenuItem menu, List items) { + private void addCopyMoveToMenusSwfList(int kind, SWF singleSwf, OpenableList targetSwfList, JMenuItem menu, List items) { if (targetSwfList.isBundle()) { JMenu bundleMenu = new JMenu(targetSwfList.name); bundleMenu.setIcon(AbstractTagTree.getIconForType(AbstractTagTree.getTreeNodeType(targetSwfList))); menu.add(bundleMenu); menu = bundleMenu; } - for (final SWF targetSwf : targetSwfList) { - if (targetSwf != singleSwf) { - addCopyMoveToMenus(kind, menu, items, targetSwf.getShortFileName(), targetSwf); + for (final Openable targetOpenable : targetSwfList) { + if (targetOpenable instanceof SWF) { + if (targetOpenable != singleSwf) { + addCopyMoveToMenus(kind, menu, items, targetOpenable.getShortFileName(), (SWF) targetOpenable); + } } } } @@ -2728,7 +2749,11 @@ public class TagTreeContextMenu extends JPopupMenu { } private Set getDependenciesSet(List items) { - SWF sourceSwf = items.get(0).getSwf(); + Openable sourceOpenable = items.get(0).getOpenable(); + if (sourceOpenable instanceof ABC) { + return new LinkedHashSet<>(); + } + SWF sourceSwf = (SWF) items.get(0).getOpenable(); Set newItems = new LinkedHashSet<>(); for (TreeItem item : items) { Set needed = new LinkedHashSet<>(); @@ -2966,32 +2991,33 @@ public class TagTreeContextMenu extends JPopupMenu { } public void importScriptsActionPerformed(ActionEvent evt) { - SWF swf = getTree().getCurrentTreeItem().getSwf(); + Openable openable = getTree().getCurrentTreeItem().getOpenable(); + SWF swf = (openable instanceof SWF) ? (SWF) openable : ((ABC)openable).getSwf(); mainPanel.importScript(swf); } public void importTextsActionPerformed(ActionEvent evt) { - SWF swf = getTree().getCurrentTreeItem().getSwf(); + SWF swf = (SWF) getTree().getCurrentTreeItem().getOpenable(); mainPanel.importText(swf); } public void importImagesActionPerformed(ActionEvent evt) { - SWF swf = getTree().getCurrentTreeItem().getSwf(); + SWF swf = (SWF) getTree().getCurrentTreeItem().getOpenable(); mainPanel.importImage(swf); } public void importShapesActionPerformed(ActionEvent evt) { - SWF swf = getTree().getCurrentTreeItem().getSwf(); + SWF swf = (SWF) getTree().getCurrentTreeItem().getOpenable(); mainPanel.importShape(swf, false); } public void importShapesNoFillActionPerformed(ActionEvent evt) { - SWF swf = getTree().getCurrentTreeItem().getSwf(); + SWF swf = (SWF) getTree().getCurrentTreeItem().getOpenable(); mainPanel.importShape(swf, true); } public void importSymbolClassActionPerformed(ActionEvent evt) { - SWF swf = getTree().getCurrentTreeItem().getSwf(); + SWF swf = (SWF) getTree().getCurrentTreeItem().getOpenable(); mainPanel.importSymbolClass(swf); } @@ -3004,7 +3030,7 @@ public class TagTreeContextMenu extends JPopupMenu { } public void moveUpDown(TreeItem item, boolean up) { - if ((item instanceof SWF) || (item instanceof SWFList)) { + if ((item instanceof SWF) || (item instanceof OpenableList)) { mainPanel.moveSwfListUpDown(item, up); return; } @@ -3080,6 +3106,6 @@ public class TagTreeContextMenu extends JPopupMenu { while (item.binaryData != null) { item = item.binaryData.getSwf(); } - Main.reloadFile(item.swfList); + Main.reloadFile(item.openableList); } } diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeModel.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeModel.java index f532cfe23..d064b5b47 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeModel.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeModel.java @@ -17,6 +17,7 @@ package com.jpexs.decompiler.flash.gui.tagtree; import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.gui.AppStrings; import com.jpexs.decompiler.flash.gui.TreeNodeType; @@ -45,12 +46,14 @@ import com.jpexs.decompiler.flash.timeline.Timelined; import com.jpexs.decompiler.flash.treeitems.AS3ClassTreeItem; import com.jpexs.decompiler.flash.treeitems.FolderItem; import com.jpexs.decompiler.flash.treeitems.HeaderItem; -import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.decompiler.flash.treeitems.Openable; +import com.jpexs.decompiler.flash.treeitems.OpenableList; import com.jpexs.decompiler.flash.treeitems.TreeItem; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.WeakHashMap; import javax.swing.event.TreeModelEvent; import javax.swing.event.TreeModelListener; import javax.swing.tree.TreePath; @@ -91,15 +94,17 @@ public class TagTreeModel extends AbstractTagTreeModel { private final TagTreeRoot root = new TagTreeRoot(); - private final List swfs; + private final List swfs; private final Map swfInfos = new HashMap<>(); private final boolean addAllFolders; private final Map pathCache = new HashMap<>(); + + private final Map abcClassesTree = new WeakHashMap<>(); - public TagTreeModel(List swfs, boolean addAllFolders) { + public TagTreeModel(List swfs, boolean addAllFolders) { this.swfs = swfs; this.addAllFolders = addAllFolders; //Main.startWork(AppStrings.translate("work.buildingscripttree") + "..."); @@ -116,7 +121,7 @@ public class TagTreeModel extends AbstractTagTreeModel { List toRemove = new ArrayList<>(); for (SWF swf : swfInfos.keySet()) { SWF swf2 = swf.getRootSwf(); - if (swf2 != null && !swfs.contains(swf2.swfList)) { + if (swf2 != null && !swfs.contains(swf2.openableList)) { toRemove.add(swf); } } @@ -499,15 +504,15 @@ public class TagTreeModel extends AbstractTagTreeModel { } if (parentNode == root) { - for (SWFList swfList : swfs) { + for (OpenableList swfList : swfs) { if (!swfList.isBundle()) { result.add(swfList.get(0)); } result.add(swfList); } return result; - } else if (parentNode instanceof SWFList) { - return ((SWFList) parentNode).swfs; + } else if (parentNode instanceof OpenableList) { + return ((OpenableList) parentNode).items; } else if (parentNode instanceof SWF) { return getSwfFolders((SWF) parentNode); } else if (parentNode instanceof FolderItem) { @@ -535,7 +540,7 @@ public class TagTreeModel extends AbstractTagTreeModel { TreeItem item = result.get(i); if (item instanceof Tag) { Tag resultTag = (Tag) item; - Map currentTagScriptCache = getTagScriptCache(item.getSwf()); + Map currentTagScriptCache = getTagScriptCache((SWF) item.getOpenable()); TagScript tagScript = currentTagScriptCache.get(resultTag); if (tagScript == null) { List subNodes = new ArrayList<>(); @@ -544,7 +549,7 @@ public class TagTreeModel extends AbstractTagTreeModel { subNodes.add(item2); } } - tagScript = new TagScript(item.getSwf(), resultTag, subNodes); + tagScript = new TagScript((SWF) item.getOpenable(), resultTag, subNodes); currentTagScriptCache.put(resultTag, tagScript); } result.set(i, tagScript); @@ -564,6 +569,9 @@ public class TagTreeModel extends AbstractTagTreeModel { } } else if (parentNode instanceof ButtonTag) { return ((ButtonTag) parentNode).getRecords(); + } else if (parentNode instanceof ABC) { + ClassesListTreeModel classesTreeModel = getClassesListTreeModel((ABC) parentNode); + return classesTreeModel.getAllChildren(classesTreeModel.getRoot()); } return result; @@ -585,13 +593,13 @@ public class TagTreeModel extends AbstractTagTreeModel { } if (parentNode == root) { - SWFList swfList = swfs.get(index); - if (!swfList.isBundle()) { - return swfList.get(0); + OpenableList openableList = swfs.get(index); + if (!openableList.isBundle()) { + return openableList.get(0); } - return swfList; - } else if (parentNode instanceof SWFList) { - return ((SWFList) parentNode).swfs.get(index); + return openableList; + } else if (parentNode instanceof OpenableList) { + return ((OpenableList) parentNode).items.get(index); } else if (parentNode instanceof SWF) { return getSwfFolders((SWF) parentNode).get(index); } else if (parentNode instanceof FolderItem) { @@ -615,7 +623,7 @@ public class TagTreeModel extends AbstractTagTreeModel { } if (result instanceof Tag) { Tag resultTag = (Tag) result; - Map currentTagScriptCache = getTagScriptCache(result.getSwf()); + Map currentTagScriptCache = getTagScriptCache((SWF) result.getOpenable()); TagScript tagScript = currentTagScriptCache.get(resultTag); if (tagScript == null) { List subNodes = new ArrayList<>(); @@ -624,7 +632,7 @@ public class TagTreeModel extends AbstractTagTreeModel { subNodes.add(item); } } - tagScript = new TagScript(result.getSwf(), resultTag, subNodes); + tagScript = new TagScript((SWF) result.getOpenable(), resultTag, subNodes); currentTagScriptCache.put(resultTag, tagScript); } result = tagScript; @@ -639,6 +647,9 @@ public class TagTreeModel extends AbstractTagTreeModel { return ((AS3Package) parentNode).getChild(index); } else if (parentNode instanceof ButtonTag) { return ((ButtonTag) parentNode).getRecords().get(index); + } else if (parentNode instanceof ABC) { + ClassesListTreeModel classesTreeModel = getClassesListTreeModel((ABC) parentNode); + return classesTreeModel.getChild(classesTreeModel.getRoot(), index); } throw new Error("Unsupported parent type: " + parentNode.getClass().getName()); @@ -653,8 +664,8 @@ public class TagTreeModel extends AbstractTagTreeModel { } if (parentNode == root) { return mappedSize + swfs.size(); - } else if (parentNode instanceof SWFList) { - return mappedSize + ((SWFList) parentNode).swfs.size(); + } else if (parentNode instanceof OpenableList) { + return mappedSize + ((OpenableList) parentNode).items.size(); } else if (parentNode instanceof SWF) { return mappedSize + getSwfFolders((SWF) parentNode).size(); } else if (parentNode instanceof HeaderItem) { @@ -683,6 +694,9 @@ public class TagTreeModel extends AbstractTagTreeModel { return mappedSize + ((ButtonTag) parentNode).getRecords().size(); } else if (parentNode instanceof CharacterTag) { return mappedSize; + } else if (parentNode instanceof ABC) { + ClassesListTreeModel classesTreeModel = getClassesListTreeModel((ABC) parentNode); + return classesTreeModel.getChildCount(classesTreeModel.getRoot()); } return 0; @@ -715,12 +729,12 @@ public class TagTreeModel extends AbstractTagTreeModel { baseIndex = mapped.size(); } if (parentNode == root) { - SWFList swfList = child instanceof SWFList - ? (SWFList) child - : ((SWF) child).swfList; - return indexOfAdd(baseIndex, swfs.indexOf(swfList)); - } else if (parentNode instanceof SWFList) { - return indexOfAdd(baseIndex, ((SWFList) parentNode).swfs.indexOf(childNode)); + OpenableList openableList = child instanceof OpenableList + ? (OpenableList) child + : ((Openable) child).getOpenableList(); + return indexOfAdd(baseIndex, swfs.indexOf(openableList)); + } else if (parentNode instanceof OpenableList) { + return indexOfAdd(baseIndex, ((OpenableList) parentNode).items.indexOf(childNode)); } else if (parentNode instanceof SWF) { return indexOfAdd(baseIndex, getSwfFolders((SWF) parentNode).indexOf(childNode)); } else if (parentNode instanceof FolderItem) { @@ -754,8 +768,21 @@ public class TagTreeModel extends AbstractTagTreeModel { return indexOfAdd(baseIndex, ((ButtonTag) parentNode).getRecords().indexOf(childNode)); } else if (parentNode instanceof CharacterTag) { return indexOfAdd(baseIndex, getMappedCharacters(((CharacterTag) parentNode).getSwf(), (CharacterTag) parentNode).indexOf(childNode)); + } else if (parentNode instanceof ABC) { + ClassesListTreeModel classesTreeModel = getClassesListTreeModel((ABC) parentNode); + return indexOfAdd(baseIndex, classesTreeModel.getIndexOfChild(classesTreeModel.getRoot(), childNode)); } return -1; } + + private ClassesListTreeModel getClassesListTreeModel(ABC abc) { + if (abcClassesTree.containsKey(abc)) { + return abcClassesTree.get(abc); + } + + ClassesListTreeModel model = new ClassesListTreeModel(abc, Configuration.flattenASPackages.get()); + abcClassesTree.put(abc, model); + return model; + } }