Skip to content

Commit d1285fb

Browse files
committed
Merge branch 'pr/381'
2 parents 52e211b + ee9b483 commit d1285fb

File tree

9 files changed

+103
-8
lines changed

9 files changed

+103
-8
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
<!-- 3rd party repo, Forge -->
2929
<repository>
3030
<id>forge</id>
31-
<url>http://files.minecraftforge.net/maven</url>
31+
<url>https://files.minecraftforge.net/maven</url>
3232
</repository>
3333
<!-- 3rd party repo, analyzer -->
3434
<repository>

src/main/java/me/coley/recaf/command/impl/Remap.java

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,23 @@
22

33
import me.coley.recaf.command.ControllerCommand;
44
import me.coley.recaf.command.completion.FileCompletions;
5-
import me.coley.recaf.mapping.*;
5+
import me.coley.recaf.mapping.MappingImpl;
6+
import me.coley.recaf.mapping.Mappings;
7+
import me.coley.recaf.workspace.JavaResource;
68
import org.objectweb.asm.ClassReader;
79
import picocli.CommandLine;
810

11+
import java.io.ByteArrayInputStream;
12+
import java.io.ByteArrayOutputStream;
913
import java.nio.file.Files;
1014
import java.nio.file.Path;
1115
import java.util.Map;
1216
import java.util.concurrent.Callable;
17+
import java.util.jar.Attributes;
18+
import java.util.jar.Manifest;
1319

14-
import static me.coley.recaf.util.Log.*;
20+
import static me.coley.recaf.util.Log.info;
21+
import static me.coley.recaf.util.Log.debug;
1522

1623
/**
1724
* Command for applying mappings.
@@ -48,8 +55,30 @@ public Void call() throws Exception {
4855
mappings.setClearDebugInfo(noDebug);
4956
mappings.setCheckFieldHierarchy(lookup);
5057
mappings.setCheckMethodHierarchy(lookup);
51-
Map<String, byte[]> mapped = mappings.accept(getWorkspace().getPrimary());
52-
// TODO: If the primary has a "META-INF/MANIFEST.MF" update the main class if renamed
58+
59+
JavaResource primary = getWorkspace().getPrimary();
60+
Map<String, byte[]> mapped = mappings.accept(primary);
61+
62+
byte[] manifestBytes = primary.getFiles().get("META-INF/MANIFEST.MF");
63+
if (manifestBytes != null) {
64+
debug("Found manifest file");
65+
Manifest manifest = new Manifest(new ByteArrayInputStream(manifestBytes));
66+
Attributes attr = manifest.getMainAttributes();
67+
if (!attr.isEmpty()) {
68+
String mainClass = attr.getValue("Main-Class").replaceAll("\\.", "/");
69+
if (mapped.containsKey(mainClass)) {
70+
debug("Found Main-Class attribute");
71+
attr.putValue("Main-Class", new ClassReader(mapped.get(mainClass))
72+
.getClassName().replaceAll("/", "\\."));
73+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
74+
manifest.write(outputStream);
75+
primary.getFiles().put("META-INF/MANIFEST.MF", outputStream.toByteArray());
76+
outputStream.close();
77+
debug("Remapped manifest");
78+
}
79+
}
80+
}
81+
5382
// Log
5483
StringBuilder sb = new StringBuilder("Classes updated: " + mapped.size());
5584
mapped.forEach((old, value) -> {

src/main/java/me/coley/recaf/config/ConfDisplay.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ public class ConfDisplay extends Config {
8383
@Conf("display.maxtreedepth")
8484
public int maxTreeDepth = 30;
8585

86+
/**
87+
* Displays access flags tooltip for class/field/method icons
88+
*/
89+
@Conf("display.accessflags")
90+
public boolean accessFlagsTooltip = true;
91+
8692
ConfDisplay() {
8793
super("display");
8894
}

src/main/java/me/coley/recaf/util/UiUtil.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77
import javafx.beans.property.SimpleDoubleProperty;
88
import javafx.scene.Group;
99
import javafx.scene.Node;
10+
import javafx.scene.control.Tooltip;
1011
import javafx.scene.effect.BlurType;
1112
import javafx.scene.effect.InnerShadow;
1213
import javafx.scene.image.PixelFormat;
1314
import javafx.scene.image.PixelWriter;
1415
import javafx.scene.image.WritableImage;
1516
import javafx.scene.paint.Color;
1617
import javafx.util.Duration;
18+
import me.coley.recaf.Recaf;
1719
import me.coley.recaf.ui.controls.IconView;
1820
import me.coley.recaf.workspace.*;
1921

@@ -23,6 +25,8 @@
2325
import java.io.ByteArrayInputStream;
2426
import java.lang.reflect.Method;
2527
import java.util.Arrays;
28+
import java.util.Set;
29+
import java.util.stream.Collectors;
2630

2731
import static me.coley.recaf.util.ClasspathUtil.resource;
2832

@@ -116,6 +120,7 @@ else if(AccessFlag.isInterface(access))
116120
g.getChildren().add(new IconView("icons/modifier/abstract.png"));
117121
if(AccessFlag.isBridge(access) || AccessFlag.isSynthetic(access))
118122
g.getChildren().add(new IconView("icons/modifier/synthetic.png"));
123+
createAccessToolTips(g, AccessFlag.Type.CLASS, access);
119124
return g;
120125
}
121126

@@ -145,6 +150,7 @@ else if(AccessFlag.isPrivate(access))
145150
g.getChildren().add(new IconView("icons/modifier/final.png"));
146151
if(AccessFlag.isBridge(access) || AccessFlag.isSynthetic(access))
147152
g.getChildren().add(new IconView("icons/modifier/synthetic.png"));
153+
createAccessToolTips(g, AccessFlag.Type.FIELD, access);
148154
return g;
149155
}
150156

