From 37467e4a7b5e05e4da413a1e06e597fa806b72e4 Mon Sep 17 00:00:00 2001 From: jeff Date: Fri, 15 Aug 2014 01:43:48 -0400 Subject: trying to get inner/anonymous classes working... I have a working heuristic in place to detect anonymous classes, but I can't seem to get Procyon to decompile them correctly. I'm writing the InnerClasses attribute and translating all the inner class names, but there must be something else I'm missing... --- src/cuchaz/enigma/analysis/JarClassIterator.java | 134 +++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 src/cuchaz/enigma/analysis/JarClassIterator.java (limited to 'src/cuchaz/enigma/analysis/JarClassIterator.java') diff --git a/src/cuchaz/enigma/analysis/JarClassIterator.java b/src/cuchaz/enigma/analysis/JarClassIterator.java new file mode 100644 index 0000000..cf6df80 --- /dev/null +++ b/src/cuchaz/enigma/analysis/JarClassIterator.java @@ -0,0 +1,134 @@ +/******************************************************************************* + * 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.analysis; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +import javassist.ByteArrayClassPath; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.NotFoundException; +import javassist.bytecode.Descriptor; + +import com.beust.jcommander.internal.Lists; + +import cuchaz.enigma.Constants; + +public class JarClassIterator implements Iterator +{ + private JarFile m_jar; + private Iterator m_iter; + + public JarClassIterator( JarFile jar ) + { + this( jar, getClassEntries( jar ) ); + } + + public JarClassIterator( JarFile jar, List entries ) + { + m_jar = jar; + m_iter = entries.iterator(); + } + + @Override + public boolean hasNext( ) + { + return m_iter.hasNext(); + } + + @Override + public CtClass next( ) + { + JarEntry entry = m_iter.next(); + try + { + // read the class into a buffer + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + byte[] buf = new byte[Constants.KiB]; + int totalNumBytesRead = 0; + InputStream in = m_jar.getInputStream( entry ); + while( in.available() > 0 ) + { + int numBytesRead = in.read( buf ); + if( numBytesRead < 0 ) + { + break; + } + bos.write( buf, 0, numBytesRead ); + + // sanity checking + totalNumBytesRead += numBytesRead; + if( totalNumBytesRead > Constants.MiB ) + { + throw new Error( "Class file " + entry.getName() + " larger than 1 MiB! Something is wrong!" ); + } + } + + // determine the class name (ie chop off the ".class") + String className = Descriptor.toJavaName( entry.getName().substring( 0, entry.getName().length() - ".class".length() ) ); + + // get a javassist handle for the class + ClassPool classPool = new ClassPool(); + classPool.insertClassPath( new ByteArrayClassPath( className, bos.toByteArray() ) ); + return classPool.get( className ); + } + catch( IOException ex ) + { + throw new Error( "Unable to read class: " + entry.getName() ); + } + catch( NotFoundException ex ) + { + throw new Error( "Unable to load class: " + entry.getName() ); + } + } + + @Override + public void remove( ) + { + throw new UnsupportedOperationException(); + } + + public static List getClassEntries( JarFile jar ) + { + List classes = Lists.newArrayList(); + Enumeration entries = jar.entries(); + while( entries.hasMoreElements() ) + { + JarEntry entry = entries.nextElement(); + + // is this a class file? + if( !entry.isDirectory() && entry.getName().endsWith( ".class" ) ) + { + classes.add( entry ); + } + } + return classes; + } + + public static Iterable classes( final JarFile jar ) + { + return new Iterable( ) + { + @Override + public Iterator iterator( ) + { + return new JarClassIterator( jar ); + } + }; + } +} -- cgit v1.2.3