Added Apply unpacker menu on binary data

Added Harman unpacker for binary data
Added Multilevel binary data unpacking is possible
This commit is contained in:
Jindra Petřík
2023-11-23 19:43:42 +01:00
parent 8ad981ff25
commit 9741e8260a
23 changed files with 783 additions and 210 deletions

View File

@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.gui.hexview.HexView;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.base.BinaryDataInterface;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
@@ -39,13 +40,13 @@ public final class BinaryPanel extends JPanel {
private byte[] data;
private JPanel swfInsidePanel;
private JPanel swfOrPackedDataInsidePanel;
private DefineBinaryDataTag binaryDataTag = null;
private BinaryDataInterface binaryData = null;
private final MainPanel mainPanel;
private final JLabel swfInsideLabel;
private final JLabel swfOrPackedDataInsideLabel;
public BinaryPanel(final MainPanel mainPanel) {
super(new BorderLayout());
@@ -66,44 +67,50 @@ public final class BinaryPanel extends JPanel {
setBinaryData(binaryDataTag);
}
});*/
swfInsideLabel = new JLabel(AppStrings.translate("binarydata.swfInside"));
swfOrPackedDataInsideLabel = new JLabel(AppStrings.translate("binarydata.swfInside"));
swfInsidePanel = new JPanel();
swfInsidePanel.setBackground(new Color(253, 205, 137));
swfInsidePanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
swfInsidePanel.add(swfInsideLabel);
swfInsidePanel.setFocusable(true);
swfInsidePanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
swfInsidePanel.addMouseListener(new MouseAdapter() {
swfOrPackedDataInsidePanel = new JPanel();
swfOrPackedDataInsidePanel.setBackground(new Color(253, 205, 137));
swfOrPackedDataInsidePanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
swfOrPackedDataInsidePanel.add(swfOrPackedDataInsideLabel);
swfOrPackedDataInsidePanel.setFocusable(true);
swfOrPackedDataInsidePanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
swfOrPackedDataInsidePanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
mainPanel.loadFromBinaryTag(binaryDataTag);
swfInsidePanel.setVisible(false);
if (binaryData.getUsedPacker() != null) {
binaryData.unpack(binaryData.getUsedPacker());
}
mainPanel.loadFromBinaryTag(binaryData);
swfOrPackedDataInsidePanel.setVisible(false);
}
});
add(swfInsidePanel, BorderLayout.NORTH);
swfInsidePanel.setVisible(false);
add(swfOrPackedDataInsidePanel, BorderLayout.NORTH);
swfOrPackedDataInsidePanel.setVisible(false);
}
public void setBinaryData(DefineBinaryDataTag binaryDataTag) {
this.binaryDataTag = binaryDataTag;
data = binaryDataTag == null ? null : binaryDataTag.binaryData.getRangeData();
public void setBinaryData(BinaryDataInterface binaryData) {
this.binaryData = binaryData;
data = binaryData == null ? null : binaryData.getDataBytes().getRangeData();
if (data != null) {
hexEditor.setData(data, null, null);
boolean isSwfData = binaryDataTag.isSwfData();
boolean isSwfData = binaryData.isSwfData();
if (isSwfData) {
if (binaryDataTag.usedPacker != null) {
swfInsideLabel.setText(AppStrings.translate("binarydata.swfInside.packer").replace("%packer%", binaryDataTag.usedPacker.getName()));
} else {
swfInsideLabel.setText(AppStrings.translate("binarydata.swfInside"));
swfOrPackedDataInsideLabel.setText(AppStrings.translate("binarydata.swfInside"));
} else {
binaryData.detectPacker();
if (binaryData.getUsedPacker() != null) {
swfOrPackedDataInsideLabel.setText(AppStrings.translate("binarydata.dataInside.packer").replace("%packer%", binaryData.getUsedPacker().getName()));
}
}
swfInsidePanel.setVisible(binaryDataTag.innerSwf == null && isSwfData);
swfOrPackedDataInsidePanel.setVisible(
(binaryData.getSub() == null && binaryData.getUsedPacker() != null)
|| (isSwfData && binaryData.getInnerSwf() == null));
} else {
hexEditor.setData(new byte[0], null, null);
swfInsidePanel.setVisible(false);
swfOrPackedDataInsidePanel.setVisible(false);
}
hexEditor.revalidate();

View File

@@ -38,6 +38,7 @@ import com.jpexs.decompiler.flash.tags.DefineFont4Tag;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.BinaryDataInterface;
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.FontTag;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
@@ -100,7 +101,7 @@ public class ExportDialog extends AppDialog {
{DefineVideoStreamTag.class},
{SoundTag.class},
{ASMSource.class, ScriptPack.class, TagScript.class},
{DefineBinaryDataTag.class},
{BinaryDataInterface.class},
{Frame.class},
{Frame.class},
{ButtonTag.class},

View File

@@ -161,14 +161,10 @@ public abstract class MainFrameMenu implements MenuBuilder {
try {
openable.saveTo(baos);
SWF swf = (SWF) openable;
byte[] data = baos.toByteArray();
if (swf.binaryData.usedPacker != null) {
ByteArrayOutputStream encBaos = new ByteArrayOutputStream();
swf.binaryData.usedPacker.encrypt(new ByteArrayInputStream(data), encBaos);
data = encBaos.toByteArray();
}
swf.binaryData.binaryData = new ByteArrayRange(data);
byte[] data = baos.toByteArray();
swf.binaryData.setDataBytes(new ByteArrayRange(data));
swf.binaryData.setModified(true);
swf.binaryData.getTopLevelBinaryData().pack();
saved = saveOpenable(swf.binaryData.getSwf()); //save parent swf
} catch (IOException ex) {
Logger.getLogger(MainFrameMenu.class.getName()).log(Level.SEVERE, "Cannot save SWF", ex);
@@ -263,7 +259,7 @@ public abstract class MainFrameMenu implements MenuBuilder {
SWF swf = (SWF) openable;
if (swf.binaryData != null) {
// embedded swf
swf.binaryData.innerSwf = null;
swf.binaryData.setInnerSwf(null);
swf.clearTagSwfs();
binaryDataClosedSwfs.add(swf);
} else {

View File

@@ -165,6 +165,7 @@ import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.TagInfo;
import com.jpexs.decompiler.flash.tags.UnknownTag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.BinaryDataInterface;
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
@@ -174,6 +175,7 @@ import com.jpexs.decompiler.flash.tags.base.FontTag;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
import com.jpexs.decompiler.flash.tags.base.MissingCharacterHandler;
import com.jpexs.decompiler.flash.tags.base.MorphShapeTag;
import com.jpexs.decompiler.flash.tags.base.PackedBinaryData;
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
import com.jpexs.decompiler.flash.tags.base.SoundImportException;
@@ -2022,7 +2024,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
List<Tag> sounds = new ArrayList<>();
List<Tag> texts = new ArrayList<>();
List<TreeItem> as12scripts = new ArrayList<>();
List<Tag> binaryData = new ArrayList<>();
List<BinaryDataInterface> binaryData = new ArrayList<>();
Map<Integer, List<Integer>> frames = new HashMap<>();
List<Tag> fonts = new ArrayList<>();
List<Tag> fonts4 = new ArrayList<>();
@@ -2042,7 +2044,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}
}
if (d instanceof Tag || d instanceof ASMSource) {
if (d instanceof Tag || d instanceof ASMSource || d instanceof BinaryDataInterface) {
TreeNodeType nodeType = TagTree.getTreeNodeType(d);
if (nodeType == TreeNodeType.IMAGE) {
images.add((Tag) d);
@@ -2074,7 +2076,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
sounds.add((Tag) d);
}
if (nodeType == TreeNodeType.BINARY_DATA) {
binaryData.add((Tag) d);
binaryData.add((BinaryDataInterface) d);
}
if (nodeType == TreeNodeType.TEXT) {
texts.add((Tag) d);
@@ -2169,7 +2171,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}
if (export.isOptionEnabled(BinaryDataExportMode.class)) {
ret.addAll(new BinaryDataExporter().exportBinaryData(handler, selFile2 + File.separator + BinaryDataExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(binaryData),
ret.addAll(new BinaryDataExporter().exportBinaryData(handler, selFile2 + File.separator + BinaryDataExportSettings.EXPORT_FOLDER_NAME, binaryData,
new BinaryDataExportSettings(export.getValue(BinaryDataExportMode.class)), evl));
}
@@ -2466,6 +2468,27 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
public List<OpenableList> getSwfs() {
return openables;
}
public Map<String, SWF> getSwfsMap(SWF swf) {
Map<String, SWF> result = new LinkedHashMap<>();
populateSwfs(result, swf, swf.getShortFileName());
return result;
}
private void populateSwfs(Map<String, SWF> result, SWF targetSwf, String name) {
for (Tag t : targetSwf.getTags()) {
if (t instanceof DefineBinaryDataTag) {
BinaryDataInterface binaryData = (BinaryDataInterface) t;
String bname = name;
do {
bname = bname + "/" + binaryData.getPathIdentifier();
if (binaryData.getInnerSwf() != null) {
result.put(bname, binaryData.getInnerSwf());
}
} while ((binaryData = binaryData.getSub()) != null);
}
}
}
public OpenableList getCurrentSwfList() {
SWF swf = getCurrentSwf();
@@ -5371,32 +5394,25 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
showCard(CARDDUMPVIEW);
}
public void loadFromBinaryTag(final DefineBinaryDataTag binaryDataTag) {
public void loadFromBinaryTag(final BinaryDataInterface binaryDataTag) {
loadFromBinaryTag(Arrays.asList(binaryDataTag));
}
public void loadFromBinaryTag(final List<DefineBinaryDataTag> binaryDataTags) {
public void loadFromBinaryTag(final List<BinaryDataInterface> binaryDataTags) {
Main.loadingDialog.setVisible(true);
new CancellableWorker<Void>() {
@Override
protected Void doInBackground() throws Exception {
try {
for (DefineBinaryDataTag binaryDataTag : binaryDataTags) {
String path = binaryDataTag.getSwf().getShortPathTitle() + "/DefineBinaryData (" + binaryDataTag.getCharacterId() + ")";
for (BinaryDataInterface binaryData : binaryDataTags) {
String path = binaryData.getSwf().getShortPathTitle() + "/" + binaryData.getPathIdentifier();
try {
SwfSpecificCustomConfiguration conf = Configuration.getSwfSpecificCustomConfiguration(path);
String charset = conf == null ? Charset.defaultCharset().name() : conf.getCustomData(CustomConfigurationKeys.KEY_CHARSET, Charset.defaultCharset().name());
byte[] data = binaryDataTag.binaryData.getRangeData();
String packerAdd = "";
if (binaryDataTag.usedPacker != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
binaryDataTag.usedPacker.decrypt(new ByteArrayInputStream(data), baos);
data = baos.toByteArray();
packerAdd = " - " + binaryDataTag.usedPacker.getName();
}
byte[] data = binaryData.getDataBytes().getRangeData();
InputStream is = new ByteArrayInputStream(data);
SWF bswf = new SWF(is, null, "(SWF Data" + packerAdd + ")", new ProgressListener() {
SWF bswf = new SWF(is, null, "(SWF Data)", new ProgressListener() {
@Override
public void progress(int p) {
Main.loadingDialog.setPercent(p);
@@ -5406,8 +5422,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
public void status(String status) {
}
}, Configuration.parallelSpeedUp.get(), charset);
binaryDataTag.innerSwf = bswf;
bswf.binaryData = binaryDataTag;
binaryData.setInnerSwf(bswf);
bswf.binaryData = binaryData;
} catch (IOException ex) {
//ignore
}
@@ -5471,9 +5487,9 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
} else if (treeItem instanceof MetadataTag) {
MetadataTag metadataTag = (MetadataTag) treeItem;
previewPanel.showMetaDataPanel(metadataTag);
} else if (treeItem instanceof DefineBinaryDataTag) {
DefineBinaryDataTag binaryTag = (DefineBinaryDataTag) treeItem;
previewPanel.showBinaryPanel(binaryTag);
} else if (treeItem instanceof BinaryDataInterface) {
BinaryDataInterface binary = (BinaryDataInterface) treeItem;
previewPanel.showBinaryPanel(binary);
} else if (treeItem instanceof ProductInfoTag) {
ProductInfoTag productInfoTag = (ProductInfoTag) treeItem;
previewPanel.showProductInfoPanel(productInfoTag);
@@ -5787,7 +5803,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
} else if (treeItem instanceof MetadataTag) {
showPreview(treeItem, previewPanel, -1, null);
showCard(CARDPREVIEWPANEL);
} else if (treeItem instanceof DefineBinaryDataTag) {
} else if (treeItem instanceof BinaryDataInterface) {
showPreview(treeItem, previewPanel, -1, null);
showCard(CARDPREVIEWPANEL);
} else if (treeItem instanceof UnknownTag) {

View File

@@ -32,7 +32,6 @@ import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel;
import com.jpexs.decompiler.flash.gui.player.MediaDisplay;
import com.jpexs.decompiler.flash.gui.player.PlayerControls;
import com.jpexs.decompiler.flash.math.BezierUtils;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineMorphShape2Tag;
import com.jpexs.decompiler.flash.tags.DefineShape4Tag;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
@@ -43,6 +42,7 @@ import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.UnknownTag;
import com.jpexs.decompiler.flash.tags.base.BinaryDataInterface;
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.FontTag;
@@ -1647,9 +1647,9 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
parametersPanel.setVisible(false);
}
public void showBinaryPanel(DefineBinaryDataTag binaryDataTag) {
public void showBinaryPanel(BinaryDataInterface binaryData) {
showCardLeft(BINARY_TAG_CARD);
binaryPanel.setBinaryData(binaryDataTag);
binaryPanel.setBinaryData(binaryData);
parametersPanel.setVisible(false);
}

View File

@@ -78,7 +78,7 @@ public class SearchResultsStorage {
String binaryDataSuffix = "";
while ((s instanceof SWF) && ((SWF) s).binaryData != null) {
binaryDataSuffix += "|binaryData[" + ((SWF) s).binaryData.getCharacterId() + "]";
binaryDataSuffix += "|" + ((SWF) s).binaryData.getStoragesPathIdentifier();
s = ((SWF) s).binaryData.getSwf();
}

View File

@@ -1239,4 +1239,10 @@ debug.import.bytearray = Import byte array data...
action.edit.flex = (Flex compiler)
header.encrypted = Harman encrypted:
header.warning.unsupportedGfxEncryption = GFX does not support Harman encryption.
header.warning.unsupportedGfxEncryption = GFX does not support Harman encryption.
contextmenu.applyUnpacker = Apply unpacker
binarydata.dataInside.packer = It looks like this binary data is packed with %packer%. Click here to unpack the binary data.
error.wrong.packer = %item%\r\nCannot unpack binary data with %packer%.\r\nThe data is probably not packed with this packer.

View File

@@ -1216,4 +1216,8 @@ debug.import.bytearray = Importovat byte array data...
action.edit.flex = (kompil\u00e1tor Flex)
header.encrypted = Harman \u0161ifrov\u00e1n\u00ed:
header.warning.unsupportedGfxEncryption = GFX nepodporuje Harman \u0161ifrov\u00e1n\u00ed.
header.warning.unsupportedGfxEncryption = GFX nepodporuje Harman \u0161ifrov\u00e1n\u00ed.
contextmenu.applyUnpacker = Pou\u017e\u00edt unpacker
binarydata.dataInside.packer = Vypad\u00e1 to, \u017ee tato bin\u00e1rn\u00ed data jsou zabalena pomoc\u00ed %packer%. Klikn\u011bte zde pro jejich rozbalen\u00ed.
error.wrong.packer = %item%\r\nNelze rozbalit bin\u00e1rn\u00ed data pomoc\u00ed %packer%.\r\nTato data pravd\u011bpodobn\u011b nebyla zabalena t\u00edmto packerem.

View File

@@ -72,6 +72,7 @@ import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.TagStub;
import com.jpexs.decompiler.flash.tags.VideoFrameTag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.BinaryDataInterface;
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.FontTag;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
@@ -292,7 +293,7 @@ public abstract class AbstractTagTree extends JTree {
return TreeNodeType.SOUND;
}
if (t instanceof DefineBinaryDataTag) {
if (t instanceof BinaryDataInterface) {
return TreeNodeType.BINARY_DATA;
}
@@ -594,7 +595,7 @@ public abstract class AbstractTagTree extends JTree {
}
}
if (d instanceof Tag || d instanceof ASMSource) {
if (d instanceof Tag || d instanceof ASMSource || d instanceof BinaryDataInterface) {
TreeNodeType nodeType = TagTree.getTreeNodeType(d);
if (nodeType == TreeNodeType.IMAGE) {
ret.add(d);

View File

@@ -47,6 +47,7 @@ import com.jpexs.decompiler.flash.gui.abc.AddClassDialog;
import com.jpexs.decompiler.flash.gui.abc.ClassesListTreeModel;
import com.jpexs.decompiler.flash.gui.action.AddScriptDialog;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.packers.Packer;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineBitsLossless2Tag;
@@ -73,13 +74,14 @@ import com.jpexs.decompiler.flash.tags.ShowFrameTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.TagTypeInfo;
import com.jpexs.decompiler.flash.tags.UnknownTag;
import com.jpexs.decompiler.flash.tags.VideoFrameTag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.BinaryDataInterface;
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
import com.jpexs.decompiler.flash.tags.base.MorphShapeTag;
import com.jpexs.decompiler.flash.tags.base.PackedBinaryData;
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
import com.jpexs.decompiler.flash.tags.base.RemoveTag;
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
@@ -240,8 +242,10 @@ public class TagTreeContextMenu extends JPopupMenu {
private JMenuItem pasteInsideMenuItem;
private JMenu applyUnpackerMenu;
private JMenuItem openSWFInsideTagMenuItem;
private JMenuItem addAs12ScriptMenuItem;
private JMenuItem addAs12FrameScriptMenuItem;
@@ -598,6 +602,22 @@ public class TagTreeContextMenu extends JPopupMenu {
pasteInsideMenuItem.addActionListener(this::pasteInsideActionPerformed);
add(pasteInsideMenuItem);
applyUnpackerMenu = new JMenu(mainPanel.translate("contextmenu.applyUnpacker"));
applyUnpackerMenu.setIcon(View.getIcon("openinside16"));
for (Packer packer : DefineBinaryDataTag.getAvailablePackers()) {
JMenuItem packerMenuItem = new JMenuItem(packer.getName());
packerMenuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
applyUnpackerActionPerformed(packer);
}
});
applyUnpackerMenu.add(packerMenuItem);
}
add(applyUnpackerMenu);
openSWFInsideTagMenuItem = new JMenuItem(mainPanel.translate("contextmenu.openswfinside"));
openSWFInsideTagMenuItem.setIcon(View.getIcon("openinside16"));
openSWFInsideTagMenuItem.addActionListener(this::openSwfInsideActionPerformed);
@@ -953,7 +973,7 @@ public class TagTreeContextMenu extends JPopupMenu {
boolean allSelectedIsBinaryData = true;
for (TreeItem item : items) {
if (!(item instanceof DefineBinaryDataTag)) {
if (!(item instanceof BinaryDataInterface)) {
allSelectedIsBinaryData = false;
break;
}
@@ -1069,6 +1089,7 @@ public class TagTreeContextMenu extends JPopupMenu {
pasteAfterMenuItem.setVisible(false);
pasteBeforeMenuItem.setVisible(false);
pasteInsideMenuItem.setVisible(false);
applyUnpackerMenu.setVisible(false);
openSWFInsideTagMenuItem.setVisible(false);
addAs12ScriptMenuItem.setVisible(false);
addAs12FrameScriptMenuItem.setVisible(false);
@@ -1127,7 +1148,7 @@ public class TagTreeContextMenu extends JPopupMenu {
replaceNoFillMenuItem.setVisible(true);
}
if (canReplace.test(it -> it instanceof DefineBinaryDataTag)) {
if (canReplace.test(it -> it instanceof BinaryDataInterface)) {
replaceMenuItem.setVisible(true);
}
@@ -1308,7 +1329,8 @@ public class TagTreeContextMenu extends JPopupMenu {
if (mainPanel.getCurrentView() == MainPanel.VIEW_RESOURCES
&& !isFolder
&& !(firstItem instanceof AS3Package)) {
&& !(firstItem instanceof AS3Package)
&& !(firstItem instanceof PackedBinaryData)) {
showInTagListViewTagMenuItem.setVisible(true);
}
@@ -1471,17 +1493,19 @@ public class TagTreeContextMenu extends JPopupMenu {
}
if (allSelectedIsBinaryData) {
applyUnpackerMenu.setVisible(true);
boolean anyInnerSwf = false;
for (TreeItem item : items) {
DefineBinaryDataTag binary = (DefineBinaryDataTag) item;
BinaryDataInterface binary = (BinaryDataInterface) item;
// inner swf is not loaded yet
if (binary.innerSwf == null && binary.isSwfData()) {
if (binary.getInnerSwf() == null && binary.isSwfData()) {
anyInnerSwf = true;
}
}
openSWFInsideTagMenuItem.setVisible(anyInnerSwf);
openSWFInsideTagMenuItem.setVisible(anyInnerSwf);
}
for (TreeItem item : items) {
@@ -1521,7 +1545,7 @@ public class TagTreeContextMenu extends JPopupMenu {
moveTagToWithDependenciesMenu.setVisible(false);
cutTagToClipboardMenuItem.setVisible(false);
cutTagToClipboardWithDependenciesMenuItem.setVisible(false);
openSWFInsideTagMenuItem.setVisible(false);
//openSWFInsideTagMenuItem.setVisible(false);
}
}
}
@@ -2009,17 +2033,28 @@ public class TagTreeContextMenu extends JPopupMenu {
copyOrMoveTags(getDependenciesSet(items), true, timelined, position);
}
private void applyUnpackerActionPerformed(Packer packer) {
List<TreeItem> sel = getSelectedItems();
for (TreeItem item : sel) {
BinaryDataInterface binaryData = (BinaryDataInterface) item;
if (!binaryData.unpack(packer)) {
ViewMessages.showMessageDialog(mainPanel, AppStrings.translate("error.wrong.packer").replace("%item%", item.toString()).replace("%packer%", packer.getName()), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
}
}
mainPanel.refreshTree();
}
private void openSwfInsideActionPerformed(ActionEvent evt) {
List<TreeItem> sel = getSelectedItems();
List<DefineBinaryDataTag> binaryDatas = new ArrayList<>();
List<BinaryDataInterface> binaryDatas = new ArrayList<>();
for (TreeItem item : sel) {
DefineBinaryDataTag binaryData = (DefineBinaryDataTag) item;
BinaryDataInterface binaryData = (BinaryDataInterface) item;
if (binaryData.isSwfData()) {
binaryDatas.add((DefineBinaryDataTag) item);
binaryDatas.add((BinaryDataInterface) item);
}
}
mainPanel.loadFromBinaryTag(binaryDatas);
mainPanel.loadFromBinaryTag(binaryDatas);
}
private void replaceWithTagActionPerformed(ActionEvent evt) {
@@ -3201,7 +3236,7 @@ public class TagTreeContextMenu extends JPopupMenu {
SWF swf = (SWF) item;
if (swf.binaryData != null) {
// embedded swf
swf.binaryData.innerSwf = null;
swf.binaryData.setInnerSwf(null);
swf.clearTagSwfs();
} else {
Main.closeFile(swf.openableList);
@@ -3521,13 +3556,9 @@ public class TagTreeContextMenu extends JPopupMenu {
swfItem.setIcon(View.getIcon("flash16"));
menu.add(swfItem);
for (Tag t : targetSwf.getTags()) {
if (t instanceof DefineBinaryDataTag) {
DefineBinaryDataTag binaryData = (DefineBinaryDataTag) t;
if (binaryData.innerSwf != null) {
addCopyMoveToMenus(kind, menu, items, name + " / " + t.getTagName() + " (" + ((DefineBinaryDataTag) t).getCharacterId() + ")", binaryData.innerSwf);
}
}
Map<String, SWF> binaryMap = mainPanel.getSwfsMap(targetSwf);
for (String key : binaryMap.keySet()) {
addCopyMoveToMenus(kind, menu, items, key, binaryMap.get(key));
}
}
@@ -3545,16 +3576,14 @@ public class TagTreeContextMenu extends JPopupMenu {
});
swfItem.setIcon(View.getIcon("flash16"));
menu.add(swfItem);
for (Tag t : targetSwf.getTags()) {
if (t instanceof DefineBinaryDataTag) {
DefineBinaryDataTag binaryData = (DefineBinaryDataTag) t;
if (binaryData.innerSwf != null) {
addCopyMoveToMenus(kind, menu, items, name + " / " + t.getTagName() + " (" + ((DefineBinaryDataTag) t).getCharacterId() + ")", binaryData.innerSwf);
}
}
}
Map<String, SWF> binaryMap = mainPanel.getSwfsMap(targetSwf);
for (String key : binaryMap.keySet()) {
addCopyMoveToFramesMenus(kind, menu, items, key, binaryMap.get(key));
}
}
private void attachTagActionPerformed(ActionEvent evt, TreeItem item, Class<?> cl, TreeNodeType createNodeType) {
int id = -1;

View File

@@ -24,7 +24,6 @@ import com.jpexs.decompiler.flash.gui.TreeNodeType;
import com.jpexs.decompiler.flash.gui.abc.ClassesListTreeModel;
import com.jpexs.decompiler.flash.gui.helpers.CollectionChangedAction;
import com.jpexs.decompiler.flash.gui.helpers.CollectionChangedEvent;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
@@ -32,6 +31,7 @@ import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.ASMSourceContainer;
import com.jpexs.decompiler.flash.tags.base.BinaryDataInterface;
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
@@ -527,10 +527,13 @@ public class TagTreeModel extends AbstractTagTreeModel {
} else if (parentNode instanceof DefineSpriteTag) {
result.addAll(((DefineSpriteTag) parentNode).getTimeline().getFrames());
return result;
} else if (parentNode instanceof DefineBinaryDataTag) {
DefineBinaryDataTag binaryDataTag = (DefineBinaryDataTag) parentNode;
if (binaryDataTag.innerSwf != null) {
result.add(((DefineBinaryDataTag) parentNode).innerSwf);
} else if (parentNode instanceof BinaryDataInterface) {
BinaryDataInterface binaryData = (BinaryDataInterface) parentNode;
if (binaryData.getInnerSwf() != null) {
result.add(binaryData.getInnerSwf());
return result;
} else if (binaryData.getSub() != null) {
result.add(binaryData.getSub());
return result;
} else {
return new ArrayList<>(0);
@@ -613,8 +616,12 @@ public class TagTreeModel extends AbstractTagTreeModel {
return ((Frame) parentNode).innerTags.get(index);
} else if (parentNode instanceof DefineSpriteTag) {
return ((DefineSpriteTag) parentNode).getTimeline().getFrame(index);
} else if (parentNode instanceof DefineBinaryDataTag) {
return ((DefineBinaryDataTag) parentNode).innerSwf;
} else if (parentNode instanceof BinaryDataInterface) {
BinaryDataInterface binaryData = (BinaryDataInterface) parentNode;
if (binaryData.getInnerSwf() != null) {
return binaryData.getInnerSwf();
}
return binaryData.getSub();
} else if (parentNode instanceof AS2Package) {
return ((AS2Package) parentNode).getChild(index);
} else if (parentNode instanceof FrameScript) {
@@ -681,8 +688,12 @@ public class TagTreeModel extends AbstractTagTreeModel {
return mappedSize + ((Frame) parentNode).innerTags.size();
} else if (parentNode instanceof DefineSpriteTag) {
return mappedSize + ((DefineSpriteTag) parentNode).getTimeline().getFrameCount();
} else if (parentNode instanceof DefineBinaryDataTag) {
return mappedSize + (((DefineBinaryDataTag) parentNode).innerSwf == null ? 0 : 1);
} else if (parentNode instanceof BinaryDataInterface) {
BinaryDataInterface binary = (BinaryDataInterface) parentNode;
if (binary.getInnerSwf() != null) {
return mappedSize + 1;
}
return mappedSize + (binary.getSub() == null ? 0 : 1);
} else if (parentNode instanceof AS2Package) {
return mappedSize + ((AS2Package) parentNode).getChildCount();
} else if (parentNode instanceof FrameScript) {
@@ -748,7 +759,7 @@ public class TagTreeModel extends AbstractTagTreeModel {
return indexOfAdd(baseIndex, ((Frame) parentNode).innerTags.indexOf(childNode));
} else if (parentNode instanceof DefineSpriteTag) {
return indexOfAdd(baseIndex, ((Frame) childNode).frame);
} else if (parentNode instanceof DefineBinaryDataTag) {
} else if (parentNode instanceof BinaryDataInterface) {
return indexOfAdd(baseIndex, 0); // binary data tag can have only 1 child
} else if (parentNode instanceof AS2Package) {
return indexOfAdd(baseIndex, ((AS2Package) parentNode).getIndexOfChild(childNode));