mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-05-27 22:04:46 +00:00
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:
@@ -16,6 +16,9 @@ All notable changes to this project will be documented in this file.
|
||||
- Saving Harman encrypted SWFs
|
||||
- Editing encrypted flag on header panel
|
||||
- `-encrypt` command on CLI for Harman encryption
|
||||
- Apply unpacker menu on binary data
|
||||
- Harman unpacker for binary data
|
||||
- Multilevel binary data unpacking is possible
|
||||
|
||||
### Fixed
|
||||
- [#2021], [#2000] Caret position in editors when using tabs and / or unicode
|
||||
|
||||
@@ -122,6 +122,7 @@ 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.ASMSourceContainer;
|
||||
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;
|
||||
@@ -357,7 +358,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
|
||||
public DumpInfoSwfNode dumpInfo;
|
||||
|
||||
@Internal
|
||||
public DefineBinaryDataTag binaryData;
|
||||
public BinaryDataInterface binaryData;
|
||||
|
||||
@Internal
|
||||
private final HashMap<DottedChain, DottedChain> deobfuscated = new HashMap<>();
|
||||
@@ -1756,7 +1757,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
|
||||
@Override
|
||||
public String getShortPathTitle() {
|
||||
if (binaryData != null) {
|
||||
return binaryData.getSwf().getShortPathTitle() + "/DefineBinaryData (" + binaryData.getCharacterId() + ")";
|
||||
return binaryData.getSwf().getShortPathTitle() + "/" + binaryData.getPathIdentifier();
|
||||
}
|
||||
if (openableList != null) {
|
||||
if (openableList.isBundle()) {
|
||||
@@ -1774,7 +1775,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
|
||||
@Override
|
||||
public String getFullPathTitle() {
|
||||
if (binaryData != null) {
|
||||
return binaryData.getSwf().getFullPathTitle() + "/DefineBinaryData (" + binaryData.getCharacterId() + ")";
|
||||
return binaryData.getSwf().getFullPathTitle() + "/" + binaryData.getPathIdentifier();
|
||||
}
|
||||
if (openableList != null) {
|
||||
if (openableList.isBundle()) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.exporters.settings.BinaryDataExportSettings;
|
||||
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.BinaryDataInterface;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.Path;
|
||||
import java.io.BufferedOutputStream;
|
||||
@@ -44,69 +45,73 @@ import java.util.Set;
|
||||
public class BinaryDataExporter {
|
||||
|
||||
public List<File> exportBinaryData(AbortRetryIgnoreHandler handler, String outdir, ReadOnlyTagList tags, BinaryDataExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
List<BinaryDataInterface> binaryDatas = new ArrayList<>();
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof BinaryDataInterface) {
|
||||
binaryDatas.add((BinaryDataInterface) t);
|
||||
}
|
||||
}
|
||||
return exportBinaryData(handler, outdir, binaryDatas, settings, evl);
|
||||
}
|
||||
|
||||
public List<File> exportBinaryData(AbortRetryIgnoreHandler handler, String outdir, List<BinaryDataInterface> binaryDatas, BinaryDataExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||
List<File> ret = new ArrayList<>();
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (tags.isEmpty()) {
|
||||
if (binaryDatas.isEmpty()) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
File foutdir = new File(outdir);
|
||||
Path.createDirectorySafe(foutdir);
|
||||
|
||||
int count = 0;
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof DefineBinaryDataTag) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
int count = binaryDatas.size();
|
||||
|
||||
if (count == 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int currentIndex = 1;
|
||||
for (final Tag t : tags) {
|
||||
if (t instanceof DefineBinaryDataTag) {
|
||||
DefineBinaryDataTag bdt = (DefineBinaryDataTag) t;
|
||||
if (evl != null) {
|
||||
evl.handleExportingEvent("binarydata", currentIndex, count, t.getName());
|
||||
}
|
||||
|
||||
String ext = bdt.innerSwf == null ? ".bin" : ".swf";
|
||||
final File file = new File(outdir + File.separator + Helper.makeFileName(bdt.getCharacterExportFileName() + ext));
|
||||
new RetryTask(() -> {
|
||||
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||
fos.write(bdt.binaryData.getRangeData());
|
||||
}
|
||||
}, handler).run();
|
||||
|
||||
Set<String> classNames = bdt.getClassNames();
|
||||
if (Configuration.as3ExportNamesUseClassNamesOnly.get() && !classNames.isEmpty()) {
|
||||
for (String className : classNames) {
|
||||
File classFile = new File(outdir + File.separator + Helper.makeFileName(className + ext));
|
||||
new RetryTask(() -> {
|
||||
Files.copy(file.toPath(), classFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
}, handler).run();
|
||||
ret.add(classFile);
|
||||
}
|
||||
file.delete();
|
||||
} else {
|
||||
ret.add(file);
|
||||
}
|
||||
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (evl != null) {
|
||||
evl.handleExportedEvent("binarydata", currentIndex, count, t.getName());
|
||||
}
|
||||
|
||||
currentIndex++;
|
||||
for (final BinaryDataInterface t : binaryDatas) {
|
||||
if (evl != null) {
|
||||
evl.handleExportingEvent("binarydata", currentIndex, count, t.getName());
|
||||
}
|
||||
|
||||
String ext = t.getInnerSwf() == null ? ".bin" : ".swf";
|
||||
final File file = new File(outdir + File.separator + Helper.makeFileName(t.getCharacterExportFileName() + ext));
|
||||
new RetryTask(() -> {
|
||||
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||
fos.write(t.getDataBytes().getRangeData());
|
||||
}
|
||||
}, handler).run();
|
||||
|
||||
DefineBinaryDataTag bdt = (DefineBinaryDataTag) t.getTopLevelBinaryData();
|
||||
|
||||
Set<String> classNames = bdt.getClassNames();
|
||||
if (Configuration.as3ExportNamesUseClassNamesOnly.get() && !classNames.isEmpty()) {
|
||||
for (String className : classNames) {
|
||||
File classFile = new File(outdir + File.separator + Helper.makeFileName(t.getClassExportFileName(className) + ext));
|
||||
new RetryTask(() -> {
|
||||
Files.copy(file.toPath(), classFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
}, handler).run();
|
||||
ret.add(classFile);
|
||||
}
|
||||
file.delete();
|
||||
} else {
|
||||
ret.add(file);
|
||||
}
|
||||
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (evl != null) {
|
||||
evl.handleExportedEvent("binarydata", currentIndex, count, t.getName());
|
||||
}
|
||||
|
||||
currentIndex++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -32,25 +32,7 @@ import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class HarmanBinaryDataEncrypt {
|
||||
|
||||
private static final String GLOBAL_KEY = "Adobe AIR SDK (c) 2021 HARMAN Internation Industries Incorporated";
|
||||
|
||||
private static final String[] hexStringCache;
|
||||
|
||||
static {
|
||||
hexStringCache = new String[256];
|
||||
for (int i = 0; i < hexStringCache.length; i++) {
|
||||
hexStringCache[i] = String.format("%02x", i);
|
||||
}
|
||||
}
|
||||
|
||||
public static String byteArrayToHex(byte[] data) {
|
||||
StringBuilder sb = new StringBuilder(data.length * 2);
|
||||
for (byte b : data) {
|
||||
sb.append(hexStringCache[b & 0xff]);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
private static final String GLOBAL_KEY = "Adobe AIR SDK (c) 2021 HARMAN Internation Industries Incorporated";
|
||||
|
||||
public static byte[] encrypt(byte[] data) {
|
||||
byte[] result;
|
||||
@@ -153,6 +135,9 @@ public class HarmanBinaryDataEncrypt {
|
||||
}
|
||||
|
||||
public static byte[] decrypt(byte[] data) {
|
||||
if (data.length < 32) {
|
||||
return null;
|
||||
}
|
||||
long encryptedLen = data.length;
|
||||
long encryptedLenXorHash = unpack(data, 0);
|
||||
long decryptedLenXorRandom1 = unpack(data, 4);
|
||||
|
||||
@@ -19,9 +19,6 @@ package com.jpexs.decompiler.flash.harman;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
@@ -44,26 +41,7 @@ import javax.crypto.spec.SecretKeySpec;
|
||||
*/
|
||||
public class HarmanSwfEncrypt {
|
||||
|
||||
private static final String GLOBAL_KEY = "Adobe AIR SDK (c) 2021 HARMAN Internation Industries Incorporated";
|
||||
|
||||
|
||||
private static final String[] hexStringCache;
|
||||
|
||||
static {
|
||||
hexStringCache = new String[256];
|
||||
for (int i = 0; i < hexStringCache.length; i++) {
|
||||
hexStringCache[i] = String.format("%02x", i);
|
||||
}
|
||||
}
|
||||
|
||||
public static String byteArrayToHex(byte[] data) {
|
||||
StringBuilder sb = new StringBuilder(data.length * 2);
|
||||
for (byte b : data) {
|
||||
sb.append(hexStringCache[b & 0xff]);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
private static final String GLOBAL_KEY = "Adobe AIR SDK (c) 2021 HARMAN Internation Industries Incorporated";
|
||||
|
||||
private static int sum(byte[] data) {
|
||||
int s = 0;
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2023 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.packers;
|
||||
|
||||
import com.jpexs.decompiler.flash.harman.HarmanBinaryDataEncrypt;
|
||||
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class HarmanAirPacker implements Packer {
|
||||
|
||||
@Override
|
||||
public Boolean suitableForBinaryData(DefineBinaryDataTag dataTag) {
|
||||
if (dataTag.binaryData.getLength() < 32) {
|
||||
return false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean suitableForData(byte[] data) {
|
||||
if (data.length < 32) {
|
||||
return false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean decrypt(InputStream is, OutputStream os) throws IOException {
|
||||
byte[] encryptedData = Helper.readStream(is);
|
||||
byte[] decryptedData = HarmanBinaryDataEncrypt.decrypt(encryptedData);
|
||||
if (decryptedData == null) {
|
||||
return false;
|
||||
}
|
||||
os.write(decryptedData);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean encrypt(InputStream is, OutputStream os) throws IOException {
|
||||
byte[] data = Helper.readStream(is);
|
||||
byte[] encryptedData = HarmanBinaryDataEncrypt.encrypt(data);
|
||||
if (encryptedData == null) {
|
||||
return false;
|
||||
}
|
||||
os.write(encryptedData);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Harman AIR SDK";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return "harmanair";
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,12 @@ public class MochiCryptPacker implements Packer {
|
||||
if (!handleXor(payload)) {
|
||||
return false;
|
||||
}
|
||||
Helper.copyStream(new InflaterInputStream(new ByteArrayInputStream(payload)), os);
|
||||
try {
|
||||
Helper.copyStreamEx(new InflaterInputStream(new ByteArrayInputStream(payload)), os);
|
||||
} catch (IOException ex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -100,7 +105,7 @@ public class MochiCryptPacker implements Packer {
|
||||
public boolean encrypt(InputStream is, OutputStream os) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DeflaterOutputStream def = new DeflaterOutputStream(baos);
|
||||
Helper.copyStream(is, def);
|
||||
Helper.copyStreamEx(is, def);
|
||||
def.finish();
|
||||
byte[] payload = baos.toByteArray();
|
||||
|
||||
@@ -117,4 +122,14 @@ public class MochiCryptPacker implements Packer {
|
||||
public String getName() {
|
||||
return "MochiCrypt";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean suitableForData(byte[] data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return "mochicrypt";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,16 @@ public interface Packer {
|
||||
* work
|
||||
*/
|
||||
public Boolean suitableForBinaryData(DefineBinaryDataTag dataTag);
|
||||
|
||||
/**
|
||||
* Is this data packed with this packer?
|
||||
*
|
||||
* @param data
|
||||
* @return true = it definitely is encrypted with this, false = it
|
||||
* definitely is not encrypted with this, null = it is unknown that it will
|
||||
* work
|
||||
*/
|
||||
public Boolean suitableForData(byte[] data);
|
||||
|
||||
/**
|
||||
* Unpack the data
|
||||
@@ -65,4 +75,6 @@ public interface Packer {
|
||||
* @return
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
public String getIdentifier();
|
||||
}
|
||||
|
||||
@@ -22,9 +22,12 @@ import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.configuration.CustomConfigurationKeys;
|
||||
import com.jpexs.decompiler.flash.configuration.SwfSpecificCustomConfiguration;
|
||||
import com.jpexs.decompiler.flash.packers.HarmanAirPacker;
|
||||
import com.jpexs.decompiler.flash.packers.MochiCryptPacker;
|
||||
import com.jpexs.decompiler.flash.packers.Packer;
|
||||
import com.jpexs.decompiler.flash.tags.base.BinaryDataInterface;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.PackedBinaryData;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Internal;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Reserved;
|
||||
@@ -43,7 +46,7 @@ import java.nio.charset.Charset;
|
||||
* @author JPEXS
|
||||
*/
|
||||
@SWFVersion(from = 9)
|
||||
public class DefineBinaryDataTag extends CharacterTag {
|
||||
public class DefineBinaryDataTag extends CharacterTag implements BinaryDataInterface {
|
||||
|
||||
public static final int ID = 87;
|
||||
|
||||
@@ -63,11 +66,19 @@ public class DefineBinaryDataTag extends CharacterTag {
|
||||
|
||||
@Internal
|
||||
public Packer usedPacker;
|
||||
|
||||
@Internal
|
||||
private PackedBinaryData sub;
|
||||
|
||||
private final Packer[] PACKERS = {
|
||||
new MochiCryptPacker()
|
||||
private static final Packer[] PACKERS = {
|
||||
new MochiCryptPacker(),
|
||||
new HarmanAirPacker()
|
||||
};
|
||||
|
||||
public static Packer[] getAvailablePackers() {
|
||||
return PACKERS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@@ -84,6 +95,25 @@ public class DefineBinaryDataTag extends CharacterTag {
|
||||
readData(sis, data, 0, false, false, false);
|
||||
}
|
||||
|
||||
public PackedBinaryData getSub() {
|
||||
return sub;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unpack(Packer packer) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try {
|
||||
if (!packer.decrypt(new ByteArrayInputStream(binaryData.getRangeData()), baos)) {
|
||||
return false;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
return false;
|
||||
}
|
||||
sub = new PackedBinaryData(swf, this, new ByteArrayRange(baos.toByteArray()));
|
||||
usedPacker = packer;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
|
||||
tag = sis.readUI16("tag");
|
||||
@@ -100,16 +130,16 @@ public class DefineBinaryDataTag extends CharacterTag {
|
||||
InputStream is = new ByteArrayInputStream(binaryData.getArray(), binaryData.getPos(), binaryData.getLength());
|
||||
detectPacker();
|
||||
String packerAdd = "";
|
||||
BinaryDataInterface binaryData = this;
|
||||
if (usedPacker != null) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
usedPacker.decrypt(is, baos);
|
||||
is = new ByteArrayInputStream(baos.toByteArray());
|
||||
packerAdd = " - " + usedPacker.getName();
|
||||
unpack(usedPacker);
|
||||
is = new ByteArrayInputStream(sub.getDataBytes().getRangeData());
|
||||
binaryData = sub;
|
||||
}
|
||||
|
||||
SWF bswf = new SWF(is, null, "(SWF Data" + packerAdd + ")", Configuration.parallelSpeedUp.get(), charset);
|
||||
innerSwf = bswf;
|
||||
bswf.binaryData = this;
|
||||
SWF bswf = new SWF(is, null, "(SWF Data)", Configuration.parallelSpeedUp.get(), charset);
|
||||
binaryData.setInnerSwf(bswf);
|
||||
bswf.binaryData = binaryData;
|
||||
} catch (IOException | InterruptedException ex) {
|
||||
// ignore
|
||||
}
|
||||
@@ -138,6 +168,7 @@ public class DefineBinaryDataTag extends CharacterTag {
|
||||
this.tag = characterId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detectPacker() {
|
||||
for (Packer packer : PACKERS) {
|
||||
if (packer.suitableForBinaryData(this) == Boolean.TRUE) {
|
||||
@@ -147,6 +178,7 @@ public class DefineBinaryDataTag extends CharacterTag {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSwfData() {
|
||||
try {
|
||||
if (binaryData.getLength() > 8) {
|
||||
@@ -159,9 +191,7 @@ public class DefineBinaryDataTag extends CharacterTag {
|
||||
//ignored
|
||||
}
|
||||
|
||||
detectPacker();
|
||||
|
||||
return usedPacker != null;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -174,4 +204,77 @@ public class DefineBinaryDataTag extends CharacterTag {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packer getUsedPacker() {
|
||||
return usedPacker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDataBytes(ByteArrayRange data) {
|
||||
this.binaryData = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteArrayRange getDataBytes() {
|
||||
return binaryData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pack() {
|
||||
if (sub == null) {
|
||||
return false;
|
||||
}
|
||||
sub.pack();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try {
|
||||
if (!usedPacker.encrypt(new ByteArrayInputStream(sub.getDataBytes().getRangeData()), baos)) {
|
||||
return false;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
return false;
|
||||
}
|
||||
setDataBytes(new ByteArrayRange(baos.toByteArray()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInnerSwf(SWF swf) {
|
||||
this.innerSwf = swf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF getInnerSwf() {
|
||||
return this.innerSwf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPathIdentifier() {
|
||||
return "DefineBinaryData (" + getCharacterId() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStoragesPathIdentifier() {
|
||||
return "binaryData[" + getCharacterId() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public BinaryDataInterface getTopLevelBinaryData() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModified(boolean value) {
|
||||
super.setModified(value);
|
||||
if (!value) {
|
||||
if (sub != null) {
|
||||
sub.setModified(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClassExportFileName(String className) {
|
||||
return className;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2023 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.tags.base;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.packers.Packer;
|
||||
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface BinaryDataInterface extends Exportable {
|
||||
|
||||
public PackedBinaryData getSub();
|
||||
|
||||
public boolean isSwfData();
|
||||
|
||||
public boolean unpack(Packer packer);
|
||||
|
||||
public void detectPacker();
|
||||
|
||||
public Packer getUsedPacker();
|
||||
|
||||
public void setDataBytes(ByteArrayRange data);
|
||||
|
||||
public ByteArrayRange getDataBytes();
|
||||
|
||||
public void setModified(boolean value);
|
||||
|
||||
public boolean pack();
|
||||
|
||||
public SWF getSwf();
|
||||
|
||||
public void setInnerSwf(SWF swf);
|
||||
|
||||
public SWF getInnerSwf();
|
||||
|
||||
public String getPathIdentifier();
|
||||
|
||||
public String getStoragesPathIdentifier();
|
||||
|
||||
public BinaryDataInterface getTopLevelBinaryData();
|
||||
|
||||
public String getCharacterExportFileName();
|
||||
|
||||
public String getName();
|
||||
|
||||
public String getClassExportFileName(String className);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2023 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.tags.base;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.packers.Packer;
|
||||
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
|
||||
import com.jpexs.decompiler.flash.treeitems.Openable;
|
||||
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.utf8.Utf8Helper;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class PackedBinaryData implements TreeItem, BinaryDataInterface {
|
||||
|
||||
private boolean modified = false;
|
||||
private final SWF swf;
|
||||
private final BinaryDataInterface parent;
|
||||
private ByteArrayRange data;
|
||||
private PackedBinaryData sub;
|
||||
private Packer usedPacker;
|
||||
private SWF innerSwf;
|
||||
|
||||
public PackedBinaryData(SWF swf, BinaryDataInterface parent, ByteArrayRange data) {
|
||||
this.swf = swf;
|
||||
this.parent = parent;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unpack(Packer packer) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try {
|
||||
if (!packer.decrypt(new ByteArrayInputStream(data.getRangeData()), baos)) {
|
||||
return false;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
return false;
|
||||
}
|
||||
sub = new PackedBinaryData(swf, this, new ByteArrayRange(baos.toByteArray()));
|
||||
usedPacker = packer;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackedBinaryData getSub() {
|
||||
return sub;
|
||||
}
|
||||
|
||||
public BinaryDataInterface getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Openable getOpenable() {
|
||||
return swf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF getSwf() {
|
||||
return swf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModified(boolean value) {
|
||||
modified = value;
|
||||
if (value) {
|
||||
parent.setModified(value);
|
||||
} else {
|
||||
if (sub != null) {
|
||||
sub.setModified(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
return modified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSwfData() {
|
||||
try {
|
||||
if (data.getLength() > 8) {
|
||||
String signature = new String(data.getRangeData(0, 3), Utf8Helper.charset);
|
||||
if (SWF.swfSignatures.contains(signature)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
//ignored
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packer getUsedPacker() {
|
||||
return usedPacker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detectPacker() {
|
||||
for (Packer packer : DefineBinaryDataTag.getAvailablePackers()) {
|
||||
if (packer.suitableForData(data.getRangeData()) == Boolean.TRUE) {
|
||||
usedPacker = packer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteArrayRange getDataBytes() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDataBytes(ByteArrayRange data) {
|
||||
this.data = data;
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pack() {
|
||||
if (sub == null) {
|
||||
return false;
|
||||
}
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try {
|
||||
if (!usedPacker.encrypt(new ByteArrayInputStream(sub.getDataBytes().getRangeData()), baos)) {
|
||||
return false;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
return false;
|
||||
}
|
||||
setDataBytes(new ByteArrayRange(baos.toByteArray()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(Data - " + parent.getUsedPacker().getName() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInnerSwf(SWF swf) {
|
||||
this.innerSwf = swf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF getInnerSwf() {
|
||||
return this.innerSwf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPathIdentifier() {
|
||||
return "(Data - " + parent.getUsedPacker().getName() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStoragesPathIdentifier() {
|
||||
return "data-" + parent.getUsedPacker().getIdentifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BinaryDataInterface getTopLevelBinaryData() {
|
||||
PackedBinaryData packed = this;
|
||||
while (packed.parent instanceof PackedBinaryData) {
|
||||
packed = (PackedBinaryData) packed.parent;
|
||||
}
|
||||
return packed.parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExportFileName() {
|
||||
List<String> parts = new ArrayList<>();
|
||||
BinaryDataInterface binaryData = this;
|
||||
while (binaryData instanceof PackedBinaryData) {
|
||||
parts.add(0, ((PackedBinaryData) binaryData).parent.getUsedPacker().getIdentifier());
|
||||
binaryData = ((PackedBinaryData) binaryData).parent;
|
||||
}
|
||||
|
||||
parts.add(0, binaryData.getExportFileName());
|
||||
return String.join("_", parts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCharacterExportFileName() {
|
||||
List<String> parts = new ArrayList<>();
|
||||
BinaryDataInterface binaryData = this;
|
||||
while (binaryData instanceof PackedBinaryData) {
|
||||
parts.add(0, ((PackedBinaryData) binaryData).parent.getUsedPacker().getIdentifier());
|
||||
binaryData = ((PackedBinaryData) binaryData).parent;
|
||||
}
|
||||
|
||||
parts.add(0, binaryData.getCharacterExportFileName());
|
||||
return String.join("_", parts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
List<String> parts = new ArrayList<>();
|
||||
BinaryDataInterface binaryData = this;
|
||||
while (binaryData instanceof PackedBinaryData) {
|
||||
parts.add(0, ((PackedBinaryData) binaryData).parent.getUsedPacker().getName());
|
||||
binaryData = ((PackedBinaryData) binaryData).parent;
|
||||
}
|
||||
|
||||
parts.add(0, binaryData.getName());
|
||||
return String.join(" / ", parts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClassExportFileName(String className) {
|
||||
List<String> parts = new ArrayList<>();
|
||||
BinaryDataInterface binaryData = this;
|
||||
while (binaryData instanceof PackedBinaryData) {
|
||||
parts.add(0, binaryData.getStoragesPathIdentifier());
|
||||
binaryData = ((PackedBinaryData) binaryData).parent;
|
||||
}
|
||||
|
||||
parts.add(0, binaryData.getClassExportFileName(className));
|
||||
return String.join("_", parts);
|
||||
}
|
||||
}
|
||||
@@ -787,6 +787,15 @@ public class Helper {
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
public static void copyStreamEx(InputStream is, OutputStream os) throws IOException {
|
||||
final int bufSize = 4096;
|
||||
byte[] buf = new byte[bufSize];
|
||||
int cnt = 0;
|
||||
while ((cnt = is.read(buf)) > 0) {
|
||||
os.write(buf, 0, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyStream(InputStream is, OutputStream os) {
|
||||
try {
|
||||
final int bufSize = 4096;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user