Resource Viewing Improvements
All of the components that update resources should now function as normal again The decompiler gui API has been improved to use less boilerplate when adding a new decompiler
This commit is contained in:
parent
4ebdd2bdbc
commit
2ef221f6e1
35 changed files with 457 additions and 471 deletions
|
@ -122,7 +122,7 @@ public class BytecodeViewer
|
||||||
public static MainViewerGUI viewer;
|
public static MainViewerGUI viewer;
|
||||||
|
|
||||||
//All of the opened resources (Files/Classes/Etc)
|
//All of the opened resources (Files/Classes/Etc)
|
||||||
public static List<FileContainer> files = new ArrayList<>();
|
public static List<ResourceContainer> files = new ArrayList<>();
|
||||||
|
|
||||||
//All of the created processes (Decompilers/etc)
|
//All of the created processes (Decompilers/etc)
|
||||||
public static List<Process> createdProcesses = new ArrayList<>();
|
public static List<Process> createdProcesses = new ArrayList<>();
|
||||||
|
@ -178,6 +178,7 @@ public class BytecodeViewer
|
||||||
|
|
||||||
//load settings and set swing components state
|
//load settings and set swing components state
|
||||||
SettingsSerializer.loadSettings();
|
SettingsSerializer.loadSettings();
|
||||||
|
Configuration.bootState = Configuration.BootState.SETTINGS_LOADED;
|
||||||
|
|
||||||
//set translation language
|
//set translation language
|
||||||
if(!Settings.hasSetLanguageAsSystemLanguage)
|
if(!Settings.hasSetLanguageAsSystemLanguage)
|
||||||
|
@ -188,20 +189,21 @@ public class BytecodeViewer
|
||||||
if (CLI == CommandLineInput.STOP)
|
if (CLI == CommandLineInput.STOP)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!FAT_JAR)
|
//load with shaded libraries
|
||||||
{
|
if (FAT_JAR)
|
||||||
bootCheck.start();
|
|
||||||
|
|
||||||
Boot.boot(args, CLI != CommandLineInput.GUI);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
installFatJar.start();
|
installFatJar.start();
|
||||||
}
|
}
|
||||||
|
else //load through bootloader
|
||||||
|
{
|
||||||
|
bootCheck.start();
|
||||||
|
Boot.boot(args, CLI != CommandLineInput.GUI);
|
||||||
|
}
|
||||||
|
|
||||||
if (CLI == CommandLineInput.GUI)
|
if (CLI == CommandLineInput.GUI)
|
||||||
{
|
{
|
||||||
BytecodeViewer.boot(false);
|
BytecodeViewer.boot(false);
|
||||||
|
Configuration.bootState = Configuration.BootState.GUI_SHOWING;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -357,7 +359,7 @@ public class BytecodeViewer
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static ClassNode blindlySearchForClassNode(String name)
|
public static ClassNode blindlySearchForClassNode(String name)
|
||||||
{
|
{
|
||||||
for (FileContainer container : files)
|
for (ResourceContainer container : files)
|
||||||
{
|
{
|
||||||
ClassNode node = container.getClassNode(name);
|
ClassNode node = container.getClassNode(name);
|
||||||
if(node != null)
|
if(node != null)
|
||||||
|
@ -370,9 +372,9 @@ public class BytecodeViewer
|
||||||
/**
|
/**
|
||||||
* Returns the File Container by the specific name
|
* Returns the File Container by the specific name
|
||||||
*/
|
*/
|
||||||
public static FileContainer getFileContainer(String name)
|
public static ResourceContainer getFileContainer(String name)
|
||||||
{
|
{
|
||||||
for (FileContainer container : files)
|
for (ResourceContainer container : files)
|
||||||
if (container.name.equals(name))
|
if (container.name.equals(name))
|
||||||
return container;
|
return container;
|
||||||
|
|
||||||
|
@ -382,7 +384,7 @@ public class BytecodeViewer
|
||||||
/**
|
/**
|
||||||
* Returns all of the loaded File Containers
|
* Returns all of the loaded File Containers
|
||||||
*/
|
*/
|
||||||
public static List<FileContainer> getFiles() {
|
public static List<ResourceContainer> getFiles() {
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,7 +396,7 @@ public class BytecodeViewer
|
||||||
*/
|
*/
|
||||||
public static byte[] getFileContents(String name)
|
public static byte[] getFileContents(String name)
|
||||||
{
|
{
|
||||||
for (FileContainer container : files)
|
for (ResourceContainer container : files)
|
||||||
if (container.resourceFiles.containsKey(name))
|
if (container.resourceFiles.containsKey(name))
|
||||||
return container.resourceFiles.get(name);
|
return container.resourceFiles.get(name);
|
||||||
|
|
||||||
|
@ -409,24 +411,6 @@ public class BytecodeViewer
|
||||||
return ClassFileUtils.getClassFileBytes(clazz);
|
return ClassFileUtils.getClassFileBytes(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces an old node with a new instance
|
|
||||||
*
|
|
||||||
* @param oldNode the old instance
|
|
||||||
* @param newNode the new instance
|
|
||||||
*/
|
|
||||||
public static void updateNode(ClassNode oldNode, ClassNode newNode)
|
|
||||||
{
|
|
||||||
for (FileContainer container : files)
|
|
||||||
{
|
|
||||||
if (container.resourceClasses.containsKey(oldNode.name))
|
|
||||||
{
|
|
||||||
container.resourceClasses.remove(oldNode.name);
|
|
||||||
container.resourceClasses.put(newNode.name, newNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all of the loaded classes as an array list
|
* Gets all of the loaded classes as an array list
|
||||||
*
|
*
|
||||||
|
@ -436,7 +420,7 @@ public class BytecodeViewer
|
||||||
{
|
{
|
||||||
ArrayList<ClassNode> a = new ArrayList<>();
|
ArrayList<ClassNode> a = new ArrayList<>();
|
||||||
|
|
||||||
for (FileContainer container : files)
|
for (ResourceContainer container : files)
|
||||||
for (ClassNode c : container.resourceClasses.values())
|
for (ClassNode c : container.resourceClasses.values())
|
||||||
if (!a.contains(c))
|
if (!a.contains(c))
|
||||||
a.add(c);
|
a.add(c);
|
||||||
|
|
|
@ -24,6 +24,7 @@ public class Configuration
|
||||||
public static File krakatauTempJar;
|
public static File krakatauTempJar;
|
||||||
public static boolean displayParentInTab = false; //also change in the main GUI
|
public static boolean displayParentInTab = false; //also change in the main GUI
|
||||||
public static boolean simplifiedTabNames = false;
|
public static boolean simplifiedTabNames = false;
|
||||||
|
public static boolean forceResourceUpdateFromClassNode = false; //TODO add to GUI
|
||||||
public static boolean currentlyDumping = false;
|
public static boolean currentlyDumping = false;
|
||||||
public static boolean needsReDump = true;
|
public static boolean needsReDump = true;
|
||||||
public static boolean warnForEditing = false;
|
public static boolean warnForEditing = false;
|
||||||
|
@ -39,12 +40,11 @@ public class Configuration
|
||||||
public static final int maxRecentFiles = 25; //eventually may be a setting
|
public static final int maxRecentFiles = 25; //eventually may be a setting
|
||||||
public static boolean verifyCorruptedStateOnBoot = false; //eventually may be a setting
|
public static boolean verifyCorruptedStateOnBoot = false; //eventually may be a setting
|
||||||
|
|
||||||
public static long lastHotKeyExecuted = 0;
|
public static BootState bootState = BootState.START_UP;
|
||||||
|
|
||||||
public static Language language = Language.ENGLISH;
|
public static Language language = Language.ENGLISH;
|
||||||
|
|
||||||
public static LAFTheme lafTheme = LAFTheme.SYSTEM; //lightmode by default since it uses the system theme
|
public static LAFTheme lafTheme = LAFTheme.SYSTEM; //lightmode by default since it uses the system theme
|
||||||
public static RSTATheme rstaTheme = lafTheme.getRSTATheme();
|
public static RSTATheme rstaTheme = lafTheme.getRSTATheme();
|
||||||
|
public static long lastHotKeyExecuted = 0;
|
||||||
|
|
||||||
public static File getLastDirectory()
|
public static File getLastDirectory()
|
||||||
{
|
{
|
||||||
|
@ -54,4 +54,11 @@ public class Configuration
|
||||||
|
|
||||||
return new File(".");
|
return new File(".");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum BootState
|
||||||
|
{
|
||||||
|
START_UP,
|
||||||
|
SETTINGS_LOADED,
|
||||||
|
GUI_SHOWING,
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,6 @@
|
||||||
package the.bytecode.club.bytecodeviewer.decompilers;
|
package the.bytecode.club.bytecodeviewer.decompilers;
|
||||||
|
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
|
||||||
import the.bytecode.club.bytecodeviewer.decompilers.impl.*;
|
import the.bytecode.club.bytecodeviewer.decompilers.impl.*;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.DecompilerViewComponent;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
import static the.bytecode.club.bytecodeviewer.gui.components.DecompilerViewComponent.DecompilerComponentTypes.*;
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
||||||
|
@ -33,46 +27,28 @@ import static the.bytecode.club.bytecodeviewer.gui.components.DecompilerViewComp
|
||||||
*/
|
*/
|
||||||
public enum Decompiler
|
public enum Decompiler
|
||||||
{
|
{
|
||||||
NONE("None", null, (JRadioButtonMenuItem) null),
|
//TODO WARNING: do not change the decompiler order, when adding a new decompiler just add it to the end
|
||||||
PROCYON_DECOMPILER("Procyon Decompiler", new ProcyonDecompiler(), new DecompilerViewComponent("Procyon", JAVA)),
|
// enum ordinal is used for settings serialization instead of the enum name
|
||||||
CFR_DECOMPILER("CFR Decompiler", new CFRDecompiler(), new DecompilerViewComponent("CFR", JAVA)),
|
NONE("None", null),
|
||||||
FERNFLOWER_DECOMPILER("FernFlower Decompiler", new FernFlowerDecompiler(), new DecompilerViewComponent("FernFlower", JAVA)),
|
PROCYON_DECOMPILER("Procyon Decompiler", new ProcyonDecompiler()),
|
||||||
BYTECODE_DISASSEMBLER("Bytecode Disassembler", new BytecodeDisassembler(), new JRadioButtonMenuItem("Bytecode")),
|
CFR_DECOMPILER("CFR Decompiler", new CFRDecompiler()),
|
||||||
HEXCODE_VIEWER("Hexcode Viewer", null, new JRadioButtonMenuItem("Hexcode")),
|
FERNFLOWER_DECOMPILER("FernFlower Decompiler", new FernFlowerDecompiler()),
|
||||||
SMALI_DISASSEMBLER("Smali Disassembler", new SmaliDisassembler(), new DecompilerViewComponent("Smali", BYTECODE)),
|
BYTECODE_DISASSEMBLER("Bytecode Disassembler", new BytecodeDisassembler()),
|
||||||
KRAKATAU_DECOMPILER("Krakatau Decompiler", new KrakatauDecompiler(), DecompilerViewComponent.KRAKATAU),
|
HEXCODE_VIEWER("Hexcode Viewer", null),
|
||||||
KRAKATAU_DISASSEMBLER("Krakatau Disassembler", new KrakatauDisassembler(), DecompilerViewComponent.KRAKATAU),
|
SMALI_DISASSEMBLER("Smali Disassembler", new SmaliDisassembler()),
|
||||||
JD_DECOMPILER("JD-GUI Decompiler", new JDGUIDecompiler(), new DecompilerViewComponent("JD-GUI", JAVA)),
|
KRAKATAU_DECOMPILER("Krakatau Decompiler", new KrakatauDecompiler()),
|
||||||
JADX_DECOMPILER("JADX Decompiler", new JADXDecompiler(), new DecompilerViewComponent("JADX", JAVA)),
|
KRAKATAU_DISASSEMBLER("Krakatau Disassembler", new KrakatauDisassembler()),
|
||||||
ASM_TEXTIFY_DISASSEMBLER("ASM Disassembler", new ASMTextifierDecompiler(), new DecompilerViewComponent("ASM Textify", BYTECODE)),
|
JD_DECOMPILER("JD-GUI Decompiler", new JDGUIDecompiler()),
|
||||||
|
JADX_DECOMPILER("JADX Decompiler", new JADXDecompiler()),
|
||||||
|
ASM_TEXTIFY_DISASSEMBLER("ASM Disassembler", new ASMTextifierDecompiler()),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final String decompilerName;
|
private final String decompilerName;
|
||||||
private final InternalDecompiler decompiler;
|
private final InternalDecompiler decompiler;
|
||||||
private final DecompilerViewComponent decompilerSelectComponent;
|
|
||||||
private final JRadioButtonMenuItem basicSelectComponent;
|
|
||||||
|
|
||||||
Decompiler(String decompilerName, InternalDecompiler decompiler, DecompilerViewComponent decompilerSelectComponent) {
|
Decompiler(String decompilerName, InternalDecompiler decompiler) {
|
||||||
this.decompilerName = decompilerName;
|
this.decompilerName = decompilerName;
|
||||||
this.decompiler = decompiler;
|
this.decompiler = decompiler;
|
||||||
this.decompilerSelectComponent = decompilerSelectComponent;
|
|
||||||
this.basicSelectComponent = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Decompiler(String decompilerName, InternalDecompiler decompiler, JRadioButtonMenuItem basicSelectComponent)
|
|
||||||
{
|
|
||||||
this.decompilerName = decompilerName;
|
|
||||||
this.decompiler = decompiler;
|
|
||||||
this.decompilerSelectComponent = null;
|
|
||||||
this.basicSelectComponent = basicSelectComponent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addDecompilerToGroup(ButtonGroup group)
|
|
||||||
{
|
|
||||||
if(decompilerSelectComponent != null)
|
|
||||||
decompilerSelectComponent.addToGroup(group);
|
|
||||||
else if(basicSelectComponent != null)
|
|
||||||
group.add(basicSelectComponent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDecompilerName()
|
public String getDecompilerName()
|
||||||
|
@ -84,17 +60,4 @@ public enum Decompiler
|
||||||
{
|
{
|
||||||
return decompiler;
|
return decompiler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DecompilerViewComponent getDecompilerSelectComponent()
|
|
||||||
{
|
|
||||||
return decompilerSelectComponent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JMenuItem getMenu()
|
|
||||||
{
|
|
||||||
if(decompilerSelectComponent != null)
|
|
||||||
return decompilerSelectComponent.getMenu();
|
|
||||||
|
|
||||||
return basicSelectComponent;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -14,7 +14,6 @@ import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
|
||||||
import the.bytecode.club.bytecodeviewer.decompilers.InternalDecompiler;
|
import the.bytecode.club.bytecodeviewer.decompilers.InternalDecompiler;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
||||||
import the.bytecode.club.bytecodeviewer.util.Dex2Jar;
|
import the.bytecode.club.bytecodeviewer.util.Dex2Jar;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
|
||||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||||
|
|
||||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||||
|
|
|
@ -292,9 +292,9 @@ public class MainViewerGUI extends JFrame
|
||||||
uiComponents.add(searchBoxPane);
|
uiComponents.add(searchBoxPane);
|
||||||
uiComponents.add(workPane);
|
uiComponents.add(workPane);
|
||||||
|
|
||||||
viewPane1.getGroup().setSelected(viewPane1.getFern().getJava().getModel(), true);
|
viewPane1.setDefault();
|
||||||
viewPane2.getGroup().setSelected(viewPane1.getBytecode().getModel(), true);
|
viewPane2.setDefault();
|
||||||
viewPane3.getGroup().setSelected(viewPane1.getNone().getModel(), true);
|
viewPane3.setDefault();
|
||||||
|
|
||||||
this.setLocationRelativeTo(null);
|
this.setLocationRelativeTo(null);
|
||||||
}
|
}
|
||||||
|
@ -349,9 +349,9 @@ public class MainViewerGUI extends JFrame
|
||||||
{
|
{
|
||||||
rootMenu.add(viewMainMenu);
|
rootMenu.add(viewMainMenu);
|
||||||
viewMainMenu.add(visualSettings);
|
viewMainMenu.add(visualSettings);
|
||||||
viewMainMenu.add(viewPane1.menu);
|
viewMainMenu.add(viewPane1.getMenu());
|
||||||
viewMainMenu.add(viewPane2.menu);
|
viewMainMenu.add(viewPane2.getMenu());
|
||||||
viewMainMenu.add(viewPane3.menu);
|
viewMainMenu.add(viewPane3.getMenu());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void buildSettingsMenu()
|
public void buildSettingsMenu()
|
||||||
|
@ -769,11 +769,11 @@ public class MainViewerGUI extends JFrame
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openClassFile(final FileContainer container, final String name, final ClassNode cn) {
|
public void openClassFile(final ResourceContainer container, final String name, final ClassNode cn) {
|
||||||
workPane.addClassResource(container, name, cn);
|
workPane.addClassResource(container, name, cn);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openFile(final FileContainer container, final String name, byte[] content) {
|
public void openFile(final ResourceContainer container, final String name, byte[] content) {
|
||||||
workPane.addFileResource(container, name, content);
|
workPane.addFileResource(container, name, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -811,7 +811,7 @@ public class MainViewerGUI extends JFrame
|
||||||
LazyNameUtil.reset();
|
LazyNameUtil.reset();
|
||||||
ArrayList<File> reopen = new ArrayList<>();
|
ArrayList<File> reopen = new ArrayList<>();
|
||||||
|
|
||||||
for (FileContainer container : BytecodeViewer.files) {
|
for (ResourceContainer container : BytecodeViewer.files) {
|
||||||
File newFile = new File(container.file.getParent() + fs + container.name);
|
File newFile = new File(container.file.getParent() + fs + container.name);
|
||||||
if (!container.file.getAbsolutePath().equals(newFile.getAbsolutePath()) &&
|
if (!container.file.getAbsolutePath().equals(newFile.getAbsolutePath()) &&
|
||||||
(container.file.getAbsolutePath().endsWith(".apk") || container.file.getAbsolutePath().endsWith(".dex"))) //APKs & dex get renamed
|
(container.file.getAbsolutePath().endsWith(".apk") || container.file.getAbsolutePath().endsWith(".dex"))) //APKs & dex get renamed
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||||
|
|
||||||
|
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.Translation;
|
import the.bytecode.club.bytecodeviewer.translation.Translation;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJCheckBoxMenuItem;
|
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJCheckBoxMenuItem;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJRadioButtonMenuItem;
|
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJRadioButtonMenuItem;
|
||||||
|
@ -7,7 +8,7 @@ import the.bytecode.club.bytecodeviewer.util.RefreshWorkPane;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
import static the.bytecode.club.bytecodeviewer.gui.components.DecompilerViewComponent.DecompilerComponentTypes.JAVA_AND_BYTECODE;
|
import static the.bytecode.club.bytecodeviewer.gui.components.DecompilerViewComponent.DecompilerComponentType.JAVA_AND_BYTECODE;
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
||||||
|
@ -33,41 +34,49 @@ import static the.bytecode.club.bytecodeviewer.gui.components.DecompilerViewComp
|
||||||
*/
|
*/
|
||||||
public class DecompilerViewComponent
|
public class DecompilerViewComponent
|
||||||
{
|
{
|
||||||
public static final DecompilerViewComponent KRAKATAU = new DecompilerViewComponent("Krakatau", JAVA_AND_BYTECODE);
|
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final JMenu menu;
|
private final JMenu menu;
|
||||||
private final DecompilerComponentTypes types;
|
private final DecompilerComponentType type;
|
||||||
private final JRadioButtonMenuItem java = new TranslatedJRadioButtonMenuItem("Java", Translation.JAVA);
|
private final Decompiler[] decompilers;
|
||||||
private final JRadioButtonMenuItem bytecode = new TranslatedJRadioButtonMenuItem("Bytecode", Translation.BYTECODE);
|
private final JRadioButtonMenuItem java;
|
||||||
private final JCheckBoxMenuItem editable = new TranslatedJCheckBoxMenuItem("Editable", Translation.EDITABLE);
|
private final JRadioButtonMenuItem bytecode;
|
||||||
|
private final JCheckBoxMenuItem editable;
|
||||||
|
|
||||||
public DecompilerViewComponent(String name, DecompilerComponentTypes types)
|
public DecompilerViewComponent(String name, DecompilerComponentType type, Decompiler... decompilers)
|
||||||
{
|
{
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.menu = new JMenu(name);
|
this.menu = new JMenu(name);
|
||||||
this.types = types;
|
this.type = type;
|
||||||
|
this.decompilers = decompilers;
|
||||||
|
this.java = new TranslatedJRadioButtonMenuItem("Java", Translation.JAVA);
|
||||||
|
this.bytecode = new TranslatedJRadioButtonMenuItem("Bytecode", Translation.BYTECODE);
|
||||||
|
this.editable = new TranslatedJCheckBoxMenuItem( "Editable", Translation.EDITABLE);
|
||||||
|
|
||||||
createMenu();
|
createMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createMenu()
|
private void createMenu()
|
||||||
{
|
{
|
||||||
if(types == DecompilerComponentTypes.JAVA || types == DecompilerComponentTypes.JAVA_AND_BYTECODE)
|
if(type == DecompilerComponentType.JAVA || type == DecompilerComponentType.JAVA_AND_BYTECODE)
|
||||||
menu.add(java);
|
menu.add(java);
|
||||||
if(types == DecompilerComponentTypes.BYTECODE || types == DecompilerComponentTypes.JAVA_AND_BYTECODE)
|
if(type == DecompilerComponentType.BYTECODE || type == DecompilerComponentType.JAVA_AND_BYTECODE
|
||||||
|
|| type == DecompilerComponentType.BYTECODE_NON_EDITABLE)
|
||||||
menu.add(bytecode);
|
menu.add(bytecode);
|
||||||
|
|
||||||
|
if(type != DecompilerComponentType.BYTECODE_NON_EDITABLE)
|
||||||
|
{
|
||||||
menu.add(new JSeparator());
|
menu.add(new JSeparator());
|
||||||
menu.add(editable);
|
menu.add(editable);
|
||||||
|
}
|
||||||
|
|
||||||
java.addActionListener(new RefreshWorkPane());
|
java.addActionListener(new RefreshWorkPane());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addToGroup(ButtonGroup group)
|
public void addToGroup(ButtonGroup group)
|
||||||
{
|
{
|
||||||
if(types == DecompilerComponentTypes.JAVA || types == DecompilerComponentTypes.JAVA_AND_BYTECODE)
|
if(type == DecompilerComponentType.JAVA || type == DecompilerComponentType.JAVA_AND_BYTECODE)
|
||||||
group.add(java);
|
group.add(java);
|
||||||
if(types == DecompilerComponentTypes.BYTECODE || types == DecompilerComponentTypes.JAVA_AND_BYTECODE)
|
if(type == DecompilerComponentType.BYTECODE || type == DecompilerComponentType.JAVA_AND_BYTECODE)
|
||||||
group.add(bytecode);
|
group.add(bytecode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,10 +100,21 @@ public class DecompilerViewComponent
|
||||||
return editable;
|
return editable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DecompilerComponentTypes
|
public DecompilerComponentType getType()
|
||||||
|
{
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Decompiler[] getDecompilers()
|
||||||
|
{
|
||||||
|
return decompilers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum DecompilerComponentType
|
||||||
{
|
{
|
||||||
JAVA,
|
JAVA,
|
||||||
BYTECODE,
|
BYTECODE,
|
||||||
|
BYTECODE_NON_EDITABLE,
|
||||||
JAVA_AND_BYTECODE
|
JAVA_AND_BYTECODE
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -34,7 +34,7 @@ import the.bytecode.club.bytecodeviewer.translation.Translation;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJCheckBox;
|
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJCheckBox;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJTextField;
|
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJTextField;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedVisibleComponent;
|
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedVisibleComponent;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileDrop;
|
import the.bytecode.club.bytecodeviewer.util.FileDrop;
|
||||||
import the.bytecode.club.bytecodeviewer.util.LazyNameUtil;
|
import the.bytecode.club.bytecodeviewer.util.LazyNameUtil;
|
||||||
|
|
||||||
|
@ -109,10 +109,10 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File
|
||||||
}
|
}
|
||||||
|
|
||||||
//used to remove resources from the resource list
|
//used to remove resources from the resource list
|
||||||
public void removeFile(FileContainer fileContainer)
|
public void removeFile(ResourceContainer resourceContainer)
|
||||||
{
|
{
|
||||||
BytecodeViewer.files.remove(fileContainer);
|
BytecodeViewer.files.remove(resourceContainer);
|
||||||
LazyNameUtil.removeName(fileContainer.name);
|
LazyNameUtil.removeName(resourceContainer.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceListPane()
|
public ResourceListPane()
|
||||||
|
@ -160,7 +160,7 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
treeRoot.removeAllChildren();
|
treeRoot.removeAllChildren();
|
||||||
for (FileContainer container : BytecodeViewer.files)
|
for (ResourceContainer container : BytecodeViewer.files)
|
||||||
{
|
{
|
||||||
ResourceTreeNode root = new ResourceTreeNode(container.name);
|
ResourceTreeNode root = new ResourceTreeNode(container.name);
|
||||||
treeRoot.add(root);
|
treeRoot.add(root);
|
||||||
|
@ -299,9 +299,9 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File
|
||||||
}
|
}
|
||||||
|
|
||||||
String cheapHax = path.getPathComponent(1).toString();
|
String cheapHax = path.getPathComponent(1).toString();
|
||||||
FileContainer container = null;
|
ResourceContainer container = null;
|
||||||
|
|
||||||
for (FileContainer c : BytecodeViewer.files)
|
for (ResourceContainer c : BytecodeViewer.files)
|
||||||
{
|
{
|
||||||
if (c.name.equals(cheapHax))
|
if (c.name.equals(cheapHax))
|
||||||
container = c;
|
container = c;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package the.bytecode.club.bytecodeviewer.gui.resourcelist;
|
package the.bytecode.club.bytecodeviewer.gui.resourcelist;
|
||||||
|
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.tree.DefaultMutableTreeNode;
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
|
@ -44,11 +44,11 @@ public class ResourceListRightClickRemove extends AbstractAction
|
||||||
DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot();
|
DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot();
|
||||||
root.remove(node);
|
root.remove(node);
|
||||||
|
|
||||||
for (FileContainer fileContainer : BytecodeViewer.files)
|
for (ResourceContainer resourceContainer : BytecodeViewer.files)
|
||||||
{
|
{
|
||||||
if (fileContainer.name.equals(selectNode.toString()))
|
if (resourceContainer.name.equals(selectNode.toString()))
|
||||||
{
|
{
|
||||||
resourceListPane.removeFile(fileContainer);
|
resourceListPane.removeFile(resourceContainer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import the.bytecode.club.bytecodeviewer.searching.RegexInsnFinder;
|
||||||
import the.bytecode.club.bytecodeviewer.searching.impl.RegexSearch;
|
import the.bytecode.club.bytecodeviewer.searching.impl.RegexSearch;
|
||||||
import the.bytecode.club.bytecodeviewer.searching.SearchResultNotifier;
|
import the.bytecode.club.bytecodeviewer.searching.SearchResultNotifier;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
|
|
||||||
import javax.swing.tree.TreePath;
|
import javax.swing.tree.TreePath;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -42,7 +42,7 @@ class PerformSearch extends BackgroundSearchThread
|
||||||
BytecodeViewer.showMessage("You have an error in your regex syntax.");
|
BytecodeViewer.showMessage("You have an error in your regex syntax.");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (FileContainer container : BytecodeViewer.files)
|
for (ResourceContainer container : BytecodeViewer.files)
|
||||||
for (ClassNode c : container.resourceClasses.values())
|
for (ClassNode c : container.resourceClasses.values())
|
||||||
searchBoxPane.searchType.details.search(container, c, srn, searchBoxPane.exact.isSelected());
|
searchBoxPane.searchType.details.search(container, c, srn, searchBoxPane.exact.isSelected());
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,11 @@ package the.bytecode.club.bytecodeviewer.gui.resourcesearch;
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.GridLayout;
|
import java.awt.GridLayout;
|
||||||
import java.awt.event.ItemListener;
|
import java.awt.event.ItemListener;
|
||||||
import java.beans.PropertyVetoException;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import javax.swing.DefaultComboBoxModel;
|
import javax.swing.DefaultComboBoxModel;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JCheckBox;
|
import javax.swing.JCheckBox;
|
||||||
import javax.swing.JComboBox;
|
import javax.swing.JComboBox;
|
||||||
import javax.swing.JLabel;
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JTree;
|
import javax.swing.JTree;
|
||||||
|
@ -18,14 +16,13 @@ import javax.swing.tree.DefaultTreeModel;
|
||||||
|
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.VisibleComponent;
|
|
||||||
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ResourceViewer;
|
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ResourceViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.searching.BackgroundSearchThread;
|
import the.bytecode.club.bytecodeviewer.searching.BackgroundSearchThread;
|
||||||
import the.bytecode.club.bytecodeviewer.searching.SearchResultNotifier;
|
import the.bytecode.club.bytecodeviewer.searching.SearchResultNotifier;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.Translation;
|
import the.bytecode.club.bytecodeviewer.translation.Translation;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.components.*;
|
import the.bytecode.club.bytecodeviewer.translation.components.*;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
||||||
|
@ -147,7 +144,7 @@ public class SearchBoxPane extends TranslatedVisibleComponent
|
||||||
|
|
||||||
String containerName = path.split(">", 2)[0];
|
String containerName = path.split(">", 2)[0];
|
||||||
String className = path.split(">", 2)[1].split("\\.")[0];
|
String className = path.split(">", 2)[1].split("\\.")[0];
|
||||||
FileContainer container = BytecodeViewer.getFileContainer(containerName);
|
ResourceContainer container = BytecodeViewer.getFileContainer(containerName);
|
||||||
|
|
||||||
final ClassNode fN = Objects.requireNonNull(container).getClassNode(className);
|
final ClassNode fN = Objects.requireNonNull(container).getClassNode(className);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package the.bytecode.club.bytecodeviewer.gui.resourceviewer;
|
package the.bytecode.club.bytecodeviewer.gui.resourceviewer;
|
||||||
|
|
||||||
|
import the.bytecode.club.bytecodeviewer.Configuration;
|
||||||
|
import the.bytecode.club.bytecodeviewer.SettingsSerializer;
|
||||||
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
|
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.DecompilerViewComponent;
|
import the.bytecode.club.bytecodeviewer.gui.components.DecompilerViewComponent;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.Translation;
|
import the.bytecode.club.bytecodeviewer.translation.Translation;
|
||||||
|
@ -8,7 +10,12 @@ import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJRadioB
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
import static the.bytecode.club.bytecodeviewer.gui.components.DecompilerViewComponent.DecompilerComponentTypes.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static the.bytecode.club.bytecodeviewer.gui.components.DecompilerViewComponent.DecompilerComponentType.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Konloch
|
* @author Konloch
|
||||||
|
@ -16,20 +23,25 @@ import static the.bytecode.club.bytecodeviewer.gui.components.DecompilerViewComp
|
||||||
*/
|
*/
|
||||||
public class DecompilerSelectionPane
|
public class DecompilerSelectionPane
|
||||||
{
|
{
|
||||||
public final int paneID;
|
private final int paneID;
|
||||||
public final JMenu menu;
|
private final JMenu menu;
|
||||||
public final ButtonGroup group = new ButtonGroup();
|
private final ButtonGroup group = new ButtonGroup();
|
||||||
public final JRadioButtonMenuItem none = new TranslatedJRadioButtonMenuItem("None", Translation.NONE);
|
private final JRadioButtonMenuItem none = new TranslatedJRadioButtonMenuItem("None", Translation.NONE);
|
||||||
public final DecompilerViewComponent procyon = new DecompilerViewComponent("Procyon", JAVA);
|
private final JRadioButtonMenuItem hexcode = new TranslatedJRadioButtonMenuItem("Hexcode", Translation.HEXCODE);
|
||||||
public final DecompilerViewComponent CFR = new DecompilerViewComponent("CFR", JAVA);
|
private final DecompilerViewComponent procyon = new DecompilerViewComponent("Procyon", JAVA, Decompiler.PROCYON_DECOMPILER);
|
||||||
public final DecompilerViewComponent JADX = new DecompilerViewComponent("JADX", JAVA);
|
private final DecompilerViewComponent CFR = new DecompilerViewComponent("CFR", JAVA, Decompiler.CFR_DECOMPILER);
|
||||||
public final DecompilerViewComponent JD = new DecompilerViewComponent("JD-GUI", JAVA);
|
private final DecompilerViewComponent JADX = new DecompilerViewComponent("JADX", JAVA, Decompiler.JADX_DECOMPILER);
|
||||||
public final DecompilerViewComponent fern = new DecompilerViewComponent("FernFlower", JAVA);
|
private final DecompilerViewComponent JD = new DecompilerViewComponent("JD-GUI", JAVA, Decompiler.JD_DECOMPILER);
|
||||||
public final DecompilerViewComponent krakatau = new DecompilerViewComponent("Krakatau", JAVA_AND_BYTECODE);
|
private final DecompilerViewComponent fern = new DecompilerViewComponent("FernFlower", JAVA, Decompiler.FERNFLOWER_DECOMPILER);
|
||||||
public final DecompilerViewComponent smali = new DecompilerViewComponent("Smali", BYTECODE);
|
private final DecompilerViewComponent krakatau = new DecompilerViewComponent( "Krakatau", JAVA_AND_BYTECODE, Decompiler.KRAKATAU_DECOMPILER, Decompiler.KRAKATAU_DISASSEMBLER);
|
||||||
public final JRadioButtonMenuItem hexcode = new TranslatedJRadioButtonMenuItem("Hexcode", Translation.HEXCODE);
|
private final DecompilerViewComponent smali = new DecompilerViewComponent("Smali", BYTECODE, Decompiler.SMALI_DISASSEMBLER);
|
||||||
public final JRadioButtonMenuItem bytecode = new TranslatedJRadioButtonMenuItem("Bytecode", Translation.BYTECODE);
|
private final DecompilerViewComponent bytecode = new DecompilerViewComponent("Bytecode", BYTECODE_NON_EDITABLE, Decompiler.BYTECODE_DISASSEMBLER);
|
||||||
public final JRadioButtonMenuItem asmTextify = new TranslatedJRadioButtonMenuItem("ASM Textify", Translation.ASM_TEXTIFY);
|
private final DecompilerViewComponent asmTextify = new DecompilerViewComponent("ASM Textify", BYTECODE_NON_EDITABLE, Decompiler.ASM_TEXTIFY_DISASSEMBLER);
|
||||||
|
|
||||||
|
//TODO when adding new decompilers insert the DecompilerViewComponent object into here
|
||||||
|
// also in the group, then finally the build menu
|
||||||
|
public List<DecompilerViewComponent> components = new ArrayList<>(Arrays.asList(
|
||||||
|
procyon, CFR, JADX, JD, fern, krakatau, smali, bytecode, asmTextify));
|
||||||
|
|
||||||
public DecompilerSelectionPane(int paneID)
|
public DecompilerSelectionPane(int paneID)
|
||||||
{
|
{
|
||||||
|
@ -44,8 +56,31 @@ public class DecompilerSelectionPane
|
||||||
buildMenu();
|
buildMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the default decompilers for each pane
|
||||||
|
*/
|
||||||
|
public void setDefault()
|
||||||
|
{
|
||||||
|
switch(paneID)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
group.setSelected(fern.getJava().getModel(), true);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
group.setSelected(bytecode.getBytecode().getModel(), true);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
group.setSelected(none.getModel(), true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the Decompiler View menu
|
||||||
|
*/
|
||||||
public void buildMenu()
|
public void buildMenu()
|
||||||
{
|
{
|
||||||
|
//build the radiobutton group
|
||||||
group.add(none);
|
group.add(none);
|
||||||
procyon.addToGroup(group);
|
procyon.addToGroup(group);
|
||||||
CFR.addToGroup(group);
|
CFR.addToGroup(group);
|
||||||
|
@ -54,10 +89,42 @@ public class DecompilerSelectionPane
|
||||||
fern.addToGroup(group);
|
fern.addToGroup(group);
|
||||||
krakatau.addToGroup(group);
|
krakatau.addToGroup(group);
|
||||||
smali.addToGroup(group);
|
smali.addToGroup(group);
|
||||||
group.add(bytecode);
|
bytecode.addToGroup(group);
|
||||||
|
asmTextify.addToGroup(group);
|
||||||
group.add(hexcode);
|
group.add(hexcode);
|
||||||
group.add(asmTextify);
|
|
||||||
|
|
||||||
|
//build the action commands
|
||||||
|
none.setActionCommand(Decompiler.NONE.name());
|
||||||
|
hexcode.setActionCommand(Decompiler.HEXCODE_VIEWER.name());
|
||||||
|
for(DecompilerViewComponent component : components)
|
||||||
|
{
|
||||||
|
for(Decompiler decompiler : component.getDecompilers())
|
||||||
|
{
|
||||||
|
String cmd = decompiler.name();
|
||||||
|
|
||||||
|
//TODO this is pretty janky and will break if a decompiler doesn't end with _DECOMPILER suffix
|
||||||
|
if(cmd.endsWith("DECOMPILER"))
|
||||||
|
component.getJava().setActionCommand(cmd);
|
||||||
|
else// if(cmd.endsWith("DISASSEMBLER"))
|
||||||
|
component.getBytecode().setActionCommand(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//auto-save on decompiler change
|
||||||
|
Enumeration<AbstractButton> it = group.getElements();
|
||||||
|
while(it.hasMoreElements())
|
||||||
|
{
|
||||||
|
AbstractButton button = it.nextElement();
|
||||||
|
button.addActionListener((event)->
|
||||||
|
{
|
||||||
|
if(Configuration.bootState != Configuration.BootState.GUI_SHOWING)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SettingsSerializer.saveSettingsAsync();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//build the menu
|
||||||
menu.add(none);
|
menu.add(none);
|
||||||
menu.add(new JSeparator());
|
menu.add(new JSeparator());
|
||||||
menu.add(procyon.getMenu());
|
menu.add(procyon.getMenu());
|
||||||
|
@ -69,164 +136,58 @@ public class DecompilerSelectionPane
|
||||||
menu.add(new JSeparator());
|
menu.add(new JSeparator());
|
||||||
menu.add(smali.getMenu());
|
menu.add(smali.getMenu());
|
||||||
menu.add(new JSeparator());
|
menu.add(new JSeparator());
|
||||||
|
menu.add(bytecode.getMenu());
|
||||||
|
menu.add(asmTextify.getMenu());
|
||||||
|
menu.add(new JSeparator());
|
||||||
menu.add(hexcode);
|
menu.add(hexcode);
|
||||||
menu.add(bytecode);
|
|
||||||
menu.add(asmTextify);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Decompiler getSelectedDecompiler()
|
public Decompiler getSelectedDecompiler()
|
||||||
{
|
{
|
||||||
if (group.isSelected(none.getModel()))
|
return Decompiler.valueOf(group.getSelection().getActionCommand());
|
||||||
return Decompiler.NONE;
|
|
||||||
else if (group.isSelected(procyon.getJava().getModel()))
|
|
||||||
return Decompiler.PROCYON_DECOMPILER;
|
|
||||||
else if (group.isSelected(CFR.getJava().getModel()))
|
|
||||||
return Decompiler.CFR_DECOMPILER;
|
|
||||||
else if (group.isSelected(fern.getJava().getModel()))
|
|
||||||
return Decompiler.FERNFLOWER_DECOMPILER;
|
|
||||||
else if (group.isSelected(bytecode.getModel()))
|
|
||||||
return Decompiler.BYTECODE_DISASSEMBLER;
|
|
||||||
else if (group.isSelected(hexcode.getModel()))
|
|
||||||
return Decompiler.HEXCODE_VIEWER;
|
|
||||||
else if (group.isSelected(smali.getBytecode().getModel()))
|
|
||||||
return Decompiler.SMALI_DISASSEMBLER;
|
|
||||||
else if (group.isSelected(krakatau.getJava().getModel()))
|
|
||||||
return Decompiler.KRAKATAU_DECOMPILER;
|
|
||||||
else if (group.isSelected(krakatau.getBytecode().getModel()))
|
|
||||||
return Decompiler.KRAKATAU_DISASSEMBLER;
|
|
||||||
else if (group.isSelected(JD.getJava().getModel()))
|
|
||||||
return Decompiler.JD_DECOMPILER;
|
|
||||||
else if (group.isSelected(JADX.getJava().getModel()))
|
|
||||||
return Decompiler.JADX_DECOMPILER;
|
|
||||||
else if (group.isSelected(asmTextify.getModel()))
|
|
||||||
return Decompiler.ASM_TEXTIFY_DISASSEMBLER;
|
|
||||||
|
|
||||||
System.out.println("DEFAULTING TO NULL");
|
|
||||||
|
|
||||||
//default to none
|
|
||||||
return Decompiler.NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectedDecompiler(Decompiler decompiler)
|
public void setSelectedDecompiler(Decompiler decompiler)
|
||||||
{
|
{
|
||||||
switch (decompiler)
|
Enumeration<AbstractButton> it = group.getElements();
|
||||||
|
while(it.hasMoreElements())
|
||||||
{
|
{
|
||||||
case NONE:
|
AbstractButton button = it.nextElement();
|
||||||
group.setSelected(none.getModel(), true);
|
if(button.getActionCommand().equals(decompiler.name()))
|
||||||
break;
|
{
|
||||||
case PROCYON_DECOMPILER:
|
group.setSelected(button.getModel(), true);
|
||||||
group.setSelected(procyon.getJava().getModel(), true);
|
|
||||||
break;
|
|
||||||
case CFR_DECOMPILER:
|
|
||||||
group.setSelected(CFR.getJava().getModel(), true);
|
|
||||||
break;
|
|
||||||
case FERNFLOWER_DECOMPILER:
|
|
||||||
group.setSelected(fern.getJava().getModel(), true);
|
|
||||||
break;
|
|
||||||
case BYTECODE_DISASSEMBLER:
|
|
||||||
group.setSelected(bytecode.getModel(), true);
|
|
||||||
break;
|
|
||||||
case HEXCODE_VIEWER:
|
|
||||||
group.setSelected(hexcode.getModel(), true);
|
|
||||||
break;
|
|
||||||
case SMALI_DISASSEMBLER:
|
|
||||||
group.setSelected(smali.getBytecode().getModel(), true);
|
|
||||||
break;
|
|
||||||
case KRAKATAU_DECOMPILER:
|
|
||||||
group.setSelected(krakatau.getJava().getModel(), true);
|
|
||||||
break;
|
|
||||||
case KRAKATAU_DISASSEMBLER:
|
|
||||||
group.setSelected(krakatau.getBytecode().getModel(), true);
|
|
||||||
break;
|
|
||||||
case JD_DECOMPILER:
|
|
||||||
group.setSelected(JD.getJava().getModel(), true);
|
|
||||||
break;
|
|
||||||
case JADX_DECOMPILER:
|
|
||||||
group.setSelected(JADX.getJava().getModel(), true);
|
|
||||||
break;
|
|
||||||
case ASM_TEXTIFY_DISASSEMBLER:
|
|
||||||
group.setSelected(asmTextify.getModel(), true);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isPaneEditable()
|
public boolean isPaneEditable()
|
||||||
{
|
{
|
||||||
if(group.isSelected(procyon.getJava().getModel()) && procyon.getEditable().isSelected())
|
String cmd = group.getSelection().getActionCommand();
|
||||||
return true;
|
|
||||||
if(group.isSelected(CFR.getJava().getModel()) && CFR.getEditable().isSelected())
|
for(DecompilerViewComponent component : components)
|
||||||
return true;
|
for (Decompiler decompiler : component.getDecompilers())
|
||||||
if(group.isSelected(JADX.getJava().getModel()) && JADX.getEditable().isSelected())
|
if(decompiler.name().equalsIgnoreCase(cmd))
|
||||||
return true;
|
return component.getEditable().isSelected();
|
||||||
if(group.isSelected(JD.getJava().getModel()) && JD.getEditable().isSelected())
|
|
||||||
return true;
|
|
||||||
if(group.isSelected(fern.getJava().getModel()) && fern.getEditable().isSelected())
|
|
||||||
return true;
|
|
||||||
if((group.isSelected(krakatau.getJava().getModel()) || group.isSelected(krakatau.getBytecode().getModel())) && krakatau.getEditable().isSelected())
|
|
||||||
return true;
|
|
||||||
if(group.isSelected(smali.getBytecode().getModel()) && smali.getEditable().isSelected())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ButtonGroup getGroup()
|
public void setPaneEditable(boolean value)
|
||||||
{
|
{
|
||||||
return group;
|
String cmd = group.getSelection().getActionCommand();
|
||||||
|
|
||||||
|
for(DecompilerViewComponent component : components)
|
||||||
|
for (Decompiler decompiler : component.getDecompilers())
|
||||||
|
if(decompiler.name().equalsIgnoreCase(cmd))
|
||||||
|
{
|
||||||
|
component.getEditable().setSelected(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public JRadioButtonMenuItem getNone()
|
public JMenu getMenu()
|
||||||
{
|
{
|
||||||
return none;
|
return menu;
|
||||||
}
|
|
||||||
|
|
||||||
public DecompilerViewComponent getProcyon()
|
|
||||||
{
|
|
||||||
return procyon;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DecompilerViewComponent getCFR()
|
|
||||||
{
|
|
||||||
return CFR;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DecompilerViewComponent getJADX()
|
|
||||||
{
|
|
||||||
return JADX;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DecompilerViewComponent getJD()
|
|
||||||
{
|
|
||||||
return JD;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DecompilerViewComponent getFern()
|
|
||||||
{
|
|
||||||
return fern;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DecompilerViewComponent getKrakatau()
|
|
||||||
{
|
|
||||||
return krakatau;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DecompilerViewComponent getSmali()
|
|
||||||
{
|
|
||||||
return smali;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JRadioButtonMenuItem getHexcode()
|
|
||||||
{
|
|
||||||
return hexcode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JRadioButtonMenuItem getBytecode()
|
|
||||||
{
|
|
||||||
return bytecode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JRadioButtonMenuItem getAsmTextify()
|
|
||||||
{
|
|
||||||
return asmTextify;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ public class ResourceViewPanel
|
||||||
if (compiledClass != null)
|
if (compiledClass != null)
|
||||||
{
|
{
|
||||||
ClassNode newNode = JarUtils.getNode(compiledClass);
|
ClassNode newNode = JarUtils.getNode(compiledClass);
|
||||||
BytecodeViewer.updateNode(viewer.cn, newNode);
|
viewer.container.updateNode(viewer.cn, newNode);
|
||||||
errConsole.finished();
|
errConsole.finished();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,13 @@ import javax.swing.JPopupMenu;
|
||||||
import javax.swing.JTabbedPane;
|
import javax.swing.JTabbedPane;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.VisibleComponent;
|
|
||||||
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ClassViewer;
|
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ClassViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.FileViewer;
|
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.FileViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ResourceViewer;
|
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ResourceViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.Translation;
|
import the.bytecode.club.bytecodeviewer.translation.Translation;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJButton;
|
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJButton;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedVisibleComponent;
|
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedVisibleComponent;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
|
|
||||||
import static the.bytecode.club.bytecodeviewer.Constants.BLOCK_TAB_MENU;
|
import static the.bytecode.club.bytecodeviewer.Constants.BLOCK_TAB_MENU;
|
||||||
|
|
||||||
|
@ -162,13 +161,13 @@ public class WorkPaneMainComponent extends TranslatedVisibleComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
//load class resources
|
//load class resources
|
||||||
public void addClassResource(final FileContainer container, final String name, final ClassNode cn)
|
public void addClassResource(final ResourceContainer container, final String name, final ClassNode cn)
|
||||||
{
|
{
|
||||||
addResource(container, name, new ClassViewer(container, name, cn));
|
addResource(container, name, new ClassViewer(container, name, cn));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Load file resources
|
//Load file resources
|
||||||
public void addFileResource(final FileContainer container, final String name, byte[] contents)
|
public void addFileResource(final ResourceContainer container, final String name, byte[] contents)
|
||||||
{
|
{
|
||||||
if (contents == null) //a directory
|
if (contents == null) //a directory
|
||||||
return;
|
return;
|
||||||
|
@ -176,9 +175,9 @@ public class WorkPaneMainComponent extends TranslatedVisibleComponent
|
||||||
addResource(container, name, new FileViewer(container, name, contents));
|
addResource(container, name, new FileViewer(container, name, contents));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addResource(final FileContainer container, final String name, final ResourceViewer resourceView)
|
private void addResource(final ResourceContainer container, final String name, final ResourceViewer resourceView)
|
||||||
{
|
{
|
||||||
final String workingName = container.generateWorkName(name);
|
final String workingName = container.getWorkingName(name);
|
||||||
|
|
||||||
//create a new tab if the resource isn't opened currently
|
//create a new tab if the resource isn't opened currently
|
||||||
if (!openedTabs.contains(workingName))
|
if (!openedTabs.contains(workingName))
|
||||||
|
|
|
@ -3,16 +3,14 @@ package the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer;
|
||||||
import the.bytecode.club.bytecodeviewer.api.ASMUtil;
|
import the.bytecode.club.bytecodeviewer.api.ASMUtil;
|
||||||
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
|
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.ResourceViewPanel;
|
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.ResourceViewPanel;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.hexviewer.JHexEditor;
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Container;
|
import java.awt.Container;
|
||||||
import java.awt.Dimension;
|
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.awt.event.ComponentAdapter;
|
import java.awt.event.ComponentAdapter;
|
||||||
import java.awt.event.ComponentEvent;
|
import java.awt.event.ComponentEvent;
|
||||||
import java.awt.event.HierarchyEvent;
|
import java.awt.event.HierarchyEvent;
|
||||||
import java.awt.event.HierarchyListener;
|
import java.awt.event.HierarchyListener;
|
||||||
import java.io.File;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
|
@ -22,13 +20,11 @@ import javax.swing.SwingUtilities;
|
||||||
import javax.swing.text.BadLocationException;
|
import javax.swing.text.BadLocationException;
|
||||||
|
|
||||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||||
import org.objectweb.asm.ClassWriter;
|
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.Configuration;
|
import the.bytecode.club.bytecodeviewer.Configuration;
|
||||||
import the.bytecode.club.bytecodeviewer.SettingsSerializer;
|
import the.bytecode.club.bytecodeviewer.SettingsSerializer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.BCVResourceUtils;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
|
||||||
import the.bytecode.club.bytecodeviewer.util.MethodParser;
|
import the.bytecode.club.bytecodeviewer.util.MethodParser;
|
||||||
|
|
||||||
import static the.bytecode.club.bytecodeviewer.util.MethodParser.Method;
|
import static the.bytecode.club.bytecodeviewer.util.MethodParser.Method;
|
||||||
|
@ -70,9 +66,9 @@ public class ClassViewer extends ResourceViewer
|
||||||
public List<MethodParser> methods = Arrays.asList(new MethodParser(), new MethodParser(), new MethodParser());
|
public List<MethodParser> methods = Arrays.asList(new MethodParser(), new MethodParser(), new MethodParser());
|
||||||
public final String workingName;
|
public final String workingName;
|
||||||
|
|
||||||
public ClassViewer(final FileContainer container, final String name, final ClassNode cn)
|
public ClassViewer(final ResourceContainer container, final String name, final ClassNode cn)
|
||||||
{
|
{
|
||||||
this.workingName = container.generateWorkName(name);
|
this.workingName = container.getWorkingName(name);
|
||||||
this.container = container;
|
this.container = container;
|
||||||
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -103,12 +99,19 @@ public class ClassViewer extends ResourceViewer
|
||||||
resourceViewPanel2.createPane(this);
|
resourceViewPanel2.createPane(this);
|
||||||
resourceViewPanel3.createPane(this);
|
resourceViewPanel3.createPane(this);
|
||||||
|
|
||||||
byte[] classBytes = getBytes();
|
byte[] classBytes = getResourceBytes();
|
||||||
|
|
||||||
//TODO remove this once all of the importers have been properly updated to use a FileContainerImporter
|
//TODO remove this once all of the importers have been properly updated to use a FileContainerImporter
|
||||||
if(classBytes == null || classBytes.length == 0)
|
if(classBytes == null || classBytes.length == 0 || Configuration.forceResourceUpdateFromClassNode)
|
||||||
{
|
{
|
||||||
System.err.println("WARNING: Imported using the old importer!");
|
//TODO remove this error message when all of the importers have been updated
|
||||||
|
// only APK and DEX are left
|
||||||
|
if(!Configuration.forceResourceUpdateFromClassNode)
|
||||||
|
{
|
||||||
|
System.err.println("WARNING: Class Resource imported using the old importer!");
|
||||||
|
System.err.println("TODO: Update it to use the FileContainerImporter");
|
||||||
|
}
|
||||||
|
|
||||||
classBytes = ASMUtil.nodeToBytes(cn);
|
classBytes = ASMUtil.nodeToBytes(cn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,13 +162,6 @@ public class ClassViewer extends ResourceViewer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void refreshTitle()
|
|
||||||
{
|
|
||||||
if(tabbedPane != null)
|
|
||||||
tabbedPane.label.setText(getTabName());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPanes() {
|
public void setPanes() {
|
||||||
resourceViewPanel1.decompiler = BytecodeViewer.viewer.viewPane1.getSelectedDecompiler();
|
resourceViewPanel1.decompiler = BytecodeViewer.viewer.viewPane1.getSelectedDecompiler();
|
||||||
resourceViewPanel2.decompiler = BytecodeViewer.viewer.viewPane2.getSelectedDecompiler();
|
resourceViewPanel2.decompiler = BytecodeViewer.viewer.viewPane2.getSelectedDecompiler();
|
||||||
|
|
|
@ -1,27 +1,19 @@
|
||||||
package the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer;
|
package the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.event.KeyEvent;
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JCheckBox;
|
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JTextField;
|
|
||||||
|
|
||||||
import org.fife.ui.rtextarea.RTextScrollPane;
|
|
||||||
import org.imgscalr.Scalr;
|
import org.imgscalr.Scalr;
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.Configuration;
|
import the.bytecode.club.bytecodeviewer.Configuration;
|
||||||
import the.bytecode.club.bytecodeviewer.Resources;
|
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.ImageJLabel;
|
import the.bytecode.club.bytecodeviewer.gui.components.ImageJLabel;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.SearchableRSyntaxTextArea;
|
import the.bytecode.club.bytecodeviewer.gui.components.SearchableRSyntaxTextArea;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.listeners.PressKeyListener;
|
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.listeners.ReleaseKeyListener;
|
|
||||||
import the.bytecode.club.bytecodeviewer.gui.hexviewer.JHexEditor;
|
import the.bytecode.club.bytecodeviewer.gui.hexviewer.JHexEditor;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.TabbedPane;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
|
||||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||||
import the.bytecode.club.bytecodeviewer.util.SyntaxLanguage;
|
import the.bytecode.club.bytecodeviewer.util.SyntaxLanguage;
|
||||||
|
|
||||||
|
@ -61,11 +53,11 @@ public class FileViewer extends ResourceViewer
|
||||||
public BufferedImage image;
|
public BufferedImage image;
|
||||||
public boolean canRefresh;
|
public boolean canRefresh;
|
||||||
|
|
||||||
public FileViewer(final FileContainer container, final String name, final byte[] contents)
|
public FileViewer(final ResourceContainer container, final String name, final byte[] contents)
|
||||||
{
|
{
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.contents = contents;
|
this.contents = contents;
|
||||||
this.workingName = container.generateWorkName(name);
|
this.workingName = container.getWorkingName(name);
|
||||||
this.container = container;
|
this.container = container;
|
||||||
this.setName(name);
|
this.setName(name);
|
||||||
this.setLayout(new BorderLayout());
|
this.setLayout(new BorderLayout());
|
||||||
|
@ -130,13 +122,6 @@ public class FileViewer extends ResourceViewer
|
||||||
mainPanel.add(textArea.getScrollPane());
|
mainPanel.add(textArea.getScrollPane());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void refreshTitle()
|
|
||||||
{
|
|
||||||
if(tabbedPane != null)
|
|
||||||
tabbedPane.label.setText(getTabName());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void refresh(JButton src)
|
public void refresh(JButton src)
|
||||||
{
|
{
|
||||||
refreshTitle();
|
refreshTitle();
|
||||||
|
|
|
@ -4,7 +4,7 @@ import javax.swing.JPanel;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bytecodeviewer.Configuration;
|
import the.bytecode.club.bytecodeviewer.Configuration;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.TabbedPane;
|
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.TabbedPane;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
@ -36,11 +36,12 @@ public abstract class ResourceViewer extends JPanel
|
||||||
public ClassNode cn;
|
public ClassNode cn;
|
||||||
public String name;
|
public String name;
|
||||||
public String workingName;
|
public String workingName;
|
||||||
public FileContainer container;
|
public ResourceContainer container;
|
||||||
public TabbedPane tabbedPane;
|
public TabbedPane tabbedPane;
|
||||||
|
|
||||||
public abstract void refreshTitle();
|
/**
|
||||||
|
* Returns the tab name
|
||||||
|
*/
|
||||||
public String getTabName()
|
public String getTabName()
|
||||||
{
|
{
|
||||||
String tabName = name;
|
String tabName = name;
|
||||||
|
@ -53,12 +54,21 @@ public abstract class ResourceViewer extends JPanel
|
||||||
return tabName;
|
return tabName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getBytes()
|
/**
|
||||||
|
* Returns the resource bytes from the resource container
|
||||||
|
*/
|
||||||
|
public byte[] getResourceBytes()
|
||||||
{
|
{
|
||||||
if(container.resourceClassBytes.containsKey(name))
|
return container.getBytes(name);
|
||||||
return container.resourceClassBytes.get(name);
|
}
|
||||||
else
|
|
||||||
return container.resourceFiles.get(name);
|
/**
|
||||||
|
* Updates the tab's title
|
||||||
|
*/
|
||||||
|
public void refreshTitle()
|
||||||
|
{
|
||||||
|
if(tabbedPane != null)
|
||||||
|
tabbedPane.label.setText(getTabName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final long serialVersionUID = -2965538493489119191L;
|
private static final long serialVersionUID = -2965538493489119191L;
|
||||||
|
|
|
@ -27,17 +27,17 @@ public class APKExport implements Exporter
|
||||||
if (BytecodeViewer.promptIfNoLoadedClasses())
|
if (BytecodeViewer.promptIfNoLoadedClasses())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
List<FileContainer> containers = BytecodeViewer.getFiles();
|
List<ResourceContainer> containers = BytecodeViewer.getFiles();
|
||||||
List<FileContainer> validContainers = new ArrayList<>();
|
List<ResourceContainer> validContainers = new ArrayList<>();
|
||||||
List<String> validContainersNames = new ArrayList<>();
|
List<String> validContainersNames = new ArrayList<>();
|
||||||
FileContainer container;
|
ResourceContainer container;
|
||||||
|
|
||||||
for (FileContainer fileContainer : containers)
|
for (ResourceContainer resourceContainer : containers)
|
||||||
{
|
{
|
||||||
if (fileContainer.APKToolContents != null && fileContainer.APKToolContents.exists())
|
if (resourceContainer.APKToolContents != null && resourceContainer.APKToolContents.exists())
|
||||||
{
|
{
|
||||||
validContainersNames.add(fileContainer.name);
|
validContainersNames.add(resourceContainer.name);
|
||||||
validContainers.add(fileContainer);
|
validContainers.add(resourceContainer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ public class APKExport implements Exporter
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final FileContainer finalContainer = container;
|
final ResourceContainer finalContainer = container;
|
||||||
|
|
||||||
Thread exportThread = new Thread(() ->
|
Thread exportThread = new Thread(() ->
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,6 @@ import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.*;
|
import the.bytecode.club.bytecodeviewer.util.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||||
|
@ -28,7 +27,7 @@ public class APKResourceImporter implements Importer
|
||||||
|
|
||||||
FileUtils.copyFile(file, tempCopy);
|
FileUtils.copyFile(file, tempCopy);
|
||||||
|
|
||||||
FileContainer container = new FileContainer(tempCopy, file.getName());
|
ResourceContainer container = new ResourceContainer(tempCopy, file.getName());
|
||||||
|
|
||||||
if (BytecodeViewer.viewer.decodeAPKResources.isSelected()) {
|
if (BytecodeViewer.viewer.decodeAPKResources.isSelected()) {
|
||||||
File decodedResources =
|
File decodedResources =
|
||||||
|
@ -48,10 +47,9 @@ public class APKResourceImporter implements Importer
|
||||||
else if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel()))
|
else if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel()))
|
||||||
Enjarify.apk2Jar(tempCopy, output);
|
Enjarify.apk2Jar(tempCopy, output);
|
||||||
|
|
||||||
//TODO update to FileContainerImporter
|
//create a new resource importer and copy the contents from it
|
||||||
ArrayList<ClassNode> nodeList = JarUtils.loadClasses(output);
|
container.clear().copy(new ResourceContainerImporter(
|
||||||
for(ClassNode cn : nodeList)
|
new ResourceContainer(output)).importAsZip().getContainer());
|
||||||
container.resourceClasses.put(cn.name, cn);
|
|
||||||
|
|
||||||
BytecodeViewer.updateBusyStatus(false);
|
BytecodeViewer.updateBusyStatus(false);
|
||||||
BytecodeViewer.files.add(container);
|
BytecodeViewer.files.add(container);
|
||||||
|
|
|
@ -4,7 +4,7 @@ import org.apache.commons.io.FilenameUtils;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
|
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
||||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ public class ClassResourceImporter implements Importer
|
||||||
{
|
{
|
||||||
final String name = file.getName();
|
final String name = file.getName();
|
||||||
byte[] bytes = MiscUtils.getBytes(new FileInputStream(file));
|
byte[] bytes = MiscUtils.getBytes(new FileInputStream(file));
|
||||||
FileContainer container = new FileContainer(file);
|
ResourceContainer container = new ResourceContainer(file);
|
||||||
|
|
||||||
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,7 +27,7 @@ public class DEXResourceImporter implements Importer
|
||||||
|
|
||||||
FileUtils.copyFile(file, tempCopy); //copy and rename to prevent unicode filenames
|
FileUtils.copyFile(file, tempCopy); //copy and rename to prevent unicode filenames
|
||||||
|
|
||||||
FileContainer container = new FileContainer(tempCopy, file.getName());
|
ResourceContainer container = new ResourceContainer(tempCopy, file.getName());
|
||||||
|
|
||||||
String name = MiscUtils.getRandomizedName() + ".jar";
|
String name = MiscUtils.getRandomizedName() + ".jar";
|
||||||
File output = new File(tempDirectory + fs + name);
|
File output = new File(tempDirectory + fs + name);
|
||||||
|
@ -37,10 +37,9 @@ public class DEXResourceImporter implements Importer
|
||||||
else if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel()))
|
else if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel()))
|
||||||
Enjarify.apk2Jar(tempCopy, output);
|
Enjarify.apk2Jar(tempCopy, output);
|
||||||
|
|
||||||
//TODO update to FileContainerImporter
|
//create a new resource importer and copy the contents from it
|
||||||
ArrayList<ClassNode> nodeList = JarUtils.loadClasses(output);
|
container.clear().copy(new ResourceContainerImporter(
|
||||||
for(ClassNode cn : nodeList)
|
new ResourceContainer(output)).importAsZip().getContainer());
|
||||||
container.resourceClasses.put(cn.name, cn);
|
|
||||||
|
|
||||||
BytecodeViewer.updateBusyStatus(false);
|
BytecodeViewer.updateBusyStatus(false);
|
||||||
BytecodeViewer.files.add(container);
|
BytecodeViewer.files.add(container);
|
||||||
|
|
|
@ -5,7 +5,7 @@ import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.resources.importing.Import;
|
import the.bytecode.club.bytecodeviewer.resources.importing.Import;
|
||||||
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
|
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
||||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ public class DirectoryResourceImporter implements Importer
|
||||||
@Override
|
@Override
|
||||||
public void open(File file) throws Exception
|
public void open(File file) throws Exception
|
||||||
{
|
{
|
||||||
FileContainer container = new FileContainer(file);
|
ResourceContainer container = new ResourceContainer(file);
|
||||||
HashMap<String, byte[]> allDirectoryFiles = new HashMap<>();
|
HashMap<String, byte[]> allDirectoryFiles = new HashMap<>();
|
||||||
HashMap<String, ClassNode> allDirectoryClasses = new HashMap<>();
|
HashMap<String, ClassNode> allDirectoryClasses = new HashMap<>();
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,10 @@ package the.bytecode.club.bytecodeviewer.resources.importing.impl;
|
||||||
|
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
|
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainerImporter;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainerImporter;
|
||||||
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
|
||||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Konloch
|
* @author Konloch
|
||||||
|
@ -21,9 +17,9 @@ public class FileResourceImporter implements Importer
|
||||||
public void open(File file) throws Exception
|
public void open(File file) throws Exception
|
||||||
{
|
{
|
||||||
//create the new file container
|
//create the new file container
|
||||||
FileContainer container = new FileContainer(file);
|
ResourceContainer container = new ResourceContainer(file);
|
||||||
//create the new file importer
|
//create the new file importer
|
||||||
FileContainerImporter importer = new FileContainerImporter(container);
|
ResourceContainerImporter importer = new ResourceContainerImporter(container);
|
||||||
//import the file into the file container
|
//import the file into the file container
|
||||||
importer.importAsFile();
|
importer.importAsFile();
|
||||||
//add the file container to BCV's total loaded files
|
//add the file container to BCV's total loaded files
|
||||||
|
|
|
@ -6,7 +6,7 @@ import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.Configuration;
|
import the.bytecode.club.bytecodeviewer.Configuration;
|
||||||
import the.bytecode.club.bytecodeviewer.resources.importing.Import;
|
import the.bytecode.club.bytecodeviewer.resources.importing.Import;
|
||||||
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
|
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
@ -29,7 +29,7 @@ public class XAPKResourceImporter implements Importer
|
||||||
@Override
|
@Override
|
||||||
public void open(File file) throws Exception
|
public void open(File file) throws Exception
|
||||||
{
|
{
|
||||||
FileContainer container = new FileContainer(file);
|
ResourceContainer container = new ResourceContainer(file);
|
||||||
HashMap<String, byte[]> allDirectoryFiles = new HashMap<>();
|
HashMap<String, byte[]> allDirectoryFiles = new HashMap<>();
|
||||||
|
|
||||||
Configuration.silenceExceptionGUI++; //turn exceptions off
|
Configuration.silenceExceptionGUI++; //turn exceptions off
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
package the.bytecode.club.bytecodeviewer.resources.importing.impl;
|
package the.bytecode.club.bytecodeviewer.resources.importing.impl;
|
||||||
|
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
|
|
||||||
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
|
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainerImporter;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainerImporter;
|
||||||
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Konloch
|
* @author Konloch
|
||||||
|
@ -20,9 +17,9 @@ public class ZipResourceImporter implements Importer
|
||||||
public void open(File file) throws Exception
|
public void open(File file) throws Exception
|
||||||
{
|
{
|
||||||
//create the new file container
|
//create the new file container
|
||||||
FileContainer container = new FileContainer(file);
|
ResourceContainer container = new ResourceContainer(file);
|
||||||
//create the new file importer
|
//create the new file importer
|
||||||
FileContainerImporter importer = new FileContainerImporter(container);
|
ResourceContainerImporter importer = new ResourceContainerImporter(container);
|
||||||
//import the file as zip into the file container
|
//import the file as zip into the file container
|
||||||
importer.importAsZip();
|
importer.importAsZip();
|
||||||
//add the file container to BCV's total loaded files
|
//add the file container to BCV's total loaded files
|
||||||
|
|
|
@ -2,7 +2,7 @@ package the.bytecode.club.bytecodeviewer.searching;
|
||||||
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
||||||
|
@ -34,5 +34,5 @@ public interface SearchTypeDetails
|
||||||
{
|
{
|
||||||
JPanel getPanel();
|
JPanel getPanel();
|
||||||
|
|
||||||
void search(FileContainer container, ClassNode node, SearchResultNotifier srn, boolean exact);
|
void search(ResourceContainer container, ClassNode node, SearchResultNotifier srn, boolean exact);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import org.objectweb.asm.tree.FieldInsnNode;
|
||||||
import org.objectweb.asm.tree.InsnList;
|
import org.objectweb.asm.tree.InsnList;
|
||||||
import org.objectweb.asm.tree.MethodNode;
|
import org.objectweb.asm.tree.MethodNode;
|
||||||
import the.bytecode.club.bytecodeviewer.searching.SearchResultNotifier;
|
import the.bytecode.club.bytecodeviewer.searching.SearchResultNotifier;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
||||||
|
@ -38,7 +38,7 @@ import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
||||||
public class FieldCallSearch extends MethodCallSearch
|
public class FieldCallSearch extends MethodCallSearch
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void search(final FileContainer container, final ClassNode node, final SearchResultNotifier srn,
|
public void search(final ResourceContainer container, final ClassNode node, final SearchResultNotifier srn,
|
||||||
boolean exact)
|
boolean exact)
|
||||||
{
|
{
|
||||||
final Iterator<MethodNode> methods = node.methods.iterator();
|
final Iterator<MethodNode> methods = node.methods.iterator();
|
||||||
|
|
|
@ -2,7 +2,6 @@ package the.bytecode.club.bytecodeviewer.searching.impl;
|
||||||
|
|
||||||
import java.awt.GridLayout;
|
import java.awt.GridLayout;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import javax.swing.JLabel;
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JTextField;
|
import javax.swing.JTextField;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
|
@ -17,7 +16,7 @@ import the.bytecode.club.bytecodeviewer.searching.SearchResultNotifier;
|
||||||
import the.bytecode.club.bytecodeviewer.searching.SearchTypeDetails;
|
import the.bytecode.club.bytecodeviewer.searching.SearchTypeDetails;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.Translation;
|
import the.bytecode.club.bytecodeviewer.translation.Translation;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJLabel;
|
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJLabel;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
||||||
|
@ -70,7 +69,7 @@ public class LDCSearch implements SearchTypeDetails
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void search(final FileContainer container, final ClassNode node, final SearchResultNotifier srn,
|
public void search(final ResourceContainer container, final ClassNode node, final SearchResultNotifier srn,
|
||||||
boolean exact)
|
boolean exact)
|
||||||
{
|
{
|
||||||
final Iterator<MethodNode> methods = node.methods.iterator();
|
final Iterator<MethodNode> methods = node.methods.iterator();
|
||||||
|
|
|
@ -4,7 +4,6 @@ import eu.bibl.banalysis.asm.desc.OpcodeInfo;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import javax.swing.JLabel;
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JTextField;
|
import javax.swing.JTextField;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
|
@ -18,7 +17,7 @@ import the.bytecode.club.bytecodeviewer.searching.SearchResultNotifier;
|
||||||
import the.bytecode.club.bytecodeviewer.searching.SearchTypeDetails;
|
import the.bytecode.club.bytecodeviewer.searching.SearchTypeDetails;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.Translation;
|
import the.bytecode.club.bytecodeviewer.translation.Translation;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJLabel;
|
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJLabel;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
||||||
|
@ -81,7 +80,7 @@ public class MethodCallSearch implements SearchTypeDetails
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void search(final FileContainer container, final ClassNode node, final SearchResultNotifier srn,
|
public void search(final ResourceContainer container, final ClassNode node, final SearchResultNotifier srn,
|
||||||
boolean exact)
|
boolean exact)
|
||||||
{
|
{
|
||||||
final Iterator<MethodNode> methods = node.methods.iterator();
|
final Iterator<MethodNode> methods = node.methods.iterator();
|
||||||
|
@ -137,7 +136,7 @@ public class MethodCallSearch implements SearchTypeDetails
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void found(final FileContainer container, final ClassNode node, final MethodNode method, final AbstractInsnNode insnNode, final SearchResultNotifier srn)
|
public void found(final ResourceContainer container, final ClassNode node, final MethodNode method, final AbstractInsnNode insnNode, final SearchResultNotifier srn)
|
||||||
{
|
{
|
||||||
String desc = method.desc;
|
String desc = method.desc;
|
||||||
try
|
try
|
||||||
|
|
|
@ -3,7 +3,6 @@ package the.bytecode.club.bytecodeviewer.searching.impl;
|
||||||
import java.awt.GridLayout;
|
import java.awt.GridLayout;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import javax.swing.JLabel;
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JTextField;
|
import javax.swing.JTextField;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
|
@ -15,7 +14,7 @@ import the.bytecode.club.bytecodeviewer.searching.SearchResultNotifier;
|
||||||
import the.bytecode.club.bytecodeviewer.searching.SearchTypeDetails;
|
import the.bytecode.club.bytecodeviewer.searching.SearchTypeDetails;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.Translation;
|
import the.bytecode.club.bytecodeviewer.translation.Translation;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJLabel;
|
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJLabel;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
import the.bytecode.club.bytecodeviewer.util.ResourceContainer;
|
||||||
|
|
||||||
import static the.bytecode.club.bytecodeviewer.searching.RegexInsnFinder.processRegex;
|
import static the.bytecode.club.bytecodeviewer.searching.RegexInsnFinder.processRegex;
|
||||||
|
|
||||||
|
@ -70,7 +69,7 @@ public class RegexSearch implements SearchTypeDetails
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void search(final FileContainer container, final ClassNode node, final SearchResultNotifier srn,
|
public void search(final ResourceContainer container, final ClassNode node, final SearchResultNotifier srn,
|
||||||
boolean exact)
|
boolean exact)
|
||||||
{
|
{
|
||||||
final Iterator<MethodNode> methods = node.methods.iterator();
|
final Iterator<MethodNode> methods = node.methods.iterator();
|
||||||
|
|
|
@ -29,7 +29,7 @@ import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||||
*/
|
*/
|
||||||
public class APKTool {
|
public class APKTool {
|
||||||
|
|
||||||
public static synchronized void decodeResources(File input, File output, FileContainer container) {
|
public static synchronized void decodeResources(File input, File output, ResourceContainer container) {
|
||||||
try {
|
try {
|
||||||
File dir = new File(tempDirectory + fs + MiscUtils.randomString(32) + fs + "Decoded Resources");
|
File dir = new File(tempDirectory + fs + MiscUtils.randomString(32) + fs + "Decoded Resources");
|
||||||
dir.mkdirs();
|
dir.mkdirs();
|
||||||
|
@ -52,7 +52,7 @@ public class APKTool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized void buildAPK(File input, File output, FileContainer container) {
|
public static synchronized void buildAPK(File input, File output, ResourceContainer container) {
|
||||||
String temp = tempDirectory + fs;
|
String temp = tempDirectory + fs;
|
||||||
File tempDir = new File(temp + fs + MiscUtils.getRandomizedName() + fs);
|
File tempDir = new File(temp + fs + MiscUtils.getRandomizedName() + fs);
|
||||||
tempDir.mkdirs();
|
tempDir.mkdirs();
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
package the.bytecode.club.bytecodeviewer.util;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
|
||||||
* Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com *
|
|
||||||
* *
|
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU General Public License as published by *
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
* This program 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 General Public License for more details. *
|
|
||||||
* *
|
|
||||||
* You should have received a copy of the GNU General Public License *
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a file container
|
|
||||||
*
|
|
||||||
* @author Konloch
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class FileContainer {
|
|
||||||
|
|
||||||
public FileContainer(File f) {
|
|
||||||
this.file = f;
|
|
||||||
this.name = LazyNameUtil.applyNameChanges(f.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileContainer(File f, String name) {
|
|
||||||
this.file = f;
|
|
||||||
this.name = LazyNameUtil.applyNameChanges(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public File file;
|
|
||||||
public String name;
|
|
||||||
public File APKToolContents = null;
|
|
||||||
|
|
||||||
public HashMap<String, byte[]> resourceFiles = new HashMap<>();
|
|
||||||
public HashMap<String, byte[]> resourceClassBytes = new HashMap<>();
|
|
||||||
public HashMap<String, ClassNode> resourceClasses = new HashMap<>();
|
|
||||||
|
|
||||||
public ClassNode getClassNode(String name)
|
|
||||||
{
|
|
||||||
return resourceClasses.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String generateWorkName(String name)
|
|
||||||
{
|
|
||||||
return file.getAbsolutePath() + ">" + name;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,5 @@
|
||||||
package the.bytecode.club.bytecodeviewer.util;
|
package the.bytecode.club.bytecodeviewer.util;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
@ -67,7 +66,7 @@ public class JarUtils
|
||||||
*/
|
*/
|
||||||
public static void importArchiveA(final File jarFile) throws IOException
|
public static void importArchiveA(final File jarFile) throws IOException
|
||||||
{
|
{
|
||||||
FileContainer container = new FileContainer(jarFile);
|
ResourceContainer container = new ResourceContainer(jarFile);
|
||||||
HashMap<String, byte[]> files = new HashMap<>();
|
HashMap<String, byte[]> files = new HashMap<>();
|
||||||
|
|
||||||
ZipInputStream jis = new ZipInputStream(new FileInputStream(jarFile));
|
ZipInputStream jis = new ZipInputStream(new FileInputStream(jarFile));
|
||||||
|
@ -121,7 +120,7 @@ public class JarUtils
|
||||||
//if this ever fails, worst case import Sun's jarsigner code from JDK 7 re-sign the jar to rebuild the CRC,
|
//if this ever fails, worst case import Sun's jarsigner code from JDK 7 re-sign the jar to rebuild the CRC,
|
||||||
// should also rebuild the archive byte offsets
|
// should also rebuild the archive byte offsets
|
||||||
|
|
||||||
FileContainer container = new FileContainer(jarFile);
|
ResourceContainer container = new ResourceContainer(jarFile);
|
||||||
HashMap<String, byte[]> files = new HashMap<>();
|
HashMap<String, byte[]> files = new HashMap<>();
|
||||||
|
|
||||||
try (ZipFile zipFile = new ZipFile(jarFile)) {
|
try (ZipFile zipFile = new ZipFile(jarFile)) {
|
||||||
|
@ -231,7 +230,9 @@ public class JarUtils
|
||||||
* @param bytez the class file's byte[]
|
* @param bytez the class file's byte[]
|
||||||
* @return the ClassNode instance
|
* @return the ClassNode instance
|
||||||
*/
|
*/
|
||||||
public static ClassNode getNode(final byte[] bytez) {
|
public static ClassNode getNode(final byte[] bytez)
|
||||||
|
{
|
||||||
|
//TODO figure out why is this synchronized and if it's actually needed (probably not)
|
||||||
synchronized (LOCK)
|
synchronized (LOCK)
|
||||||
{
|
{
|
||||||
return ASMUtil.bytesToNode(bytez);
|
return ASMUtil.bytesToNode(bytez);
|
||||||
|
@ -263,7 +264,7 @@ public class JarUtils
|
||||||
out.write((manifest.trim() + "\r\n\r\n").getBytes());
|
out.write((manifest.trim() + "\r\n\r\n").getBytes());
|
||||||
out.closeEntry();
|
out.closeEntry();
|
||||||
|
|
||||||
for (FileContainer container : BytecodeViewer.files)
|
for (ResourceContainer container : BytecodeViewer.files)
|
||||||
for (Entry<String, byte[]> entry : container.resourceFiles.entrySet()) {
|
for (Entry<String, byte[]> entry : container.resourceFiles.entrySet()) {
|
||||||
String filename = entry.getKey();
|
String filename = entry.getKey();
|
||||||
if (!filename.startsWith("META-INF")) {
|
if (!filename.startsWith("META-INF")) {
|
||||||
|
@ -287,6 +288,7 @@ public class JarUtils
|
||||||
*/
|
*/
|
||||||
public static void saveAsJarClassesOnly(Collection<ClassNode> nodeList, String path)
|
public static void saveAsJarClassesOnly(Collection<ClassNode> nodeList, String path)
|
||||||
{
|
{
|
||||||
|
//TODO figure out why is this synchronized and if it's actually needed (probably not)
|
||||||
synchronized (LOCK)
|
synchronized (LOCK)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -366,7 +368,7 @@ public class JarUtils
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (FileContainer container : BytecodeViewer.files)
|
for (ResourceContainer container : BytecodeViewer.files)
|
||||||
for (Entry<String, byte[]> entry : container.resourceFiles.entrySet()) {
|
for (Entry<String, byte[]> entry : container.resourceFiles.entrySet()) {
|
||||||
String filename = entry.getKey();
|
String filename = entry.getKey();
|
||||||
if (!filename.startsWith("META-INF")) {
|
if (!filename.startsWith("META-INF")) {
|
||||||
|
|
|
@ -176,9 +176,9 @@ public class MiscUtils
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int fileContainersHash(ArrayList<FileContainer> fileContainers) {
|
public static int fileContainersHash(ArrayList<ResourceContainer> resourceContainers) {
|
||||||
StringBuilder block = new StringBuilder();
|
StringBuilder block = new StringBuilder();
|
||||||
for (FileContainer container : fileContainers) {
|
for (ResourceContainer container : resourceContainers) {
|
||||||
block.append(container.name);
|
block.append(container.name);
|
||||||
for (ClassNode node : container.resourceClasses.values()) {
|
for (ClassNode node : container.resourceClasses.values()) {
|
||||||
block.append(node.name);
|
block.append(node.name);
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
package the.bytecode.club.bytecodeviewer.util;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
import the.bytecode.club.bytecodeviewer.api.ASMUtil;
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
||||||
|
* Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com *
|
||||||
|
* *
|
||||||
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program 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 General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a file container
|
||||||
|
*
|
||||||
|
* @author Konloch
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ResourceContainer
|
||||||
|
{
|
||||||
|
public File file;
|
||||||
|
public String name;
|
||||||
|
public File APKToolContents = null;
|
||||||
|
|
||||||
|
public HashMap<String, byte[]> resourceFiles = new HashMap<>();
|
||||||
|
public HashMap<String, byte[]> resourceClassBytes = new HashMap<>();
|
||||||
|
public HashMap<String, ClassNode> resourceClasses = new HashMap<>();
|
||||||
|
|
||||||
|
public ResourceContainer(File f)
|
||||||
|
{
|
||||||
|
this(f, LazyNameUtil.applyNameChanges(f.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceContainer(File f, String name)
|
||||||
|
{
|
||||||
|
this.file = f;
|
||||||
|
this.name = LazyNameUtil.applyNameChanges(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ClassNode resource for the specified resource key (full name path)
|
||||||
|
*/
|
||||||
|
public ClassNode getClassNode(String resourceName)
|
||||||
|
{
|
||||||
|
return resourceClasses.get(resourceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the unique 'working' name for container + resource look up.
|
||||||
|
* This is used to look up a specific resource inside of this specific
|
||||||
|
* container when you need to iterate through all opened containers
|
||||||
|
*/
|
||||||
|
public String getWorkingName(String resourceName)
|
||||||
|
{
|
||||||
|
return file.getAbsolutePath() + ">" + resourceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the resource bytes for the specified resource key (full name path)
|
||||||
|
*/
|
||||||
|
public byte[] getBytes(String resourceName)
|
||||||
|
{
|
||||||
|
if(resourceClassBytes.containsKey(resourceName))
|
||||||
|
return resourceClassBytes.get(resourceName);
|
||||||
|
else
|
||||||
|
return resourceFiles.get(resourceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the ClassNode reference on the resourceClass list and resourceClassBytes list
|
||||||
|
*/
|
||||||
|
public ResourceContainer updateNode(ClassNode oldNode, ClassNode newNode)
|
||||||
|
{
|
||||||
|
//update all classnode references for ASM
|
||||||
|
if (resourceClasses.containsKey(oldNode.name))
|
||||||
|
{
|
||||||
|
resourceClasses.remove(oldNode.name);
|
||||||
|
resourceClasses.put(newNode.name, newNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
//update the resource bytes
|
||||||
|
String oldResourceKey = oldNode.name + ".class";
|
||||||
|
String newResourceKey = newNode.name + ".class";
|
||||||
|
if(resourceClassBytes.containsKey(oldResourceKey))
|
||||||
|
{
|
||||||
|
resourceClassBytes.remove(oldResourceKey);
|
||||||
|
resourceClassBytes.put(newResourceKey, ASMUtil.nodeToBytes(newNode));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceContainer clear()
|
||||||
|
{
|
||||||
|
resourceFiles.clear();
|
||||||
|
resourceClassBytes.clear();
|
||||||
|
resourceClasses.clear();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceContainer copy(ResourceContainer copyFrom)
|
||||||
|
{
|
||||||
|
resourceFiles.putAll(copyFrom.resourceFiles);
|
||||||
|
resourceClassBytes.putAll(copyFrom.resourceClassBytes);
|
||||||
|
resourceClasses.putAll(copyFrom.resourceClasses);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,21 +15,26 @@ import java.util.zip.ZipInputStream;
|
||||||
* @author Konloch
|
* @author Konloch
|
||||||
* @since 7/10/2021
|
* @since 7/10/2021
|
||||||
*/
|
*/
|
||||||
public class FileContainerImporter
|
public class ResourceContainerImporter
|
||||||
{
|
{
|
||||||
private final FileContainer container;
|
private final ResourceContainer container;
|
||||||
|
|
||||||
public FileContainerImporter(FileContainer container)
|
public ResourceContainerImporter(ResourceContainer container)
|
||||||
{
|
{
|
||||||
this.container = container;
|
this.container = container;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void importAsFile() throws IOException
|
public ResourceContainer getContainer()
|
||||||
{
|
{
|
||||||
addUnknownFile(container.file.getName(), new FileInputStream(container.file), false);
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void importAsZip() throws IOException
|
public ResourceContainerImporter importAsFile() throws IOException
|
||||||
|
{
|
||||||
|
return addUnknownFile(container.file.getName(), new FileInputStream(container.file), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceContainerImporter importAsZip() throws IOException
|
||||||
{
|
{
|
||||||
container.resourceClasses.clear();
|
container.resourceClasses.clear();
|
||||||
container.resourceClassBytes.clear();
|
container.resourceClassBytes.clear();
|
||||||
|
@ -47,19 +52,22 @@ public class FileContainerImporter
|
||||||
//fallback to apache commons ZipFile
|
//fallback to apache commons ZipFile
|
||||||
importApacheZipFile(false);
|
importApacheZipFile(false);
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
//sorts the file type from classes or resources
|
//sorts the file type from classes or resources
|
||||||
public void addUnknownFile(String name, InputStream stream, boolean classesOnly) throws IOException
|
public ResourceContainerImporter addUnknownFile(String name, InputStream stream, boolean classesOnly) throws IOException
|
||||||
{
|
{
|
||||||
//TODO remove this .class check and just look for cafebabe
|
//TODO remove this .class check and just look for cafebabe
|
||||||
if (name.endsWith(".class"))
|
if (name.endsWith(".class"))
|
||||||
addClassResource(name, stream);
|
addClassResource(name, stream);
|
||||||
else if(!classesOnly)
|
else if(!classesOnly)
|
||||||
addResource(name, stream);
|
addResource(name, stream);
|
||||||
|
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addClassResource(String name, InputStream stream) throws IOException
|
public ResourceContainerImporter addClassResource(String name, InputStream stream) throws IOException
|
||||||
{
|
{
|
||||||
byte[] bytes = MiscUtils.getBytes(stream);
|
byte[] bytes = MiscUtils.getBytes(stream);
|
||||||
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
||||||
|
@ -87,15 +95,18 @@ public class FileContainerImporter
|
||||||
} else {
|
} else {
|
||||||
System.err.println(container.file + ">" + name + ": Header does not start with CAFEBABE, ignoring.");
|
System.err.println(container.file + ">" + name + ": Header does not start with CAFEBABE, ignoring.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addResource(String name, InputStream stream) throws IOException
|
public ResourceContainerImporter addResource(String name, InputStream stream) throws IOException
|
||||||
{
|
{
|
||||||
byte[] bytes = MiscUtils.getBytes(stream);
|
byte[] bytes = MiscUtils.getBytes(stream);
|
||||||
container.resourceFiles.put(name, bytes);
|
container.resourceFiles.put(name, bytes);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void importZipInputStream(boolean classesOnly) throws IOException
|
public ResourceContainerImporter importZipInputStream(boolean classesOnly) throws IOException
|
||||||
{
|
{
|
||||||
ZipInputStream jis = new ZipInputStream(new FileInputStream(container.file));
|
ZipInputStream jis = new ZipInputStream(new FileInputStream(container.file));
|
||||||
ZipEntry entry;
|
ZipEntry entry;
|
||||||
|
@ -111,11 +122,12 @@ public class FileContainerImporter
|
||||||
jis.closeEntry();
|
jis.closeEntry();
|
||||||
}
|
}
|
||||||
jis.close();
|
jis.close();
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO if this ever fails: import Sun's jarsigner code from JDK 7, re-sign the jar to rebuild the CRC,
|
//TODO if this ever fails: import Sun's jarsigner code from JDK 7, re-sign the jar to rebuild the CRC,
|
||||||
// should also rebuild the archive byte offsets
|
// should also rebuild the archive byte offsets
|
||||||
public void importApacheZipFile(boolean classesOnly) throws IOException
|
public ResourceContainerImporter importApacheZipFile(boolean classesOnly) throws IOException
|
||||||
{
|
{
|
||||||
try (ZipFile zipFile = new ZipFile(container.file))
|
try (ZipFile zipFile = new ZipFile(container.file))
|
||||||
{
|
{
|
||||||
|
@ -134,5 +146,7 @@ public class FileContainerImporter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue