summaryrefslogtreecommitdiffstats
path: root/src/main/java/com/btr/proxy/search/desktop
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/btr/proxy/search/desktop')
-rw-r--r--src/main/java/com/btr/proxy/search/desktop/DesktopProxySearchStrategy.java69
-rw-r--r--src/main/java/com/btr/proxy/search/desktop/gnome/GnomeProxySearchStrategy.java353
-rw-r--r--src/main/java/com/btr/proxy/search/desktop/gnome/ProxySchemasGSettingsAccess.java60
-rw-r--r--src/main/java/com/btr/proxy/search/desktop/kde/KdeProxySearchStrategy.java198
-rw-r--r--src/main/java/com/btr/proxy/search/desktop/kde/KdeSettingsParser.java132
-rw-r--r--src/main/java/com/btr/proxy/search/desktop/osx/OsxProxySearchStrategy.java325
-rw-r--r--src/main/java/com/btr/proxy/search/desktop/win/DLLManager.java171
-rw-r--r--src/main/java/com/btr/proxy/search/desktop/win/Win32IESettings.java68
-rw-r--r--src/main/java/com/btr/proxy/search/desktop/win/Win32ProxyUtils.java88
-rw-r--r--src/main/java/com/btr/proxy/search/desktop/win/WinProxySearchStrategy.java52
10 files changed, 1516 insertions, 0 deletions
diff --git a/src/main/java/com/btr/proxy/search/desktop/DesktopProxySearchStrategy.java b/src/main/java/com/btr/proxy/search/desktop/DesktopProxySearchStrategy.java
new file mode 100644
index 0000000..8a5a5d8
--- /dev/null
+++ b/src/main/java/com/btr/proxy/search/desktop/DesktopProxySearchStrategy.java
@@ -0,0 +1,69 @@
+package com.btr.proxy.search.desktop;
+
+import java.net.ProxySelector;
+
+import com.btr.proxy.search.ProxySearchStrategy;
+import com.btr.proxy.search.desktop.gnome.GnomeProxySearchStrategy;
+import com.btr.proxy.search.desktop.kde.KdeProxySearchStrategy;
+import com.btr.proxy.search.desktop.osx.OsxProxySearchStrategy;
+import com.btr.proxy.search.desktop.win.WinProxySearchStrategy;
+import com.btr.proxy.util.Logger;
+import com.btr.proxy.util.PlatformUtil;
+import com.btr.proxy.util.ProxyException;
+import com.btr.proxy.util.Logger.LogLevel;
+import com.btr.proxy.util.PlatformUtil.Desktop;
+import com.btr.proxy.util.PlatformUtil.Platform;
+
+/*****************************************************************************
+ * This search provider will try to find out on which desktop platform we
+ * are running and then will initialize the default proxy search.
+ *
+ * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009
+ ****************************************************************************/
+
+public class DesktopProxySearchStrategy implements ProxySearchStrategy {
+
+ /*************************************************************************
+ * Gets the default ProxySelector for the current platform.
+ * @return a ProxySelector, null if none is found.
+ * @throws ProxyException on error.
+ ************************************************************************/
+
+ public ProxySelector getProxySelector() throws ProxyException {
+ ProxySearchStrategy strategy = findDesktopSpecificStrategy();
+ return strategy == null? null : strategy.getProxySelector();
+ }
+
+ /*************************************************************************
+ * Determine the desktop and create a strategy for it.
+ * @return a desktop specific strategy, null if none was found.
+ ************************************************************************/
+
+ private ProxySearchStrategy findDesktopSpecificStrategy() {
+ Platform pf = PlatformUtil.getCurrentPlattform();
+ Desktop dt = PlatformUtil.getCurrentDesktop();
+
+ Logger.log(getClass(), LogLevel.TRACE, "Detecting system settings.");
+
+ ProxySearchStrategy strategy = null;
+
+ if (pf == Platform.WIN) {
+ Logger.log(getClass(), LogLevel.TRACE, "We are running on Windows.");
+ strategy = new WinProxySearchStrategy();
+ } else
+ if (dt == Desktop.KDE) {
+ Logger.log(getClass(), LogLevel.TRACE, "We are running on KDE.");
+ strategy = new KdeProxySearchStrategy();
+ } else
+ if (dt == Desktop.GNOME) {
+ Logger.log(getClass(), LogLevel.TRACE, "We are running on Gnome.");
+ strategy = new GnomeProxySearchStrategy();
+ } else
+ if (dt == Desktop.MAC_OS) {
+ Logger.log(getClass(), LogLevel.TRACE, "We are running on Mac OSX.");
+ strategy = new OsxProxySearchStrategy();
+ }
+ return strategy;
+ }
+
+}
diff --git a/src/main/java/com/btr/proxy/search/desktop/gnome/GnomeProxySearchStrategy.java b/src/main/java/com/btr/proxy/search/desktop/gnome/GnomeProxySearchStrategy.java
new file mode 100644
index 0000000..240fb39
--- /dev/null
+++ b/src/main/java/com/btr/proxy/search/desktop/gnome/GnomeProxySearchStrategy.java
@@ -0,0 +1,353 @@
+package com.btr.proxy.search.desktop.gnome;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.ProxySelector;
+import java.util.Properties;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import com.btr.proxy.search.ProxySearchStrategy;
+import com.btr.proxy.selector.direct.NoProxySelector;
+import com.btr.proxy.selector.fixed.FixedProxySelector;
+import com.btr.proxy.selector.misc.ProtocolDispatchSelector;
+import com.btr.proxy.selector.whitelist.ProxyBypassListSelector;
+import com.btr.proxy.util.EmptyXMLResolver;
+import com.btr.proxy.util.Logger;
+import com.btr.proxy.util.ProxyException;
+import com.btr.proxy.util.ProxyUtil;
+import com.btr.proxy.util.Logger.LogLevel;
+
+/*****************************************************************************
+ * Loads the Gnome proxy settings from the Gnome GConf settings.
+ * <p>
+ * The following settings are extracted from the configuration that is stored
+ * in <i>.gconf</i> folder found in the user's home directory:
+ * </p>
+ * <ul>
+ * <li><i>/system/http_proxy/use_http_proxy</i> -> bool used only by gnome-vfs </li>
+ * <li><i>/system/http_proxy/host</i> -> string "my-proxy.example.com" without "http://"</li>
+ * <li><i>/system/http_proxy/port</i> -> int</li>
+ * <li><i>/system/http_proxy/use_authentication</i> -> bool</li>
+ * <li><i>/system/http_proxy/authentication_user</i> -> string</li>
+ * <li><i>/system/http_proxy/authentication_password</i> -> string</li>
+ * <li><i>/system/http_proxy/ignore_hosts</i> -> list-of-string</li>
+ * <li><i>/system/proxy/mode</i> -> string THIS IS THE CANONICAL KEY; SEE BELOW</li>
+ * <li><i>/system/proxy/secure_host</i> -> string "proxy-for-https.example.com"</li>
+ * <li><i>/system/proxy/secure_port</i> -> int</li>
+ * <li><i>/system/proxy/ftp_host</i> -> string "proxy-for-ftp.example.com"</li>
+ * <li><i>/system/proxy/ftp_port</i> -> int</li>
+ * <li><i>/system/proxy/socks_host</i> -> string "proxy-for-socks.example.com"</li>
+ * <li><i>/system/proxy/socks_port</i> -> int</li>
+ * <li><i>/system/proxy/autoconfig_url</i> -> string "http://proxy-autoconfig.example.com"</li>
+ * </ul>
+ * <i>/system/proxy/mode</i> can be either:<br/>
+ * "none" -> No proxy is used<br/>
+ * "manual" -> The user's configuration values are used (/system/http_proxy/{host,port,etc.})<br/>
+ * "auto" -> The "/system/proxy/autoconfig_url" key is used <br/>
+ * <p>
+ * GNOME Proxy_configuration settings are explained
+ * <a href="http://en.opensuse.org/GNOME/Proxy_configuration">here</a> in detail
+ * </p>
+ * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009
+ ****************************************************************************/
+
+public class GnomeProxySearchStrategy implements ProxySearchStrategy {
+
+ /*************************************************************************
+ * ProxySelector
+ * @see java.net.ProxySelector#ProxySelector()
+ ************************************************************************/
+
+ public GnomeProxySearchStrategy() {
+ super();
+ }
+
+ /*************************************************************************
+ * Loads the proxy settings and initializes a proxy selector for the Gnome
+ * proxy settings.
+ * @return a configured ProxySelector, null if none is found.
+ * @throws ProxyException on file reading error.
+ ************************************************************************/
+
+ public ProxySelector getProxySelector() throws ProxyException {
+
+ Logger.log(getClass(), LogLevel.TRACE, "Detecting Gnome proxy settings");
+
+ Properties settings = readSettings();
+
+ String type = settings.getProperty("/system/proxy/mode");
+ ProxySelector result = null;
+ if (type == null) {
+ String useProxy = settings.getProperty("/system/http_proxy/use_http_proxy");
+ if (useProxy == null) {
+ return null;
+ }
+ type = Boolean.parseBoolean(useProxy)?"manual":"none";
+ }
+
+ if ("none".equals(type)) {
+ Logger.log(getClass(), LogLevel.TRACE, "Gnome uses no proxy");
+ result = NoProxySelector.getInstance();
+ }
+ if ("manual".equals(type)) {
+ Logger.log(getClass(), LogLevel.TRACE, "Gnome uses manual proxy settings");
+ result = setupFixedProxySelector(settings);
+ }
+ 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);
+ }
+
+ // Wrap into white-list filter?
+ String noProxyList = settings.getProperty("/system/http_proxy/ignore_hosts", null);
+ if (result != null && noProxyList != null && noProxyList.trim().length() > 0) {
+ Logger.log(getClass(), LogLevel.TRACE, "Gnome uses proxy bypass list: {0}", noProxyList);
+ result = new ProxyBypassListSelector(noProxyList, result);
+ }
+
+ return result;
+ }
+
+ /*************************************************************************
+ * Load the proxy settings from the gconf settings XML file.
+ * @return the loaded settings stored in a properties object.
+ * @throws ProxyException on processing error.
+ ************************************************************************/
+
+ public Properties readSettings() throws ProxyException {
+ Properties settings = new Properties();
+ try {
+ parseSettings("/system/proxy/", settings);
+ parseSettings("/system/http_proxy/", settings);
+ } catch (IOException e) {
+ Logger.log(getClass(), LogLevel.ERROR, "Gnome settings file error.", e);
+ throw new ProxyException(e);
+ }
+ return settings;
+ }
+
+ /*************************************************************************
+ * Finds the Gnome GConf settings file.
+ * @param context the gconf context to parse.
+ * @return a file or null if does not exist.
+ ************************************************************************/
+
+ private File findSettingsFile(String context) {
+ // Normally we should inspect /etc/gconf/<version>/path to find out where the actual file is.
+ // But for normal systems this is always stored in .gconf folder in the user's home directory.
+ File userDir = new File(System.getProperty("user.home"));
+
+ // Build directory path for context
+ StringBuilder path = new StringBuilder();
+ String[] parts = context.split("/");
+ for (String part : parts) {
+ path.append(part);
+ path.append(File.separator);
+ }
+
+ File settingsFile = new File(userDir, ".gconf"+File.separator+path.toString()+"%gconf.xml");
+ if (!settingsFile.exists()) {
+ Logger.log(getClass(), LogLevel.WARNING, "Gnome settings: {0} not found.", settingsFile);
+ return null;
+ }
+ return settingsFile;
+ }
+
+ /*************************************************************************
+ * Parse the fixed proxy settings and build an ProxySelector for this a
+ * chained configuration.
+ * @param settings the proxy settings to evaluate.
+ ************************************************************************/
+
+ private ProxySelector setupFixedProxySelector(Properties settings) {
+ if (!hasProxySettings(settings)) {
+ return null;
+ }
+ ProtocolDispatchSelector ps = new ProtocolDispatchSelector();
+ installHttpSelector(settings, ps);
+
+ if (useForAllProtocols(settings)) {
+ ps.setFallbackSelector(ps.getSelector("http"));
+ } else {
+ installSecureSelector(settings, ps);
+ installFtpSelector(settings, ps);
+ installSocksSelector(settings, ps);
+ }
+ return ps;
+ }
+
+ /*************************************************************************
+ * Check if the http proxy should also be used for all other protocols.
+ * @param settings to inspect.
+ * @return true if only one proxy is configured else false.
+ ************************************************************************/
+
+ private boolean useForAllProtocols(Properties settings) {
+ return Boolean.parseBoolean(
+ settings.getProperty("/system/http_proxy/use_same_proxy", "false"));
+ }
+
+ /*************************************************************************
+ * Checks if we have Proxy configuration settings in the properties.
+ * @param settings to inspect.
+ * @return true if we have found Proxy settings.
+ ************************************************************************/
+
+ private boolean hasProxySettings(Properties settings) {
+ String proxyHost = settings.getProperty("/system/http_proxy/host", null);
+ return proxyHost != null && proxyHost.length() > 0;
+ }
+
+ /*************************************************************************
+ * Install a http proxy from the given settings.
+ * @param settings to inspect
+ * @param ps the dispatch selector to configure.
+ * @throws NumberFormatException
+ ************************************************************************/
+
+ private void installHttpSelector(Properties settings,
+ ProtocolDispatchSelector ps) throws NumberFormatException {
+ String proxyHost = settings.getProperty("/system/http_proxy/host", null);
+ int proxyPort = Integer.parseInt(settings.getProperty("/system/http_proxy/port", "0").trim());
+ if (proxyHost != null && proxyHost.length() > 0 && proxyPort > 0) {
+ Logger.log(getClass(), LogLevel.TRACE, "Gnome http proxy is {0}:{1}", proxyHost, proxyPort);
+ ps.setSelector("http", new FixedProxySelector(proxyHost.trim(), proxyPort));
+ }
+ }
+
+ /*************************************************************************
+ * Install a socks proxy from the given settings.
+ * @param settings to inspect
+ * @param ps the dispatch selector to configure.
+ * @throws NumberFormatException
+ ************************************************************************/
+
+ private void installSocksSelector(Properties settings,
+ ProtocolDispatchSelector ps) throws NumberFormatException {
+ String proxyHost = settings.getProperty("/system/proxy/socks_host", null);
+ int proxyPort = Integer.parseInt(settings.getProperty("/system/proxy/socks_port", "0").trim());
+ if (proxyHost != null && proxyHost.length() > 0 && proxyPort > 0) {
+ Logger.log(getClass(), LogLevel.TRACE, "Gnome socks proxy is {0}:{1}", proxyHost, proxyPort);
+ ps.setSelector("socks", new FixedProxySelector(proxyHost.trim(), proxyPort));
+ }
+ }
+
+ /*************************************************************************
+ * @param settings
+ * @param ps
+ * @throws NumberFormatException
+ ************************************************************************/
+
+ private void installFtpSelector(Properties settings,
+ ProtocolDispatchSelector ps) throws NumberFormatException {
+ String proxyHost = settings.getProperty("/system/proxy/ftp_host", null);
+ int proxyPort = Integer.parseInt(settings.getProperty("/system/proxy/ftp_port", "0").trim());
+ if (proxyHost != null && proxyHost.length() > 0 && proxyPort > 0) {
+ Logger.log(getClass(), LogLevel.TRACE, "Gnome ftp proxy is {0}:{1}", proxyHost, proxyPort);
+ ps.setSelector("ftp", new FixedProxySelector(proxyHost.trim(), proxyPort));
+ }
+ }
+
+ /*************************************************************************
+ * @param settings
+ * @param ps
+ * @throws NumberFormatException
+ ************************************************************************/
+
+
+ private void installSecureSelector(Properties settings,
+ ProtocolDispatchSelector ps) throws NumberFormatException {
+ String proxyHost = settings.getProperty("/system/proxy/secure_host", null);
+ int proxyPort = Integer.parseInt(settings.getProperty("/system/proxy/secure_port", "0").trim());
+ if (proxyHost != null && proxyHost.length() > 0 && proxyPort > 0) {
+ Logger.log(getClass(), LogLevel.TRACE, "Gnome secure proxy is {0}:{1}", proxyHost, proxyPort);
+ ps.setSelector("https", new FixedProxySelector(proxyHost.trim(), proxyPort));
+ ps.setSelector("sftp", new FixedProxySelector(proxyHost.trim(), proxyPort));
+ }
+ }
+
+ /*************************************************************************
+ * Parse the settings file and extract all network.proxy.* settings from it.
+ * @param context the gconf context to parse.
+ * @param settings the settings object to fill.
+ * @return the parsed properties.
+ * @throws IOException on read error.
+ ************************************************************************/
+
+ private Properties parseSettings(String context, Properties settings) throws IOException {
+
+ // Read settings from file
+ File settingsFile = findSettingsFile(context);
+ if (settingsFile == null) {
+ return settings;
+ }
+
+ try {
+ DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ documentBuilder.setEntityResolver(new EmptyXMLResolver());
+ Document doc = documentBuilder.parse(settingsFile);
+ Element root = doc.getDocumentElement();
+ Node entry = root.getFirstChild();
+ while (entry != null) {
+ if ("entry".equals(entry.getNodeName()) && entry instanceof Element) {
+ String entryName = ((Element)entry).getAttribute("name");
+ settings.setProperty(context+entryName, getEntryValue((Element) entry));
+ }
+ entry = entry.getNextSibling();
+ }
+ } catch (SAXException e) {
+ Logger.log(getClass(), LogLevel.ERROR, "Gnome settings parse error", e);
+ throw new IOException(e.getMessage());
+ } catch (ParserConfigurationException e) {
+ Logger.log(getClass(), LogLevel.ERROR, "Gnome settings parse error", e);
+ throw new IOException(e.getMessage());
+ }
+
+ return settings;
+ }
+
+ /*************************************************************************
+ * Parse an entry value from a given entry node.
+ * @param entry the XML node to inspect.
+ * @return the value, null if it has no value.
+ ************************************************************************/
+
+ private String getEntryValue(Element entry) {
+ String type = entry.getAttribute("type");
+
+ if ("int".equals(type) || "bool".equals(type)) {
+ return entry.getAttribute("value");
+ }
+ if ("string".equals(type)) {
+ NodeList list = entry.getElementsByTagName("stringvalue");
+ if (list.getLength() > 0) {
+ return list.item(0).getTextContent();
+ }
+ }
+ if ("list".equals(type)) {
+ StringBuilder result = new StringBuilder();
+ NodeList list = entry.getElementsByTagName("li");
+
+ // Build comma separated list of items
+ for (int i = 0; i < list.getLength(); i++) {
+ if (result.length() > 0) {
+ result.append(",");
+ }
+ result.append(getEntryValue((Element) list.item(i)));
+ }
+ return result.toString();
+ }
+ return null;
+ }
+
+}
diff --git a/src/main/java/com/btr/proxy/search/desktop/gnome/ProxySchemasGSettingsAccess.java b/src/main/java/com/btr/proxy/search/desktop/gnome/ProxySchemasGSettingsAccess.java
new file mode 100644
index 0000000..6e1b425
--- /dev/null
+++ b/src/main/java/com/btr/proxy/search/desktop/gnome/ProxySchemasGSettingsAccess.java
@@ -0,0 +1,60 @@
+package com.btr.proxy.search.desktop.gnome;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Map;
+
+public class ProxySchemasGSettingsAccess {
+
+ private static void closeStream(Closeable c) {
+ try {
+ c.close();
+ } catch (IOException e) {
+ // Ignore cleanup errors
+ }
+ }
+
+ static void copy(InputStream source, OutputStream dest) throws IOException {
+ try {
+ byte[] buffer = new byte[1024];
+ int read = 0;
+ while (read >= 0) {
+ dest.write(buffer, 0, read);
+ read = source.read(buffer);
+ }
+ dest.flush();
+ } finally {
+ closeStream(source);
+ closeStream(dest);
+ }
+ }
+
+ static {
+ String arch = System.getProperty("os.arch");
+ if (arch.equals("x86_64") || arch.equals("x64") || arch.equals("x86-64")) {
+ arch = "amd64";
+ }
+ if (arch.equals("i386") || arch.equals("i686")) {
+ arch = "x86";
+ }
+ String libName = "gsettings-" + arch + ".so";
+ File libFile;
+ try {
+ InputStream source = ProxySchemasGSettingsAccess.class.getResourceAsStream("/lib/" + libName);
+ libFile = File.createTempFile("gsettings", ".so");
+ libFile.deleteOnExit();
+ FileOutputStream destination = new FileOutputStream(libFile);
+ copy(source, destination);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ System.load(libFile.getAbsolutePath());
+ }
+
+ public static native Map<String, Map<String, Object>> getValueByKeyBySchema();
+
+}
diff --git a/src/main/java/com/btr/proxy/search/desktop/kde/KdeProxySearchStrategy.java b/src/main/java/com/btr/proxy/search/desktop/kde/KdeProxySearchStrategy.java
new file mode 100644
index 0000000..e05d72e
--- /dev/null
+++ b/src/main/java/com/btr/proxy/search/desktop/kde/KdeProxySearchStrategy.java
@@ -0,0 +1,198 @@
+package com.btr.proxy.search.desktop.kde;
+
+import java.io.IOException;
+import java.net.ProxySelector;
+import java.util.Properties;
+
+import com.btr.proxy.search.ProxySearchStrategy;
+import com.btr.proxy.search.env.EnvProxySearchStrategy;
+import com.btr.proxy.search.wpad.WpadProxySearchStrategy;
+import com.btr.proxy.selector.direct.NoProxySelector;
+import com.btr.proxy.selector.fixed.FixedProxySelector;
+import com.btr.proxy.selector.misc.ProtocolDispatchSelector;
+import com.btr.proxy.selector.pac.PacProxySelector;
+import com.btr.proxy.selector.pac.UrlPacScriptSource;
+import com.btr.proxy.selector.whitelist.ProxyBypassListSelector;
+import com.btr.proxy.selector.whitelist.UseProxyWhiteListSelector;
+import com.btr.proxy.util.Logger;
+import com.btr.proxy.util.Logger.LogLevel;
+import com.btr.proxy.util.ProxyException;
+import com.btr.proxy.util.ProxyUtil;
+
+/*****************************************************************************
+ * Loads the KDE4 proxy settings from the KDE <i>kioslaverc</i> file.
+ * This will load properties from the file
+ * <p>
+ * <i>.kde/share/config/kioslaverc</i>
+ * </P>
+ * starting from the current users home directory.
+ * <p>
+ * The following settings are extracted from the section "[Proxy Settings]":
+ * </p>
+ * <ul>
+ * <li><i>AuthMode</i> -> 0 = no auth., 1 = use login.</li>
+ * <li><i>ProxyType</i> -> 0 = direct 1 = use fixed settings, 2 = use PAC, 3 = automatic (WPAD) , 4 = Use environment variables?</li>
+ * <li><i>Proxy Config</i> Script -> URL to PAC file</li>
+ * <li><i>ftpProxy</i> -> Fixed ftp proxy address e.g. http://www.ftp-proxy.com:8080</li>
+ * <li><i>httpProxy</i> -> Fixed http proxy e.g http://www.http-proxy.com:8080</li>
+ * <li><i>httpsProxy</i> -> Fixed https proxy e.g http://www.https-proxy.com:8080</li>
+ * <li><i>NoProxyFor</i> -> Proxy white list</li>
+ * <li><i>ReversedException</i> -> false = use NoProxyFor, true = revert meaning of the NoProxyFor list</li>
+ * </ul>
+ *
+ *
+ * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009
+ ****************************************************************************/
+
+public class KdeProxySearchStrategy implements ProxySearchStrategy {
+
+ private KdeSettingsParser settingsParser;
+
+ /*************************************************************************
+ * ProxySelector using the given parser.
+ * @see java.net.ProxySelector#ProxySelector()
+ ************************************************************************/
+
+ public KdeProxySearchStrategy() {
+ this(new KdeSettingsParser());
+ }
+
+ /*************************************************************************
+ * ProxySelector
+ * @see java.net.ProxySelector#ProxySelector()
+ ************************************************************************/
+
+ public KdeProxySearchStrategy(KdeSettingsParser settingsParser) {
+ super();
+ this.settingsParser = settingsParser;
+ }
+
+ /*************************************************************************
+ * Loads the proxy settings and initializes a proxy selector for the firefox
+ * proxy settings.
+ * @return a configured ProxySelector, null if none is found.
+ * @throws ProxyException on file reading error.
+ ************************************************************************/
+
+ public ProxySelector getProxySelector() throws ProxyException {
+
+ Logger.log(getClass(), LogLevel.TRACE, "Detecting Kde proxy settings");
+
+ Properties settings = readSettings();
+ if (settings == null) {
+ return null;
+ }
+
+ ProxySelector result = null;
+ int type = Integer.parseInt(settings.getProperty("ProxyType", "-1"));
+ switch (type) {
+ case 0: // Use no proxy
+ Logger.log(getClass(), LogLevel.TRACE, "Kde uses no proxy");
+ result = NoProxySelector.getInstance();
+ break;
+ case 1: // Fixed settings
+ Logger.log(getClass(), LogLevel.TRACE, "Kde uses manual proxy settings");
+ result = setupFixedProxySelector(settings);
+ break;
+ 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);
+ break;
+ case 3: // WPAD
+ Logger.log(getClass(), LogLevel.TRACE, "Kde uses WPAD to detect the proxy");
+ result = new WpadProxySearchStrategy().getProxySelector();
+ break;
+ case 4: // Use environment variables
+ Logger.log(getClass(), LogLevel.TRACE, "Kde reads proxy from environment");
+ result = setupEnvVarSelector(settings);
+ break;
+ default:
+ break;
+ }
+
+ return result;
+ }
+
+ /*************************************************************************
+ * Reads the settings and stores them in a properties map.
+ * @return the parsed settings.
+ * @throws ProxyException
+ ************************************************************************/
+
+ private Properties readSettings() throws ProxyException {
+ try {
+ return this.settingsParser.parseSettings();
+ } catch (IOException e) {
+ Logger.log(getClass(), LogLevel.ERROR, "Can't parse settings.", e);
+ throw new ProxyException(e);
+ }
+ }
+
+ /*************************************************************************
+ * Builds an environment variable selector.
+ * @param settings the settings to read from.
+ * @return the ProxySelector using environment variables.
+ ************************************************************************/
+
+ private ProxySelector setupEnvVarSelector(Properties settings) {
+ ProxySelector result;
+ result = new EnvProxySearchStrategy(
+ settings.getProperty("httpProxy"),
+ settings.getProperty("httpsProxy"),
+ settings.getProperty("ftpProxy"),
+ settings.getProperty("NoProxyFor")
+ ).getProxySelector();
+ return result;
+ }
+
+ /*************************************************************************
+ * Parse the fixed proxy settings and build an ProxySelector for this a
+ * chained configuration.
+ * @param settings the proxy settings to evaluate.
+ ************************************************************************/
+
+ private ProxySelector setupFixedProxySelector(Properties settings) {
+ String proxyVar = settings.getProperty("httpProxy", null);
+ FixedProxySelector httpPS = ProxyUtil.parseProxySettings(proxyVar);
+ if (httpPS == null) {
+ Logger.log(getClass(), LogLevel.TRACE, "Kde http proxy is {0}", proxyVar);
+ return null;
+ }
+
+ ProtocolDispatchSelector ps = new ProtocolDispatchSelector();
+ ps.setSelector("http", httpPS);
+
+ proxyVar = settings.getProperty("httpsProxy", null);
+ FixedProxySelector httpsPS = ProxyUtil.parseProxySettings(proxyVar);
+ if (httpsPS != null) {
+ Logger.log(getClass(), LogLevel.TRACE, "Kde https proxy is {0}", proxyVar);
+ ps.setSelector("https", httpsPS);
+ }
+
+ proxyVar = settings.getProperty("ftpProxy", null);
+ FixedProxySelector ftpPS = ProxyUtil.parseProxySettings(proxyVar);
+ if (ftpPS != null) {
+ Logger.log(getClass(), LogLevel.TRACE, "Kde ftp proxy is {0}", proxyVar);
+ ps.setSelector("ftp", ftpPS);
+ }
+
+ // Wrap in white list filter.
+ String noProxyList = settings.getProperty("NoProxyFor", null);
+ if (noProxyList != null && noProxyList.trim().length() > 0) {
+ boolean reverse = "true".equals(settings.getProperty("ReversedException", "false"));
+ if (reverse) {
+ Logger.log(getClass(), LogLevel.TRACE, "Kde proxy blacklist is {0}", noProxyList);
+ return new UseProxyWhiteListSelector(noProxyList, ps);
+ } else {
+ Logger.log(getClass(), LogLevel.TRACE, "Kde proxy whitelist is {0}", noProxyList);
+ return new ProxyBypassListSelector(noProxyList, ps);
+ }
+ }
+
+ return ps;
+ }
+
+
+
+}
diff --git a/src/main/java/com/btr/proxy/search/desktop/kde/KdeSettingsParser.java b/src/main/java/com/btr/proxy/search/desktop/kde/KdeSettingsParser.java
new file mode 100644
index 0000000..904528e
--- /dev/null
+++ b/src/main/java/com/btr/proxy/search/desktop/kde/KdeSettingsParser.java
@@ -0,0 +1,132 @@
+package com.btr.proxy.search.desktop.kde;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Properties;
+
+import com.btr.proxy.util.Logger;
+import com.btr.proxy.util.Logger.LogLevel;
+
+/*****************************************************************************
+ * Parser for the KDE settings file.
+ * The KDE proxy settings are stored in the file:
+ * <p>
+ * <i>.kde/share/config/kioslaverc</i>
+ * </p>
+ * in the users home directory.
+ *
+ * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009
+ ****************************************************************************/
+
+public class KdeSettingsParser {
+
+ private File settingsFile;
+
+ /*************************************************************************
+ * Constructor
+ ************************************************************************/
+
+ public KdeSettingsParser() {
+ this(null);
+ }
+
+ /*************************************************************************
+ * Constructor
+ ************************************************************************/
+
+ public KdeSettingsParser(File settingsFile) {
+ super();
+ this.settingsFile = settingsFile;
+ }
+
+ /*************************************************************************
+ * Parse the settings file and extract all network.proxy.* settings from it.
+ * @return the parsed properties.
+ * @throws IOException on read error.
+ ************************************************************************/
+
+ public Properties parseSettings() throws IOException {
+ // Search for existing settings.
+ if (this.settingsFile == null) {
+ this.settingsFile = findSettingsFile();
+ }
+ if (this.settingsFile == null) {
+ return null;
+ }
+
+ // Read settings from file.
+ BufferedReader fin = new BufferedReader(
+ new InputStreamReader(
+ new FileInputStream(this.settingsFile)));
+
+ Properties result = new Properties();
+ try {
+ String line = fin.readLine();
+
+ // Find section start.
+ while (line != null && !"[Proxy Settings]".equals(line.trim())) {
+ line = fin.readLine();
+ }
+ if (line == null) {
+ return result;
+ }
+
+ // Read full section
+ line = "";
+ while (line != null && !line.trim().startsWith("[")) {
+ line = line.trim();
+ int index = line.indexOf('=');
+ if (index > 0) {
+ String key = line.substring(0, index).trim();
+ String value = line.substring(index+1).trim();
+ result.setProperty(key, value);
+ }
+
+ line = fin.readLine();
+ }
+ } finally {
+ fin.close();
+ }
+
+ return result;
+ }
+
+ /*************************************************************************
+ * Finds all the KDE network settings file.
+ * @return a file or null if does not exist.
+ ************************************************************************/
+
+ private File findSettingsFile() {
+ File userDir = new File(System.getProperty("user.home"));
+ if ("4".equals(System.getenv("KDE_SESSION_VERSION"))) {
+ this.settingsFile = findSettingsFile(
+ new File(userDir, ".kde4"+File.separator+"share"+File.separator+"config"+File.separator+"kioslaverc"));
+ }
+ if (this.settingsFile == null) {
+ return findSettingsFile(
+ new File(userDir, ".kde"+File.separator+"share"+File.separator+"config"+File.separator+"kioslaverc"));
+ } else {
+ return this.settingsFile;
+ }
+ }
+
+ /*************************************************************************
+ * Internal method to test if the settings file is at the given place.
+ * @param settingsFile the path to test.
+ * @return the file or null if it does not exist.
+ ************************************************************************/
+
+ private File findSettingsFile(File settingsFile) {
+ Logger.log(getClass(), LogLevel.TRACE, "Searching Kde settings in {0}", settingsFile);
+ if (!settingsFile.exists()) {
+ Logger.log(getClass(), LogLevel.DEBUG, "Settings not found");
+ return null;
+ }
+ Logger.log(getClass(), LogLevel.TRACE, "Settings found");
+ return settingsFile;
+ }
+
+}
diff --git a/src/main/java/com/btr/proxy/search/desktop/osx/OsxProxySearchStrategy.java b/src/main/java/com/btr/proxy/search/desktop/osx/OsxProxySearchStrategy.java
new file mode 100644
index 0000000..3d67ae7
--- /dev/null
+++ b/src/main/java/com/btr/proxy/search/desktop/osx/OsxProxySearchStrategy.java
@@ -0,0 +1,325 @@
+package com.btr.proxy.search.desktop.osx;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.NetworkInterface;
+import java.net.ProxySelector;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.List;
+
+import com.btr.proxy.search.ProxySearchStrategy;
+import com.btr.proxy.search.browser.ie.IELocalByPassFilter;
+import com.btr.proxy.search.wpad.WpadProxySearchStrategy;
+import com.btr.proxy.selector.direct.NoProxySelector;
+import com.btr.proxy.selector.fixed.FixedProxySelector;
+import com.btr.proxy.selector.fixed.FixedSocksSelector;
+import com.btr.proxy.selector.misc.ProtocolDispatchSelector;
+import com.btr.proxy.selector.whitelist.ProxyBypassListSelector;
+import com.btr.proxy.util.Logger;
+import com.btr.proxy.util.Logger.LogLevel;
+import com.btr.proxy.util.PListParser;
+import com.btr.proxy.util.PListParser.Dict;
+import com.btr.proxy.util.PListParser.XmlParseException;
+import com.btr.proxy.util.ProxyException;
+import com.btr.proxy.util.ProxyUtil;
+import com.btr.proxy.util.UriFilter;
+
+/*****************************************************************************
+ * Loads the OSX system proxy settings from the settings file.
+ * <p>
+ * All settings are stored in OSX in a special XML file format.
+ * These settings file are named plist files and contain nested dictionaries, arrays and values.
+ * </p><p>
+ * To parse this file we use a parser that is derived from a plist parser that
+ * comes with the xmlwise XML parser package:
+ * </p><p>
+ * http://code.google.com/p/xmlwise/
+ * </p><p>
+ * I modified that parser to work with the default Java XML parsing library.
+ * </p><p>
+ * The plist file is located on OSX at:
+ * </p><p>
+ * /Library/Preferences/SystemConfiguration/preferences.plist
+ * </p>
+ *
+ * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2011
+ ****************************************************************************/
+
+public class OsxProxySearchStrategy implements ProxySearchStrategy {
+
+ public static final String OVERRIDE_SETTINGS_FILE = "com.btr.proxy.osx.settingsFile";
+ public static final String OVERRIDE_ACCEPTED_DEVICES = "com.btr.proxy.osx.acceptedDevices";
+
+ private static final String SETTINGS_FILE = "/Library/Preferences/SystemConfiguration/preferences.plist";
+
+ /*************************************************************************
+ * ProxySelector
+ * @see java.net.ProxySelector#ProxySelector()
+ ************************************************************************/
+
+ public OsxProxySearchStrategy() {
+ super();
+ }
+
+ /*************************************************************************
+ * Loads the proxy settings and initializes a proxy selector for the OSX
+ * proxy settings.
+ * @return a configured ProxySelector, null if none is found.
+ * @throws ProxyException on file reading error.
+ ************************************************************************/
+
+ public ProxySelector getProxySelector() throws ProxyException {
+
+ Logger.log(getClass(), LogLevel.TRACE, "Detecting OSX proxy settings");
+
+ try {
+ List<String> acceptedInterfaces = getNetworkInterfaces();
+
+ Dict settings = PListParser.load(getSettingsFile());
+ Object currentSet = settings.getAtPath("/CurrentSet");
+ if (currentSet == null) {
+ throw new ProxyException("CurrentSet not defined");
+ }
+
+ Dict networkSet = (Dict) settings.getAtPath(String.valueOf(currentSet));
+ List<?> serviceOrder = (List<?>) networkSet.getAtPath("/Network/Global/IPv4/ServiceOrder");
+ if (serviceOrder == null || serviceOrder.size() == 0) {
+ throw new ProxyException("ServiceOrder not defined");
+ }
+
+ // Look at the Services in priority order and pick the first one that was
+ // also accepted above
+ Dict proxySettings = null;
+ for (int i = 0; i < serviceOrder.size() && proxySettings == null; i++) {
+ Object candidateService = serviceOrder.get(i);
+ Object networkService = networkSet.getAtPath("/Network/Service/"+candidateService+"/__LINK__");
+ if (networkService == null ) {
+ throw new ProxyException("NetworkService not defined.");
+ }
+ Dict selectedServiceSettings = (Dict) settings.getAtPath(""+networkService);
+ String interfaceName = (String) selectedServiceSettings.getAtPath("/Interface/DeviceName");
+ if (acceptedInterfaces.contains(interfaceName)) {
+ Logger.log(getClass(), LogLevel.TRACE, "Looking up proxies for device " + interfaceName);
+ proxySettings = (Dict) selectedServiceSettings.getAtPath("/Proxies");
+ }
+ }
+ if (proxySettings == null) {
+ return NoProxySelector.getInstance();
+ }
+
+ return buildSelector(proxySettings);
+ } catch (XmlParseException e) {
+ throw new ProxyException(e);
+ } catch (IOException e) {
+ throw new ProxyException(e);
+ }
+ }
+
+ /*************************************************************************
+ * Build a selector from the given settings.
+ * @param proxySettings to parse
+ * @return the configured selector
+ * @throws ProxyException on error
+ ************************************************************************/
+
+ private ProxySelector buildSelector(Dict proxySettings) throws ProxyException {
+ ProtocolDispatchSelector ps = new ProtocolDispatchSelector();
+ installSelectorForProtocol(proxySettings, ps, "HTTP");
+ installSelectorForProtocol(proxySettings, ps, "HTTPS");
+ installSelectorForProtocol(proxySettings, ps, "FTP");
+ installSelectorForProtocol(proxySettings, ps, "Gopher");
+ installSelectorForProtocol(proxySettings, ps, "RTSP");
+ installSocksProxy(proxySettings, ps);
+
+ ProxySelector result = ps;
+ result = installPacProxyIfAvailable(proxySettings, result);
+ result = autodetectProxyIfAvailable(proxySettings, result);
+
+ result = installExceptionList(proxySettings, result);
+ result = installSimpleHostFilter(proxySettings, result);
+ return result;
+ }
+
+ /*************************************************************************
+ * Create a list of Ethernet interfaces that are connected
+ * @return
+ * @throws SocketException
+ ************************************************************************/
+
+ private List<String> getNetworkInterfaces() throws SocketException {
+ String override = System.getProperty(OVERRIDE_ACCEPTED_DEVICES);
+ if (override != null && override.length() > 0) {
+ return Arrays.asList(override.split(";"));
+ }
+
+ List<String> acceptedInterfaces = new ArrayList<String>();
+ Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
+ while (interfaces.hasMoreElements()) {
+ NetworkInterface ni = interfaces.nextElement();
+ if (isInterfaceAllowed(ni)) {
+ acceptedInterfaces.add(ni.getName());
+ }
+ }
+ return acceptedInterfaces;
+ }
+
+ /*************************************************************************
+ * Check if a given network interface is interesting for us.
+ * @param ni the interface to check
+ * @return true if accepted else false.
+ * @throws SocketException on error.
+ ************************************************************************/
+
+ private boolean isInterfaceAllowed(NetworkInterface ni) throws SocketException {
+ return !ni.isLoopback() &&
+ !ni.isPointToPoint() && // Not sure if we should filter the point to point interfaces?
+ !ni.isVirtual() &&
+ ni.isUp();
+ }
+
+ /*************************************************************************
+ * @return
+ ************************************************************************/
+
+ private File getSettingsFile() {
+ File result = new File(SETTINGS_FILE);
+ String overrideFile = System.getProperty(OVERRIDE_SETTINGS_FILE);
+ if (overrideFile != null) {
+ return new File(overrideFile);
+ }
+ return result;
+ }
+
+ /*************************************************************************
+ * @param proxySettings
+ * @param result
+ * @return
+ ************************************************************************/
+
+ private ProxySelector installSimpleHostFilter(
+ Dict proxySettings, ProxySelector result) {
+ if (isActive(proxySettings.get("ExcludeSimpleHostnames"))) {
+ List<UriFilter> localBypassFilter = new ArrayList<UriFilter>();
+ localBypassFilter.add(new IELocalByPassFilter());
+ result = new ProxyBypassListSelector(localBypassFilter, result);
+ }
+ return result;
+ }
+
+ /*************************************************************************
+ * @param proxySettings
+ * @param result
+ * @return
+ ************************************************************************/
+
+ private ProxySelector installExceptionList(
+ Dict proxySettings, ProxySelector result) {
+ List<?> proxyExceptions = (List<?>) proxySettings.get("ExceptionsList");
+ if (proxyExceptions != null && proxyExceptions.size() > 0) {
+ Logger.log(getClass(), LogLevel.TRACE, "OSX uses proxy bypass list: {0}", proxyExceptions);
+ String noProxyList = toCommaSeparatedString(proxyExceptions);
+ result = new ProxyBypassListSelector(noProxyList, result);
+ }
+ return result;
+ }
+
+ /*************************************************************************
+ * Convert a list to a comma separated list.
+ * @param proxyExceptions list of elements.
+ * @return a comma separated string of the list's content.
+ ************************************************************************/
+
+ private String toCommaSeparatedString(List<?> proxyExceptions) {
+ StringBuilder result = new StringBuilder();
+ for (Object object : proxyExceptions) {
+ if (result.length() > 0) {
+ result.append(",");
+ }
+ result.append(object);
+ }
+ return result.toString();
+ }
+
+ /*************************************************************************
+ * @param proxySettings
+ * @param result
+ * @return
+ * @throws ProxyException
+ ************************************************************************/
+
+ private ProxySelector autodetectProxyIfAvailable(
+ Dict proxySettings, ProxySelector result)
+ throws ProxyException {
+ if (isActive(proxySettings.get("ProxyAutoDiscoveryEnable"))) {
+ ProxySelector wp = new WpadProxySearchStrategy().getProxySelector();
+ if (wp != null) {
+ result = wp;
+ }
+ }
+ return result;
+ }
+
+ /*************************************************************************
+ * @param proxySettings
+ * @param result
+ * @return
+ ************************************************************************/
+
+ private ProxySelector installPacProxyIfAvailable(Dict proxySettings,
+ ProxySelector result) {
+ if (isActive(proxySettings.get("ProxyAutoConfigEnable"))) {
+ String url = (String) proxySettings.get("ProxyAutoConfigURLString");
+ result = ProxyUtil.buildPacSelectorForUrl(url);
+ }
+ return result;
+ }
+
+ /*************************************************************************
+ * Build a socks proxy and set it for the socks protocol.
+ * @param proxySettings to read the config values from.
+ * @param ps the ProtocolDispatchSelector to install the new proxy on.
+ ************************************************************************/
+
+ private void installSocksProxy(Dict proxySettings,
+ ProtocolDispatchSelector ps) {
+ if (isActive(proxySettings.get("SOCKSEnable"))) {
+ String proxyHost = (String) proxySettings.get("SOCKSProxy");
+ int proxyPort = (Integer) proxySettings.get("SOCKSPort");
+ ps.setSelector("socks", new FixedSocksSelector(proxyHost, proxyPort));
+ Logger.log(getClass(), LogLevel.TRACE, "OSX socks proxy is {0}:{1}", proxyHost, proxyPort);
+ }
+ }
+
+ /*************************************************************************
+ * Installs a proxy selector for the given protocoll on the ProtocolDispatchSelector
+ * @param proxySettings to read the config for the procotol from.
+ * @param ps the ProtocolDispatchSelector to install the new selector on.
+ * @param protocol to use.
+ ************************************************************************/
+
+ private void installSelectorForProtocol(Dict proxySettings,
+ ProtocolDispatchSelector ps, String protocol) {
+ String prefix = protocol.trim();
+ if (isActive(proxySettings.get(prefix+"Enable"))) {
+ String proxyHost = (String) proxySettings.get(prefix+"Proxy");
+ int proxyPort = (Integer) proxySettings.get(prefix+"Port");
+ FixedProxySelector fp = new FixedProxySelector(proxyHost, proxyPort);
+ ps.setSelector(protocol.toLowerCase(), fp);
+ Logger.log(getClass(), LogLevel.TRACE, "OSX uses for {0} the proxy {1}:{2}", protocol, proxyHost, proxyPort);
+ }
+ }
+
+ /*************************************************************************
+ * Checks if the given value is set to "on".
+ * @param value the value to test.
+ * @return true if it is set else false.
+ ************************************************************************/
+
+ private boolean isActive(Object value) {
+ return Integer.valueOf(1).equals(value);
+ }
+
+}
diff --git a/src/main/java/com/btr/proxy/search/desktop/win/DLLManager.java b/src/main/java/com/btr/proxy/search/desktop/win/DLLManager.java
new file mode 100644
index 0000000..8d67984
--- /dev/null
+++ b/src/main/java/com/btr/proxy/search/desktop/win/DLLManager.java
@@ -0,0 +1,171 @@
+package com.btr.proxy.search.desktop.win;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import com.btr.proxy.util.Logger;
+import com.btr.proxy.util.Logger.LogLevel;
+
+/*****************************************************************************
+ * This class provides some helper methods to work with the dll
+ * extracting /loading for windows.
+ *
+ * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009
+ ****************************************************************************/
+
+final class DLLManager {
+
+ private static final class TempDLLFileFilter implements FileFilter {
+ public boolean accept(File pathname) {
+ String name = pathname.getName();
+ return pathname.isFile() &&
+ name.startsWith(TEMP_FILE_PREFIX) &&
+ name.endsWith(DLL_EXTENSION);
+ }
+ }
+
+ public static final String LIB_DIR_OVERRIDE = "proxy_vole_lib_dir";
+
+ static final String TEMP_FILE_PREFIX = "proxy_vole";
+ static final String DLL_EXTENSION = ".dll";
+ static String LIB_NAME_BASE = "proxy_util_";
+ static final String DEFAULT_LIB_FOLDER = "lib";
+
+ /*************************************************************************
+ * Find the location of the native code dll file.
+ * @return the File pointing to the dll.
+ * @throws IOException on IO error.
+ ************************************************************************/
+
+ static File findLibFile() throws IOException {
+ String libName = buildLibName();
+ File libFile = getOverrideLibFile(libName);
+ if (libFile == null || libFile.exists() == false) {
+ libFile = getDefaultLibFile(libName);
+ }
+ if (libFile == null || libFile.exists() == false) {
+ libFile = extractToTempFile(libName);
+ }
+ return libFile;
+ }
+
+ /*************************************************************************
+ * Delete old temp files that may be there because they were extracted
+ * from the jar but could not be deleted on VM shutdown because they
+ * are still locked by windows.
+ * This is here to prevent a lot of temp dll files on disk.
+ ************************************************************************/
+
+ static void cleanupTempFiles() {
+ try {
+ String tempFolder = System.getProperty("java.io.tmpdir");
+ if (tempFolder == null || tempFolder.trim().length() == 0) {
+ return;
+ }
+ File fldr = new File(tempFolder);
+ File[] oldFiles = fldr.listFiles(new TempDLLFileFilter());
+ if (oldFiles == null) {
+ return;
+ }
+ for (File tmp : oldFiles) {
+ tmp.delete();
+ }
+ } catch (Exception e) {
+ Logger.log(DLLManager.class, LogLevel.DEBUG, "Error cleaning up temporary dll files. ", e);
+ }
+ }
+
+ /*************************************************************************
+ * @param libName
+ * @return
+ ************************************************************************/
+
+ private static File getDefaultLibFile(String libName) {
+ return new File(DEFAULT_LIB_FOLDER, libName);
+ }
+
+ /*************************************************************************
+ * Gets the file name that was overriden via system property.
+ * @param libName
+ * @return the file, null if it is not existing.
+ ************************************************************************/
+
+ private static File getOverrideLibFile(String libName) {
+ String libDir = System.getProperty(LIB_DIR_OVERRIDE);
+ if (libDir == null || libDir.trim().length() == 0) {
+ return null;
+ }
+ return new File(libDir, libName);
+ }
+
+ /*************************************************************************
+ * @param libName
+ * @return
+ * @throws IOException
+ * @throws FileNotFoundException
+ ************************************************************************/
+
+ static File extractToTempFile(String libName) throws IOException {
+ InputStream source = Win32ProxyUtils.class.getResourceAsStream("/"+DEFAULT_LIB_FOLDER+"/"+libName);
+ File tempFile = File.createTempFile(TEMP_FILE_PREFIX, DLL_EXTENSION);
+ tempFile.deleteOnExit();
+ FileOutputStream destination = new FileOutputStream(tempFile);
+ copy(source, destination);
+ return tempFile;
+ }
+
+ /*************************************************************************
+ * @param c a closeable to cleanup ignoring all errors.
+ ************************************************************************/
+
+ private static void closeStream(Closeable c) {
+ try {
+ c.close();
+ } catch (IOException e) {
+ // Ignore cleanup errors
+ }
+ }
+
+ /*************************************************************************
+ * Copies the content from source to destination.
+ * @param source
+ * @param dest
+ * @throws IOException
+ ************************************************************************/
+
+ static void copy(InputStream source, OutputStream dest)
+ throws IOException {
+ try {
+ byte[] buffer = new byte[1024];
+ int read = 0;
+ while (read >= 0) {
+ dest.write(buffer, 0, read);
+ read = source.read(buffer);
+ }
+ dest.flush();
+ } finally {
+ closeStream(source);
+ closeStream(dest);
+ }
+ }
+
+ /*************************************************************************
+ * @return the name of the dll valid for the current architecture.
+ ************************************************************************/
+
+ private static String buildLibName() {
+ String arch = "w32";
+ if(!System.getProperty("os.arch").equals("x86") ) {
+ arch = System.getProperty("os.arch");
+ }
+ return LIB_NAME_BASE + arch + DLL_EXTENSION;
+ }
+
+}
+
diff --git a/src/main/java/com/btr/proxy/search/desktop/win/Win32IESettings.java b/src/main/java/com/btr/proxy/search/desktop/win/Win32IESettings.java
new file mode 100644
index 0000000..ef91a22
--- /dev/null
+++ b/src/main/java/com/btr/proxy/search/desktop/win/Win32IESettings.java
@@ -0,0 +1,68 @@
+package com.btr.proxy.search.desktop.win;
+
+/*****************************************************************************
+ * Proxy settings container used for the native methods.
+ * Will contain the Internet Explorer proxy settings as reported by windows
+ * WinHTTP API.
+ *
+ * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009
+ ****************************************************************************/
+
+public class Win32IESettings {
+
+ private boolean autoDetect;
+ private String autoConfigUrl;
+ private String proxy;
+ private String proxyBypass;
+
+ /*************************************************************************
+ * Constructor
+ * @param autoDetect flag is autodetect is active or not.
+ * @param autoConfigUrl the URL for a PAC script
+ * @param proxy the proxy server selected
+ * @param proxyBypass the proxy bypass address list.
+ ************************************************************************/
+
+ public Win32IESettings(boolean autoDetect, String autoConfigUrl, String proxy, String proxyBypass) {
+ super();
+ this.autoDetect = autoDetect;
+ this.autoConfigUrl = autoConfigUrl;
+ this.proxy = proxy;
+ this.proxyBypass = proxyBypass;
+ }
+
+ /*************************************************************************
+ * @return Returns the autoDetect.
+ ************************************************************************/
+
+ public boolean isAutoDetect() {
+ return this.autoDetect;
+ }
+
+ /*************************************************************************
+ * @return Returns the autoConfigUrl.
+ ************************************************************************/
+
+ public String getAutoConfigUrl() {
+ return this.autoConfigUrl;
+ }
+
+ /*************************************************************************
+ * @return Returns the proxy.
+ ************************************************************************/
+
+ public String getProxy() {
+ return this.proxy;
+ }
+
+ /*************************************************************************
+ * @return Returns the proxyBypass.
+ ************************************************************************/
+
+ public String getProxyBypass() {
+ return this.proxyBypass;
+ }
+
+
+}
+
diff --git a/src/main/java/com/btr/proxy/search/desktop/win/Win32ProxyUtils.java b/src/main/java/com/btr/proxy/search/desktop/win/Win32ProxyUtils.java
new file mode 100644
index 0000000..fb1f0b3
--- /dev/null
+++ b/src/main/java/com/btr/proxy/search/desktop/win/Win32ProxyUtils.java
@@ -0,0 +1,88 @@
+package com.btr.proxy.search.desktop.win;
+
+import java.io.File;
+import java.io.IOException;
+
+/*****************************************************************************
+ * Defines the native methods used for windows to extract some system information.
+ * <p>
+ * This class will need some native code from the library proxy_util_"arch".dll.
+ * To load this library we use a three step algorithm as following:
+ * </p><P>
+ * First check the System property "proxy_vole_lib_dir" if it is set and
+ * it points to a folder where the dll is found than the dll from this
+ * folder is loaded as e.g. <i>"proxy_vole_lib_dir"/proxy_util_w32.dll</i>
+ * </p><p>
+ * Second we try to load the dll from the subfolder <i>lib</i> if that one exists.<br>
+ * Finally if we are inside of a jar file we need to extract the dll file
+ * to a temp-file because windows can not load dlls from a jar
+ * directly. This is a hack but it may work.
+ * </p><p>
+ * Please note that the file is named Win32ProxyUtils but has now also support
+ * for x64 architecture.
+ * </p>
+ * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009
+ ****************************************************************************/
+
+public class Win32ProxyUtils {
+
+ public static final int WINHTTP_AUTO_DETECT_TYPE_DHCP = 0x00000001;
+ public static final int WINHTTP_AUTO_DETECT_TYPE_DNS_A = 0x00000002;
+
+
+ // Code for loading the windows native dll
+ static {
+ try {
+ File libFile = DLLManager.findLibFile();
+ System.load(libFile.getAbsolutePath());
+ DLLManager.cleanupTempFiles();
+ } catch (IOException e) {
+ throw new RuntimeException("Error loading dll"+e.getMessage(), e);
+ }
+ }
+
+ /*************************************************************************
+ * Constructor
+ ************************************************************************/
+
+ public Win32ProxyUtils() {
+ super();
+ }
+
+ /*************************************************************************
+ * WinHTTP method to detect an PAC URL.
+ * @param mode the mode to use.
+ * @return the PAC URL, null if none was found.
+ ************************************************************************/
+
+ public native String winHttpDetectAutoProxyConfigUrl(int mode);
+
+ /*************************************************************************
+ * Gets the default windows proxy settings.
+ * The returned string will have the following format.
+ * TYPE PROXY | BYPASSLIST
+ * <p>
+ * e.g. DIRECT myproxy.mycompany.com:8080 | *.mycompany.com, localhost
+ * </p>
+ * @return a string containing all info, null if not found.
+ ************************************************************************/
+ // TODO Not implemented correctly in DLL yet.
+ native String winHttpGetDefaultProxyConfiguration();
+
+ /*************************************************************************
+ * Extracts the Internet Explorer proxy settings from the Windows system.
+ * @return a data structure containing all details, null on fail.
+ ************************************************************************/
+
+ public native Win32IESettings winHttpGetIEProxyConfigForCurrentUser();
+
+ /*************************************************************************
+ * Extracts the Internet Explorer proxy settings from the Windows system.
+ * @return a data structure containing all details, null on fail.
+ ************************************************************************/
+
+ public native String readUserHomedir();
+
+
+}
+
diff --git a/src/main/java/com/btr/proxy/search/desktop/win/WinProxySearchStrategy.java b/src/main/java/com/btr/proxy/search/desktop/win/WinProxySearchStrategy.java
new file mode 100644
index 0000000..1f26505
--- /dev/null
+++ b/src/main/java/com/btr/proxy/search/desktop/win/WinProxySearchStrategy.java
@@ -0,0 +1,52 @@
+package com.btr.proxy.search.desktop.win;
+
+import java.net.ProxySelector;
+
+import com.btr.proxy.search.ProxySearchStrategy;
+import com.btr.proxy.search.browser.ie.IEProxySearchStrategy;
+import com.btr.proxy.util.ProxyException;
+
+/*****************************************************************************
+ * Extracts the proxy settings from the windows registry.
+ * This will read the windows system proxy settings.
+ *
+ * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009
+ ****************************************************************************/
+
+public class WinProxySearchStrategy implements ProxySearchStrategy {
+
+ /*************************************************************************
+ * Constructor
+ ************************************************************************/
+
+ public WinProxySearchStrategy() {
+ super();
+ }
+
+ /*************************************************************************
+ * getProxySelector
+ * @see com.btr.proxy.search.ProxySearchStrategy#getProxySelector()
+ ************************************************************************/
+
+ public ProxySelector getProxySelector() throws ProxyException {
+ // TODO Rossi 08.05.2009 Implement this by using Win API calls.
+ // new Win32ProxyUtils().winHttpGetDefaultProxyConfiguration()
+ // Current fallback is to use the IE settings. This is better
+ // because the registry settings are most of the time not set.
+ // Some Windows server installations may use it though.
+ return new IEProxySearchStrategy().getProxySelector();
+ }
+
+ /*************************************************************************
+ * Loads the settings.
+ * @return a WinIESettings object containing all proxy settings.
+ ************************************************************************/
+
+ public Win32IESettings readSettings() {
+ return new IEProxySearchStrategy().readSettings();
+ }
+
+
+
+
+}