replace Email's private base64 class with one from android-common

Convert all usages of com.android.email.codec.binary.Base64 to use
com.android.common.Base64 instead, except for Base64OutputStream
(which doesn't exist in android-common yet).

Change-Id: I339a1f451245138187080c7444fcabef8d13f8aa
This commit is contained in:
Doug Zongker 2010-02-08 13:04:03 -08:00
parent f3332ddac8
commit f44a40cda1
9 changed files with 58 additions and 60 deletions

View File

@ -24,6 +24,7 @@ LOCAL_SRC_FILES += \
src/com/android/email/service/IEmailServiceCallback.aidl src/com/android/email/service/IEmailServiceCallback.aidl
# EXCHANGE-REMOVE-SECTION-END # EXCHANGE-REMOVE-SECTION-END
LOCAL_JAVA_STATIC_LIBRARIES := android-common
LOCAL_PACKAGE_NAME := Email LOCAL_PACKAGE_NAME := Email

View File

@ -16,7 +16,7 @@
package com.android.email; package com.android.email;
import com.android.email.provider.EmailContent; import com.android.common.Base64;
import com.android.email.provider.EmailContent.Account; import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.AccountColumns; import com.android.email.provider.EmailContent.AccountColumns;
import com.android.email.provider.EmailContent.HostAuth; import com.android.email.provider.EmailContent.HostAuth;
@ -25,9 +25,15 @@ import com.android.email.provider.EmailContent.Mailbox;
import com.android.email.provider.EmailContent.MailboxColumns; import com.android.email.provider.EmailContent.MailboxColumns;
import com.android.email.provider.EmailContent.Message; import com.android.email.provider.EmailContent.Message;
import com.android.email.provider.EmailContent.MessageColumns; import com.android.email.provider.EmailContent.MessageColumns;
import com.android.email.provider.EmailContent;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context;
import android.content.res.TypedArray;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.widget.TextView;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -35,14 +41,6 @@ import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.Date; import java.util.Date;
import com.android.email.codec.binary.Base64;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.widget.TextView;
public class Utility { public class Utility {
public final static String readInputStream(InputStream in, String encoding) throws IOException { public final static String readInputStream(InputStream in, String encoding) throws IOException {
InputStreamReader reader = new InputStreamReader(in, encoding); InputStreamReader reader = new InputStreamReader(in, encoding);
@ -91,7 +89,7 @@ public class Utility {
if (encoded == null) { if (encoded == null) {
return null; return null;
} }
byte[] decoded = new Base64().decode(encoded.getBytes()); byte[] decoded = Base64.decode(encoded, Base64.DEFAULT);
return new String(decoded); return new String(decoded);
} }
@ -99,8 +97,7 @@ public class Utility {
if (s == null) { if (s == null) {
return s; return s;
} }
byte[] encoded = new Base64().encode(s.getBytes()); return Base64.encodeToString(s.getBytes(), Base64.NO_WRAP);
return new String(encoded);
} }
public static boolean requiredFieldValid(TextView view) { public static boolean requiredFieldValid(TextView view) {
@ -114,9 +111,9 @@ public class Utility {
/** /**
* Ensures that the given string starts and ends with the double quote character. The string is not modified in any way except to add the * Ensures that the given string starts and ends with the double quote character. The string is not modified in any way except to add the
* double quote character to start and end if it's not already there. * double quote character to start and end if it's not already there.
* *
* TODO: Rename this, because "quoteString()" can mean so many different things. * TODO: Rename this, because "quoteString()" can mean so many different things.
* *
* sample -> "sample" * sample -> "sample"
* "sample" -> "sample" * "sample" -> "sample"
* ""sample"" -> "sample" * ""sample"" -> "sample"
@ -139,37 +136,37 @@ public class Utility {
return s; return s;
} }
} }
/** /**
* Apply quoting rules per IMAP RFC, * Apply quoting rules per IMAP RFC,
* quoted = DQUOTE *QUOTED-CHAR DQUOTE * quoted = DQUOTE *QUOTED-CHAR DQUOTE
* QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> / "\" quoted-specials * QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> / "\" quoted-specials
* quoted-specials = DQUOTE / "\" * quoted-specials = DQUOTE / "\"
* *
* This is used primarily for IMAP login, but might be useful elsewhere. * This is used primarily for IMAP login, but might be useful elsewhere.
* *
* NOTE: Not very efficient - you may wish to preflight this, or perhaps it should check * NOTE: Not very efficient - you may wish to preflight this, or perhaps it should check
* for trouble chars before calling the replace functions. * for trouble chars before calling the replace functions.
* *
* @param s The string to be quoted. * @param s The string to be quoted.
* @return A copy of the string, having undergone quoting as described above * @return A copy of the string, having undergone quoting as described above
*/ */
public static String imapQuoted(String s) { public static String imapQuoted(String s) {
// First, quote any backslashes by replacing \ with \\ // First, quote any backslashes by replacing \ with \\
// regex Pattern: \\ (Java string const = \\\\) // regex Pattern: \\ (Java string const = \\\\)
// Substitute: \\\\ (Java string const = \\\\\\\\) // Substitute: \\\\ (Java string const = \\\\\\\\)
String result = s.replaceAll("\\\\", "\\\\\\\\"); String result = s.replaceAll("\\\\", "\\\\\\\\");
// Then, quote any double-quotes by replacing " with \" // Then, quote any double-quotes by replacing " with \"
// regex Pattern: " (Java string const = \") // regex Pattern: " (Java string const = \")
// Substitute: \\" (Java string const = \\\\\") // Substitute: \\" (Java string const = \\\\\")
result = result.replaceAll("\"", "\\\\\""); result = result.replaceAll("\"", "\\\\\"");
// return string with quotes around it // return string with quotes around it
return "\"" + result + "\""; return "\"" + result + "\"";
} }
/** /**
* A fast version of URLDecoder.decode() that works only with UTF-8 and does only two * A fast version of URLDecoder.decode() that works only with UTF-8 and does only two
* allocations. This version is around 3x as fast as the standard one and I'm using it * allocations. This version is around 3x as fast as the standard one and I'm using it

View File

@ -33,7 +33,7 @@ import java.math.BigInteger;
* @since 1.0-dev * @since 1.0-dev
* @version $Id$ * @version $Id$
*/ */
public class Base64 { /* package */ class Base64 {
/** /**
* Chunk size per RFC 2045 section 6.8. * Chunk size per RFC 2045 section 6.8.
* *

View File

@ -16,17 +16,16 @@
package com.android.email.mail.internet; package com.android.email.mail.internet;
import com.android.common.Base64;
import com.android.email.mail.Body;
import com.android.email.mail.MessagingException;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import com.android.email.codec.binary.Base64;
import com.android.email.mail.Body;
import com.android.email.mail.MessagingException;
public class TextBody implements Body { public class TextBody implements Body {
String mBody; String mBody;
@ -36,11 +35,11 @@ public class TextBody implements Body {
public void writeTo(OutputStream out) throws IOException, MessagingException { public void writeTo(OutputStream out) throws IOException, MessagingException {
byte[] bytes = mBody.getBytes("UTF-8"); byte[] bytes = mBody.getBytes("UTF-8");
out.write(Base64.encodeBase64Chunked(bytes)); out.write(Base64.encode(bytes, Base64.CRLF));
} }
/** /**
* Get the text of the body in it's unencoded format. * Get the text of the body in it's unencoded format.
* @return * @return
*/ */
public String getText() { public String getText() {

View File

@ -16,11 +16,11 @@
package com.android.email.mail.store; package com.android.email.mail.store;
import com.android.common.Base64;
import com.android.email.Email; import com.android.email.Email;
import com.android.email.Preferences; import com.android.email.Preferences;
import com.android.email.Utility; import com.android.email.Utility;
import com.android.email.VendorPolicyLoader; import com.android.email.VendorPolicyLoader;
import com.android.email.codec.binary.Base64;
import com.android.email.mail.AuthenticationFailedException; import com.android.email.mail.AuthenticationFailedException;
import com.android.email.mail.CertificateValidationException; import com.android.email.mail.CertificateValidationException;
import com.android.email.mail.FetchProfile; import com.android.email.mail.FetchProfile;
@ -167,7 +167,7 @@ public class ImapStore extends Store {
mUsername = userInfoParts[0]; mUsername = userInfoParts[0];
if (userInfoParts.length > 1) { if (userInfoParts.length > 1) {
mPassword = userInfoParts[1]; mPassword = userInfoParts[1];
// build the LOGIN string once (instead of over-and-over again.) // build the LOGIN string once (instead of over-and-over again.)
// apply the quoting here around the built-up password // apply the quoting here around the built-up password
mLoginPhrase = "LOGIN " + mUsername + " " + Utility.imapQuoted(mPassword); mLoginPhrase = "LOGIN " + mUsername + " " + Utility.imapQuoted(mPassword);
@ -191,8 +191,8 @@ public class ImapStore extends Store {
} }
/** /**
* For testing only. Injects a different root transport (it will be copied using * For testing only. Injects a different root transport (it will be copied using
* newInstanceWithConfiguration() each time IMAP sets up a new channel). The transport * newInstanceWithConfiguration() each time IMAP sets up a new channel). The transport
* should already be set up and ready to use. Do not use for real code. * should already be set up and ready to use. Do not use for real code.
* @param testTransport The Transport to inject and use for all future communication. * @param testTransport The Transport to inject and use for all future communication.
*/ */
@ -221,7 +221,7 @@ public class ImapStore extends Store {
* *
* @param userName the username of the account * @param userName the username of the account
* @param host the host (server) of the account * @param host the host (server) of the account
* @return a String for use in an IMAP ID message. * @return a String for use in an IMAP ID message.
*/ */
public String getImapId(Context context, String userName, String host) { public String getImapId(Context context, String userName, String host) {
// The first section is global to all IMAP connections, and generates the fixed // The first section is global to all IMAP connections, and generates the fixed
@ -257,7 +257,7 @@ public class ImapStore extends Store {
messageDigest.update(userName.getBytes()); messageDigest.update(userName.getBytes());
messageDigest.update(devUID.getBytes()); messageDigest.update(devUID.getBytes());
byte[] uid = messageDigest.digest(); byte[] uid = messageDigest.digest();
String hexUid = new String(new Base64().encode(uid)); String hexUid = Base64.encodeToString(uid, Base64.NO_WRAP);
id.append(" \"AGUID\" \""); id.append(" \"AGUID\" \"");
id.append(hexUid); id.append(hexUid);
id.append('\"'); id.append('\"');
@ -644,7 +644,7 @@ public class ImapStore extends Store {
} }
@Override @Override
public void copyMessages(Message[] messages, Folder folder, public void copyMessages(Message[] messages, Folder folder,
MessageUpdateCallbacks callbacks) throws MessagingException { MessageUpdateCallbacks callbacks) throws MessagingException {
checkOpen(); checkOpen();
String[] uids = new String[messages.length]; String[] uids = new String[messages.length];
@ -822,7 +822,7 @@ public class ImapStore extends Store {
if (fp.contains(FetchProfile.Item.ENVELOPE)) { if (fp.contains(FetchProfile.Item.ENVELOPE)) {
fetchFields.add("INTERNALDATE"); fetchFields.add("INTERNALDATE");
fetchFields.add("RFC822.SIZE"); fetchFields.add("RFC822.SIZE");
fetchFields.add("BODY.PEEK[HEADER.FIELDS " + fetchFields.add("BODY.PEEK[HEADER.FIELDS " +
"(date subject from content-type to cc message-id)]"); "(date subject from content-type to cc message-id)]");
} }
if (fp.contains(FetchProfile.Item.STRUCTURE)) { if (fp.contains(FetchProfile.Item.STRUCTURE)) {
@ -1310,7 +1310,7 @@ public class ImapStore extends Store {
if (mTransport == null) { if (mTransport == null) {
mTransport = mRootTransport.newInstanceWithConfiguration(); mTransport = mRootTransport.newInstanceWithConfiguration();
} }
mTransport.open(); mTransport.open();
mTransport.setSoTimeout(MailTransport.SOCKET_READ_TIMEOUT); mTransport.setSoTimeout(MailTransport.SOCKET_READ_TIMEOUT);
@ -1405,10 +1405,10 @@ public class ImapStore extends Store {
/** /**
* Send a single command to the server. The command will be preceded by an IMAP command * Send a single command to the server. The command will be preceded by an IMAP command
* tag and followed by \r\n (caller need not supply them). * tag and followed by \r\n (caller need not supply them).
* *
* @param command The command to send to the server * @param command The command to send to the server
* @param sensitive If true, the command will not be logged * @param sensitive If true, the command will not be logged
* @return Returns the command tag that was sent * @return Returns the command tag that was sent
*/ */
public String sendCommand(String command, boolean sensitive) public String sendCommand(String command, boolean sensitive)
throws MessagingException, IOException { throws MessagingException, IOException {

View File

@ -16,7 +16,7 @@
package com.android.email.mail.transport; package com.android.email.mail.transport;
import com.android.email.codec.binary.Base64; import com.android.common.Base64;
import com.android.email.codec.binary.Base64OutputStream; import com.android.email.codec.binary.Base64OutputStream;
import com.android.email.mail.Address; import com.android.email.mail.Address;
import com.android.email.mail.MessagingException; import com.android.email.mail.MessagingException;
@ -323,6 +323,6 @@ public class Rfc822Output {
writer.write("\r\n"); writer.write("\r\n");
byte[] bytes = text.getBytes("UTF-8"); byte[] bytes = text.getBytes("UTF-8");
writer.flush(); writer.flush();
out.write(Base64.encodeBase64Chunked(bytes)); out.write(Base64.encode(bytes, Base64.CRLF));
} }
} }

View File

@ -16,8 +16,8 @@
package com.android.email.mail.transport; package com.android.email.mail.transport;
import com.android.common.Base64;
import com.android.email.Email; import com.android.email.Email;
import com.android.email.codec.binary.Base64;
import com.android.email.mail.Address; import com.android.email.mail.Address;
import com.android.email.mail.AuthenticationFailedException; import com.android.email.mail.AuthenticationFailedException;
import com.android.email.mail.CertificateValidationException; import com.android.email.mail.CertificateValidationException;
@ -304,9 +304,11 @@ public class SmtpSender extends Sender {
AuthenticationFailedException, IOException { AuthenticationFailedException, IOException {
try { try {
executeSimpleCommand("AUTH LOGIN"); executeSimpleCommand("AUTH LOGIN");
executeSensitiveCommand(new String(Base64.encodeBase64(username.getBytes())), executeSensitiveCommand(
Base64.encodeToString(username.getBytes(), Base64.NO_WRAP),
"/username redacted/"); "/username redacted/");
executeSensitiveCommand(new String(Base64.encodeBase64(password.getBytes())), executeSensitiveCommand(
Base64.encodeToString(password.getBytes(), Base64.NO_WRAP),
"/password redacted/"); "/password redacted/");
} }
catch (MessagingException me) { catch (MessagingException me) {
@ -320,7 +322,7 @@ public class SmtpSender extends Sender {
private void saslAuthPlain(String username, String password) throws MessagingException, private void saslAuthPlain(String username, String password) throws MessagingException,
AuthenticationFailedException, IOException { AuthenticationFailedException, IOException {
byte[] data = ("\000" + username + "\000" + password).getBytes(); byte[] data = ("\000" + username + "\000" + password).getBytes();
data = new Base64().encode(data); data = Base64.encode(data, Base64.NO_WRAP);
try { try {
executeSensitiveCommand("AUTH PLAIN " + new String(data), "AUTH PLAIN /redacted/"); executeSensitiveCommand("AUTH PLAIN " + new String(data), "AUTH PLAIN /redacted/");
} }

View File

@ -17,9 +17,9 @@
package com.android.exchange; package com.android.exchange;
import com.android.email.SecurityPolicy; import com.android.common.Base64;
import com.android.email.SecurityPolicy.PolicySet; import com.android.email.SecurityPolicy.PolicySet;
import com.android.email.codec.binary.Base64; import com.android.email.SecurityPolicy;
import com.android.email.mail.AuthenticationFailedException; import com.android.email.mail.AuthenticationFailedException;
import com.android.email.mail.MessagingException; import com.android.email.mail.MessagingException;
import com.android.email.provider.EmailContent.Account; import com.android.email.provider.EmailContent.Account;
@ -39,11 +39,11 @@ import com.android.exchange.adapter.ContactsSyncAdapter;
import com.android.exchange.adapter.EmailSyncAdapter; import com.android.exchange.adapter.EmailSyncAdapter;
import com.android.exchange.adapter.FolderSyncParser; import com.android.exchange.adapter.FolderSyncParser;
import com.android.exchange.adapter.MeetingResponseParser; import com.android.exchange.adapter.MeetingResponseParser;
import com.android.exchange.adapter.Parser.EasParserException;
import com.android.exchange.adapter.PingParser; import com.android.exchange.adapter.PingParser;
import com.android.exchange.adapter.ProvisionParser; import com.android.exchange.adapter.ProvisionParser;
import com.android.exchange.adapter.Serializer; import com.android.exchange.adapter.Serializer;
import com.android.exchange.adapter.Tags; import com.android.exchange.adapter.Tags;
import com.android.exchange.adapter.Parser.EasParserException;
import org.apache.http.Header; import org.apache.http.Header;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
@ -792,7 +792,7 @@ public class EasSyncService extends AbstractSyncService {
String safeUserName = URLEncoder.encode(mUserName); String safeUserName = URLEncoder.encode(mUserName);
if (mAuthString == null) { if (mAuthString == null) {
String cs = mUserName + ':' + mPassword; String cs = mUserName + ':' + mPassword;
mAuthString = "Basic " + new String(Base64.encodeBase64(cs.getBytes())); mAuthString = "Basic " + Base64.encodeToString(cs.getBytes(), Base64.NO_WRAP);
mCmdString = "&User=" + safeUserName + "&DeviceId=" + mDeviceId + "&DeviceType=" mCmdString = "&User=" + safeUserName + "&DeviceId=" + mDeviceId + "&DeviceType="
+ mDeviceType; + mDeviceType;
} }
@ -1206,7 +1206,7 @@ public class EasSyncService extends AbstractSyncService {
ArrayList<String> readyMailboxes = new ArrayList<String>(); ArrayList<String> readyMailboxes = new ArrayList<String>();
ArrayList<String> notReadyMailboxes = new ArrayList<String>(); ArrayList<String> notReadyMailboxes = new ArrayList<String>();
int pingWaitCount = 0; int pingWaitCount = 0;
while ((System.currentTimeMillis() < endTime) && !mStop) { while ((System.currentTimeMillis() < endTime) && !mStop) {
// Count of pushable mailboxes // Count of pushable mailboxes
int pushCount = 0; int pushCount = 0;
@ -1214,7 +1214,7 @@ public class EasSyncService extends AbstractSyncService {
int canPushCount = 0; int canPushCount = 0;
// Count of uninitialized boxes // Count of uninitialized boxes
int uninitCount = 0; int uninitCount = 0;
Serializer s = new Serializer(); Serializer s = new Serializer();
Cursor c = mContentResolver.query(Mailbox.CONTENT_URI, Mailbox.CONTENT_PROJECTION, Cursor c = mContentResolver.query(Mailbox.CONTENT_URI, Mailbox.CONTENT_PROJECTION,
MailboxColumns.ACCOUNT_KEY + '=' + mAccount.mId + MailboxColumns.ACCOUNT_KEY + '=' + mAccount.mId +
@ -1275,7 +1275,7 @@ public class EasSyncService extends AbstractSyncService {
userLog("Ping ready for: " + readyMailboxes); userLog("Ping ready for: " + readyMailboxes);
} }
} }
// If we've waited 10 seconds or more, just ping with whatever boxes are ready // If we've waited 10 seconds or more, just ping with whatever boxes are ready
// But use a shorter than normal heartbeat // But use a shorter than normal heartbeat
boolean forcePing = !notReadyMailboxes.isEmpty() && (pingWaitCount > 5); boolean forcePing = !notReadyMailboxes.isEmpty() && (pingWaitCount > 5);

View File

@ -17,7 +17,7 @@
package com.android.exchange.adapter; package com.android.exchange.adapter;
import com.android.email.codec.binary.Base64; import com.android.common.Base64;
import com.android.email.provider.EmailContent.Mailbox; import com.android.email.provider.EmailContent.Mailbox;
import com.android.exchange.Eas; import com.android.exchange.Eas;
import com.android.exchange.EasSyncService; import com.android.exchange.EasSyncService;
@ -1258,7 +1258,7 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter {
RowBuilder builder = untypedRowBuilder(entity, Photo.CONTENT_ITEM_TYPE); RowBuilder builder = untypedRowBuilder(entity, Photo.CONTENT_ITEM_TYPE);
// We're always going to add this; it's not worth trying to figure out whether the // We're always going to add this; it's not worth trying to figure out whether the
// picture is the same as the one stored. // picture is the same as the one stored.
byte[] pic = Base64.decodeBase64(photo.getBytes()); byte[] pic = Base64.decode(photo, Base64.DEFAULT);
builder.withValue(Photo.PHOTO, pic); builder.withValue(Photo.PHOTO, pic);
add(builder.build()); add(builder.build());
} }
@ -1636,8 +1636,7 @@ public class ContactsSyncAdapter extends AbstractSyncAdapter {
private void sendPhoto(Serializer s, ContentValues cv) throws IOException { private void sendPhoto(Serializer s, ContentValues cv) throws IOException {
if (cv.containsKey(Photo.PHOTO)) { if (cv.containsKey(Photo.PHOTO)) {
byte[] bytes = cv.getAsByteArray(Photo.PHOTO); byte[] bytes = cv.getAsByteArray(Photo.PHOTO);
byte[] encodedBytes = Base64.encodeBase64(bytes); String pic = Base64.encodeToString(bytes, Base64.NO_WRAP);
String pic = new String(encodedBytes);
s.data(Tags.CONTACTS_PICTURE, pic); s.data(Tags.CONTACTS_PICTURE, pic);
} }
} }