package com.fsck.k9.message; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; import android.net.Uri; import timber.log.Timber; import com.fsck.k9.K9; import com.fsck.k9.mail.filter.Base64; public class IdentityHeaderParser { /** * Parse an identity string. Handles both legacy and new (!) style identities. * * @param identityString * The encoded identity string that was saved in a drafts header. * * @return A map containing the value for each {@link IdentityField} in the identity string. */ public static Map<IdentityField, String> parse(final String identityString) { Map<IdentityField, String> identity = new HashMap<IdentityField, String>(); Timber.d("Decoding identity: %s", identityString); if (identityString == null || identityString.length() < 1) { return identity; } // Check to see if this is a "next gen" identity. if (identityString.charAt(0) == IdentityField.IDENTITY_VERSION_1.charAt(0) && identityString.length() > 2) { Uri.Builder builder = new Uri.Builder(); builder.encodedQuery(identityString.substring(1)); // Need to cut off the ! at the beginning. Uri uri = builder.build(); for (IdentityField key : IdentityField.values()) { String value = uri.getQueryParameter(key.value()); if (value != null) { identity.put(key, value); } } Timber.d("Decoded identity: %s", identity); // Sanity check our Integers so that recipients of this result don't have to. for (IdentityField key : IdentityField.getIntegerFields()) { if (identity.get(key) != null) { try { Integer.parseInt(identity.get(key)); } catch (NumberFormatException e) { Timber.e("Invalid %s field in identity: %s", key.name(), identity.get(key)); } } } } else { // Legacy identity Timber.d("Got a saved legacy identity: %s", identityString); StringTokenizer tokenizer = new StringTokenizer(identityString, ":", false); // First item is the body length. We use this to separate the composed reply from the quoted text. if (tokenizer.hasMoreTokens()) { String bodyLengthS = Base64.decode(tokenizer.nextToken()); try { identity.put(IdentityField.LENGTH, Integer.valueOf(bodyLengthS).toString()); } catch (Exception e) { Timber.e("Unable to parse bodyLength '%s'", bodyLengthS); } } if (tokenizer.hasMoreTokens()) { identity.put(IdentityField.SIGNATURE, Base64.decode(tokenizer.nextToken())); } if (tokenizer.hasMoreTokens()) { identity.put(IdentityField.NAME, Base64.decode(tokenizer.nextToken())); } if (tokenizer.hasMoreTokens()) { identity.put(IdentityField.EMAIL, Base64.decode(tokenizer.nextToken())); } if (tokenizer.hasMoreTokens()) { identity.put(IdentityField.QUOTED_TEXT_MODE, Base64.decode(tokenizer.nextToken())); } } return identity; } }