Logo Search packages:      
Sourcecode: javacc version File versions  Download package

Obfuscator.java

/*
 * Copyright © 2002 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * California 95054, U.S.A. All rights reserved.  Sun Microsystems, Inc. has
 * intellectual property rights relating to technology embodied in the product
 * that is described in this document. In particular, and without limitation,
 * these intellectual property rights may include one or more of the U.S.
 * patents listed at http://www.sun.com/patents and one or more additional
 * patents or pending patent applications in the U.S. and in other countries.
 * U.S. Government Rights - Commercial software. Government users are subject
 * to the Sun Microsystems, Inc. standard license agreement and applicable
 * provisions of the FAR and its supplements.  Use is subject to license terms.
 * Sun,  Sun Microsystems,  the Sun logo and  Java are trademarks or registered
 * trademarks of Sun Microsystems, Inc. in the U.S. and other countries.  This
 * product is covered and controlled by U.S. Export Control laws and may be
 * subject to the export or import laws in other countries.  Nuclear, missile,
 * chemical biological weapons or nuclear maritime end uses or end users,
 * whether direct or indirect, are strictly prohibited.  Export or reexport
 * to countries subject to U.S. embargo or to entities identified on U.S.
 * export exclusion lists, including, but not limited to, the denied persons
 * and specially designated nationals lists is strictly prohibited.
 */


import java.io.*;
import java.util.*;

public class Obfuscator extends Globals {

  // These data structures implement a stack that is used to recursively
  // walk the input directory structure looking for Java files.

  static String[][] dirStack = new String[100][];
  static int[] dirStackIndex = new int[100];
  static int dirStackSize;
  static File[] dirFile = new File[100];

  static {
    dirFile[0] = inpDir;
    dirStackSize = 1;
    dirStack[dirStackSize] = dirFile[dirStackSize-1].list();
    dirStackIndex[dirStackSize] = 0;
  }

  // Returns true if this is a Java file.
  static boolean javaFile(String name) {
    if (name.length() < 6) {
      return false;
    }
    if (name.substring(name.length() - 5).equals(".java")) {
      return true;
    }
    return false;
  }

  // The iterator.  This uses the above datastructures to walk the input
  // directory tree.  Everytime it finds a Java file or when it cannot find
  // any more Java file, it returns to the caller.
  static void nextJavaFile() {
    while (true) {
      if (dirStackIndex[dirStackSize] == dirStack[dirStackSize].length) {
        dirStackSize--;
        if (dirStackSize == 0) {
          return;
        } else {
          dirStackIndex[dirStackSize]++;
        }
      } else {
        dirFile[dirStackSize] = new File(dirFile[dirStackSize-1],
                                         dirStack[dirStackSize][dirStackIndex[dirStackSize]]);
        if (dirStack[dirStackSize][dirStackIndex[dirStackSize]].equals("SCCS")) {
          dirStackIndex[dirStackSize]++;
        } else if (dirFile[dirStackSize].isDirectory()) {
          dirStackSize++;
          dirStack[dirStackSize] = dirFile[dirStackSize-1].list();
          dirStackIndex[dirStackSize] = 0;
        } else if (javaFile(dirStack[dirStackSize][dirStackIndex[dirStackSize]])) {
          dirStackIndex[dirStackSize]++;
          return;
        } else {
          dirStackIndex[dirStackSize]++;
        }
      }
    }
  }

  // The main Obfuscator routine.  It calls the iterator for each Java file to
  // work on.  It then creates the output file, then parses the input Java file
  // to determine whether or not it has a main program and also to collect the
  // tokens that make up this file.  It then calls printOutputFile that takes
  // first token and walks the next field chain printing tokens as it goes along.
  // Finally a main program is created if necessary.
  static public void start() {
    boolean parserInitialized = false;
    JavaParser parser = null;
    Token first;
    while (true) {
      nextJavaFile();
      if (dirStackSize == 0) {
        break;
      }
      createOutputFile();
      System.out.println("Obfuscating " + dirFile[dirStackSize].getPath());
      System.out.println("       into " + outFile.getPath());
      try {
      if (parserInitialized) {
        parser.ReInit(new FileInputStream(dirFile[dirStackSize]));
      } else {
        parser = new JavaParser(new FileInputStream(dirFile[dirStackSize]));
        parserInitialized = true;
      }
        first = parser.CompilationUnit(dirStack[dirStackSize][dirStackIndex[dirStackSize]-1]);
      } catch (ParseException e1) {
        System.out.println("Parse error in file " + dirFile[dirStackSize].getPath());
        throw new Error();
      } catch (IOException e2) {
        System.out.println("Could not open file " + dirFile[dirStackSize].getPath());
        throw new Error();
      }
      printOutputFile(first);
      if (mainExists) {
        createMainClass();
      }
    }
  }

  static File outFile;
  static PrintWriter ostr;

