summaryrefslogtreecommitdiffstats
path: root/src/main/java/com/btr/proxy/search/desktop/gnome/GnomeProxySearchStrategy.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/btr/proxy/search/desktop/gnome/GnomeProxySearchStrategy.java')
-rw-r--r--src/main/java/com/btr/proxy/search/desktop/gnome/GnomeProxySearchStrategy.java353
1 files changed, 353 insertions, 0 deletions
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;
+ }
+
+}