From d659751cbe143d320efdc8bfd37a6c29f5813c12 Mon Sep 17 00:00:00 2001 From: TerriblePanda Date: Tue, 13 Aug 2019 00:00:27 +0800 Subject: [PATCH] Upload --- .idea/$PRODUCT_WORKSPACE_FILE$ | 19 + .idea/.name | 1 + .idea/compiler.xml | 21 + .idea/encodings.xml | 6 + .idea/inspectionProfiles/Project_Default.xml | 8 + ...en__com_fifesoft_rsyntaxtextarea_2_6_1.xml | 13 + .idea/libraries/Maven__com_sun_attach_1_7.xml | 13 + .../Maven__com_weblaf_weblaf_1_2_9.xml | 13 + .../Maven__commons_cli_commons_cli_1_4.xml | 13 + .../Maven__commons_io_commons_io_2_4.xml | 13 + .../Maven__org_apache_ant_ant_1_10_5.xml | 13 + ...en__org_apache_ant_ant_launcher_1_10_5.xml | 13 + .../Maven__org_benf_reader_1_3_9.xml | 13 + ..._org_bitbucket_mstrobel_procyon_0_5_33.xml | 13 + .../Maven__org_jfree_jfreechart_1_5_0.xml | 13 + ...n__org_tinyjee_jgraphx_jgraphx_3_4_1_3.xml | 13 + .idea/misc.xml | 13 + .idea/modules.xml | 8 + .idea/workspace.xml | 116 + JByteMod Reborn.iml | 27 + pom.xml | 209 + src/main/java/android/util/Patterns.java | 409 ++ src/main/java/me/grax/jbytemod/JByteMod.java | 512 +++ .../java/me/grax/jbytemod/JarArchive.java | 57 + .../grax/jbytemod/analysis/block/Block.java | 94 + .../analysis/converter/Converter.java | 273 ++ .../analysis/decompiler/ClassDefinition.java | 33 + .../decompiler/code/TabbedStringBuffer.java | 21 + .../decompiler/code/ast/AstColors.java | 12 + .../decompiler/code/ast/Comparison.java | 19 + .../decompiler/code/ast/EndBlock.java | 5 + .../decompiler/code/ast/Expression.java | 9 + .../decompiler/code/ast/Operation.java | 75 + .../analysis/decompiler/code/ast/VarType.java | 49 + .../ast/expressions/ArrayIndexExpression.java | 34 + .../ast/expressions/ArrayStoreExpression.java | 34 + .../code/ast/expressions/CastExpression.java | 71 + .../ast/expressions/ClassTypeExpression.java | 27 + .../ast/expressions/ComparisonExpression.java | 58 + .../DebugStackAssignExpression.java | 45 + .../ast/expressions/DebugStackExpression.java | 72 + .../DebugStackUnknownExpression.java | 58 + .../expressions/FieldAssignExpression.java | 105 + .../code/ast/expressions/FieldExpression.java | 94 + .../ast/expressions/IncrementExpression.java | 39 + .../ast/expressions/InstanceofExpression.java | 31 + .../expressions/InvokeDynamicExpression.java | 84 + .../expressions/LookupSwitchExpression.java | 29 + .../ast/expressions/MethodExpression.java | 119 + .../ast/expressions/NewArrayExpression.java | 32 + .../expressions/NewPrimArrayExpression.java | 32 + .../ast/expressions/NewTypeExpression.java | 57 + .../code/ast/expressions/NotExpression.java | 36 + .../code/ast/expressions/NullExpression.java | 23 + .../code/ast/expressions/OpExpression.java | 60 + .../ast/expressions/ReturnExpression.java | 40 + .../ast/expressions/SingleOpExpression.java | 27 + .../ast/expressions/StringExpression.java | 38 + .../expressions/TableSwitchExpression.java | 31 + .../code/ast/expressions/TextExpression.java | 28 + .../code/ast/expressions/ThrowExpression.java | 36 + .../code/ast/expressions/ValueExpression.java | 46 + .../ast/expressions/VarAssignExpression.java | 64 + .../ast/expressions/VarLoadExpression.java | 48 + .../ast/expressions/VarSpecialExpression.java | 28 + .../analysis/decompiler/defs/Keywords.java | 8 + .../decompiler/struct/Conversion.java | 769 ++++ .../analysis/decompiler/struct/JVMStack.java | 123 + .../struct/exception/StackException.java | 10 + .../struct/exception/UnknownOPException.java | 11 + .../decompiler/struct/utils/DescUtils.java | 41 + .../decompiler/syntax/nodes/NodeList.java | 11 + .../analysis/errors/EmptyMistake.java | 7 + .../analysis/errors/ErrorAnalyzer.java | 70 + .../jbytemod/analysis/errors/InsnError.java | 9 + .../jbytemod/analysis/errors/InsnWarning.java | 9 + .../jbytemod/analysis/errors/Mistake.java | 18 + .../obfuscation/ObfuscationAnalyzer.java | 167 + .../obfuscation/enums/MethodObfType.java | 17 + .../obfuscation/enums/NameObfType.java | 17 + .../obfuscation/result/MethodResult.java | 15 + .../obfuscation/result/NamesResult.java | 19 + .../jbytemod/analysis/utils/BlockUtils.java | 27 + .../jbytemod/decompiler/CFRDecompiler.java | 173 + .../grax/jbytemod/decompiler/Decompiler.java | 63 + .../grax/jbytemod/decompiler/Decompilers.java | 25 + .../decompiler/FernflowerDecompiler.java | 127 + .../decompiler/KrakatauDecompiler.java | 147 + .../decompiler/ProcyonDecompiler.java | 79 + .../me/grax/jbytemod/logging/Logging.java | 85 + .../java/me/grax/jbytemod/plugin/Plugin.java | 67 + .../grax/jbytemod/plugin/PluginManager.java | 80 + .../me/grax/jbytemod/res/LanguageRes.java | 101 + .../java/me/grax/jbytemod/res/Option.java | 79 + .../java/me/grax/jbytemod/res/Options.java | 167 + .../java/me/grax/jbytemod/ui/ClassTree.java | 397 ++ .../me/grax/jbytemod/ui/DecompilerPanel.java | 27 + .../me/grax/jbytemod/ui/DecompilerTab.java | 98 + .../java/me/grax/jbytemod/ui/InfoPanel.java | 122 + .../java/me/grax/jbytemod/ui/JAboutFrame.java | 57 + .../me/grax/jbytemod/ui/JAccessHelper.java | 202 + .../jbytemod/ui/JAccessSelectorPanel.java | 367 ++ .../grax/jbytemod/ui/JAnnotationEditor.java | 794 ++++ .../java/me/grax/jbytemod/ui/JFrameList.java | 158 + .../java/me/grax/jbytemod/ui/JLDCEditor.java | 86 + .../java/me/grax/jbytemod/ui/JListEditor.java | 123 + .../grax/jbytemod/ui/JMethodObfAnalysis.java | 40 + .../me/grax/jbytemod/ui/JNameObfAnalysis.java | 58 + .../me/grax/jbytemod/ui/JObfAnalysis.java | 42 + .../grax/jbytemod/ui/JProcessSelection.java | 95 + .../java/me/grax/jbytemod/ui/JSearch.java | 106 + .../me/grax/jbytemod/ui/MyCodeEditor.java | 33 + .../java/me/grax/jbytemod/ui/MyEditorTab.java | 152 + .../java/me/grax/jbytemod/ui/MyMenuBar.java | 835 ++++ .../java/me/grax/jbytemod/ui/MySplitPane.java | 28 + .../me/grax/jbytemod/ui/MyTabbedPane.java | 107 + .../java/me/grax/jbytemod/ui/MyToolBar.java | 66 + .../java/me/grax/jbytemod/ui/NoBorderSP.java | 13 + .../java/me/grax/jbytemod/ui/OpcodeTable.java | 27 + .../me/grax/jbytemod/ui/PageEndPanel.java | 67 + .../me/grax/jbytemod/ui/TreeCellRenderer.java | 160 + .../jbytemod/ui/dialogue/ClassDialogue.java | 798 ++++ .../ui/dialogue/InsnEditDialogue.java | 567 +++ .../jbytemod/ui/dialogue/JChooseString.java | 63 + .../ui/dialogue/testing/TestValues.java | 37 + .../grax/jbytemod/ui/graph/BlockVertex.java | 120 + .../me/grax/jbytemod/ui/graph/CFGraph.java | 177 + .../jbytemod/ui/graph/ControlFlowPanel.java | 246 ++ .../ui/graph/PatchedCoordinateAssignment.java | 142 + .../ui/graph/PatchedHierarchicalLayout.java | 39 + .../me/grax/jbytemod/ui/ifs/CNSettings.java | 170 + .../me/grax/jbytemod/ui/ifs/LVPFrame.java | 28 + .../me/grax/jbytemod/ui/ifs/MNSettings.java | 118 + .../grax/jbytemod/ui/ifs/MyInternalFrame.java | 17 + .../me/grax/jbytemod/ui/ifs/TCBFrame.java | 28 + .../me/grax/jbytemod/ui/lists/AdressList.java | 45 + .../me/grax/jbytemod/ui/lists/ErrorList.java | 107 + .../me/grax/jbytemod/ui/lists/LVPList.java | 84 + .../me/grax/jbytemod/ui/lists/MyCodeList.java | 605 +++ .../me/grax/jbytemod/ui/lists/SearchList.java | 87 + .../me/grax/jbytemod/ui/lists/TCBList.java | 92 + .../jbytemod/ui/lists/entries/FieldEntry.java | 53 + .../jbytemod/ui/lists/entries/InstrEntry.java | 50 + .../jbytemod/ui/lists/entries/LVPEntry.java | 43 + .../ui/lists/entries/PrototypeEntry.java | 23 + .../ui/lists/entries/SearchEntry.java | 74 + .../jbytemod/ui/lists/entries/TCBEntry.java | 42 + .../grax/jbytemod/ui/tree/SortedTreeNode.java | 87 + .../me/grax/jbytemod/utils/ErrorDisplay.java | 68 + .../me/grax/jbytemod/utils/FileUtils.java | 18 + .../me/grax/jbytemod/utils/HtmlSelection.java | 58 + .../me/grax/jbytemod/utils/ImageUtils.java | 36 + .../me/grax/jbytemod/utils/InstrUtils.java | 331 ++ .../me/grax/jbytemod/utils/MethodUtils.java | 103 + .../me/grax/jbytemod/utils/TextUtils.java | 39 + .../me/grax/jbytemod/utils/ThemeChanges.java | 61 + .../me/grax/jbytemod/utils/asm/FrameGen.java | 57 + .../me/grax/jbytemod/utils/asm/Hints.java | 268 ++ .../jbytemod/utils/asm/LibClassWriter.java | 87 + .../me/grax/jbytemod/utils/asm/Loader.java | 34 + .../grax/jbytemod/utils/asm/ParentUtils.java | 35 + .../jbytemod/utils/attach/AttachUtils.java | 109 + .../jbytemod/utils/attach/InjectUtils.java | 47 + .../utils/attach/RuntimeJarArchive.java | 76 + .../me/grax/jbytemod/utils/gui/LookUtils.java | 46 + .../grax/jbytemod/utils/gui/SwingUtils.java | 34 + .../jbytemod/utils/list/LazyListModel.java | 32 + .../grax/jbytemod/utils/task/AttachTask.java | 90 + .../me/grax/jbytemod/utils/task/LoadTask.java | 174 + .../jbytemod/utils/task/RetransformTask.java | 83 + .../me/grax/jbytemod/utils/task/SaveTask.java | 101 + .../jbytemod/utils/task/search/LdcTask.java | 96 + .../utils/task/search/ReferenceTask.java | 100 + .../jbytemod/utils/task/search/SFTask.java | 63 + src/main/java/me/lpk/util/ASMUtils.java | 126 + src/main/java/me/lpk/util/AccessHelper.java | 344 ++ src/main/java/me/lpk/util/JarUtils.java | 154 + src/main/java/me/lpk/util/OpUtils.java | 629 +++ src/main/java/me/lpk/util/StringUtils.java | 144 + src/main/java/me/lpk/util/drop/IDropUser.java | 9 + .../java/me/lpk/util/drop/JarDropHandler.java | 47 + .../java/decompiler/code/CodeConstants.java | 373 ++ .../java/decompiler/code/ConstantsUtil.java | 511 +++ .../decompiler/code/ExceptionHandler.java | 60 + .../java/decompiler/code/ExceptionTable.java | 60 + .../code/FullInstructionSequence.java | 37 + .../java/decompiler/code/IfInstruction.java | 36 + .../java/decompiler/code/Instruction.java | 123 + .../decompiler/code/InstructionSequence.java | 228 ++ .../java/decompiler/code/JumpInstruction.java | 41 + .../code/SimpleInstructionSequence.java | 39 + .../decompiler/code/SwitchInstruction.java | 94 + .../java/decompiler/code/cfg/BasicBlock.java | 265 ++ .../decompiler/code/cfg/ControlFlowGraph.java | 871 ++++ .../code/cfg/ExceptionRangeCFG.java | 127 + .../code/interpreter/InstructionImpact.java | 514 +++ .../decompiler/code/interpreter/Util.java | 283 ++ .../code/optinstructions/ALOAD.java | 56 + .../code/optinstructions/ANEWARRAY.java | 33 + .../code/optinstructions/ASTORE.java | 56 + .../code/optinstructions/BIPUSH.java | 46 + .../code/optinstructions/CHECKCAST.java | 33 + .../code/optinstructions/DLOAD.java | 56 + .../code/optinstructions/DSTORE.java | 56 + .../code/optinstructions/FLOAD.java | 56 + .../code/optinstructions/FSTORE.java | 56 + .../code/optinstructions/GETFIELD.java | 33 + .../code/optinstructions/GETSTATIC.java | 33 + .../decompiler/code/optinstructions/GOTO.java | 44 + .../code/optinstructions/GOTO_W.java | 33 + .../decompiler/code/optinstructions/IINC.java | 42 + .../code/optinstructions/ILOAD.java | 52 + .../code/optinstructions/INSTANCEOF.java | 33 + .../code/optinstructions/INVOKEDYNAMIC.java | 35 + .../code/optinstructions/INVOKEINTERFACE.java | 35 + .../code/optinstructions/INVOKESPECIAL.java | 33 + .../code/optinstructions/INVOKESTATIC.java | 33 + .../code/optinstructions/INVOKEVIRTUAL.java | 33 + .../code/optinstructions/ISTORE.java | 52 + .../decompiler/code/optinstructions/JSR.java | 44 + .../code/optinstructions/JSR_W.java | 33 + .../decompiler/code/optinstructions/LDC.java | 33 + .../code/optinstructions/LDC2_W.java | 33 + .../code/optinstructions/LDC_W.java | 33 + .../code/optinstructions/LLOAD.java | 52 + .../code/optinstructions/LOOKUPSWITCH.java | 42 + .../code/optinstructions/LSTORE.java | 52 + .../code/optinstructions/MULTIANEWARRAY.java | 34 + .../decompiler/code/optinstructions/NEW.java | 33 + .../code/optinstructions/NEWARRAY.java | 33 + .../code/optinstructions/PUTFIELD.java | 33 + .../code/optinstructions/PUTSTATIC.java | 33 + .../decompiler/code/optinstructions/RET.java | 40 + .../code/optinstructions/SIPUSH.java | 33 + .../code/optinstructions/TABLESWITCH.java | 42 + .../java/decompiler/main/AssertProcessor.java | 347 ++ .../main/ClassReference14Processor.java | 270 ++ .../java/decompiler/main/ClassWriter.java | 1051 +++++ .../decompiler/main/ClassesProcessor.java | 426 ++ .../decompiler/main/DecompilerContext.java | 159 + .../java/decompiler/main/EnumProcessor.java | 70 + .../java/decompiler/main/Fernflower.java | 92 + .../decompiler/main/InitializerProcessor.java | 265 ++ .../java/decompiler/main/TextBuffer.java | 315 ++ .../collectors/BytecodeMappingTracer.java | 125 + .../main/collectors/BytecodeSourceMapper.java | 149 + .../main/collectors/CounterContainer.java | 37 + .../main/collectors/ImportCollector.java | 147 + .../main/collectors/VarNamesCollector.java | 47 + .../main/decompiler/BaseDecompiler.java | 46 + .../main/decompiler/ConsoleDecompiler.java | 289 ++ .../main/decompiler/PrintStreamLogger.java | 110 + .../main/extern/IBytecodeProvider.java | 22 + .../main/extern/IFernflowerLogger.java | 67 + .../main/extern/IFernflowerPreferences.java | 101 + .../main/extern/IIdentifierRenamer.java | 31 + .../decompiler/main/extern/IResultSaver.java | 36 + .../decompiler/main/rels/ClassWrapper.java | 198 + .../decompiler/main/rels/LambdaProcessor.java | 152 + .../main/rels/MethodProcessorRunnable.java | 234 ++ .../decompiler/main/rels/MethodWrapper.java | 53 + .../main/rels/NestedClassProcessor.java | 931 +++++ .../main/rels/NestedMemberAccess.java | 469 +++ .../modules/code/DeadCodeHelper.java | 424 ++ .../modules/decompiler/ClearStructHelper.java | 39 + .../decompiler/ConcatenationHelper.java | 264 ++ .../modules/decompiler/DecHelper.java | 210 + .../modules/decompiler/DomHelper.java | 692 ++++ .../decompiler/EliminateLoopsHelper.java | 205 + .../modules/decompiler/ExitHelper.java | 250 ++ .../modules/decompiler/ExprProcessor.java | 876 ++++ .../modules/decompiler/ExprentStack.java | 45 + .../modules/decompiler/FinallyProcessor.java | 1051 +++++ .../modules/decompiler/IdeaNotNullHelper.java | 321 ++ .../modules/decompiler/IfHelper.java | 715 ++++ .../decompiler/InlineSingleBlockHelper.java | 212 + .../modules/decompiler/LabelHelper.java | 503 +++ .../modules/decompiler/LoopExtractHelper.java | 198 + .../modules/decompiler/LowBreakHelper.java | 202 + .../modules/decompiler/MergeHelper.java | 414 ++ .../modules/decompiler/PPandMMHelper.java | 149 + .../decompiler/PrimitiveExprsList.java | 49 + .../decompiler/SecondaryFunctionsHelper.java | 412 ++ .../modules/decompiler/SequenceHelper.java | 317 ++ .../decompiler/SimplifyExprentsHelper.java | 903 ++++ .../decompiler/StackVarsProcessor.java | 704 ++++ .../modules/decompiler/StatEdge.java | 98 + .../decompiler/StrongConnectivityHelper.java | 203 + .../decompiler/decompose/DominatorEngine.java | 126 + .../DominatorTreeExceptionFilter.java | 186 + .../FastExtendedPostdominanceHelper.java | 346 ++ .../decompose/GenericDominatorEngine.java | 148 + .../modules/decompiler/decompose/IGraph.java | 26 + .../decompiler/decompose/IGraphNode.java | 23 + .../deobfuscator/ExceptionDeobfuscator.java | 331 ++ .../IrreducibleCFGDeobfuscator.java | 230 ++ .../decompiler/exps/AnnotationExprent.java | 109 + .../modules/decompiler/exps/ArrayExprent.java | 123 + .../decompiler/exps/AssertExprent.java | 53 + .../decompiler/exps/AssignmentExprent.java | 204 + .../modules/decompiler/exps/ConstExprent.java | 382 ++ .../modules/decompiler/exps/ExitExprent.java | 176 + .../modules/decompiler/exps/Exprent.java | 193 + .../modules/decompiler/exps/FieldExprent.java | 220 + .../decompiler/exps/FunctionExprent.java | 572 +++ .../modules/decompiler/exps/IfExprent.java | 134 + .../decompiler/exps/InvocationExprent.java | 537 +++ .../decompiler/exps/MonitorExprent.java | 90 + .../modules/decompiler/exps/NewExprent.java | 475 +++ .../decompiler/exps/SwitchExprent.java | 122 + .../decompiler/exps/TypeAnnotation.java | 67 + .../modules/decompiler/exps/VarExprent.java | 212 + .../decompiler/sforms/DirectGraph.java | 134 + .../modules/decompiler/sforms/DirectNode.java | 66 + .../sforms/FlattenStatementsHelper.java | 564 +++ .../sforms/SSAConstructorSparseEx.java | 508 +++ .../sforms/SSAUConstructorSparseEx.java | 812 ++++ .../decompiler/stats/BasicBlockStatement.java | 96 + .../decompiler/stats/CatchAllStatement.java | 227 ++ .../decompiler/stats/CatchStatement.java | 220 + .../modules/decompiler/stats/DoStatement.java | 229 ++ .../decompiler/stats/DummyExitStatement.java | 41 + .../decompiler/stats/GeneralStatement.java | 70 + .../modules/decompiler/stats/IfStatement.java | 448 ++ .../decompiler/stats/RootStatement.java | 48 + .../decompiler/stats/SequenceStatement.java | 136 + .../modules/decompiler/stats/Statement.java | 920 +++++ .../modules/decompiler/stats/Statements.java | 59 + .../decompiler/stats/SwitchStatement.java | 370 ++ .../stats/SynchronizedStatement.java | 164 + .../decompiler/vars/CheckTypesResult.java | 57 + .../decompiler/vars/VarDefinitionHelper.java | 343 ++ .../modules/decompiler/vars/VarProcessor.java | 130 + .../decompiler/vars/VarTypeProcessor.java | 274 ++ .../decompiler/vars/VarVersionEdge.java | 58 + .../decompiler/vars/VarVersionNode.java | 79 + .../decompiler/vars/VarVersionPair.java | 65 + .../decompiler/vars/VarVersionsGraph.java | 170 + .../decompiler/vars/VarVersionsProcessor.java | 318 ++ .../modules/renamer/ClassWrapperNode.java | 55 + .../modules/renamer/ConverterHelper.java | 95 + .../modules/renamer/IdentifierConverter.java | 393 ++ .../modules/renamer/PoolInterceptor.java | 50 + .../java/decompiler/struct/ContextUnit.java | 167 + .../decompiler/struct/IDecompiledData.java | 23 + .../java/decompiler/struct/StructClass.java | 202 + .../java/decompiler/struct/StructContext.java | 191 + .../java/decompiler/struct/StructField.java | 62 + .../java/decompiler/struct/StructMember.java | 84 + .../java/decompiler/struct/StructMethod.java | 472 +++ .../attr/StructAnnDefaultAttribute.java | 35 + .../attr/StructAnnotationAttribute.java | 184 + .../StructAnnotationParameterAttribute.java | 50 + .../attr/StructBootstrapMethodsAttribute.java | 66 + .../attr/StructConstantValueAttribute.java | 34 + .../attr/StructEnclosingMethodAttribute.java | 55 + .../attr/StructExceptionsAttribute.java | 51 + .../struct/attr/StructGeneralAttribute.java | 108 + .../attr/StructGenericSignatureAttribute.java | 35 + .../attr/StructInnerClassesAttribute.java | 77 + .../attr/StructLineNumberTableAttribute.java | 67 + .../StructLocalVariableTableAttribute.java | 66 + .../attr/StructSourceFileAttribute.java | 35 + .../attr/StructTypeAnnotationAttribute.java | 106 + .../struct/consts/ConstantPool.java | 253 ++ .../struct/consts/LinkConstant.java | 153 + .../struct/consts/PooledConstant.java | 115 + .../struct/consts/PrimitiveConstant.java | 125 + .../struct/consts/VariableTypeEnum.java | 47 + .../java/decompiler/struct/gen/DataPoint.java | 96 + .../struct/gen/FieldDescriptor.java | 65 + .../struct/gen/MethodDescriptor.java | 144 + .../struct/gen/NewClassNameBuilder.java | 20 + .../java/decompiler/struct/gen/VarType.java | 406 ++ .../gen/generics/GenericClassDescriptor.java | 30 + .../gen/generics/GenericFieldDescriptor.java | 21 + .../struct/gen/generics/GenericMain.java | 239 ++ .../gen/generics/GenericMethodDescriptor.java | 32 + .../struct/gen/generics/GenericType.java | 224 + .../decompiler/struct/lazy/LazyLoader.java | 158 + .../decompiler/struct/match/IMatchable.java | 30 + .../decompiler/struct/match/MatchEngine.java | 252 ++ .../decompiler/struct/match/MatchNode.java | 84 + .../decompiler/util/DataInputFullStream.java | 34 + .../decompiler/util/FastFixedSetFactory.java | 362 ++ .../java/decompiler/util/FastSetFactory.java | 483 +++ .../decompiler/util/FastSparseSetFactory.java | 544 +++ .../java/decompiler/util/InterpreterUtil.java | 130 + .../java/decompiler/util/ListStack.java | 93 + .../decompiler/util/SFormsFastMapDirect.java | 407 ++ .../java/decompiler/util/TextUtil.java | 87 + .../decompiler/util/VBStyleCollection.java | 203 + .../org/objectweb/asm/AnnotationVisitor.java | 148 + .../org/objectweb/asm/AnnotationWriter.java | 553 +++ .../java/org/objectweb/asm/Attribute.java | 392 ++ .../java/org/objectweb/asm/ByteVector.java | 361 ++ .../java/org/objectweb/asm/ClassReader.java | 3620 +++++++++++++++++ .../objectweb/asm/ClassTooLargeException.java | 71 + .../java/org/objectweb/asm/ClassVisitor.java | 329 ++ .../java/org/objectweb/asm/ClassWriter.java | 965 +++++ .../org/objectweb/asm/ConstantDynamic.java | 178 + .../java/org/objectweb/asm/Constants.java | 177 + src/main/java/org/objectweb/asm/Context.java | 137 + .../java/org/objectweb/asm/CurrentFrame.java | 56 + src/main/java/org/objectweb/asm/Edge.java | 91 + .../java/org/objectweb/asm/FieldVisitor.java | 133 + .../java/org/objectweb/asm/FieldWriter.java | 284 ++ src/main/java/org/objectweb/asm/Frame.java | 1473 +++++++ src/main/java/org/objectweb/asm/Handle.java | 189 + src/main/java/org/objectweb/asm/Handler.java | 198 + src/main/java/org/objectweb/asm/Label.java | 622 +++ .../asm/MethodTooLargeException.java | 99 + .../java/org/objectweb/asm/MethodVisitor.java | 777 ++++ .../java/org/objectweb/asm/MethodWriter.java | 2393 +++++++++++ .../java/org/objectweb/asm/ModuleVisitor.java | 176 + .../java/org/objectweb/asm/ModuleWriter.java | 253 ++ src/main/java/org/objectweb/asm/Opcodes.java | 546 +++ src/main/java/org/objectweb/asm/Symbol.java | 243 ++ .../java/org/objectweb/asm/SymbolTable.java | 1320 ++++++ src/main/java/org/objectweb/asm/Type.java | 895 ++++ src/main/java/org/objectweb/asm/TypePath.java | 201 + .../java/org/objectweb/asm/TypeReference.java | 436 ++ .../objectweb/asm/commons/AdviceAdapter.java | 647 +++ .../asm/commons/AnalyzerAdapter.java | 908 +++++ .../asm/commons/AnnotationRemapper.java | 103 + .../objectweb/asm/commons/ClassRemapper.java | 236 ++ .../asm/commons/CodeSizeEvaluator.java | 207 + .../objectweb/asm/commons/FieldRemapper.java | 89 + .../asm/commons/GeneratorAdapter.java | 1368 +++++++ .../asm/commons/InstructionAdapter.java | 1300 ++++++ .../asm/commons/JSRInlinerAdapter.java | 563 +++ .../asm/commons/LocalVariablesSorter.java | 351 ++ .../org/objectweb/asm/commons/Method.java | 262 ++ .../objectweb/asm/commons/MethodRemapper.java | 264 ++ .../asm/commons/ModuleHashesAttribute.java | 139 + .../objectweb/asm/commons/ModuleRemapper.java | 122 + .../commons/ModuleResolutionAttribute.java | 113 + .../asm/commons/ModuleTargetAttribute.java | 87 + .../org/objectweb/asm/commons/Remapper.java | 334 ++ .../asm/commons/SerialVersionUIDAdder.java | 492 +++ .../asm/commons/SignatureRemapper.java | 174 + .../objectweb/asm/commons/SimpleRemapper.java | 96 + .../asm/commons/StaticInitMerger.java | 124 + .../asm/commons/TableSwitchGenerator.java | 51 + .../asm/commons/TryCatchBlockSorter.java | 119 + .../org/objectweb/asm/commons/package.html | 48 + src/main/java/org/objectweb/asm/package.html | 74 + .../asm/signature/SignatureReader.java | 252 ++ .../asm/signature/SignatureVisitor.java | 203 + .../asm/signature/SignatureWriter.java | 240 ++ .../org/objectweb/asm/signature/package.html | 36 + .../objectweb/asm/tree/AbstractInsnNode.java | 320 ++ .../objectweb/asm/tree/AnnotationNode.java | 288 ++ .../org/objectweb/asm/tree/ClassNode.java | 441 ++ .../org/objectweb/asm/tree/FieldInsnNode.java | 115 + .../org/objectweb/asm/tree/FieldNode.java | 296 ++ .../org/objectweb/asm/tree/FrameNode.java | 210 + .../org/objectweb/asm/tree/IincInsnNode.java | 87 + .../objectweb/asm/tree/InnerClassNode.java | 99 + .../java/org/objectweb/asm/tree/InsnList.java | 628 +++ .../java/org/objectweb/asm/tree/InsnNode.java | 92 + .../org/objectweb/asm/tree/IntInsnNode.java | 93 + .../asm/tree/InvokeDynamicInsnNode.java | 110 + .../org/objectweb/asm/tree/JumpInsnNode.java | 101 + .../org/objectweb/asm/tree/LabelNode.java | 85 + .../org/objectweb/asm/tree/LdcInsnNode.java | 84 + .../objectweb/asm/tree/LineNumberNode.java | 88 + .../asm/tree/LocalVariableAnnotationNode.java | 155 + .../objectweb/asm/tree/LocalVariableNode.java | 110 + .../asm/tree/LookupSwitchInsnNode.java | 121 + .../objectweb/asm/tree/MethodInsnNode.java | 144 + .../org/objectweb/asm/tree/MethodNode.java | 790 ++++ .../objectweb/asm/tree/ModuleExportNode.java | 83 + .../org/objectweb/asm/tree/ModuleNode.java | 240 ++ .../objectweb/asm/tree/ModuleOpenNode.java | 83 + .../objectweb/asm/tree/ModuleProvideNode.java | 75 + .../objectweb/asm/tree/ModuleRequireNode.java | 86 + .../asm/tree/MultiANewArrayInsnNode.java | 88 + .../org/objectweb/asm/tree/ParameterNode.java | 76 + .../asm/tree/TableSwitchInsnNode.java | 117 + .../objectweb/asm/tree/TryCatchBlockNode.java | 144 + .../asm/tree/TypeAnnotationNode.java | 99 + .../org/objectweb/asm/tree/TypeInsnNode.java | 97 + .../org/objectweb/asm/tree/VarInsnNode.java | 99 + .../objectweb/asm/tree/analysis/Analyzer.java | 530 +++ .../asm/tree/analysis/AnalyzerException.java | 59 + .../asm/tree/analysis/BasicInterpreter.java | 343 ++ .../asm/tree/analysis/BasicValue.java | 107 + .../asm/tree/analysis/BasicVerifier.java | 406 ++ .../objectweb/asm/tree/analysis/Frame.java | 731 ++++ .../asm/tree/analysis/Interpreter.java | 219 + .../asm/tree/analysis/SimpleVerifier.java | 306 ++ .../objectweb/asm/tree/analysis/SmallSet.java | 134 + .../asm/tree/analysis/SourceInterpreter.java | 188 + .../asm/tree/analysis/SourceValue.java | 97 + .../asm/tree/analysis/Subroutine.java | 89 + .../objectweb/asm/tree/analysis/Value.java | 45 + .../objectweb/asm/tree/analysis/package.html | 67 + .../java/org/objectweb/asm/tree/package.html | 192 + .../java/org/objectweb/asm/util/ASMifier.java | 1544 +++++++ .../objectweb/asm/util/ASMifierSupport.java | 45 + .../asm/util/CheckAnnotationAdapter.java | 135 + .../objectweb/asm/util/CheckClassAdapter.java | 1093 +++++ .../objectweb/asm/util/CheckFieldAdapter.java | 116 + .../asm/util/CheckMethodAdapter.java | 1443 +++++++ .../asm/util/CheckModuleAdapter.java | 212 + .../asm/util/CheckSignatureAdapter.java | 359 ++ .../java/org/objectweb/asm/util/Printer.java | 1230 ++++++ .../org/objectweb/asm/util/Textifier.java | 1541 +++++++ .../objectweb/asm/util/TextifierSupport.java | 41 + .../asm/util/TraceAnnotationVisitor.java | 93 + .../objectweb/asm/util/TraceClassVisitor.java | 229 ++ .../objectweb/asm/util/TraceFieldVisitor.java | 93 + .../asm/util/TraceMethodVisitor.java | 312 ++ .../asm/util/TraceModuleVisitor.java | 111 + .../asm/util/TraceSignatureVisitor.java | 344 ++ .../java/org/objectweb/asm/util/package.html | 40 + src/main/resources/locale/de.xml | 91 + src/main/resources/locale/en.xml | 215 + src/main/resources/locale/es.xml | 89 + src/main/resources/locale/pt-br.xml | 102 + src/main/resources/locale/ru.xml | 86 + src/main/resources/locale/zh-cn.xml | 91 + src/main/resources/locale/zh-tr.xml | 91 + src/main/resources/locale/zh.xml | 91 + src/main/resources/resources/LICENSES | 1150 ++++++ .../resources/resources/access/abstract.png | Bin 0 -> 2907 bytes src/main/resources/resources/access/final.png | Bin 0 -> 2863 bytes .../resources/resources/access/native.png | Bin 0 -> 2868 bytes .../resources/resources/access/static.png | Bin 0 -> 2894 bytes .../resources/resources/access/synthetic.png | Bin 0 -> 2973 bytes .../resources/resources/classtype/enum.png | Bin 0 -> 300 bytes .../resources/classtype/interface.png | Bin 0 -> 300 bytes src/main/resources/resources/file.png | Bin 0 -> 414 bytes .../resources/resources/html/optable.html | 1677 ++++++++ src/main/resources/resources/icon_close.png | Bin 0 -> 675 bytes src/main/resources/resources/jar.png | Bin 0 -> 660 bytes src/main/resources/resources/java.png | Bin 0 -> 517 bytes .../resources/resources/method/methdef.png | Bin 0 -> 290 bytes .../resources/resources/method/methpri.png | Bin 0 -> 192 bytes .../resources/resources/method/methpro.png | Bin 0 -> 309 bytes .../resources/resources/method/methpub.png | Bin 0 -> 291 bytes src/main/resources/resources/package.png | Bin 0 -> 345 bytes src/main/resources/resources/search.png | Bin 0 -> 5804 bytes src/main/resources/resources/toolbar/load.png | Bin 0 -> 413 bytes src/main/resources/resources/toolbar/plug.png | Bin 0 -> 423 bytes .../resources/resources/toolbar/refresh.png | Bin 0 -> 680 bytes src/main/resources/resources/toolbar/save.png | Bin 0 -> 454 bytes .../resources/resources/toolbar/search.png | Bin 0 -> 677 bytes .../resources/resources/toolbar/table.png | Bin 0 -> 382 bytes src/main/resources/resources/txt.png | Bin 0 -> 356 bytes src/main/resources/resources/warning.png | Bin 0 -> 662 bytes 552 files changed, 106536 insertions(+) create mode 100644 .idea/$PRODUCT_WORKSPACE_FILE$ create mode 100644 .idea/.name create mode 100644 .idea/compiler.xml create mode 100644 .idea/encodings.xml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/libraries/Maven__com_fifesoft_rsyntaxtextarea_2_6_1.xml create mode 100644 .idea/libraries/Maven__com_sun_attach_1_7.xml create mode 100644 .idea/libraries/Maven__com_weblaf_weblaf_1_2_9.xml create mode 100644 .idea/libraries/Maven__commons_cli_commons_cli_1_4.xml create mode 100644 .idea/libraries/Maven__commons_io_commons_io_2_4.xml create mode 100644 .idea/libraries/Maven__org_apache_ant_ant_1_10_5.xml create mode 100644 .idea/libraries/Maven__org_apache_ant_ant_launcher_1_10_5.xml create mode 100644 .idea/libraries/Maven__org_benf_reader_1_3_9.xml create mode 100644 .idea/libraries/Maven__org_bitbucket_mstrobel_procyon_0_5_33.xml create mode 100644 .idea/libraries/Maven__org_jfree_jfreechart_1_5_0.xml create mode 100644 .idea/libraries/Maven__org_tinyjee_jgraphx_jgraphx_3_4_1_3.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/workspace.xml create mode 100644 JByteMod Reborn.iml create mode 100644 pom.xml create mode 100644 src/main/java/android/util/Patterns.java create mode 100644 src/main/java/me/grax/jbytemod/JByteMod.java create mode 100644 src/main/java/me/grax/jbytemod/JarArchive.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/block/Block.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/converter/Converter.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/ClassDefinition.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/TabbedStringBuffer.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/AstColors.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/Comparison.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/EndBlock.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/Expression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/Operation.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/VarType.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ArrayIndexExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ArrayStoreExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/CastExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ClassTypeExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ComparisonExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/DebugStackAssignExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/DebugStackExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/DebugStackUnknownExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/FieldAssignExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/FieldExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/IncrementExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/InstanceofExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/InvokeDynamicExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/LookupSwitchExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/MethodExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NewArrayExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NewPrimArrayExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NewTypeExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NotExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NullExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/OpExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ReturnExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/SingleOpExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/StringExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/TableSwitchExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/TextExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ThrowExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ValueExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/VarAssignExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/VarLoadExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/VarSpecialExpression.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/defs/Keywords.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/struct/Conversion.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/struct/JVMStack.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/struct/exception/StackException.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/struct/exception/UnknownOPException.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/struct/utils/DescUtils.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/decompiler/syntax/nodes/NodeList.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/errors/EmptyMistake.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/errors/ErrorAnalyzer.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/errors/InsnError.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/errors/InsnWarning.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/errors/Mistake.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/obfuscation/ObfuscationAnalyzer.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/obfuscation/enums/MethodObfType.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/obfuscation/enums/NameObfType.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/obfuscation/result/MethodResult.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/obfuscation/result/NamesResult.java create mode 100644 src/main/java/me/grax/jbytemod/analysis/utils/BlockUtils.java create mode 100644 src/main/java/me/grax/jbytemod/decompiler/CFRDecompiler.java create mode 100644 src/main/java/me/grax/jbytemod/decompiler/Decompiler.java create mode 100644 src/main/java/me/grax/jbytemod/decompiler/Decompilers.java create mode 100644 src/main/java/me/grax/jbytemod/decompiler/FernflowerDecompiler.java create mode 100644 src/main/java/me/grax/jbytemod/decompiler/KrakatauDecompiler.java create mode 100644 src/main/java/me/grax/jbytemod/decompiler/ProcyonDecompiler.java create mode 100644 src/main/java/me/grax/jbytemod/logging/Logging.java create mode 100644 src/main/java/me/grax/jbytemod/plugin/Plugin.java create mode 100644 src/main/java/me/grax/jbytemod/plugin/PluginManager.java create mode 100644 src/main/java/me/grax/jbytemod/res/LanguageRes.java create mode 100644 src/main/java/me/grax/jbytemod/res/Option.java create mode 100644 src/main/java/me/grax/jbytemod/res/Options.java create mode 100644 src/main/java/me/grax/jbytemod/ui/ClassTree.java create mode 100644 src/main/java/me/grax/jbytemod/ui/DecompilerPanel.java create mode 100644 src/main/java/me/grax/jbytemod/ui/DecompilerTab.java create mode 100644 src/main/java/me/grax/jbytemod/ui/InfoPanel.java create mode 100644 src/main/java/me/grax/jbytemod/ui/JAboutFrame.java create mode 100644 src/main/java/me/grax/jbytemod/ui/JAccessHelper.java create mode 100644 src/main/java/me/grax/jbytemod/ui/JAccessSelectorPanel.java create mode 100644 src/main/java/me/grax/jbytemod/ui/JAnnotationEditor.java create mode 100644 src/main/java/me/grax/jbytemod/ui/JFrameList.java create mode 100644 src/main/java/me/grax/jbytemod/ui/JLDCEditor.java create mode 100644 src/main/java/me/grax/jbytemod/ui/JListEditor.java create mode 100644 src/main/java/me/grax/jbytemod/ui/JMethodObfAnalysis.java create mode 100644 src/main/java/me/grax/jbytemod/ui/JNameObfAnalysis.java create mode 100644 src/main/java/me/grax/jbytemod/ui/JObfAnalysis.java create mode 100644 src/main/java/me/grax/jbytemod/ui/JProcessSelection.java create mode 100644 src/main/java/me/grax/jbytemod/ui/JSearch.java create mode 100644 src/main/java/me/grax/jbytemod/ui/MyCodeEditor.java create mode 100644 src/main/java/me/grax/jbytemod/ui/MyEditorTab.java create mode 100644 src/main/java/me/grax/jbytemod/ui/MyMenuBar.java create mode 100644 src/main/java/me/grax/jbytemod/ui/MySplitPane.java create mode 100644 src/main/java/me/grax/jbytemod/ui/MyTabbedPane.java create mode 100644 src/main/java/me/grax/jbytemod/ui/MyToolBar.java create mode 100644 src/main/java/me/grax/jbytemod/ui/NoBorderSP.java create mode 100644 src/main/java/me/grax/jbytemod/ui/OpcodeTable.java create mode 100644 src/main/java/me/grax/jbytemod/ui/PageEndPanel.java create mode 100644 src/main/java/me/grax/jbytemod/ui/TreeCellRenderer.java create mode 100644 src/main/java/me/grax/jbytemod/ui/dialogue/ClassDialogue.java create mode 100644 src/main/java/me/grax/jbytemod/ui/dialogue/InsnEditDialogue.java create mode 100644 src/main/java/me/grax/jbytemod/ui/dialogue/JChooseString.java create mode 100644 src/main/java/me/grax/jbytemod/ui/dialogue/testing/TestValues.java create mode 100644 src/main/java/me/grax/jbytemod/ui/graph/BlockVertex.java create mode 100644 src/main/java/me/grax/jbytemod/ui/graph/CFGraph.java create mode 100644 src/main/java/me/grax/jbytemod/ui/graph/ControlFlowPanel.java create mode 100644 src/main/java/me/grax/jbytemod/ui/graph/PatchedCoordinateAssignment.java create mode 100644 src/main/java/me/grax/jbytemod/ui/graph/PatchedHierarchicalLayout.java create mode 100644 src/main/java/me/grax/jbytemod/ui/ifs/CNSettings.java create mode 100644 src/main/java/me/grax/jbytemod/ui/ifs/LVPFrame.java create mode 100644 src/main/java/me/grax/jbytemod/ui/ifs/MNSettings.java create mode 100644 src/main/java/me/grax/jbytemod/ui/ifs/MyInternalFrame.java create mode 100644 src/main/java/me/grax/jbytemod/ui/ifs/TCBFrame.java create mode 100644 src/main/java/me/grax/jbytemod/ui/lists/AdressList.java create mode 100644 src/main/java/me/grax/jbytemod/ui/lists/ErrorList.java create mode 100644 src/main/java/me/grax/jbytemod/ui/lists/LVPList.java create mode 100644 src/main/java/me/grax/jbytemod/ui/lists/MyCodeList.java create mode 100644 src/main/java/me/grax/jbytemod/ui/lists/SearchList.java create mode 100644 src/main/java/me/grax/jbytemod/ui/lists/TCBList.java create mode 100644 src/main/java/me/grax/jbytemod/ui/lists/entries/FieldEntry.java create mode 100644 src/main/java/me/grax/jbytemod/ui/lists/entries/InstrEntry.java create mode 100644 src/main/java/me/grax/jbytemod/ui/lists/entries/LVPEntry.java create mode 100644 src/main/java/me/grax/jbytemod/ui/lists/entries/PrototypeEntry.java create mode 100644 src/main/java/me/grax/jbytemod/ui/lists/entries/SearchEntry.java create mode 100644 src/main/java/me/grax/jbytemod/ui/lists/entries/TCBEntry.java create mode 100644 src/main/java/me/grax/jbytemod/ui/tree/SortedTreeNode.java create mode 100644 src/main/java/me/grax/jbytemod/utils/ErrorDisplay.java create mode 100644 src/main/java/me/grax/jbytemod/utils/FileUtils.java create mode 100644 src/main/java/me/grax/jbytemod/utils/HtmlSelection.java create mode 100644 src/main/java/me/grax/jbytemod/utils/ImageUtils.java create mode 100644 src/main/java/me/grax/jbytemod/utils/InstrUtils.java create mode 100644 src/main/java/me/grax/jbytemod/utils/MethodUtils.java create mode 100644 src/main/java/me/grax/jbytemod/utils/TextUtils.java create mode 100644 src/main/java/me/grax/jbytemod/utils/ThemeChanges.java create mode 100644 src/main/java/me/grax/jbytemod/utils/asm/FrameGen.java create mode 100644 src/main/java/me/grax/jbytemod/utils/asm/Hints.java create mode 100644 src/main/java/me/grax/jbytemod/utils/asm/LibClassWriter.java create mode 100644 src/main/java/me/grax/jbytemod/utils/asm/Loader.java create mode 100644 src/main/java/me/grax/jbytemod/utils/asm/ParentUtils.java create mode 100644 src/main/java/me/grax/jbytemod/utils/attach/AttachUtils.java create mode 100644 src/main/java/me/grax/jbytemod/utils/attach/InjectUtils.java create mode 100644 src/main/java/me/grax/jbytemod/utils/attach/RuntimeJarArchive.java create mode 100644 src/main/java/me/grax/jbytemod/utils/gui/LookUtils.java create mode 100644 src/main/java/me/grax/jbytemod/utils/gui/SwingUtils.java create mode 100644 src/main/java/me/grax/jbytemod/utils/list/LazyListModel.java create mode 100644 src/main/java/me/grax/jbytemod/utils/task/AttachTask.java create mode 100644 src/main/java/me/grax/jbytemod/utils/task/LoadTask.java create mode 100644 src/main/java/me/grax/jbytemod/utils/task/RetransformTask.java create mode 100644 src/main/java/me/grax/jbytemod/utils/task/SaveTask.java create mode 100644 src/main/java/me/grax/jbytemod/utils/task/search/LdcTask.java create mode 100644 src/main/java/me/grax/jbytemod/utils/task/search/ReferenceTask.java create mode 100644 src/main/java/me/grax/jbytemod/utils/task/search/SFTask.java create mode 100644 src/main/java/me/lpk/util/ASMUtils.java create mode 100644 src/main/java/me/lpk/util/AccessHelper.java create mode 100644 src/main/java/me/lpk/util/JarUtils.java create mode 100644 src/main/java/me/lpk/util/OpUtils.java create mode 100644 src/main/java/me/lpk/util/StringUtils.java create mode 100644 src/main/java/me/lpk/util/drop/IDropUser.java create mode 100644 src/main/java/me/lpk/util/drop/JarDropHandler.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/CodeConstants.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/ConstantsUtil.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/ExceptionHandler.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/ExceptionTable.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/FullInstructionSequence.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/IfInstruction.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/Instruction.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/InstructionSequence.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/JumpInstruction.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/SimpleInstructionSequence.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/SwitchInstruction.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/cfg/BasicBlock.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/cfg/ControlFlowGraph.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/cfg/ExceptionRangeCFG.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/interpreter/InstructionImpact.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/interpreter/Util.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/ALOAD.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/ANEWARRAY.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/ASTORE.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/BIPUSH.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/CHECKCAST.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/DLOAD.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/DSTORE.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/FLOAD.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/FSTORE.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/GETFIELD.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/GETSTATIC.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/GOTO.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/GOTO_W.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/IINC.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/ILOAD.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/INSTANCEOF.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/INVOKEDYNAMIC.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/INVOKEINTERFACE.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/INVOKESPECIAL.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/INVOKESTATIC.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/INVOKEVIRTUAL.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/ISTORE.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/JSR.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/JSR_W.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/LDC.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/LDC2_W.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/LDC_W.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/LLOAD.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/LOOKUPSWITCH.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/LSTORE.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/MULTIANEWARRAY.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/NEW.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/NEWARRAY.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/PUTFIELD.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/PUTSTATIC.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/RET.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/SIPUSH.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/code/optinstructions/TABLESWITCH.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/AssertProcessor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/ClassReference14Processor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/ClassWriter.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/ClassesProcessor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/DecompilerContext.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/EnumProcessor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/Fernflower.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/InitializerProcessor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/TextBuffer.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/collectors/BytecodeMappingTracer.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/collectors/CounterContainer.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/collectors/ImportCollector.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/collectors/VarNamesCollector.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/decompiler/BaseDecompiler.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/decompiler/ConsoleDecompiler.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/decompiler/PrintStreamLogger.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/extern/IBytecodeProvider.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/extern/IFernflowerLogger.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/extern/IIdentifierRenamer.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/extern/IResultSaver.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/rels/LambdaProcessor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/rels/MethodProcessorRunnable.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/rels/MethodWrapper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/code/DeadCodeHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/ClearStructHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/ConcatenationHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/DecHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/DomHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/EliminateLoopsHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/ExitHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/ExprentStack.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/IdeaNotNullHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/IfHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/InlineSingleBlockHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/LabelHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/LoopExtractHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/LowBreakHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/MergeHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/PPandMMHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/PrimitiveExprsList.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/SecondaryFunctionsHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/SequenceHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/SimplifyExprentsHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/StackVarsProcessor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/StatEdge.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/StrongConnectivityHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/decompose/DominatorEngine.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/decompose/DominatorTreeExceptionFilter.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/decompose/FastExtendedPostdominanceHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/decompose/GenericDominatorEngine.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/decompose/IGraph.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/decompose/IGraphNode.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/deobfuscator/ExceptionDeobfuscator.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/deobfuscator/IrreducibleCFGDeobfuscator.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/AnnotationExprent.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/ArrayExprent.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/AssertExprent.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/ExitExprent.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/Exprent.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/IfExprent.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/MonitorExprent.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/SwitchExprent.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/TypeAnnotation.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/sforms/DirectGraph.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/sforms/DirectNode.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/sforms/FlattenStatementsHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/sforms/SSAConstructorSparseEx.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/sforms/SSAUConstructorSparseEx.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/BasicBlockStatement.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/DoStatement.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/DummyExitStatement.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/GeneralStatement.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/Statement.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/Statements.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/vars/CheckTypesResult.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/vars/VarProcessor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/vars/VarTypeProcessor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionEdge.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionNode.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionPair.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionsGraph.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionsProcessor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/renamer/ClassWrapperNode.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/renamer/ConverterHelper.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/renamer/IdentifierConverter.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/modules/renamer/PoolInterceptor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/ContextUnit.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/IDecompiledData.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/StructClass.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/StructContext.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/StructField.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/StructMember.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/StructMethod.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/attr/StructAnnDefaultAttribute.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/attr/StructAnnotationAttribute.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/attr/StructAnnotationParameterAttribute.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/attr/StructBootstrapMethodsAttribute.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/attr/StructConstantValueAttribute.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/attr/StructEnclosingMethodAttribute.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/attr/StructExceptionsAttribute.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/attr/StructGeneralAttribute.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/attr/StructGenericSignatureAttribute.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/attr/StructInnerClassesAttribute.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/attr/StructLineNumberTableAttribute.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/attr/StructLocalVariableTableAttribute.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/attr/StructSourceFileAttribute.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/attr/StructTypeAnnotationAttribute.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/consts/ConstantPool.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/consts/LinkConstant.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/consts/PooledConstant.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/consts/PrimitiveConstant.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/consts/VariableTypeEnum.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/gen/DataPoint.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/gen/FieldDescriptor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/gen/MethodDescriptor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/gen/NewClassNameBuilder.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/gen/VarType.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/gen/generics/GenericClassDescriptor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/gen/generics/GenericFieldDescriptor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/gen/generics/GenericMain.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/gen/generics/GenericMethodDescriptor.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/gen/generics/GenericType.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/lazy/LazyLoader.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/match/IMatchable.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/match/MatchEngine.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/struct/match/MatchNode.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/util/DataInputFullStream.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/util/FastFixedSetFactory.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/util/FastSetFactory.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/util/FastSparseSetFactory.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/util/InterpreterUtil.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/util/ListStack.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/util/SFormsFastMapDirect.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/util/TextUtil.java create mode 100644 src/main/java/org/jetbrains/java/decompiler/util/VBStyleCollection.java create mode 100644 src/main/java/org/objectweb/asm/AnnotationVisitor.java create mode 100644 src/main/java/org/objectweb/asm/AnnotationWriter.java create mode 100644 src/main/java/org/objectweb/asm/Attribute.java create mode 100644 src/main/java/org/objectweb/asm/ByteVector.java create mode 100644 src/main/java/org/objectweb/asm/ClassReader.java create mode 100644 src/main/java/org/objectweb/asm/ClassTooLargeException.java create mode 100644 src/main/java/org/objectweb/asm/ClassVisitor.java create mode 100644 src/main/java/org/objectweb/asm/ClassWriter.java create mode 100644 src/main/java/org/objectweb/asm/ConstantDynamic.java create mode 100644 src/main/java/org/objectweb/asm/Constants.java create mode 100644 src/main/java/org/objectweb/asm/Context.java create mode 100644 src/main/java/org/objectweb/asm/CurrentFrame.java create mode 100644 src/main/java/org/objectweb/asm/Edge.java create mode 100644 src/main/java/org/objectweb/asm/FieldVisitor.java create mode 100644 src/main/java/org/objectweb/asm/FieldWriter.java create mode 100644 src/main/java/org/objectweb/asm/Frame.java create mode 100644 src/main/java/org/objectweb/asm/Handle.java create mode 100644 src/main/java/org/objectweb/asm/Handler.java create mode 100644 src/main/java/org/objectweb/asm/Label.java create mode 100644 src/main/java/org/objectweb/asm/MethodTooLargeException.java create mode 100644 src/main/java/org/objectweb/asm/MethodVisitor.java create mode 100644 src/main/java/org/objectweb/asm/MethodWriter.java create mode 100644 src/main/java/org/objectweb/asm/ModuleVisitor.java create mode 100644 src/main/java/org/objectweb/asm/ModuleWriter.java create mode 100644 src/main/java/org/objectweb/asm/Opcodes.java create mode 100644 src/main/java/org/objectweb/asm/Symbol.java create mode 100644 src/main/java/org/objectweb/asm/SymbolTable.java create mode 100644 src/main/java/org/objectweb/asm/Type.java create mode 100644 src/main/java/org/objectweb/asm/TypePath.java create mode 100644 src/main/java/org/objectweb/asm/TypeReference.java create mode 100644 src/main/java/org/objectweb/asm/commons/AdviceAdapter.java create mode 100644 src/main/java/org/objectweb/asm/commons/AnalyzerAdapter.java create mode 100644 src/main/java/org/objectweb/asm/commons/AnnotationRemapper.java create mode 100644 src/main/java/org/objectweb/asm/commons/ClassRemapper.java create mode 100644 src/main/java/org/objectweb/asm/commons/CodeSizeEvaluator.java create mode 100644 src/main/java/org/objectweb/asm/commons/FieldRemapper.java create mode 100644 src/main/java/org/objectweb/asm/commons/GeneratorAdapter.java create mode 100644 src/main/java/org/objectweb/asm/commons/InstructionAdapter.java create mode 100644 src/main/java/org/objectweb/asm/commons/JSRInlinerAdapter.java create mode 100644 src/main/java/org/objectweb/asm/commons/LocalVariablesSorter.java create mode 100644 src/main/java/org/objectweb/asm/commons/Method.java create mode 100644 src/main/java/org/objectweb/asm/commons/MethodRemapper.java create mode 100644 src/main/java/org/objectweb/asm/commons/ModuleHashesAttribute.java create mode 100644 src/main/java/org/objectweb/asm/commons/ModuleRemapper.java create mode 100644 src/main/java/org/objectweb/asm/commons/ModuleResolutionAttribute.java create mode 100644 src/main/java/org/objectweb/asm/commons/ModuleTargetAttribute.java create mode 100644 src/main/java/org/objectweb/asm/commons/Remapper.java create mode 100644 src/main/java/org/objectweb/asm/commons/SerialVersionUIDAdder.java create mode 100644 src/main/java/org/objectweb/asm/commons/SignatureRemapper.java create mode 100644 src/main/java/org/objectweb/asm/commons/SimpleRemapper.java create mode 100644 src/main/java/org/objectweb/asm/commons/StaticInitMerger.java create mode 100644 src/main/java/org/objectweb/asm/commons/TableSwitchGenerator.java create mode 100644 src/main/java/org/objectweb/asm/commons/TryCatchBlockSorter.java create mode 100644 src/main/java/org/objectweb/asm/commons/package.html create mode 100644 src/main/java/org/objectweb/asm/package.html create mode 100644 src/main/java/org/objectweb/asm/signature/SignatureReader.java create mode 100644 src/main/java/org/objectweb/asm/signature/SignatureVisitor.java create mode 100644 src/main/java/org/objectweb/asm/signature/SignatureWriter.java create mode 100644 src/main/java/org/objectweb/asm/signature/package.html create mode 100644 src/main/java/org/objectweb/asm/tree/AbstractInsnNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/AnnotationNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/ClassNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/FieldInsnNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/FieldNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/FrameNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/IincInsnNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/InnerClassNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/InsnList.java create mode 100644 src/main/java/org/objectweb/asm/tree/InsnNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/IntInsnNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/InvokeDynamicInsnNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/JumpInsnNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/LabelNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/LdcInsnNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/LineNumberNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/LocalVariableAnnotationNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/LocalVariableNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/LookupSwitchInsnNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/MethodInsnNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/MethodNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/ModuleExportNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/ModuleNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/ModuleOpenNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/ModuleProvideNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/ModuleRequireNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/MultiANewArrayInsnNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/ParameterNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/TableSwitchInsnNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/TryCatchBlockNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/TypeAnnotationNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/TypeInsnNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/VarInsnNode.java create mode 100644 src/main/java/org/objectweb/asm/tree/analysis/Analyzer.java create mode 100644 src/main/java/org/objectweb/asm/tree/analysis/AnalyzerException.java create mode 100644 src/main/java/org/objectweb/asm/tree/analysis/BasicInterpreter.java create mode 100644 src/main/java/org/objectweb/asm/tree/analysis/BasicValue.java create mode 100644 src/main/java/org/objectweb/asm/tree/analysis/BasicVerifier.java create mode 100644 src/main/java/org/objectweb/asm/tree/analysis/Frame.java create mode 100644 src/main/java/org/objectweb/asm/tree/analysis/Interpreter.java create mode 100644 src/main/java/org/objectweb/asm/tree/analysis/SimpleVerifier.java create mode 100644 src/main/java/org/objectweb/asm/tree/analysis/SmallSet.java create mode 100644 src/main/java/org/objectweb/asm/tree/analysis/SourceInterpreter.java create mode 100644 src/main/java/org/objectweb/asm/tree/analysis/SourceValue.java create mode 100644 src/main/java/org/objectweb/asm/tree/analysis/Subroutine.java create mode 100644 src/main/java/org/objectweb/asm/tree/analysis/Value.java create mode 100644 src/main/java/org/objectweb/asm/tree/analysis/package.html create mode 100644 src/main/java/org/objectweb/asm/tree/package.html create mode 100644 src/main/java/org/objectweb/asm/util/ASMifier.java create mode 100644 src/main/java/org/objectweb/asm/util/ASMifierSupport.java create mode 100644 src/main/java/org/objectweb/asm/util/CheckAnnotationAdapter.java create mode 100644 src/main/java/org/objectweb/asm/util/CheckClassAdapter.java create mode 100644 src/main/java/org/objectweb/asm/util/CheckFieldAdapter.java create mode 100644 src/main/java/org/objectweb/asm/util/CheckMethodAdapter.java create mode 100644 src/main/java/org/objectweb/asm/util/CheckModuleAdapter.java create mode 100644 src/main/java/org/objectweb/asm/util/CheckSignatureAdapter.java create mode 100644 src/main/java/org/objectweb/asm/util/Printer.java create mode 100644 src/main/java/org/objectweb/asm/util/Textifier.java create mode 100644 src/main/java/org/objectweb/asm/util/TextifierSupport.java create mode 100644 src/main/java/org/objectweb/asm/util/TraceAnnotationVisitor.java create mode 100644 src/main/java/org/objectweb/asm/util/TraceClassVisitor.java create mode 100644 src/main/java/org/objectweb/asm/util/TraceFieldVisitor.java create mode 100644 src/main/java/org/objectweb/asm/util/TraceMethodVisitor.java create mode 100644 src/main/java/org/objectweb/asm/util/TraceModuleVisitor.java create mode 100644 src/main/java/org/objectweb/asm/util/TraceSignatureVisitor.java create mode 100644 src/main/java/org/objectweb/asm/util/package.html create mode 100644 src/main/resources/locale/de.xml create mode 100644 src/main/resources/locale/en.xml create mode 100644 src/main/resources/locale/es.xml create mode 100644 src/main/resources/locale/pt-br.xml create mode 100644 src/main/resources/locale/ru.xml create mode 100644 src/main/resources/locale/zh-cn.xml create mode 100644 src/main/resources/locale/zh-tr.xml create mode 100644 src/main/resources/locale/zh.xml create mode 100644 src/main/resources/resources/LICENSES create mode 100644 src/main/resources/resources/access/abstract.png create mode 100644 src/main/resources/resources/access/final.png create mode 100644 src/main/resources/resources/access/native.png create mode 100644 src/main/resources/resources/access/static.png create mode 100644 src/main/resources/resources/access/synthetic.png create mode 100644 src/main/resources/resources/classtype/enum.png create mode 100644 src/main/resources/resources/classtype/interface.png create mode 100644 src/main/resources/resources/file.png create mode 100644 src/main/resources/resources/html/optable.html create mode 100644 src/main/resources/resources/icon_close.png create mode 100644 src/main/resources/resources/jar.png create mode 100644 src/main/resources/resources/java.png create mode 100644 src/main/resources/resources/method/methdef.png create mode 100644 src/main/resources/resources/method/methpri.png create mode 100644 src/main/resources/resources/method/methpro.png create mode 100644 src/main/resources/resources/method/methpub.png create mode 100644 src/main/resources/resources/package.png create mode 100644 src/main/resources/resources/search.png create mode 100644 src/main/resources/resources/toolbar/load.png create mode 100644 src/main/resources/resources/toolbar/plug.png create mode 100644 src/main/resources/resources/toolbar/refresh.png create mode 100644 src/main/resources/resources/toolbar/save.png create mode 100644 src/main/resources/resources/toolbar/search.png create mode 100644 src/main/resources/resources/toolbar/table.png create mode 100644 src/main/resources/resources/txt.png create mode 100644 src/main/resources/resources/warning.png diff --git a/.idea/$PRODUCT_WORKSPACE_FILE$ b/.idea/$PRODUCT_WORKSPACE_FILE$ new file mode 100644 index 0000000..3733e0d --- /dev/null +++ b/.idea/$PRODUCT_WORKSPACE_FILE$ @@ -0,0 +1,19 @@ + + + + + + + 1.8 + + + + + + + + \ No newline at end of file diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..3a65287 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +JByteMod \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..76a4ef6 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..b26911b --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..2e6b69e --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fifesoft_rsyntaxtextarea_2_6_1.xml b/.idea/libraries/Maven__com_fifesoft_rsyntaxtextarea_2_6_1.xml new file mode 100644 index 0000000..10c71bd --- /dev/null +++ b/.idea/libraries/Maven__com_fifesoft_rsyntaxtextarea_2_6_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_sun_attach_1_7.xml b/.idea/libraries/Maven__com_sun_attach_1_7.xml new file mode 100644 index 0000000..2976de5 --- /dev/null +++ b/.idea/libraries/Maven__com_sun_attach_1_7.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_weblaf_weblaf_1_2_9.xml b/.idea/libraries/Maven__com_weblaf_weblaf_1_2_9.xml new file mode 100644 index 0000000..596f2c6 --- /dev/null +++ b/.idea/libraries/Maven__com_weblaf_weblaf_1_2_9.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__commons_cli_commons_cli_1_4.xml b/.idea/libraries/Maven__commons_cli_commons_cli_1_4.xml new file mode 100644 index 0000000..55a1fa8 --- /dev/null +++ b/.idea/libraries/Maven__commons_cli_commons_cli_1_4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__commons_io_commons_io_2_4.xml b/.idea/libraries/Maven__commons_io_commons_io_2_4.xml new file mode 100644 index 0000000..bc2aad0 --- /dev/null +++ b/.idea/libraries/Maven__commons_io_commons_io_2_4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_apache_ant_ant_1_10_5.xml b/.idea/libraries/Maven__org_apache_ant_ant_1_10_5.xml new file mode 100644 index 0000000..d9200d7 --- /dev/null +++ b/.idea/libraries/Maven__org_apache_ant_ant_1_10_5.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_apache_ant_ant_launcher_1_10_5.xml b/.idea/libraries/Maven__org_apache_ant_ant_launcher_1_10_5.xml new file mode 100644 index 0000000..9c2f99f --- /dev/null +++ b/.idea/libraries/Maven__org_apache_ant_ant_launcher_1_10_5.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_benf_reader_1_3_9.xml b/.idea/libraries/Maven__org_benf_reader_1_3_9.xml new file mode 100644 index 0000000..0391d9e --- /dev/null +++ b/.idea/libraries/Maven__org_benf_reader_1_3_9.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_bitbucket_mstrobel_procyon_0_5_33.xml b/.idea/libraries/Maven__org_bitbucket_mstrobel_procyon_0_5_33.xml new file mode 100644 index 0000000..e361936 --- /dev/null +++ b/.idea/libraries/Maven__org_bitbucket_mstrobel_procyon_0_5_33.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jfree_jfreechart_1_5_0.xml b/.idea/libraries/Maven__org_jfree_jfreechart_1_5_0.xml new file mode 100644 index 0000000..cad183c --- /dev/null +++ b/.idea/libraries/Maven__org_jfree_jfreechart_1_5_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_tinyjee_jgraphx_jgraphx_3_4_1_3.xml b/.idea/libraries/Maven__org_tinyjee_jgraphx_jgraphx_3_4_1_3.xml new file mode 100644 index 0000000..2e9764e --- /dev/null +++ b/.idea/libraries/Maven__org_tinyjee_jgraphx_jgraphx_3_4_1_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..d30d09e --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..efaec85 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..cbe8318 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1565614837456 + + + + + + \ No newline at end of file diff --git a/JByteMod Reborn.iml b/JByteMod Reborn.iml new file mode 100644 index 0000000..6d4fecb --- /dev/null +++ b/JByteMod Reborn.iml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..f5f8c05 --- /dev/null +++ b/pom.xml @@ -0,0 +1,209 @@ + + + 4.0.0 + GraxCode + JByteMod + Reborn + jar + + UTF-8 + 1.8 + 1.8 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + + -verbose + -Xlint:all,-options,-path + + true + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.0.2 + + + + true + lib/ + me.grax.jbytemod.JByteMod + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + false + false + + + + package + + shade + + + + + + org.apache.maven.plugins + maven-install-plugin + 2.5.2 + + + install-weblaf + clean + + ${basedir}/lib/weblaf-complete-1.29-fixed.jar + default + com.weblaf + weblaf + 1.2.9 + jar + true + + + install-file + + + + install-cfr + clean + + ${basedir}/lib/cfr_0_139.jar + default + org.benf + reader + 1.3.9 + jar + true + + + install-file + + + + install-attach + clean + + ${basedir}/lib/attach-1.7.jar + default + com.sun + attach + 1.7 + jar + true + + + install-file + + + + install-procyon + clean + + ${basedir}/lib/procyon-0.5.33.jar + default + org.bitbucket.mstrobel + procyon + 0.5.33 + jar + true + + + install-file + + + + + + + + + commons-io + commons-io + 2.4 + + + com.fifesoft + rsyntaxtextarea + 2.6.1 + + + + + org.bitbucket.mstrobel + procyon + 0.5.33 + + + + org.tinyjee.jgraphx + jgraphx + 3.4.1.3 + + + org.jfree + jfreechart + 1.5.0 + + + com.weblaf + weblaf + 1.2.9 + + + org.benf + reader + 1.3.9 + + + com.sun + attach + 1.7 + + + commons-cli + commons-cli + 1.4 + + + + org.apache.ant + ant + 1.10.5 + + + diff --git a/src/main/java/android/util/Patterns.java b/src/main/java/android/util/Patterns.java new file mode 100644 index 0000000..bcb5488 --- /dev/null +++ b/src/main/java/android/util/Patterns.java @@ -0,0 +1,409 @@ +package android.util; + +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Commonly used regular expression patterns. + */ +public class Patterns { + /** + * Regular expression to match all IANA top-level domains. List accurate as of + * 2011/07/18. List taken from: + * http://data.iana.org/TLD/tlds-alpha-by-domain.txt This pattern is + * auto-generated by frameworks/ex/common/tools/make-iana-tld-pattern.py + * + * @deprecated Due to the recent profileration of gTLDs, this API is expected + * to become out-of-date very quickly. Therefore it is now + * deprecated. + */ + @Deprecated + public static final String TOP_LEVEL_DOMAIN_STR = "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])" + "|(biz|b[abdefghijmnorstvwyz])" + + "|(cat|com|coop|c[acdfghiklmnoruvxyz])" + "|d[ejkmoz]" + "|(edu|e[cegrstu])" + "|f[ijkmor]" + "|(gov|g[abdefghilmnpqrstuwy])" + "|h[kmnrtu]" + + "|(info|int|i[delmnoqrst])" + "|(jobs|j[emop])" + "|k[eghimnprwyz]" + "|l[abcikrstuvy]" + "|(mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])" + + "|(name|net|n[acefgilopruz])" + "|(org|om)" + "|(pro|p[aefghklmnrstwy])" + "|qa" + "|r[eosuw]" + "|s[abcdeghijklmnortuvyz]" + + "|(tel|travel|t[cdfghjklmnoprtvwz])" + "|u[agksyz]" + "|v[aceginu]" + "|w[fs]" + + "|(\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)" + + "|y[et]" + "|z[amw])"; + + /** + * Regular expression pattern to match all IANA top-level domains. + * + * @deprecated This API is deprecated. See {@link #TOP_LEVEL_DOMAIN_STR}. + */ + @Deprecated + public static final Pattern TOP_LEVEL_DOMAIN = Pattern.compile(TOP_LEVEL_DOMAIN_STR); + + /** + * Regular expression to match all IANA top-level domains for WEB_URL. List + * accurate as of 2011/07/18. List taken from: + * http://data.iana.org/TLD/tlds-alpha-by-domain.txt This pattern is + * auto-generated by frameworks/ex/common/tools/make-iana-tld-pattern.py + * + * @deprecated This API is deprecated. See {@link #TOP_LEVEL_DOMAIN_STR}. + */ + @Deprecated + public static final String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL = "(?:" + "(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])" + "|(?:biz|b[abdefghijmnorstvwyz])" + + "|(?:cat|com|coop|c[acdfghiklmnoruvxyz])" + "|d[ejkmoz]" + "|(?:edu|e[cegrstu])" + "|f[ijkmor]" + "|(?:gov|g[abdefghilmnpqrstuwy])" + + "|h[kmnrtu]" + "|(?:info|int|i[delmnoqrst])" + "|(?:jobs|j[emop])" + "|k[eghimnprwyz]" + "|l[abcikrstuvy]" + + "|(?:mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])" + "|(?:name|net|n[acefgilopruz])" + "|(?:org|om)" + "|(?:pro|p[aefghklmnrstwy])" + "|qa" + + "|r[eosuw]" + "|s[abcdeghijklmnortuvyz]" + "|(?:tel|travel|t[cdfghjklmnoprtvwz])" + "|u[agksyz]" + "|v[aceginu]" + "|w[fs]" + + "|(?:\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)" + + "|y[et]" + "|z[amw]))"; + + /** + * Regular expression to match all IANA top-level domains. + * + * List accurate as of 2015/11/24. List taken from: + * http://data.iana.org/TLD/tlds-alpha-by-domain.txt This pattern is + * auto-generated by frameworks/ex/common/tools/make-iana-tld-pattern.py + * + * @hide + */ + static final String IANA_TOP_LEVEL_DOMAINS = "(?:" + "(?:aaa|aarp|abb|abbott|abogado|academy|accenture|accountant|accountants|aco|active" + + "|actor|ads|adult|aeg|aero|afl|agency|aig|airforce|airtel|allfinanz|alsace|amica|amsterdam" + + "|android|apartments|app|apple|aquarelle|aramco|archi|army|arpa|arte|asia|associates" + + "|attorney|auction|audio|auto|autos|axa|azure|a[cdefgilmoqrstuwxz])" + + "|(?:band|bank|bar|barcelona|barclaycard|barclays|bargains|bauhaus|bayern|bbc|bbva" + + "|bcn|beats|beer|bentley|berlin|best|bet|bharti|bible|bid|bike|bing|bingo|bio|biz|black" + + "|blackfriday|bloomberg|blue|bms|bmw|bnl|bnpparibas|boats|bom|bond|boo|boots|boutique" + + "|bradesco|bridgestone|broadway|broker|brother|brussels|budapest|build|builders|business" + "|buzz|bzh|b[abdefghijmnorstvwyz])" + + "|(?:cab|cafe|cal|camera|camp|cancerresearch|canon|capetown|capital|car|caravan|cards" + + "|care|career|careers|cars|cartier|casa|cash|casino|cat|catering|cba|cbn|ceb|center|ceo" + + "|cern|cfa|cfd|chanel|channel|chat|cheap|chloe|christmas|chrome|church|cipriani|cisco" + + "|citic|city|cityeats|claims|cleaning|click|clinic|clothing|cloud|club|clubmed|coach" + + "|codes|coffee|college|cologne|com|commbank|community|company|computer|comsec|condos" + + "|construction|consulting|contractors|cooking|cool|coop|corsica|country|coupons|courses" + + "|credit|creditcard|creditunion|cricket|crown|crs|cruises|csc|cuisinella|cymru|cyou|c[acdfghiklmnoruvwxyz])" + + "|(?:dabur|dad|dance|date|dating|datsun|day|dclk|deals|degree|delivery|dell|delta" + + "|democrat|dental|dentist|desi|design|dev|diamonds|diet|digital|direct|directory|discount" + + "|dnp|docs|dog|doha|domains|doosan|download|drive|durban|dvag|d[ejkmoz])" + + "|(?:earth|eat|edu|education|email|emerck|energy|engineer|engineering|enterprises" + + "|epson|equipment|erni|esq|estate|eurovision|eus|events|everbank|exchange|expert|exposed" + "|express|e[cegrstu])" + + "|(?:fage|fail|fairwinds|faith|family|fan|fans|farm|fashion|feedback|ferrero|film" + + "|final|finance|financial|firmdale|fish|fishing|fit|fitness|flights|florist|flowers|flsmidth" + + "|fly|foo|football|forex|forsale|forum|foundation|frl|frogans|fund|furniture|futbol|fyi" + "|f[ijkmor])" + + "|(?:gal|gallery|game|garden|gbiz|gdn|gea|gent|genting|ggee|gift|gifts|gives|giving" + + "|glass|gle|global|globo|gmail|gmo|gmx|gold|goldpoint|golf|goo|goog|google|gop|gov|grainger" + + "|graphics|gratis|green|gripe|group|gucci|guge|guide|guitars|guru|g[abdefghilmnpqrstuwy])" + + "|(?:hamburg|hangout|haus|healthcare|help|here|hermes|hiphop|hitachi|hiv|hockey|holdings" + + "|holiday|homedepot|homes|honda|horse|host|hosting|hoteles|hotmail|house|how|hsbc|hyundai" + "|h[kmnrtu])" + + "|(?:ibm|icbc|ice|icu|ifm|iinet|immo|immobilien|industries|infiniti|info|ing|ink|institute" + + "|insure|int|international|investments|ipiranga|irish|ist|istanbul|itau|iwc|i[delmnoqrst])" + + "|(?:jaguar|java|jcb|jetzt|jewelry|jlc|jll|jobs|joburg|jprs|juegos|j[emop])" + + "|(?:kaufen|kddi|kia|kim|kinder|kitchen|kiwi|koeln|komatsu|krd|kred|kyoto|k[eghimnprwyz])" + + "|(?:lacaixa|lancaster|land|landrover|lasalle|lat|latrobe|law|lawyer|lds|lease|leclerc" + + "|legal|lexus|lgbt|liaison|lidl|life|lifestyle|lighting|limited|limo|linde|link|live" + + "|lixil|loan|loans|lol|london|lotte|lotto|love|ltd|ltda|lupin|luxe|luxury|l[abcikrstuvy])" + + "|(?:madrid|maif|maison|man|management|mango|market|marketing|markets|marriott|mba" + + "|media|meet|melbourne|meme|memorial|men|menu|meo|miami|microsoft|mil|mini|mma|mobi|moda" + + "|moe|moi|mom|monash|money|montblanc|mormon|mortgage|moscow|motorcycles|mov|movie|movistar" + + "|mtn|mtpc|mtr|museum|mutuelle|m[acdeghklmnopqrstuvwxyz])" + + "|(?:nadex|nagoya|name|navy|nec|net|netbank|network|neustar|new|news|nexus|ngo|nhk" + + "|nico|ninja|nissan|nokia|nra|nrw|ntt|nyc|n[acefgilopruz])" + + "|(?:obi|office|okinawa|omega|one|ong|onl|online|ooo|oracle|orange|org|organic|osaka" + "|otsuka|ovh|om)" + + "|(?:page|panerai|paris|partners|parts|party|pet|pharmacy|philips|photo|photography" + + "|photos|physio|piaget|pics|pictet|pictures|ping|pink|pizza|place|play|playstation|plumbing" + + "|plus|pohl|poker|porn|post|praxi|press|pro|prod|productions|prof|properties|property" + "|protection|pub|p[aefghklmnrstwy])" + + "|(?:qpon|quebec|qa)" + "|(?:racing|realtor|realty|recipes|red|redstone|rehab|reise|reisen|reit|ren|rent|rentals" + + "|repair|report|republican|rest|restaurant|review|reviews|rich|ricoh|rio|rip|rocher|rocks" + "|rodeo|rsvp|ruhr|run|rwe|ryukyu|r[eosuw])" + + "|(?:saarland|sakura|sale|samsung|sandvik|sandvikcoromant|sanofi|sap|sapo|sarl|saxo" + + "|sbs|sca|scb|schmidt|scholarships|school|schule|schwarz|science|scor|scot|seat|security" + + "|seek|sener|services|seven|sew|sex|sexy|shiksha|shoes|show|shriram|singles|site|ski" + + "|sky|skype|sncf|soccer|social|software|sohu|solar|solutions|sony|soy|space|spiegel|spreadbetting" + + "|srl|stada|starhub|statoil|stc|stcgroup|stockholm|studio|study|style|sucks|supplies" + + "|supply|support|surf|surgery|suzuki|swatch|swiss|sydney|systems|s[abcdeghijklmnortuvxyz])" + + "|(?:tab|taipei|tatamotors|tatar|tattoo|tax|taxi|team|tech|technology|tel|telefonica" + + "|temasek|tennis|thd|theater|theatre|tickets|tienda|tips|tires|tirol|today|tokyo|tools" + + "|top|toray|toshiba|tours|town|toyota|toys|trade|trading|training|travel|trust|tui|t[cdfghjklmnortvwz])" + + "|(?:ubs|university|uno|uol|u[agksyz])" + "|(?:vacations|vana|vegas|ventures|versicherung|vet|viajes|video|villas|vin|virgin" + + "|vision|vista|vistaprint|viva|vlaanderen|vodka|vote|voting|voto|voyage|v[aceginu])" + + "|(?:wales|walter|wang|watch|webcam|website|wed|wedding|weir|whoswho|wien|wiki|williamhill" + + "|win|windows|wine|wme|work|works|world|wtc|wtf|w[fs])" + + "|(?:\u03b5\u03bb|\u0431\u0435\u043b|\u0434\u0435\u0442\u0438|\u043a\u043e\u043c|\u043c\u043a\u0434" + + "|\u043c\u043e\u043d|\u043c\u043e\u0441\u043a\u0432\u0430|\u043e\u043d\u043b\u0430\u0439\u043d" + + "|\u043e\u0440\u0433|\u0440\u0443\u0441|\u0440\u0444|\u0441\u0430\u0439\u0442|\u0441\u0440\u0431" + + "|\u0443\u043a\u0440|\u049b\u0430\u0437|\u0570\u0561\u0575|\u05e7\u05d5\u05dd|\u0627\u0631\u0627\u0645\u0643\u0648" + + "|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629" + + "|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0627\u06cc\u0631\u0627\u0646" + + "|\u0628\u0627\u0632\u0627\u0631|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633" + + "|\u0633\u0648\u062f\u0627\u0646|\u0633\u0648\u0631\u064a\u0629|\u0634\u0628\u0643\u0629" + + "|\u0639\u0631\u0627\u0642|\u0639\u0645\u0627\u0646|\u0641\u0644\u0633\u0637\u064a\u0646" + + "|\u0642\u0637\u0631|\u0643\u0648\u0645|\u0645\u0635\u0631|\u0645\u0644\u064a\u0633\u064a\u0627" + + "|\u0645\u0648\u0642\u0639|\u0915\u0949\u092e|\u0928\u0947\u091f|\u092d\u093e\u0930\u0924" + + "|\u0938\u0902\u0917\u0920\u0928|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4" + + "|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd" + + "|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e04\u0e2d\u0e21|\u0e44\u0e17\u0e22" + + "|\u10d2\u10d4|\u307f\u3093\u306a|\u30b0\u30fc\u30b0\u30eb|\u30b3\u30e0|\u4e16\u754c" + + "|\u4e2d\u4fe1|\u4e2d\u56fd|\u4e2d\u570b|\u4e2d\u6587\u7f51|\u4f01\u4e1a|\u4f5b\u5c71" + + "|\u4fe1\u606f|\u5065\u5eb7|\u516b\u5366|\u516c\u53f8|\u516c\u76ca|\u53f0\u6e7e|\u53f0\u7063" + + "|\u5546\u57ce|\u5546\u5e97|\u5546\u6807|\u5728\u7ebf|\u5927\u62ff|\u5a31\u4e50|\u5de5\u884c" + + "|\u5e7f\u4e1c|\u6148\u5584|\u6211\u7231\u4f60|\u624b\u673a|\u653f\u52a1|\u653f\u5e9c" + + "|\u65b0\u52a0\u5761|\u65b0\u95fb|\u65f6\u5c1a|\u673a\u6784|\u6de1\u9a6c\u9521|\u6e38\u620f" + + "|\u70b9\u770b|\u79fb\u52a8|\u7ec4\u7ec7\u673a\u6784|\u7f51\u5740|\u7f51\u5e97|\u7f51\u7edc" + + "|\u8c37\u6b4c|\u96c6\u56e2|\u98de\u5229\u6d66|\u9910\u5385|\u9999\u6e2f|\ub2f7\ub137" + "|\ub2f7\ucef4|\uc0bc\uc131|\ud55c\uad6d|xbox" + + "|xerox|xin|xn\\-\\-11b4c3d|xn\\-\\-1qqw23a|xn\\-\\-30rr7y|xn\\-\\-3bst00m|xn\\-\\-3ds443g" + + "|xn\\-\\-3e0b707e|xn\\-\\-3pxu8k|xn\\-\\-42c2d9a|xn\\-\\-45brj9c|xn\\-\\-45q11c|xn\\-\\-4gbrim" + + "|xn\\-\\-55qw42g|xn\\-\\-55qx5d|xn\\-\\-6frz82g|xn\\-\\-6qq986b3xl|xn\\-\\-80adxhks" + + "|xn\\-\\-80ao21a|xn\\-\\-80asehdb|xn\\-\\-80aswg|xn\\-\\-90a3ac|xn\\-\\-90ais|xn\\-\\-9dbq2a" + + "|xn\\-\\-9et52u|xn\\-\\-b4w605ferd|xn\\-\\-c1avg|xn\\-\\-c2br7g|xn\\-\\-cg4bki|xn\\-\\-clchc0ea0b2g2a9gcd" + + "|xn\\-\\-czr694b|xn\\-\\-czrs0t|xn\\-\\-czru2d|xn\\-\\-d1acj3b|xn\\-\\-d1alf|xn\\-\\-efvy88h" + + "|xn\\-\\-estv75g|xn\\-\\-fhbei|xn\\-\\-fiq228c5hs|xn\\-\\-fiq64b|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s" + + "|xn\\-\\-fjq720a|xn\\-\\-flw351e|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-gecrj9c" + + "|xn\\-\\-h2brj9c|xn\\-\\-hxt814e|xn\\-\\-i1b6b1a6a2e|xn\\-\\-imr513n|xn\\-\\-io0a7i" + + "|xn\\-\\-j1aef|xn\\-\\-j1amh|xn\\-\\-j6w193g|xn\\-\\-kcrx77d1x4a|xn\\-\\-kprw13d|xn\\-\\-kpry57d" + + "|xn\\-\\-kput3i|xn\\-\\-l1acc|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgb9awbf|xn\\-\\-mgba3a3ejt" + + "|xn\\-\\-mgba3a4f16a|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbab2bd|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e" + + "|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-mgbpl2fh|xn\\-\\-mgbtx2b|xn\\-\\-mgbx4cd0ab" + + "|xn\\-\\-mk1bu44c|xn\\-\\-mxtq1m|xn\\-\\-ngbc5azd|xn\\-\\-node|xn\\-\\-nqv7f|xn\\-\\-nqv7fs00ema" + + "|xn\\-\\-nyqy26a|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1acf|xn\\-\\-p1ai|xn\\-\\-pgbs0dh" + + "|xn\\-\\-pssy2u|xn\\-\\-q9jyb4c|xn\\-\\-qcka1pmc|xn\\-\\-qxam|xn\\-\\-rhqv96g|xn\\-\\-s9brj9c" + + "|xn\\-\\-ses554g|xn\\-\\-t60b56a|xn\\-\\-tckwe|xn\\-\\-unup4y|xn\\-\\-vermgensberater\\-ctb" + + "|xn\\-\\-vermgensberatung\\-pwb|xn\\-\\-vhquv|xn\\-\\-vuq861b|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a" + + "|xn\\-\\-xhq521b|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-y9a3aq|xn\\-\\-yfro4i67o" + + "|xn\\-\\-ygbi2ammx|xn\\-\\-zfr164b|xperia|xxx|xyz)" + "|(?:yachts|yamaxun|yandex|yodobashi|yoga|yokohama|youtube|y[et])" + + "|(?:zara|zip|zone|zuerich|z[amw]))"; + + /** + * Kept for backward compatibility reasons. + * + * @deprecated Deprecated since it does not include all IRI characters defined + * in RFC 3987 + */ + @Deprecated + public static final String GOOD_IRI_CHAR = "a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF"; + + private static final String IP_ADDRESS_STRING = "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]" + + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]" + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}" + + "|[1-9][0-9]|[0-9]))"; + public static final Pattern IP_ADDRESS = Pattern.compile(IP_ADDRESS_STRING); + + /** + * Valid UCS characters defined in RFC 3987. Excludes space characters. + */ + private static final String UCS_CHAR = "[" + "\u00A0-\uD7FF" + "\uF900-\uFDCF" + "\uFDF0-\uFFEF" + "\uD800\uDC00-\uD83F\uDFFD" + + "\uD840\uDC00-\uD87F\uDFFD" + "\uD880\uDC00-\uD8BF\uDFFD" + "\uD8C0\uDC00-\uD8FF\uDFFD" + "\uD900\uDC00-\uD93F\uDFFD" + + "\uD940\uDC00-\uD97F\uDFFD" + "\uD980\uDC00-\uD9BF\uDFFD" + "\uD9C0\uDC00-\uD9FF\uDFFD" + "\uDA00\uDC00-\uDA3F\uDFFD" + + "\uDA40\uDC00-\uDA7F\uDFFD" + "\uDA80\uDC00-\uDABF\uDFFD" + "\uDAC0\uDC00-\uDAFF\uDFFD" + "\uDB00\uDC00-\uDB3F\uDFFD" + + "\uDB44\uDC00-\uDB7F\uDFFD" + "&&[^\u00A0[\u2000-\u200A]\u2028\u2029\u202F\u3000]]"; + + /** + * Valid characters for IRI label defined in RFC 3987. + */ + private static final String LABEL_CHAR = "a-zA-Z0-9" + UCS_CHAR; + + /** + * Valid characters for IRI TLD defined in RFC 3987. + */ + private static final String TLD_CHAR = "a-zA-Z" + UCS_CHAR; + + /** + * RFC 1035 Section 2.3.4 limits the labels to a maximum 63 octets. + */ + private static final String IRI_LABEL = "[" + LABEL_CHAR + "](?:[" + LABEL_CHAR + "_\\-]{0,61}[" + LABEL_CHAR + "]){0,1}"; + + /** + * RFC 3492 references RFC 1034 and limits Punycode algorithm output to 63 + * characters. + */ + private static final String PUNYCODE_TLD = "xn\\-\\-[\\w\\-]{0,58}\\w"; + + private static final String TLD = "(" + PUNYCODE_TLD + "|" + "[" + TLD_CHAR + "]{2,63}" + ")"; + + private static final String HOST_NAME = "(" + IRI_LABEL + "\\.)+" + TLD; + + private static final String DOMAIN_NAME_STR = "(" + HOST_NAME + "|" + IP_ADDRESS_STRING + ")"; + public static final Pattern DOMAIN_NAME = Pattern.compile(DOMAIN_NAME_STR); + + private static final String PROTOCOL = "(?i:http|https|rtsp)://"; + + /* + * A word boundary or end of input. This is to stop foo.sure from matching as + * foo.su + */ + private static final String WORD_BOUNDARY = "(?:\\b|$|^)"; + + private static final String USER_INFO = "(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)" + + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_" + + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@"; + + private static final String PORT_NUMBER = "\\:\\d{1,5}"; + + private static final String PATH_AND_QUERY = "[/\\?](?:(?:[" + LABEL_CHAR + ";/\\?:@&=#~" // plus optional query params + + "\\-\\.\\+!\\*'\\(\\),_\\$])|(?:%[a-fA-F0-9]{2}))*"; + + /** + * Regular expression pattern to match most part of RFC 3987 Internationalized + * URLs, aka IRIs. + */ + public static final Pattern WEB_URL = Pattern.compile("(" + "(" + "(?:" + PROTOCOL + "(?:" + USER_INFO + ")?" + ")?" + "(?:" + DOMAIN_NAME_STR + ")" + + "(?:" + PORT_NUMBER + ")?" + ")" + "(" + PATH_AND_QUERY + ")?" + WORD_BOUNDARY + ")"); + + /** + * Regular expression that matches known TLDs and punycode TLDs + */ + private static final String STRICT_TLD = "(?:" + IANA_TOP_LEVEL_DOMAINS + "|" + PUNYCODE_TLD + ")"; + + /** + * Regular expression that matches host names using {@link #STRICT_TLD} + */ + private static final String STRICT_HOST_NAME = "(?:(?:" + IRI_LABEL + "\\.)+" + STRICT_TLD + ")"; + + /** + * Regular expression that matches domain names using either + * {@link #STRICT_HOST_NAME} or {@link #IP_ADDRESS} + */ + private static final String STRICT_DOMAIN_NAME = "(?:" + STRICT_HOST_NAME + "|" + IP_ADDRESS_STRING + ")"; + + /** + * Regular expression that matches domain names without a TLD + */ + private static final String RELAXED_DOMAIN_NAME = "(?:" + "(?:" + IRI_LABEL + "(?:\\.(?=\\S))" + "?)+" + "|" + IP_ADDRESS_STRING + ")"; + + /** + * Regular expression to match strings that do not start with a supported + * protocol. The TLDs are expected to be one of the known TLDs. + */ + private static final String WEB_URL_WITHOUT_PROTOCOL = "(" + WORD_BOUNDARY + "(? + * The pattern matches the following: + * + */ + public static final Pattern PHONE = Pattern.compile( // sdd = space, dot, or dash + "(\\+[0-9]+[\\- \\.]*)?" // +* + + "(\\([0-9]+\\)[\\- \\.]*)?" // ()* + + "([0-9][0-9\\- \\.]+[0-9])"); // + + + /** + * Convenience method to take all of the non-null matching groups in a regex + * Matcher and return them as a concatenated string. + * + * @param matcher + * The Matcher object from which grouped text will be extracted + * + * @return A String comprising all of the non-null matched groups concatenated + * together + */ + public static final String concatGroups(Matcher matcher) { + StringBuilder b = new StringBuilder(); + final int numGroups = matcher.groupCount(); + + for (int i = 1; i <= numGroups; i++) { + String s = matcher.group(i); + + if (s != null) { + b.append(s); + } + } + + return b.toString(); + } + + /** + * Convenience method to return only the digits and plus signs in the matching + * string. + * + * @param matcher + * The Matcher object from which digits and plus will be extracted + * + * @return A String comprising all of the digits and plus in the match + */ + public static final String digitsAndPlusOnly(Matcher matcher) { + StringBuilder buffer = new StringBuilder(); + String matchingRegion = matcher.group(); + + for (int i = 0, size = matchingRegion.length(); i < size; i++) { + char character = matchingRegion.charAt(i); + + if (character == '+' || Character.isDigit(character)) { + buffer.append(character); + } + } + return buffer.toString(); + } + + /** + * Do not create this static utility class. + */ + private Patterns() { + } +} diff --git a/src/main/java/me/grax/jbytemod/JByteMod.java b/src/main/java/me/grax/jbytemod/JByteMod.java new file mode 100644 index 0000000..cbd309d --- /dev/null +++ b/src/main/java/me/grax/jbytemod/JByteMod.java @@ -0,0 +1,512 @@ +package me.grax.jbytemod; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.GridLayout; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; +import java.lang.instrument.Instrumentation; +import java.lang.reflect.Field; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.util.HashMap; +import java.util.LinkedHashMap; + +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JSplitPane; +import javax.swing.UIManager; +import javax.swing.border.EmptyBorder; +import javax.swing.border.LineBorder; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.HelpFormatter; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; + +import com.sun.tools.attach.VirtualMachine; + +import me.grax.jbytemod.logging.Logging; +import me.grax.jbytemod.plugin.Plugin; +import me.grax.jbytemod.plugin.PluginManager; +import me.grax.jbytemod.res.LanguageRes; +import me.grax.jbytemod.res.Options; +import me.grax.jbytemod.ui.ClassTree; +import me.grax.jbytemod.ui.DecompilerPanel; +import me.grax.jbytemod.ui.InfoPanel; +import me.grax.jbytemod.ui.MyMenuBar; +import me.grax.jbytemod.ui.MySplitPane; +import me.grax.jbytemod.ui.MyTabbedPane; +import me.grax.jbytemod.ui.MyToolBar; +import me.grax.jbytemod.ui.PageEndPanel; +import me.grax.jbytemod.ui.graph.ControlFlowPanel; +import me.grax.jbytemod.ui.lists.LVPList; +import me.grax.jbytemod.ui.lists.MyCodeList; +import me.grax.jbytemod.ui.lists.SearchList; +import me.grax.jbytemod.ui.lists.TCBList; +import me.grax.jbytemod.ui.tree.SortedTreeNode; +import me.grax.jbytemod.utils.ErrorDisplay; +import me.grax.jbytemod.utils.FileUtils; +import me.grax.jbytemod.utils.asm.FrameGen; +import me.grax.jbytemod.utils.attach.RuntimeJarArchive; +import me.grax.jbytemod.utils.gui.LookUtils; +import me.grax.jbytemod.utils.task.AttachTask; +import me.grax.jbytemod.utils.task.RetransformTask; +import me.grax.jbytemod.utils.task.SaveTask; +import me.lpk.util.ASMUtils; +import me.lpk.util.OpUtils; + +public class JByteMod extends JFrame { + + public static File workingDir = new File("."); + public static String configPath = "jbytemod.cfg"; + public static Logging LOGGER; + public static LanguageRes res; + public static Options ops; + + private static boolean lafInit; + + private static JarArchive file; + public static HashMap lastSelectedTreeEntries = new LinkedHashMap<>(); + + private static Instrumentation agentInstrumentation; + + public static JByteMod instance; + public static Color border; + private static final String jbytemod = "JByteMod Reborn"; + static { + try { + System.loadLibrary("attach"); + } catch (Throwable ex) {} + } + + public static void agentmain(String agentArgs, Instrumentation ins) { + if (!ins.isRedefineClassesSupported()) { + JOptionPane.showMessageDialog(null, "Class redefinition is disabled, cannot attach!"); + return; + } + agentInstrumentation = ins; + workingDir = new File(agentArgs); + initialize(); + if (!lafInit) { + LookUtils.setLAF(); + lafInit = true; + } + JByteMod.file = new RuntimeJarArchive(ins); + JByteMod frame = new JByteMod(true); + frame.setTitleSuffix("Agent"); + instance = frame; + frame.setVisible(true); + } + + public static void initialize() { + LOGGER = new Logging(); + res = new LanguageRes(); + ops = new Options(); + try { + System.setProperty("file.encoding", "UTF-8"); + Field charset = Charset.class.getDeclaredField("defaultCharset"); + charset.setAccessible(true); + charset.set(null, null); + } catch (Throwable t) { + JByteMod.LOGGER.err("Failed to set encoding to UTF-8 (" + t.getMessage() + ")"); + } + } + + /** + * Launch the application. + */ + public static void main(String[] args) { + org.apache.commons.cli.Options options = new org.apache.commons.cli.Options(); + options.addOption("f", "file", true, "File to open"); + options.addOption("d", "dir", true, "Working directory"); + options.addOption("c", "config", true, "Config file name"); + options.addOption("?", "help", false, "Prints this help"); + + CommandLineParser parser = new DefaultParser(); + CommandLine line; + try { + line = parser.parse(options, args); + } catch (org.apache.commons.cli.ParseException e) { + e.printStackTrace(); + throw new RuntimeException("An error occurred while parsing the commandline "); + } + if (line.hasOption("help")) { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp(jbytemod, options); + return; + } + if (line.hasOption("d")) { + workingDir = new File(line.getOptionValue("d")); + if (!(workingDir.exists() && workingDir.isDirectory())) { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp(jbytemod, options); + return; + } + JByteMod.LOGGER.err("Specified working dir set"); + } + if (line.hasOption("c")) { + configPath = line.getOptionValue("c"); + } + initialize(); + EventQueue.invokeLater(new Runnable() { + + public void run() { + try { + if (!lafInit) { + LookUtils.setLAF(); + lafInit = true; + } + JByteMod frame = new JByteMod(false); + instance = frame; + frame.setVisible(true); + if (line.hasOption("f")) { + File input = new File(line.getOptionValue("f")); + if (FileUtils.exists(input) && FileUtils.isType(input, ".jar", ".class")) { + frame.loadFile(input); + JByteMod.LOGGER.log("Specified file loaded"); + } else { + JByteMod.LOGGER.err("Specified file not found"); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + public static void resetLAF() { + lafInit = false; + } + + public static void restartGUI() { + instance.dispose(); + instance = null; + System.gc(); + JByteMod.main(new String[0]); + } + + private JPanel contentPane; + private ClassTree jarTree; + private MyCodeList clist; + + private PageEndPanel pp; + private SearchList slist; + + private DecompilerPanel dp; + private TCBList tcblist; + private MyTabbedPane tabbedPane; + private InfoPanel sp; + + private LVPList lvplist; + + private ControlFlowPanel cfp; + + private MyMenuBar myMenuBar; + + private ClassNode currentNode; + + private MethodNode currentMethod; + + private PluginManager pluginManager; + + private File filePath; + + /** + * Create the frame. + */ + public JByteMod(boolean agent) { + if (ops.get("use_rt").getBoolean()) { + new FrameGen().start(); + } + this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + this.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent we) { + if (JOptionPane.showConfirmDialog(JByteMod.this, res.getResource("exit_warn"), res.getResource("is_sure"), + JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { + if (agent) { + dispose(); + } else { + Runtime.getRuntime().exit(0); + } + } + } + }); + border = UIManager.getColor("nimbusBorder"); + if (border == null) { + border = new Color(146, 151, 161); + } + this.setBounds(100, 100, 1280, 720); + this.setTitle(jbytemod); + this.setJMenuBar(myMenuBar = new MyMenuBar(this, agent)); + this.jarTree = new ClassTree(this); + contentPane = new JPanel(); + contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); + contentPane.setLayout(new BorderLayout(5, 5)); + this.setContentPane(contentPane); + this.setTCBList(new TCBList()); + this.setLVPList(new LVPList()); + JPanel border = new JPanel(); + if (!UIManager.getLookAndFeel().getName().equals("WebLookAndFeel")) { + //looks better without border for weblaf + border.setBorder(new LineBorder(JByteMod.border)); + } + border.setLayout(new GridLayout()); + JSplitPane splitPane = new MySplitPane(this, jarTree); + JPanel b2 = new JPanel(); + b2.setBorder(new EmptyBorder(5, 0, 5, 0)); + b2.setLayout(new GridLayout()); + b2.add(splitPane); + border.add(b2); + contentPane.add(border, BorderLayout.CENTER); + contentPane.add(pp = new PageEndPanel(), BorderLayout.PAGE_END); + contentPane.add(new MyToolBar(this), BorderLayout.PAGE_START); + if (file != null) { + this.refreshTree(); + } + } + + public void applyChangesAgent() { + if (agentInstrumentation == null) { + throw new RuntimeException(); + } + new RetransformTask(this, agentInstrumentation, file).execute(); + } + + public void attachTo(VirtualMachine vm) throws Exception { + if (JOptionPane.showConfirmDialog(JByteMod.this, res.getResource("exit_warn"), res.getResource("is_sure"), + JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { + new AttachTask(this, vm).execute(); + } + } + + public void changeUI(String clazz) { + LookUtils.changeLAF(clazz); + } + + public ControlFlowPanel getCFP() { + return this.cfp; + } + + public MyCodeList getCodeList() { + return clist; + } + + public MethodNode getCurrentMethod() { + return currentMethod; + } + + public ClassNode getCurrentNode() { + return currentNode; + } + + public JarArchive getFile() { + return file; + } + + public File getFilePath() { + return filePath; + } + + public ClassTree getJarTree() { + return jarTree; + } + + public LVPList getLVPList() { + return lvplist; + } + + public MyMenuBar getMyMenuBar() { + return myMenuBar; + } + + public PluginManager getPluginManager() { + return pluginManager; + } + + public PageEndPanel getPP() { + return pp; + } + + public SearchList getSearchList() { + return slist; + } + + public MyTabbedPane getTabbedPane() { + return tabbedPane; + } + + public TCBList getTCBList() { + return tcblist; + } + + /** + * Load .jar or .class file + */ + public void loadFile(File input) { + this.filePath = input; + String ap = input.getAbsolutePath(); + if (ap.endsWith(".jar")) { + try { + file = new JarArchive(this, input); + this.setTitleSuffix(input.getName()); + } catch (Throwable e) { + new ErrorDisplay(e); + } + } else if (ap.endsWith(".class")) { + try { + file = new JarArchive(ASMUtils.getNode(Files.readAllBytes(input.toPath()))); + this.setTitleSuffix(input.getName()); + this.refreshTree(); + } catch (Throwable e) { + new ErrorDisplay(e); + } + } else { + new ErrorDisplay(new UnsupportedOperationException(res.getResource("jar_warn"))); + } + for (Plugin p : pluginManager.getPlugins()) { + p.loadFile(file.getClasses()); + } + } + + public void refreshAgentClasses() { + if (agentInstrumentation == null) { + throw new RuntimeException(); + } + this.refreshTree(); + } + + public void refreshTree() { + LOGGER.log("Building tree.."); + this.jarTree.refreshTree(file); + } + + public void saveFile(File output) { + try { + new SaveTask(this, output, file).execute(); + } catch (Throwable t) { + new ErrorDisplay(t); + } + } + + public void selectClass(ClassNode cn) { + if (ops.get("select_code_tab").getBoolean()) { + tabbedPane.setSelectedIndex(0); + } + this.currentNode = cn; + this.currentMethod = null; + sp.selectClass(cn); + clist.loadFields(cn); + tabbedPane.selectClass(cn); + lastSelectedTreeEntries.put(cn, null); + if (lastSelectedTreeEntries.size() > 5) { + lastSelectedTreeEntries.remove(lastSelectedTreeEntries.keySet().iterator().next()); + } + } + + private boolean selectEntry(MethodNode mn, DefaultTreeModel tm, SortedTreeNode node) { + for (int i = 0; i < tm.getChildCount(node); i++) { + SortedTreeNode child = (SortedTreeNode) tm.getChild(node, i); + if (child.getMn() != null && child.getMn().equals(mn)) { + TreePath tp = new TreePath(tm.getPathToRoot(child)); + jarTree.setSelectionPath(tp); + jarTree.scrollPathToVisible(tp); + return true; + } + if (!child.isLeaf()) { + if (selectEntry(mn, tm, child)) { + return true; + } + } + } + return false; + } + + public void selectMethod(ClassNode cn, MethodNode mn) { + if (ops.get("select_code_tab").getBoolean()) { + tabbedPane.setSelectedIndex(0); + } + OpUtils.clearLabelCache(); + this.currentNode = cn; + this.currentMethod = mn; + sp.selectMethod(cn, mn); + if (!clist.loadInstructions(mn)) { + clist.setSelectedIndex(-1); + } + tcblist.addNodes(cn, mn); + lvplist.addNodes(cn, mn); + cfp.setNode(mn); + dp.setText(""); + tabbedPane.selectMethod(cn, mn); + lastSelectedTreeEntries.put(cn, mn); + if (lastSelectedTreeEntries.size() > 5) { + lastSelectedTreeEntries.remove(lastSelectedTreeEntries.keySet().iterator().next()); + } + } + + public void setCFP(ControlFlowPanel cfp) { + this.cfp = cfp; + } + + public void setCodeList(MyCodeList list) { + this.clist = list; + } + + public void setDP(DecompilerPanel dp) { + this.dp = dp; + } + + private void setLVPList(LVPList lvp) { + this.lvplist = lvp; + } + + public void setPluginManager(PluginManager pluginManager) { + this.pluginManager = pluginManager; + } + + public void setSearchlist(SearchList searchList) { + this.slist = searchList; + } + + public void setSP(InfoPanel sp) { + this.sp = sp; + } + + public void setTabbedPane(MyTabbedPane tp) { + this.tabbedPane = tp; + } + + public void setTCBList(TCBList tcb) { + this.tcblist = tcb; + } + + private void setTitleSuffix(String suffix) { + this.setTitle(jbytemod + " - " + suffix); + } + + @Override + public void setVisible(boolean b) { + this.setPluginManager(new PluginManager(this)); + this.myMenuBar.addPluginMenu(pluginManager.getPlugins()); + super.setVisible(b); + } + + public void treeSelection(ClassNode cn, MethodNode mn) { + //selection may take some time + new Thread(() -> { + DefaultTreeModel tm = (DefaultTreeModel) jarTree.getModel(); + if (this.selectEntry(mn, tm, (SortedTreeNode) tm.getRoot())) { + jarTree.repaint(); + } + }).start(); + } +} diff --git a/src/main/java/me/grax/jbytemod/JarArchive.java b/src/main/java/me/grax/jbytemod/JarArchive.java new file mode 100644 index 0000000..f7228bb --- /dev/null +++ b/src/main/java/me/grax/jbytemod/JarArchive.java @@ -0,0 +1,57 @@ +package me.grax.jbytemod; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import org.objectweb.asm.tree.ClassNode; + +import me.grax.jbytemod.utils.ErrorDisplay; +import me.grax.jbytemod.utils.task.LoadTask; + +public class JarArchive { + protected Map classes; + protected Map output; + private boolean singleEntry; + + public JarArchive(ClassNode cn) { + super(); + this.classes = new HashMap<>(); + this.singleEntry = true; + classes.put(cn.name, cn); + } + + public JarArchive(JByteMod jbm, File input) { + try { + new LoadTask(jbm, input, this).execute(); + } catch (Throwable t) { + new ErrorDisplay(t); + } + } + + public JarArchive(Map classes, Map output) { + super(); + this.classes = classes; + this.output = output; + } + + public Map getClasses() { + return classes; + } + + public Map getOutput() { + return output; + } + + public boolean isSingleEntry() { + return singleEntry; + } + + public void setClasses(Map classes) { + this.classes = classes; + } + + public void setOutput(Map output) { + this.output = output; + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/block/Block.java b/src/main/java/me/grax/jbytemod/analysis/block/Block.java new file mode 100644 index 0000000..7d3311f --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/block/Block.java @@ -0,0 +1,94 @@ +package me.grax.jbytemod.analysis.block; + +import java.util.ArrayList; + +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.LookupSwitchInsnNode; +import org.objectweb.asm.tree.TableSwitchInsnNode; + +public class Block { + private ArrayList output = new ArrayList<>(); + + /** + * when output is added automatically add input + **/ + private ArrayList input = new ArrayList<>(); + + private AbstractInsnNode endNode; + private ArrayList nodes = new ArrayList<>(); + + private LabelNode label; + + private ArrayList surroundingBlocks = new ArrayList<>(); + private int depth; + + public Block() { + super(); + } + + public AbstractInsnNode getEndNode() { + return endNode; + } + + public void setEndNode(AbstractInsnNode endNode) { + this.endNode = endNode; + } + + public ArrayList getOutput() { + return output; + } + + public void setOutput(ArrayList output) { + this.output = output; + } + + public ArrayList getInput() { + return input; + } + + public void setInput(ArrayList input) { + this.input = input; + } + + public LabelNode getLabel() { + return label; + } + + public void setLabel(LabelNode label) { + this.label = label; + } + + public ArrayList getNodes() { + return nodes; + } + + public void setNodes(ArrayList nodes) { + this.nodes = nodes; + } + + public ArrayList getSurroundingBlocks() { + return surroundingBlocks; + } + + public void setSurroundingBlocks(ArrayList surroundingBlocks) { + this.surroundingBlocks = surroundingBlocks; + } + + public int getDepth() { + return depth; + } + + public void setDepth(int depth) { + this.depth = depth; + } + + public boolean endsWithJump() { + return endNode instanceof JumpInsnNode; + } + + public boolean endsWithSwitch() { + return endNode instanceof TableSwitchInsnNode || endNode instanceof LookupSwitchInsnNode; + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/converter/Converter.java b/src/main/java/me/grax/jbytemod/analysis/converter/Converter.java new file mode 100644 index 0000000..dd192f6 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/converter/Converter.java @@ -0,0 +1,273 @@ +package me.grax.jbytemod.analysis.converter; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.LookupSwitchInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.TableSwitchInsnNode; + +import me.grax.jbytemod.analysis.block.Block; +import me.lpk.util.OpUtils; + +public class Converter implements Opcodes { + + private ArrayList nodes; + private static final boolean DEBUG = false; + + public Converter(MethodNode mn) { + assert (mn.instructions != null && mn.instructions.size() > 0); + this.nodes = new ArrayList<>(Arrays.asList(mn.instructions.toArray())); + } + + public Converter(AbstractInsnNode[] array) { + assert (array != null && array.length > 0); + this.nodes = new ArrayList<>(Arrays.asList(array)); + } + + public ArrayList convert(boolean simplify, boolean removeRedundant, boolean skipDupeSwitches, int maxInputRemoveNonsense) { + ArrayList blocks = new ArrayList<>(); + HashMap correspBlock = new HashMap<>(); + Block block = null; + if (nodes.isEmpty()) { + return blocks; + } + //detect block structure & last block insns + for (AbstractInsnNode ain : nodes) { + if (block == null) { + block = new Block(); + } + if (ain instanceof LabelNode) { + block.setLabel((LabelNode) ain); + } + block.getNodes().add(ain); + correspBlock.put(ain, block); + //end blocks + int op = ain.getOpcode(); + if (op >= IRETURN && op <= RETURN || ain instanceof JumpInsnNode || op == ATHROW || op == LOOKUPSWITCH || op == TABLESWITCH) { + block.setEndNode(ain); + blocks.add(block); + block = null; + continue; + } + //next because the label should have a new block + //blocks that end without a jump + if (ain.getNext() != null && (ain.getNext() instanceof LabelNode)) { + block.setEndNode(ain.getNext()); + blocks.add(block); + block = null; + continue; + } + } + for (Block b : blocks) { + AbstractInsnNode end = b.getEndNode(); + //only opc where it continues + if (end instanceof JumpInsnNode) { + JumpInsnNode jin = (JumpInsnNode) end; + ArrayList outputs = new ArrayList<>(); + if (!correspBlock.containsKey(jin.label)) { + throw new RuntimeException("label not visited"); + } + Block blockAtLabel = correspBlock.get(jin.label); + //blockAtLabel can be the same block! + if (end.getOpcode() == GOTO) { + outputs.add(blockAtLabel); + b.setOutput(outputs); + blockAtLabel.getInput().add(b); + } else { + //ifs have two outputs: either it jumps or not + outputs.add(blockAtLabel); + if (jin.getNext() == null) { + throw new RuntimeException("if has no next entry"); + } + if (correspBlock.get(jin.getNext()) == b) { + throw new RuntimeException("next node is self?"); + } + Block blockAfter = correspBlock.get(jin.getNext()); + outputs.add(blockAfter); + b.setOutput(outputs); + blockAtLabel.getInput().add(b); + blockAfter.getInput().add(b); + } + } else if (end instanceof TableSwitchInsnNode) { + ArrayList outputs = new ArrayList<>(); + TableSwitchInsnNode tsin = (TableSwitchInsnNode) end; + if (tsin.dflt != null) { + Block blockAtDefault = correspBlock.get(tsin.dflt); + blockAtDefault.getInput().add(b); + outputs.add(blockAtDefault); + } + ArrayList alreadyConnected = new ArrayList<>(); + for (LabelNode l : tsin.labels) { + if (skipDupeSwitches) { + if (alreadyConnected.contains(l)) + continue; + alreadyConnected.add(l); + } + Block blockAtCase = correspBlock.get(l); + blockAtCase.getInput().add(b); + outputs.add(blockAtCase); + } + b.setOutput(outputs); + } else if (end instanceof LookupSwitchInsnNode) { + ArrayList outputs = new ArrayList<>(); + LookupSwitchInsnNode lsin = (LookupSwitchInsnNode) end; + if (lsin.dflt != null) { + Block blockAtDefault = correspBlock.get(lsin.dflt); + blockAtDefault.getInput().add(b); + outputs.add(blockAtDefault); + } + ArrayList alreadyConnected = new ArrayList<>(); + for (LabelNode l : lsin.labels) { + if (skipDupeSwitches) { + if (alreadyConnected.contains(l)) + continue; + alreadyConnected.add(l); + } + Block blockAtCase = correspBlock.get(l); + blockAtCase.getInput().add(b); + outputs.add(blockAtCase); + } + b.setOutput(outputs); + } else if (end instanceof LabelNode) { + if (!correspBlock.containsKey(end)) { + throw new RuntimeException("label not visited"); + } + ArrayList outputs = new ArrayList<>(); + Block blockAtNext = correspBlock.get(end); + outputs.add(blockAtNext); + b.setOutput(outputs); + blockAtNext.getInput().add(b); + } + } + Block first = correspBlock.get(nodes.get(0)); + assert (first != null); + if (removeRedundant) { + ArrayList visited = new ArrayList<>(); + removeNonsense(visited, blocks, first, maxInputRemoveNonsense); + for (Block b : new ArrayList<>(blocks)) { + if (b.getInput().isEmpty()) { + removeNonsense(visited, blocks, b, maxInputRemoveNonsense); + } + } + } + if (simplify) { + ArrayList visited = new ArrayList<>(); + simplifyBlock(visited, blocks, first); + for (Block b : new ArrayList<>(blocks)) { + if (b.getInput().isEmpty()) { + simplifyBlock(visited, blocks, b); + } + } + } + if (DEBUG) { + ArrayList visited = new ArrayList<>(); + calculateDepths(visited, blocks, first, 0); + for (Block b : blocks) { + if (b.getInput().isEmpty()) { + calculateDepths(visited, blocks, b, 0); + } + } + } + return blocks; + } + + private void calculateDepths(ArrayList visited, ArrayList blocks, Block b, int depth) { + if (visited.contains(b)) { + return; + } + visited.add(b); + b.setDepth(depth); + if (b.endsWithJump()) { + if (b.getOutput().size() > 1) { + if (b.getInput().size() <= 1) { + //handle if surrounding + Block blockAtLabel = b.getOutput().get(0); + Block blockAfter = b.getOutput().get(1); + calculateDepths(visited, blocks, blockAtLabel, depth); + calculateDepths(visited, blocks, blockAfter, depth + 1); + } else { + //handle while surrounding + Block blockAtLabel = b.getOutput().get(0); + Block blockAfter = b.getOutput().get(1); + calculateDepths(visited, blocks, blockAfter, depth); + calculateDepths(visited, blocks, blockAtLabel, depth + 1); + } + } + } + for (Block output : b.getOutput()) { + calculateDepths(visited, blocks, output, depth); + } + } + + private void removeNonsense(ArrayList visited, ArrayList blocks, Block b, int maxInputRemoveNonsense) { + if (visited.contains(b)) { + return; + } + visited.add(b); + if (b.endsWithJump()) { + if (b.getInput().size() <= maxInputRemoveNonsense && b.getOutput().size() == 1) { //there could be more inputs but that might lead to a unreadable graph + if (isJumpBlock(b)) { + Block output = b.getOutput().get(0); + for (Block input : b.getInput()) { + input.getOutput().remove(b); + input.getOutput().add(output); + output.getInput().add(input); + } + output.getInput().remove(b); + } + } + } + for (Block output : new ArrayList<>(b.getOutput())) { + removeNonsense(visited, blocks, output, maxInputRemoveNonsense); + } + } + + private boolean isJumpBlock(Block b) { + for (AbstractInsnNode ain : b.getNodes()) { + int type = ain.getType(); + if (type != AbstractInsnNode.LABEL && type != AbstractInsnNode.LINE && type != AbstractInsnNode.FRAME && type != AbstractInsnNode.JUMP_INSN) { + return false; + } + } + return true; + } + + private void simplifyBlock(ArrayList simplified, ArrayList blocks, Block b) { + if (simplified.contains(b)) { + return; + } + simplified.add(b); + while (true) { + if (b.getOutput().size() == 1) { + Block to = b.getOutput().get(0); + //also optimizes unnecessary gotos + if (to.getInput().size() == 1 && !isFirst(to)) { + assert (to.getInput().get(0) == b); + b.getNodes().addAll(to.getNodes()); + b.setEndNode(to.getEndNode()); + b.setOutput(to.getOutput()); + blocks.remove(to); + continue; + } + } + break; + } + for (Block output : b.getOutput()) { + simplifyBlock(simplified, blocks, output); + } + } + + private boolean isFirst(Block to) { + LabelNode ln = to.getLabel(); + if (ln != null && OpUtils.getLabelIndex(ln) == 0) { + return true; + } + return false; + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/ClassDefinition.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/ClassDefinition.java new file mode 100644 index 0000000..01f02f9 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/ClassDefinition.java @@ -0,0 +1,33 @@ +package me.grax.jbytemod.analysis.decompiler; + +public class ClassDefinition { + private String name; + + public ClassDefinition(String name) { + super(); + if (name.startsWith("L") && name.endsWith(";")) { + this.name = name.substring(1, name.length() - 1); + } else { + this.name = name; + } + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getShortName() { + if (!name.contains("/")) { + return name; + } + return name.substring(name.lastIndexOf("/") + 1); + } + + public String getSourceName() { + return name.replace('/', '.'); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/TabbedStringBuffer.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/TabbedStringBuffer.java new file mode 100644 index 0000000..db5f916 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/TabbedStringBuffer.java @@ -0,0 +1,21 @@ +package me.grax.jbytemod.analysis.decompiler.code; + +public class TabbedStringBuffer { + public int tabs; + private StringBuilder sb = new StringBuilder(); + + public void append(String s) { + sb.append(s); + } + + public void indent() { + for (int i = 0; i < tabs; i++) { + sb.append(" "); + } + } + + @Override + public String toString() { + return sb.toString(); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/AstColors.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/AstColors.java new file mode 100644 index 0000000..cc00953 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/AstColors.java @@ -0,0 +1,12 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast; + +public class AstColors { + public static final String edgeColor = "#111111"; + public static final String jumpColor = "#39698a"; + + public static final String jumpColorGreen = "#388a47"; + public static final String jumpColorRed = "#8a3e38"; + public static final String jumpColorPurple = "#71388a"; + public static final String jumpColorPink = "#ba057a"; //8a386d + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/Comparison.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/Comparison.java new file mode 100644 index 0000000..86fa4fe --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/Comparison.java @@ -0,0 +1,19 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast; + +public enum Comparison { + IS("=="), ISNOT("!="), LOWER("<"), LOWEREQUALS("<="), GREATER(">"), GREATEREQUALS(">="); + + private String symbol; + + private Comparison(String symbol) { + this.symbol = symbol; + } + + public String getSymbol() { + return symbol; + } + + public void setSymbol(String symbol) { + this.symbol = symbol; + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/EndBlock.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/EndBlock.java new file mode 100644 index 0000000..ccd90e6 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/EndBlock.java @@ -0,0 +1,5 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast; + +public enum EndBlock { + CONTINUE, BREAK; +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/Expression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/Expression.java new file mode 100644 index 0000000..eddcce2 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/Expression.java @@ -0,0 +1,9 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast; + +public abstract class Expression { + public abstract String toString(); + + public abstract int size(); + + public abstract Expression clone(); +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/Operation.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/Operation.java new file mode 100644 index 0000000..5b55d95 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/Operation.java @@ -0,0 +1,75 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast; + +import org.objectweb.asm.Opcodes; + +public enum Operation implements Opcodes { + ADD("+"), SUB("-"), MUL("*"), DIV("/"), REM("%"), SHL("<<"), SHR(">>"), USHR(">>>"), AND("&"), OR("|"), XOR("^"), NEG("-"); + + private String symbol; + + Operation(String symbol) { + this.symbol = symbol; + } + + public String getSymbol() { + return symbol; + } + + public void setSymbol(String symbol) { + this.symbol = symbol; + } + + public static Operation of(int opc) { + switch (opc) { + case IADD: + case DADD: + case FADD: + case LADD: + return Operation.ADD; + case ISUB: + case FSUB: + case LSUB: + case DSUB: + return Operation.SUB; + case IMUL: + case FMUL: + case LMUL: + case DMUL: + return Operation.MUL; + case IDIV: + case FDIV: + case LDIV: + case DDIV: + return Operation.DIV; + case IREM: + case FREM: + case LREM: + case DREM: + return Operation.REM; + case ISHL: + case LSHL: + return Operation.SHL; + case ISHR: + case LSHR: + return Operation.SHR; + case IUSHR: + case LUSHR: + return Operation.USHR; + case IAND: + case LAND: + return Operation.AND; + case IOR: + case LOR: + return Operation.OR; + case IXOR: + case LXOR: + return Operation.XOR; + case INEG: + case FNEG: + case LNEG: + case DNEG: + return Operation.NEG; + } + throw new RuntimeException("unresolved operation"); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/VarType.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/VarType.java new file mode 100644 index 0000000..aa8e101 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/VarType.java @@ -0,0 +1,49 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast; + +public enum VarType { + INT("int"), FLOAT("float"), LONG("long"), DOUBLE("double"), OBJECT("Object"), VOID("void"), BOOLEAN("boolean"), CHAR("char"), BYTE("byte"), SHORT( + "short"); + private String type; + + VarType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public int size() { + return (this == VarType.LONG || this == VarType.DOUBLE) ? 2 : 1; + } + + public static VarType ofDesc(String desc) { + if (desc.contains(")")) { + desc = desc.substring(desc.lastIndexOf(')') + 1); + } + if (desc.endsWith(";") || desc.contains("[")) + return OBJECT; + if (desc.endsWith("V")) + return VOID; + if (desc.endsWith("F")) + return FLOAT; + if (desc.endsWith("J")) + return LONG; + if (desc.endsWith("D")) + return DOUBLE; + if (desc.endsWith("Z")) + return BOOLEAN; + if (desc.endsWith("C")) + return CHAR; + if (desc.endsWith("B")) + return BYTE; + if (desc.endsWith("S")) + return SHORT; + return INT; + } + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ArrayIndexExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ArrayIndexExpression.java new file mode 100644 index 0000000..64cead2 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ArrayIndexExpression.java @@ -0,0 +1,34 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.utils.InstrUtils; +import me.grax.jbytemod.utils.TextUtils; + +public class ArrayIndexExpression extends Expression { + + private Expression array; + private Expression index; + private boolean twoword; + + public ArrayIndexExpression(Expression array, Expression index, boolean twoword) { + super(); + this.array = array; + this.index = index; + this.twoword = twoword; + } + + @Override + public String toString() { + return TextUtils.addTag(array.toString(), "font color=" + InstrUtils.primColor.getString()) + "[" + index + "]"; + } + + @Override + public int size() { + return twoword ? 2 : 1; + } + + @Override + public Expression clone() { + return new ArrayIndexExpression(array.clone(), index.clone(), twoword); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ArrayStoreExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ArrayStoreExpression.java new file mode 100644 index 0000000..5f8b264 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ArrayStoreExpression.java @@ -0,0 +1,34 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.utils.InstrUtils; +import me.grax.jbytemod.utils.TextUtils; + +public class ArrayStoreExpression extends Expression { + private Expression array; + private Expression index; + private Expression value; + + public ArrayStoreExpression(Expression array, Expression index, Expression value) { + super(); + this.array = array; + this.index = index; + this.value = value; + + } + + @Override + public String toString() { + return TextUtils.addTag(array.toString(), "font color=" + InstrUtils.primColor.getString()) + "[" + index + "]" + " = " + value; + } + + @Override + public int size() { + return 0; + } + + @Override + public Expression clone() { + return new ArrayStoreExpression(array.clone(), index.clone(), value.clone()); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/CastExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/CastExpression.java new file mode 100644 index 0000000..5adb294 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/CastExpression.java @@ -0,0 +1,71 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.ClassDefinition; +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.analysis.decompiler.code.ast.VarType; + +public class CastExpression extends Expression { + private ClassDefinition cast; + private Expression object; + private VarType typeCast; + + public CastExpression(ClassDefinition cast, Expression object) { + super(); + this.cast = cast; + this.object = object; + } + + public CastExpression(VarType typeCast, Expression object) { + super(); + this.typeCast = typeCast; + this.object = object; + } + + public ClassDefinition getCast() { + return cast; + } + + public void setCast(ClassDefinition cast) { + this.cast = cast; + } + + public Expression getObject() { + return object; + } + + public void setObject(Expression object) { + this.object = object; + } + + public VarType getTypeCast() { + return typeCast; + } + + public void setTypeCast(VarType typeCast) { + this.typeCast = typeCast; + } + + @Override + public String toString() { + if (typeCast != null) { + return "((" + typeCast.getType() + ") " + object + ")"; + } + return "((" + cast.getShortName() + ") " + object + ")"; + } + + @Override + public int size() { + if (typeCast != null) { + return typeCast.size(); + } + return 1; + } + + @Override + public Expression clone() { + if (typeCast != null) { + return new CastExpression(typeCast, object.clone()); + } + return new CastExpression(new ClassDefinition(cast.getName()), object.clone()); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ClassTypeExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ClassTypeExpression.java new file mode 100644 index 0000000..358c94e --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ClassTypeExpression.java @@ -0,0 +1,27 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; + +public class ClassTypeExpression extends Expression { + + private String object; + + public ClassTypeExpression(String object) { + this.object = object; + } + + @Override + public String toString() { + return object + ".class"; + } + + @Override + public int size() { + return 1; + } + + @Override + public Expression clone() { + return new ClassTypeExpression(object); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ComparisonExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ComparisonExpression.java new file mode 100644 index 0000000..142ecee --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ComparisonExpression.java @@ -0,0 +1,58 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Comparison; +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.utils.TextUtils; + +public class ComparisonExpression extends Expression { + + private Expression left; + private Comparison comparison; + private Expression right; + + public ComparisonExpression(Expression left, Comparison comparison, Expression right) { + super(); + this.left = left; + this.comparison = comparison; + this.right = right; + } + + public Expression getLeft() { + return left; + } + + public void setLeft(Expression left) { + this.left = left; + } + + public Comparison getComparison() { + return comparison; + } + + public void setComparison(Comparison comparison) { + this.comparison = comparison; + } + + public Expression getRight() { + return right; + } + + public void setRight(Expression right) { + this.right = right; + } + + @Override + public String toString() { + return "if " + left.toString() + " " + TextUtils.escape(comparison.getSymbol()) + " " + right.toString() + ""; + } + + @Override + public int size() { + return 1; + } + + @Override + public Expression clone() { + return new ComparisonExpression(left.clone(), comparison, right.clone()); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/DebugStackAssignExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/DebugStackAssignExpression.java new file mode 100644 index 0000000..694bf75 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/DebugStackAssignExpression.java @@ -0,0 +1,45 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.utils.TextUtils; + +public class DebugStackAssignExpression extends Expression { + + private int var; + private Expression value; + private String prefix; + + public DebugStackAssignExpression(int var, Expression value) { + this(var, value, "stack"); + } + + public DebugStackAssignExpression(int var, Expression value, String prefix) { + this.var = var; + this.value = value; + this.prefix = prefix; + } + + @Override + public String toString() { + return TextUtils.addTag("" + prefix + var + "", "font color=#909011") + " = " + value; + } + + @Override + public int size() { + return 0; + } + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + @Override + public Expression clone() { + return new DebugStackAssignExpression(var, value.clone(), prefix); + } + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/DebugStackExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/DebugStackExpression.java new file mode 100644 index 0000000..220b5f5 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/DebugStackExpression.java @@ -0,0 +1,72 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.analysis.decompiler.code.ast.VarType; +import me.grax.jbytemod.utils.TextUtils; + +public class DebugStackExpression extends Expression { + + private int var; + private int size; + private VarType type; + private String prefix; + + public DebugStackExpression(int var, int size, VarType type) { + this(var, size, type, "stack"); + } + + public DebugStackExpression(int var, int size, VarType type, String prefix) { + this.var = var; + this.size = size; + this.type = type; + this.prefix = prefix; + } + + @Override + public String toString() { + return TextUtils.addTag("" + prefix + var + "", "font color=#909011"); + } + + @Override + public int size() { + return size; + } + + @Override + public Expression clone() { + return new DebugStackExpression(var, size, type, prefix); + } + + public int getVar() { + return var; + } + + public void setVar(int var) { + this.var = var; + } + + public int getSize() { + return size; + } + + public void setSize(int size) { + this.size = size; + } + + public VarType getType() { + return type; + } + + public void setType(VarType type) { + this.type = type; + } + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/DebugStackUnknownExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/DebugStackUnknownExpression.java new file mode 100644 index 0000000..03ec2e0 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/DebugStackUnknownExpression.java @@ -0,0 +1,58 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.analysis.decompiler.code.ast.VarType; +import me.grax.jbytemod.utils.TextUtils; + +public class DebugStackUnknownExpression extends Expression { + + private int var; + private int size; + private VarType type; + + public DebugStackUnknownExpression(int var, int size, VarType type) { + this.var = var; + this.size = size; + this.type = type; + } + + @Override + public String toString() { + return TextUtils.addTag("unkn_stack_" + var + "", "font color=#997755"); + } + + @Override + public int size() { + return size; + } + + @Override + public Expression clone() { + return new DebugStackUnknownExpression(var, size, type); + } + + public int getVar() { + return var; + } + + public void setVar(int var) { + this.var = var; + } + + public int getSize() { + return size; + } + + public void setSize(int size) { + this.size = size; + } + + public VarType getType() { + return type; + } + + public void setType(VarType type) { + this.type = type; + } + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/FieldAssignExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/FieldAssignExpression.java new file mode 100644 index 0000000..9853af6 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/FieldAssignExpression.java @@ -0,0 +1,105 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.ClassDefinition; +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.analysis.decompiler.code.ast.VarType; +import me.grax.jbytemod.utils.InstrUtils; +import me.grax.jbytemod.utils.TextUtils; + +public class FieldAssignExpression extends Expression { + private Expression owner; + private ClassDefinition staticOwner; + + private String name; + private VarType type; + private Expression value; + + public FieldAssignExpression(Expression owner, String name, VarType type, Expression value) { + super(); + this.owner = owner; + this.name = name; + this.type = type; + this.value = value; + } + + public FieldAssignExpression(ClassDefinition staticOwner, String name, VarType type, Expression value) { + super(); + this.staticOwner = staticOwner; + this.name = name; + this.type = type; + this.value = value; + } + + public boolean isStatic() { + return owner == null; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + if (owner == null) { + sb.append(TextUtils.addTag(staticOwner.getName(), "font color=" + InstrUtils.secColor.getString())); + } else { + sb.append(TextUtils.addTag(owner.toString(), "font color=" + InstrUtils.secColor.getString())); + } + sb.append("."); + sb.append(TextUtils.addTag(name, "font color=" + InstrUtils.primColor.getString())); + sb.append(" = "); + sb.append(value.toString()); + return sb.toString(); + } + + public Expression getOwner() { + return owner; + } + + public void setOwner(Expression owner) { + this.owner = owner; + } + + public ClassDefinition getStaticOwner() { + return staticOwner; + } + + public void setStaticOwner(ClassDefinition staticOwner) { + this.staticOwner = staticOwner; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public VarType getType() { + return type; + } + + public void setType(VarType type) { + this.type = type; + } + + public Expression getValue() { + return value; + } + + public void setValue(Expression value) { + this.value = value; + } + + @Override + public int size() { + return 0; + } + + @Override + public Expression clone() { + if (owner != null) { + return new FieldAssignExpression(owner.clone(), name, type, value.clone()); + } else { + return new FieldAssignExpression(new ClassDefinition(staticOwner.getName()), name, type, value.clone()); + } + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/FieldExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/FieldExpression.java new file mode 100644 index 0000000..e94d81e --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/FieldExpression.java @@ -0,0 +1,94 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.ClassDefinition; +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.analysis.decompiler.code.ast.VarType; +import me.grax.jbytemod.utils.InstrUtils; +import me.grax.jbytemod.utils.TextUtils; + +public class FieldExpression extends Expression { + + private Expression owner; + private ClassDefinition staticOwner; + + private String fieldName; + private VarType returnType; + + public FieldExpression(Expression owner, String fieldName, VarType returnType) { + super(); + this.owner = owner; + this.fieldName = fieldName; + this.returnType = returnType; + } + + public FieldExpression(ClassDefinition staticOwner, String fieldName, VarType returnType) { + super(); + this.staticOwner = staticOwner; + this.fieldName = fieldName; + this.returnType = returnType; + } + + public Expression getOwner() { + return owner; + } + + public void setOwner(Expression owner) { + this.owner = owner; + } + + public ClassDefinition getStaticOwner() { + return staticOwner; + } + + public void setStaticOwner(ClassDefinition staticOwner) { + this.staticOwner = staticOwner; + } + + public String getFieldName() { + return fieldName; + } + + public void setFieldName(String fieldName) { + this.fieldName = fieldName; + } + + public VarType getReturnType() { + return returnType; + } + + public void setReturnType(VarType returnType) { + this.returnType = returnType; + } + + public boolean isStatic() { + return owner == null; + } + + @Override + public String toString() { + boolean isStatic = isStatic(); + StringBuilder sb = new StringBuilder(); + if (isStatic) { + sb.append(TextUtils.addTag(staticOwner.getName(), "font color=" + InstrUtils.secColor.getString())); + } else { + sb.append(owner.toString()); + } + sb.append("."); + sb.append(TextUtils.addTag(fieldName, "font color=" + InstrUtils.primColor.getString())); + return sb.toString(); + } + + @Override + public int size() { + return returnType.size(); + } + + @Override + public Expression clone() { + if (owner != null) { + return new FieldExpression(owner.clone(), fieldName, returnType); + } else { + return new FieldExpression(new ClassDefinition(staticOwner.getName()), fieldName, returnType); + } + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/IncrementExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/IncrementExpression.java new file mode 100644 index 0000000..b966aa7 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/IncrementExpression.java @@ -0,0 +1,39 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.utils.InstrUtils; +import me.grax.jbytemod.utils.TextUtils; + +public class IncrementExpression extends Expression { + private Expression object; + private int increment; + + public IncrementExpression(Expression object, int increment) { + super(); + this.object = object; + this.increment = increment; + } + + public Expression getObject() { + return object; + } + + public void setObject(Expression object) { + this.object = object; + } + + @Override + public String toString() { + return TextUtils.addTag(object.toString(), "font color=" + InstrUtils.primColor.getString()) + " += " + increment; + } + + @Override + public int size() { + return 0; + } + + @Override + public Expression clone() { + return new IncrementExpression(object.clone(), increment); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/InstanceofExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/InstanceofExpression.java new file mode 100644 index 0000000..aaf3b87 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/InstanceofExpression.java @@ -0,0 +1,31 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.ClassDefinition; +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; + +public class InstanceofExpression extends Expression { + + private Expression object; + private ClassDefinition classDef; + + public InstanceofExpression(Expression object, ClassDefinition classDef) { + super(); + this.object = object; + this.classDef = classDef; + } + + @Override + public String toString() { + return object.toString() + " instanceof " + classDef.getName(); + } + + @Override + public int size() { + return 1; + } + + @Override + public Expression clone() { + return new InstanceofExpression(object.clone(), classDef); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/InvokeDynamicExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/InvokeDynamicExpression.java new file mode 100644 index 0000000..d54bdf5 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/InvokeDynamicExpression.java @@ -0,0 +1,84 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.objectweb.asm.Handle; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.utils.InstrUtils; +import me.grax.jbytemod.utils.TextUtils; + +public class InvokeDynamicExpression extends Expression { + + private String name; + private String desc; + private Object[] bsmArgs; + private Handle bsm; + private Handle methodHandle; + private List args; + + public InvokeDynamicExpression(String name, String desc, Object[] bsmArgs, Handle bsm) { + this.methodHandle = getMethodHandle(bsmArgs); + this.name = name; + this.desc = desc; + this.bsmArgs = bsmArgs; + this.bsm = bsm; + } + + private Handle getMethodHandle(Object[] bsmArgs) { + for (Object o : bsmArgs) { + if (o instanceof Handle) { + return (Handle) o; + } + } + return null; + } + + public Handle getMethodHandle() { + return methodHandle; + } + + public List getArgs() { + return args; + } + + public void setArgs(List args) { + this.args = args; + } + + @Override + public String toString() { + if (methodHandle != null) { + StringBuilder sb = new StringBuilder(); + sb.append(TextUtils.addTag(methodHandle.getOwner(), "font color=" + InstrUtils.secColor.getString())); + sb.append("."); + sb.append(TextUtils.addTag(TextUtils.escape(methodHandle.getName()), "font color=#8855aa")); + sb.append("("); + if (args != null) { + ArrayList argsString = new ArrayList<>(); + for (Expression ref : args) { + argsString.add(ref.toString()); + } + sb.append(String.join(", ", argsString)); + } else { + sb.append(TextUtils.escape(methodHandle.getDesc())); + } + sb.append(")"); + return sb.toString(); + } + return "invokedynamic(" + name + " " + desc + " " + Arrays.toString(bsmArgs) + " " + bsm.getOwner() + "." + bsm.getName() + bsm.getDesc() + + ")"; + } + + @Override + public int size() { + return 1; + } + + @Override + public Expression clone() { + return new InvokeDynamicExpression(name, desc, bsmArgs, bsm); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/LookupSwitchExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/LookupSwitchExpression.java new file mode 100644 index 0000000..fb2eabd --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/LookupSwitchExpression.java @@ -0,0 +1,29 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; + +public class LookupSwitchExpression extends Expression { + + private Expression toSwitch; + private int size; + + public LookupSwitchExpression(Expression toSwitch, int size) { + this.toSwitch = toSwitch; + this.size = size; + } + + @Override + public String toString() { + return "switch(" + toSwitch + ") " + size + " cases"; + } + + @Override + public int size() { + return 1; + } + + @Override + public Expression clone() { + return new LookupSwitchExpression(toSwitch.clone(), size); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/MethodExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/MethodExpression.java new file mode 100644 index 0000000..83abe6d --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/MethodExpression.java @@ -0,0 +1,119 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import java.util.ArrayList; +import java.util.List; + +import me.grax.jbytemod.analysis.decompiler.ClassDefinition; +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.analysis.decompiler.code.ast.VarType; +import me.grax.jbytemod.utils.InstrUtils; +import me.grax.jbytemod.utils.TextUtils; + +public class MethodExpression extends Expression { + + private Expression invokeOn; + private ClassDefinition staticOwner; + + private String methodName; + private List args; + private VarType returnType; + + public MethodExpression(Expression invokeOn, String methodName, List args, VarType returnType) { + super(); + this.invokeOn = invokeOn; + this.methodName = methodName; + this.args = args; + this.returnType = returnType; + } + + public MethodExpression(ClassDefinition staticOwner, String methodName, List args, VarType returnType) { + super(); + this.staticOwner = staticOwner; + this.methodName = methodName; + this.args = args; + this.returnType = returnType; + } + + @Override + public String toString() { + boolean isStatic = isStatic(); + StringBuilder sb = new StringBuilder(); + if (isStatic) { + sb.append(TextUtils.addTag(staticOwner.getName(), "font color=" + InstrUtils.secColor.getString())); + } else { + sb.append(invokeOn.toString()); + } + sb.append("."); + sb.append(TextUtils.addTag(TextUtils.escape(methodName), "font color=#8855aa")); + sb.append("("); + ArrayList argsString = new ArrayList<>(); + for (Expression ref : args) { + argsString.add(ref.toString()); + } + sb.append(String.join(", ", argsString)); + sb.append(")"); + return sb.toString(); + } + + public boolean isStatic() { + return invokeOn == null; + } + + public Expression getInvokeOn() { + return invokeOn; + } + + public void setInvokeOn(Expression invokeOn) { + this.invokeOn = invokeOn; + } + + public ClassDefinition getStaticOwner() { + return staticOwner; + } + + public void setStaticOwner(ClassDefinition staticOwner) { + this.staticOwner = staticOwner; + } + + public String getMethodName() { + return methodName; + } + + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + public List getArgs() { + return args; + } + + public void setArgs(List args) { + this.args = args; + } + + public VarType getReturnType() { + return returnType; + } + + public void setReturnType(VarType returnType) { + this.returnType = returnType; + } + + @Override + public int size() { + return returnType.size(); + } + + @Override + public Expression clone() { + ArrayList clonedArgs = new ArrayList<>(); + for (Expression arg : args) { + clonedArgs.add(arg); + } + if (invokeOn != null) { + return new MethodExpression(invokeOn.clone(), methodName, clonedArgs, returnType); + } else { + return new MethodExpression(new ClassDefinition(staticOwner.getName()), methodName, clonedArgs, returnType); + } + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NewArrayExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NewArrayExpression.java new file mode 100644 index 0000000..7badf08 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NewArrayExpression.java @@ -0,0 +1,32 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.ClassDefinition; +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.utils.InstrUtils; +import me.grax.jbytemod.utils.TextUtils; + +public class NewArrayExpression extends Expression { + private Expression count; + private ClassDefinition object; + + public NewArrayExpression(Expression count, ClassDefinition object) { + super(); + this.count = count; + this.object = object; + } + + @Override + public String toString() { + return "new " + TextUtils.addTag(object.getName(), "font color=" + InstrUtils.secColor.getString()) + "[" + count + "]"; + } + + @Override + public int size() { + return 1; + } + + @Override + public Expression clone() { + return new NewArrayExpression(count.clone(), object); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NewPrimArrayExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NewPrimArrayExpression.java new file mode 100644 index 0000000..a0f35e7 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NewPrimArrayExpression.java @@ -0,0 +1,32 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.analysis.decompiler.code.ast.VarType; +import me.grax.jbytemod.utils.InstrUtils; +import me.grax.jbytemod.utils.TextUtils; + +public class NewPrimArrayExpression extends Expression { + private Expression count; + private VarType type; + + public NewPrimArrayExpression(Expression count, VarType type) { + super(); + this.count = count; + this.type = type; + } + + @Override + public String toString() { + return "new " + TextUtils.addTag(type.getType(), "font color=" + InstrUtils.secColor.getString()) + "[" + count + "]"; + } + + @Override + public int size() { + return 1; + } + + @Override + public Expression clone() { + return new NewPrimArrayExpression(count.clone(), type); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NewTypeExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NewTypeExpression.java new file mode 100644 index 0000000..54931b3 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NewTypeExpression.java @@ -0,0 +1,57 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import java.util.ArrayList; + +import me.grax.jbytemod.analysis.decompiler.ClassDefinition; +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.utils.InstrUtils; +import me.grax.jbytemod.utils.TextUtils; + +public class NewTypeExpression extends Expression { + private ClassDefinition object; + private MethodExpression init; + + public NewTypeExpression(ClassDefinition object) { + super(); + this.object = object; + } + + @Override + public String toString() { + if (init != null) { + StringBuilder sb = new StringBuilder(); + sb.append("new " + TextUtils.addTag(object.getName(), "font color=" + InstrUtils.secColor.getString())); + sb.append("("); + ArrayList argsString = new ArrayList<>(); + for (Expression ref : init.getArgs()) { + argsString.add(ref.toString()); + } + sb.append(String.join(", ", argsString)); + sb.append(")"); + return sb.toString(); + } + return "new " + TextUtils.addTag(object.getName(), "font color=" + InstrUtils.secColor.getString()); + } + + @Override + public int size() { + return 1; + } + + public Expression getInit() { + return init; + } + + public void setInit(MethodExpression init) { + this.init = init; + } + + @Override + public Expression clone() { + NewTypeExpression nte = new NewTypeExpression(object); + if (init != null) { + nte.setInit((MethodExpression) init.clone()); + } + return nte; + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NotExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NotExpression.java new file mode 100644 index 0000000..ba07116 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NotExpression.java @@ -0,0 +1,36 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; + +public class NotExpression extends Expression { + private Expression toNegate; + + public NotExpression(Expression toNegate) { + super(); + this.toNegate = toNegate; + } + + public Expression getToNegate() { + return toNegate; + } + + public void setToNegate(Expression toNegate) { + this.toNegate = toNegate; + } + + @Override + public String toString() { + return "!(" + toNegate.toString() + ")"; + } + + @Override + public int size() { + return toNegate.size(); + } + + @Override + public Expression clone() { + return new NotExpression(toNegate.clone()); + } + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NullExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NullExpression.java new file mode 100644 index 0000000..719ec07 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/NullExpression.java @@ -0,0 +1,23 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.analysis.decompiler.defs.Keywords; + +public class NullExpression extends Expression { + + @Override + public String toString() { + return "" + Keywords.NULL + ""; + } + + @Override + public int size() { + return 1; + } + + @Override + public Expression clone() { + return new NullExpression(); + } + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/OpExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/OpExpression.java new file mode 100644 index 0000000..5e0fad0 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/OpExpression.java @@ -0,0 +1,60 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.analysis.decompiler.code.ast.Operation; +import me.grax.jbytemod.analysis.decompiler.code.ast.VarType; +import me.grax.jbytemod.utils.TextUtils; + +public class OpExpression extends Expression { + protected Expression left; + private Expression right; + protected Operation op; + protected VarType returnType; + + public OpExpression(Expression left, Expression right, Operation op, VarType returnType) { + super(); + this.left = left; + this.right = right; + this.op = op; + this.returnType = returnType; + } + + public Expression getLeft() { + return left; + } + + public void setLeft(Expression left) { + this.left = left; + } + + public Expression getRight() { + return right; + } + + public void setRight(Expression right) { + this.right = right; + } + + public Operation getOp() { + return op; + } + + public void setOp(Operation op) { + this.op = op; + } + + @Override + public String toString() { + return left.toString() + " " + TextUtils.escape(op.getSymbol()) + " " + right.toString(); + } + + @Override + public int size() { + return returnType.size(); //right side defines the size + } + + @Override + public Expression clone() { + return new OpExpression(left.clone(), right.clone(), op, returnType); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ReturnExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ReturnExpression.java new file mode 100644 index 0000000..3f4c00b --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ReturnExpression.java @@ -0,0 +1,40 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.analysis.decompiler.defs.Keywords; + +public class ReturnExpression extends Expression { + + private Expression returnValue; + + public ReturnExpression(Expression returnValue) { + super(); + this.returnValue = returnValue; + } + + public ReturnExpression() { + super(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("" + Keywords.RETURN + ""); + if (returnValue != null) { + sb.append(" "); + sb.append(returnValue); + } + return sb.toString(); + } + + @Override + public int size() { + return 0; + } + + @Override + public Expression clone() { + return new ReturnExpression(returnValue); + } + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/SingleOpExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/SingleOpExpression.java new file mode 100644 index 0000000..ee43a22 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/SingleOpExpression.java @@ -0,0 +1,27 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.analysis.decompiler.code.ast.Operation; +import me.grax.jbytemod.analysis.decompiler.code.ast.VarType; + +public class SingleOpExpression extends OpExpression { + + public SingleOpExpression(Expression ref, Operation op, VarType returnType) { + super(ref, null, op, returnType); + } + + @Override + public Expression getRight() { + throw new IllegalArgumentException("called getRight on single exp reference"); + } + + @Override + public String toString() { + return op.getSymbol() + "(" + left.toString() + ")"; + } + + @Override + public Expression clone() { + return new SingleOpExpression(left.clone(), op, returnType); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/StringExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/StringExpression.java new file mode 100644 index 0000000..3056993 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/StringExpression.java @@ -0,0 +1,38 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.utils.TextUtils; + +public class StringExpression extends Expression { + + private String value; + + public StringExpression(String value) { + super(); + this.value = value; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String toString() { + return TextUtils.addTag("\"" + value + "\"", "font color=#559955"); //TODO escape + } + + @Override + public int size() { + return 1; + } + + @Override + public Expression clone() { + return new StringExpression(value); + } + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/TableSwitchExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/TableSwitchExpression.java new file mode 100644 index 0000000..920c36e --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/TableSwitchExpression.java @@ -0,0 +1,31 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; + +public class TableSwitchExpression extends Expression { + + private Expression toSwitch; + private int min; + private int max; + + public TableSwitchExpression(Expression toSwitch, int min, int max) { + this.toSwitch = toSwitch; + this.min = min; + this.max = max; + } + + @Override + public String toString() { + return "switch(" + toSwitch + ") " + min + " - " + max + ""; + } + + @Override + public int size() { + return 1; + } + + @Override + public Expression clone() { + return new TableSwitchExpression(toSwitch.clone(), min, max); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/TextExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/TextExpression.java new file mode 100644 index 0000000..4d0b59d --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/TextExpression.java @@ -0,0 +1,28 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.utils.TextUtils; + +public class TextExpression extends Expression { + + private String text; + + public TextExpression(String var) { + this.text = var; + } + + @Override + public String toString() { + return "" + TextUtils.escape(text) + ""; + } + + @Override + public int size() { + return 0; + } + + @Override + public Expression clone() { + return new TextExpression(text); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ThrowExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ThrowExpression.java new file mode 100644 index 0000000..30d5f60 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ThrowExpression.java @@ -0,0 +1,36 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.analysis.decompiler.defs.Keywords; + +public class ThrowExpression extends Expression { + + private Expression throwable; + + public ThrowExpression(Expression throwable) { + super(); + this.throwable = throwable; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("" + Keywords.THROW + ""); + if (throwable != null) { + sb.append(" "); + sb.append(throwable); + } + return sb.toString(); + } + + @Override + public int size() { + return 0; + } + + @Override + public Expression clone() { + return new ThrowExpression(throwable); + } + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ValueExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ValueExpression.java new file mode 100644 index 0000000..0dfb134 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/ValueExpression.java @@ -0,0 +1,46 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.analysis.decompiler.code.ast.VarType; + +public class ValueExpression extends Expression { + private VarType type; + private Object value; + + public ValueExpression(VarType type, Object value) { + super(); + this.type = type; + this.value = value; + } + + private String getSub() { + switch (type) { + case OBJECT: + case INT: + return ""; + case DOUBLE: + return "d"; + case FLOAT: + return "f"; + case LONG: + return "L"; + default: + return ""; + } + } + + @Override + public String toString() { + return value.toString() + getSub(); + } + + @Override + public int size() { + return type.size(); + } + + @Override + public Expression clone() { + return new ValueExpression(type, value); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/VarAssignExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/VarAssignExpression.java new file mode 100644 index 0000000..9e4aa4d --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/VarAssignExpression.java @@ -0,0 +1,64 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.analysis.decompiler.code.ast.VarType; +import me.grax.jbytemod.utils.InstrUtils; +import me.grax.jbytemod.utils.TextUtils; + +public class VarAssignExpression extends Expression { + private int index; + private VarType type; + private Expression value; + + public VarAssignExpression(int index, VarType type, Expression value) { + super(); + this.index = index; + this.type = type; + this.value = value; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public VarType getType() { + return type; + } + + public void setType(VarType type) { + this.type = type; + } + + public Expression getValue() { + return value; + } + + public void setValue(Expression value) { + this.value = value; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(type.getType()); + sb.append(" "); + sb.append(TextUtils.addTag("var" + index, "font color=" + InstrUtils.primColor.getString())); + sb.append(" = "); + sb.append(value.toString()); + return sb.toString(); + } + + @Override + public int size() { + return 0; + } + + @Override + public Expression clone() { + return new VarAssignExpression(index, type, value.clone()); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/VarLoadExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/VarLoadExpression.java new file mode 100644 index 0000000..6cee5ad --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/VarLoadExpression.java @@ -0,0 +1,48 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.analysis.decompiler.code.ast.VarType; +import me.grax.jbytemod.utils.InstrUtils; +import me.grax.jbytemod.utils.TextUtils; + +public class VarLoadExpression extends Expression { + private int index; + private VarType type; + + public VarLoadExpression(int index, VarType type) { + super(); + this.index = index; + this.type = type; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public VarType getType() { + return type; + } + + public void setType(VarType type) { + this.type = type; + } + + @Override + public String toString() { + return TextUtils.addTag("var" + index, "font color=" + InstrUtils.primColor.getString()); //TODO use localvartable + } + + @Override + public int size() { + return type.size(); + } + + @Override + public Expression clone() { + return new VarLoadExpression(index, type); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/VarSpecialExpression.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/VarSpecialExpression.java new file mode 100644 index 0000000..e17d9ae --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/code/ast/expressions/VarSpecialExpression.java @@ -0,0 +1,28 @@ +package me.grax.jbytemod.analysis.decompiler.code.ast.expressions; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.utils.TextUtils; + +public class VarSpecialExpression extends Expression { + + private String var; + + public VarSpecialExpression(String var) { + this.var = var; + } + + @Override + public String toString() { + return TextUtils.addTag(var, "font color=#669966"); + } + + @Override + public int size() { + return 1; + } + + @Override + public Expression clone() { + return new VarSpecialExpression(var); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/defs/Keywords.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/defs/Keywords.java new file mode 100644 index 0000000..d65e834 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/defs/Keywords.java @@ -0,0 +1,8 @@ +package me.grax.jbytemod.analysis.decompiler.defs; + +public class Keywords { + public static final String RETURN = "return"; + public static final String THROW = "throw"; + public static final String NULL = "null"; + //TODO add other keywords +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/struct/Conversion.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/struct/Conversion.java new file mode 100644 index 0000000..c4a8a6a --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/struct/Conversion.java @@ -0,0 +1,769 @@ +package me.grax.jbytemod.analysis.decompiler.struct; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.objectweb.asm.Handle; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.IincInsnNode; +import org.objectweb.asm.tree.IntInsnNode; +import org.objectweb.asm.tree.InvokeDynamicInsnNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.LookupSwitchInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.TableSwitchInsnNode; +import org.objectweb.asm.tree.TypeInsnNode; +import org.objectweb.asm.tree.VarInsnNode; + +import me.grax.jbytemod.analysis.block.Block; +import me.grax.jbytemod.analysis.decompiler.ClassDefinition; +import me.grax.jbytemod.analysis.decompiler.code.ast.Comparison; +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.analysis.decompiler.code.ast.Operation; +import me.grax.jbytemod.analysis.decompiler.code.ast.VarType; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.ArrayIndexExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.ArrayStoreExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.CastExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.ClassTypeExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.ComparisonExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.DebugStackAssignExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.DebugStackExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.FieldAssignExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.FieldExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.IncrementExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.InstanceofExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.InvokeDynamicExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.LookupSwitchExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.MethodExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.NewArrayExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.NewPrimArrayExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.NewTypeExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.NullExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.OpExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.ReturnExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.SingleOpExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.StringExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.TableSwitchExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.TextExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.ThrowExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.ValueExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.VarAssignExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.VarLoadExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.VarSpecialExpression; +import me.grax.jbytemod.analysis.decompiler.struct.exception.StackException; +import me.grax.jbytemod.analysis.decompiler.struct.exception.UnknownOPException; +import me.grax.jbytemod.analysis.decompiler.struct.utils.DescUtils; +import me.grax.jbytemod.analysis.decompiler.syntax.nodes.NodeList; +import me.lpk.util.AccessHelper; +import me.lpk.util.OpUtils; + +public class Conversion implements Opcodes { + + private NodeList list; + private JVMStack stack; + private int line; + private MethodNode mn; + private JVMStack preStack; + private int arrayDebugIndex; + + public Conversion(MethodNode mn, NodeList list) { + this.mn = mn; + this.list = list; + } + + public Conversion(MethodNode mn, NodeList list, JVMStack preStack) { + this.mn = mn; + this.list = list; + this.preStack = preStack; + } + + public int getLine() { + return line; + } + + public void convert(Block b) { + this.line = 0; + if (preStack != null) { + this.stack = new JVMStack(preStack); + } else { + this.stack = new JVMStack(); + } + for (AbstractInsnNode ain : b.getNodes()) { + switch (ain.getType()) { + case AbstractInsnNode.INSN: + visitInsnNode(ain.getOpcode()); + break; + case AbstractInsnNode.VAR_INSN: + VarInsnNode vin = (VarInsnNode) ain; + visitVarInsnNode(vin.getOpcode(), vin.var); + break; + case AbstractInsnNode.METHOD_INSN: + MethodInsnNode min = (MethodInsnNode) ain; + visitMethodInsnNode(min.getOpcode(), min.owner, min.name, min.desc); + break; + case AbstractInsnNode.FIELD_INSN: + FieldInsnNode fin = (FieldInsnNode) ain; + visiFieldInsnNode(fin.getOpcode(), fin.owner, fin.name, fin.desc); + break; + case AbstractInsnNode.TYPE_INSN: + TypeInsnNode tin = (TypeInsnNode) ain; + visiTypeInsnNode(tin.getOpcode(), tin.desc); + break; + case AbstractInsnNode.LDC_INSN: + LdcInsnNode lin = (LdcInsnNode) ain; + visitLdcInsnNode(lin.cst); + break; + case AbstractInsnNode.INT_INSN: + IntInsnNode iin = (IntInsnNode) ain; + visitIntInsnNode(iin.getOpcode(), iin.operand); + break; + case AbstractInsnNode.JUMP_INSN: + visitJumpInsnNode(ain.getOpcode()); + break; + case AbstractInsnNode.IINC_INSN: + IincInsnNode iinc = (IincInsnNode) ain; + visitIincInsnNode(iinc.var, iinc.incr); + break; + case AbstractInsnNode.TABLESWITCH_INSN: + TableSwitchInsnNode sw = (TableSwitchInsnNode) ain; + visitTableSwitch(sw.min, sw.max); + break; + case AbstractInsnNode.LOOKUPSWITCH_INSN: + LookupSwitchInsnNode lsw = (LookupSwitchInsnNode) ain; + visitLookupSwitch(lsw.keys.size()); + break; + case AbstractInsnNode.INVOKE_DYNAMIC_INSN: + InvokeDynamicInsnNode idin = (InvokeDynamicInsnNode) ain; + visitInvokeDynamic(idin); + case AbstractInsnNode.LABEL: + case AbstractInsnNode.LINE: + case AbstractInsnNode.FRAME: + break; + default: + throw new RuntimeException("unrecognized AbstractInsnNode type: " + ain.getType()); + } + line++; + } + int var = 0; + ArrayList left = new ArrayList<>(); + while (!stack.getList().isEmpty()) { + Expression item = stack.getList().pop(); + if (item instanceof ComparisonExpression || item instanceof TableSwitchExpression) { + list.add(item); + } else { + left.add(0, item); + } + } + for (Expression debug : left) { + int prev = -1; + if (debug instanceof DebugStackExpression) { + prev = ((DebugStackExpression) debug).getVar(); + } + if (prev != var) { + //avoid nonsense setters + list.add(new DebugStackAssignExpression(var, debug)); + } + stack.getList().push(debug); + var++; + } + } + + private void visitInvokeDynamic(InvokeDynamicInsnNode idin) { + InvokeDynamicExpression idye = new InvokeDynamicExpression(idin.name, idin.desc, idin.bsmArgs, idin.bsm); + Handle methodHandle = idye.getMethodHandle(); + if (methodHandle != null) { + ArrayList descSizes = DescUtils.getInnerDescSizes(methodHandle.getDesc()); + List args = new ArrayList<>(); + for (int i : descSizes) { + if (i == 1) { + args.add(stack.pop()); + } else { + args.add(stack.pop2()); + } + } + Collections.reverse(args); + idye.setArgs(args); + } + stack.push(idye); + } + + private void visitLookupSwitch(int size) { + stack.push(new LookupSwitchExpression(stack.pop(), size)); + } + + private void visitTableSwitch(int min, int max) { + stack.push(new TableSwitchExpression(stack.pop(), min, max)); + } + + private void visitIincInsnNode(int var, int incr) { + list.add(new IncrementExpression(new VarLoadExpression(var, VarType.INT), incr)); + } + + private void visitIntInsnNode(int opcode, int operand) { + switch (opcode) { + case BIPUSH: + case SIPUSH: + stack.push(new ValueExpression(VarType.INT, operand)); + break; + case NEWARRAY: + VarType type = null; + switch (operand) { + case 4: + type = VarType.BOOLEAN; + break; + case 5: + type = VarType.CHAR; + break; + case 6: + type = VarType.FLOAT; + break; + case 7: + type = VarType.DOUBLE; + break; + case 8: + type = VarType.BYTE; + break; + case 9: + type = VarType.SHORT; + break; + case 10: + type = VarType.INT; + break; + case 11: + type = VarType.LONG; + break; + default: + throw new RuntimeException(); + } + stack.push(new NewPrimArrayExpression(stack.pop(), type)); + break; + default: + throw new UnknownOPException(opcode); + } + } + + private void visitJumpInsnNode(int opcode) { + switch (opcode) { + case IFEQ: + stack.push(new ComparisonExpression(stack.pop(), Comparison.IS, new ValueExpression(VarType.INT, 0))); + break; + case IFNE: + stack.push(new ComparisonExpression(stack.pop(), Comparison.ISNOT, new ValueExpression(VarType.INT, 0))); + break; + case IFGE: + stack.push(new ComparisonExpression(stack.pop(), Comparison.GREATEREQUALS, new ValueExpression(VarType.INT, 0))); + break; + case IFGT: + stack.push(new ComparisonExpression(stack.pop(), Comparison.GREATER, new ValueExpression(VarType.INT, 0))); + break; + case IFLE: + stack.push(new ComparisonExpression(stack.pop(), Comparison.LOWEREQUALS, new ValueExpression(VarType.INT, 0))); + break; + case IFLT: + stack.push(new ComparisonExpression(stack.pop(), Comparison.LOWER, new ValueExpression(VarType.INT, 0))); + break; + case IF_ACMPEQ: + Expression top = stack.pop(); + Expression second = stack.pop(); + stack.push(new ComparisonExpression(second, Comparison.IS, top)); + break; + case IF_ACMPNE: + top = stack.pop(); + second = stack.pop(); + stack.push(new ComparisonExpression(second, Comparison.ISNOT, top)); + break; + case IFNULL: + stack.push(new ComparisonExpression(stack.pop(), Comparison.IS, new NullExpression())); + break; + case IFNONNULL: + stack.push(new ComparisonExpression(stack.pop(), Comparison.ISNOT, new NullExpression())); + break; + case GOTO: + break; + default: + top = stack.pop(); + second = stack.pop(); + switch (opcode) { + case IF_ICMPEQ: + stack.push(new ComparisonExpression(second, Comparison.IS, top)); + break; + case IF_ICMPNE: + stack.push(new ComparisonExpression(second, Comparison.ISNOT, top)); + break; + case IF_ICMPGE: + stack.push(new ComparisonExpression(second, Comparison.GREATEREQUALS, top)); + break; + case IF_ICMPGT: + stack.push(new ComparisonExpression(second, Comparison.GREATER, top)); + break; + case IF_ICMPLE: + stack.push(new ComparisonExpression(second, Comparison.LOWEREQUALS, top)); + break; + case IF_ICMPLT: + stack.push(new ComparisonExpression(second, Comparison.LOWER, top)); + break; + case JSR: + default: + throw new UnknownOPException(opcode); + } + } + } + + private void visiTypeInsnNode(int opcode, String desc) { + switch (opcode) { + case NEW: + stack.push(new NewTypeExpression(new ClassDefinition(desc))); + break; + case ANEWARRAY: + NewArrayExpression nae = new NewArrayExpression(stack.pop(), new ClassDefinition(desc)); + DebugStackExpression e = new DebugStackExpression(arrayDebugIndex, 1, null, "array"); + list.add(new DebugStackAssignExpression(arrayDebugIndex++, nae, "array")); + stack.push(e); + break; + case INSTANCEOF: + stack.push(new InstanceofExpression(stack.pop(), new ClassDefinition(desc))); + break; + case CHECKCAST: + stack.push(new CastExpression(new ClassDefinition(desc), stack.pop())); + break; + default: + throw new UnknownOPException(opcode); + } + } + + private void visiFieldInsnNode(int opcode, String owner, String name, String desc) { + if (opcode == GETSTATIC) { + FieldExpression fe = new FieldExpression(new ClassDefinition(owner), name, VarType.ofDesc(desc)); + stack.push(fe); + } else if (opcode == GETFIELD) { + FieldExpression fe = new FieldExpression(stack.pop(), name, VarType.ofDesc(desc)); + stack.push(fe); + } else { + VarType descType = VarType.ofDesc(desc); + if (opcode == PUTSTATIC) { + Expression value = descType.size() == 2 ? stack.pop2() : stack.pop(); + list.add(new FieldAssignExpression(new ClassDefinition(owner), name, descType, value)); + } else if (opcode == PUTFIELD) { + Expression value = descType.size() == 2 ? stack.pop2() : stack.pop(); + list.add(new FieldAssignExpression(stack.pop(), name, descType, value)); + } + } + } + + private void visitMethodInsnNode(int opcode, String owner, String name, String desc) { + ArrayList args = new ArrayList<>(); + ArrayList descSizes = DescUtils.getInnerDescSizes(desc); + if (opcode == INVOKEVIRTUAL) { //for some reason invokevirtual reads stack as arg1, arg2.... and all other read as argN ... arg1 + Collections.reverse(descSizes); + } + for (int i : descSizes) { + if (i == 1) { + args.add(stack.pop()); + } else { + args.add(stack.pop2()); + } + } + Collections.reverse(args); + if (opcode == INVOKESTATIC) { + MethodExpression me = new MethodExpression(new ClassDefinition(owner), name, args, VarType.ofDesc(desc)); + if (me.getReturnType() == VarType.VOID) { + list.add(me); + } else { + stack.push(me); + } + } else if (opcode == INVOKEVIRTUAL || opcode == INVOKESPECIAL) { + MethodExpression me = new MethodExpression(stack.pop(), name, args, VarType.ofDesc(desc)); + if (me.getReturnType() == VarType.VOID) { + if (name.equals("")) { + if (stack.size() > 0) { + Expression e = stack.peek(); + if (e instanceof NewTypeExpression) { + NewTypeExpression nte = (NewTypeExpression) e; + nte.setInit(me); + return; + } + } + } + list.add(me); + } else { + stack.push(me); + } + } else if (opcode == INVOKEINTERFACE) { + MethodExpression me = new MethodExpression(stack.pop(), name, args, VarType.ofDesc(desc)); + if (me.getReturnType() == VarType.VOID) { + list.add(me); + } else { + stack.push(me); + } + } + } + + private void visitLdcInsnNode(Object cst) { + if (cst instanceof String) { + stack.push(new StringExpression((String) cst)); + } else if (cst instanceof Integer) { + stack.push(new ValueExpression(VarType.INT, cst)); + } else if (cst instanceof Float) { + stack.push(new ValueExpression(VarType.FLOAT, cst)); + } else if (cst instanceof Long) { + stack.push(new ValueExpression(VarType.LONG, cst)); + } else if (cst instanceof Double) { + stack.push(new ValueExpression(VarType.DOUBLE, cst)); + } else if (cst instanceof Type) { + Type t = (Type) cst; + stack.push(new ClassTypeExpression(t.getClassName())); + } else { + throw new RuntimeException(cst.getClass().getName()); + } + } + + private void visitVarInsnNode(int opc, int index) { + Expression top; + switch (opc) { + case ALOAD: + if (!AccessHelper.isStatic(mn.access) && index == 0) { + stack.push(new VarSpecialExpression("this")); + break; + } + stack.push(new VarLoadExpression(index, VarType.OBJECT)); + break; + case ILOAD: + stack.push(new VarLoadExpression(index, VarType.INT)); + break; + case FLOAD: + stack.push(new VarLoadExpression(index, VarType.FLOAT)); + break; + case LLOAD: + stack.push(new VarLoadExpression(index, VarType.LONG)); + break; + case DLOAD: + stack.push(new VarLoadExpression(index, VarType.DOUBLE)); + break; + case ASTORE: + top = stack.pop(); + if (top.size() != 1) { + throw new StackException("wrong var store size: " + top.size()); + } + list.add(new VarAssignExpression(index, VarType.OBJECT, top)); + break; + case ISTORE: + top = stack.pop(); + if (top.size() != 1) { + throw new StackException("wrong var store size: " + top.size()); + } + list.add(new VarAssignExpression(index, VarType.INT, top)); + break; + case FSTORE: + top = stack.pop(); + if (top.size() != 1) { + throw new StackException("wrong var store size: " + top.size()); + } + list.add(new VarAssignExpression(index, VarType.FLOAT, top)); + break; + case LSTORE: + top = stack.pop2(); + if (top.size() != 2) { + throw new StackException("wrong var store size: " + top.size()); + } + list.add(new VarAssignExpression(index, VarType.LONG, top)); + break; + case DSTORE: + top = stack.pop2(); + if (top.size() != 2) { + throw new StackException("wrong var store size: " + top.size()); + } + list.add(new VarAssignExpression(index, VarType.DOUBLE, top)); + break; + default: + throw new UnknownOPException(opc); + } + } + + private void visitInsnNode(int opc) { + if (opc >= ACONST_NULL && opc <= DCONST_1) { + insnPush(opc); + } else if (opc >= POP && opc <= SWAP) { + stackOp(opc); + } else if (opc >= IADD && opc <= LXOR) { + operation(opc); + } else if (opc >= I2L && opc <= I2S) { + conversion(opc); + } else if (opc >= IRETURN && opc <= RETURN) { + retValue(opc); + } else if (opc == ATHROW) { + athrow(); + } else if (opc >= IALOAD && opc <= SALOAD) { + arrayLoad(opc); + } else if (opc >= IASTORE && opc <= SASTORE) { + arrayStore(opc); + } else if (opc == ARRAYLENGTH) { + visiFieldInsnNode(GETFIELD, null, "length", "I"); + } else if (opc == MONITORENTER || opc == MONITOREXIT) { + list.add(new TextExpression(OpUtils.getOpcodeText(opc).toLowerCase())); + } else if (opc == NOP) { + //do nothing + } else { + //comparison nodes + throw new RuntimeException(OpUtils.getOpcodeText(opc)); + } + } + + private void arrayStore(int opc) { + Expression value; + if (opc == LASTORE || opc == DASTORE) { + value = stack.pop2(); + } else { + value = stack.pop(); + } + Expression index = stack.pop(); + Expression array = stack.pop(); + list.add(new ArrayStoreExpression(array, index, value)); + } + + private void arrayLoad(int opc) { + Expression index = stack.pop(); + Expression array = stack.pop(); + boolean twoword = opc == LALOAD || opc == DALOAD; + stack.push(new ArrayIndexExpression(array, index, twoword), twoword); + } + + private void athrow() { + list.add(new ThrowExpression(stack.pop())); + } + + private void retValue(int opc) { + switch (opc) { + case IRETURN: + case FRETURN: + case ARETURN: + list.add(new ReturnExpression(stack.pop())); + break; + case LRETURN: + case DRETURN: + list.add(new ReturnExpression(stack.pop2())); + break; + case RETURN: + list.add(new ReturnExpression()); + break; + } + } + + private void conversion(int opc) { + switch (opc) { + case L2I: + case D2I: + stack.push(new CastExpression(VarType.INT, stack.pop2())); + break; + case F2I: + stack.push(new CastExpression(VarType.INT, stack.pop())); + break; + case I2B: + stack.push(new CastExpression(VarType.BYTE, stack.pop())); + break; + case I2C: + stack.push(new CastExpression(VarType.CHAR, stack.pop())); + break; + case I2S: + stack.push(new CastExpression(VarType.SHORT, stack.pop())); + break; + case I2F: + stack.push(new CastExpression(VarType.FLOAT, stack.pop())); + break; + case L2F: + case D2F: + stack.push(new CastExpression(VarType.FLOAT, stack.pop2())); + break; + case I2L: + case F2L: + stack.push(new CastExpression(VarType.LONG, stack.pop())); + break; + case D2L: + stack.push(new CastExpression(VarType.LONG, stack.pop2())); + break; + case I2D: + case F2D: + stack.push(new CastExpression(VarType.DOUBLE, stack.pop())); + break; + case L2D: + stack.push(new CastExpression(VarType.DOUBLE, stack.pop2())); + break; + default: + throw new UnknownOPException(opc); + } + } + + private void insnPush(int opc) { + switch (opc) { + case ACONST_NULL: + stack.push(new NullExpression()); + break; + case ICONST_0: + case ICONST_1: + case ICONST_2: + case ICONST_3: + case ICONST_4: + case ICONST_5: + case ICONST_M1: + stack.push(new ValueExpression(VarType.INT, (int) (opc - 3))); + break; + case FCONST_0: + case FCONST_1: + case FCONST_2: + stack.push(new ValueExpression(VarType.FLOAT, (float) (opc - 11f))); + break; + case DCONST_0: + case DCONST_1: + stack.push(new ValueExpression(VarType.DOUBLE, (double) (opc - 14d))); + break; + case LCONST_0: + case LCONST_1: + stack.push(new ValueExpression(VarType.LONG, (long) (opc - 9L))); + break; + default: + throw new UnknownOPException(opc); + } + } + + private void stackOp(int opc) { + switch (opc) { + case POP: + Expression pop = stack.pop(); + if (pop instanceof MethodExpression || pop instanceof NewArrayExpression) { + list.add(pop); //expressions were invoked, they must be added to the output + } + break; + case POP2: + Expression pop2 = stack.pop2(); + if (pop2 instanceof MethodExpression) { + list.add(pop2); //expressions were invoked, they must be added to the output + } + break; + case DUP: + stack.push(stack.peek().clone(), false); + break; + case DUP_X1: + stack.push(stack.peek().clone(), 1, false); + break; + case DUP_X2: + stack.push(stack.peek().clone(), 2, false); + break; + case DUP2: + if (stack.peek().size() == 2) { + stack.push(stack.peek().clone(), true); + } else if (stack.peek().size() == 1 && stack.peek2().size() == 1) { + Expression o1 = stack.peek(); + Expression o2 = stack.peek2(); + stack.push(o2.clone()); + stack.push(o1.clone()); + } + break; + case DUP2_X1: + stack.push(stack.peek().clone(), 1, true); + break; + case DUP2_X2: + stack.push(stack.peek().clone(), 2, true); + break; + case SWAP: + if (stack.peek().size() == 2) { + break; + } else if (stack.peek().size() == 1 && stack.peek2().size() == 1) { + Expression o1 = stack.pop(); + Expression o2 = stack.pop(); + stack.push(o1); + stack.push(o2); + } else { + throw new StackException("cannot swap"); + } + break; + default: + throw new UnknownOPException(opc); + } + } + + private void operation(int opc) { + Expression e1; + Expression e2; + + switch (opc) { + case IADD: + case ISUB: + case IMUL: + case IDIV: + case IREM: + case ISHL: + case ISHR: + case IUSHR: + case IAND: + case IOR: + case IXOR: + e1 = stack.pop(); + e2 = stack.pop(); + stack.push(new OpExpression(e2, e1, Operation.of(opc), VarType.INT)); + break; + case FADD: + case FSUB: + case FMUL: + case FDIV: + case FREM: + e1 = stack.pop(); + e2 = stack.pop(); + stack.push(new OpExpression(e2, e1, Operation.of(opc), VarType.FLOAT)); + break; + case LADD: + case LSUB: + case LMUL: + case LDIV: + case LREM: + case LAND: + case LOR: + case LXOR: + e1 = stack.pop2(); + e2 = stack.pop2(); + stack.push(new OpExpression(e2, e1, Operation.of(opc), VarType.LONG)); + break; + case LSHL: + case LSHR: + case LUSHR: + e1 = stack.pop(); + e2 = stack.pop2(); + stack.push(new OpExpression(e2, e1, Operation.of(opc), VarType.LONG)); + break; + case DADD: + case DSUB: + case DMUL: + case DDIV: + case DREM: + e1 = stack.pop2(); + e2 = stack.pop2(); + stack.push(new OpExpression(e2, e1, Operation.of(opc), VarType.DOUBLE)); + break; + case INEG: + e1 = stack.pop(); + stack.push(new SingleOpExpression(e1, Operation.of(opc), VarType.INT)); + break; + case FNEG: + e1 = stack.pop(); + stack.push(new SingleOpExpression(e1, Operation.of(opc), VarType.FLOAT)); + break; + case LNEG: + e1 = stack.pop2(); + stack.push(new SingleOpExpression(e1, Operation.of(opc), VarType.LONG)); + break; + case DNEG: + e1 = stack.pop2(); + stack.push(new SingleOpExpression(e1, Operation.of(opc), VarType.DOUBLE)); + break; + default: + throw new UnknownOPException(opc); + } + } + + public JVMStack getStack() { + return stack; + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/struct/JVMStack.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/struct/JVMStack.java new file mode 100644 index 0000000..cc48bb2 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/struct/JVMStack.java @@ -0,0 +1,123 @@ +package me.grax.jbytemod.analysis.decompiler.struct; + +import java.lang.reflect.Field; +import java.util.EmptyStackException; +import java.util.Stack; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; +import me.grax.jbytemod.analysis.decompiler.code.ast.VarType; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.DebugStackExpression; +import me.grax.jbytemod.analysis.decompiler.code.ast.expressions.DebugStackUnknownExpression; +import me.grax.jbytemod.analysis.decompiler.struct.exception.StackException; + +public class JVMStack { + + private Stack list; + + public JVMStack() { + this.list = new Stack(); + } + + private int belowStackCount = 0; + + public JVMStack(JVMStack preStack) { + this.list = new Stack(); + for (Expression e : preStack.list) { + list.add(new DebugStackExpression(belowStackCount++, e.size(), getVarType(e))); + } + } + + private VarType getVarType(Expression array) { + for (Field f : array.getClass().getDeclaredFields()) { + if (f.getType() == VarType.class) { + f.setAccessible(true); + try { + return (VarType) f.get(array); + } catch (Exception e) { + } + } + } + return null; + } + + public void push(Expression o, boolean twoword) { + if (twoword) { + if (o.size() != 2) { + throw new StackException("not a wide value: " + o.size()); + } + } else { + if (o.size() != 1) { + throw new StackException("not a 1-size: " + o.size()); + } + } + push(o); + } + + public void push(Expression o) { + list.push(o); + } + + public Expression pop() { + Expression top = peek(); + if (top.size() != 1) { + throw new StackException("Top is " + top.size() + "-word value, cannot pop"); + } + return list.pop(); + } + + public Expression peek() { + try { + return list.peek(); + } catch (EmptyStackException e) { + //stack empty, maybe a try catch block? + list.push(new DebugStackUnknownExpression(belowStackCount, 1, null)); + return list.peek(); + } + } + + public void push(Expression o, int i, boolean twoword) { + if (twoword) { + if (o.size() != 2) { + throw new StackException("not a wide value: " + o.size()); + } + } else { + if (o.size() != 1) { + throw new StackException("not a 1-size: " + o.size()); + } + } + push(o, i); + } + + public void push(Expression o, int i) { + list.add(list.size() - 1 - i, o); + } + + public int size() { + return list.size(); + } + + public Expression pop2() { + Expression top = peek(); + int size = top.size(); + if (size == 2) { + return list.pop(); + } else if (size == 1) { + Expression oldTop = list.pop(); + if (peek().size() != 1) { + throw new StackException("Second value is " + top.size() + "-word, cannot pop2 (Top was 1-word: " + oldTop.getClass().getSimpleName() + " " + + oldTop.toString() + ")"); + } + return list.pop(); + } + throw new StackException(String.valueOf(size)); + } + + public Expression peek2() { + return list.elementAt(list.size() - 2); + } + + public Stack getList() { + return list; + } + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/struct/exception/StackException.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/struct/exception/StackException.java new file mode 100644 index 0000000..0b98f8e --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/struct/exception/StackException.java @@ -0,0 +1,10 @@ +package me.grax.jbytemod.analysis.decompiler.struct.exception; + +public class StackException extends RuntimeException { + private static final long serialVersionUID = 1L; + + public StackException(String string) { + super(string); + } + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/struct/exception/UnknownOPException.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/struct/exception/UnknownOPException.java new file mode 100644 index 0000000..cec9e12 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/struct/exception/UnknownOPException.java @@ -0,0 +1,11 @@ +package me.grax.jbytemod.analysis.decompiler.struct.exception; + +import me.lpk.util.OpUtils; + +public class UnknownOPException extends RuntimeException { + private static final long serialVersionUID = 1L; + + public UnknownOPException(int opc) { + super("Unresolved opcode: " + OpUtils.getOpcodeText(opc) + " (" + opc + ")"); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/struct/utils/DescUtils.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/struct/utils/DescUtils.java new file mode 100644 index 0000000..e3268cf --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/struct/utils/DescUtils.java @@ -0,0 +1,41 @@ +package me.grax.jbytemod.analysis.decompiler.struct.utils; + +import java.util.ArrayList; + +public class DescUtils { + public static ArrayList getDescSizes(String desc) { + ArrayList descSizes = new ArrayList<>(); + int dims = 0; + boolean inObject = false; + for (char c : desc.toCharArray()) { + if (inObject) { + if (c == ';') { + inObject = false; + descSizes.add(1); + dims = 0; + } + continue; + } + if (c == 'L') { + inObject = true; + } else if (c == '[') { + dims++; + } else { + if (dims == 0 && (c == 'J' || c == 'D')) { + descSizes.add(2); + } else { + descSizes.add(1); + } + dims = 0; + } + } + return descSizes; + } + + public static ArrayList getInnerDescSizes(String desc) { + if (desc.startsWith("()")) { + return new ArrayList<>(); + } + return getDescSizes(desc.substring(1, desc.lastIndexOf(')'))); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/decompiler/syntax/nodes/NodeList.java b/src/main/java/me/grax/jbytemod/analysis/decompiler/syntax/nodes/NodeList.java new file mode 100644 index 0000000..c0d79e8 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/decompiler/syntax/nodes/NodeList.java @@ -0,0 +1,11 @@ +package me.grax.jbytemod.analysis.decompiler.syntax.nodes; + +import java.util.ArrayList; + +import me.grax.jbytemod.analysis.decompiler.code.ast.Expression; + +public class NodeList extends ArrayList { + + private static final long serialVersionUID = 1L; + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/errors/EmptyMistake.java b/src/main/java/me/grax/jbytemod/analysis/errors/EmptyMistake.java new file mode 100644 index 0000000..c545f09 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/errors/EmptyMistake.java @@ -0,0 +1,7 @@ +package me.grax.jbytemod.analysis.errors; + +public class EmptyMistake extends Mistake { + public EmptyMistake() { + super(" "); + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/errors/ErrorAnalyzer.java b/src/main/java/me/grax/jbytemod/analysis/errors/ErrorAnalyzer.java new file mode 100644 index 0000000..6812565 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/errors/ErrorAnalyzer.java @@ -0,0 +1,70 @@ +package me.grax.jbytemod.analysis.errors; + +import java.util.HashMap; + +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.IincInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.VarInsnNode; +import org.objectweb.asm.tree.analysis.Analyzer; +import org.objectweb.asm.tree.analysis.AnalyzerException; +import org.objectweb.asm.tree.analysis.BasicVerifier; + +import me.grax.jbytemod.JByteMod; + +public class ErrorAnalyzer { + private MethodNode mn; + private ClassNode cn; + + public ErrorAnalyzer(ClassNode cn, MethodNode mn) { + this.cn = cn; + this.mn = mn; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public HashMap findErrors() { + HashMap map = new HashMap<>(); + //general analysis + for (AbstractInsnNode ain : mn.instructions.toArray()) { + maxLocals(mn.maxLocals, ain, map); + } + //asm verification + final Analyzer a = new Analyzer(new BasicVerifier()); + try { + a.analyze(cn.name, mn); + } catch (AnalyzerException e) { + put(map, e.node, new InsnError(e.getMessage())); + } catch (Exception e) { + JByteMod.LOGGER.err("Couldn't analyze errors in bytecode (" + e.toString() + ")"); + } + return map; + } + + private void maxLocals(int maxLocals, AbstractInsnNode ain, HashMap map) { + int var = -1; + if (ain.getType() == AbstractInsnNode.VAR_INSN) { + VarInsnNode vin = (VarInsnNode) ain; + var = vin.var; + } + if (ain.getType() == AbstractInsnNode.IINC_INSN) { + IincInsnNode iinc = (IincInsnNode) ain; + var = iinc.var; + } + if (var > maxLocals) { + put(map, ain, new InsnWarning("max locals exceeded")); + } + } + + private void put(HashMap map, AbstractInsnNode ain, Mistake mistake) { + if (!map.containsKey(ain)) { + map.put(ain, mistake); + } else { + Mistake present = map.get(ain); + boolean isMoreImportant = !(present instanceof InsnError && mistake instanceof InsnWarning); + if (isMoreImportant) { + map.put(ain, mistake); + } + } + } +} diff --git a/src/main/java/me/grax/jbytemod/analysis/errors/InsnError.java b/src/main/java/me/grax/jbytemod/analysis/errors/InsnError.java new file mode 100644 index 0000000..56dc11e --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/errors/InsnError.java @@ -0,0 +1,9 @@ +package me.grax.jbytemod.analysis.errors; + +public class InsnError extends Mistake { + + public InsnError(String desc) { + super(desc); + } + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/errors/InsnWarning.java b/src/main/java/me/grax/jbytemod/analysis/errors/InsnWarning.java new file mode 100644 index 0000000..aa3457f --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/errors/InsnWarning.java @@ -0,0 +1,9 @@ +package me.grax.jbytemod.analysis.errors; + +public class InsnWarning extends Mistake { + + public InsnWarning(String desc) { + super(desc); + } + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/errors/Mistake.java b/src/main/java/me/grax/jbytemod/analysis/errors/Mistake.java new file mode 100644 index 0000000..5e48838 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/errors/Mistake.java @@ -0,0 +1,18 @@ +package me.grax.jbytemod.analysis.errors; + +public abstract class Mistake { + private String desc; + + public Mistake(String desc) { + this.desc = desc; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/obfuscation/ObfuscationAnalyzer.java b/src/main/java/me/grax/jbytemod/analysis/obfuscation/ObfuscationAnalyzer.java new file mode 100644 index 0000000..19800f0 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/obfuscation/ObfuscationAnalyzer.java @@ -0,0 +1,167 @@ +package me.grax.jbytemod.analysis.obfuscation; + +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.FieldNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.TryCatchBlockNode; + +import me.grax.jbytemod.analysis.obfuscation.enums.MethodObfType; +import me.grax.jbytemod.analysis.obfuscation.enums.NameObfType; +import me.grax.jbytemod.analysis.obfuscation.result.MethodResult; +import me.grax.jbytemod.analysis.obfuscation.result.NamesResult; +import me.lpk.util.OpUtils; + +@SuppressWarnings("unused") +public class ObfuscationAnalyzer implements Opcodes { + private Map classes; + + private static final String NONE = "None"; + private static final String ALLATORI = "Allatori"; + private static final String STRINGER = "Stringer"; + private static final String ZKM8 = "ZKM8"; + private static final String ZKM5 = "ZKM5"; + + public ObfuscationAnalyzer(Map classes) { + this.classes = classes; + } + + public NamesResult analyzeNames() { + ArrayList cnames = new ArrayList<>(); + ArrayList mnames = new ArrayList<>(); + ArrayList fnames = new ArrayList<>(); + for (ClassNode cn : classes.values()) { + analyzeName(cn.name, cnames); + for (MethodNode mn : cn.methods) { + analyzeName(mn.name, mnames); + } + for (FieldNode fn : cn.fields) { + analyzeName(fn.name, fnames); + } + } + return new NamesResult(cnames, mnames, fnames); + } + + private static CharsetEncoder asciiEncoder = Charset.forName("US-ASCII").newEncoder(); + + public MethodResult analyzeMethod() { + ArrayList mobf = new ArrayList<>(); + for (ClassNode cn : classes.values()) { + for (MethodNode mn : cn.methods) { + boolean tcbo = false; + if (isTCBO(mn)) { + tcbo = true; + } + boolean pop2 = false; + boolean indyn = false; + boolean strobf = false; + for (AbstractInsnNode ain : mn.instructions.toArray()) { + if (ain.getOpcode() == POP2) { + pop2 = true; + } + if (ain.getOpcode() == INVOKEDYNAMIC) { + indyn = true; + } + if (ain.getOpcode() == LDC) { + LdcInsnNode ldc = (LdcInsnNode) ain; + if (ldc.cst instanceof String && isStringObf(ldc.cst.toString())) { + strobf = true; + } + } + } + if (!tcbo && !pop2 && !indyn && !strobf) { + mobf.add(MethodObfType.NONE); + } else { + if (tcbo) { + mobf.add(MethodObfType.TCBO); + } + if (pop2) { + mobf.add(MethodObfType.POP2); + } + if (indyn) { + mobf.add(MethodObfType.INVOKEDYNAMIC); + } + if (strobf) { + mobf.add(MethodObfType.STRING); + } + } + } + } + return new MethodResult(mobf); + } + + private boolean isStringObf(String string) { + if (string.length() >= 1000) { + return true; + } + int nonAscii = 0; + for (char c : string.toCharArray()) { + if (!asciiEncoder.canEncode(c)) { + nonAscii++; + } + } + double p = nonAscii / (double) string.length(); + return p > 0.5; + } + + private boolean isTCBO(MethodNode mn) { + if (mn.tryCatchBlocks.size() > mn.instructions.size() / 8 || mn.tryCatchBlocks.size() > 15) { + return true; + } + for (TryCatchBlockNode tcbn : mn.tryCatchBlocks) { + int start = OpUtils.getLabelIndex(tcbn.start); + int end = OpUtils.getLabelIndex(tcbn.start); + for (TryCatchBlockNode tcbn2 : mn.tryCatchBlocks) { + int start2 = OpUtils.getLabelIndex(tcbn2.start); + if (start2 >= start && start2 < end) { + return true; + } + } + } + return false; + } + + private static final List keywords = Arrays + .asList(new String[] { "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", + "double", "else", "enum", "extends", "for", "final", "finally", "float", "goto", "if", "implements", "import", "instanceof", "int", + "interface", "long", "native", "new", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super", + "switch", "synchronized", "this", "throw", "throws", "transient", "try", "void", "volatile", "while", "true", "false", "null" }); + + private static final List windir = Arrays.asList(new String[] { "con", "nul", "aux", "prn" }); + + private void analyzeName(String name, ArrayList names) { + boolean none = true; + String sname = name.substring(name.lastIndexOf('/') + 1); + if (sname.length() > 32) { + names.add(NameObfType.LONG_LETTERS); + none = false; + } else if (sname.length() <= 2) { //actually 3 but there are "run", "put" and "get" + names.add(NameObfType.SHORT_LETTERS); + none = false; + } + if (!asciiEncoder.canEncode(sname)) { + names.add(NameObfType.HIGH_CHAR); + none = false; + } + if (keywords.contains(sname)) { + names.add(NameObfType.JAVA_KEYWORD); + none = false; + } else if (windir.contains(sname.toLowerCase())) { + names.add(NameObfType.INVALID_WINDIR); + none = false; + } + if (none) { + names.add(NameObfType.NONE); + } + } + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/obfuscation/enums/MethodObfType.java b/src/main/java/me/grax/jbytemod/analysis/obfuscation/enums/MethodObfType.java new file mode 100644 index 0000000..6b9faf4 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/obfuscation/enums/MethodObfType.java @@ -0,0 +1,17 @@ +package me.grax.jbytemod.analysis.obfuscation.enums; + +public enum MethodObfType { + NONE("None"), TCBO("Unneccesary TCBs"), POP2( + "POP2 Exploit")/* , LOCAL_VAR("Local Var Obf") */, STRING("String Obfuscation"), INVOKEDYNAMIC("Invokedynamic"); + + private final String type; + + private MethodObfType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + +} \ No newline at end of file diff --git a/src/main/java/me/grax/jbytemod/analysis/obfuscation/enums/NameObfType.java b/src/main/java/me/grax/jbytemod/analysis/obfuscation/enums/NameObfType.java new file mode 100644 index 0000000..8edc666 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/obfuscation/enums/NameObfType.java @@ -0,0 +1,17 @@ +package me.grax.jbytemod.analysis.obfuscation.enums; + +public enum NameObfType { + NONE("None"), LONG_LETTERS("Long Letters"), SHORT_LETTERS("Short Letters"), HIGH_CHAR("High UTF8 Values"), JAVA_KEYWORD( + "Java Keywords"), INVALID_WINDIR("Invalid Dir Names"); + + private final String type; + + private NameObfType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + +} \ No newline at end of file diff --git a/src/main/java/me/grax/jbytemod/analysis/obfuscation/result/MethodResult.java b/src/main/java/me/grax/jbytemod/analysis/obfuscation/result/MethodResult.java new file mode 100644 index 0000000..7dec953 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/obfuscation/result/MethodResult.java @@ -0,0 +1,15 @@ +package me.grax.jbytemod.analysis.obfuscation.result; + +import java.util.ArrayList; + +import me.grax.jbytemod.analysis.obfuscation.enums.MethodObfType; + +public class MethodResult { + public ArrayList mobf; + + public MethodResult(ArrayList mobf) { + super(); + this.mobf = mobf; + } + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/obfuscation/result/NamesResult.java b/src/main/java/me/grax/jbytemod/analysis/obfuscation/result/NamesResult.java new file mode 100644 index 0000000..2ba6f18 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/obfuscation/result/NamesResult.java @@ -0,0 +1,19 @@ +package me.grax.jbytemod.analysis.obfuscation.result; + +import java.util.ArrayList; + +import me.grax.jbytemod.analysis.obfuscation.enums.NameObfType; + +public class NamesResult { + public ArrayList cnames; + public ArrayList mnames; + public ArrayList fnames; + + public NamesResult(ArrayList cnames, ArrayList mnames, ArrayList fnames) { + super(); + this.cnames = cnames; + this.mnames = mnames; + this.fnames = fnames; + } + +} diff --git a/src/main/java/me/grax/jbytemod/analysis/utils/BlockUtils.java b/src/main/java/me/grax/jbytemod/analysis/utils/BlockUtils.java new file mode 100644 index 0000000..547a0f9 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/analysis/utils/BlockUtils.java @@ -0,0 +1,27 @@ +package me.grax.jbytemod.analysis.utils; + +import java.util.ArrayList; + +import me.grax.jbytemod.analysis.block.Block; + +public class BlockUtils { + public static boolean doesMerge(Block block, Block into) { + return doesMerge(new ArrayList<>(), block, into); + } + + private static boolean doesMerge(ArrayList visited, Block block, Block into) { + if (visited.contains(block)) { + return false; + } + visited.add(block); + if (block == into) { + return true; + } + for (Block output : block.getOutput()) { + if (doesMerge(visited, output, into)) { + return true; + } + } + return false; + } +} diff --git a/src/main/java/me/grax/jbytemod/decompiler/CFRDecompiler.java b/src/main/java/me/grax/jbytemod/decompiler/CFRDecompiler.java new file mode 100644 index 0000000..bee7cfb --- /dev/null +++ b/src/main/java/me/grax/jbytemod/decompiler/CFRDecompiler.java @@ -0,0 +1,173 @@ +package me.grax.jbytemod.decompiler; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Field; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.benf.cfr.reader.PluginRunner; +import org.benf.cfr.reader.api.ClassFileSource; +import org.benf.cfr.reader.bytecode.analysis.parse.utils.Pair; +import org.benf.cfr.reader.entities.ClassFile; +import org.benf.cfr.reader.entities.Method; +import org.benf.cfr.reader.entities.constantpool.ConstantPool; +import org.benf.cfr.reader.state.ClassFileSourceImpl; +import org.benf.cfr.reader.state.DCCommonState; +import org.benf.cfr.reader.util.bytestream.BaseByteData; +import org.benf.cfr.reader.util.getopt.OptionsImpl; +import org.benf.cfr.reader.util.output.ToStringDumper; +import org.objectweb.asm.tree.MethodNode; + +import me.grax.jbytemod.JByteMod; +import me.grax.jbytemod.ui.DecompilerPanel; + +public class CFRDecompiler extends Decompiler { + + public static final HashMap options = new HashMap<>(); + + public CFRDecompiler(JByteMod jbm, DecompilerPanel dp) { + super(jbm, dp); + } + + static { + options.put("aexagg", "false"); + options.put("allowcorrecting", "true"); + options.put("arrayiter", "true"); + options.put("caseinsensitivefs", "false"); + options.put("clobber", "false"); + options.put("collectioniter", "true"); + options.put("commentmonitors", "false"); + options.put("decodeenumswitch", "true"); + options.put("decodefinally", "true"); + options.put("decodelambdas", "true"); + options.put("decodestringswitch", "true"); + options.put("dumpclasspath", "false"); + options.put("eclipse", "true"); + options.put("elidescala", "false"); + options.put("forcecondpropagate", "false"); + options.put("forceexceptionprune", "false"); + options.put("forcereturningifs", "false"); + options.put("forcetopsort", "false"); + options.put("forcetopsortaggress", "false"); + options.put("forloopaggcapture", "false"); + options.put("hidebridgemethods", "true"); + options.put("hidelangimports", "true"); + options.put("hidelongstrings", "false"); + options.put("hideutf", "true"); + options.put("innerclasses", "true"); + options.put("j14classobj", "false"); + options.put("labelledblocks", "true"); + options.put("lenient", "false"); + options.put("liftconstructorinit", "true"); + options.put("override", "true"); + options.put("pullcodecase", "false"); + options.put("recover", "true"); + options.put("recovertypeclash", "false"); + options.put("recovertypehints", "false"); + options.put("relinkconststring", "true"); + options.put("removebadgenerics", "true"); + options.put("removeboilerplate", "true"); + options.put("removedeadmethods", "true"); + options.put("removeinnerclasssynthetics", "true"); + options.put("rename", "false"); + options.put("renamedupmembers", "false"); + options.put("renameenumidents", "false"); + options.put("renameillegalidents", "false"); + options.put("showinferrable", "false"); + options.put("silent", "false"); + options.put("stringbuffer", "false"); + options.put("stringbuilder", "true"); + options.put("sugarasserts", "true"); + options.put("sugarboxing", "true"); + options.put("sugarenums", "true"); + options.put("tidymonitors", "true"); + options.put("usenametable", "true"); + } + + public String decompile(byte[] b, MethodNode mn) { + try { + HashMap ops = new HashMap<>(); + ops.put("comments", "false"); + for (String key : options.keySet()) { + ops.put(key, String.valueOf(JByteMod.ops.get("cfr_" + key).getBoolean())); + } + ClassFileSource cfs = new ClassFileSource() { + + @Override + public void informAnalysisRelativePathDetail(String a, String b) { + } + + @Override + public String getPossiblyRenamedPath(String path) { + return path; + } + + @Override + public Pair getClassFileContent(String path) throws IOException { + String name = path.substring(0, path.length() - 6); + if (name.equals(cn.name)) { + return Pair.make(b, name); + } + return null; //cfr loads unnecessary classes + } + + @Override + public Collection addJar(String arg0) { + throw new RuntimeException(); + } + }; + PluginRunner runner = new PluginRunner(ops, cfs); + if(mn != null) { + BaseByteData data = new BaseByteData(b); + ClassFile cf = new ClassFile(data, "", initDCState(ops, cfs)); + Field cpf = Method.class.getDeclaredField("cp"); + Field descI = Method.class.getDeclaredField("descriptorIndex"); + descI.setAccessible(true); + cpf.setAccessible(true); + for(Method m : cf.getMethodByName(mn.name)) { + ConstantPool cp = (ConstantPool) cpf.get(m); + if(cp.getUTF8Entry(descI.getInt(m)).getValue().equals(mn.desc)) { + ToStringDumper tsd = new ToStringDumper(); + m.dump(tsd, true); + return tsd.toString(); + } + } + } + String decompilation = runner.getDecompilationFor(cn.name); + System.gc(); //cfr has a performance bug + return decompilation.substring(37); //small hack to remove watermark + } catch (Exception e) { + e.printStackTrace(); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + return sw.toString(); + } + } + + private static DCCommonState initDCState(Map optionsMap, ClassFileSource classFileSource) { + OptionsImpl options = new OptionsImpl(optionsMap); + if (classFileSource == null) classFileSource = new ClassFileSourceImpl(options); + DCCommonState dcCommonState = new DCCommonState(options, classFileSource); + return dcCommonState; + } + + protected Pair getSystemClass(String name, String path) throws IOException { + InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(path); + if (is != null) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[4096]; + int n; + while ((n = is.read(buffer)) > 0) { + baos.write(buffer, 0, n); + } + return Pair.make(baos.toByteArray(), name); + } + return null; + } +} diff --git a/src/main/java/me/grax/jbytemod/decompiler/Decompiler.java b/src/main/java/me/grax/jbytemod/decompiler/Decompiler.java new file mode 100644 index 0000000..db6c7e6 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/decompiler/Decompiler.java @@ -0,0 +1,63 @@ +package me.grax.jbytemod.decompiler; + +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; + +import me.grax.jbytemod.JByteMod; +import me.grax.jbytemod.ui.DecompilerPanel; + +public abstract class Decompiler extends Thread { + protected JByteMod jbm; + protected ClassNode cn; + protected DecompilerPanel dp; + private MethodNode mn; + /** + * Do not reload if we already know the output + */ + public static ClassNode last; + public static MethodNode lastMn; + public static String lastOutput; + + public Decompiler(JByteMod jbm, DecompilerPanel dp) { + this.jbm = jbm; + this.dp = dp; + } + + public Decompiler setNode(ClassNode cn, MethodNode mn) { + this.cn = cn; + this.mn = mn; + return this; + } + + public Decompiler deleteCache() { + last = null; + return this; + } + + @Override + public final void run() { + dp.setText("Loading..."); + if (cn == null) { + dp.setText("ClassNode is null."); + return; + } + dp.setText(lastOutput = this.decompile(cn, mn)); + } + + protected String decompile(ClassNode cn, MethodNode mn) { + if (last != null && cn.equals(last) + && ((lastMn == null && mn == null) || (mn != null && lastMn != null && mn.equals(lastMn)))) { + // same node, same output + return lastOutput; + } + last = cn; + lastMn = mn; + // do not regenerate anything here + ClassWriter cw = new ClassWriter(0); + cn.accept(cw); + return decompile(cw.toByteArray(), mn); + } + + protected abstract String decompile(byte[] b, MethodNode mn); +} diff --git a/src/main/java/me/grax/jbytemod/decompiler/Decompilers.java b/src/main/java/me/grax/jbytemod/decompiler/Decompilers.java new file mode 100644 index 0000000..577a0f3 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/decompiler/Decompilers.java @@ -0,0 +1,25 @@ +package me.grax.jbytemod.decompiler; + +public enum Decompilers { + PROCYON("Procyon", "0.5.32"), FERNFLOWER("Fernflower", ""), CFR("CFR", "1.39"), KRAKATAU("Krakatau", "502"); + private String version; + private String name; + + Decompilers(String name, String version) { + this.name = name; + this.version = version; + } + + public String getVersion() { + return version; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return name + " " + version; + } +} diff --git a/src/main/java/me/grax/jbytemod/decompiler/FernflowerDecompiler.java b/src/main/java/me/grax/jbytemod/decompiler/FernflowerDecompiler.java new file mode 100644 index 0000000..0f73b5b --- /dev/null +++ b/src/main/java/me/grax/jbytemod/decompiler/FernflowerDecompiler.java @@ -0,0 +1,127 @@ +package me.grax.jbytemod.decompiler; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.jar.Manifest; + +import org.jetbrains.java.decompiler.main.Fernflower; +import org.jetbrains.java.decompiler.main.decompiler.PrintStreamLogger; +import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider; +import org.jetbrains.java.decompiler.main.extern.IResultSaver; +import org.jetbrains.java.decompiler.struct.ContextUnit; +import org.jetbrains.java.decompiler.struct.StructClass; +import org.jetbrains.java.decompiler.struct.StructContext; +import org.jetbrains.java.decompiler.struct.lazy.LazyLoader; +import org.objectweb.asm.tree.MethodNode; + +import me.grax.jbytemod.JByteMod; +import me.grax.jbytemod.ui.DecompilerPanel; + +public class FernflowerDecompiler extends Decompiler implements IBytecodeProvider, IResultSaver { + + private byte[] bytes; + private String returned; + + public static final HashMap options = new HashMap<>(); + + static { + options.put("rbr", true); + options.put("rsy", false); + options.put("din", true); + options.put("dc4", true); + options.put("das", true); + options.put("hes", true); + options.put("hdc", true); + options.put("dgs", false); + options.put("ner", true); + options.put("den", true); + options.put("rgn", true); + options.put("lit", false); + options.put("asc", true); + options.put("bto", true); + options.put("nns", false); + options.put("uto", true); + options.put("udv", true); + options.put("rer", true); + options.put("fdi", true); + options.put("ren", false); + options.put("inn", true); + options.put("lac", false); + } + + public FernflowerDecompiler(JByteMod jbm, DecompilerPanel dp) { + super(jbm, dp); + } + + public String decompile(byte[] b, MethodNode mn) { + try { + //TODO decompile method only + this.bytes = b; + HashMap map = new HashMap<>(); + for (String key : options.keySet()) { + map.put(key, JByteMod.ops.get("ff_" + key).getBoolean() ? "1" : "0"); + } + Fernflower f = new Fernflower(this, this, map, new PrintStreamLogger(JByteMod.LOGGER)); + StructContext sc = f.getStructContext(); + StructClass cl = new StructClass(b, true, sc.getLoader()); + sc.getClasses().put(cn.name, cl); + //instead of loading a file use custom bridge, created a few getters + String fakePath = new File("none.class").getAbsolutePath(); + ContextUnit unit = new ContextUnit(ContextUnit.TYPE_FOLDER, null, fakePath, true, sc.getSaver(), sc.getDecompiledData()); + sc.getUnits().put(fakePath, unit); + unit.addClass(cl, "none.class"); + sc.getLoader().addClassLink(cn.name, new LazyLoader.Link(LazyLoader.Link.CLASS, fakePath, null)); + + f.decompileContext(); + return returned; + } catch (Exception e) { + e.printStackTrace(); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + return sw.toString(); + } + } + + @Override + public byte[] getBytecode(String externalPath, String internalPath) throws IOException { + return bytes; + } + + //we can ignore most of those methods because we do not want to save the output as a file + @Override + public void saveFolder(String path) { + } + + @Override + public void copyFile(String source, String path, String entryName) { + } + + @Override + public void saveClassFile(String path, String qualifiedName, String entryName, String content, int[] mapping) { + this.returned = content; + } + + @Override + public void createArchive(String path, String archiveName, Manifest manifest) { + } + + @Override + public void saveDirEntry(String path, String archiveName, String entryName) { + } + + @Override + public void copyEntry(String source, String path, String archiveName, String entry) { + } + + @Override + public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content) { + } + + @Override + public void closeArchive(String path, String archiveName) { + } +} diff --git a/src/main/java/me/grax/jbytemod/decompiler/KrakatauDecompiler.java b/src/main/java/me/grax/jbytemod/decompiler/KrakatauDecompiler.java new file mode 100644 index 0000000..e720133 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/decompiler/KrakatauDecompiler.java @@ -0,0 +1,147 @@ +package me.grax.jbytemod.decompiler; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Collections; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.benf.cfr.reader.bytecode.analysis.parse.utils.Pair; +import org.objectweb.asm.tree.MethodNode; + +import me.grax.jbytemod.JByteMod; +import me.grax.jbytemod.ui.DecompilerPanel; +import me.lpk.util.JarUtils; + +public class KrakatauDecompiler extends Decompiler { + + private static File tempDir = new File(System.getProperty("java.io.tmpdir")); + private static File krakatauDir = new File(tempDir, "krakatau"); + private static File decompile; + + public KrakatauDecompiler(JByteMod jbm, DecompilerPanel dp) { + super(jbm, dp); + } + + public String decompile(byte[] b, MethodNode mn) { + try { + File tempJar = createTempJar(b); + File outputZip = new File(tempDir, b.hashCode() + ".zip"); + if (decompile == null) { + decompile = makeTemp(); + JByteMod.LOGGER.log("Successfully created Krakatau temp folder"); + } + File filePath = jbm.getFilePath(); + String command = getPythonPath() + " " + escape(decompile.getAbsolutePath()) + " -nauto -path " + escape(JarUtils.getRT().getAbsolutePath()) + + ";" + escape(tempJar.getAbsolutePath()) + (filePath != null ? (";" + escape(filePath.getAbsolutePath())) : "") + " -out " + + escape(outputZip.getAbsolutePath()) + " -skip " + escape(tempJar.getAbsolutePath()); + Process p = Runtime.getRuntime().exec(command); + BufferedReader error = new BufferedReader(new InputStreamReader(p.getErrorStream())); + BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream())); + + String s = null; + while ((s = input.readLine()) != null) { + JByteMod.LOGGER.log(s); + } + while ((s = error.readLine()) != null) { + JByteMod.LOGGER.err(s); + } + p.waitFor(); + JByteMod.LOGGER.log("Finished Krakatau emulation"); + ZipInputStream zis = new ZipInputStream(new FileInputStream(outputZip)); + zis.getNextEntry(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len; + while ((len = zis.read(buffer)) > 0) { + out.write(buffer, 0, len); + } + zis.close(); + tempJar.delete(); + outputZip.delete(); + return new String(out.toByteArray(), "UTF-8"); + } catch (Exception e) { + e.printStackTrace(); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + return sw.toString() + "\n\n" + JByteMod.res.getResource("set_py_path"); + } + } + + private String getPythonPath() { + String pp = JByteMod.ops.get("python_path").getString(); + if (!pp.isEmpty()) { + try { + File path = new File(pp); + if (!path.exists()) { + JByteMod.LOGGER.err("Python executable does not exist"); + } else { + return "\"" + path.getAbsolutePath() + "\""; + } + } catch (Exception e) { + JByteMod.LOGGER.err("Invalid python path (" + e.toString() + ")"); + } + } + return "py"; + } + + private String escape(String absolutePath) { + return "\"" + absolutePath.replace('\\', '/') + "\""; + } + + private File createTempJar(byte[] b) { + File temp = new File(tempDir, b.hashCode() + ".jar"); + JarUtils.saveAsJar(Collections.singletonMap(cn.name + ".class", b), temp.getAbsolutePath()); + return temp; + } + + protected Pair getSystemClass(String name, String path) throws IOException { + InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(path); + if (is != null) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[4096]; + int n; + while ((n = is.read(buffer)) > 0) { + baos.write(buffer, 0, n); + } + return Pair.make(baos.toByteArray(), name); + } + return null; + } + + public static File makeTemp() throws IOException { + byte[] buffer = new byte[1024]; + ZipInputStream zis = new ZipInputStream(KrakatauDecompiler.class.getResourceAsStream("/resources/krakatau.zip")); + ZipEntry zipEntry = zis.getNextEntry(); + if (!krakatauDir.exists()) { + krakatauDir.mkdirs(); + } + while (zipEntry != null) { + String fileName = zipEntry.getName(); + File newFile = new File(krakatauDir, fileName); + if (zipEntry.isDirectory()) { + newFile.mkdirs(); + } else { + FileOutputStream fos = new FileOutputStream(newFile); + int len; + while ((len = zis.read(buffer)) > 0) { + fos.write(buffer, 0, len); + } + fos.close(); + } + zipEntry = zis.getNextEntry(); + } + zis.closeEntry(); + zis.close(); + return new File(krakatauDir, "decompile.py"); + } +} diff --git a/src/main/java/me/grax/jbytemod/decompiler/ProcyonDecompiler.java b/src/main/java/me/grax/jbytemod/decompiler/ProcyonDecompiler.java new file mode 100644 index 0000000..086e2e1 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/decompiler/ProcyonDecompiler.java @@ -0,0 +1,79 @@ +package me.grax.jbytemod.decompiler; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Field; + +import org.objectweb.asm.tree.MethodNode; + +import com.strobel.assembler.InputTypeLoader; +import com.strobel.assembler.metadata.Buffer; +import com.strobel.assembler.metadata.ITypeLoader; +import com.strobel.assembler.metadata.MetadataSystem; +import com.strobel.assembler.metadata.TypeDefinition; +import com.strobel.assembler.metadata.TypeReference; +import com.strobel.decompiler.DecompilationOptions; +import com.strobel.decompiler.DecompilerSettings; +import com.strobel.decompiler.PlainTextOutput; + +import me.grax.jbytemod.JByteMod; +import me.grax.jbytemod.ui.DecompilerPanel; +import me.grax.jbytemod.utils.ErrorDisplay; + +public class ProcyonDecompiler extends Decompiler { + + public ProcyonDecompiler(JByteMod jbm, DecompilerPanel dp) { + super(jbm, dp); + } + + public String decompile(byte[] b, MethodNode mn) { + try { + //TODO decompile method only + DecompilerSettings settings = new DecompilerSettings(); + try { + for (Field f : settings.getClass().getDeclaredFields()) { + if (f.getType() == boolean.class) { + f.setAccessible(true); + f.setBoolean(settings, JByteMod.ops.get("procyon" + f.getName()).getBoolean()); + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + settings.setShowSyntheticMembers(true); + MetadataSystem metadataSystem = new MetadataSystem(new ITypeLoader() { + private InputTypeLoader backLoader = new InputTypeLoader(); + + @Override + public boolean tryLoadType(String s, Buffer buffer) { + if (s.equals(cn.name)) { + buffer.putByteArray(b, 0, b.length); + buffer.position(0); + return true; + } else { + return backLoader.tryLoadType(s, buffer); + } + } + }); + TypeReference type = metadataSystem.lookupType(cn.name); + DecompilationOptions decompilationOptions = new DecompilationOptions(); + decompilationOptions.setSettings(DecompilerSettings.javaDefaults()); + decompilationOptions.setFullDecompilation(true); + TypeDefinition resolvedType = null; + if (type == null || ((resolvedType = type.resolve()) == null)) { + new ErrorDisplay("Unable to resolve type."); + return "error"; + } + StringWriter stringwriter = new StringWriter(); + settings.getLanguage().decompileType(resolvedType, new PlainTextOutput(stringwriter), decompilationOptions); + String decompiledSource = stringwriter.toString(); + return decompiledSource; + } catch (Exception e) { + e.printStackTrace(); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + return sw.toString(); + } + } +} diff --git a/src/main/java/me/grax/jbytemod/logging/Logging.java b/src/main/java/me/grax/jbytemod/logging/Logging.java new file mode 100644 index 0000000..a2990b4 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/logging/Logging.java @@ -0,0 +1,85 @@ +package me.grax.jbytemod.logging; + +import java.io.PrintStream; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.apache.commons.io.output.ByteArrayOutputStream; + +import com.alee.managers.notification.NotificationManager; + +import me.grax.jbytemod.JByteMod; + +public class Logging extends PrintStream { + + public Logging() { + super(new ByteArrayOutputStream(), true); + } + + private GuiLogging gl; + private static final SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss"); + + public void log(String text) { + logConsole(getPrefix(Level.INFO), text); + } + + public void logNotification(String text) { + logConsole(getPrefix(Level.INFO), text); + NotificationManager.showNotification(text); + } + + public void warn(String text) { + logConsole(getPrefix(Level.WARN), text); + } + + public void err(String text) { + logConsole(getPrefix(Level.ERROR), text); + } + + public String getPrefix(Level l) { + return "[" + format.format(new Date()) + "] [" + l.name() + "]"; + } + + public enum Level { + WARN, INFO, ERROR + } + + private void logConsole(String prefix, String text) { + System.out.print(prefix); + System.out.print(" "); + System.out.println(text); + + if (gl != null) { + gl.interrupt(); + } + gl = new GuiLogging(text); + gl.start(); + } + + @Override + public void println(String x) { + log(x); + } + + private static class GuiLogging extends Thread { + + private String text; + + public GuiLogging(String text) { + this.text = text; + } + + @Override + public void run() { + JByteMod inst = JByteMod.instance; + if (inst != null) { + inst.getPP().setTip(text); + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + } + inst.getPP().setTip(null); + } + } + } +} diff --git a/src/main/java/me/grax/jbytemod/plugin/Plugin.java b/src/main/java/me/grax/jbytemod/plugin/Plugin.java new file mode 100644 index 0000000..af8f899 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/plugin/Plugin.java @@ -0,0 +1,67 @@ +package me.grax.jbytemod.plugin; + +import java.util.Map; + +import javax.swing.JMenuBar; +import javax.swing.JTree; + +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; + +import me.grax.jbytemod.JByteMod; + +public abstract class Plugin { + protected String name; + protected String version; + protected String author; + + public Plugin(String name, String version, String author) { + this.name = name; + this.version = version; + this.author = author; + } + + public abstract void init(); + + public abstract void loadFile(Map map); + + public abstract boolean isClickable(); + + public abstract void menuClick(); + + protected final Map getCurrentFile() { + return JByteMod.instance.getFile().getClasses(); + } + + protected final void updateTree() { + JByteMod.instance.refreshTree(); + } + + protected final JMenuBar getMenu() { + return JByteMod.instance.getMyMenuBar(); + } + + protected final JTree gerTree() { + return JByteMod.instance.getJarTree(); + } + + protected final ClassNode gerSelectedNode() { + return JByteMod.instance.getCurrentNode(); + } + + protected final MethodNode gerSelectedMethod() { + return JByteMod.instance.getCurrentMethod(); + } + + public final String getName() { + return name; + } + + public final String getVersion() { + return version; + } + + public final String getAuthor() { + return author; + } +} diff --git a/src/main/java/me/grax/jbytemod/plugin/PluginManager.java b/src/main/java/me/grax/jbytemod/plugin/PluginManager.java new file mode 100644 index 0000000..d51011f --- /dev/null +++ b/src/main/java/me/grax/jbytemod/plugin/PluginManager.java @@ -0,0 +1,80 @@ +package me.grax.jbytemod.plugin; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import me.grax.jbytemod.JByteMod; + +public class PluginManager { + + private File pluginFolder = new File(JByteMod.workingDir, "plugins"); + + private final ArrayList plugins = new ArrayList<>(); + + public PluginManager(JByteMod jbm) { + if (pluginFolder.exists() && pluginFolder.isDirectory()) { + loadPlugins(); + } else { + JByteMod.LOGGER.err("No plugin folder found!"); + } + } + + @SuppressWarnings("deprecation") + private void loadPlugins() { + for (File f : pluginFolder.listFiles()) { + if (f.getName().endsWith(".jar")) { + try { + ZipFile zip = new ZipFile(f); + Enumeration entries = zip.entries(); + addURL(f.toURL()); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + String name = entry.getName(); + if (name.endsWith(".class")) { + try { + Class loaded = Class.forName(name.replace('/', '.').substring(0, name.length() - 6), true, ClassLoader.getSystemClassLoader()); + if (Plugin.class.isAssignableFrom(loaded)) { + Plugin p = (Plugin) loaded.newInstance(); + p.init(); + this.plugins.add(p); + break; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + zip.close(); + } catch (Exception e) { + e.printStackTrace(); + JByteMod.LOGGER.err("Plugin " + f.getName() + " failed to load!"); + } + } + } + JByteMod.LOGGER.log(plugins.size() + " plugin(s) loaded!"); + } + + public static void addURL(URL u) throws IOException { + URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader(); + Class sysclass = URLClassLoader.class; + try { + Method method = sysclass.getDeclaredMethod("addURL", new Class[] { URL.class }); + method.setAccessible(true); + method.invoke(sysloader, new Object[] { u }); + } catch (Throwable t) { + t.printStackTrace(); + } + } + + public ArrayList getPlugins() { + return plugins; + } + +} diff --git a/src/main/java/me/grax/jbytemod/res/LanguageRes.java b/src/main/java/me/grax/jbytemod/res/LanguageRes.java new file mode 100644 index 0000000..eaddc18 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/res/LanguageRes.java @@ -0,0 +1,101 @@ +package me.grax.jbytemod.res; + +import java.awt.Font; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.alee.laf.WebLookAndFeel; + +import me.grax.jbytemod.JByteMod; +import me.grax.jbytemod.utils.ErrorDisplay; + +public class LanguageRes { + private final HashMap map = new HashMap<>(); + private final HashMap defaultMap = new HashMap<>(); + + public LanguageRes() { + JByteMod.LOGGER.log("Reading Language XML.."); + this.readXML(map, getXML()); + this.readXML(defaultMap, LanguageRes.class.getResourceAsStream("/locale/en.xml")); + JByteMod.LOGGER.log("Successfully loaded " + map.size() + " local resources and " + defaultMap.size() + " default resources"); + this.fixUnicodeSupport(); + } + + private void fixUnicodeSupport() { + for (String translation : map.values()) { + for (char c : translation.toCharArray()) { + if (!WebLookAndFeel.globalControlFont.canDisplay(c)) { + WebLookAndFeel.globalControlFont = fixFont(WebLookAndFeel.globalControlFont); + WebLookAndFeel.globalTooltipFont = fixFont(WebLookAndFeel.globalTooltipFont); + WebLookAndFeel.globalAlertFont = fixFont(WebLookAndFeel.globalAlertFont); + WebLookAndFeel.globalMenuFont = fixFont(WebLookAndFeel.globalMenuFont); + WebLookAndFeel.globalAcceleratorFont = fixFont(WebLookAndFeel.globalAcceleratorFont); + WebLookAndFeel.globalTitleFont = fixFont(WebLookAndFeel.globalTitleFont); + WebLookAndFeel.globalTextFont = fixFont(WebLookAndFeel.globalTextFont); + JByteMod.LOGGER.log("Updated WebLaF fonts for unicode support"); + return; + } + } + } + JByteMod.LOGGER.log("Unicode check finished!"); + } + + private Font fixFont(Font font) { + return new Font(null, font.getStyle(), font.getSize()); + } + + public String getResource(String desc) { + return map.getOrDefault(desc, defaultMap.getOrDefault(desc, desc)); + } + + private void readXML(Map m, InputStream is) { + try { + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + Document doc = dBuilder.parse(is); + doc.getDocumentElement().normalize(); + Element resources = doc.getDocumentElement(); + NodeList nodes = resources.getChildNodes(); + for (int i = 0; i < nodes.getLength(); i++) { + Node e = (Node) nodes.item(i); + if (e.getNodeName().equals("string")) { + Element el = (Element) e; + m.put(el.getAttribute("name"), e.getTextContent()); + } + } + } catch (Exception e) { + JByteMod.LOGGER.err("Failed to load resources: " + e.getMessage()); + e.printStackTrace(); + new ErrorDisplay(e); + } + } + + private InputStream getXML() { + return LanguageRes.class.getResourceAsStream("/locale/en.xml"); + + /* + InputStream is = LanguageRes.class.getResourceAsStream("/locale/" + this.getLanguage() + ".xml"); + if (is == null) { + JByteMod.LOGGER.warn("Locale not found, using default en.xml"); + is = LanguageRes.class.getResourceAsStream("/locale/en.xml"); + if (is == null) { + JByteMod.LOGGER.err("en.xml not found!"); + } + } + return is; + */ + } + + private String getLanguage() { + return System.getProperty("user.language").toLowerCase().replace('_', '-'); + } +} diff --git a/src/main/java/me/grax/jbytemod/res/Option.java b/src/main/java/me/grax/jbytemod/res/Option.java new file mode 100644 index 0000000..4111c2d --- /dev/null +++ b/src/main/java/me/grax/jbytemod/res/Option.java @@ -0,0 +1,79 @@ +package me.grax.jbytemod.res; + +public class Option { + + private String name; + private String group; + + private Object value; + private Type type; + + public Option(String name, Object value, Type type) { + this(name, value, type, "general"); + } + + public Option(String name, Object value, Type type, String group) { + this.name = name; + switch (type) { + case INT: + this.value = Integer.parseInt(value.toString()); + break; + case BOOLEAN: + this.value = Boolean.parseBoolean(value.toString()); + break; + default: + this.value = value; + break; + } + this.type = type; + this.group = group; + } + + public boolean getBoolean() { + return (boolean) value; + } + + public String getString() { + return (String) value; + } + + public int getInteger() { + return (int) value; + } + + public void setValue(Object value) { + this.value = value; + } + + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Object getValue() { + return value; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + public enum Type { + BOOLEAN, STRING, INT + } +} diff --git a/src/main/java/me/grax/jbytemod/res/Options.java b/src/main/java/me/grax/jbytemod/res/Options.java new file mode 100644 index 0000000..ac2b414 --- /dev/null +++ b/src/main/java/me/grax/jbytemod/res/Options.java @@ -0,0 +1,167 @@ +package me.grax.jbytemod.res; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.Field; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map.Entry; + +import javax.swing.JOptionPane; + +import com.strobel.decompiler.DecompilerSettings; + +import me.grax.jbytemod.JByteMod; +import me.grax.jbytemod.decompiler.CFRDecompiler; +import me.grax.jbytemod.decompiler.FernflowerDecompiler; +import me.grax.jbytemod.res.Option.Type; +import me.grax.jbytemod.utils.ErrorDisplay; + +public class Options { + private static final File propFile = new File(JByteMod.workingDir, JByteMod.configPath); + + public List