  static void createOutputFile() {
    // sets outFile and ostr
    outFile = outDir;
    for (int i = 1; i < dirStackSize; i++) {
      outFile = new File(outFile, map(dirStack[i][dirStackIndex[i]]));
      if (outFile.exists()) {
        if (!outFile.isDirectory()) {
          System.out.println("Unexpected error!");
          throw new Error();
        }
      } else {
        if (!outFile.mkdir()) {
          System.out.println("Could not create directory " + outFile.getPath());
          throw new Error();
        }
      }
    }
    String origFileName = dirStack[dirStackSize][dirStackIndex[dirStackSize]-1];
    String newFileName = map(origFileName.substring(0, origFileName.length() - 5)) + ".java";
    outFile = new File(outFile, newFileName);
    try {
      ostr = new PrintWriter(new FileWriter(outFile));
    } catch (IOException e) {
      System.out.println("Could not create file " + outFile.getPath());
      throw new Error();
    }
  }

  static void printOutputFile(Token first) {
    Token t = first;
    for (int i = 1; i < t.beginColumn; i++) {
      ostr.print(" ");
    }
    while (true) {
      if (t.kind == JavaParserConstants.IDENTIFIER) {
        t.image = map(t.image);
      }
      ostr.print(addUnicodeEscapes(t.image));
      if (t.next == null) {
        ostr.println("");
        break;
      }
      if (t.endLine != t.next.beginLine) {
        for (int i = t.endLine; i < t.next.beginLine; i++) {
          ostr.println("");
        }
        for (int i = 1; i < t.next.beginColumn; i++) {
          ostr.print(" ");
        }
      } else {
        for (int i = t.endColumn+1; i < t.next.beginColumn; i++) {
          ostr.print(" ");
        }
      }
      t = t.next;
    }
    ostr.close();
  }

  static String addUnicodeEscapes(String str) {
    String retval = "";
    char ch;
    for (int i = 0; i < str.length(); i++) {
      ch = str.charAt(i);
      if (ch < 0x20 || ch > 0x7e) {
      String s = "0000" + Integer.toString(ch, 16);
      retval += "\\u" + s.substring(s.length() - 4, s.length());
      } else {
        retval += ch;
      }
    }
    return retval;
  }

  // This creates a main program if there was one in the original file.  This
  // main program has the same name and resides in the same package as the original
  // file and it simply calls the obfuscated main program.  This allows scripts
  // to continue to work.
  static void createMainClass() {
    PrintWriter mstr;
    boolean mustCreate = false;
    File mFile = outDir;
    for (int i = 1; i < dirStackSize; i++) {
      mFile = new File(mFile, dirStack[i][dirStackIndex[i]]);
      mustCreate = mustCreate || !map(dirStack[i][dirStackIndex[i]]).equals(dirStack[i][dirStackIndex[i]]);
      if (mFile.exists()) {
        if (!mFile.isDirectory()) {
          System.out.println("Error: Created file " + mFile.getPath() + ", but need to create a main program with the same path prefix.  Please remove identifiers from the path prefix from your <useidsfile> and run again.");
          throw new Error();
        }
      }
    }
    String origFileName = dirStack[dirStackSize][dirStackIndex[dirStackSize]-1];
    String newFileName = map(origFileName.substring(0, origFileName.length() - 5)) + ".java";
    if (!mustCreate && origFileName.equals(newFileName)) {
      return; // this main program has not been obfuscated.
    }
    if (!mFile.exists() && !mFile.mkdirs()) {
      System.out.println("Could not create " + mFile.getPath());
      throw new Error();
    }
    mFile = new File(mFile, origFileName);
    try {
      mstr = new PrintWriter(new FileWriter(mFile));
    } catch (IOException e) {
      System.out.println("Could not create " + mFile.getPath());
      throw new Error();
    }
    System.out.print("Generating main program ");
    String pname = "";
    if (dirStackSize > 1) {
      for (int i = 1; i < dirStackSize; i++) {
        pname += "." + dirStack[i][dirStackIndex[i]];
      }
      mstr.println("package " + pname.substring(1) + ";");
      System.out.print(pname.substring(1) + ".");
      mstr.println("");
    }
    System.out.println(origFileName.substring(0, origFileName.length() - 5));
    mstr.println("public class " + origFileName.substring(0, origFileName.length() - 5) + " {");
    mstr.println("");
    mstr.println("  public static void main(String[] args) {");
    pname = "";
    for (int i = 1; i < dirStackSize; i++) {
      pname += map(dirStack[i][dirStackIndex[i]]) + ".";
    }
    mstr.println("    " + pname + map(origFileName.substring(0, origFileName.length() - 5)) + ".main(args);");
    mstr.println("  }");
    mstr.println("");
    mstr.println("}");
    mstr.close();
  }

}

Generated by  Doxygen 1.6.0   Back to index