From f829582ae418504ff6685eeb14fad5a67916c6f9 Mon Sep 17 00:00:00 2001 From: Thog Date: Fri, 24 Mar 2017 01:28:34 +0100 Subject: Implement experimental Tiny mappings loader ~ This will need some tests and more security checks --- .../cuchaz/enigma/mapping/MappingsTinyReader.java | 99 ++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/main/java/cuchaz/enigma/mapping/MappingsTinyReader.java (limited to 'src/main/java/cuchaz/enigma/mapping/MappingsTinyReader.java') diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsTinyReader.java b/src/main/java/cuchaz/enigma/mapping/MappingsTinyReader.java new file mode 100644 index 0000000..b2ba191 --- /dev/null +++ b/src/main/java/cuchaz/enigma/mapping/MappingsTinyReader.java @@ -0,0 +1,99 @@ +package cuchaz.enigma.mapping; + +import com.google.common.base.Charsets; +import com.google.common.collect.Maps; +import cuchaz.enigma.throwables.MappingConflict; +import cuchaz.enigma.throwables.MappingParseException; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class MappingsTinyReader { + public ClassMapping readClass(String[] parts) { + // Extract the inner naming of the deob form if it have one + String deobName = parts[2].contains("$") ? parts[2].substring(parts[2].lastIndexOf('$') + 1) : parts[2]; + return new ClassMapping(parts[1], deobName).setDeobInner(parts[2]); + } + + public FieldMapping readField(String[] parts) { + return new FieldMapping(parts[3], new Type(parts[2]), parts[4], Mappings.EntryModifier.UNCHANGED); + } + + public MethodMapping readMethod(String[] parts) { + return new MethodMapping(parts[3], new Signature(parts[2]), parts[4]); + } + + public Mappings read(File file) throws IOException, MappingParseException { + Mappings mappings = new Mappings(Mappings.FormatType.TINY_FILE); + System.out.println(file); + List lines = Files.readAllLines(file.toPath(), Charsets.UTF_8); + Map classMappingMap = Maps.newHashMap(); + String header = lines.remove(0); + for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) { + String line = lines.get(lineNumber); + String[] parts = line.split("\\s"); + try { + String token = parts[0]; + ClassMapping classMapping; + switch (token) { + case "CLASS": + if (classMappingMap.containsKey(parts[1])) { + classMapping = classMappingMap.get(parts[1]); + String deobName = parts[2].contains("$") ? + parts[2].substring(parts[2].lastIndexOf('$') + 1) : + parts[2]; + classMappingMap.put(parts[2], classMapping.setDeobInner(parts[2])); + classMapping.setDeobfName(deobName); + classMapping.resetDirty(); + } else + classMapping = readClass(parts); + classMappingMap.put(parts[1], classMapping); + break; + case "FIELD": + classMapping = classMappingMap.computeIfAbsent(parts[1], k -> new ClassMapping(parts[1])); + //throw new MappingParseException(file, lineNumber, "Cannot find class '" + parts[1] + "' declaration!"); + classMapping.addFieldMapping(readField(parts)); + break; + case "METHOD": + classMapping = classMappingMap.computeIfAbsent(parts[1], k -> new ClassMapping(parts[1])); + //throw new MappingParseException(file, lineNumber, "Cannot find class '" + parts[1] + "' declaration!"); + classMapping.addMethodMapping(readMethod(parts)); + break; + default: + throw new MappingParseException(file, lineNumber, "Unknown token '" + token + "' !"); + } + } catch (ArrayIndexOutOfBoundsException | IllegalArgumentException ex) { + throw new MappingParseException(file, lineNumber, "Malformed line:\n" + line); + } + } + + List toRegister = new ArrayList<>(classMappingMap.values()); + for (ClassMapping classMapping : toRegister) { + ClassEntry obEntry = classMapping.getObfEntry(); + ClassEntry deobEntry = classMapping.getDeObfEntry(); + try { + if (obEntry.isInnerClass()) { + ClassMapping parent = classMappingMap.get(obEntry.getOuterClassName()); + if (parent == null) { + parent = new ClassMapping(obEntry.getOuterClassName()); + classMappingMap.put(obEntry.getOuterClassName(), parent); + mappings.addClassMapping(parent); + } + parent.addInnerClassMapping(classMapping); + } else if (deobEntry != null && deobEntry.isInnerClass()) + classMappingMap.get(deobEntry.getOuterClassName()).addInnerClassMapping(classMapping); + else + mappings.addClassMapping(classMapping); + } catch (MappingConflict e) { + throw new MappingParseException(file, -1, e.getMessage()); + } + } + lines.clear(); + classMappingMap.clear(); + return mappings; + } +} -- cgit v1.2.3