19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.net;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwaltimport android.annotation.SdkConstant;
20434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwaltimport android.annotation.SdkConstant.SdkConstantType;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
22d192dad69e9e5a820c5c11d8cd34460c9cc2ed11Robert Greenwaltimport android.text.TextUtils;
23d192dad69e9e5a820c5c11d8cd34460c9cc2ed11Robert Greenwaltimport android.util.Log;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2516fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayorimport java.net.InetSocketAddress;
26d192dad69e9e5a820c5c11d8cd34460c9cc2ed11Robert Greenwaltimport java.net.ProxySelector;
272986f858ae6c6cc8a84614083661d1a2e2108aeeAndreas Sandbladimport java.net.URI;
282b4378fef8906b385ee173ebdff9a91d205c7c36Narayan Kamathimport java.util.List;
2916fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayorimport java.util.regex.Matcher;
3016fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayorimport java.util.regex.Pattern;
312986f858ae6c6cc8a84614083661d1a2e2108aeeAndreas Sandblad
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A convenience class for accessing the user and default proxy
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * settings.
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
3616fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayorpublic final class Proxy {
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
38434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt    private static final String TAG = "Proxy";
39fb8390729192860066c081b11b2f58db4cba9924Dave Bort
40602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk    private static final ProxySelector sDefaultProxySelector;
41602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk
42434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt    /**
43ad8234213d24975ce8262b810d93af77a231bb5ePaul Jensen     * Used to notify an app that's caching the proxy that either the default
44ad8234213d24975ce8262b810d93af77a231bb5ePaul Jensen     * connection has changed or any connection's proxy has changed. The new
45ad8234213d24975ce8262b810d93af77a231bb5ePaul Jensen     * proxy should be queried using {@link ConnectivityManager#getDefaultProxy()}.
46434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt     *
47434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt     * <p class="note">This is a protected intent that can only be sent by the system
48434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt     */
49434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
50434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt    public static final String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE";
51207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk    /**
52207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk     * Intent extra included with {@link #PROXY_CHANGE_ACTION} intents.
53207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk     * It describes the new proxy being used (as a {@link ProxyInfo} object).
54ad8234213d24975ce8262b810d93af77a231bb5ePaul Jensen     * @deprecated Because {@code PROXY_CHANGE_ACTION} is sent whenever the proxy
55ad8234213d24975ce8262b810d93af77a231bb5ePaul Jensen     * for any network on the system changes, applications should always use
56ad8234213d24975ce8262b810d93af77a231bb5ePaul Jensen     * {@link ConnectivityManager#getDefaultProxy()} or
57ad8234213d24975ce8262b810d93af77a231bb5ePaul Jensen     * {@link ConnectivityManager#getLinkProperties(Network)}.{@link LinkProperties#getHttpProxy()}
58ad8234213d24975ce8262b810d93af77a231bb5ePaul Jensen     * to get the proxy for the Network(s) they are using.
59207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk     */
60514c5ef8d5774d8820ed1bf90fe53af1606cf106Aurimas Liutikas    @Deprecated
61207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk    public static final String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO";
6216fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor
639070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng    /** @hide */
649070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng    public static final int PROXY_VALID             = 0;
659070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng    /** @hide */
669070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng    public static final int PROXY_HOSTNAME_EMPTY    = 1;
679070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng    /** @hide */
689070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng    public static final int PROXY_HOSTNAME_INVALID  = 2;
699070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng    /** @hide */
709070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng    public static final int PROXY_PORT_EMPTY        = 3;
719070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng    /** @hide */
729070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng    public static final int PROXY_PORT_INVALID      = 4;
739070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng    /** @hide */
749070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng    public static final int PROXY_EXCLLIST_INVALID  = 5;
759070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng
76d192dad69e9e5a820c5c11d8cd34460c9cc2ed11Robert Greenwalt    private static ConnectivityManager sConnectivityManager = null;
77d192dad69e9e5a820c5c11d8cd34460c9cc2ed11Robert Greenwalt
7816fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor    // Hostname / IP REGEX validation
7916fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor    // Matches blank input, ips, and domain names
8016fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor    private static final String NAME_IP_REGEX =
8116fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor        "[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*";
8216fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor
8316fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor    private static final String HOSTNAME_REGEXP = "^$|^" + NAME_IP_REGEX + "$";
8416fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor
8516fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor    private static final Pattern HOSTNAME_PATTERN;
8616fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor
873dce5af6abc9c8d41d24d9499410b33ec76b1f08Yuhao Zheng    private static final String EXCL_REGEX =
883dce5af6abc9c8d41d24d9499410b33ec76b1f08Yuhao Zheng        "[a-zA-Z0-9*]+(\\-[a-zA-Z0-9*]+)*(\\.[a-zA-Z0-9*]+(\\-[a-zA-Z0-9*]+)*)*";
893dce5af6abc9c8d41d24d9499410b33ec76b1f08Yuhao Zheng
903dce5af6abc9c8d41d24d9499410b33ec76b1f08Yuhao Zheng    private static final String EXCLLIST_REGEXP = "^$|^" + EXCL_REGEX + "(," + EXCL_REGEX + ")*$";
9116fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor
9216fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor    private static final Pattern EXCLLIST_PATTERN;
9316fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor
9416fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor    static {
9516fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor        HOSTNAME_PATTERN = Pattern.compile(HOSTNAME_REGEXP);
9616fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor        EXCLLIST_PATTERN = Pattern.compile(EXCLLIST_REGEXP);
97602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        sDefaultProxySelector = ProxySelector.getDefault();
9816fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor    }
9916fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor
10016fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor    /**
10116fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor     * Return the proxy object to be used for the URL given as parameter.
10216fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor     * @param ctx A Context used to get the settings for the proxy host.
10316fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor     * @param url A URL to be accessed. Used to evaluate exclusion list.
10416fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor     * @return Proxy (java.net) object containing the host name. If the
10516fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor     *         user did not set a hostname it returns the default host.
10616fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor     *         A null value means that no host is to be used.
10716fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor     * {@hide}
10816fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor     */
10916fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor    public static final java.net.Proxy getProxy(Context ctx, String url) {
110434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        String host = "";
111207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk        if ((url != null) && !isLocalHost(host)) {
112434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt            URI uri = URI.create(url);
113207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk            ProxySelector proxySelector = ProxySelector.getDefault();
114434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt
115207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk            List<java.net.Proxy> proxyList = proxySelector.select(uri);
116434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt
117207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk            if (proxyList.size() > 0) {
118207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk                return proxyList.get(0);
11916fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor            }
1206f71b42bc4531618e2b050bdf9ad05a72ac2a565Oscar Montemayor        }
121434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        return java.net.Proxy.NO_PROXY;
12216fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor    }
12316fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor
124434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the proxy host set by the user.
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param ctx A Context used to get the settings for the proxy host.
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return String containing the host name. If the user did not set a host
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         name it returns the default host. A null value means that no
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         host is to be used.
131778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt     * @deprecated Use standard java vm proxy values to find the host, port
132778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt     *         and exclusion list.  This call ignores the exclusion list.
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
134514c5ef8d5774d8820ed1bf90fe53af1606cf106Aurimas Liutikas    @Deprecated
13516fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor    public static final String getHost(Context ctx) {
136d192dad69e9e5a820c5c11d8cd34460c9cc2ed11Robert Greenwalt        java.net.Proxy proxy = getProxy(ctx, null);
137d192dad69e9e5a820c5c11d8cd34460c9cc2ed11Robert Greenwalt        if (proxy == java.net.Proxy.NO_PROXY) return null;
13816fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor        try {
139d192dad69e9e5a820c5c11d8cd34460c9cc2ed11Robert Greenwalt            return ((InetSocketAddress)(proxy.address())).getHostName();
140d192dad69e9e5a820c5c11d8cd34460c9cc2ed11Robert Greenwalt        } catch (Exception e) {
141d192dad69e9e5a820c5c11d8cd34460c9cc2ed11Robert Greenwalt            return null;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the proxy port set by the user.
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param ctx A Context used to get the settings for the proxy port.
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The port number to use or -1 if no proxy is to be used.
149778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt     * @deprecated Use standard java vm proxy values to find the host, port
150778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt     *         and exclusion list.  This call ignores the exclusion list.
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
152514c5ef8d5774d8820ed1bf90fe53af1606cf106Aurimas Liutikas    @Deprecated
15316fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor    public static final int getPort(Context ctx) {
154d192dad69e9e5a820c5c11d8cd34460c9cc2ed11Robert Greenwalt        java.net.Proxy proxy = getProxy(ctx, null);
155d192dad69e9e5a820c5c11d8cd34460c9cc2ed11Robert Greenwalt        if (proxy == java.net.Proxy.NO_PROXY) return -1;
15616fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor        try {
157d192dad69e9e5a820c5c11d8cd34460c9cc2ed11Robert Greenwalt            return ((InetSocketAddress)(proxy.address())).getPort();
158d192dad69e9e5a820c5c11d8cd34460c9cc2ed11Robert Greenwalt        } catch (Exception e) {
159d192dad69e9e5a820c5c11d8cd34460c9cc2ed11Robert Greenwalt            return -1;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the default proxy host specified by the carrier.
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return String containing the host name or null if there is no proxy for
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this carrier.
167778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt     * @deprecated Use standard java vm proxy values to find the host, port and
168778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt     *         exclusion list.  This call ignores the exclusion list and no
169778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt     *         longer reports only mobile-data apn-based proxy values.
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
171514c5ef8d5774d8820ed1bf90fe53af1606cf106Aurimas Liutikas    @Deprecated
17216fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor    public static final String getDefaultHost() {
173778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt        String host = System.getProperty("http.proxyHost");
174778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt        if (TextUtils.isEmpty(host)) return null;
175778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt        return host;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the default proxy port specified by the carrier.
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The port number to be used with the proxy host or -1 if there is
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * no proxy for this carrier.
182778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt     * @deprecated Use standard java vm proxy values to find the host, port and
183778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt     *         exclusion list.  This call ignores the exclusion list and no
184778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt     *         longer reports only mobile-data apn-based proxy values.
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
186514c5ef8d5774d8820ed1bf90fe53af1606cf106Aurimas Liutikas    @Deprecated
18716fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor    public static final int getDefaultPort() {
188778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt        if (getDefaultHost() == null) return -1;
189778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt        try {
190778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt            return Integer.parseInt(System.getProperty("http.proxyPort"));
191778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt        } catch (NumberFormatException e) {
192778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt            return -1;
193778c0ba8586a4494ed617c2d3cb3692311df1086Robert Greenwalt        }
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
196434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt    private static final boolean isLocalHost(String host) {
197434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        if (host == null) {
1982986f858ae6c6cc8a84614083661d1a2e2108aeeAndreas Sandblad            return false;
1992986f858ae6c6cc8a84614083661d1a2e2108aeeAndreas Sandblad        }
2002986f858ae6c6cc8a84614083661d1a2e2108aeeAndreas Sandblad        try {
2012986f858ae6c6cc8a84614083661d1a2e2108aeeAndreas Sandblad            if (host != null) {
2026b7af6055f25022361beb2c169d2c1835922dc32Elliott Hughes                if (host.equalsIgnoreCase("localhost")) {
2032986f858ae6c6cc8a84614083661d1a2e2108aeeAndreas Sandblad                    return true;
2042986f858ae6c6cc8a84614083661d1a2e2108aeeAndreas Sandblad                }
205e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt                if (NetworkUtils.numericToInetAddress(host).isLoopbackAddress()) {
206e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt                    return true;
2076b7af6055f25022361beb2c169d2c1835922dc32Elliott Hughes                }
2082986f858ae6c6cc8a84614083661d1a2e2108aeeAndreas Sandblad            }
2092986f858ae6c6cc8a84614083661d1a2e2108aeeAndreas Sandblad        } catch (IllegalArgumentException iex) {
2102986f858ae6c6cc8a84614083661d1a2e2108aeeAndreas Sandblad        }
2112986f858ae6c6cc8a84614083661d1a2e2108aeeAndreas Sandblad        return false;
2122986f858ae6c6cc8a84614083661d1a2e2108aeeAndreas Sandblad    }
2132986f858ae6c6cc8a84614083661d1a2e2108aeeAndreas Sandblad
21416fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor    /**
21516fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor     * Validate syntax of hostname, port and exclusion list entries
21616fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor     * {@hide}
21716fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor     */
2189070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng    public static int validate(String hostname, String port, String exclList) {
21916fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor        Matcher match = HOSTNAME_PATTERN.matcher(hostname);
22016fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor        Matcher listMatch = EXCLLIST_PATTERN.matcher(exclList);
22116fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor
2229070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng        if (!match.matches()) return PROXY_HOSTNAME_INVALID;
22316fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor
2249070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng        if (!listMatch.matches()) return PROXY_EXCLLIST_INVALID;
22516fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor
2269070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng        if (hostname.length() > 0 && port.length() == 0) return PROXY_PORT_EMPTY;
22716fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor
22816fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor        if (port.length() > 0) {
2299070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng            if (hostname.length() == 0) return PROXY_HOSTNAME_EMPTY;
23016fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor            int portVal = -1;
23116fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor            try {
23216fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor                portVal = Integer.parseInt(port);
23316fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor            } catch (NumberFormatException ex) {
2349070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng                return PROXY_PORT_INVALID;
23516fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor            }
2369070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng            if (portVal <= 0 || portVal > 0xFFFF) return PROXY_PORT_INVALID;
23716fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor        }
2389070484e179b2215ea595c8f3f1f69dbc0dc149dYuhao Zheng        return PROXY_VALID;
23916fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor    }
240d192dad69e9e5a820c5c11d8cd34460c9cc2ed11Robert Greenwalt
241434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt    /** @hide */
242207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk    public static final void setHttpProxySystemProperty(ProxyInfo p) {
243434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        String host = null;
244434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        String port = null;
245434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        String exclList = null;
24683520b95124e0fcaaf3154a7a267f6be0205bc74Jason Monk        Uri pacFileUrl = Uri.EMPTY;
247434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        if (p != null) {
248434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt            host = p.getHost();
249434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt            port = Integer.toString(p.getPort());
250207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk            exclList = p.getExclusionListAsString();
25183520b95124e0fcaaf3154a7a267f6be0205bc74Jason Monk            pacFileUrl = p.getPacFileUrl();
252434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        }
253602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        setHttpProxySystemProperty(host, port, exclList, pacFileUrl);
254434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt    }
255434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt
256434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt    /** @hide */
257602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk    public static final void setHttpProxySystemProperty(String host, String port, String exclList,
25883520b95124e0fcaaf3154a7a267f6be0205bc74Jason Monk            Uri pacFileUrl) {
259434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        if (exclList != null) exclList = exclList.replace(",", "|");
260434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        if (false) Log.d(TAG, "setHttpProxySystemProperty :"+host+":"+port+" - "+exclList);
261434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        if (host != null) {
262434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt            System.setProperty("http.proxyHost", host);
263434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt            System.setProperty("https.proxyHost", host);
264434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        } else {
265434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt            System.clearProperty("http.proxyHost");
266434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt            System.clearProperty("https.proxyHost");
267434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        }
268434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        if (port != null) {
269434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt            System.setProperty("http.proxyPort", port);
270434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt            System.setProperty("https.proxyPort", port);
271434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        } else {
272434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt            System.clearProperty("http.proxyPort");
273434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt            System.clearProperty("https.proxyPort");
274434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        }
275434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        if (exclList != null) {
276434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt            System.setProperty("http.nonProxyHosts", exclList);
277434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt            System.setProperty("https.nonProxyHosts", exclList);
278434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        } else {
279434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt            System.clearProperty("http.nonProxyHosts");
280434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt            System.clearProperty("https.nonProxyHosts");
281434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        }
28283520b95124e0fcaaf3154a7a267f6be0205bc74Jason Monk        if (!Uri.EMPTY.equals(pacFileUrl)) {
2839ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            ProxySelector.setDefault(new PacProxySelector());
284602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        } else {
285602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk            ProxySelector.setDefault(sDefaultProxySelector);
286602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        }
287434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt    }
28816fb7910fd3a86780edf4e65b529542ae95c26cdOscar Montemayor}
289