OSDN Git Service

Start using NetworkUtils.numericToInetAddress.
[android-x86/frameworks-base.git] / core / java / android / net / Proxy.java
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.ContentResolver;
22 import android.content.Context;
23 import android.database.ContentObserver;
24 import android.net.ProxyProperties;
25 import android.os.Handler;
26 import android.os.SystemProperties;
27 import android.text.TextUtils;
28 import android.provider.Settings;
29 import android.util.Log;
30
31 import java.net.InetAddress;
32 import java.net.InetSocketAddress;
33 import java.net.ProxySelector;
34 import java.net.SocketAddress;
35 import java.net.URI;
36 import java.net.UnknownHostException;
37 import java.util.concurrent.locks.ReadWriteLock;
38 import java.util.concurrent.locks.ReentrantReadWriteLock;
39 import java.util.List;
40 import java.util.regex.Matcher;
41 import java.util.regex.Pattern;
42
43 import junit.framework.Assert;
44
45 import org.apache.http.conn.routing.HttpRoute;
46 import org.apache.http.conn.routing.HttpRoutePlanner;
47 import org.apache.http.conn.scheme.SchemeRegistry;
48 import org.apache.http.HttpHost;
49 import org.apache.http.HttpRequest;
50 import org.apache.http.impl.conn.ProxySelectorRoutePlanner;
51 import org.apache.http.protocol.HttpContext;
52
53 /**
54  * A convenience class for accessing the user and default proxy
55  * settings.
56  */
57 public final class Proxy {
58
59     // Set to true to enable extra debugging.
60     private static final boolean DEBUG = false;
61     private static final String TAG = "Proxy";
62
63     /**
64      * Used to notify an app that's caching the default connection proxy
65      * that either the default connection or its proxy has changed.
66      * The intent will have the following extra value:</p>
67      * <ul>
68      *   <li><em>EXTRA_PROXY_INFO</em> - The ProxyProperties for the proxy.  Non-null,
69      *                                   though if the proxy is undefined the host string
70      *                                   will be empty.
71      * </ul>
72      *
73      * <p class="note">This is a protected intent that can only be sent by the system
74      */
75     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
76     public static final String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE";
77     /** {@hide} **/
78     public static final String EXTRA_PROXY_INFO = "proxy";
79
80     private static ConnectivityManager sConnectivityManager = null;
81
82     // Hostname / IP REGEX validation
83     // Matches blank input, ips, and domain names
84     private static final String NAME_IP_REGEX =
85         "[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*";
86
87     private static final String HOSTNAME_REGEXP = "^$|^" + NAME_IP_REGEX + "$";
88
89     private static final Pattern HOSTNAME_PATTERN;
90
91     private static final String EXCLLIST_REGEXP = "$|^(.?" + NAME_IP_REGEX
92         + ")+(,(.?" + NAME_IP_REGEX + "))*$";
93
94     private static final Pattern EXCLLIST_PATTERN;
95
96     static {
97         HOSTNAME_PATTERN = Pattern.compile(HOSTNAME_REGEXP);
98         EXCLLIST_PATTERN = Pattern.compile(EXCLLIST_REGEXP);
99     }
100
101     /**
102      * Return the proxy object to be used for the URL given as parameter.
103      * @param ctx A Context used to get the settings for the proxy host.
104      * @param url A URL to be accessed. Used to evaluate exclusion list.
105      * @return Proxy (java.net) object containing the host name. If the
106      *         user did not set a hostname it returns the default host.
107      *         A null value means that no host is to be used.
108      * {@hide}
109      */
110     public static final java.net.Proxy getProxy(Context ctx, String url) {
111         String host = "";
112         if (url != null) {
113             URI uri = URI.create(url);
114             host = uri.getHost();
115         }
116
117         if (!isLocalHost(host)) {
118             if (sConnectivityManager == null) {
119                 sConnectivityManager = (ConnectivityManager)ctx.getSystemService(
120                         Context.CONNECTIVITY_SERVICE);
121             }
122             if (sConnectivityManager == null) return java.net.Proxy.NO_PROXY;
123
124             ProxyProperties proxyProperties = sConnectivityManager.getProxy();
125
126             if (proxyProperties != null) {
127                 if (!proxyProperties.isExcluded(host)) {
128                     return proxyProperties.makeProxy();
129                 }
130             }
131         }
132         return java.net.Proxy.NO_PROXY;
133     }
134
135
136     /**
137      * Return the proxy host set by the user.
138      * @param ctx A Context used to get the settings for the proxy host.
139      * @return String containing the host name. If the user did not set a host
140      *         name it returns the default host. A null value means that no
141      *         host is to be used.
142      * @deprecated Use standard java vm proxy values to find the host, port
143      *         and exclusion list.  This call ignores the exclusion list.
144      */
145     public static final String getHost(Context ctx) {
146         java.net.Proxy proxy = getProxy(ctx, null);
147         if (proxy == java.net.Proxy.NO_PROXY) return null;
148         try {
149             return ((InetSocketAddress)(proxy.address())).getHostName();
150         } catch (Exception e) {
151             return null;
152         }
153     }
154
155     /**
156      * Return the proxy port set by the user.
157      * @param ctx A Context used to get the settings for the proxy port.
158      * @return The port number to use or -1 if no proxy is to be used.
159      * @deprecated Use standard java vm proxy values to find the host, port
160      *         and exclusion list.  This call ignores the exclusion list.
161      */
162     public static final int getPort(Context ctx) {
163         java.net.Proxy proxy = getProxy(ctx, null);
164         if (proxy == java.net.Proxy.NO_PROXY) return -1;
165         try {
166             return ((InetSocketAddress)(proxy.address())).getPort();
167         } catch (Exception e) {
168             return -1;
169         }
170     }
171
172     /**
173      * Return the default proxy host specified by the carrier.
174      * @return String containing the host name or null if there is no proxy for
175      * this carrier.
176      * @deprecated Use standard java vm proxy values to find the host, port and
177      *         exclusion list.  This call ignores the exclusion list and no
178      *         longer reports only mobile-data apn-based proxy values.
179      */
180     public static final String getDefaultHost() {
181         String host = System.getProperty("http.proxyHost");
182         if (TextUtils.isEmpty(host)) return null;
183         return host;
184     }
185
186     /**
187      * Return the default proxy port specified by the carrier.
188      * @return The port number to be used with the proxy host or -1 if there is
189      * no proxy for this carrier.
190      * @deprecated Use standard java vm proxy values to find the host, port and
191      *         exclusion list.  This call ignores the exclusion list and no
192      *         longer reports only mobile-data apn-based proxy values.
193      */
194     public static final int getDefaultPort() {
195         if (getDefaultHost() == null) return -1;
196         try {
197             return Integer.parseInt(System.getProperty("http.proxyPort"));
198         } catch (NumberFormatException e) {
199             return -1;
200         }
201     }
202
203     /**
204      * Returns the preferred proxy to be used by clients. This is a wrapper
205      * around {@link android.net.Proxy#getHost()}.
206      *
207      * @param context the context which will be passed to
208      * {@link android.net.Proxy#getHost()}
209      * @param url the target URL for the request
210      * @note Calling this method requires permission
211      * android.permission.ACCESS_NETWORK_STATE
212      * @return The preferred proxy to be used by clients, or null if there
213      * is no proxy.
214      * {@hide}
215      */
216     public static final HttpHost getPreferredHttpHost(Context context,
217             String url) {
218         java.net.Proxy prefProxy = getProxy(context, url);
219         if (prefProxy.equals(java.net.Proxy.NO_PROXY)) {
220             return null;
221         } else {
222             InetSocketAddress sa = (InetSocketAddress)prefProxy.address();
223             return new HttpHost(sa.getHostName(), sa.getPort(), "http");
224         }
225     }
226
227     private static final boolean isLocalHost(String host) {
228         if (host == null) {
229             return false;
230         }
231         try {
232             if (host != null) {
233                 if (host.equalsIgnoreCase("localhost")) {
234                     return true;
235                 }
236                 if (NetworkUtils.numericToInetAddress(host).isLoopbackAddress()) {
237                     return true;
238                 }
239             }
240         } catch (IllegalArgumentException iex) {
241         }
242         return false;
243     }
244
245     /**
246      * Validate syntax of hostname, port and exclusion list entries
247      * {@hide}
248      */
249     public static void validate(String hostname, String port, String exclList) {
250         Matcher match = HOSTNAME_PATTERN.matcher(hostname);
251         Matcher listMatch = EXCLLIST_PATTERN.matcher(exclList);
252
253         if (!match.matches()) {
254             throw new IllegalArgumentException();
255         }
256
257         if (!listMatch.matches()) {
258             throw new IllegalArgumentException();
259         }
260
261         if (hostname.length() > 0 && port.length() == 0) {
262             throw new IllegalArgumentException();
263         }
264
265         if (port.length() > 0) {
266             if (hostname.length() == 0) {
267                 throw new IllegalArgumentException();
268             }
269             int portVal = -1;
270             try {
271                 portVal = Integer.parseInt(port);
272             } catch (NumberFormatException ex) {
273                 throw new IllegalArgumentException();
274             }
275             if (portVal <= 0 || portVal > 0xFFFF) {
276                 throw new IllegalArgumentException();
277             }
278         }
279     }
280
281     static class AndroidProxySelectorRoutePlanner
282             extends org.apache.http.impl.conn.ProxySelectorRoutePlanner {
283
284         private Context mContext;
285
286         public AndroidProxySelectorRoutePlanner(SchemeRegistry schreg, ProxySelector prosel,
287                 Context context) {
288             super(schreg, prosel);
289             mContext = context;
290         }
291
292         @Override
293         protected java.net.Proxy chooseProxy(List<java.net.Proxy> proxies, HttpHost target,
294                 HttpRequest request, HttpContext context) {
295             return getProxy(mContext, target.getHostName());
296         }
297
298         @Override
299         protected HttpHost determineProxy(HttpHost target, HttpRequest request,
300                 HttpContext context) {
301             return getPreferredHttpHost(mContext, target.getHostName());
302         }
303
304         @Override
305         public HttpRoute determineRoute(HttpHost target, HttpRequest request,
306                 HttpContext context) {
307             HttpHost proxy = getPreferredHttpHost(mContext, target.getHostName());
308             if (proxy == null) {
309                 return new HttpRoute(target);
310             } else {
311                 return new HttpRoute(target, null, proxy, false);
312             }
313         }
314     }
315
316     /** @hide */
317     public static final HttpRoutePlanner getAndroidProxySelectorRoutePlanner(Context context) {
318         AndroidProxySelectorRoutePlanner ret = new AndroidProxySelectorRoutePlanner(
319                 new SchemeRegistry(), ProxySelector.getDefault(), context);
320         return ret;
321     }
322
323     /** @hide */
324     public static final void setHttpProxySystemProperty(ProxyProperties p) {
325         String host = null;
326         String port = null;
327         String exclList = null;
328         if (p != null) {
329             host = p.getHost();
330             port = Integer.toString(p.getPort());
331             exclList = p.getExclusionList();
332         }
333         setHttpProxySystemProperty(host, port, exclList);
334     }
335
336     /** @hide */
337     public static final void setHttpProxySystemProperty(String host, String port, String exclList) {
338         if (exclList != null) exclList = exclList.replace(",", "|");
339         if (false) Log.d(TAG, "setHttpProxySystemProperty :"+host+":"+port+" - "+exclList);
340         if (host != null) {
341             System.setProperty("http.proxyHost", host);
342             System.setProperty("https.proxyHost", host);
343         } else {
344             System.clearProperty("http.proxyHost");
345             System.clearProperty("https.proxyHost");
346         }
347         if (port != null) {
348             System.setProperty("http.proxyPort", port);
349             System.setProperty("https.proxyPort", port);
350         } else {
351             System.clearProperty("http.proxyPort");
352             System.clearProperty("https.proxyPort");
353         }
354         if (exclList != null) {
355             System.setProperty("http.nonProxyHosts", exclList);
356             System.setProperty("https.nonProxyHosts", exclList);
357         } else {
358             System.clearProperty("http.nonProxyHosts");
359             System.clearProperty("https.nonProxyHosts");
360         }
361     }
362 }