package org.zarroboogs.smartzpn.tunnel.pacscript; import org.mozilla.javascript.Context; import org.mozilla.javascript.Function; import org.mozilla.javascript.NativeJavaObject; import org.mozilla.javascript.NativeObject; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; /** * Created by wangdiyuan on 16-9-6. */ public class PacScriptParser { private String mScript; public PacScriptParser(String script){ mScript = shExpMatch + "\n" + isInNet + "\n" + script; } private static final String shExpMatch = "var shExpMatch = function (){\n" + " var _map = { '.': '\\\\.', '*': '.*?', '?': '.' };\n" + " var _rep = function (m){ return _map[m] };\n" + " return function (text, exp){\n" + " return new RegExp(exp.replace(/\\.|\\*|\\?/g, _rep)).test(text);\n" + " };\n" + "}();"; private static final String isInNet = "var isInNet = function (){\n" + " function convert_addr(ipchars) {\n" + " var bytes = ipchars.split('.');\n" + " return ((bytes[0] & 0xff) << 24) |\n" + " ((bytes[1] & 0xff) << 16) |\n" + " ((bytes[2] & 0xff) << 8) |\n" + " (bytes[3] & 0xff);\n" + " }\n" + " return function (ipaddr, pattern, maskstr) {\n" + " var match = /^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/.exec(ipaddr);\n" + " if (match[1] > 255 || match[2] > 255 ||\n" + " match[3] > 255 || match[4] > 255) {\n" + " return false; // not an IP address\n" + " }\n" + " var host = convert_addr(ipaddr);\n" + " var pat = convert_addr(pattern);\n" + " var mask = convert_addr(maskstr);\n" + " return ((host & mask) == (pat & mask));\n" + " };\n" + "}();"; private String runScript(String js, String functionName, Object[] functionParams) { Context rhino = Context.enter(); rhino.setOptimizationLevel(-1); try { Scriptable scope = rhino.initStandardObjects(); rhino.evaluateString(scope, js, "JavaScript", js.split("\n").length, null); Function function = (Function) scope.get(functionName, scope); Object result = function.call(rhino, scope, scope, functionParams); if (result instanceof String) { return (String) result; } else if (result instanceof NativeJavaObject) { return (String) ((NativeJavaObject) result).getDefaultValue(String.class); } else if (result instanceof NativeObject) { return (String) ((NativeObject) result).getDefaultValue(String.class); } return result.toString(); } finally { Context.exit(); } } public String findProxyForURL(String url, String host){ return runScript(mScript, "FindProxyForURL", new String[]{url, host}); } }