package codechicken.obfuscator;
import codechicken.lib.asm.ObfMapping;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.*;
import java.util.LinkedList;
import java.util.List;
import static org.objectweb.asm.tree.AbstractInsnNode.LDC_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.METHOD_INSN;
public class ConstantObfuscator implements Opcodes {
public ObfRemapper obf;
public List<ObfMapping> descCalls = new LinkedList<ObfMapping>();
public List<ObfMapping> classCalls = new LinkedList<ObfMapping>();
public ConstantObfuscator(ObfRemapper obf, String[] a_classCalls, String[] a_descCalls) {
this.obf = obf;
for (String callDesc : a_classCalls) {
classCalls.add(ObfMapping.fromDesc(callDesc));
}
for (String callDesc : a_descCalls) {
descCalls.add(ObfMapping.fromDesc(callDesc));
}
}
public void transform(ClassNode cnode) {
for (MethodNode method : cnode.methods) {
for (AbstractInsnNode insn = method.instructions.getFirst(); insn != null; insn = insn.getNext()) {
obfuscateInsnSeq(insn);
}
}
}
private void obfuscateInsnSeq(AbstractInsnNode insn) {
if (matchesClass(insn)) {
LdcInsnNode node1 = (LdcInsnNode) insn;
node1.cst = obf.map((String) node1.cst);
}
if (matchesDesc(insn)) {
LdcInsnNode node1 = (LdcInsnNode) insn;
LdcInsnNode node2 = (LdcInsnNode) node1.getNext();
LdcInsnNode node3 = (LdcInsnNode) node2.getNext();
ObfMapping mapping = new ObfMapping((String) node1.cst, (String) node2.cst, (String) node3.cst).map(obf);
node1.cst = mapping.s_owner;
node2.cst = mapping.s_name;
node3.cst = mapping.s_desc;
}
}
private boolean matchesClass(AbstractInsnNode insn) {
if (insn.getType() != LDC_INSN) {
return false;
}
insn = insn.getNext();
if (insn == null || insn.getType() != METHOD_INSN) {
return false;
}
for (ObfMapping m : classCalls) {
if (m.matches((MethodInsnNode) insn)) {
return true;
}
}
return false;
}
private boolean matchesDesc(AbstractInsnNode insn) {
if (insn.getType() != LDC_INSN) {
return false;
}
insn = insn.getNext();
if (insn == null || insn.getType() != LDC_INSN) {
return false;
}
insn = insn.getNext();
if (insn == null || insn.getType() != LDC_INSN) {
return false;
}
insn = insn.getNext();
if (insn == null || insn.getType() != METHOD_INSN) {
return false;
}
for (ObfMapping m : descCalls) {
if (m.matches((MethodInsnNode) insn)) {
return true;
}
}
return false;
}
}