@@ -178,9 +184,24 @@ else if(AccessFlag.isAbstract(access))
178184
g.getChildren().add(new IconView("icons/modifier/final.png"));
179185
if(AccessFlag.isBridge(access) || AccessFlag.isSynthetic(access))
180186
g.getChildren().add(new IconView("icons/modifier/synthetic.png"));
187+
createAccessToolTips(g, AccessFlag.Type.METHOD, access);
181188
return g;
182189
}
183190

191+
private static void createAccessToolTips(Node node, AccessFlag.Type type, int access) {
192+
Set<String> accessFlags = AccessFlag.getApplicableFlags(type, access).stream()
193+
.map(AccessFlag::getName).collect(Collectors.toSet());
194+
Tooltip tooltip = new Tooltip(String.join(", ", accessFlags));
195+
node.setOnMouseEntered(event -> {
196+
if (!tooltip.getText().isEmpty() && Recaf.getController().config().display().accessFlagsTooltip) {
197+
tooltip.show(node, event.getScreenX(), event.getScreenY() + 15);
198+
}
199+
});
200+
node.setOnMouseExited(event -> tooltip.hide());
201+
// This has a weird delay
202+
// Tooltip.install(node, tooltip);
203+
}
204+
184205
/**
185206
* Convert raw bytes to an image.
186207
*

src/main/resources/style/ui-dark.css

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,8 @@
7676
-fx-background-color: rgb(61, 61, 62);
7777
}
7878
.context-menu-header {
79-
/* TODO: Find a way to disable hover coloring on the menu header */
80-
-fx-opacity: 1.0;
81-
-fx-background-color: rgb(24, 50, 95);
79+
-fx-opacity: 1.0 !important;
80+
-fx-background-color: rgb(24, 50, 95) !important;
8281
}
8382
.context-menu-header .label {
8483
-fx-opacity: 1.0;

src/main/resources/translations/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,8 @@
481481
"display.maxlength.tree.desc": "The max length of names in the file tree. Useful for obfuscated assemblies with crazy names.",
482482
"display.maxtreedepth.name": "Max tree directory depth",
483483
"display.maxtreedepth.desc": "The max number of directories to show in the file tree before truncation.",
484+
"display.accessflags.name" : "Access Flags tooltip",
485+
"display.accessflags.desc" : "Displays a tooltip when hovering over access icons",
484486
"display.treesourcename.name": "Show SourceFile names",
485487
"display.treesourcename.desc": "Display classes SourceFile next to their declared names in the file-tree.",
486488
"display.exitwarning.name": "Give save prompt on exit",

src/test/java/me/coley/recaf/HeadlessTest.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
package me.coley.recaf;
22

3+
import com.strobel.core.Mapping;
34
import me.coley.recaf.control.headless.HeadlessController;
5+
import me.coley.recaf.mapping.MappingImpl;
6+
import me.coley.recaf.mapping.Mappings;
7+
import me.coley.recaf.workspace.JavaResource;
48
import org.junit.jupiter.api.Test;
9+
import org.objectweb.asm.ClassReader;
510

11+
import java.io.ByteArrayInputStream;
612
import java.lang.reflect.Method;
13+
import java.util.Map;
14+
import java.util.jar.Attributes;
15+
import java.util.jar.Manifest;
716

17+
import static me.coley.recaf.util.Log.info;
818
import static org.junit.jupiter.api.Assertions.*;
919

1020
/**
@@ -22,6 +32,31 @@ public void test() throws Exception {
2232
assertEquals("calc.jar", controller.getWorkspace().getPrimary().getShortName().toString());
2333
}
2434

35+
@Test
36+
public void remapManifestTest() throws Exception {
37+
HeadlessController controller = new HeadlessController(null, null);
38+
controller.setup();
39+
invokeRun(controller, "loadworkspace " + getClasspathFile("Manifest.jar").normalize().toAbsolutePath());
40+
assertEquals("Manifest.jar", controller.getWorkspace().getPrimary().getShortName().toString());
41+
42+
// Check Manifest
43+
JavaResource primary = controller.getWorkspace().getPrimary();
44+
byte[] manifestBytes = primary.getFiles().get("META-INF/MANIFEST.MF");
45+
assertNotEquals(manifestBytes, null);
46+
Manifest manifest = new Manifest(new ByteArrayInputStream(manifestBytes));
47+
Attributes attr = manifest.getMainAttributes();
48+
assertEquals(attr.size(), 2);
49+
String mainClass = attr.getValue("Main-Class").replaceAll("\\.", "/");
50+
assertEquals(mainClass, "Code/Code/Code");
51+
52+
invokeRun(controller, "remap PROGUARD " + getClasspathFile("manifest-map.txt").normalize().toAbsolutePath());
53+
manifestBytes = primary.getFiles().get("META-INF/MANIFEST.MF");
54+
manifest = new Manifest(new ByteArrayInputStream(manifestBytes));
55+
attr = manifest.getMainAttributes();
56+
mainClass = attr.getValue("Main-Class").replaceAll("\\.", "/");
57+
assertEquals(mainClass, "some/pkg/Main");
58+
}
59+
2560
private static void invokeRun(HeadlessController controller, String cmd) throws Exception {
2661
Method m = controller.getClass().getDeclaredMethod("handle", String.class);
2762
m.setAccessible(true);

src/test/resources/Manifest.jar

941 Bytes
Binary file not shown.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
some.pkg.Main -> Code.Code.Code:
2+
void <init>() -> <init>
3+
void main(java.lang.String[]) -> Code

0 commit comments

Comments
 (0)