diff --git a/emailcommon/src/com/android/emailcommon/mail/Address.java b/emailcommon/src/com/android/emailcommon/mail/Address.java index a2807c916..9a7756a47 100644 --- a/emailcommon/src/com/android/emailcommon/mail/Address.java +++ b/emailcommon/src/com/android/emailcommon/mail/Address.java @@ -352,14 +352,21 @@ public class Address { } /** - * Unpacks an address list previously packed with pack() - * @param addressList String with packed addresses as returned by pack() + * Unpacks an address list that is either CSV of RFC822 addresses OR (for backward + * compatibility) previously packed with pack() + * @param addressList string packed with pack() or CSV of RFC822 addresses * @return array of addresses resulting from unpack */ public static Address[] unpack(String addressList) { if (addressList == null || addressList.length() == 0) { return EMPTY_ADDRESS_ARRAY; } + // IF we're CSV, just parse + if ((addressList.indexOf(LIST_DELIMITER_PERSONAL) == -1) && + (addressList.indexOf(LIST_DELIMITER_EMAIL) == -1)) { + return Address.parse(addressList); + } + // Otherwise, do backward-compatibile unpack ArrayList
addresses = new ArrayList
(); int length = addressList.length(); int pairStartIndex = 0; @@ -395,45 +402,11 @@ public class Address { } /** - * Packs an address list into a String that is very quick to read - * and parse. Packed lists can be unpacked with unpack(). - * The format is a series of packed addresses separated by LIST_DELIMITER_EMAIL. - * Each address is packed as - * a pair of address and personal separated by LIST_DELIMITER_PERSONAL, - * where the personal and delimiter are optional. - * E.g. "foo@x.com\1joe@x.com\2Joe Doe" - * @param addresses Array of addresses - * @return a string containing the packed addresses. + * Generate a String containing RFC822 addresses separated by commas + * NOTE: We used to "pack" these addresses in an app-specific format, but no longer do so */ public static String pack(Address[] addresses) { - // TODO: return same value for both null & empty list - if (addresses == null) { - return null; - } - final int nAddr = addresses.length; - if (nAddr == 0) { - return ""; - } - - // shortcut: one email with no displayName - if (nAddr == 1 && addresses[0].getPersonal() == null) { - return addresses[0].getAddress(); - } - - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < nAddr; i++) { - if (i != 0) { - sb.append(LIST_DELIMITER_EMAIL); - } - final Address address = addresses[i]; - sb.append(address.getAddress()); - final String displayName = address.getPersonal(); - if (displayName != null) { - sb.append(LIST_DELIMITER_PERSONAL); - sb.append(displayName); - } - } - return sb.toString(); + return Address.toHeader(addresses); } /** diff --git a/src/com/android/email/provider/EmailProvider.java b/src/com/android/email/provider/EmailProvider.java index 4d122b7d9..10847fc34 100644 --- a/src/com/android/email/provider/EmailProvider.java +++ b/src/com/android/email/provider/EmailProvider.java @@ -35,6 +35,7 @@ import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteOpenHelper; import android.net.Uri; +import android.os.Debug; import android.provider.BaseColumns; import android.provider.ContactsContract; import android.text.TextUtils; @@ -48,6 +49,7 @@ import com.android.email.service.AttachmentDownloadService; import com.android.emailcommon.AccountManagerTypes; import com.android.emailcommon.CalendarProviderStub; import com.android.emailcommon.Logging; +import com.android.emailcommon.mail.Address; import com.android.emailcommon.provider.Account; import com.android.emailcommon.provider.EmailContent; import com.android.emailcommon.provider.EmailContent.AccountColumns; @@ -175,8 +177,9 @@ public class EmailProvider extends ContentProvider { // Version 27: Add protocolSearchInfo to Message table // Version 28: Add notifiedMessageId and notifiedMessageCount to Account // Version 29: Add protocolPoliciesEnforced and protocolPoliciesUnsupported to Policy + // Version 30: Use CSV of RFC822 addresses instead of "packed" values - public static final int DATABASE_VERSION = 29; + public static final int DATABASE_VERSION = 30; // Any changes to the database format *must* include update-in-place code. // Original version: 2 @@ -1388,6 +1391,10 @@ public class EmailProvider extends ContentProvider { } oldVersion = 29; } + if (oldVersion == 29) { + upgradeFromVersion29ToVersion30(db); + oldVersion = 30; + } } @Override @@ -2677,6 +2684,42 @@ outer: } } + /** Upgrades the database from v29 to v30 by updating all address fields in Message */ + private static final int[] ADDRESS_COLUMN_INDICES = new int[] { + Message.CONTENT_BCC_LIST_COLUMN, Message.CONTENT_CC_LIST_COLUMN, + Message.CONTENT_FROM_LIST_COLUMN, Message.CONTENT_REPLY_TO_COLUMN, + Message.CONTENT_TO_LIST_COLUMN + }; + private static final String[] ADDRESS_COLUMN_NAMES = new String[] { + Message.BCC_LIST, Message.CC_LIST, Message.FROM_LIST, Message.REPLY_TO_LIST, Message.TO_LIST + }; + + private static void upgradeFromVersion29ToVersion30(SQLiteDatabase db) { + try { + // Loop through all messages, updating address columns to new format (CSV, RFC822) + Cursor messageCursor = db.query(Message.TABLE_NAME, Message.CONTENT_PROJECTION, null, + null, null, null, null); + ContentValues cv = new ContentValues(); + String[] whereArgs = new String[1]; + try { + while (messageCursor.moveToNext()) { + for (int i = 0; i < ADDRESS_COLUMN_INDICES.length; i++) { + Address[] addrs = + Address.unpack(messageCursor.getString(ADDRESS_COLUMN_INDICES[i])); + cv.put(ADDRESS_COLUMN_NAMES[i], Address.pack(addrs)); + } + whereArgs[0] = messageCursor.getString(Message.CONTENT_ID_COLUMN); + db.update(Message.TABLE_NAME, cv, WHERE_ID, whereArgs); + } + } finally { + messageCursor.close(); + } + } catch (SQLException e) { + // Shouldn't be needed unless we're debugging and interrupt the process + Log.w(TAG, "Exception upgrading EmailProvider.db from 29 to 30 " + e); + } + } + /** * For testing purposes, check whether a given row is cached * @param baseUri the base uri of the EmailContent