EaglerForge/NoReflect/javaRecon.js

180 lines
6.6 KiB
JavaScript
Raw Permalink Normal View History

2024-05-21 06:07:24 -05:00
const getStatements = {
"int": "params.getInt(%s)",
"String": "params.getString(%s)",
"boolean": "params.getBoolean(%s)",
"float": "params.getFloat(%s)",
"byte": "params.getByte(%s)",
"char": "params.getChar(%s)",
"double": "params.getDouble(%s)",
}
2024-05-24 03:39:34 -05:00
const primitiveDefaultValues = {
"int": "0",
"String": "\"\"",
"boolean": "false",
"float": "0.0f",
"byte": "(byte) 0",
"char": "\'a\'",
"double": "0.0d",
}
2024-05-21 19:04:52 -05:00
const callbackStatements = {
"boolean": "setCallbackBooleanWithDataArg",
"int": "setCallbackIntWithDataArg",
"String": "setCallbackStringWithDataArg",
"double": "setCallbackDoubleWithDataArg",
"float": "setCallbackFloatWithDataArg",
}
2024-05-21 06:07:24 -05:00
const getStatementsTypes = Object.keys(getStatements);
2024-05-21 19:04:52 -05:00
const callbackStatementsTypes = Object.keys(callbackStatements);
2024-05-21 06:07:24 -05:00
function reconJ(java, className) {
2024-05-21 19:04:52 -05:00
var usedClasses = [];
var javaText = java;
javaText = javaText.replace(/\/\/.*$/gm, '');
javaText = javaText.replace(/\/\*[\s\S]*?\*\//gm, '');
javaText = javaText.replace(/[ \t](public|private|protected|)\s*(static|) (class|enum) .+ \{(\W|\w)*?\n(\t)\}/gm, '');
2024-05-21 19:04:52 -05:00
2024-05-21 06:07:24 -05:00
let constructorRegex = /(public|protected|private|static|\s) +(\w+) *\(([^)]*)\)/g;
2024-05-21 19:04:52 -05:00
let constructors = [...javaText.matchAll(constructorRegex).filter((line)=>{
2024-05-24 03:39:34 -05:00
return !line[0].includes(" private ") && !line[0].includes(" protected ") && !line[0].includes("\n\t\t") && line[1] !== "private" && line[1] !== "protected";
2024-05-21 06:07:24 -05:00
})];
if (javaText.match(/^(public|private|protected|) abstract class /gm)) {
constructors = [];
}
2024-05-21 06:07:24 -05:00
let constructorDetails = constructors.map((constructor) => {
let constructorName = constructor[2];
let argumentString = constructor[3];
let arguments = {};
if (argumentString.trim().length > 0) {
let argumentList = argumentString.split(",");
argumentList.forEach((argument) => {
let [type, name] = argument.trim().split(" ");
arguments[name] = type;
});
}
let argStr = "";
var argumentsKeys = Object.keys(arguments);
for (let i = 0; i < argumentsKeys.length; i++) {
const key = argumentsKeys[i];
2024-05-21 19:04:52 -05:00
if (!getStatementsTypes.includes(arguments[key])) {
usedClasses.push(arguments[key]);
}
2024-05-21 06:07:24 -05:00
argStr += `(${arguments[key]}) ${getStatementsTypes.includes(arguments[key]) ? getStatements[arguments[key]].replaceAll("%s", "\""+key+"\"") : `params.getReflective("${key}")`}`;
if (i !== argumentsKeys.length - 1) {
argStr += ", "
}
}
2024-05-27 03:02:40 -05:00
let impl = `setCallbackReflectiveWithDataArg("exec", (BaseData params) -> {
2024-05-21 19:04:52 -05:00
return new ${className}(${argStr});
2024-05-21 06:07:24 -05:00
});
`;
return {
name: constructorName,
idx: constructors.indexOf(constructor),
arguments: arguments,
2024-05-24 03:39:34 -05:00
impl: impl,
data: constructor
2024-05-21 06:07:24 -05:00
};
});
let methodRegex = /(public|static|private|protected|final|\s)* +([\w\<\>\[\]]+)\s+(\w+) *\(([^)]*)\)/g;
2024-05-21 19:04:52 -05:00
let methods = [...javaText.matchAll(methodRegex).filter((line)=>{
return !line[0].includes("> ") && !line[0].startsWith(" else ") && !line[0].startsWith(" new ") && !line[0].includes(" private ") && !line[0].includes("\tprotected ") && !line[0].includes("\tprivate ") && !line[0].includes(" protected ") && !line[0].includes("\n\t\t") && line[0].includes("public ");
2024-05-21 19:04:52 -05:00
//Doesn't support Type<Subtype> yet
})];
let methodDetails = methods.map((method) => {
let isStatic = `${method[1]}`.includes("static");
let returnType = method[2];
let methodName = method[3];
let argumentString = method[4];
let arguments = {};
let methodContainsInlineClasses = false;
2024-05-21 19:04:52 -05:00
if (argumentString.trim().length > 0) {
let argumentList = argumentString.split(",");
argumentList.forEach((argument) => {
let [type, name] = argument.trim().split(" ").filter(potential => {
return potential !== "final";
});
if (type.includes(".")) {
methodContainsInlineClasses = true;
}
2024-05-21 19:04:52 -05:00
arguments[name] = type;
});
}
if (methodContainsInlineClasses) {
return false;
}
2024-05-21 19:04:52 -05:00
let argStr = "";
var argumentsKeys = Object.keys(arguments);
for (let i = 0; i < argumentsKeys.length; i++) {
const key = argumentsKeys[i];
if (!getStatementsTypes.includes(arguments[key])) {
usedClasses.push(arguments[key]);
}
argStr += `(${arguments[key]}) ${getStatementsTypes.includes(arguments[key]) ? getStatements[arguments[key]].replaceAll("%s", "\""+key+"\"") : `params.getReflective("${key}")`}`;
if (i !== argumentsKeys.length - 1) {
argStr += ", "
}
}
2024-05-24 02:44:10 -05:00
let prefix = isStatic ? className : `((${className}) params.getReflective("_self"))`;
2024-05-21 19:04:52 -05:00
let impl;
if (returnType === "void") {
2024-05-27 03:02:40 -05:00
impl = `setCallbackVoidWithDataArg("exec", (BaseData params) -> {
2024-05-24 03:39:34 -05:00
try {
${prefix}.${methodName}(${argStr});
} catch (Exception _exception_reflect_) {
return;
}
2024-05-21 19:04:52 -05:00
});
`;
} else if (callbackStatementsTypes.includes(returnType)) {
2024-05-27 03:02:40 -05:00
impl = `${callbackStatements[returnType]}("exec", (BaseData params) -> {
2024-05-24 03:39:34 -05:00
try {
return (${returnType}) ${prefix}.${methodName}(${argStr});
} catch (Exception _exception_reflect_) {
return ${primitiveDefaultValues[returnType]};
}
2024-05-21 19:04:52 -05:00
});
`;
} else {
usedClasses.push(returnType);
2024-05-27 03:02:40 -05:00
impl = `setCallbackReflectiveWithDataArg("exec", (BaseData params) -> {
2024-05-24 03:39:34 -05:00
try {
return (${returnType}) ${prefix}.${methodName}(${argStr});
} catch (Exception _exception_reflect_) {
return null;
}
2024-05-21 19:04:52 -05:00
});
`;
}
return {
name: methodName,
returnType: returnType,
isStatic: isStatic,
arguments: arguments,
impl: impl,
2024-05-24 03:39:34 -05:00
idx: methods.indexOf(method),
data: method
2024-05-21 19:04:52 -05:00
};
});
2024-05-21 06:07:24 -05:00
return {
className: className,
constructors: constructorDetails.filter(obj => obj),
methods: methodDetails.filter(obj => obj),
2024-05-21 19:04:52 -05:00
usedClasses: [...new Set(usedClasses)]
2024-05-21 06:07:24 -05:00
}
}