| /******************************************************************************* |
| * 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(); |
| } |