content: package me.n1ar4.clazz.obfuscator.asm;
  
  import me.n1ar4.clazz.obfuscator.Const;
  import me.n1ar4.clazz.obfuscator.core.ObfEnv;
  import me.n1ar4.clazz.obfuscator.utils.AESUtil;
  import me.n1ar4.templates.AESTemplates;
  import org.objectweb.asm.*;
  
  public class StringEncryptClassVisitor extends ClassVisitor {
      private String className;
      private final String aesKey;
      private final String aesDecName;
  
      public StringEncryptClassVisitor(ClassVisitor classVisitor, String aesKey, String aesDecName) {
          super(Const.ASMVersion, classVisitor);
          this.aesKey = aesKey;
          this.aesDecName = aesDecName;
      }
  
      @Override
      public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
          this.className = name;
          super.visit(version, access, name, signature, superName, interfaces);
          FieldVisitor fieldVisitor = this.cv.visitField(
                  // private static final String [AES KEY] = "AES KEY";
                  Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL,
                  ObfEnv.config.getAesKeyField(),
                  "Ljava/lang/String;",
                  null,
                  ObfEnv.config.getAesKey());
          fieldVisitor.visitEnd();
      }
  
      @Override
      public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
          MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
          return new StringEncryptMethodAdapter(mv, className, aesKey, aesDecName);
      }
  
      @Override
      public void visitEnd() {
          AESUtil.addAesDecodeCode(cv, this.aesDecName);
          super.visitEnd();
      }
  
      static class StringEncryptMethodAdapter extends MethodVisitor {
          private final String className;
          private final String aesKey;
          private final String aesDecName;
  
          StringEncryptMethodAdapter(MethodVisitor mv, String name, String aesKey, String aesDecName) {
              super(Const.ASMVersion, mv);
              this.className = name;
              this.aesKey = aesKey;
              this.aesDecName = aesDecName;
          }
  
          @Override
          public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
              super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
          }
  
          @Override
          public void visitFieldInsn(int opcode, String owner, String name, String descriptor) {
              super.visitFieldInsn(opcode, owner, name, descriptor);
          }
  
          @Override
          public void visitTypeInsn(int opcode, String type) {
              super.visitTypeInsn(opcode, type);
          }
  
          @Override
          public void visitAttribute(Attribute attribute) {
              super.visitAttribute(attribute);
          }
  
          @Override
          public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) {
              return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible);
          }
  
          @Override
          public MethodVisitor getDelegate() {
              return super.getDelegate();
          }
  
          @Override
          public void visitEnd() {
              super.visitEnd();
          }
  
          @Override
          public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
              return super.visitAnnotation(descriptor, visible);
          }
  
          @Override
          public AnnotationVisitor visitAnnotationDefault() {
              return super.visitAnnotationDefault();
          }
  
          @Override
          public AnnotationVisitor visitInsnAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) {
              return super.visitInsnAnnotation(typeRef, typePath, descriptor, visible);
          }
  
          @Override
          public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String descriptor, boolean visible) {
              return super.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, descriptor, visible);
          }
  
          @Override
          public AnnotationVisitor visitParameterAnnotation(int parameter, String descriptor, boolean visible) {
              return super.visitParameterAnnotation(parameter, descriptor, visible);
          }
  
          @Override
          public AnnotationVisitor visitTryCatchAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) {
              return super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible);
          }
  
          @Override
          public void visitAnnotableParameterCount(int parameterCount, boolean visible) {
              super.visitAnnotableParameterCount(parameterCount, visible);
          }
  
          @Override
          public void visitCode() {
              super.visitCode();
          }
  
          @Override
          public void visitFrame(int type, int numLocal, Object[] local, int numStack, Object[] stack) {
              super.visitFrame(type, numLocal, local, numStack, stack);
          }
  
          @Override
          public void visitIincInsn(int varIndex, int increment) {
              super.visitIincInsn(varIndex, increment);
          }
  
          @Override
          public void visitInsn(int opcode) {
              super.visitInsn(opcode);
          }
  
          @Override
          public void visitIntInsn(int opcode, int operand) {
              super.visitIntInsn(opcode, operand);
          }
  
          @Override
          public void visitInvokeDynamicInsn(String name, String descriptor, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) {
              super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
          }
  
          @Override
          public void visitJumpInsn(int opcode, Label label) {
              super.visitJumpInsn(opcode, label);
          }
  
          @Override
          public void visitLabel(Label label) {
              super.visitLabel(label);
          }
  
          @Override
          public void visitLdcInsn(Object value) {
              if (value instanceof String) {
                  try {
                      mv.visitLdcInsn(AESTemplates.encrypt((String) value, this.aesKey));
                      mv.visitFieldInsn(Opcodes.GETSTATIC, className,
                              ObfEnv.config.getAesKeyField(), "Ljava/lang/String;");
                      mv.visitMethodInsn(
                              Opcodes.INVOKESTATIC,
                              className,
                              this.aesDecName,
                              "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
                              false);
                  } catch (Exception ignored) {
                      super.visitLdcInsn(value);
                  }
              } else {
                  super.visitLdcInsn(value);
              }
          }
  
          @Override
          public void visitLineNumber(int line, Label start) {
              super.visitLineNumber(line, start);
          }
  
          @Override
          public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) {
              super.visitLocalVariable(name, descriptor, signature, start, end, index);
          }
  
          @Override
          public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
              super.visitLookupSwitchInsn(dflt, keys, labels);
          }
  
          @Override
          public void visitMaxs(int maxStack, int maxLocals) {
              super.visitMaxs(maxStack, maxLocals);
          }
  
          @Override
          public void visitMultiANewArrayInsn(String descriptor, int numDimensions) {
              super.visitMultiANewArrayInsn(descriptor, numDimensions);
          }
  
          @Override
          public void visitParameter(String name, int access) {
              super.visitParameter(name, access);
          }
  
          @Override
          public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
              super.visitTableSwitchInsn(min, max, dflt, labels);
          }
  
          @Override
          public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
              super.visitTryCatchBlock(start, end, handler, type);
          }
  
          @Override
          public void visitVarInsn(int opcode, int varIndex) {
              super.visitVarInsn(opcode, varIndex);
          }
      }
  }
  