172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/*
272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2008 Esmertec AG.
372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * you may not use this file except in compliance with the License.
772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * You may obtain a copy of the License at
872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
1072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
1172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * See the License for the specific language governing permissions and
1572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * limitations under the License.
1672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */
1772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
1872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpackage com.android.mms.transaction;
19812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang
2072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport org.apache.http.HttpEntity;
2172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport org.apache.http.HttpHost;
2272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport org.apache.http.HttpRequest;
2372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport org.apache.http.HttpResponse;
2472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport org.apache.http.StatusLine;
2572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport org.apache.http.client.methods.HttpGet;
2672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport org.apache.http.client.methods.HttpPost;
2772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport org.apache.http.conn.params.ConnRouteParams;
2872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport org.apache.http.params.HttpParams;
2972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport org.apache.http.params.HttpProtocolParams;
30293000e15498b71a4986d7247e60fe8bdaa05a4bWei Huangimport org.apache.http.params.HttpConnectionParams;
31dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylorimport org.apache.http.Header;
3272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
3386a1cf79bf92dbb2b9d09431379bff6de83c2581Tom Taylorimport com.android.mms.MmsConfig;
34812391ad832f3fdac054ad3a50af563da16e99b5Wei Huangimport com.android.mms.LogTag;
3586a1cf79bf92dbb2b9d09431379bff6de83c2581Tom Taylor
3672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Context;
374d33cdcbb402a87ffeeaddb58237c70c4608c6f5Dianne Hackbornimport android.net.http.AndroidHttpClient;
3889e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafssonimport android.telephony.TelephonyManager;
3989e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafssonimport android.text.TextUtils;
40dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylorimport android.util.Config;
4172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.util.Log;
4272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
43208b7834ee01388a5fecacf00a9c1e1b8ffc5240Matthias Thomaeimport java.io.ByteArrayOutputStream;
44dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylorimport java.io.DataInputStream;
45208b7834ee01388a5fecacf00a9c1e1b8ffc5240Matthias Thomaeimport java.io.InputStream;
4672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.io.IOException;
4772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.net.SocketException;
4872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.net.URI;
4972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.net.URISyntaxException;
5072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.util.Locale;
5172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
5272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpublic class HttpUtils {
53812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang    private static final String TAG = LogTag.TRANSACTION;
54812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang
550ecc26df09777835cfa8dbfd3c48ca7b7fa7f011Tom Taylor    private static final boolean DEBUG = false;
560ecc26df09777835cfa8dbfd3c48ca7b7fa7f011Tom Taylor    private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
570ecc26df09777835cfa8dbfd3c48ca7b7fa7f011Tom Taylor
5872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static final int HTTP_POST_METHOD = 1;
5972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static final int HTTP_GET_METHOD = 2;
6072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
61208b7834ee01388a5fecacf00a9c1e1b8ffc5240Matthias Thomae    private static final int MMS_READ_BUFFER = 4096;
62208b7834ee01388a5fecacf00a9c1e1b8ffc5240Matthias Thomae
6372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // This is the value to use for the "Accept-Language" header.
6472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // Once it becomes possible for the user to change the locale
6572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // setting, this should no longer be static.  We should call
6672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // getHttpAcceptLanguage instead.
6772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final String HDR_VALUE_ACCEPT_LANGUAGE;
6872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
6972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    static {
70c122ca5ebd2ccac240002425a567718a9577568cTom Taylor        HDR_VALUE_ACCEPT_LANGUAGE = getCurrentAcceptLanguage(Locale.getDefault());
7172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
7272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
7372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // Definition for necessary HTTP headers.
7472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final String HDR_KEY_ACCEPT = "Accept";
7572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final String HDR_KEY_ACCEPT_LANGUAGE = "Accept-Language";
7672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
7772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final String HDR_VALUE_ACCEPT =
7872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        "*/*, application/vnd.wap.mms-message, application/vnd.wap.sic";
7972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
8072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private HttpUtils() {
8172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // To forbidden instantiate this class.
8272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
8372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
8472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
8572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * A helper method to send or retrieve data through HTTP protocol.
8672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     *
8772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * @param token The token to identify the sending progress.
8872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * @param url The URL used in a GET request. Null when the method is
8972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     *         HTTP_POST_METHOD.
9072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * @param pdu The data to be POST. Null when the method is HTTP_GET_METHOD.
9172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * @param method HTTP_POST_METHOD or HTTP_GET_METHOD.
9272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * @return A byte array which contains the response data.
9372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     *         If an HTTP error code is returned, an IOException will be thrown.
9472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * @throws IOException if any error occurred on network interface or
9572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     *         an HTTP error code(>=400) returned from the server.
9672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
9772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected static byte[] httpConnection(Context context, long token,
9872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String url, byte[] pdu, int method, boolean isProxySet,
9972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String proxyHost, int proxyPort) throws IOException {
10072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (url == null) {
10172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            throw new IllegalArgumentException("URL must not be null.");
10272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
10372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
104472cecc82e384f0c81d2a7885ade3db702213d82Tom Taylor        if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
10572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.v(TAG, "httpConnection: params list");
10672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.v(TAG, "\ttoken\t\t= " + token);
10772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.v(TAG, "\turl\t\t= " + url);
10872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.v(TAG, "\tmethod\t\t= "
10972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    + ((method == HTTP_POST_METHOD) ? "POST"
11072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            : ((method == HTTP_GET_METHOD) ? "GET" : "UNKNOWN")));
11172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.v(TAG, "\tisProxySet\t= " + isProxySet);
11272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.v(TAG, "\tproxyHost\t= " + proxyHost);
11372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.v(TAG, "\tproxyPort\t= " + proxyPort);
11472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // TODO Print out binary data more readable.
11572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            //Log.v(TAG, "\tpdu\t\t= " + Arrays.toString(pdu));
11672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
11772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
11872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        AndroidHttpClient client = null;
11972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
12072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        try {
12172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Make sure to use a proxy which supports CONNECT.
12272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            URI hostUrl = new URI(url);
12372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            HttpHost target = new HttpHost(
12472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    hostUrl.getHost(), hostUrl.getPort(),
12572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    HttpHost.DEFAULT_SCHEME_NAME);
12672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
127d62a959cf2e7d261e296f82831942a9a99320175Dan Egnor            client = createHttpClient(context);
12872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            HttpRequest req = null;
12972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            switch(method) {
13072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                case HTTP_POST_METHOD:
13172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    ProgressCallbackEntity entity = new ProgressCallbackEntity(
13272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                                        context, token, pdu);
13372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    // Set request content type.
13472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    entity.setContentType("application/vnd.wap.mms-message");
13572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
13672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    HttpPost post = new HttpPost(url);
13772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    post.setEntity(entity);
13872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    req = post;
13972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    break;
14072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                case HTTP_GET_METHOD:
14172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    req = new HttpGet(url);
14272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    break;
14372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                default:
14472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    Log.e(TAG, "Unknown HTTP method: " + method
14572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            + ". Must be one of POST[" + HTTP_POST_METHOD
14672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            + "] or GET[" + HTTP_GET_METHOD + "].");
14772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    return null;
14872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
14972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
15072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Set route parameters for the request.
15172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            HttpParams params = client.getParams();
15272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (isProxySet) {
15372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                ConnRouteParams.setDefaultProxy(
15472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        params, new HttpHost(proxyHost, proxyPort));
15572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
15672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            req.setParams(params);
15772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
15872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // Set necessary HTTP headers for MMS transmission.
15972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            req.addHeader(HDR_KEY_ACCEPT, HDR_VALUE_ACCEPT);
16072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            {
16189e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                String xWapProfileTagName = MmsConfig.getUaProfTagName();
16286a1cf79bf92dbb2b9d09431379bff6de83c2581Tom Taylor                String xWapProfileUrl = MmsConfig.getUaProfUrl();
16372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
16472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (xWapProfileUrl != null) {
1651b37c93a3b67483ee9b0ad604a2e1e9d8aaa84d9Wei Huang                    if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
1661b37c93a3b67483ee9b0ad604a2e1e9d8aaa84d9Wei Huang                        Log.d(LogTag.TRANSACTION,
1671b37c93a3b67483ee9b0ad604a2e1e9d8aaa84d9Wei Huang                                "[HttpUtils] httpConn: xWapProfUrl=" + xWapProfileUrl);
1681b37c93a3b67483ee9b0ad604a2e1e9d8aaa84d9Wei Huang                    }
16989e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                    req.addHeader(xWapProfileTagName, xWapProfileUrl);
17089e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                }
17189e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson            }
17289e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson
17389e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson            // Extra http parameters. Split by '|' to get a list of value pairs.
17489e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson            // Separate each pair by the first occurrence of ':' to obtain a name and
17589e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson            // value. Replace the occurrence of the string returned by
17689e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson            // MmsConfig.getHttpParamsLine1Key() with the users telephone number inside
17789e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson            // the value.
17889e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson            String extraHttpParams = MmsConfig.getHttpParams();
17989e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson
18089e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson            if (extraHttpParams != null) {
18189e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                String line1Number = ((TelephonyManager)context
18289e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                        .getSystemService(Context.TELEPHONY_SERVICE))
18389e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                        .getLine1Number();
18489e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                String line1Key = MmsConfig.getHttpParamsLine1Key();
18589e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                String paramList[] = extraHttpParams.split("\\|");
18689e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson
18789e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                for (String paramPair : paramList) {
18889e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                    String splitPair[] = paramPair.split(":", 2);
18989e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson
19089e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                    if (splitPair.length == 2) {
19189e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                        String name = splitPair[0].trim();
19289e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                        String value = splitPair[1].trim();
19389e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson
19489e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                        if (line1Key != null) {
19589e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                            value = value.replace(line1Key, line1Number);
19689e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                        }
19789e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                        if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(value)) {
19889e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                            req.addHeader(name, value);
19989e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                        }
20089e7af1acc0b62f2822ace8df6d56f4c6d37a40fChristian Gustafsson                    }
20172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
20272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
20372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            req.addHeader(HDR_KEY_ACCEPT_LANGUAGE, HDR_VALUE_ACCEPT_LANGUAGE);
20472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
20572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            HttpResponse response = client.execute(target, req);
20672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            StatusLine status = response.getStatusLine();
20772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (status.getStatusCode() != 200) { // HTTP 200 is success.
20872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                throw new IOException("HTTP error: " + status.getReasonPhrase());
20972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
21072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
21172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            HttpEntity entity = response.getEntity();
21272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            byte[] body = null;
21372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (entity != null) {
21472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                try {
215dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                    if (entity.getContentLength() > 0) {
216dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                        body = new byte[(int) entity.getContentLength()];
217dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                        DataInputStream dis = new DataInputStream(entity.getContent());
218dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                        try {
219dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                            dis.readFully(body);
220dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                        } finally {
221dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                            try {
222dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                dis.close();
223dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                            } catch (IOException e) {
224dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                Log.e(TAG, "Error closing input stream: " + e.getMessage());
225dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                            }
226208b7834ee01388a5fecacf00a9c1e1b8ffc5240Matthias Thomae                        }
227dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                    }
228dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                    if (entity.isChunked()) {
229dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                        Log.v(TAG, "httpConnection: transfer encoding is chunked");
230dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                        int bytesTobeRead = MmsConfig.getMaxMessageSize();
231dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                        byte[] tempBody = new byte[bytesTobeRead];
232dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                        DataInputStream dis = new DataInputStream(entity.getContent());
23372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        try {
234dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                            int bytesRead = 0;
235dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                            int offset = 0;
236dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                            boolean readError = false;
237dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                            do {
238dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                try {
239dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                    bytesRead = dis.read(tempBody, offset, bytesTobeRead);
240dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                } catch (IOException e) {
241dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                    readError = true;
242dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                    Log.e(TAG, "httpConnection: error reading input stream"
243dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                        + e.getMessage());
244dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                    break;
245dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                }
246dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                if (bytesRead > 0) {
247dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                    bytesTobeRead -= bytesRead;
248dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                    offset += bytesRead;
249dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                }
250dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                            } while (bytesRead >= 0 && bytesTobeRead > 0);
251dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                            if (bytesRead == -1 && offset > 0 && !readError) {
252dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                // offset is same as total number of bytes read
253dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                // bytesRead will be -1 if the data was read till the eof
254dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                body = new byte[offset];
255dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                System.arraycopy(tempBody, 0, body, 0, offset);
256dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                Log.v(TAG, "httpConnection: Chunked response length ["
257dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                    + Integer.toString(offset) + "]");
258dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                            } else {
259dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                Log.e(TAG, "httpConnection: Response entity too large or empty");
260dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                            }
261dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                        } finally {
262dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                            try {
263dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                dis.close();
264dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                            } catch (IOException e) {
265dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                                Log.e(TAG, "Error closing input stream: " + e.getMessage());
266dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                            }
26772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
26872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
26972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                } finally {
270dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                    if (entity != null) {
271dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                        entity.consumeContent();
272dd374f47c61f4fed8e6702c1f9d3f33ac5b77d02Tom Taylor                    }
27372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
27472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
27572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return body;
27672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } catch (URISyntaxException e) {
2777a17eaedae4c54b72f420380ec7129a15442cbbcTom Taylor            handleHttpConnectionException(e, url);
27872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } catch (IllegalStateException e) {
2797a17eaedae4c54b72f420380ec7129a15442cbbcTom Taylor            handleHttpConnectionException(e, url);
28072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } catch (IllegalArgumentException e) {
2817a17eaedae4c54b72f420380ec7129a15442cbbcTom Taylor            handleHttpConnectionException(e, url);
28272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } catch (SocketException e) {
2837a17eaedae4c54b72f420380ec7129a15442cbbcTom Taylor            handleHttpConnectionException(e, url);
28472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } catch (Exception e) {
2857a17eaedae4c54b72f420380ec7129a15442cbbcTom Taylor            handleHttpConnectionException(e, url);
28672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
28772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        finally {
28872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (client != null) {
28972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                client.close();
29072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
29172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
29272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return null;
29372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
29472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
2957a17eaedae4c54b72f420380ec7129a15442cbbcTom Taylor    private static void handleHttpConnectionException(Exception exception, String url)
29672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            throws IOException {
29772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Inner exception should be logged to make life easier.
2987a17eaedae4c54b72f420380ec7129a15442cbbcTom Taylor        Log.e(TAG, "Url: " + url + "\n" + exception.getMessage());
2997a17eaedae4c54b72f420380ec7129a15442cbbcTom Taylor        IOException e = new IOException(exception.getMessage());
3007a17eaedae4c54b72f420380ec7129a15442cbbcTom Taylor        e.initCause(exception);
3017a17eaedae4c54b72f420380ec7129a15442cbbcTom Taylor        throw e;
30272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
30372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
304d62a959cf2e7d261e296f82831942a9a99320175Dan Egnor    private static AndroidHttpClient createHttpClient(Context context) {
3051a0ec0c1576cab49e02a1dab796ed2be33f0a0a5Wei Huang        String userAgent = MmsConfig.getUserAgent();
306d62a959cf2e7d261e296f82831942a9a99320175Dan Egnor        AndroidHttpClient client = AndroidHttpClient.newInstance(userAgent, context);
30772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        HttpParams params = client.getParams();
30872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        HttpProtocolParams.setContentCharset(params, "UTF-8");
309293000e15498b71a4986d7247e60fe8bdaa05a4bWei Huang
310293000e15498b71a4986d7247e60fe8bdaa05a4bWei Huang        // set the socket timeout
311293000e15498b71a4986d7247e60fe8bdaa05a4bWei Huang        int soTimeout = MmsConfig.getHttpSocketTimeout();
312293000e15498b71a4986d7247e60fe8bdaa05a4bWei Huang
3131a0ec0c1576cab49e02a1dab796ed2be33f0a0a5Wei Huang        if (Log.isLoggable(LogTag.TRANSACTION, Log.DEBUG)) {
3141a0ec0c1576cab49e02a1dab796ed2be33f0a0a5Wei Huang            Log.d(TAG, "[HttpUtils] createHttpClient w/ socket timeout " + soTimeout + " ms, "
3151a0ec0c1576cab49e02a1dab796ed2be33f0a0a5Wei Huang                    + ", UA=" + userAgent);
316293000e15498b71a4986d7247e60fe8bdaa05a4bWei Huang        }
317293000e15498b71a4986d7247e60fe8bdaa05a4bWei Huang        HttpConnectionParams.setSoTimeout(params, soTimeout);
31872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return client;
31972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
32072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
321c122ca5ebd2ccac240002425a567718a9577568cTom Taylor    private static final String ACCEPT_LANG_FOR_US_LOCALE = "en-US";
322c122ca5ebd2ccac240002425a567718a9577568cTom Taylor
32372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
32472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * Return the Accept-Language header.  Use the current locale plus
32572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * US if we are in a different locale than US.
326c122ca5ebd2ccac240002425a567718a9577568cTom Taylor     * This code copied from the browser's WebSettings.java
327c122ca5ebd2ccac240002425a567718a9577568cTom Taylor     * @return Current AcceptLanguage String.
32872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
329c122ca5ebd2ccac240002425a567718a9577568cTom Taylor    public static String getCurrentAcceptLanguage(Locale locale) {
330c122ca5ebd2ccac240002425a567718a9577568cTom Taylor        StringBuilder buffer = new StringBuilder();
331c122ca5ebd2ccac240002425a567718a9577568cTom Taylor        addLocaleToHttpAcceptLanguage(buffer, locale);
332c122ca5ebd2ccac240002425a567718a9577568cTom Taylor
333c122ca5ebd2ccac240002425a567718a9577568cTom Taylor        if (!Locale.US.equals(locale)) {
334c122ca5ebd2ccac240002425a567718a9577568cTom Taylor            if (buffer.length() > 0) {
335c122ca5ebd2ccac240002425a567718a9577568cTom Taylor                buffer.append(", ");
33672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
337c122ca5ebd2ccac240002425a567718a9577568cTom Taylor            buffer.append(ACCEPT_LANG_FOR_US_LOCALE);
33872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
339c122ca5ebd2ccac240002425a567718a9577568cTom Taylor
340c122ca5ebd2ccac240002425a567718a9577568cTom Taylor        return buffer.toString();
34172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
34272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
343c122ca5ebd2ccac240002425a567718a9577568cTom Taylor    /**
344c122ca5ebd2ccac240002425a567718a9577568cTom Taylor     * Convert obsolete language codes, including Hebrew/Indonesian/Yiddish,
345c122ca5ebd2ccac240002425a567718a9577568cTom Taylor     * to new standard.
346c122ca5ebd2ccac240002425a567718a9577568cTom Taylor     */
347c122ca5ebd2ccac240002425a567718a9577568cTom Taylor    private static String convertObsoleteLanguageCodeToNew(String langCode) {
348c122ca5ebd2ccac240002425a567718a9577568cTom Taylor        if (langCode == null) {
349c122ca5ebd2ccac240002425a567718a9577568cTom Taylor            return null;
350c122ca5ebd2ccac240002425a567718a9577568cTom Taylor        }
351c122ca5ebd2ccac240002425a567718a9577568cTom Taylor        if ("iw".equals(langCode)) {
352c122ca5ebd2ccac240002425a567718a9577568cTom Taylor            // Hebrew
353c122ca5ebd2ccac240002425a567718a9577568cTom Taylor            return "he";
354c122ca5ebd2ccac240002425a567718a9577568cTom Taylor        } else if ("in".equals(langCode)) {
355c122ca5ebd2ccac240002425a567718a9577568cTom Taylor            // Indonesian
356c122ca5ebd2ccac240002425a567718a9577568cTom Taylor            return "id";
357c122ca5ebd2ccac240002425a567718a9577568cTom Taylor        } else if ("ji".equals(langCode)) {
358c122ca5ebd2ccac240002425a567718a9577568cTom Taylor            // Yiddish
359c122ca5ebd2ccac240002425a567718a9577568cTom Taylor            return "yi";
360c122ca5ebd2ccac240002425a567718a9577568cTom Taylor        }
361c122ca5ebd2ccac240002425a567718a9577568cTom Taylor        return langCode;
362c122ca5ebd2ccac240002425a567718a9577568cTom Taylor    }
36372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
364c122ca5ebd2ccac240002425a567718a9577568cTom Taylor    private static void addLocaleToHttpAcceptLanguage(StringBuilder builder,
365c122ca5ebd2ccac240002425a567718a9577568cTom Taylor                                                      Locale locale) {
366c122ca5ebd2ccac240002425a567718a9577568cTom Taylor        String language = convertObsoleteLanguageCodeToNew(locale.getLanguage());
36772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (language != null) {
36872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            builder.append(language);
36972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String country = locale.getCountry();
37072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (country != null) {
37172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                builder.append("-");
37272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                builder.append(country);
37372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
37472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
37572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
37672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project}
377