com.github.markusbernhardt.proxy.search.desktop.gnome.GnomeProxySearchStrategy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of proxy-vole Show documentation
Show all versions of proxy-vole Show documentation
Proxy Vole is a Java library to auto detect the platform network proxy settings.
package com.github.markusbernhardt.proxy.search.desktop.gnome;
import java.io.File;
import java.io.IOException;
import java.net.ProxySelector;
import java.util.Properties;
import javax.xml.XMLConstants;
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.github.markusbernhardt.proxy.ProxySearchStrategy;
import com.github.markusbernhardt.proxy.selector.direct.NoProxySelector;
import com.github.markusbernhardt.proxy.selector.fixed.FixedProxySelector;
import com.github.markusbernhardt.proxy.selector.misc.ProtocolDispatchSelector;
import com.github.markusbernhardt.proxy.selector.whitelist.ProxyBypassListSelector;
import com.github.markusbernhardt.proxy.util.EmptyXMLResolver;
import com.github.markusbernhardt.proxy.util.Logger;
import com.github.markusbernhardt.proxy.util.Logger.LogLevel;
import com.github.markusbernhardt.proxy.util.PlatformUtil;
import com.github.markusbernhardt.proxy.util.ProxyException;
import com.github.markusbernhardt.proxy.util.ProxyUtil;
/*****************************************************************************
* Loads the Gnome proxy settings from the Gnome GConf settings.
*
* The following settings are extracted from the configuration that is stored in
* .gconf folder found in the user's home directory:
*
*
* - /system/http_proxy/use_http_proxy -> bool used only by
* gnome-vfs
* - /system/http_proxy/host -> string "my-proxy.example.com"
* without "http://"
* - /system/http_proxy/port -> int
* - /system/http_proxy/use_authentication -> bool
* - /system/http_proxy/authentication_user -> string
* - /system/http_proxy/authentication_password -> string
* - /system/http_proxy/ignore_hosts -> list-of-string
* - /system/proxy/mode -> string THIS IS THE CANONICAL KEY; SEE
* BELOW
* - /system/proxy/secure_host -> string
* "proxy-for-https.example.com"
* - /system/proxy/secure_port -> int
* - /system/proxy/ftp_host -> string "proxy-for-ftp.example.com"
*
* - /system/proxy/ftp_port -> int
* - /system/proxy/socks_host -> string
* "proxy-for-socks.example.com"
* - /system/proxy/socks_port -> int
* - /system/proxy/autoconfig_url -> string
* "http://proxy-autoconfig.example.com"
*
* /system/proxy/mode can be either:
* "none" -> No proxy is used
* "manual" -> The user's configuration values are used
* (/system/http_proxy/{host,port,etc.})
* "auto" -> The "/system/proxy/autoconfig_url" key is used
*
* GNOME Proxy_configuration settings are explained
* here in detail
*
*
* @author Markus Bernhardt, Copyright 2016
* @author Bernd Rosstauscher, 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.
************************************************************************/
@Override
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 {}", 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: {}", noProxyList);
result = new ProxyBypassListSelector(noProxyList, result);
}
return result;
}
/*************************************************************************
* Gets the printable name of the search strategy.
*
* @return the printable name of the search strategy
************************************************************************/
@Override
public String getName() {
return "gnome";
}
/*************************************************************************
* 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//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(PlatformUtil.getUserHomeDir());
// 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: {} 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 {}:{}", 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 {}:{}", 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 {}:{}", 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 {}:{}", proxyHost, proxyPort);
ps.setSelector("https", new FixedProxySelector(proxyHost.trim(), proxyPort));
ps.setSelector("sftp", new FixedProxySelector(proxyHost.trim(), proxyPort));
ps.setSelector("wss", 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 {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
if(Boolean.getBoolean( PlatformUtil.XML_FEATURE_SECURE_PROCESSING ))
{
documentBuilderFactory.setFeature( XMLConstants.FEATURE_SECURE_PROCESSING, true );
}
else
{
documentBuilderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
documentBuilderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
}
DocumentBuilder documentBuilder = documentBuilderFactory.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;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy