blob: c430217d621cb2650b97f843245d0727a84e0a27 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2018 Oakland Software Incorporated and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Oakland Software Incorporated - initial API and implementation
* IBM Corporation - implementation
* Red Hat - GSettings implementation and code clean up (bug 394087)
*******************************************************************************/
package org.eclipse.core.internal.net.proxy.unix;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Objects;
import java.util.Properties;
import org.eclipse.core.internal.net.AbstractProxyProvider;
import org.eclipse.core.internal.net.Activator;
import org.eclipse.core.internal.net.Policy;
import org.eclipse.core.internal.net.ProxyData;
import org.eclipse.core.internal.net.StringUtil;
import org.eclipse.core.net.proxy.IProxyData;
public class UnixProxyProvider extends AbstractProxyProvider {
private static final String LIBRARY_NAME = "gnomeproxy-1.0.0"; //$NON-NLS-1$
private static final String ENABLE_GNOME = Activator.ID + ".enableGnome"; //$NON-NLS-1$
private static boolean isGnomeLibLoaded = false;
static {
// Load the GSettings JNI library if org.eclipse.core.net.enableGnome is specified
String value = System.getProperty(ENABLE_GNOME);
if ("".equals(value) || "true".equals(value)) { //$NON-NLS-1$ //$NON-NLS-2$
loadGnomeLib();
}
}
public UnixProxyProvider() {
// Nothing to initialize
}
@Override
public IProxyData[] select(URI uri) {
String[] nonProxyHosts = getNonProxiedHosts();
if (nonProxyHosts != null) {
String host = uri.getHost();
for (int npIndex = 0; npIndex < nonProxyHosts.length; npIndex++) {
if (StringUtil.hostMatchesFilter(host, nonProxyHosts[npIndex])) {
return new IProxyData[0];
}
}
}
IProxyData[] proxies = new IProxyData[0];
if (uri.getScheme() != null) {
ProxyData pd = getSystemProxyInfo(uri.getScheme());
proxies = pd != null ? new IProxyData[] { pd } : new IProxyData[0];
} else {
proxies = getProxyData();
}
if (Policy.DEBUG) {
Policy.debug("UnixProxyProvider#select result for [" + uri + "]"); //$NON-NLS-1$ //$NON-NLS-2$
for (int i = 0; i < proxies.length; i++)
System.out.println(" " + proxies[i]); //$NON-NLS-1$
}
return proxies;
}
@Override
public IProxyData[] getProxyData() {
String[] commonTypes = new String[] { IProxyData.HTTP_PROXY_TYPE,
IProxyData.SOCKS_PROXY_TYPE, IProxyData.HTTPS_PROXY_TYPE };
return getProxyForTypes(commonTypes);
}
private IProxyData[] getProxyForTypes(String[] types) {
ArrayList<IProxyData> allData = new ArrayList<>();
for (int i = 0; i < types.length; i++) {
String type = types[i];
ProxyData pd = getSystemProxyInfo(type);
if (pd != null && pd.getHost() != null) {
allData.add(pd);
}
}
return allData.toArray(new IProxyData[0]);
}
@Override
public String[] getNonProxiedHosts() {
String[] npHosts;
if (Policy.DEBUG_SYSTEM_PROVIDERS)
Policy.debug("Getting no_proxy"); //$NON-NLS-1$
// First try the environment variable which is a URL
String npEnv = getEnv("no_proxy"); //$NON-NLS-1$
if (npEnv != null) {
npHosts = StringUtil.split(npEnv, new String[] { "," }); //$NON-NLS-1$
for (int i = 0; i < npHosts.length; i++)
npHosts[i] = npHosts[i].trim();
if (Policy.DEBUG_SYSTEM_PROVIDERS) {
Policy.debug("Got Env no_proxy: " + npEnv); //$NON-NLS-1$
debugPrint(npHosts);
}
return npHosts;
}
if (isGnomeLibLoaded) {
try {
npHosts = getGSettingsNonProxyHosts();
if (npHosts != null && npHosts.length > 0) {
if (Policy.DEBUG_SYSTEM_PROVIDERS) {
Policy.debug("Got Gnome no_proxy"); //$NON-NLS-1$
debugPrint(npHosts);
}
return npHosts;
}
} catch (UnsatisfiedLinkError e) {
// The library should be loaded, so this is a real exception
Activator.logError(
"Problem during accessing Gnome library", e); //$NON-NLS-1$
}
}
return new String[0];
}
// Returns null if something wrong or there is no proxy for the protocol
protected ProxyData getSystemProxyInfo(String protocol) {
ProxyData pd = null;
String envName = null;
if (Policy.DEBUG_SYSTEM_PROVIDERS)
Policy.debug("Getting proxies for: " + protocol); //$NON-NLS-1$
try {
// protocol schemes are ISO 8859 (ASCII)
protocol = protocol.toLowerCase(Locale.ENGLISH);
// First try the environment variable which is a URL
envName = protocol + "_proxy"; //$NON-NLS-1$
String proxyEnv = getEnv(envName);
if (Policy.DEBUG_SYSTEM_PROVIDERS)
Policy.debug("Got proxyEnv: " + proxyEnv); //$NON-NLS-1$
if (proxyEnv != null) {
int colonInd = proxyEnv.indexOf(":"); //$NON-NLS-1$
if (colonInd !=-1 && proxyEnv.length() > colonInd + 2 && !"//".equals(proxyEnv.substring(colonInd + 1, colonInd + 3))) { //$NON-NLS-1$
proxyEnv = "http://" + proxyEnv; //$NON-NLS-1$
}
URI uri = new URI(proxyEnv);
pd = new ProxyData(protocol);
pd.setHost(Objects.requireNonNull(uri.getHost(), "no host in " + proxyEnv)); //$NON-NLS-1$
int port = uri.getPort();
if (port == -1) {
throw new IllegalStateException("no port in " + proxyEnv); //$NON-NLS-1$
}
pd.setPort(port);
String userInfo = uri.getUserInfo();
if (userInfo != null) {
String user = null;
String password = null;
int pwInd = userInfo.indexOf(':');
if (pwInd >= 0) {
user = userInfo.substring(0, pwInd);
password = userInfo.substring(pwInd + 1);
} else {
user = userInfo;
}
pd.setUserid(user);
pd.setPassword(password);
}
pd.setSource("LINUX_ENV"); //$NON-NLS-1$
if (Policy.DEBUG_SYSTEM_PROVIDERS)
Policy.debug("Got Env proxy: " + pd); //$NON-NLS-1$
return pd;
}
} catch (Exception e) {
Activator.logError(
"Problem during accessing system variable: " + envName, e); //$NON-NLS-1$
}
if (isGnomeLibLoaded) {
try {
// Then ask Gnome
pd = getGSettingsProxyInfo(protocol);
if (pd != null) {
if (Policy.DEBUG_SYSTEM_PROVIDERS)
Policy.debug("Got Gnome proxy: " + pd); //$NON-NLS-1$
pd.setSource("LINUX_GNOME"); //$NON-NLS-1$
return pd;
}
} catch (UnsatisfiedLinkError e) {
// The library should be loaded, so this is a real exception
Activator.logError(
"Problem during accessing Gnome library", e); //$NON-NLS-1$
}
}
return null;
}
private static String getEnv(String env) {
try {
Method m = System.class.getMethod(
"getenv", new Class[] { String.class }); //$NON-NLS-1$
return (String) m.invoke(null, new Object[] { env });
} catch (Throwable t) {
// Fall-back to running 'env' directly. Warning this is very slow...
// up to 200ms
String cmd[] = { "/bin/sh", //$NON-NLS-1$
"-c", //$NON-NLS-1$
"env | grep -i proxy" }; //$NON-NLS-1$
Properties props = new Properties();
Process proc = null;
try {
proc = Runtime.getRuntime().exec(cmd);
props.load(proc.getInputStream());
} catch (IOException e) {
Activator.logError(
"Problem during accessing system variable: " + env, e); //$NON-NLS-1$
} catch (IllegalArgumentException e) {
Activator.logError(
"Problem during accessing system variable: " + env, e); //$NON-NLS-1$
} finally {
if (proc != null) {
proc.destroy();
}
}
return props.getProperty(env);
}
}
private static void loadGnomeLib() {
try {
System.loadLibrary(LIBRARY_NAME);
isGnomeLibLoaded = true;
if (Policy.DEBUG_SYSTEM_PROVIDERS)
Policy.debug("Loaded " + //$NON-NLS-1$
System.mapLibraryName(LIBRARY_NAME) + " library"); //$NON-NLS-1$
} catch (final UnsatisfiedLinkError e) {
// Expected on systems that are missing Gnome library
if (Policy.DEBUG_SYSTEM_PROVIDERS)
Policy.debug("Could not load library: " //$NON-NLS-1$
+ System.mapLibraryName(LIBRARY_NAME));
}
}
private void debugPrint(String[] strs) {
for (int i = 0; i < strs.length; i++)
System.out.println(i + ": " + strs[i]); //$NON-NLS-1$
}
protected static native void gsettingsInit();
protected static native ProxyData getGSettingsProxyInfo(String protocol);
protected static native String[] getGSettingsNonProxyHosts();
}