diff --git a/parabotv2/src/org/parabot/core/asm/hooks/HookFile.java b/parabotv2/src/org/parabot/core/asm/hooks/HookFile.java new file mode 100644 index 0000000..d438e19 --- /dev/null +++ b/parabotv2/src/org/parabot/core/asm/hooks/HookFile.java @@ -0,0 +1,50 @@ +package org.parabot.core.asm.hooks; + +import java.io.File; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; + +import org.parabot.core.parsers.HookParser; +import org.parabot.core.parsers.JSONHookParser; +import org.parabot.core.parsers.XMLHookParser; +import org.parabot.environment.api.utils.WebUtil; + +public class HookFile { + public static final int TYPE_XML = 0; + public static final int TYPE_JSON = 1; + + private URL url; + private int type; + + public HookFile(File file, int type) throws MalformedURLException { + this(file.toURI().toURL(), type); + } + + public HookFile(URL url, int type) { + setType(type); + this.url = url; + this.type = type; + } + + private void setType(int type) { + if(type < 0 || type > 1) { + throw new IllegalArgumentException("This type does not exist"); + } + } + + public InputStream getInputStream() { + return WebUtil.getInputStream(url); + } + + public HookParser getParser() { + switch(type) { + case TYPE_XML: + return new XMLHookParser(this); + case TYPE_JSON: + return new JSONHookParser(this); + } + return null; + } + +} diff --git a/parabotv2/src/org/parabot/core/parsers/HookParser.java b/parabotv2/src/org/parabot/core/parsers/HookParser.java index 68a7bdd..99533cd 100644 --- a/parabotv2/src/org/parabot/core/parsers/HookParser.java +++ b/parabotv2/src/org/parabot/core/parsers/HookParser.java @@ -1,17 +1,8 @@ package org.parabot.core.parsers; -import org.parabot.core.asm.adapters.AddInterfaceAdapter; +import org.parabot.core.asm.hooks.HookFile; import org.parabot.core.asm.interfaces.Injectable; import org.parabot.core.asm.wrappers.*; -import org.parabot.environment.api.utils.WebUtil; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import java.net.URL; import java.util.ArrayList; import java.util.HashMap; @@ -21,171 +12,26 @@ import java.util.HashMap; * * @author Everel */ -public class HookParser { - private Document doc = null; - private boolean parsedInterfaces = false; - private HashMap interfaceMap = new HashMap(); +public abstract class HookParser { - private HashMap constants = new HashMap(); - public HookParser(URL url) { - try { - DocumentBuilderFactory dbFactory = DocumentBuilderFactory - .newInstance(); - DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); - doc = dBuilder.parse(WebUtil.getInputStream(url)); - doc.getDocumentElement().normalize(); - if (!doc.getDocumentElement().getNodeName().equals("injector")) { - throw new RuntimeException("Incorrect hook file."); - } - } catch (Throwable t) { - throw new RuntimeException("Unable to parse hooks " + t); - } + public HookParser(HookFile hookFile) { + } - public final Interface[] getInterfaces() { - parsedInterfaces = true; - final NodeList interfaceRootList = doc - .getElementsByTagName("interfaces"); - switch (interfaceRootList.getLength()) { - case 0: - return null; - case 1: - break; - default: - throw new RuntimeException( - "Hook file may not contains multiple tags "); - } - final Node node = interfaceRootList.item(0); - if (node.getNodeType() != Node.ELEMENT_NODE) { - return null; - } - final Element interfaceRoot = (Element) node; - final NodeList interfaces = interfaceRoot.getElementsByTagName("add"); - if (interfaces.getLength() == 0) { - return null; - } - final ArrayList interfaceList = new ArrayList(); - for (int x = 0; x < interfaces.getLength(); x++) { - final Node n = interfaces.item(x); - if (n.getNodeType() != Node.ELEMENT_NODE) { - continue; - } - final Element addInterface = (Element) n; - final String className = getValue("classname", addInterface); - final String interfaceClass = getValue("interface", addInterface); - interfaceMap.put(interfaceClass, className); - final Interface inf = new Interface(className, interfaceClass); - interfaceList.add(inf); - } - return interfaceList.toArray(new Interface[interfaceList.size()]); - } + public abstract Interface[] getInterfaces(); - public final Super[] getSupers() { - final NodeList interfaceRootList = doc.getElementsByTagName("supers"); - switch (interfaceRootList.getLength()) { - case 0: - return null; - case 1: - break; - default: - throw new RuntimeException( - "Hook file may not contains multiple tags "); - } - final Node node = interfaceRootList.item(0); - if (node.getNodeType() != Node.ELEMENT_NODE) { - return null; - } - final Element superRoot = (Element) node; - final NodeList supers = superRoot.getElementsByTagName("add"); - if (supers.getLength() == 0) { - return null; - } - final ArrayList superList = new ArrayList(); - for (int x = 0; x < supers.getLength(); x++) { - final Node n = supers.item(x); - if (n.getNodeType() != Node.ELEMENT_NODE) { - continue; - } - final Element addSuper = (Element) n; - final String className = getValue("classname", addSuper); - final String superClass = getValue("super", addSuper); - final Super sup = new Super(className, superClass); - superList.add(sup); - } - return superList.toArray(new Super[superList.size()]); - } + public abstract Super[] getSupers(); - public final Getter[] getGetters() { - final NodeList getterRootList = doc.getElementsByTagName("getters"); - switch (getterRootList.getLength()) { - case 0: - return null; - case 1: - break; - default: - throw new RuntimeException( - "Hook file may not contains multiple tags "); - } - final Node node = getterRootList.item(0); - if (node.getNodeType() != Node.ELEMENT_NODE) { - return null; - } - final Element getterRoot = (Element) node; - final NodeList getters = getterRoot.getElementsByTagName("add"); - if (getters.getLength() == 0) { - return null; - } - final ArrayList getterList = new ArrayList(); - for (int x = 0; x < getters.getLength(); x++) { - final Node n = getters.item(x); - if (n.getNodeType() != Node.ELEMENT_NODE) { - continue; - } - final Element addGetter = (Element) n; - if (isSet("classname", addGetter) && isSet("accessor", addGetter)) { - throw new RuntimeException( - "Can't set classname and accessor tag together."); - } - if (isSet("accessor", addGetter) && !parsedInterfaces) { - throw new RuntimeException( - "You'll need to parse interfaces first."); - } - final String className = isSet("classname", addGetter) ? getValue( - "classname", addGetter) : interfaceMap.get(getValue( - "accessor", addGetter)); - final String into = isSet("into", addGetter) ? getValue("into", - addGetter) : className; - final String fieldName = getValue("field", addGetter); - final String methodName = getValue("methodname", addGetter); - boolean staticMethod = isSet("methstatic", addGetter) ? (getValue( - "methstatic", addGetter).equals("true")) : false; - String returnDesc = isSet("desc", addGetter) ? getValue("desc", - addGetter) : null; - String array = ""; - if (returnDesc != null && returnDesc.contains("%s")) { - StringBuilder str = new StringBuilder(); - if (returnDesc.startsWith("[")) { - for (int i = 0; i < returnDesc.length(); i++) { - if (returnDesc.charAt(i) == '[') { - array += '['; - } - } - returnDesc = returnDesc.replaceAll("\\[", ""); - } - str.append(array) - .append('L') - .append(String.format(returnDesc, - AddInterfaceAdapter.getAccessorPackage())) - .append(";"); - returnDesc = str.toString(); - } - final Getter get = new Getter(into, className, fieldName, - methodName, returnDesc, staticMethod); - getterList.add(get); - } - return getterList.toArray(new Getter[getterList.size()]); - } + public abstract Getter[] getGetters(); + + public abstract Setter[] getSetters(); + + public abstract Invoker[] getInvokers(); + + public abstract Callback[] getCallbacks(); + + public abstract HashMap getConstants(); public Injectable[] getInjectables() { ArrayList injectables = new ArrayList(); @@ -228,253 +74,4 @@ public class HookParser { return injectables.toArray(new Injectable[injectables.size()]); } - public final Setter[] getSetters() { - final NodeList setterRootList = doc.getElementsByTagName("setters"); - switch (setterRootList.getLength()) { - case 0: - return null; - case 1: - break; - default: - throw new RuntimeException( - "Hook file may not contains multiple tags "); - } - final Node node = setterRootList.item(0); - if (node.getNodeType() != Node.ELEMENT_NODE) { - return null; - } - final Element setterRoot = (Element) node; - final NodeList setters = setterRoot.getElementsByTagName("add"); - if (setters.getLength() == 0) { - return null; - } - final ArrayList setterList = new ArrayList(); - for (int x = 0; x < setters.getLength(); x++) { - final Node n = setters.item(x); - if (n.getNodeType() != Node.ELEMENT_NODE) { - continue; - } - final Element addSetter = (Element) n; - if (isSet("classname", addSetter) && isSet("accessor", addSetter)) { - throw new RuntimeException( - "Can't set classname and accessor tag together."); - } - if (isSet("accessor", addSetter) && !parsedInterfaces) { - throw new RuntimeException( - "You'll need to parse interfaces first."); - } - final String className = isSet("classname", addSetter) ? getValue( - "classname", addSetter) : interfaceMap.get(getValue( - "accessor", addSetter)); - final String into = isSet("into", addSetter) ? getValue("into", - addSetter) : className; - final String fieldName = getValue("field", addSetter); - final String methodName = getValue("methodname", addSetter); - boolean staticMethod = isSet("methstatic", addSetter) ? (getValue( - "methstatic", addSetter).equals("true")) : false; - String returnDesc = isSet("desc", addSetter) ? getValue("desc", - addSetter) : null; - String array = ""; - if (returnDesc != null && returnDesc.contains("%s")) { - StringBuilder str = new StringBuilder(); - if (returnDesc.startsWith("[")) { - for (int i = 0; i < returnDesc.length(); i++) { - if (returnDesc.charAt(i) == '[') { - array += '['; - } - } - returnDesc = returnDesc.replaceAll("\\[", ""); - } - str.append(array) - .append('L') - .append(String.format(returnDesc, - AddInterfaceAdapter.getAccessorPackage())) - .append(";"); - returnDesc = str.toString(); - } - final Setter get = new Setter(className, into, fieldName, - methodName, returnDesc, staticMethod); - setterList.add(get); - } - return setterList.toArray(new Setter[setterList.size()]); - } - - public final Invoker[] getInvokers() { - final NodeList invokerRootList = doc.getElementsByTagName("invokers"); - switch (invokerRootList.getLength()) { - case 0: - return null; - case 1: - break; - default: - throw new RuntimeException( - "Hook file may not contains multiple tags "); - } - final Node node = invokerRootList.item(0); - if (node.getNodeType() != Node.ELEMENT_NODE) { - return null; - } - final Element invokerRoot = (Element) node; - final NodeList invokers = invokerRoot.getElementsByTagName("add"); - if (invokers.getLength() == 0) { - return null; - } - final ArrayList invokerList = new ArrayList(); - for (int x = 0; x < invokers.getLength(); x++) { - final Node n = invokers.item(x); - if (n.getNodeType() != Node.ELEMENT_NODE) { - continue; - } - final Element addInvoker = (Element) n; - if (isSet("classname", addInvoker) && isSet("accessor", addInvoker)) { - throw new RuntimeException( - "Can't set classname and accessor tag together."); - } - if (isSet("accessor", addInvoker) && !parsedInterfaces) { - throw new RuntimeException( - "You'll need to parse interfaces first."); - } - final String className = isSet("classname", addInvoker) ? getValue( - "classname", addInvoker) : interfaceMap.get(getValue( - "accessor", addInvoker)); - final String into = isSet("into", addInvoker) ? getValue("into", - addInvoker) : className; - final String methodName = getValue("methodname", addInvoker); - final String invMethodName = getValue("invokemethod", addInvoker); - final String argsDesc = getValue("argsdesc", addInvoker); - String returnDesc = isSet("desc", addInvoker) ? resolveDesc(getValue( - "desc", addInvoker)) : null; - - final Invoker invoker = new Invoker(into, className, invMethodName, - argsDesc, returnDesc, methodName); - invokerList.add(invoker); - } - return invokerList.toArray(new Invoker[invokerList.size()]); - } - - public final Callback[] getCallbacks() { - final NodeList callbackRootList = doc.getElementsByTagName("callbacks"); - switch (callbackRootList.getLength()) { - case 0: - return null; - case 1: - break; - default: - throw new RuntimeException( - "Hook file may not contains multiple tags "); - } - final Node node = callbackRootList.item(0); - if (node.getNodeType() != Node.ELEMENT_NODE) { - return null; - } - final Element callbackRoot = (Element) node; - final NodeList callbacks = callbackRoot.getElementsByTagName("add"); - if (callbacks.getLength() == 0) { - return null; - } - final ArrayList callbackList = new ArrayList(); - for (int x = 0; x < callbacks.getLength(); x++) { - final Node n = callbacks.item(x); - if (n.getNodeType() != Node.ELEMENT_NODE) { - continue; - } - final Element addCallback = (Element) n; - if (isSet("classname", addCallback) - && isSet("accessor", addCallback)) { - throw new RuntimeException( - "Can't set classname and accessor tag together."); - } - if (isSet("accessor", addCallback) && !parsedInterfaces) { - throw new RuntimeException( - "You'll need to parse interfaces first."); - } - final String className = isSet("classname", addCallback) ? getValue( - "classname", addCallback) : interfaceMap.get(getValue( - "accessor", addCallback)); - - final String methodName = getValue("methodname", addCallback); - final String callClass = getValue("callclass", addCallback); - final String callMethod = getValue("callmethod", addCallback); - final String callDesc = getValue("calldesc", addCallback); - final String callArgs = getValue("callargs", addCallback); - final String desc = getValue("desc", addCallback); - - final Callback callback = new Callback(className, methodName, desc, - callClass, callMethod, callDesc, callArgs); - callbackList.add(callback); - } - return callbackList.toArray(new Callback[callbackList.size()]); - } - - private static String resolveDesc(String returnDesc) { - String array = ""; - if (returnDesc != null && returnDesc.contains("%s")) { - StringBuilder str = new StringBuilder(); - if (returnDesc.startsWith("[")) { - for (int i = 0; i < returnDesc.length(); i++) { - if (returnDesc.charAt(i) == '[') { - array += '['; - } - } - returnDesc = returnDesc.replaceAll("\\[", ""); - } - str.append(array) - .append('L') - .append(String.format(returnDesc, - AddInterfaceAdapter.getAccessorPackage())) - .append(";"); - returnDesc = str.toString(); - } - return returnDesc; - } - - private static final boolean isSet(String tag, Element element) { - return element.getElementsByTagName(tag).getLength() > 0; - } - - private static final String getValue(String tag, Element element) { - NodeList nodes = element.getElementsByTagName(tag).item(0) - .getChildNodes(); - Node node = (Node) nodes.item(0); - return node.getNodeValue(); - } - - public final HashMap getConstants() { - if (!constants.isEmpty()) { - return constants; - } - final NodeList constantsRootList = doc - .getElementsByTagName("constants"); - switch (constantsRootList.getLength()) { - case 0: - return null; - case 1: - break; - default: - throw new RuntimeException( - "Hook file may not contains multiple tags "); - } - final Node node = constantsRootList.item(0); - if (node.getNodeType() != Node.ELEMENT_NODE) { - return null; - } - final Element constantRoot = (Element) node; - final NodeList constantsList = constantRoot.getElementsByTagName("add"); - if (constantsList.getLength() == 0) { - // return empty hashmap - return constants; - } - for (int x = 0; x < constantsList.getLength(); x++) { - final Node n = constantsList.item(x); - if (n.getNodeType() != Node.ELEMENT_NODE) { - continue; - } - final Element addConstant = (Element) n; - final String key = getValue("key", addConstant); - final String value = getValue("value", addConstant); - constants.put(key, value); - } - return constants; - } - } diff --git a/parabotv2/src/org/parabot/core/parsers/JSONHookParser.java b/parabotv2/src/org/parabot/core/parsers/JSONHookParser.java new file mode 100644 index 0000000..0969e7d --- /dev/null +++ b/parabotv2/src/org/parabot/core/parsers/JSONHookParser.java @@ -0,0 +1,54 @@ +package org.parabot.core.parsers; + +import java.util.HashMap; + +import org.parabot.core.asm.hooks.HookFile; +import org.parabot.core.asm.wrappers.Callback; +import org.parabot.core.asm.wrappers.Getter; +import org.parabot.core.asm.wrappers.Interface; +import org.parabot.core.asm.wrappers.Invoker; +import org.parabot.core.asm.wrappers.Setter; +import org.parabot.core.asm.wrappers.Super; + +public class JSONHookParser extends HookParser { + + public JSONHookParser(HookFile hookFile) { + super(hookFile); + } + + @Override + public Interface[] getInterfaces() { + return null; + } + + @Override + public Super[] getSupers() { + return null; + } + + @Override + public Getter[] getGetters() { + return null; + } + + @Override + public Setter[] getSetters() { + return null; + } + + @Override + public Invoker[] getInvokers() { + return null; + } + + @Override + public Callback[] getCallbacks() { + return null; + } + + @Override + public HashMap getConstants() { + return null; + } + +} diff --git a/parabotv2/src/org/parabot/core/parsers/XMLHookParser.java b/parabotv2/src/org/parabot/core/parsers/XMLHookParser.java new file mode 100644 index 0000000..c492385 --- /dev/null +++ b/parabotv2/src/org/parabot/core/parsers/XMLHookParser.java @@ -0,0 +1,447 @@ +package org.parabot.core.parsers; + +import java.util.ArrayList; +import java.util.HashMap; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.parabot.core.asm.adapters.AddInterfaceAdapter; +import org.parabot.core.asm.hooks.HookFile; +import org.parabot.core.asm.wrappers.Callback; +import org.parabot.core.asm.wrappers.Getter; +import org.parabot.core.asm.wrappers.Interface; +import org.parabot.core.asm.wrappers.Invoker; +import org.parabot.core.asm.wrappers.Setter; +import org.parabot.core.asm.wrappers.Super; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class XMLHookParser extends HookParser { + private boolean parsedInterfaces; + private Document doc; + private HashMap interfaceMap; + private HashMap constants; + + public XMLHookParser(HookFile hookFile) { + super(hookFile); + interfaceMap = new HashMap(); + constants = new HashMap(); + try { + DocumentBuilderFactory dbFactory = DocumentBuilderFactory + .newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + doc = dBuilder.parse(hookFile.getInputStream()); + doc.getDocumentElement().normalize(); + if (!doc.getDocumentElement().getNodeName().equals("injector")) { + throw new RuntimeException("Incorrect hook file."); + } + } catch (Throwable t) { + throw new RuntimeException("Unable to parse hooks " + t); + } + } + + @Override + public Interface[] getInterfaces() { + parsedInterfaces = true; + final NodeList interfaceRootList = doc + .getElementsByTagName("interfaces"); + switch (interfaceRootList.getLength()) { + case 0: + return null; + case 1: + break; + default: + throw new RuntimeException( + "Hook file may not contains multiple tags "); + } + final Node node = interfaceRootList.item(0); + if (node.getNodeType() != Node.ELEMENT_NODE) { + return null; + } + final Element interfaceRoot = (Element) node; + final NodeList interfaces = interfaceRoot.getElementsByTagName("add"); + if (interfaces.getLength() == 0) { + return null; + } + final ArrayList interfaceList = new ArrayList(); + for (int x = 0; x < interfaces.getLength(); x++) { + final Node n = interfaces.item(x); + if (n.getNodeType() != Node.ELEMENT_NODE) { + continue; + } + final Element addInterface = (Element) n; + final String className = getValue("classname", addInterface); + final String interfaceClass = getValue("interface", addInterface); + interfaceMap.put(interfaceClass, className); + final Interface inf = new Interface(className, interfaceClass); + interfaceList.add(inf); + } + return interfaceList.toArray(new Interface[interfaceList.size()]); + } + + @Override + public Super[] getSupers() { + final NodeList interfaceRootList = doc.getElementsByTagName("supers"); + switch (interfaceRootList.getLength()) { + case 0: + return null; + case 1: + break; + default: + throw new RuntimeException( + "Hook file may not contains multiple tags "); + } + final Node node = interfaceRootList.item(0); + if (node.getNodeType() != Node.ELEMENT_NODE) { + return null; + } + final Element superRoot = (Element) node; + final NodeList supers = superRoot.getElementsByTagName("add"); + if (supers.getLength() == 0) { + return null; + } + final ArrayList superList = new ArrayList(); + for (int x = 0; x < supers.getLength(); x++) { + final Node n = supers.item(x); + if (n.getNodeType() != Node.ELEMENT_NODE) { + continue; + } + final Element addSuper = (Element) n; + final String className = getValue("classname", addSuper); + final String superClass = getValue("super", addSuper); + final Super sup = new Super(className, superClass); + superList.add(sup); + } + return superList.toArray(new Super[superList.size()]); + } + + @Override + public Getter[] getGetters() { + final NodeList getterRootList = doc.getElementsByTagName("getters"); + switch (getterRootList.getLength()) { + case 0: + return null; + case 1: + break; + default: + throw new RuntimeException( + "Hook file may not contains multiple tags "); + } + final Node node = getterRootList.item(0); + if (node.getNodeType() != Node.ELEMENT_NODE) { + return null; + } + final Element getterRoot = (Element) node; + final NodeList getters = getterRoot.getElementsByTagName("add"); + if (getters.getLength() == 0) { + return null; + } + final ArrayList getterList = new ArrayList(); + for (int x = 0; x < getters.getLength(); x++) { + final Node n = getters.item(x); + if (n.getNodeType() != Node.ELEMENT_NODE) { + continue; + } + final Element addGetter = (Element) n; + if (isSet("classname", addGetter) && isSet("accessor", addGetter)) { + throw new RuntimeException( + "Can't set classname and accessor tag together."); + } + if (isSet("accessor", addGetter) && !parsedInterfaces) { + throw new RuntimeException( + "You'll need to parse interfaces first."); + } + final String className = isSet("classname", addGetter) ? getValue( + "classname", addGetter) : interfaceMap.get(getValue( + "accessor", addGetter)); + final String into = isSet("into", addGetter) ? getValue("into", + addGetter) : className; + final String fieldName = getValue("field", addGetter); + final String methodName = getValue("methodname", addGetter); + boolean staticMethod = isSet("methstatic", addGetter) ? (getValue( + "methstatic", addGetter).equals("true")) : false; + String returnDesc = isSet("desc", addGetter) ? getValue("desc", + addGetter) : null; + String array = ""; + if (returnDesc != null && returnDesc.contains("%s")) { + StringBuilder str = new StringBuilder(); + if (returnDesc.startsWith("[")) { + for (int i = 0; i < returnDesc.length(); i++) { + if (returnDesc.charAt(i) == '[') { + array += '['; + } + } + returnDesc = returnDesc.replaceAll("\\[", ""); + } + str.append(array) + .append('L') + .append(String.format(returnDesc, + AddInterfaceAdapter.getAccessorPackage())) + .append(";"); + returnDesc = str.toString(); + } + final Getter get = new Getter(into, className, fieldName, + methodName, returnDesc, staticMethod); + getterList.add(get); + } + return getterList.toArray(new Getter[getterList.size()]); + } + + @Override + public Setter[] getSetters() { + final NodeList setterRootList = doc.getElementsByTagName("setters"); + switch (setterRootList.getLength()) { + case 0: + return null; + case 1: + break; + default: + throw new RuntimeException( + "Hook file may not contains multiple tags "); + } + final Node node = setterRootList.item(0); + if (node.getNodeType() != Node.ELEMENT_NODE) { + return null; + } + final Element setterRoot = (Element) node; + final NodeList setters = setterRoot.getElementsByTagName("add"); + if (setters.getLength() == 0) { + return null; + } + final ArrayList setterList = new ArrayList(); + for (int x = 0; x < setters.getLength(); x++) { + final Node n = setters.item(x); + if (n.getNodeType() != Node.ELEMENT_NODE) { + continue; + } + final Element addSetter = (Element) n; + if (isSet("classname", addSetter) && isSet("accessor", addSetter)) { + throw new RuntimeException( + "Can't set classname and accessor tag together."); + } + if (isSet("accessor", addSetter) && !parsedInterfaces) { + throw new RuntimeException( + "You'll need to parse interfaces first."); + } + final String className = isSet("classname", addSetter) ? getValue( + "classname", addSetter) : interfaceMap.get(getValue( + "accessor", addSetter)); + final String into = isSet("into", addSetter) ? getValue("into", + addSetter) : className; + final String fieldName = getValue("field", addSetter); + final String methodName = getValue("methodname", addSetter); + boolean staticMethod = isSet("methstatic", addSetter) ? (getValue( + "methstatic", addSetter).equals("true")) : false; + String returnDesc = isSet("desc", addSetter) ? getValue("desc", + addSetter) : null; + String array = ""; + if (returnDesc != null && returnDesc.contains("%s")) { + StringBuilder str = new StringBuilder(); + if (returnDesc.startsWith("[")) { + for (int i = 0; i < returnDesc.length(); i++) { + if (returnDesc.charAt(i) == '[') { + array += '['; + } + } + returnDesc = returnDesc.replaceAll("\\[", ""); + } + str.append(array) + .append('L') + .append(String.format(returnDesc, + AddInterfaceAdapter.getAccessorPackage())) + .append(";"); + returnDesc = str.toString(); + } + final Setter get = new Setter(className, into, fieldName, + methodName, returnDesc, staticMethod); + setterList.add(get); + } + return setterList.toArray(new Setter[setterList.size()]); + } + + + private static String resolveDesc(String returnDesc) { + String array = ""; + if (returnDesc != null && returnDesc.contains("%s")) { + StringBuilder str = new StringBuilder(); + if (returnDesc.startsWith("[")) { + for (int i = 0; i < returnDesc.length(); i++) { + if (returnDesc.charAt(i) == '[') { + array += '['; + } + } + returnDesc = returnDesc.replaceAll("\\[", ""); + } + str.append(array) + .append('L') + .append(String.format(returnDesc, + AddInterfaceAdapter.getAccessorPackage())) + .append(";"); + returnDesc = str.toString(); + } + return returnDesc; + } + + private static final boolean isSet(String tag, Element element) { + return element.getElementsByTagName(tag).getLength() > 0; + } + + private static final String getValue(String tag, Element element) { + NodeList nodes = element.getElementsByTagName(tag).item(0) + .getChildNodes(); + Node node = (Node) nodes.item(0); + return node.getNodeValue(); + } + + @Override + public Invoker[] getInvokers() { + final NodeList invokerRootList = doc.getElementsByTagName("invokers"); + switch (invokerRootList.getLength()) { + case 0: + return null; + case 1: + break; + default: + throw new RuntimeException( + "Hook file may not contains multiple tags "); + } + final Node node = invokerRootList.item(0); + if (node.getNodeType() != Node.ELEMENT_NODE) { + return null; + } + final Element invokerRoot = (Element) node; + final NodeList invokers = invokerRoot.getElementsByTagName("add"); + if (invokers.getLength() == 0) { + return null; + } + final ArrayList invokerList = new ArrayList(); + for (int x = 0; x < invokers.getLength(); x++) { + final Node n = invokers.item(x); + if (n.getNodeType() != Node.ELEMENT_NODE) { + continue; + } + final Element addInvoker = (Element) n; + if (isSet("classname", addInvoker) && isSet("accessor", addInvoker)) { + throw new RuntimeException( + "Can't set classname and accessor tag together."); + } + if (isSet("accessor", addInvoker) && !parsedInterfaces) { + throw new RuntimeException( + "You'll need to parse interfaces first."); + } + final String className = isSet("classname", addInvoker) ? getValue( + "classname", addInvoker) : interfaceMap.get(getValue( + "accessor", addInvoker)); + final String into = isSet("into", addInvoker) ? getValue("into", + addInvoker) : className; + final String methodName = getValue("methodname", addInvoker); + final String invMethodName = getValue("invokemethod", addInvoker); + final String argsDesc = getValue("argsdesc", addInvoker); + String returnDesc = isSet("desc", addInvoker) ? resolveDesc(getValue( + "desc", addInvoker)) : null; + + final Invoker invoker = new Invoker(into, className, invMethodName, + argsDesc, returnDesc, methodName); + invokerList.add(invoker); + } + return invokerList.toArray(new Invoker[invokerList.size()]); + } + + @Override + public HashMap getConstants() { + if (!constants.isEmpty()) { + return constants; + } + final NodeList constantsRootList = doc + .getElementsByTagName("constants"); + switch (constantsRootList.getLength()) { + case 0: + return null; + case 1: + break; + default: + throw new RuntimeException( + "Hook file may not contains multiple tags "); + } + final Node node = constantsRootList.item(0); + if (node.getNodeType() != Node.ELEMENT_NODE) { + return null; + } + final Element constantRoot = (Element) node; + final NodeList constantsList = constantRoot.getElementsByTagName("add"); + if (constantsList.getLength() == 0) { + // return empty hashmap + return constants; + } + for (int x = 0; x < constantsList.getLength(); x++) { + final Node n = constantsList.item(x); + if (n.getNodeType() != Node.ELEMENT_NODE) { + continue; + } + final Element addConstant = (Element) n; + final String key = getValue("key", addConstant); + final String value = getValue("value", addConstant); + constants.put(key, value); + } + return constants; + } + + @Override + public Callback[] getCallbacks() { + final NodeList callbackRootList = doc.getElementsByTagName("callbacks"); + switch (callbackRootList.getLength()) { + case 0: + return null; + case 1: + break; + default: + throw new RuntimeException( + "Hook file may not contains multiple tags "); + } + final Node node = callbackRootList.item(0); + if (node.getNodeType() != Node.ELEMENT_NODE) { + return null; + } + final Element callbackRoot = (Element) node; + final NodeList callbacks = callbackRoot.getElementsByTagName("add"); + if (callbacks.getLength() == 0) { + return null; + } + final ArrayList callbackList = new ArrayList(); + for (int x = 0; x < callbacks.getLength(); x++) { + final Node n = callbacks.item(x); + if (n.getNodeType() != Node.ELEMENT_NODE) { + continue; + } + final Element addCallback = (Element) n; + if (isSet("classname", addCallback) + && isSet("accessor", addCallback)) { + throw new RuntimeException( + "Can't set classname and accessor tag together."); + } + if (isSet("accessor", addCallback) && !parsedInterfaces) { + throw new RuntimeException( + "You'll need to parse interfaces first."); + } + final String className = isSet("classname", addCallback) ? getValue( + "classname", addCallback) : interfaceMap.get(getValue( + "accessor", addCallback)); + + final String methodName = getValue("methodname", addCallback); + final String callClass = getValue("callclass", addCallback); + final String callMethod = getValue("callmethod", addCallback); + final String callDesc = getValue("calldesc", addCallback); + final String callArgs = getValue("callargs", addCallback); + final String desc = getValue("desc", addCallback); + + final Callback callback = new Callback(className, methodName, desc, + callClass, callMethod, callDesc, callArgs); + callbackList.add(callback); + } + return callbackList.toArray(new Callback[callbackList.size()]); + } + +} diff --git a/parabotv2/src/org/parabot/environment/servers/ServerProvider.java b/parabotv2/src/org/parabot/environment/servers/ServerProvider.java index 1419b02..a8c4173 100644 --- a/parabotv2/src/org/parabot/environment/servers/ServerProvider.java +++ b/parabotv2/src/org/parabot/environment/servers/ServerProvider.java @@ -2,6 +2,7 @@ package org.parabot.environment.servers; import org.objectweb.asm.Opcodes; import org.parabot.core.Context; +import org.parabot.core.asm.hooks.HookFile; import org.parabot.core.asm.interfaces.Injectable; import org.parabot.core.parsers.HookParser; import org.parabot.environment.input.Keyboard; @@ -25,12 +26,21 @@ public abstract class ServerProvider implements Opcodes { /** * Hooks to parse * + * @deprecated use getHookFile() now * @return URL to hooks file */ @Deprecated public URL getHooks() { return null; } + + /** + * Get hook file to parse + * @return hook file + */ + public HookFile getHookFile() { + return null; + } /** * Jar to parse @@ -46,11 +56,13 @@ public abstract class ServerProvider implements Opcodes { } public void injectHooks() { - URL hooksFile = getHooks(); - if (hooksFile == null) { + HookFile hookFile = fetchHookFile(); + + if(hookFile == null) { return; } - HookParser parser = new HookParser(hooksFile); + + HookParser parser = hookFile.getParser(); Injectable[] injectables = parser.getInjectables(); if (injectables == null) { return; @@ -60,6 +72,20 @@ public abstract class ServerProvider implements Opcodes { } Context.resolve().setHookParser(parser); } + + private HookFile fetchHookFile() { + HookFile hookFile = getHookFile(); + if(hookFile != null) { + return hookFile; + } + + URL hookLocation = getHooks(); + if(hookLocation == null) { + return null; + } + + return new HookFile(hookLocation, HookFile.TYPE_XML); + } /** * Add custom items to the bot menu bar