diff --git a/pom.xml b/pom.xml
index 992c7362..7512b837 100644
--- a/pom.xml
+++ b/pom.xml
@@ -61,6 +61,10 @@
org.javadelight
delight-nashorn-sandbox
+
+ org.javadelight
+ delight-rhino-sandbox
+
org.slf4j
slf4j-api
@@ -99,6 +103,13 @@
delight-nashorn-sandbox
0.1.14
+
+ org.javadelight
+ delight-rhino-sandbox
+ 0.0.9
+ compile
+ true
+
org.slf4j
slf4j-api
diff --git a/src/main/java/com/github/markusbernhardt/proxy/ProxySearch.java b/src/main/java/com/github/markusbernhardt/proxy/ProxySearch.java
index 610a473b..f48f7009 100644
--- a/src/main/java/com/github/markusbernhardt/proxy/ProxySearch.java
+++ b/src/main/java/com/github/markusbernhardt/proxy/ProxySearch.java
@@ -56,6 +56,7 @@ public class ProxySearch implements ProxySearchStrategy {
private int pacCacheSize;
private long pacCacheTTL;
private CacheScope pacCacheScope;
+ private ScriptingEngineType engineType = ScriptingEngineType.NASHORHN;
/*****************************************************************************
* Types of proxy detection supported by the builder.
@@ -83,6 +84,18 @@ public enum Strategy {
/// Use Java Networking system properties
JAVA
}
+
+ /*****************************************************************************
+ * Types of supported scripting engines.
+ ****************************************************************************/
+
+ public enum ScriptingEngineType {
+ // embedded in java
+ NASHORHN,
+
+ // Mozilla Rhino, open-source implementation of JavaScript written entirely in Java.
+ RHINO
+ }
/*************************************************************************
* Constructor
@@ -137,16 +150,16 @@ public void addStrategy(Strategy strategy) {
this.strategies.add(new DesktopProxySearchStrategy());
break;
case WPAD:
- this.strategies.add(new WpadProxySearchStrategy());
+ this.strategies.add(new WpadProxySearchStrategy(engineType));
break;
case BROWSER:
this.strategies.add(getDefaultBrowserStrategy());
break;
case FIREFOX:
- this.strategies.add(new FirefoxProxySearchStrategy());
+ this.strategies.add(new FirefoxProxySearchStrategy(engineType));
break;
case IE:
- this.strategies.add(new IEProxySearchStrategy());
+ this.strategies.add(new IEProxySearchStrategy(engineType));
break;
case ENV_VAR:
this.strategies.add(new EnvProxySearchStrategy());
@@ -155,11 +168,11 @@ public void addStrategy(Strategy strategy) {
this.strategies.add(new WinProxySearchStrategy());
break;
case KDE:
- this.strategies.add(new KdeProxySearchStrategy());
+ this.strategies.add(new KdeProxySearchStrategy(engineType));
break;
case GNOME:
- this.strategies.add(new GnomeDConfProxySearchStrategy());
- this.strategies.add(new GnomeProxySearchStrategy());
+ this.strategies.add(new GnomeDConfProxySearchStrategy(engineType));
+ this.strategies.add(new GnomeProxySearchStrategy(engineType));
break;
case JAVA:
this.strategies.add(new JavaProxySearchStrategy());
@@ -200,9 +213,9 @@ public void setPacCacheSettings(int size, long ttl, CacheScope cacheScope) {
private ProxySearchStrategy getDefaultBrowserStrategy() {
switch (PlatformUtil.getDefaultBrowser()) {
case IE:
- return new IEProxySearchStrategy();
+ return new IEProxySearchStrategy(engineType);
case FIREFOX:
- return new FirefoxProxySearchStrategy();
+ return new FirefoxProxySearchStrategy(engineType);
}
return null;
}
@@ -303,4 +316,23 @@ public void log(Class> clazz, LogLevel loglevel, String msg, Object... params)
ps.getProxySelector();
}
+ /*************************************************************************
+ *
+ * Returns scripting engine used to evaluate PAC scripts
+ *
+ ************************************************************************/
+ public ScriptingEngineType getScriptingEngine() {
+ return engineType;
+ }
+
+ /*************************************************************************
+ *
+ * Configures scripting engine used to evaluate PAC scripts
+ *
+ * @param scriptingEngine
+ ************************************************************************/
+ public void setScriptingEngine(ScriptingEngineType scriptingEngine) {
+ this.engineType = scriptingEngine;
+ }
+
}
diff --git a/src/main/java/com/github/markusbernhardt/proxy/search/browser/firefox/FirefoxProxySearchStrategy.java b/src/main/java/com/github/markusbernhardt/proxy/search/browser/firefox/FirefoxProxySearchStrategy.java
index ac79aff3..abfd033a 100644
--- a/src/main/java/com/github/markusbernhardt/proxy/search/browser/firefox/FirefoxProxySearchStrategy.java
+++ b/src/main/java/com/github/markusbernhardt/proxy/search/browser/firefox/FirefoxProxySearchStrategy.java
@@ -5,6 +5,7 @@
import java.util.Properties;
import com.github.markusbernhardt.proxy.ProxySearchStrategy;
+import com.github.markusbernhardt.proxy.ProxySearch.ScriptingEngineType;
import com.github.markusbernhardt.proxy.search.desktop.DesktopProxySearchStrategy;
import com.github.markusbernhardt.proxy.search.wpad.WpadProxySearchStrategy;
import com.github.markusbernhardt.proxy.selector.direct.NoProxySelector;
@@ -71,6 +72,7 @@ public class FirefoxProxySearchStrategy implements ProxySearchStrategy {
private FirefoxProfileSource profileScanner;
private FirefoxSettingParser settingsParser;
+ private ScriptingEngineType engineType = ScriptingEngineType.NASHORHN;
/*************************************************************************
* ProxySelector
@@ -89,6 +91,18 @@ public FirefoxProxySearchStrategy() {
}
this.settingsParser = new FirefoxSettingParser();
}
+
+ /*************************************************************************
+ * ProxySelector
+ *
+ * @see java.net.ProxySelector#ProxySelector()
+ ************************************************************************/
+
+ public FirefoxProxySearchStrategy(ScriptingEngineType engineType) {
+ this();
+ this.engineType = engineType;
+ }
+
/*************************************************************************
* Loads the proxy settings and initializes a proxy selector for the firefox
@@ -123,7 +137,7 @@ public ProxySelector getProxySelector() throws ProxyException {
case 2: // PAC Script
String pacScriptUrl = settings.getProperty("network.proxy.autoconfig_url", "");
Logger.log(getClass(), LogLevel.TRACE, "Firefox uses script (PAC) {0}", pacScriptUrl);
- result = ProxyUtil.buildPacSelectorForUrl(pacScriptUrl);
+ result = ProxyUtil.buildPacSelectorForUrl(engineType, pacScriptUrl);
break;
case 3: // Backward compatibility to netscape.
Logger.log(getClass(), LogLevel.TRACE, "Netscape compability mode -> uses no proxy");
diff --git a/src/main/java/com/github/markusbernhardt/proxy/search/browser/ie/IEProxySearchStrategy.java b/src/main/java/com/github/markusbernhardt/proxy/search/browser/ie/IEProxySearchStrategy.java
index 64fa07f1..7fca123f 100644
--- a/src/main/java/com/github/markusbernhardt/proxy/search/browser/ie/IEProxySearchStrategy.java
+++ b/src/main/java/com/github/markusbernhardt/proxy/search/browser/ie/IEProxySearchStrategy.java
@@ -3,6 +3,7 @@
import java.net.ProxySelector;
import java.util.Properties;
+import com.github.markusbernhardt.proxy.ProxySearch.ScriptingEngineType;
import com.github.markusbernhardt.proxy.jna.win.WinHttp;
import com.github.markusbernhardt.proxy.jna.win.WinHttpCurrentUserIEProxyConfig;
import com.github.markusbernhardt.proxy.jna.win.WinHttpHelpers;
@@ -24,6 +25,17 @@
public class IEProxySearchStrategy extends CommonWindowsSearchStrategy {
+ public IEProxySearchStrategy() {
+ }
+
+ public IEProxySearchStrategy(ScriptingEngineType engineType) {
+ this();
+ this.engineType = engineType;
+ }
+
+
+ private ScriptingEngineType engineType = ScriptingEngineType.NASHORHN;
+
/*************************************************************************
* getProxySelector
*
@@ -111,7 +123,7 @@ private PacProxySelector createPacSelector(IEProxyConfig ieProxyConfig) {
if (pacUrl.startsWith("file://") && !pacUrl.startsWith("file:///")) {
pacUrl = "file:///" + pacUrl.substring(7);
}
- return ProxyUtil.buildPacSelectorForUrl(pacUrl);
+ return ProxyUtil.buildPacSelectorForUrl(engineType, pacUrl);
}
return null;
diff --git a/src/main/java/com/github/markusbernhardt/proxy/search/desktop/gnome/GnomeDConfProxySearchStrategy.java b/src/main/java/com/github/markusbernhardt/proxy/search/desktop/gnome/GnomeDConfProxySearchStrategy.java
index 109f65fd..b598349a 100644
--- a/src/main/java/com/github/markusbernhardt/proxy/search/desktop/gnome/GnomeDConfProxySearchStrategy.java
+++ b/src/main/java/com/github/markusbernhardt/proxy/search/desktop/gnome/GnomeDConfProxySearchStrategy.java
@@ -5,6 +5,7 @@
import java.util.Properties;
import com.github.markusbernhardt.proxy.ProxySearchStrategy;
+import com.github.markusbernhardt.proxy.ProxySearch.ScriptingEngineType;
import com.github.markusbernhardt.proxy.selector.direct.NoProxySelector;
import com.github.markusbernhardt.proxy.selector.fixed.FixedProxySelector;
import com.github.markusbernhardt.proxy.selector.misc.ProtocolDispatchSelector;
@@ -67,6 +68,8 @@
public class GnomeDConfProxySearchStrategy implements ProxySearchStrategy {
+ private ScriptingEngineType engineType = ScriptingEngineType.NASHORHN;
+
/*************************************************************************
* ProxySelector
*
@@ -76,6 +79,11 @@ public class GnomeDConfProxySearchStrategy implements ProxySearchStrategy {
public GnomeDConfProxySearchStrategy() {
super();
}
+
+ public GnomeDConfProxySearchStrategy(ScriptingEngineType engineType) {
+ this();
+ this.engineType = engineType;
+ }
/*************************************************************************
* Loads the proxy settings and initializes a proxy selector for the Gnome
@@ -115,7 +123,7 @@ public ProxySelector getProxySelector() throws ProxyException {
if ("auto".equals(type)) {
String pacScriptUrl = settings.getProperty("org.gnome.system.proxy autoconfig-url", "");
Logger.log(getClass(), LogLevel.TRACE, "Gnome uses autodetect script {0}", pacScriptUrl);
- result = ProxyUtil.buildPacSelectorForUrl(pacScriptUrl);
+ result = ProxyUtil.buildPacSelectorForUrl(engineType, pacScriptUrl);
}
// Wrap into white-list filter?
diff --git a/src/main/java/com/github/markusbernhardt/proxy/search/desktop/gnome/GnomeProxySearchStrategy.java b/src/main/java/com/github/markusbernhardt/proxy/search/desktop/gnome/GnomeProxySearchStrategy.java
index e5d953b0..fa90fcb6 100644
--- a/src/main/java/com/github/markusbernhardt/proxy/search/desktop/gnome/GnomeProxySearchStrategy.java
+++ b/src/main/java/com/github/markusbernhardt/proxy/search/desktop/gnome/GnomeProxySearchStrategy.java
@@ -16,6 +16,7 @@
import org.xml.sax.SAXException;
import com.github.markusbernhardt.proxy.ProxySearchStrategy;
+import com.github.markusbernhardt.proxy.ProxySearch.ScriptingEngineType;
import com.github.markusbernhardt.proxy.selector.direct.NoProxySelector;
import com.github.markusbernhardt.proxy.selector.fixed.FixedProxySelector;
import com.github.markusbernhardt.proxy.selector.misc.ProtocolDispatchSelector;
@@ -73,6 +74,8 @@
public class GnomeProxySearchStrategy implements ProxySearchStrategy {
+ private ScriptingEngineType engineType = ScriptingEngineType.NASHORHN;
+
/*************************************************************************
* ProxySelector
*
@@ -82,7 +85,12 @@ public class GnomeProxySearchStrategy implements ProxySearchStrategy {
public GnomeProxySearchStrategy() {
super();
}
-
+
+ public GnomeProxySearchStrategy(ScriptingEngineType engineType) {
+ this();
+ this.engineType = engineType;
+ }
+
/*************************************************************************
* Loads the proxy settings and initializes a proxy selector for the Gnome
* proxy settings.
@@ -120,7 +128,7 @@ public ProxySelector getProxySelector() throws ProxyException {
if ("auto".equals(type)) {
String pacScriptUrl = settings.getProperty("/system/proxy/autoconfig_url", "");
Logger.log(getClass(), LogLevel.TRACE, "Gnome uses autodetect script {0}", pacScriptUrl);
- result = ProxyUtil.buildPacSelectorForUrl(pacScriptUrl);
+ result = ProxyUtil.buildPacSelectorForUrl(engineType, pacScriptUrl);
}
// Wrap into white-list filter?
diff --git a/src/main/java/com/github/markusbernhardt/proxy/search/desktop/kde/KdeProxySearchStrategy.java b/src/main/java/com/github/markusbernhardt/proxy/search/desktop/kde/KdeProxySearchStrategy.java
index 27fadefb..907b37e6 100644
--- a/src/main/java/com/github/markusbernhardt/proxy/search/desktop/kde/KdeProxySearchStrategy.java
+++ b/src/main/java/com/github/markusbernhardt/proxy/search/desktop/kde/KdeProxySearchStrategy.java
@@ -5,6 +5,7 @@
import java.util.Properties;
import com.github.markusbernhardt.proxy.ProxySearchStrategy;
+import com.github.markusbernhardt.proxy.ProxySearch.ScriptingEngineType;
import com.github.markusbernhardt.proxy.search.env.EnvProxySearchStrategy;
import com.github.markusbernhardt.proxy.search.wpad.WpadProxySearchStrategy;
import com.github.markusbernhardt.proxy.selector.direct.NoProxySelector;
@@ -49,6 +50,8 @@
public class KdeProxySearchStrategy implements ProxySearchStrategy {
+ private ScriptingEngineType engineType = ScriptingEngineType.NASHORHN;
+
private KdeSettingsParser settingsParser;
/*************************************************************************
@@ -60,6 +63,11 @@ public class KdeProxySearchStrategy implements ProxySearchStrategy {
public KdeProxySearchStrategy() {
this(new KdeSettingsParser());
}
+
+ public KdeProxySearchStrategy(ScriptingEngineType engineType) {
+ this();
+ this.engineType = engineType;
+ }
/*************************************************************************
* ProxySelector
@@ -107,7 +115,7 @@ public ProxySelector getProxySelector() throws ProxyException {
case 2: // PAC Script
String pacScriptUrl = settings.getProperty("Proxy Config Script", "");
Logger.log(getClass(), LogLevel.TRACE, "Kde uses autodetect script {0}", pacScriptUrl);
- result = ProxyUtil.buildPacSelectorForUrl(pacScriptUrl);
+ result = ProxyUtil.buildPacSelectorForUrl(engineType, pacScriptUrl);
break;
case 3: // WPAD
Logger.log(getClass(), LogLevel.TRACE, "Kde uses WPAD to detect the proxy");
diff --git a/src/main/java/com/github/markusbernhardt/proxy/search/desktop/osx/OsxProxySearchStrategy.java b/src/main/java/com/github/markusbernhardt/proxy/search/desktop/osx/OsxProxySearchStrategy.java
index aaf97c7d..5e2b95ab 100644
--- a/src/main/java/com/github/markusbernhardt/proxy/search/desktop/osx/OsxProxySearchStrategy.java
+++ b/src/main/java/com/github/markusbernhardt/proxy/search/desktop/osx/OsxProxySearchStrategy.java
@@ -11,6 +11,7 @@
import java.util.List;
import com.github.markusbernhardt.proxy.ProxySearchStrategy;
+import com.github.markusbernhardt.proxy.ProxySearch.ScriptingEngineType;
import com.github.markusbernhardt.proxy.search.browser.ie.IELocalByPassFilter;
import com.github.markusbernhardt.proxy.search.wpad.WpadProxySearchStrategy;
import com.github.markusbernhardt.proxy.selector.direct.NoProxySelector;
@@ -62,6 +63,8 @@ public class OsxProxySearchStrategy implements ProxySearchStrategy {
private static final String SETTINGS_FILE = "/Library/Preferences/SystemConfiguration/preferences.plist";
+ private ScriptingEngineType engineType = ScriptingEngineType.NASHORHN;
+
/*************************************************************************
* ProxySelector
*
@@ -71,6 +74,11 @@ public class OsxProxySearchStrategy implements ProxySearchStrategy {
public OsxProxySearchStrategy() {
super();
}
+
+ public OsxProxySearchStrategy(ScriptingEngineType engineType) {
+ this();
+ this.engineType = engineType;
+ }
/*************************************************************************
* Loads the proxy settings and initializes a proxy selector for the OSX
@@ -323,7 +331,7 @@ private ProxySelector autodetectProxyIfAvailable(Dict proxySettings, ProxySelect
private ProxySelector installPacProxyIfAvailable(Dict proxySettings, ProxySelector result) {
if (isActive(proxySettings.get("ProxyAutoConfigEnable"))) {
String url = (String) proxySettings.get("ProxyAutoConfigURLString");
- result = ProxyUtil.buildPacSelectorForUrl(url);
+ result = ProxyUtil.buildPacSelectorForUrl(engineType, url);
}
return result;
}
diff --git a/src/main/java/com/github/markusbernhardt/proxy/search/wpad/WpadProxySearchStrategy.java b/src/main/java/com/github/markusbernhardt/proxy/search/wpad/WpadProxySearchStrategy.java
index 964eff2e..13ac4bce 100644
--- a/src/main/java/com/github/markusbernhardt/proxy/search/wpad/WpadProxySearchStrategy.java
+++ b/src/main/java/com/github/markusbernhardt/proxy/search/wpad/WpadProxySearchStrategy.java
@@ -14,6 +14,7 @@
import java.util.Random;
import com.github.markusbernhardt.proxy.ProxySearchStrategy;
+import com.github.markusbernhardt.proxy.ProxySearch.ScriptingEngineType;
import com.github.markusbernhardt.proxy.search.wpad.dhcp.DHCPMessage;
import com.github.markusbernhardt.proxy.search.wpad.dhcp.DHCPOptions;
import com.github.markusbernhardt.proxy.search.wpad.dhcp.DHCPSocket;
@@ -45,6 +46,8 @@
public class WpadProxySearchStrategy implements ProxySearchStrategy {
+ private ScriptingEngineType engineType = ScriptingEngineType.NASHORHN;
+
/*************************************************************************
* Constructor
************************************************************************/
@@ -52,6 +55,11 @@ public class WpadProxySearchStrategy implements ProxySearchStrategy {
public WpadProxySearchStrategy() {
super();
}
+
+ public WpadProxySearchStrategy(ScriptingEngineType engineType) {
+ this();
+ this.engineType = engineType;
+ }
/*************************************************************************
* Loads the proxy settings from a PAC file. The location of the PAC file is
@@ -75,7 +83,7 @@ public ProxySelector getProxySelector() throws ProxyException {
return null;
}
Logger.log(getClass(), LogLevel.TRACE, "PAC script url found: {0}", pacScriptUrl);
- return ProxyUtil.buildPacSelectorForUrl(pacScriptUrl);
+ return ProxyUtil.buildPacSelectorForUrl(engineType, pacScriptUrl);
} catch (IOException e) {
Logger.log(getClass(), LogLevel.ERROR, "Error during WPAD search.", e);
throw new ProxyException(e);
diff --git a/src/main/java/com/github/markusbernhardt/proxy/search/wpad/WpadProxySearchStrategyWithDHPC.java b/src/main/java/com/github/markusbernhardt/proxy/search/wpad/WpadProxySearchStrategyWithDHPC.java
index 04fbd30c..4afdf6b9 100644
--- a/src/main/java/com/github/markusbernhardt/proxy/search/wpad/WpadProxySearchStrategyWithDHPC.java
+++ b/src/main/java/com/github/markusbernhardt/proxy/search/wpad/WpadProxySearchStrategyWithDHPC.java
@@ -10,6 +10,7 @@
import java.util.Properties;
import com.github.markusbernhardt.proxy.ProxySearchStrategy;
+import com.github.markusbernhardt.proxy.ProxySearch.ScriptingEngineType;
import com.github.markusbernhardt.proxy.search.wpad.dhcp.DHCPMessage;
import com.github.markusbernhardt.proxy.util.Logger;
import com.github.markusbernhardt.proxy.util.ProxyException;
@@ -39,6 +40,8 @@
public class WpadProxySearchStrategyWithDHPC implements ProxySearchStrategy {
+ private ScriptingEngineType engineType = ScriptingEngineType.NASHORHN;
+
/*************************************************************************
* Constructor
************************************************************************/
@@ -46,6 +49,11 @@ public class WpadProxySearchStrategyWithDHPC implements ProxySearchStrategy {
public WpadProxySearchStrategyWithDHPC() {
super();
}
+
+ public WpadProxySearchStrategyWithDHPC(ScriptingEngineType engineType) {
+ this();
+ this.engineType = engineType;
+ }
/*************************************************************************
* Loads the proxy settings from a PAC file. The location of the PAC file is
@@ -69,7 +77,7 @@ public ProxySelector getProxySelector() throws ProxyException {
return null;
}
Logger.log(getClass(), LogLevel.TRACE, "PAC script url found: {0}", pacScriptUrl);
- return ProxyUtil.buildPacSelectorForUrl(pacScriptUrl);
+ return ProxyUtil.buildPacSelectorForUrl(engineType, pacScriptUrl);
} catch (IOException e) {
Logger.log(getClass(), LogLevel.ERROR, "Error during WPAD search.", e);
throw new ProxyException(e);
diff --git a/src/main/java/com/github/markusbernhardt/proxy/selector/pac/PacProxySelector.java b/src/main/java/com/github/markusbernhardt/proxy/selector/pac/PacProxySelector.java
index 2ba3d657..0bc1049b 100644
--- a/src/main/java/com/github/markusbernhardt/proxy/selector/pac/PacProxySelector.java
+++ b/src/main/java/com/github/markusbernhardt/proxy/selector/pac/PacProxySelector.java
@@ -9,6 +9,7 @@
import java.util.ArrayList;
import java.util.List;
+import com.github.markusbernhardt.proxy.ProxySearch.ScriptingEngineType;
import com.github.markusbernhardt.proxy.util.Logger;
import com.github.markusbernhardt.proxy.util.Logger.LogLevel;
import com.github.markusbernhardt.proxy.util.ProxyUtil;
@@ -36,9 +37,9 @@ public class PacProxySelector extends ProxySelector {
* the source for the PAC file.
************************************************************************/
- public PacProxySelector(PacScriptSource pacSource) {
+ public PacProxySelector(ScriptingEngineType engineType, PacScriptSource pacSource) {
super();
- selectEngine(pacSource);
+ selectEngine(engineType, pacSource);
}
/*************************************************************************
@@ -70,14 +71,26 @@ public static boolean isEnabled() {
* to use as input.
************************************************************************/
- private void selectEngine(PacScriptSource pacSource) {
+ private void selectEngine(ScriptingEngineType engineType, PacScriptSource pacSource) {
try {
Logger.log(getClass(), LogLevel.INFO, "Using javax.script JavaScript engine.");
- pacScriptParser = new JavaxPacScriptParser(pacSource);
+ if (ScriptingEngineType.RHINO.equals(engineType)) {
+ pacScriptParser = createRhinoPacScriptParser(pacSource);
+ } else {
+ pacScriptParser = createJavaxPacScriptParser(pacSource);
+ }
} catch (Exception e) {
Logger.log(getClass(), LogLevel.ERROR, "PAC parser error.", e);
}
}
+
+ private PacScriptParser createJavaxPacScriptParser(PacScriptSource pacSource) throws ProxyEvaluationException {
+ return new JavaxPacScriptParser(pacSource);
+ }
+
+ private PacScriptParser createRhinoPacScriptParser(PacScriptSource pacSource) throws ProxyEvaluationException {
+ return new RhinoPacScriptParser(pacSource);
+ }
/*************************************************************************
* connectFailed
diff --git a/src/main/java/com/github/markusbernhardt/proxy/selector/pac/RhinoPacScriptParser.java b/src/main/java/com/github/markusbernhardt/proxy/selector/pac/RhinoPacScriptParser.java
new file mode 100644
index 00000000..95234333
--- /dev/null
+++ b/src/main/java/com/github/markusbernhardt/proxy/selector/pac/RhinoPacScriptParser.java
@@ -0,0 +1,146 @@
+package com.github.markusbernhardt.proxy.selector.pac;
+
+import com.github.markusbernhardt.proxy.util.Logger;
+import com.github.markusbernhardt.proxy.util.Logger.LogLevel;
+import delight.rhinosandox.RhinoSandbox;
+import delight.rhinosandox.RhinoSandboxes;
+
+import java.lang.reflect.Method;
+
+/*****************************************************************************
+ * PAC parser using the Rhino JavaScript engine bundled with Java 1.6
+ *
+ * More information about PAC can be found there:
+ * Proxy_auto-config
+ *
+ *
+ * web-browser-auto-proxy-configuration
+ *
+ * @author Markus Bernhardt, Copyright 2016
+ * @author Bernd Rosstauscher, Copyright 2009
+ ****************************************************************************/
+public class RhinoPacScriptParser implements PacScriptParser {
+ static final String SCRIPT_METHODS_OBJECT = "__pacutil";
+ static final String SOURCE_NAME = RhinoPacScriptParser.class.getName();
+
+ private final PacScriptSource source;
+ private final RhinoSandbox engine;
+
+ /*************************************************************************
+ * Constructor
+ *
+ * @param source
+ * the source for the PAC script.
+ * @throws ProxyEvaluationException
+ * on error.
+ ************************************************************************/
+ public RhinoPacScriptParser(PacScriptSource source) throws ProxyEvaluationException {
+ this.source = source;
+ this.engine = setupEngine();
+ }
+
+ /*************************************************************************
+ * Initializes the JavaScript engine and adds aliases for the functions
+ * defined in ScriptMethods.
+ *
+ * @throws ProxyEvaluationException
+ * on error.
+ ************************************************************************/
+ private RhinoSandbox setupEngine() throws ProxyEvaluationException {
+ RhinoSandbox engine = RhinoSandboxes.create();
+ engine.inject(SCRIPT_METHODS_OBJECT, new PacScriptMethods());
+ // allow String
+ engine.allow(String.class);
+
+ Class> scriptMethodsClazz = ScriptMethods.class;
+ Method[] scriptMethods = scriptMethodsClazz.getMethods();
+
+ for (Method method : scriptMethods) {
+ String name = method.getName();
+ int args = method.getParameterTypes().length;
+ StringBuilder toEval = new StringBuilder(name).append(" = function(");
+ for (int i = 0; i < args; i++) {
+ if (i > 0) {
+ toEval.append(",");
+ }
+ toEval.append("arg").append(i);
+ }
+ toEval.append(") {return ");
+
+ String functionCall = buildFunctionCallCode(name, args);
+
+ // If return type is java.lang.String convert it to a JS string
+ if (String.class.isAssignableFrom(method.getReturnType())) {
+ functionCall = "String(" + functionCall + ")";
+ }
+ toEval.append(functionCall).append("; }");
+ try {
+ // Add functions with calls to Java object to global scope
+ engine.evalWithGlobalScope(SOURCE_NAME, toEval.toString());
+ } catch (Exception e) {
+ Logger.log(getClass(), LogLevel.ERROR, "JS evaluation error when creating alias for " + name + ".", e);
+ throw new ProxyEvaluationException("Error setting up script engine", e);
+ }
+ }
+
+ return engine;
+ }
+
+ /*************************************************************************
+ * Builds a JavaScript code snippet to call a function that we bind.
+ *
+ * @param functionName
+ * of the bound function
+ * @param args
+ * of the bound function
+ * @return the JS code to invoke the method.
+ ************************************************************************/
+
+ private String buildFunctionCallCode(String functionName, int args) {
+ StringBuilder functionCall = new StringBuilder();
+ functionCall.append(SCRIPT_METHODS_OBJECT).append(".").append(functionName).append("(");
+ for (int i = 0; i < args; i++) {
+ if (i > 0) {
+ functionCall.append(",");
+ }
+ functionCall.append("arg").append(i);
+ }
+ functionCall.append(")");
+ return functionCall.toString();
+ }
+
+ /***************************************************************************
+ * Gets the source of the PAC script used by this parser.
+ *
+ * @return a PacScriptSource.
+ **************************************************************************/
+ public PacScriptSource getScriptSource() {
+ return this.source;
+ }
+
+ /*************************************************************************
+ * Evaluates the given URL and host against the PAC script.
+ *
+ * @param url
+ * the URL to evaluate.
+ * @param host
+ * the host name part of the URL.
+ * @return the script result.
+ * @throws ProxyEvaluationException
+ * on execution error.
+ ************************************************************************/
+ public String evaluate(String url, String host) throws ProxyEvaluationException {
+ try {
+ StringBuilder script = new StringBuilder(this.source.getScriptContent());
+ String evalMethod = " ;FindProxyForURL (\"" + url + "\",\"" + host + "\")";
+ script.append(evalMethod);
+ Object result = this.engine.eval(SOURCE_NAME, script.toString());
+ return (String) result;
+ } catch (Exception e) {
+ Logger.log(getClass(), LogLevel.ERROR, "JS evaluation error.", e);
+ throw new ProxyEvaluationException("Error while executing PAC script: " + e.getMessage(), e);
+ }
+
+ }
+}
diff --git a/src/main/java/com/github/markusbernhardt/proxy/ui/ProxyTester.java b/src/main/java/com/github/markusbernhardt/proxy/ui/ProxyTester.java
index 46fadfba..18175f6a 100644
--- a/src/main/java/com/github/markusbernhardt/proxy/ui/ProxyTester.java
+++ b/src/main/java/com/github/markusbernhardt/proxy/ui/ProxyTester.java
@@ -22,6 +22,7 @@
import javax.swing.UIManager;
import com.github.markusbernhardt.proxy.ProxySearch;
+import com.github.markusbernhardt.proxy.ProxySearch.ScriptingEngineType;
import com.github.markusbernhardt.proxy.ProxySearch.Strategy;
import com.github.markusbernhardt.proxy.util.Logger;
import com.github.markusbernhardt.proxy.util.Logger.LogLevel;
@@ -38,7 +39,8 @@ public class ProxyTester extends JFrame {
private static final long serialVersionUID = 1L;
- private JComboBox modes;
+ private JComboBox modes;
+ private JComboBox engines;
private JButton testButton;
private JTextField urlField;
@@ -64,9 +66,11 @@ private void init() {
JPanel p = new JPanel();
p.add(new JLabel("Mode:"));
-
- this.modes = new JComboBox(ProxySearch.Strategy.values());
- p.add(this.modes);
+ this.modes = new JComboBox(ProxySearch.Strategy.values());
+ p.add(this.modes);
+ p.add(new JLabel("ScriptingEngine:"));
+ this.engines = new JComboBox(ProxySearch.ScriptingEngineType.values());
+ p.add(this.engines);
p.add(new JLabel("URL:"));
this.urlField = new JTextField(30);
@@ -118,7 +122,9 @@ protected void testUrl() {
this.logArea.setText("");
Strategy pss = (Strategy) this.modes.getSelectedItem();
+ ScriptingEngineType engineType = (ScriptingEngineType) this.engines.getSelectedItem();
ProxySearch ps = new ProxySearch();
+ ps.setScriptingEngine(engineType);
ps.addStrategy(pss);
ProxySelector psel = ps.getProxySelector();
if (psel == null) {
diff --git a/src/main/java/com/github/markusbernhardt/proxy/util/ProxyUtil.java b/src/main/java/com/github/markusbernhardt/proxy/util/ProxyUtil.java
index 9fe88ee5..b2d18c8f 100644
--- a/src/main/java/com/github/markusbernhardt/proxy/util/ProxyUtil.java
+++ b/src/main/java/com/github/markusbernhardt/proxy/util/ProxyUtil.java
@@ -7,6 +7,7 @@
import java.util.Collections;
import java.util.List;
+import com.github.markusbernhardt.proxy.ProxySearch.ScriptingEngineType;
import com.github.markusbernhardt.proxy.selector.fixed.FixedProxySelector;
import com.github.markusbernhardt.proxy.selector.pac.PacProxySelector;
import com.github.markusbernhardt.proxy.selector.pac.PacScriptSource;
@@ -83,11 +84,11 @@ public static synchronized List noProxyList() {
* working selector.
************************************************************************/
- public static PacProxySelector buildPacSelectorForUrl(String url) {
+ public static PacProxySelector buildPacSelectorForUrl(ScriptingEngineType engineType, String url) {
PacProxySelector result = null;
PacScriptSource pacSource = new UrlPacScriptSource(url);
if (pacSource.isScriptValid()) {
- result = new PacProxySelector(pacSource);
+ result = new PacProxySelector(engineType, pacSource);
}
return result;
}
diff --git a/src/test/java/com/github/markusbernhardt/proxy/selector/pac/JavaxPacScriptParserTest.java b/src/test/java/com/github/markusbernhardt/proxy/selector/pac/JavaxPacScriptParserTest.java
index 38823655..49d7c1b4 100644
--- a/src/test/java/com/github/markusbernhardt/proxy/selector/pac/JavaxPacScriptParserTest.java
+++ b/src/test/java/com/github/markusbernhardt/proxy/selector/pac/JavaxPacScriptParserTest.java
@@ -61,7 +61,18 @@ public void testScriptExecution() throws ProxyException, MalformedURLException {
PacScriptParser p = new JavaxPacScriptParser(new UrlPacScriptSource(toUrl("test1.pac")));
p.evaluate(TestUtil.HTTP_TEST_URI.toString(), "host1.unit-test.invalid");
}
-
+
+ /*************************************************************************
+ * Test method
+ * @throws Exception
+ ************************************************************************/
+ @Test(expected = Exception.class)
+ public void testSemicolonBeforeElse() throws Exception {
+ PacScriptParser p = new JavaxPacScriptParser(new UrlPacScriptSource(toUrl("testSemicolonBeforeElse.pac")));
+ String evaluate = p.evaluate(TestUtil.HTTP_TEST_URI.toString(), "host1.unit-test.invalid");
+ Assert.assertEquals("PROXY proxy:3128", evaluate);
+ }
+
/*************************************************************************
* Test method
*
diff --git a/src/test/java/com/github/markusbernhardt/proxy/selector/pac/PacPerProtocolTest.java b/src/test/java/com/github/markusbernhardt/proxy/selector/pac/PacPerProtocolTest.java
index 44d08e86..0bcecf05 100644
--- a/src/test/java/com/github/markusbernhardt/proxy/selector/pac/PacPerProtocolTest.java
+++ b/src/test/java/com/github/markusbernhardt/proxy/selector/pac/PacPerProtocolTest.java
@@ -13,6 +13,7 @@
import org.junit.Test;
import com.github.markusbernhardt.proxy.TestUtil;
+import com.github.markusbernhardt.proxy.ProxySearch.ScriptingEngineType;
import com.github.markusbernhardt.proxy.selector.pac.PacProxySelector;
import com.github.markusbernhardt.proxy.selector.pac.UrlPacScriptSource;
@@ -35,7 +36,7 @@ public void testPacForSocket() throws IOException, URISyntaxException {
new URI("socket://host1.unit-test.invalid/");
- List result = new PacProxySelector(new UrlPacScriptSource(toUrl("test1.pac")))
+ List result = new PacProxySelector(ScriptingEngineType.NASHORHN, new UrlPacScriptSource(toUrl("test1.pac")))
.select(TestUtil.SOCKET_TEST_URI);
assertEquals(TestUtil.HTTP_TEST_PROXY, result.get(0));
diff --git a/src/test/java/com/github/markusbernhardt/proxy/selector/pac/PacProxySelectorTest.java b/src/test/java/com/github/markusbernhardt/proxy/selector/pac/PacProxySelectorTest.java
index 3e4e2d0b..79eb0a18 100644
--- a/src/test/java/com/github/markusbernhardt/proxy/selector/pac/PacProxySelectorTest.java
+++ b/src/test/java/com/github/markusbernhardt/proxy/selector/pac/PacProxySelectorTest.java
@@ -16,6 +16,7 @@
import org.junit.Test;
import com.github.markusbernhardt.proxy.TestUtil;
+import com.github.markusbernhardt.proxy.ProxySearch.ScriptingEngineType;
import com.github.markusbernhardt.proxy.selector.pac.PacProxySelector;
import com.github.markusbernhardt.proxy.selector.pac.PacScriptMethods;
import com.github.markusbernhardt.proxy.selector.pac.UrlPacScriptSource;
@@ -40,7 +41,7 @@ public class PacProxySelectorTest {
************************************************************************/
@Test
public void testScriptExecution() throws ProxyException, MalformedURLException {
- List result = new PacProxySelector(new UrlPacScriptSource(toUrl("test1.pac")))
+ List result = new PacProxySelector(ScriptingEngineType.NASHORHN, new UrlPacScriptSource(toUrl("test1.pac")))
.select(TestUtil.HTTP_TEST_URI);
assertEquals(TestUtil.HTTP_TEST_PROXY, result.get(0));
@@ -56,7 +57,7 @@ public void testScriptExecution() throws ProxyException, MalformedURLException {
************************************************************************/
@Test
public void testScriptExecution2() throws ProxyException, MalformedURLException {
- PacProxySelector pacProxySelector = new PacProxySelector(new UrlPacScriptSource(toUrl("test2.pac")));
+ PacProxySelector pacProxySelector = new PacProxySelector(ScriptingEngineType.NASHORHN, new UrlPacScriptSource(toUrl("test2.pac")));
List result = pacProxySelector.select(TestUtil.HTTP_TEST_URI);
assertEquals(Proxy.NO_PROXY, result.get(0));
@@ -89,7 +90,7 @@ public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
});
PacProxySelector pacProxySelector = new PacProxySelector(
- new UrlPacScriptSource("http://www.test.invalid/wpad.pac"));
+ ScriptingEngineType.NASHORHN, new UrlPacScriptSource("http://www.test.invalid/wpad.pac"));
pacProxySelector.select(TestUtil.HTTPS_TEST_URI);
} finally {
ProxySelector.setDefault(oldOne);
@@ -106,7 +107,8 @@ public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
************************************************************************/
@Test
public void testScriptMuliProxy() throws ProxyException, MalformedURLException {
- PacProxySelector pacProxySelector = new PacProxySelector(new UrlPacScriptSource(toUrl("testMultiProxy.pac")));
+ PacProxySelector pacProxySelector = new PacProxySelector(ScriptingEngineType.NASHORHN,
+ new UrlPacScriptSource(toUrl("testMultiProxy.pac")));
List result = pacProxySelector.select(TestUtil.HTTP_TEST_URI);
assertEquals(4, result.size());
assertEquals(new Proxy(Type.HTTP, InetSocketAddress.createUnresolved("my-proxy.com", 80)), result.get(0));
@@ -127,7 +129,8 @@ public void testScriptMuliProxy() throws ProxyException, MalformedURLException {
public void testLocalIPOverride() throws ProxyException, MalformedURLException {
System.setProperty(PacScriptMethods.OVERRIDE_LOCAL_IP, "123.123.123.123");
try {
- PacProxySelector pacProxySelector = new PacProxySelector(new UrlPacScriptSource(toUrl("testLocalIP.pac")));
+ PacProxySelector pacProxySelector = new PacProxySelector(ScriptingEngineType.NASHORHN,
+ new UrlPacScriptSource(toUrl("testLocalIP.pac")));
List result = pacProxySelector.select(TestUtil.HTTP_TEST_URI);
assertEquals(result.get(0),
new Proxy(Type.HTTP, InetSocketAddress.createUnresolved("123.123.123.123", 8080)));
diff --git a/src/test/java/com/github/markusbernhardt/proxy/selector/pac/RhinoPacScriptParserTest.java b/src/test/java/com/github/markusbernhardt/proxy/selector/pac/RhinoPacScriptParserTest.java
new file mode 100644
index 00000000..5da79f99
--- /dev/null
+++ b/src/test/java/com/github/markusbernhardt/proxy/selector/pac/RhinoPacScriptParserTest.java
@@ -0,0 +1,178 @@
+package com.github.markusbernhardt.proxy.selector.pac;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.util.Calendar;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.github.markusbernhardt.proxy.TestUtil;
+import com.github.markusbernhardt.proxy.util.ProxyException;
+
+/*****************************************************************************
+ * Tests for the javax.script PAC script parser.
+ *
+ * @author Markus Bernhardt, Copyright 2016
+ * @author Bernd Rosstauscher, Copyright 2009
+ ****************************************************************************/
+
+public class RhinoPacScriptParserTest {
+
+ /*************************************************************************
+ * Set calendar for date and time base tests. Current date for all tests is: 15.
+ * December 1994 12:00.00 its a Thursday
+ ************************************************************************/
+ @BeforeClass
+ public static void setup() {
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.YEAR, 1994);
+ cal.set(Calendar.MONTH, Calendar.DECEMBER);
+ cal.set(Calendar.DAY_OF_MONTH, 15);
+ cal.set(Calendar.HOUR_OF_DAY, 12);
+ cal.set(Calendar.MINUTE, 00);
+ cal.set(Calendar.SECOND, 00);
+ cal.set(Calendar.MILLISECOND, 00);
+
+ // TODO Rossi 26.08.2010 need to fake time
+ // RhinoPacScriptParser.setCurrentTime(cal);
+ }
+
+ /*************************************************************************
+ * Cleanup after the tests.
+ ************************************************************************/
+ @AfterClass
+ public static void teadDown() {
+ // RhinoPacScriptParser.setCurrentTime(null);
+ }
+
+ /*************************************************************************
+ * Test method
+ *
+ * @throws ProxyException
+ * on proxy detection error.
+ * @throws MalformedURLException
+ * on URL erros
+ ************************************************************************/
+ @Test
+ public void testScriptExecution() throws ProxyException, MalformedURLException {
+ PacScriptParser p = new RhinoPacScriptParser(new UrlPacScriptSource(toUrl("test1.pac")));
+ p.evaluate(TestUtil.HTTP_TEST_URI.toString(), "host1.unit-test.invalid");
+ }
+
+ /*************************************************************************
+ * Test method
+ *
+ * @throws ProxyException
+ * on proxy detection error.
+ * @throws MalformedURLException
+ * on URL erros
+ ************************************************************************/
+ @Test
+ public void testSemicolonBeforeElse() throws ProxyException, MalformedURLException {
+ PacScriptParser p = new RhinoPacScriptParser(new UrlPacScriptSource(toUrl("testSemicolonBeforeElse.pac")));
+ String evaluate = p.evaluate(TestUtil.HTTP_TEST_URI.toString(), "host1.unit-test.invalid");
+ Assert.assertEquals("PROXY proxy.:3128; PROXY dmzproxy:3128", evaluate);
+ }
+
+ /*************************************************************************
+ * Test method
+ *
+ * @throws ProxyException
+ * on proxy detection error.
+ * @throws MalformedURLException
+ * on URL erros
+ ************************************************************************/
+ @Test
+ public void testCommentsInScript() throws ProxyException, MalformedURLException {
+ PacScriptParser p = new RhinoPacScriptParser(new UrlPacScriptSource(toUrl("test2.pac")));
+ p.evaluate(TestUtil.HTTP_TEST_URI.toString(), "host1.unit-test.invalid");
+ }
+
+ /*************************************************************************
+ * Test method
+ *
+ * @throws ProxyException
+ * on proxy detection error.
+ * @throws MalformedURLException
+ * on URL erros
+ ************************************************************************/
+ @Test
+ public void testScriptWeekDayScript() throws ProxyException, MalformedURLException {
+ PacScriptParser p = new RhinoPacScriptParser(new UrlPacScriptSource(toUrl("testWeekDay.pac")));
+ p.evaluate(TestUtil.HTTP_TEST_URI.toString(), "host1.unit-test.invalid");
+ }
+
+ /*************************************************************************
+ * Test method
+ *
+ * @throws ProxyException
+ * on proxy detection error.
+ * @throws MalformedURLException
+ * on URL erros
+ ************************************************************************/
+ @Test
+ public void testDateRangeScript() throws ProxyException, MalformedURLException {
+ PacScriptParser p = new RhinoPacScriptParser(new UrlPacScriptSource(toUrl("testDateRange.pac")));
+ p.evaluate(TestUtil.HTTP_TEST_URI.toString(), "host1.unit-test.invalid");
+ }
+
+ /*************************************************************************
+ * Test method
+ *
+ * @throws ProxyException
+ * on proxy detection error.
+ * @throws MalformedURLException
+ * on URL erros
+ ************************************************************************/
+ @Test
+ public void testTimeRangeScript() throws ProxyException, MalformedURLException {
+ PacScriptParser p = new RhinoPacScriptParser(new UrlPacScriptSource(toUrl("testTimeRange.pac")));
+ p.evaluate(TestUtil.HTTP_TEST_URI.toString(), "host1.unit-test.invalid");
+ }
+
+ /*************************************************************************
+ * Test method
+ *
+ * @throws ProxyException
+ * on proxy detection error.
+ * @throws MalformedURLException
+ * on URL erros
+ ************************************************************************/
+ @Test
+ public void methodsShouldReturnJsStrings() throws ProxyException, MalformedURLException {
+ PacScriptParser p = new RhinoPacScriptParser(new UrlPacScriptSource(toUrl("testReturnTypes.pac")));
+ String actual = p.evaluate(TestUtil.HTTP_TEST_URI.toString(), "host1.unit-test.invalid");
+ Assert.assertEquals("number boolean string", actual);
+ }
+
+ /*************************************************************************
+ * Test method
+ *
+ * @throws ProxyException
+ * on proxy detection error.
+ * @throws MalformedURLException
+ * on URL erros
+ ************************************************************************/
+ @Test(expected = Exception.class)
+ public void shouldNotExecuteCodeInPac() throws ProxyException, MalformedURLException {
+ PacScriptParser p = new RhinoPacScriptParser(new UrlPacScriptSource(toUrl("testRemoteCodeExecution.pac")));
+ p.evaluate(TestUtil.HTTP_TEST_URI.toString(), "host.does.not.matter");
+ }
+
+ /*************************************************************************
+ * Helper method to build the url to the given test file
+ *
+ * @param testFile
+ * the name of the test file.
+ * @return the URL.
+ * @throws MalformedURLException
+ ************************************************************************/
+
+ private String toUrl(String testFile) throws MalformedURLException {
+ return new File(TestUtil.TEST_DATA_FOLDER + "pac", testFile).toURI().toURL().toString();
+ }
+
+}
diff --git a/src/test/resources/pac/testSemicolonBeforeElse.pac b/src/test/resources/pac/testSemicolonBeforeElse.pac
new file mode 100644
index 00000000..d03bfb56
--- /dev/null
+++ b/src/test/resources/pac/testSemicolonBeforeElse.pac
@@ -0,0 +1,26 @@
+// Nashorn scripting engine fails to parse this script with
+// jdk.nashorn.internal.runtime.ParserException: :8:2 Expected an operand but found else
+// else return "PROXY proxy:3128";
+function FindProxyForURL(url, host)
+ {
+ if (shExpMatch(host, "deploy.abc.eu"))
+
+ return "PROXY proxy:3128";
+
+ else if (isInNet(myIpAddress(), "10.25.48.0", "255.255.240.0"))
+
+ return "PROXY dmzproxy:3128; PROXY proxy:3128; DIRECT";
+
+ else if (isInNet(myIpAddress(), "10.26.128.0", "255.255.248.0"))
+
+ return "PROXY proxy:3128; DIRECT";
+
+ else if (isInNet(myIpAddress(), "10.25.0.0", "255.255.0.0")
+ )
+
+ return "PROXY dmzproxy:3128; PROXY proxy:3128; DIRECT";
+
+ else
+
+ return "PROXY proxy.:3128; PROXY dmzproxy:3128";
+ }
\ No newline at end of file