diff options
Diffstat (limited to 'android/src/android')
20 files changed, 416 insertions, 62 deletions
diff --git a/android/src/android/net/compatibility/WebAddress.java b/android/src/android/net/compatibility/WebAddress.java new file mode 100644 index 0000000..ca3081f --- /dev/null +++ b/android/src/android/net/compatibility/WebAddress.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.compatibility; + +import static android.util.Patterns.GOOD_IRI_CHAR; + +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Web Address Parser + * + * This is called WebAddress, rather than URL or URI, because it + * attempts to parse the stuff that a user will actually type into a + * browser address widget. + * + * Unlike java.net.uri, this parser will not choke on URIs missing + * schemes. It will only throw a IllegalArgumentException if the input is + * really hosed. + * + * If given an https scheme but no port, fills in port + * + */ +public class WebAddress { + + private String mScheme; + private String mHost; + private int mPort; + private String mPath; + private String mAuthInfo; + + static final int MATCH_GROUP_SCHEME = 1; + static final int MATCH_GROUP_AUTHORITY = 2; + static final int MATCH_GROUP_HOST = 3; + static final int MATCH_GROUP_PORT = 4; + static final int MATCH_GROUP_PATH = 5; + + static Pattern sAddressPattern = Pattern.compile( + /* scheme */ "(?:(http|https|file)\\:\\/\\/)?" + + /* authority */ "(?:([-A-Za-z0-9$_.+!*'(),;?&=]+(?:\\:[-A-Za-z0-9$_.+!*'(),;?&=]+)?)@)?" + + /* host */ "([" + GOOD_IRI_CHAR + "%_-][" + GOOD_IRI_CHAR + "%_\\.-]*|\\[[0-9a-fA-F:\\.]+\\])?" + + /* port */ "(?:\\:([0-9]*))?" + + /* path */ "(\\/?[^#]*)?" + + /* anchor */ ".*", Pattern.CASE_INSENSITIVE); + + /** parses given uriString. */ + public WebAddress(String address) throws IllegalArgumentException { + if (address == null) { + throw new NullPointerException(); + } + + // android.util.Log.d(LOGTAG, "WebAddress: " + address); + + mScheme = ""; + mHost = ""; + mPort = -1; + mPath = "/"; + mAuthInfo = ""; + + Matcher m = sAddressPattern.matcher(address); + String t; + if (m.matches()) { + t = m.group(MATCH_GROUP_SCHEME); + if (t != null) mScheme = t.toLowerCase(Locale.ROOT); + t = m.group(MATCH_GROUP_AUTHORITY); + if (t != null) mAuthInfo = t; + t = m.group(MATCH_GROUP_HOST); + if (t != null) mHost = t; + t = m.group(MATCH_GROUP_PORT); + if (t != null && t.length() > 0) { + // The ':' character is not returned by the regex. + try { + mPort = Integer.parseInt(t); + } catch (NumberFormatException ex) { + throw new IllegalArgumentException("Bad port"); + } + } + t = m.group(MATCH_GROUP_PATH); + if (t != null && t.length() > 0) { + /* handle busted myspace frontpage redirect with + missing initial "/" */ + if (t.charAt(0) == '/') { + mPath = t; + } else { + mPath = "/" + t; + } + } + + } else { + // nothing found... outa here + throw new IllegalArgumentException("Bad address"); + } + + /* Get port from scheme or scheme from port, if necessary and + possible */ + if (mPort == 443 && mScheme.equals("")) { + mScheme = "https"; + } else if (mPort == -1) { + if (mScheme.equals("https")) + mPort = 443; + else + mPort = 80; // default + } + if (mScheme.equals("")) mScheme = "http"; + } + + @Override + public String toString() { + String port = ""; + if ((mPort != 443 && mScheme.equals("https")) || + (mPort != 80 && mScheme.equals("http"))) { + port = ":" + Integer.toString(mPort); + } + String authInfo = ""; + if (mAuthInfo.length() > 0) { + authInfo = mAuthInfo + "@"; + } + + return mScheme + "://" + authInfo + mHost + port + mPath; + } + + public void setScheme(String scheme) { + mScheme = scheme; + } + + public String getScheme() { + return mScheme; + } + + public void setHost(String host) { + mHost = host; + } + + public String getHost() { + return mHost; + } + + public void setPort(int port) { + mPort = port; + } + + public int getPort() { + return mPort; + } + + public void setPath(String path) { + mPath = path; + } + + public String getPath() { + return mPath; + } + + public void setAuthInfo(String authInfo) { + mAuthInfo = authInfo; + } + + public String getAuthInfo() { + return mAuthInfo; + } +} diff --git a/android/src/android/net/http/AndroidHttpClient.java b/android/src/android/net/http/AndroidHttpClient.java index 04f3974..c2e5999 100644 --- a/android/src/android/net/http/AndroidHttpClient.java +++ b/android/src/android/net/http/AndroidHttpClient.java @@ -16,8 +16,6 @@ package android.net.http; -import com.android.internal.http.HttpDateTime; - import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; @@ -504,6 +502,6 @@ public final class AndroidHttpClient implements HttpClient { * of an unsupported format. */ public static long parseDate(String dateString) { - return HttpDateTime.parse(dateString); + return LegacyHttpDateTime.parse(dateString); } } diff --git a/android/src/android/net/http/AndroidHttpClientConnection.java b/android/src/android/net/http/AndroidHttpClientConnection.java index 6d48fce..a90da62 100644 --- a/android/src/android/net/http/AndroidHttpClientConnection.java +++ b/android/src/android/net/http/AndroidHttpClientConnection.java @@ -57,8 +57,6 @@ import java.net.SocketException; /** * A alternate class for (@link DefaultHttpClientConnection). * It has better performance than DefaultHttpClientConnection - * - * {@hide} */ public class AndroidHttpClientConnection implements HttpInetConnection, HttpConnection { diff --git a/android/src/android/net/http/CertificateChainValidator.java b/android/src/android/net/http/CertificateChainValidator.java index bf3fe02..d45e83f 100644 --- a/android/src/android/net/http/CertificateChainValidator.java +++ b/android/src/android/net/http/CertificateChainValidator.java @@ -19,7 +19,7 @@ package android.net.http; import com.android.org.conscrypt.SSLParametersImpl; import com.android.org.conscrypt.TrustManagerImpl; -import android.util.Slog; +import android.util.Log; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -44,8 +44,6 @@ import javax.net.ssl.X509TrustManager; /** * Class responsible for all server certificate validation functionality - * - * {@hide} */ public class CertificateChainValidator { private static final String TAG = "CertificateChainValidator"; @@ -176,10 +174,10 @@ public class CertificateChainValidator { tmf = TrustManagerFactory.getInstance("X.509"); tmf.init((KeyStore) null); } catch (NoSuchAlgorithmException e) { - Slog.w(TAG, "Couldn't find default X.509 TrustManagerFactory"); + Log.w(TAG, "Couldn't find default X.509 TrustManagerFactory"); return; } catch (KeyStoreException e) { - Slog.w(TAG, "Couldn't initialize default X.509 TrustManagerFactory", e); + Log.w(TAG, "Couldn't initialize default X.509 TrustManagerFactory", e); return; } @@ -195,7 +193,7 @@ public class CertificateChainValidator { } } if (!sentUpdate) { - Slog.w(TAG, "Didn't find a TrustManager to handle CA list update"); + Log.w(TAG, "Didn't find a TrustManager to handle CA list update"); } } diff --git a/android/src/android/net/http/Connection.java b/android/src/android/net/http/Connection.java index 831bd0e..4a49d22 100644 --- a/android/src/android/net/http/Connection.java +++ b/android/src/android/net/http/Connection.java @@ -36,9 +36,6 @@ import org.apache.http.protocol.ExecutionContext; import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.BasicHttpContext; -/** - * {@hide} - */ abstract class Connection { /** diff --git a/android/src/android/net/http/ConnectionThread.java b/android/src/android/net/http/ConnectionThread.java index d825530..3a8cd05 100644 --- a/android/src/android/net/http/ConnectionThread.java +++ b/android/src/android/net/http/ConnectionThread.java @@ -21,9 +21,6 @@ import android.os.SystemClock; import java.lang.Thread; -/** - * {@hide} - */ class ConnectionThread extends Thread { static final int WAIT_TIMEOUT = 5000; diff --git a/android/src/android/net/http/DelegatingSSLSession.java b/android/src/android/net/http/DelegatingSSLSession.java index 98fbe21..48692d7 100644 --- a/android/src/android/net/http/DelegatingSSLSession.java +++ b/android/src/android/net/http/DelegatingSSLSession.java @@ -29,8 +29,6 @@ import javax.net.ssl.X509TrustManager; /** * This is only used when a {@code certificate} is available but usage * requires a {@link SSLSession}. - * - * @hide */ public class DelegatingSSLSession implements SSLSession { protected DelegatingSSLSession() { diff --git a/android/src/android/net/http/EventHandler.java b/android/src/android/net/http/EventHandler.java index 3fd471d..df9a5d6 100644 --- a/android/src/android/net/http/EventHandler.java +++ b/android/src/android/net/http/EventHandler.java @@ -23,8 +23,6 @@ package android.net.http; * then multiple data() then endData(). handleSslErrorRequest(), if * there is an SSL certificate error. error() can occur anywhere * in the transaction. - * - * {@hide} */ public interface EventHandler { diff --git a/android/src/android/net/http/Headers.java b/android/src/android/net/http/Headers.java index 0f8b105..f5b1044 100644 --- a/android/src/android/net/http/Headers.java +++ b/android/src/android/net/http/Headers.java @@ -29,8 +29,6 @@ import org.apache.http.util.CharArrayBuffer; /** * Manages received headers - * - * {@hide} */ public final class Headers { private static final String LOGTAG = "Http"; diff --git a/android/src/android/net/http/HttpAuthHeader.java b/android/src/android/net/http/HttpAuthHeader.java index 3abac23..2a1ee98 100644 --- a/android/src/android/net/http/HttpAuthHeader.java +++ b/android/src/android/net/http/HttpAuthHeader.java @@ -21,8 +21,6 @@ import java.util.Locale; /** * HttpAuthHeader: a class to store HTTP authentication-header parameters. * For more information, see: RFC 2617: HTTP Authentication. - * - * {@hide} */ public class HttpAuthHeader { /** diff --git a/android/src/android/net/http/HttpConnection.java b/android/src/android/net/http/HttpConnection.java index edf8fed..316c1a8 100644 --- a/android/src/android/net/http/HttpConnection.java +++ b/android/src/android/net/http/HttpConnection.java @@ -27,8 +27,6 @@ import org.apache.http.params.HttpConnectionParams; /** * A requestConnection connecting to a normal (non secure) http server - * - * {@hide} */ class HttpConnection extends Connection { diff --git a/android/src/android/net/http/HttpLog.java b/android/src/android/net/http/HttpLog.java index 0934664..60b7673 100644 --- a/android/src/android/net/http/HttpLog.java +++ b/android/src/android/net/http/HttpLog.java @@ -24,9 +24,6 @@ import android.os.SystemClock; import android.util.Log; -/** - * {@hide} - */ class HttpLog { private final static String LOGTAG = "http"; diff --git a/android/src/android/net/http/HttpsConnection.java b/android/src/android/net/http/HttpsConnection.java index a8674de..213537b 100644 --- a/android/src/android/net/http/HttpsConnection.java +++ b/android/src/android/net/http/HttpsConnection.java @@ -48,8 +48,6 @@ import java.util.Locale; /** * A Connection connecting to a secure http server or tunneling through * a http proxy server to a https server. - * - * @hide */ public class HttpsConnection extends Connection { @@ -66,8 +64,6 @@ public class HttpsConnection extends Connection { } /** - * @hide - * * @param sessionDir directory to cache SSL sessions */ public static void initializeEngine(File sessionDir) { @@ -423,7 +419,6 @@ public class HttpsConnection extends Connection { /** * Simple exception we throw if the SSL connection is closed by the user. * - * {@hide} */ class SSLConnectionClosedByUserException extends SSLException { diff --git a/android/src/android/net/http/IdleCache.java b/android/src/android/net/http/IdleCache.java index fda6009..023dff1 100644 --- a/android/src/android/net/http/IdleCache.java +++ b/android/src/android/net/http/IdleCache.java @@ -24,9 +24,6 @@ import org.apache.http.HttpHost; import android.os.SystemClock; -/** - * {@hide} - */ class IdleCache { class Entry { diff --git a/android/src/android/net/http/LegacyHttpDateTime.java b/android/src/android/net/http/LegacyHttpDateTime.java new file mode 100644 index 0000000..f8d0529 --- /dev/null +++ b/android/src/android/net/http/LegacyHttpDateTime.java @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.http; + +import android.text.format.Time; + +import java.util.Calendar; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Helper for parsing an HTTP date. + */ +final class LegacyHttpDateTime { + + /* + * Regular expression for parsing HTTP-date. + * + * Wdy, DD Mon YYYY HH:MM:SS GMT + * RFC 822, updated by RFC 1123 + * + * Weekday, DD-Mon-YY HH:MM:SS GMT + * RFC 850, obsoleted by RFC 1036 + * + * Wdy Mon DD HH:MM:SS YYYY + * ANSI C's asctime() format + * + * with following variations + * + * Wdy, DD-Mon-YYYY HH:MM:SS GMT + * Wdy, (SP)D Mon YYYY HH:MM:SS GMT + * Wdy,DD Mon YYYY HH:MM:SS GMT + * Wdy, DD-Mon-YY HH:MM:SS GMT + * Wdy, DD Mon YYYY HH:MM:SS -HHMM + * Wdy, DD Mon YYYY HH:MM:SS + * Wdy Mon (SP)D HH:MM:SS YYYY + * Wdy Mon DD HH:MM:SS YYYY GMT + * + * HH can be H if the first digit is zero. + * + * Mon can be the full name of the month. + */ + private static final String HTTP_DATE_RFC_REGEXP = + "([0-9]{1,2})[- ]([A-Za-z]{3,9})[- ]([0-9]{2,4})[ ]" + + "([0-9]{1,2}:[0-9][0-9]:[0-9][0-9])"; + + private static final String HTTP_DATE_ANSIC_REGEXP = + "[ ]([A-Za-z]{3,9})[ ]+([0-9]{1,2})[ ]" + + "([0-9]{1,2}:[0-9][0-9]:[0-9][0-9])[ ]([0-9]{2,4})"; + + /** + * The compiled version of the HTTP-date regular expressions. + */ + private static final Pattern HTTP_DATE_RFC_PATTERN = + Pattern.compile(HTTP_DATE_RFC_REGEXP); + private static final Pattern HTTP_DATE_ANSIC_PATTERN = + Pattern.compile(HTTP_DATE_ANSIC_REGEXP); + + private static class TimeOfDay { + TimeOfDay(int h, int m, int s) { + this.hour = h; + this.minute = m; + this.second = s; + } + + int hour; + int minute; + int second; + } + + public static long parse(String timeString) + throws IllegalArgumentException { + + int date = 1; + int month = Calendar.JANUARY; + int year = 1970; + TimeOfDay timeOfDay; + + Matcher rfcMatcher = HTTP_DATE_RFC_PATTERN.matcher(timeString); + if (rfcMatcher.find()) { + date = getDate(rfcMatcher.group(1)); + month = getMonth(rfcMatcher.group(2)); + year = getYear(rfcMatcher.group(3)); + timeOfDay = getTime(rfcMatcher.group(4)); + } else { + Matcher ansicMatcher = HTTP_DATE_ANSIC_PATTERN.matcher(timeString); + if (ansicMatcher.find()) { + month = getMonth(ansicMatcher.group(1)); + date = getDate(ansicMatcher.group(2)); + timeOfDay = getTime(ansicMatcher.group(3)); + year = getYear(ansicMatcher.group(4)); + } else { + throw new IllegalArgumentException(); + } + } + + // FIXME: Y2038 BUG! + if (year >= 2038) { + year = 2038; + month = Calendar.JANUARY; + date = 1; + } + + Time time = new Time(Time.TIMEZONE_UTC); + time.set(timeOfDay.second, timeOfDay.minute, timeOfDay.hour, date, + month, year); + return time.toMillis(false /* use isDst */); + } + + private static int getDate(String dateString) { + if (dateString.length() == 2) { + return (dateString.charAt(0) - '0') * 10 + + (dateString.charAt(1) - '0'); + } else { + return (dateString.charAt(0) - '0'); + } + } + + /* + * jan = 9 + 0 + 13 = 22 + * feb = 5 + 4 + 1 = 10 + * mar = 12 + 0 + 17 = 29 + * apr = 0 + 15 + 17 = 32 + * may = 12 + 0 + 24 = 36 + * jun = 9 + 20 + 13 = 42 + * jul = 9 + 20 + 11 = 40 + * aug = 0 + 20 + 6 = 26 + * sep = 18 + 4 + 15 = 37 + * oct = 14 + 2 + 19 = 35 + * nov = 13 + 14 + 21 = 48 + * dec = 3 + 4 + 2 = 9 + */ + private static int getMonth(String monthString) { + int hash = Character.toLowerCase(monthString.charAt(0)) + + Character.toLowerCase(monthString.charAt(1)) + + Character.toLowerCase(monthString.charAt(2)) - 3 * 'a'; + switch (hash) { + case 22: + return Calendar.JANUARY; + case 10: + return Calendar.FEBRUARY; + case 29: + return Calendar.MARCH; + case 32: + return Calendar.APRIL; + case 36: + return Calendar.MAY; + case 42: + return Calendar.JUNE; + case 40: + return Calendar.JULY; + case 26: + return Calendar.AUGUST; + case 37: + return Calendar.SEPTEMBER; + case 35: + return Calendar.OCTOBER; + case 48: + return Calendar.NOVEMBER; + case 9: + return Calendar.DECEMBER; + default: + throw new IllegalArgumentException(); + } + } + + private static int getYear(String yearString) { + if (yearString.length() == 2) { + int year = (yearString.charAt(0) - '0') * 10 + + (yearString.charAt(1) - '0'); + if (year >= 70) { + return year + 1900; + } else { + return year + 2000; + } + } else if (yearString.length() == 3) { + // According to RFC 2822, three digit years should be added to 1900. + int year = (yearString.charAt(0) - '0') * 100 + + (yearString.charAt(1) - '0') * 10 + + (yearString.charAt(2) - '0'); + return year + 1900; + } else if (yearString.length() == 4) { + return (yearString.charAt(0) - '0') * 1000 + + (yearString.charAt(1) - '0') * 100 + + (yearString.charAt(2) - '0') * 10 + + (yearString.charAt(3) - '0'); + } else { + return 1970; + } + } + + private static TimeOfDay getTime(String timeString) { + // HH might be H + int i = 0; + int hour = timeString.charAt(i++) - '0'; + if (timeString.charAt(i) != ':') + hour = hour * 10 + (timeString.charAt(i++) - '0'); + // Skip ':' + i++; + + int minute = (timeString.charAt(i++) - '0') * 10 + + (timeString.charAt(i++) - '0'); + // Skip ':' + i++; + + int second = (timeString.charAt(i++) - '0') * 10 + + (timeString.charAt(i++) - '0'); + + return new TimeOfDay(hour, minute, second); + } +} diff --git a/android/src/android/net/http/LoggingEventHandler.java b/android/src/android/net/http/LoggingEventHandler.java index bdafa0b..4af1e8b 100644 --- a/android/src/android/net/http/LoggingEventHandler.java +++ b/android/src/android/net/http/LoggingEventHandler.java @@ -22,9 +22,6 @@ package android.net.http; import android.net.http.Headers; -/** - * {@hide} - */ public class LoggingEventHandler implements EventHandler { public void requestSent() { diff --git a/android/src/android/net/http/Request.java b/android/src/android/net/http/Request.java index 76d7bb9..d8eba11 100644 --- a/android/src/android/net/http/Request.java +++ b/android/src/android/net/http/Request.java @@ -42,8 +42,6 @@ import org.apache.http.protocol.RequestContent; /** * Represents an HTTP request for a given host. - * - * {@hide} */ class Request { @@ -516,11 +514,8 @@ class Request { * Helper: calls error() on eventhandler with appropriate message * This should not be called before the mConnection is set. */ - void error(int errorId, int resourceId) { - mEventHandler.error( - errorId, - mConnection.mContext.getText( - resourceId).toString()); + void error(int errorId, String errorMessage) { + mEventHandler.error(errorId, errorMessage); } } diff --git a/android/src/android/net/http/RequestFeeder.java b/android/src/android/net/http/RequestFeeder.java index 34ca267..a6322ae 100644 --- a/android/src/android/net/http/RequestFeeder.java +++ b/android/src/android/net/http/RequestFeeder.java @@ -22,9 +22,6 @@ package android.net.http; import org.apache.http.HttpHost; -/** - * {@hide} - */ interface RequestFeeder { Request getRequest(); diff --git a/android/src/android/net/http/RequestHandle.java b/android/src/android/net/http/RequestHandle.java index 46c3869..bc40df1 100644 --- a/android/src/android/net/http/RequestHandle.java +++ b/android/src/android/net/http/RequestHandle.java @@ -16,8 +16,7 @@ package android.net.http; -import android.net.ParseException; -import android.net.WebAddress; +import android.net.compatibility.WebAddress; import android.webkit.CookieManager; import org.apache.commons.codec.binary.Base64; @@ -33,8 +32,6 @@ import java.util.Random; /** * RequestHandle: handles a request session that may include multiple * redirects, HTTP authentication requests, etc. - * - * {@hide} */ public class RequestHandle { @@ -161,7 +158,7 @@ public class RequestHandle { "RequestHandle.setupRedirect(): too many redirects " + mRequest); mRequest.error(EventHandler.ERROR_REDIRECT_LOOP, - com.android.internal.R.string.httpErrorRedirectLoop); + "The page contains too many server redirects."); return false; } @@ -176,13 +173,16 @@ public class RequestHandle { mUrl = redirectTo; try { mUri = new WebAddress(mUrl); - } catch (ParseException e) { + } catch (IllegalArgumentException e) { e.printStackTrace(); } // update the "Cookie" header based on the redirected url mHeaders.remove("Cookie"); - String cookie = CookieManager.getInstance().getCookie(mUri); + String cookie = null; + if (mUri != null) { + cookie = CookieManager.getInstance().getCookie(mUri.toString()); + } if (cookie != null && cookie.length() > 0) { mHeaders.put("Cookie", cookie); } diff --git a/android/src/android/net/http/RequestQueue.java b/android/src/android/net/http/RequestQueue.java index 7d2da1b..17f34a5 100644 --- a/android/src/android/net/http/RequestQueue.java +++ b/android/src/android/net/http/RequestQueue.java @@ -28,7 +28,7 @@ import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Proxy; -import android.net.WebAddress; +import android.net.compatibility.WebAddress; import android.util.Log; import java.io.InputStream; @@ -40,9 +40,6 @@ import java.util.Map; import org.apache.http.HttpHost; -/** - * {@hide} - */ public class RequestQueue implements RequestFeeder { |