summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/bytecode/InnerClassWriter.java
blob: d4abe4ea0d4365e047862b97d36ee83109f65e17 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/*******************************************************************************
 * Copyright (c) 2014 Jeff Martin.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 * 
 * Contributors:
 *     Jeff Martin - initial API and implementation
 ******************************************************************************/
package cuchaz.enigma.bytecode;

import java.util.Collection;

import javassist.CtClass;
import javassist.bytecode.AccessFlag;
import javassist.bytecode.Descriptor;
import javassist.bytecode.InnerClassesAttribute;
import cuchaz.enigma.analysis.JarIndex;
import cuchaz.enigma.mapping.Translator;

public class InnerClassWriter
{
	private Translator m_deobfuscatingTranslator;
	private JarIndex m_jarIndex;
	
	public InnerClassWriter( Translator deobfuscatingTranslator, JarIndex jarIndex )
	{
		m_deobfuscatingTranslator = deobfuscatingTranslator;
		m_jarIndex = jarIndex;
	}

	public void writeInnerClasses( CtClass c )
	{
		// is this an outer class with inner classes?
		String obfOuterClassName = Descriptor.toJvmName( c.getName() );
		Collection<String> obfInnerClassNames = m_jarIndex.getInnerClasses( obfOuterClassName );
		if( obfInnerClassNames != null && !obfInnerClassNames.isEmpty() )
		{
			writeInnerClasses( c, obfInnerClassNames );
		}
	}

	private void writeInnerClasses( CtClass c, Collection<String> obfInnerClassNames )
	{
		String obfOuterClassName = Descriptor.toJvmName( c.getName() );
		InnerClassesAttribute attr = new InnerClassesAttribute( c.getClassFile().getConstPool() );
		c.getClassFile().addAttribute( attr );
		for( String obfInnerClassName : obfInnerClassNames )
		{
			// deobfuscate the class names
			String deobfOuterClassName = m_deobfuscatingTranslator.translateClass( obfOuterClassName );
			if( deobfOuterClassName == null )
			{
				deobfOuterClassName = obfOuterClassName;
			}
			String deobfInnerClassName = m_deobfuscatingTranslator.translateClass( obfInnerClassName );
			if( deobfInnerClassName == null )
			{
				deobfInnerClassName = obfInnerClassName;
			}
			
			// update the attribute
			String deobfOuterInnerClassName = deobfOuterClassName + "$" + deobfInnerClassName;
			attr.append(
					deobfOuterInnerClassName,
				deobfOuterClassName,
				deobfInnerClassName,
				c.getClassFile().getAccessFlags() & ~AccessFlag.SUPER
			);
			
			// make sure the outer class references only the new inner class names
			c.replaceClassName( obfInnerClassName, deobfOuterInnerClassName );
			
			// TEMP
			System.out.println( "\tInner " + obfInnerClassName + " -> " + deobfOuterInnerClassName );
		}
	}
}