home *** CD-ROM | disk | FTP | other *** search
- package opera;
-
- import java.io.BufferedInputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.lang.reflect.Modifier;
-
- class Broken11ClassFixer {
- private byte[] src;
- private int srcPos;
- private byte[] dest;
- private int destPos;
- private int numConstantPoolEntries;
- private boolean detectedBogusLocalVariableNameIndex;
- private static final int CODE_MASK = 1;
- private static final int LOCAL_VARIABLE_TABLE_MASK = 2;
- private byte[] constantPoolUtf8Entries;
- private static final int CONSTANT_CLASS_TAG = 7;
- private static final int CONSTANT_FIELD_REF_TAG = 9;
- private static final int CONSTANT_METHOD_REF_TAG = 10;
- private static final int CONSTANT_INTERFACE_METHOD_REF_TAG = 11;
- private static final int CONSTANT_STRING_TAG = 8;
- private static final int CONSTANT_INTEGER_TAG = 3;
- private static final int CONSTANT_FLOAT_TAG = 4;
- private static final int CONSTANT_LONG_TAG = 5;
- private static final int CONSTANT_DOUBLE_TAG = 6;
- private static final int CONSTANT_NAME_AND_TYPE_TAG = 12;
- private static final int CONSTANT_UTF8_TAG = 1;
-
- public Broken11ClassFixer() {
- }
-
- public void process(byte[] var1, int var2, int var3) throws Exception {
- this.init(var1, var2, var3);
- this.copyHeader();
- this.scanAndCopyConstantPool();
- this.copyAccessFlagsAndClassInformation();
- this.copyInterfaces();
- this.scanAndCopyFields();
- this.scanAndCopyMethods();
- this.copyAttributes();
- }
-
- public byte[] getProcessedData() {
- return this.dest;
- }
-
- public int getProcessedDataOffset() {
- return 0;
- }
-
- public int getProcessedDataLength() {
- return this.destPos;
- }
-
- private void init(byte[] var1, int var2, int var3) {
- this.src = var1;
- this.srcPos = var2;
- this.dest = new byte[var3];
- this.destPos = 0;
- this.detectedBogusLocalVariableNameIndex = false;
- }
-
- private int srcPos() {
- return this.srcPos;
- }
-
- private int destPos() {
- return this.destPos;
- }
-
- private int readByte() {
- return this.src[this.srcPos++] & 255;
- }
-
- private int readShort() {
- int var1 = this.readByte();
- int var2 = this.readByte();
- return var1 << 8 | var2;
- }
-
- private int readInt() {
- int var1 = this.readShort();
- int var2 = this.readShort();
- return var1 << 16 | var2;
- }
-
- private void writeByte(int var1) {
- this.dest[this.destPos++] = (byte)var1;
- }
-
- private void writeShort(int var1) {
- this.writeByte(var1 >> 8);
- this.writeByte(var1);
- }
-
- private void writeInt(int var1) {
- this.writeShort(var1 >> 16);
- this.writeShort(var1);
- }
-
- private void writeByteAt(int var1, int var2) {
- this.dest[var1] = (byte)var2;
- }
-
- private void writeShortAt(int var1, int var2) {
- this.writeByteAt(var1, var2 >> 8);
- this.writeByteAt(var1 + 1, var2);
- }
-
- private void writeIntAt(int var1, int var2) {
- this.writeShortAt(var1, var2 >> 16);
- this.writeShortAt(var1 + 2, var2);
- }
-
- private void copy(int var1) {
- for(int var2 = 0; var2 < var1; ++var2) {
- this.dest[this.destPos + var2] = this.src[this.srcPos + var2];
- }
-
- this.srcPos += var1;
- this.destPos += var1;
- }
-
- private int copyByte() {
- int var1 = this.readByte();
- this.writeByte(var1);
- return var1;
- }
-
- private int copyShort() {
- int var1 = this.readShort();
- this.writeShort(var1);
- return var1;
- }
-
- private int copyInt() {
- int var1 = this.readInt();
- this.writeInt(var1);
- return var1;
- }
-
- private void copyHeader() {
- this.copy(8);
- }
-
- private void scanAndCopyConstantPool() {
- this.numConstantPoolEntries = this.copyShort() - 1;
- this.constantPoolUtf8Entries = new byte[this.numConstantPoolEntries];
-
- for(int var1 = 0; var1 < this.numConstantPoolEntries; ++var1) {
- int var2 = this.copyByte();
- switch (var2) {
- case 1:
- this.scanAndCopyUtf8(var1);
- break;
- case 2:
- default:
- throw new RuntimeException("Invalid constant pool tag " + var2);
- case 3:
- case 4:
- case 9:
- case 10:
- case 11:
- case 12:
- this.copy(4);
- break;
- case 5:
- case 6:
- this.copy(8);
- ++var1;
- break;
- case 7:
- case 8:
- this.copy(2);
- }
- }
-
- }
-
- private void scanAndCopyUtf8(int var1) {
- int var2 = this.copyShort();
- String var3 = "Code";
- String var4 = "LocalVariableTable";
- if (var2 == var3.length()) {
- if (this.copyUtf8LookingFor(var3)) {
- this.markCodeInCP(var1);
- }
- } else if (var2 == var4.length()) {
- if (this.copyUtf8LookingFor(var4)) {
- this.markLocalVariableTableInCP(var1);
- }
- } else {
- this.copy(var2);
- }
-
- }
-
- private boolean copyUtf8LookingFor(String var1) {
- int var2 = var1.length();
-
- for(int var3 = 0; var3 < var2; ++var3) {
- int var4 = this.copyByte();
- if (var4 != (var1.charAt(var3) & 255)) {
- this.copy(var2 - var3 - 1);
- return false;
- }
- }
-
- return true;
- }
-
- private void markCodeInCP(int var1) {
- byte[] var10000 = this.constantPoolUtf8Entries;
- var10000[var1] = (byte)(var10000[var1] | 1);
- }
-
- private void markLocalVariableTableInCP(int var1) {
- byte[] var10000 = this.constantPoolUtf8Entries;
- var10000[var1] = (byte)(var10000[var1] | 2);
- }
-
- private void copyAccessFlagsAndClassInformation() {
- this.copy(6);
- }
-
- private void copyInterfaces() {
- int var1 = this.copyShort();
- this.copy(2 * var1);
- }
-
- private void scanAndCopyFields() {
- int var1 = this.copyShort();
-
- for(int var2 = 0; var2 < var1; ++var2) {
- this.scanAndCopyAccessFlags();
- this.copy(4);
- this.copyAttributes();
- }
-
- }
-
- private void scanAndCopyAccessFlags() {
- int var1 = this.readShort();
- if (Modifier.isPublic(var1)) {
- var1 &= -7;
- } else if (Modifier.isProtected(var1)) {
- var1 &= -4;
- } else {
- var1 &= -6;
- }
-
- this.writeShort(var1);
- }
-
- private boolean cpIdxIsLocalVariableTable(int var1) {
- return (this.constantPoolUtf8Entries[var1 - 1] & 2) != 0;
- }
-
- private boolean cpIdxIsCode(int var1) {
- return (this.constantPoolUtf8Entries[var1 - 1] & 1) != 0;
- }
-
- private boolean isValidConstantPoolIndex(int var1) {
- return var1 > 0 && var1 <= this.numConstantPoolEntries;
- }
-
- private boolean isValidStartAndLength(int var1, int var2, int var3) {
- return var1 >= 0 && var1 + var2 <= var3;
- }
-
- private void copyAttributes() {
- int var1 = this.copyShort();
-
- for(int var2 = 0; var2 < var1; ++var2) {
- this.copyAttribute();
- }
-
- }
-
- private void copyAttribute() {
- this.copy(2);
- this.copyRestOfAttribute();
- }
-
- private void copyRestOfAttribute() {
- this.copy(this.copyInt());
- }
-
- private void scanAndCopyMethods() {
- int var1 = this.copyShort();
-
- for(int var2 = 0; var2 < var1; ++var2) {
- this.scanAndCopyAccessFlags();
- this.copy(4);
- int var3 = this.copyShort();
-
- for(int var4 = 0; var4 < var3; ++var4) {
- int var5 = this.copyShort();
- if (this.cpIdxIsCode(var5)) {
- this.processCodeAttribute();
- } else {
- this.copyRestOfAttribute();
- }
- }
- }
-
- }
-
- private void processCodeAttribute() {
- int var1 = this.destPos();
- int var2 = this.copyInt();
- this.copy(4);
- int var3 = this.copyInt();
- this.copy(var3);
- this.copy(8 * this.copyShort());
- int var4 = this.copyShort();
-
- for(int var5 = 0; var5 < var4; ++var5) {
- int var6 = this.copyShort();
- if (this.cpIdxIsLocalVariableTable(var6)) {
- this.processLocalVariableTableAttribute(var1, var2, var3);
- } else {
- this.copyRestOfAttribute();
- }
- }
-
- }
-
- private void processLocalVariableTableAttribute(int var1, int var2, int var3) {
- int var4 = this.destPos();
- int var5 = this.copyInt();
- int var6 = this.destPos();
- int var7 = this.copyShort();
- int var8 = var7;
-
- for(int var10 = 0; var10 < var7; ++var10) {
- int var11 = this.readShort();
- int var12 = this.readShort();
- int var13 = this.readShort();
- int var14 = this.readShort();
- int var15 = this.readShort();
- if (this.isValidConstantPoolIndex(var13) && this.isValidStartAndLength(var11, var12, var3)) {
- this.writeShort(var11);
- this.writeShort(var12);
- this.writeShort(var13);
- this.writeShort(var14);
- this.writeShort(var15);
- } else {
- var2 -= 10;
- var5 -= 10;
- --var8;
- this.writeIntAt(var1, var2);
- this.writeIntAt(var4, var5);
- this.writeShortAt(var6, var8);
- this.detectedBogusLocalVariableNameIndex = true;
- }
- }
-
- }
-
- private static void usage() {
- System.err.println("Usage: java Broken11ClassFixer [filename]");
- System.exit(1);
- }
-
- public static void main(String[] var0) {
- if (var0.length != 1) {
- usage();
- }
-
- try {
- File var1 = new File(var0[0]);
- int var2 = (int)var1.length();
- byte[] var3 = new byte[var2];
- BufferedInputStream var4 = new BufferedInputStream(new FileInputStream(var1));
-
- for(int var5 = 0; var5 < var3.length; var5 += var4.read(var3, var5, var3.length - var5)) {
- }
-
- Broken11ClassFixer var6 = new Broken11ClassFixer();
- var6.process(var3, 0, var3.length);
- if (var6.detectedBogusLocalVariableNameIndex) {
- System.err.println("Detected bogus local variable name index");
- }
-
- if (var6.srcPos < var3.length) {
- System.err.println("Detected extra bytes at the end of the class file");
- }
- } catch (Exception var7) {
- var7.printStackTrace();
- }
-
- }
- }
-