Recent File Duplication Fix

Fixes #258
This commit is contained in:
Konloch 2021-06-25 22:25:50 -07:00
parent 5603f466b3
commit 2314af5f7f
5 changed files with 135 additions and 120 deletions

View file

@ -72,29 +72,31 @@ import static the.bytecode.club.bytecodeviewer.Constants.*;
* http://the.bytecode.club * http://the.bytecode.club
* *
* TODO BUGS: * TODO BUGS:
* Spam-clicking the refresh button will cause the swing thread to deadlock (Quickly opening resources used to also do this) * + Tab simplified titles aren't working correctly until refreshed
* + Synchronized scrolling is broken
* + Spam-clicking the refresh button will cause the swing thread to deadlock (Quickly opening resources used to also do this)
* This is caused by the ctrlMouseWheelZoom code, a temporary patch is just removing it worst case * This is caused by the ctrlMouseWheelZoom code, a temporary patch is just removing it worst case
* Open as folder doesn't actually work * + Open as folder doesn't actually work
* Fix classfile searcher * + Fix classfile searcher
* Smali Assembly compile - Needs to be fixed * + Smali Assembly compile - Needs to be fixed
* Krakatau Assembly compile - Needs to be fixed * + Krakatau Assembly compile - Needs to be fixed
* *
* TODO IN-PROGRESS: * TODO IN-PROGRESS:
* Finish dragging code * + Finish dragging code
* Finish right-click tab menu detection * + Finish right-click tab menu detection
* Fix hook inject for EZ-Injection * + Fix hook inject for EZ-Injection
* *
* TODO FEATURES: * TODO FEATURES:
* Add stackmapframes to bytecode decompiler * + Add stackmapframes to bytecode decompiler
* Add JEB decompiler optionally, requires them to add jeb library jar * + Add JEB decompiler optionally, requires them to add jeb library jar
* Add https://github.com/ptnkjke/Java-Bytecode-Editor visualize as a plugin * + Add https://github.com/ptnkjke/Java-Bytecode-Editor visualize as a plugin
* Add https://github.com/exbin/bined as the replacement Hed Viewer/Editor * + Add https://github.com/exbin/bined as the replacement Hed Viewer/Editor
* Make the decompilers launch in a separate process * + Make the decompilers launch in a separate process
* Make it use that global last used inside of export as jar * + Make it use that global last used inside of export as jar
* Make zipfile not include the decode shit * + Make zipfile not include the decode shit
* Make ez-injection plugin console show all sys.out calls * + Make ez-injection plugin console show all sys.out calls
* Add decompile as zip for krakatau-bytecode, jd-gui and smali for CLI * + Add decompile as zip for krakatau-bytecode, jd-gui and smali for CLI
* Add decompile all as zip for CLI * + Add decompile all as zip for CLI
* *
* @author Konloch * @author Konloch
* @author The entire BCV community * @author The entire BCV community
@ -235,7 +237,7 @@ public class BytecodeViewer
})); }));
viewer.calledAfterLoad(); viewer.calledAfterLoad();
resetRecentFilesMenu(); Constants.resetRecentFilesMenu();
if (!Configuration.pingback) { if (!Configuration.pingback) {
pingBack.start(); pingBack.start();
@ -518,7 +520,7 @@ public class BytecodeViewer
if (recentFiles) if (recentFiles)
for (File f : files) for (File f : files)
if (f.exists()) if (f.exists())
BytecodeViewer.addRecentFile(f); Constants.addRecentFile(f);
BytecodeViewer.viewer.updateBusyStatus(true); BytecodeViewer.viewer.updateBusyStatus(true);
Configuration.needsReDump = true; Configuration.needsReDump = true;
@ -585,90 +587,6 @@ public class BytecodeViewer
the.bytecode.club.bytecodeviewer.api.BytecodeViewer.getClassNodeLoader().clear(); the.bytecode.club.bytecodeviewer.api.BytecodeViewer.getClassNodeLoader().clear();
} }
private static final List<String> killList = new ArrayList<>();
/**
* Add the recent file
*
* @param f the recent file
*/
public static void addRecentFile(File f) {
for (int i = 0; i < recentFiles.size(); i++) { // remove dead strings
String s = recentFiles.get(i);
if (s.isEmpty() || i > maxRecentFiles)
killList.add(s);
}
if (!killList.isEmpty()) {
for (String s : killList)
recentFiles.remove(s);
killList.clear();
}
// already added on the list
recentFiles.remove(f.getAbsolutePath());
if (recentFiles.size() >= maxRecentFiles)
recentFiles.remove(maxRecentFiles - 1); // zero indexing
recentFiles.add(0, f.getAbsolutePath());
DiskWriter.replaceFile(filesName, MiscUtils.listToString(recentFiles), false);
resetRecentFilesMenu();
}
private static final List<String> killList2 = new ArrayList<>();
/**
* Add to the recent plugin list
*
* @param f the plugin file
*/
public static void addRecentPlugin(File f) {
for (int i = 0; i < recentPlugins.size(); i++) { // remove dead strings
String s = recentPlugins.get(i);
if (s.isEmpty() || i > maxRecentFiles)
killList2.add(s);
}
if (!killList2.isEmpty()) {
for (String s : killList2)
recentPlugins.remove(s);
killList2.clear();
}
// already added on the list
recentPlugins.remove(f.getAbsolutePath());
if (recentPlugins.size() >= maxRecentFiles)
recentPlugins.remove(maxRecentFiles - 1); // zero indexing
recentPlugins.add(0, f.getAbsolutePath());
DiskWriter.replaceFile(pluginsName, MiscUtils.listToString(recentPlugins), false);
resetRecentFilesMenu();
}
/**
* resets the recent files menu
*/
public static void resetRecentFilesMenu() {
viewer.recentFilesSecondaryMenu.removeAll();
for (String s : recentFiles)
if (!s.isEmpty()) {
JMenuItem m = new JMenuItem(s);
m.addActionListener(e -> {
JMenuItem m12 = (JMenuItem) e.getSource();
openFiles(new File[]{new File(m12.getText())}, true);
});
viewer.recentFilesSecondaryMenu.add(m);
}
viewer.recentPluginsSecondaryMenu.removeAll();
for (String s : recentPlugins)
if (!s.isEmpty()) {
JMenuItem m = new JMenuItem(s);
m.addActionListener(e -> {
JMenuItem m1 = (JMenuItem) e.getSource();
startPlugin(new File(m1.getText()));
});
viewer.recentPluginsSecondaryMenu.add(m);
}
}
/** /**
* Clears the temp directory * Clears the temp directory
*/ */

