1/*
2 * Copyright (C) 2010 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
17package android.net;
18
19
20import android.os.Parcel;
21import android.os.Parcelable;
22import android.text.TextUtils;
23
24import java.net.InetSocketAddress;
25import java.net.UnknownHostException;
26import java.util.Locale;
27
28/**
29 * A container class for the http proxy info
30 * @hide
31 */
32public class ProxyProperties implements Parcelable {
33
34    private String mHost;
35    private int mPort;
36    private String mExclusionList;
37    private String[] mParsedExclusionList;
38
39    private String mPacFileUrl;
40    public static final String LOCAL_EXCL_LIST = "";
41    public static final int LOCAL_PORT = -1;
42    public static final String LOCAL_HOST = "localhost";
43
44    public ProxyProperties(String host, int port, String exclList) {
45        mHost = host;
46        mPort = port;
47        setExclusionList(exclList);
48    }
49
50    public ProxyProperties(String pacFileUrl) {
51        mHost = LOCAL_HOST;
52        mPort = LOCAL_PORT;
53        setExclusionList(LOCAL_EXCL_LIST);
54        mPacFileUrl = pacFileUrl;
55    }
56
57    // Only used in PacManager after Local Proxy is bound.
58    public ProxyProperties(String pacFileUrl, int localProxyPort) {
59        mHost = LOCAL_HOST;
60        mPort = localProxyPort;
61        setExclusionList(LOCAL_EXCL_LIST);
62        mPacFileUrl = pacFileUrl;
63    }
64
65    private ProxyProperties(String host, int port, String exclList, String[] parsedExclList) {
66        mHost = host;
67        mPort = port;
68        mExclusionList = exclList;
69        mParsedExclusionList = parsedExclList;
70        mPacFileUrl = null;
71    }
72
73    // copy constructor instead of clone
74    public ProxyProperties(ProxyProperties source) {
75        if (source != null) {
76            mHost = source.getHost();
77            mPort = source.getPort();
78            mPacFileUrl = source.getPacFileUrl();
79            mExclusionList = source.getExclusionList();
80            mParsedExclusionList = source.mParsedExclusionList;
81        }
82    }
83
84    public InetSocketAddress getSocketAddress() {
85        InetSocketAddress inetSocketAddress = null;
86        try {
87            inetSocketAddress = new InetSocketAddress(mHost, mPort);
88        } catch (IllegalArgumentException e) { }
89        return inetSocketAddress;
90    }
91
92    public String getPacFileUrl() {
93        return mPacFileUrl;
94    }
95
96    public String getHost() {
97        return mHost;
98    }
99
100    public int getPort() {
101        return mPort;
102    }
103
104    // comma separated
105    public String getExclusionList() {
106        return mExclusionList;
107    }
108
109    // comma separated
110    private void setExclusionList(String exclusionList) {
111        mExclusionList = exclusionList;
112        if (mExclusionList == null) {
113            mParsedExclusionList = new String[0];
114        } else {
115            String splitExclusionList[] = exclusionList.toLowerCase(Locale.ROOT).split(",");
116            mParsedExclusionList = new String[splitExclusionList.length * 2];
117            for (int i = 0; i < splitExclusionList.length; i++) {
118                String s = splitExclusionList[i].trim();
119                if (s.startsWith(".")) s = s.substring(1);
120                mParsedExclusionList[i*2] = s;
121                mParsedExclusionList[(i*2)+1] = "." + s;
122            }
123        }
124    }
125
126    public boolean isExcluded(String url) {
127        if (TextUtils.isEmpty(url) || mParsedExclusionList == null ||
128                mParsedExclusionList.length == 0) return false;
129
130        Uri u = Uri.parse(url);
131        String urlDomain = u.getHost();
132        if (urlDomain == null) return false;
133        for (int i = 0; i< mParsedExclusionList.length; i+=2) {
134            if (urlDomain.equals(mParsedExclusionList[i]) ||
135                    urlDomain.endsWith(mParsedExclusionList[i+1])) {
136                return true;
137            }
138        }
139        return false;
140    }
141
142    public boolean isValid() {
143        if (!TextUtils.isEmpty(mPacFileUrl)) return true;
144        try {
145            Proxy.validate(mHost == null ? "" : mHost, mPort == 0 ? "" : Integer.toString(mPort),
146                    mExclusionList == null ? "" : mExclusionList);
147        } catch (IllegalArgumentException e) {
148            return false;
149        }
150        return true;
151    }
152
153    public java.net.Proxy makeProxy() {
154        java.net.Proxy proxy = java.net.Proxy.NO_PROXY;
155        if (mHost != null) {
156            try {
157                InetSocketAddress inetSocketAddress = new InetSocketAddress(mHost, mPort);
158                proxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, inetSocketAddress);
159            } catch (IllegalArgumentException e) {
160            }
161        }
162        return proxy;
163    }
164
165    @Override
166    public String toString() {
167        StringBuilder sb = new StringBuilder();
168        if (mPacFileUrl != null) {
169            sb.append("PAC Script: ");
170            sb.append(mPacFileUrl);
171        } else if (mHost != null) {
172            sb.append("[");
173            sb.append(mHost);
174            sb.append("] ");
175            sb.append(Integer.toString(mPort));
176            if (mExclusionList != null) {
177                    sb.append(" xl=").append(mExclusionList);
178            }
179        } else {
180            sb.append("[ProxyProperties.mHost == null]");
181        }
182        return sb.toString();
183    }
184
185    @Override
186    public boolean equals(Object o) {
187        if (!(o instanceof ProxyProperties)) return false;
188        ProxyProperties p = (ProxyProperties)o;
189        // If PAC URL is present in either then they must be equal.
190        // Other parameters will only be for fall back.
191        if (!TextUtils.isEmpty(mPacFileUrl)) {
192            return mPacFileUrl.equals(p.getPacFileUrl()) && mPort == p.mPort;
193        }
194        if (!TextUtils.isEmpty(p.getPacFileUrl())) {
195            return false;
196        }
197        if (mExclusionList != null && !mExclusionList.equals(p.getExclusionList())) return false;
198        if (mHost != null && p.getHost() != null && mHost.equals(p.getHost()) == false) {
199            return false;
200        }
201        if (mHost != null && p.mHost == null) return false;
202        if (mHost == null && p.mHost != null) return false;
203        if (mPort != p.mPort) return false;
204        return true;
205    }
206
207    /**
208     * Implement the Parcelable interface
209     * @hide
210     */
211    public int describeContents() {
212        return 0;
213    }
214
215    @Override
216    /*
217     * generate hashcode based on significant fields
218     */
219    public int hashCode() {
220        return ((null == mHost) ? 0 : mHost.hashCode())
221        + ((null == mExclusionList) ? 0 : mExclusionList.hashCode())
222        + mPort;
223    }
224
225    /**
226     * Implement the Parcelable interface.
227     * @hide
228     */
229    public void writeToParcel(Parcel dest, int flags) {
230        if (mPacFileUrl != null) {
231            dest.writeByte((byte)1);
232            dest.writeString(mPacFileUrl);
233            dest.writeInt(mPort);
234            return;
235        } else {
236            dest.writeByte((byte)0);
237        }
238        if (mHost != null) {
239            dest.writeByte((byte)1);
240            dest.writeString(mHost);
241            dest.writeInt(mPort);
242        } else {
243            dest.writeByte((byte)0);
244        }
245        dest.writeString(mExclusionList);
246        dest.writeStringArray(mParsedExclusionList);
247    }
248
249    /**
250     * Implement the Parcelable interface.
251     * @hide
252     */
253    public static final Creator<ProxyProperties> CREATOR =
254        new Creator<ProxyProperties>() {
255            public ProxyProperties createFromParcel(Parcel in) {
256                String host = null;
257                int port = 0;
258                if (in.readByte() != 0) {
259                    String url = in.readString();
260                    int localPort = in.readInt();
261                    return new ProxyProperties(url, localPort);
262                }
263                if (in.readByte() != 0) {
264                    host = in.readString();
265                    port = in.readInt();
266                }
267                String exclList = in.readString();
268                String[] parsedExclList = in.readStringArray();
269                ProxyProperties proxyProperties =
270                        new ProxyProperties(host, port, exclList, parsedExclList);
271                return proxyProperties;
272            }
273
274            public ProxyProperties[] newArray(int size) {
275                return new ProxyProperties[size];
276            }
277        };
278}
279