Skip to content

Commit

Permalink
feat: auto common dependency downloader
Browse files Browse the repository at this point in the history
  • Loading branch information
terminalsin committed Oct 15, 2024
1 parent 648f125 commit 498957e
Show file tree
Hide file tree
Showing 10 changed files with 357 additions and 82 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ jobs:
uses: actions/[email protected]
with:
name: Skidfuscator.jar
path: staging/client-2.0.0-SNAPSHOT.jar
path: staging/client-standalone-all.jar
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package dev.skidfuscator.obfuscator;

import dev.skidfuscator.obfuscator.command.HelpCommand;
import dev.skidfuscator.obfuscator.command.MappingsCommand;
import dev.skidfuscator.obfuscator.command.ObfuscateCommand;
import dev.skidfuscator.obfuscator.util.LogoUtil;
import lombok.SneakyThrows;
import org.jline.reader.EndOfFileException;
import org.jline.reader.LineReader;
Expand Down Expand Up @@ -70,8 +72,10 @@ public static void main(String[] args) {
}

} else {
LogoUtil.printLogo();
new CommandLine(new HelpCommand())
.addSubcommand("obfuscate", new ObfuscateCommand())
.addSubcommand("mappings", new MappingsCommand())
.execute(args);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package dev.skidfuscator.obfuscator.command;

import dev.skidfuscator.jghost.GhostHelper;
import dev.skidfuscator.jghost.tree.GhostLibrary;
import dev.skidfuscator.obfuscator.Skidfuscator;
import dev.skidfuscator.obfuscator.util.misc.SkidTimedLogger;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import picocli.CommandLine;

import java.io.File;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicReference;

@CommandLine.Command(
aliases = "mappings",
mixinStandardHelpOptions = true,
version = "1.0.0",
description = "Creates a collated mappings file given a specific directory"
)
public class MappingsCommand implements Callable<Integer> {

@CommandLine.Parameters(
index = "0",
description = "The directory which will be used to create the mappings file"
)
private File input;

@CommandLine.Option(
names = {"-o", "--output"},
description = "Path to the output mappings file location"
)
private File output = new File("compressed-mappings.json");

@Override
public Integer call() throws Exception {
if (input == null) {
System.out.println("Invalid input file");
return 1;
}

if (!input.getPath().endsWith(".jar") && !input.isDirectory()) {
System.err.println("Invalid input file. Must be a jar file or a directory");
return 1;
}

if (output == null) {
System.err.println("Invalid output file");
return 1;
}

final Logger log = LogManager.getLogger(Skidfuscator.class);
final SkidTimedLogger logger = new SkidTimedLogger(true, log);

AtomicReference<GhostLibrary> ghostLibrary = new AtomicReference<>(null);
iterateFolder(input, logger, ghostLibrary);

GhostHelper.saveLibraryFile(logger, ghostLibrary.get(), output);
logger.style("Successfully created mappings file");

return 0;
}

private void iterateFolder(File file, SkidTimedLogger logger, AtomicReference<GhostLibrary> ghostLibrary) {
if (file.isDirectory()) {
for (File files : file.listFiles()) {
iterateFolder(files, logger, ghostLibrary);
}
} else {
if (file.getAbsolutePath().endsWith(".jar") || file.getAbsolutePath().endsWith(".jmod")) {
final GhostLibrary ghost = GhostHelper.createFromLibraryFile(logger, file);
logger.style("Creating mappings for " + file.getAbsolutePath() + "...\n");
if (ghostLibrary.get() == null) {
ghostLibrary.set(ghost);
} else {
ghostLibrary.get().merge(ghost);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import dev.skidfuscator.obfuscator.Skidfuscator;
import dev.skidfuscator.obfuscator.SkidfuscatorSession;
import dev.skidfuscator.obfuscator.util.ConsoleColors;
import dev.skidfuscator.obfuscator.util.LogoUtil;
import dev.skidfuscator.obfuscator.util.MiscUtil;
import picocli.CommandLine;

Expand Down Expand Up @@ -89,66 +90,6 @@ public class ObfuscateCommand implements Callable<Integer> {

@Override
public Integer call() {
/* Total number of processors or cores available to the JVM */
final String processors =
String.format("%19.19s", "Processors:")
+ " "
+ String.format(
"%-19.19s",
Runtime.getRuntime().availableProcessors() + " cores"
);

final long freeMemory = Math.round(Runtime.getRuntime().freeMemory() / 1E6);
final String memory =
String.format("%19.19s", "Current Memory:")
+ " "
+ String.format("%-19.19s", freeMemory + "mb");

final long maxMemory = Math.round(Runtime.getRuntime().maxMemory() / 1E6);
final String memoryString = (maxMemory == Long.MAX_VALUE
? ConsoleColors.GREEN + "no limit"
: maxMemory + "mb"
);
String topMemory =
String.format("%19.19s", "Max Memory:")
+ " "
+ String.format("%-19.19s",
memoryString + (maxMemory > 1500 ? "" : " ⚠️")
);

topMemory = MiscUtil.replaceColor(
topMemory,
memoryString,
maxMemory > 1500 ? ConsoleColors.GREEN_BRIGHT : ConsoleColors.RED_BRIGHT
);
// slight fix for thing
topMemory = topMemory.replace("⚠️", "⚠️ ");

final String[] logo = new String[] {
"",
" /$$$$$$ /$$ /$$ /$$ /$$$$$$ /$$",
" /$$__ $$| $$ |__/ | $$ /$$__ $$ | $$",
"| $$ \\__/| $$ /$$ /$$ /$$$$$$$| $$ \\__//$$ /$$ /$$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$",
"| $$$$$$ | $$ /$$/| $$ /$$__ $$| $$$$ | $$ | $$ /$$_____/ /$$_____/ |____ $$|_ $$_/ /$$__ $$ /$$__ $$",
" \\____ $$| $$$$$$/ | $$| $$ | $$| $$_/ | $$ | $$| $$$$$$ | $$ /$$$$$$$ | $$ | $$ \\ $$| $$ \\__/",
" /$$ \\ $$| $$_ $$ | $$| $$ | $$| $$ | $$ | $$ \\____ $$| $$ /$$__ $$ | $$ /$$| $$ | $$| $$",
"| $$$$$$/| $$ \\ $$| $$| $$$$$$$| $$ | $$$$$$/ /$$$$$$$/| $$$$$$$| $$$$$$$ | $$$$/| $$$$$$/| $$",
" \\______/ |__/ \\__/|__/ \\_______/|__/ \\______/ |_______/ \\_______/ \\_______/ \\___/ \\______/ |__/",
"",
" ┌───────────────────────────────────────────┐",
" │ " + processors + " │",
" │ " + memory + " │",
" │ " + topMemory + " │",
" └───────────────────────────────────────────┘",
"",
" Author: Ghast Version: 2.0.8 Today: "
+ DateFormat.getDateTimeInstance().format(new Date(Instant.now().toEpochMilli())),
""
};

for (String s : logo) {
System.out.println(s);
}

if (input == null) {
return -1;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package dev.skidfuscator.obfuscator.util;

import lombok.experimental.UtilityClass;

import java.text.DateFormat;
import java.time.Instant;
import java.util.Date;

@UtilityClass
public class LogoUtil {
public static void printLogo() {
/* Total number of processors or cores available to the JVM */
final String processors =
String.format("%19.19s", "Processors:")
+ " "
+ String.format(
"%-19.19s",
Runtime.getRuntime().availableProcessors() + " cores"
);

final long freeMemory = Math.round(Runtime.getRuntime().freeMemory() / 1E6);
final String memory =
String.format("%19.19s", "Current Memory:")
+ " "
+ String.format("%-19.19s", freeMemory + "mb");

final long maxMemory = Math.round(Runtime.getRuntime().maxMemory() / 1E6);
final String memoryString = (maxMemory == Long.MAX_VALUE
? ConsoleColors.GREEN + "no limit"
: maxMemory + "mb"
);
String topMemory =
String.format("%19.19s", "Max Memory:")
+ " "
+ String.format("%-19.19s",
memoryString + (maxMemory > 1500 ? "" : " ⚠️")
);

topMemory = MiscUtil.replaceColor(
topMemory,
memoryString,
maxMemory > 1500 ? ConsoleColors.GREEN_BRIGHT : ConsoleColors.RED_BRIGHT
);
// slight fix for thing
topMemory = topMemory.replace("⚠️", "⚠️ ");

final String[] logo = new String[] {
"",
" /$$$$$$ /$$ /$$ /$$ /$$$$$$ /$$",
" /$$__ $$| $$ |__/ | $$ /$$__ $$ | $$",
"| $$ \\__/| $$ /$$ /$$ /$$$$$$$| $$ \\__//$$ /$$ /$$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$",
"| $$$$$$ | $$ /$$/| $$ /$$__ $$| $$$$ | $$ | $$ /$$_____/ /$$_____/ |____ $$|_ $$_/ /$$__ $$ /$$__ $$",
" \\____ $$| $$$$$$/ | $$| $$ | $$| $$_/ | $$ | $$| $$$$$$ | $$ /$$$$$$$ | $$ | $$ \\ $$| $$ \\__/",
" /$$ \\ $$| $$_ $$ | $$| $$ | $$| $$ | $$ | $$ \\____ $$| $$ /$$__ $$ | $$ /$$| $$ | $$| $$",
"| $$$$$$/| $$ \\ $$| $$| $$$$$$$| $$ | $$$$$$/ /$$$$$$$/| $$$$$$$| $$$$$$$ | $$$$/| $$$$$$/| $$",
" \\______/ |__/ \\__/|__/ \\_______/|__/ \\______/ |_______/ \\_______/ \\_______/ \\___/ \\______/ |__/",
"",
" ┌───────────────────────────────────────────┐",
" │ " + processors + " │",
" │ " + memory + " │",
" │ " + topMemory + " │",
" └───────────────────────────────────────────┘",
"",
" Author: Ghast Version: 2.0.8 Today: "
+ DateFormat.getDateTimeInstance().format(new Date(Instant.now().toEpochMilli())),
""
};

for (String s : logo) {
System.out.println(s);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
import dev.skidfuscator.config.DefaultSkidConfig;
import dev.skidfuscator.obfuscator.creator.SkidApplicationClassSource;
import dev.skidfuscator.obfuscator.creator.SkidCache;
import dev.skidfuscator.obfuscator.dependency.CommonDependency;
import dev.skidfuscator.obfuscator.dependency.DependencyDownloader;
import dev.skidfuscator.obfuscator.dependency.matcher.DependencyMatcher;
import dev.skidfuscator.obfuscator.directory.SkiddedDirectory;
import dev.skidfuscator.obfuscator.event.EventBus;
import dev.skidfuscator.obfuscator.event.impl.transform.ClassTransformEvent;
Expand Down Expand Up @@ -113,6 +116,7 @@ public class Skidfuscator {
private PredicateAnalysis predicateAnalysis;

private final SkidRemapper classRemapper = new SkidRemapper(new HashMap<>());
private final DependencyDownloader dependencyDownloader = new DependencyDownloader();

private final Counter counter = new Counter();

Expand Down Expand Up @@ -685,28 +689,78 @@ private void _verify() {
LOGGER.post("Starting verification");
try {
classSource.getClassTree().verify();
} catch (Exception e) {
LOGGER.error("\n" +
"-----------------------------------------------------\n"
+ "/!\\ Skidfuscator failed to compute some libraries!\n"
+ "It it advised to read https://github.com/terminalsin/skidfuscator-java-obfuscator/wiki/Libraries\n"
+ "\n"
+ "The following class was NOT found. This can be a dependency of a dependency."
+ "Error: " + e.getMessage() + "\n" +
(e.getCause() == null
? "\n"
: " " + e.getCause().getMessage() + "\n"
)
+ "-----------------------------------------------------\n"
, e);

if (!CLOUD)
System.exit(1);
} catch (Exception ex) {
final List<String> missingClasses = classSource.getClassTree().getMissingClasses();

LOGGER.warn("Attempting to auto-resolve missing classes...");
final Set<CommonDependency> commonDependencies = Arrays.stream(CommonDependency.values()).filter(f -> f.getMatcher().test(missingClasses)).collect(Collectors.toSet());

if (commonDependencies.isEmpty()) {
LOGGER.warn("\n" +
"-----------------------------------------------------\n"
+ "/!\\ Skidfuscator failed to compute some libraries!\n"
+ "PLEASE READ THE FOLLOWING WITH MUCH ATTENTION\n"
+ "-----------------------------------------------------\n"
+ "It it advised to read https://skidfuscator.dev/docs/libraries.html\n"
+ "\n"
+ "The following classes were NOT found. This means they are \n"
+ "either not present in the libraries or the libraries are \n"
+ "corrupted. Libraries themselves can have dependencies\n"
+ "\n"
+ "List of missing classes:\n"
+ missingClasses.stream().map(f -> " --> " + f + "\n").collect(Collectors.joining())
+ "-----------------------------------------------------\n"
);

if (!CLOUD)
System.exit(1);
return;
}
commonDependencies.forEach(e -> {
LOGGER.warn("Found common dependency: " + e.name() + "...\n");
dependencyDownloader.download(e);
LOGGER.warn("Downloaded " + e.name() + "...\n");
});


final Path mappingsDir = Paths.get("mappings");
this.importMappingFolder(mappingsDir.toFile());

LOGGER.warn(String.format(
"Resolved %d common dependencies... retrying verification...\n",
commonDependencies.size()
));
_verify();
return;
}
LOGGER.log("Finished verification!");
}

private void importMappingFolder(final File folder) {
for (File lib : folder.listFiles()) {
if (lib.isDirectory()) {
importMappingFolder(lib);
continue;
}

final String absolute = lib.getAbsolutePath();
if (!absolute.endsWith(".json")) {
LOGGER.debug(String.format("Skipping over %s since not end in json", absolute));
continue;
}

final GhostLibrary library = GhostHelper.readFromLibraryFile(LOGGER, lib);
final ApplicationClassSource libraryClassSource = GhostHelper.importFile(LOGGER, session.isFuckIt(), library);
/* Add library source to class source */
classSource.addLibraries(new LibraryClassSource(
libraryClassSource,
5
));

LOGGER.style(String.format("Importing %s... please wait...\n", absolute));
}
}

protected void _cleanup() {
this.hierarchy = null;
this.irFactory.clear();
Expand Down
Loading

0 comments on commit 498957e

Please sign in to comment.