View file

@ -4,7 +4,10 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import me.konloch.kontainer.io.DiskReader; import me.konloch.kontainer.io.DiskReader;
import me.konloch.kontainer.io.DiskWriter;
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
import javax.swing.*;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -42,12 +45,14 @@ public class Constants
public static String enjarifyWorkingDirectory = getBCVDirectory() + fs + "enjarify_" + enjarifyVersion; public static String enjarifyWorkingDirectory = getBCVDirectory() + fs + "enjarify_" + enjarifyVersion;
public static final String[] SUPPORTED_FILE_EXTENSIONS = new String[]{"jar", "zip", "class", "apk", "dex", "war", "jsp"}; public static final String[] SUPPORTED_FILE_EXTENSIONS = new String[]{"jar", "zip", "class", "apk", "dex", "war", "jsp"};
public static List<String> recentPlugins; private static List<String> recentPlugins;
public static List<String> recentFiles; private static List<String> recentFiles;
public static Gson gson; public static Gson gson;
static { static
try { {
try
{
gson = new GsonBuilder().setPrettyPrinting().create(); gson = new GsonBuilder().setPrettyPrinting().create();
if (new File(filesName).exists()) if (new File(filesName).exists())
recentFiles = gson.fromJson(DiskReader.loadAsString(filesName), new TypeToken<ArrayList<String>>() {}.getType()); recentFiles = gson.fromJson(DiskReader.loadAsString(filesName), new TypeToken<ArrayList<String>>() {}.getType());
@ -58,17 +63,89 @@ public class Constants
recentPlugins = gson.fromJson(DiskReader.loadAsString(pluginsName), new TypeToken<ArrayList<String>>() {}.getType()); recentPlugins = gson.fromJson(DiskReader.loadAsString(pluginsName), new TypeToken<ArrayList<String>>() {}.getType());
else else
recentPlugins = DiskReader.loadArrayList(getBCVDirectory() + fs + "recentplugins.bcv", false); recentPlugins = DiskReader.loadArrayList(getBCVDirectory() + fs + "recentplugins.bcv", false);
} catch (Exception e) {
MiscUtils.deduplicateAndTrim(recentFiles, 25);
MiscUtils.deduplicateAndTrim(recentPlugins, 25);
}
catch (Exception e)
{
e.printStackTrace(); e.printStackTrace();
} }
} }
/**
* Add the recent file
*
* @param f the recent file
*/
public static void addRecentFile(File f)
{
recentFiles.remove(f.getAbsolutePath()); // already added on the list
recentFiles.add(0, f.getAbsolutePath());
MiscUtils.deduplicateAndTrim(recentFiles, 25);
DiskWriter.replaceFile(filesName, MiscUtils.listToString(recentFiles), false);
resetRecentFilesMenu();
}
/**
* Add to the recent plugin list
*
* @param f the plugin file
*/
public static void addRecentPlugin(File f)
{
recentPlugins.remove(f.getAbsolutePath()); // already added on the list
recentPlugins.add(0, f.getAbsolutePath());
MiscUtils.deduplicateAndTrim(recentPlugins, 25);
DiskWriter.replaceFile(pluginsName, MiscUtils.listToString(recentPlugins), false);
resetRecentFilesMenu();
}
/**
* resets the recent files menu
*/
protected static void resetRecentFilesMenu()
{
//build recent files
BytecodeViewer.viewer.recentFilesSecondaryMenu.removeAll();
for (String s : recentFiles)
{
if (!s.isEmpty())
{
JMenuItem m = new JMenuItem(s);
m.addActionListener(e ->
{
JMenuItem m12 = (JMenuItem) e.getSource();
BytecodeViewer.openFiles(new File[]{new File(m12.getText())}, true);
});
BytecodeViewer.viewer.recentFilesSecondaryMenu.add(m);
}
}
//build recent plugins
BytecodeViewer.viewer.recentPluginsSecondaryMenu.removeAll();
for (String s : recentPlugins)
{
if (!s.isEmpty())
{
JMenuItem m = new JMenuItem(s);
m.addActionListener(e ->
{
JMenuItem m1 = (JMenuItem) e.getSource();
BytecodeViewer.startPlugin(new File(m1.getText()));
});
BytecodeViewer.viewer.recentPluginsSecondaryMenu.add(m);
}
}
}
/** /**
* Returns the BCV directory * Returns the BCV directory
* *
* @return the static BCV directory * @return the static BCV directory
*/ */
public static String getBCVDirectory() { public static String getBCVDirectory()
{
while (!BCVDir.exists()) while (!BCVDir.exists())
BCVDir.mkdirs(); BCVDir.mkdirs();
@ -83,7 +160,8 @@ public class Constants
* *
* @return true if the os.name property contains 'win' * @return true if the os.name property contains 'win'
*/ */
private static boolean isWindows() { private static boolean isWindows()
{
return System.getProperty("os.name").toLowerCase().contains("win"); return System.getProperty("os.name").toLowerCase().contains("win");
} }
@ -92,7 +170,8 @@ public class Constants
* *
* @param f file you want hidden * @param f file you want hidden
*/ */
private static void hideFile(File f) { private static void hideFile(File f)
{
BytecodeViewer.sm.stopBlocking(); BytecodeViewer.sm.stopBlocking();
try { try {
// Hide file by running attrib system command (on Windows) // Hide file by running attrib system command (on Windows)

View file

@ -51,7 +51,6 @@ import the.bytecode.club.bytecodeviewer.util.SyntaxLanguage;
public class FileViewer extends ResourceViewer public class FileViewer extends ResourceViewer
{ {
public final String name;
public final byte[] contents; public final byte[] contents;
public final String workingName; public final String workingName;
@ -82,8 +81,6 @@ public class FileViewer extends ResourceViewer
final String nameLowerCase = this.name.toLowerCase(); final String nameLowerCase = this.name.toLowerCase();
final String contentsAsString = new String(contents); final String contentsAsString = new String(contents);
refreshTitle();
//image viewer //image viewer
if (!MiscUtils.isPureAscii(contentsAsString)) if (!MiscUtils.isPureAscii(contentsAsString))
{ {
@ -128,6 +125,8 @@ public class FileViewer extends ResourceViewer
textArea.setCaretPosition(0); textArea.setCaretPosition(0);
mainPanel.add(textArea.getScrollPane()); mainPanel.add(textArea.getScrollPane());
refreshTitle();
} }
@Override @Override
@ -139,6 +138,8 @@ public class FileViewer extends ResourceViewer
public void refresh(JButton src) public void refresh(JButton src)
{ {
refreshTitle();
if (!canRefresh) if (!canRefresh)
{ {
src.setEnabled(true); src.setEnabled(true);
@ -153,8 +154,6 @@ public class FileViewer extends ResourceViewer
mainPanel.add(label, BorderLayout.CENTER); mainPanel.add(label, BorderLayout.CENTER);
mainPanel.updateUI(); mainPanel.updateUI();
refreshTitle();
src.setEnabled(true); src.setEnabled(true);
} }

View file

@ -24,13 +24,20 @@ import the.bytecode.club.bytecodeviewer.util.MiscUtils;
* along with this program. If not, see <http://www.gnu.org/licenses/>. * * along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/ ***************************************************************************/
/**
* A ResourceViewer
*
* @author Konloch
*/
public abstract class ResourceViewer extends JPanel public abstract class ResourceViewer extends JPanel
{ {
public ClassNode cn; public ClassNode cn;
public String originalName;
public String name; public String name;
public FileContainer container; public FileContainer container;
public abstract void refreshTitle();
public String getTabName() public String getTabName()
{ {
String tabName = name; String tabName = name;
@ -43,7 +50,5 @@ public abstract class ResourceViewer extends JPanel
return tabName; return tabName;
} }
public abstract void refreshTitle();
private static final long serialVersionUID = -2965538493489119191L; private static final long serialVersionUID = -2965538493489119191L;
} }

View file

@ -210,6 +210,20 @@ public class MiscUtils
return defaultImage; return defaultImage;
} }
public static void deduplicateAndTrim(List<String> list, int maxLength)
{
List<String> temporaryList = new ArrayList<>();
for(String s : list)
if(!s.isEmpty() && !temporaryList.contains(s))
temporaryList.add(s);
list.clear();
list.addAll(temporaryList);
while(temporaryList.size() > maxLength)
list.remove(0);
}
public static boolean isPureAscii(String v) { public static boolean isPureAscii(String v) {
return asciiEncoder.canEncode(v); return asciiEncoder.canEncode(v);
} }