Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.net;
     18 
     19 import android.annotation.SdkConstant;
     20 import android.annotation.SdkConstant.SdkConstantType;
     21 import android.content.Context;
     22 import android.text.TextUtils;
     23 import android.util.Log;
     24 
     25 import java.net.InetSocketAddress;
     26 import java.net.ProxySelector;
     27 import java.net.URI;
     28 import java.util.List;
     29 import java.util.regex.Matcher;
     30 import java.util.regex.Pattern;
     31 
     32 /**
     33  * A convenience class for accessing the user and default proxy
     34  * settings.
     35  */
     36 public final class Proxy {
     37 
     38     private static final String TAG = "Proxy";
     39 
     40     private static final ProxySelector sDefaultProxySelector;
     41 
     42     /**
     43      * Used to notify an app that's caching the proxy that either the default
     44      * connection has changed or any connection's proxy has changed. The new
     45      * proxy should be queried using {@link ConnectivityManager#getDefaultProxy()}.
     46      *
     47      * <p class="note">This is a protected intent that can only be sent by the system
     48      */
     49     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     50     public static final String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE";
     51     /**
     52      * Intent extra included with {@link #PROXY_CHANGE_ACTION} intents.
     53      * It describes the new proxy being used (as a {@link ProxyInfo} object).
     54      * @deprecated Because {@code PROXY_CHANGE_ACTION} is sent whenever the proxy
     55      * for any network on the system changes, applications should always use
     56      * {@link ConnectivityManager#getDefaultProxy()} or
     57      * {@link ConnectivityManager#getLinkProperties(Network)}.{@link LinkProperties#getHttpProxy()}
     58      * to get the proxy for the Network(s) they are using.
     59      */
     60     @Deprecated
     61     public static final String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO";
     62 
     63     /** @hide */
     64     public static final int PROXY_VALID             = 0;
     65     /** @hide */
     66     public static final int PROXY_HOSTNAME_EMPTY    = 1;
     67     /** @hide */
     68     public static final int PROXY_HOSTNAME_INVALID  = 2;
     69     /** @hide */
     70     public static final int PROXY_PORT_EMPTY        = 3;
     71     /** @hide */
     72     public static final int PROXY_PORT_INVALID      = 4;
     73     /** @hide */
     74     public static final int PROXY_EXCLLIST_INVALID  = 5;
     75 
     76     private static ConnectivityManager sConnectivityManager = null;
     77 
     78     // Hostname / IP REGEX validation
     79     // Matches blank input, ips, and domain names
     80     private static final String NAME_IP_REGEX =
     81         "[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*";
     82 
     83     private static final String HOSTNAME_REGEXP = "^$|^" + NAME_IP_REGEX + "$";
     84 
     85     private static final Pattern HOSTNAME_PATTERN;
     86 
     87     private static final String EXCL_REGEX =
     88         "[a-zA-Z0-9*]+(\\-[a-zA-Z0-9*]+)*(\\.[a-zA-Z0-9*]+(\\-[a-zA-Z0-9*]+)*)*";
     89 
     90     private static final String EXCLLIST_REGEXP = "^$|^" + EXCL_REGEX + "(," + EXCL_REGEX + ")*$";
     91 
     92     private static final Pattern EXCLLIST_PATTERN;
     93 
     94     static {
     95         HOSTNAME_PATTERN = Pattern.compile(HOSTNAME_REGEXP);
     96         EXCLLIST_PATTERN = Pattern.compile(EXCLLIST_REGEXP);
     97         sDefaultProxySelector = ProxySelector.getDefault();
     98     }
     99 
    100     /**
    101      * Return the proxy object to be used for the URL given as parameter.
    102      * @param ctx A Context used to get the settings for the proxy host.
    103      * @param url A URL to be accessed. Used to evaluate exclusion list.
    104      * @return Proxy (java.net) object containing the host name. If the
    105      *         user did not set a hostname it returns the default host.
    106      *         A null value means that no host is to be used.
    107      * {@hide}
    108      */
    109     public static final java.net.Proxy getProxy(Context ctx, String url) {
    110         String host = "";
    111         if ((url != null) && !isLocalHost(host)) {
    112             URI uri = URI.create(url);
    113             ProxySelector proxySelector = ProxySelector.getDefault();
    114 
    115             List<java.net.Proxy> proxyList = proxySelector.select(uri);
    116 
    117             if (proxyList.size() > 0) {
    118                 return proxyList.get(0);
    119             }
    120         }
    121         return java.net.Proxy.NO_PROXY;
    122     }
    123 
    124 
    125     /**
    126      * Return the proxy host set by the user.
    127      * @param ctx A Context used to get the settings for the proxy host.
    128      * @return String containing the host name. If the user did not set a host
    129      *         name it returns the default host. A null value means that no
    130      *         host is to be used.
    131      * @deprecated Use standard java vm proxy values to find the host, port
    132      *         and exclusion list.  This call ignores the exclusion list.
    133      */
    134     @Deprecated
    135     public static final String getHost(Context ctx) {
    136         java.net.Proxy proxy = getProxy(ctx, null);
    137         if (proxy == java.net.Proxy.NO_PROXY) return null;
    138         try {
    139             return ((InetSocketAddress)(proxy.address())).getHostName();
    140         } catch (Exception e) {
    141             return null;
    142         }
    143     }
    144 
    145     /**
    146      * Return the proxy port set by the user.
    147      * @param ctx A Context used to get the settings for the proxy port.
    148      * @return The port number to use or -1 if no proxy is to be used.
    149      * @deprecated Use standard java vm proxy values to find the host, port
    150      *         and exclusion list.  This call ignores the exclusion list.
    151      */
    152     @Deprecated
    153     public static final int getPort(Context ctx) {
    154         java.net.Proxy proxy = getProxy(ctx, null);
    155         if (proxy == java.net.Proxy.NO_PROXY) return -1;
    156         try {
    157             return ((InetSocketAddress)(proxy.address())).getPort();
    158         } catch (Exception e) {
    159             return -1;
    160         }
    161     }
    162 
    163     /**
    164      * Return the default proxy host specified by the carrier.
    165      * @return String containing the host name or null if there is no proxy for
    166      * this carrier.
    167      * @deprecated Use standard java vm proxy values to find the host, port and
    168      *         exclusion list.  This call ignores the exclusion list and no
    169      *         longer reports only mobile-data apn-based proxy values.
    170      */
    171     @Deprecated
    172     public static final String getDefaultHost() {
    173         String host = System.getProperty("http.proxyHost");
    174         if (TextUtils.isEmpty(host)) return null;
    175         return host;
    176     }
    177 
    178     /**
    179      * Return the default proxy port specified by the carrier.
    180      * @return The port number to be used with the proxy host or -1 if there is
    181      * no proxy for this carrier.
    182      * @deprecated Use standard java vm proxy values to find the host, port and
    183      *         exclusion list.  This call ignores the exclusion list and no
    184      *         longer reports only mobile-data apn-based proxy values.
    185      */
    186     @Deprecated
    187     public static final int getDefaultPort() {
    188         if (getDefaultHost() == null) return -1;
    189         try {
    190             return Integer.parseInt(System.getProperty("http.proxyPort"));
    191         } catch (NumberFormatException e) {
    192             return -1;
    193         }
    194     }
    195 
    196     private static final boolean isLocalHost(String host) {
    197         if (host == null) {
    198             return false;
    199         }
    200         try {
    201             if (host != null) {
    202                 if (host.equalsIgnoreCase("localhost")) {
    203                     return true;
    204                 }
    205                 if (NetworkUtils.numericToInetAddress(host).isLoopbackAddress()) {
    206                     return true;
    207                 }
    208             }
    209         } catch (IllegalArgumentException iex) {
    210         }
    211         return false;
    212     }
    213 
    214     /**
    215      * Validate syntax of hostname, port and exclusion list entries
    216      * {@hide}
    217      */
    218     public static int validate(String hostname, String port, String exclList) {
    219         Matcher match = HOSTNAME_PATTERN.matcher(hostname);
    220         Matcher listMatch = EXCLLIST_PATTERN.matcher(exclList);
    221 
    222         if (!match.matches()) return PROXY_HOSTNAME_INVALID;
    223 
    224         if (!listMatch.matches()) return PROXY_EXCLLIST_INVALID;
    225 
    226         if (hostname.length() > 0 && port.length() == 0) return PROXY_PORT_EMPTY;
    227 
    228         if (port.length() > 0) {
    229             if (hostname.length() == 0) return PROXY_HOSTNAME_EMPTY;
    230             int portVal = -1;
    231             try {
    232                 portVal = Integer.parseInt(port);
    233             } catch (NumberFormatException ex) {
    234                 return PROXY_PORT_INVALID;
    235             }
    236             if (portVal <= 0 || portVal > 0xFFFF) return PROXY_PORT_INVALID;
    237         }
    238         return PROXY_VALID;
    239     }
    240 
    241     /** @hide */
    242     public static final void setHttpProxySystemProperty(ProxyInfo p) {
    243         String host = null;
    244         String port = null;
    245         String exclList = null;
    246         Uri pacFileUrl = Uri.EMPTY;
    247         if (p != null) {
    248             host = p.getHost();
    249             port = Integer.toString(p.getPort());
    250             exclList = p.getExclusionListAsString();
    251             pacFileUrl = p.getPacFileUrl();
    252         }
    253         setHttpProxySystemProperty(host, port, exclList, pacFileUrl);
    254     }
    255 
    256     /** @hide */
    257     public static final void setHttpProxySystemProperty(String host, String port, String exclList,
    258             Uri pacFileUrl) {
    259         if (exclList != null) exclList = exclList.replace(",", "|");
    260         if (false) Log.d(TAG, "setHttpProxySystemProperty :"+host+":"+port+" - "+exclList);
    261         if (host != null) {
    262             System.setProperty("http.proxyHost", host);
    263             System.setProperty("https.proxyHost", host);
    264         } else {
    265             System.clearProperty("http.proxyHost");
    266             System.clearProperty("https.proxyHost");
    267         }
    268         if (port != null) {
    269             System.setProperty("http.proxyPort", port);
    270             System.setProperty("https.proxyPort", port);
    271         } else {
    272             System.clearProperty("http.proxyPort");
    273             System.clearProperty("https.proxyPort");
    274         }
    275         if (exclList != null) {
    276             System.setProperty("http.nonProxyHosts", exclList);
    277             System.setProperty("https.nonProxyHosts", exclList);
    278         } else {
    279             System.clearProperty("http.nonProxyHosts");
    280             System.clearProperty("https.nonProxyHosts");
    281         }
    282         if (!Uri.EMPTY.equals(pacFileUrl)) {
    283             ProxySelector.setDefault(new PacProxySelector());
    284         } else {
    285             ProxySelector.setDefault(sDefaultProxySelector);
    286         }
    287     }
    288 }
    289