applied compromise code reformatting:
find src/com/android/email/ -name \*java|xargs astyle --style=ansi \ --mode=java --indent-switches --indent=spaces=4 --convert-tabs \ --unpad=paren
This commit is contained in:
parent
04e8c6a55c
commit
9cac2cd5b7
87 changed files with 13278 additions and 8766 deletions
File diff suppressed because it is too large
Load diff
|
@ -20,18 +20,19 @@ import com.android.email.mail.internet.BinaryTempFileBody;
|
|||
import com.android.email.service.BootReceiver;
|
||||
import com.android.email.service.MailService;
|
||||
|
||||
public class Email extends Application {
|
||||
public class Email extends Application
|
||||
{
|
||||
public static Application app = null;
|
||||
public static File tempDirectory;
|
||||
public static final String LOG_TAG = "k9";
|
||||
|
||||
|
||||
public enum BACKGROUND_OPS
|
||||
{
|
||||
WHEN_CHECKED, ALWAYS, NEVER
|
||||
WHEN_CHECKED, ALWAYS, NEVER
|
||||
}
|
||||
|
||||
private static int theme = android.R.style.Theme_Light;
|
||||
|
||||
|
||||
private static int theme = android.R.style.Theme_Light;
|
||||
|
||||
private static BACKGROUND_OPS backgroundOps = BACKGROUND_OPS.WHEN_CHECKED;
|
||||
/**
|
||||
* Some log messages can be sent to a file, so that the logs
|
||||
|
@ -67,34 +68,39 @@ public class Email extends Application {
|
|||
* item in the list. The entire list will be used to filter down attachments that are added
|
||||
* with Intent.ACTION_SEND.
|
||||
*/
|
||||
public static final String[] ACCEPTABLE_ATTACHMENT_SEND_TYPES = new String[] {
|
||||
public static final String[] ACCEPTABLE_ATTACHMENT_SEND_TYPES = new String[]
|
||||
{
|
||||
"*/*"
|
||||
};
|
||||
|
||||
/**
|
||||
* The MIME type(s) of attachments we're willing to view.
|
||||
*/
|
||||
public static final String[] ACCEPTABLE_ATTACHMENT_VIEW_TYPES = new String[] {
|
||||
public static final String[] ACCEPTABLE_ATTACHMENT_VIEW_TYPES = new String[]
|
||||
{
|
||||
"*/*",
|
||||
};
|
||||
|
||||
/**
|
||||
* The MIME type(s) of attachments we're not willing to view.
|
||||
*/
|
||||
public static final String[] UNACCEPTABLE_ATTACHMENT_VIEW_TYPES = new String[] {
|
||||
public static final String[] UNACCEPTABLE_ATTACHMENT_VIEW_TYPES = new String[]
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* The MIME type(s) of attachments we're willing to download to SD.
|
||||
*/
|
||||
public static final String[] ACCEPTABLE_ATTACHMENT_DOWNLOAD_TYPES = new String[] {
|
||||
public static final String[] ACCEPTABLE_ATTACHMENT_DOWNLOAD_TYPES = new String[]
|
||||
{
|
||||
"*/*",
|
||||
};
|
||||
|
||||
/**
|
||||
* The MIME type(s) of attachments we're not willing to download to SD.
|
||||
*/
|
||||
public static final String[] UNACCEPTABLE_ATTACHMENT_DOWNLOAD_TYPES = new String[] {
|
||||
public static final String[] UNACCEPTABLE_ATTACHMENT_DOWNLOAD_TYPES = new String[]
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -102,18 +108,18 @@ public class Email extends Application {
|
|||
* the server refers to as the user's Inbox. Placed here to ease use.
|
||||
*/
|
||||
public static final String INBOX = "INBOX";
|
||||
|
||||
|
||||
/**
|
||||
* For use when displaying that no folder is selected
|
||||
*/
|
||||
public static final String FOLDER_NONE = "-NONE-";
|
||||
|
||||
public static final String LOCAL_UID_PREFIX = "K9LOCAL:";
|
||||
|
||||
|
||||
public static final String REMOTE_UID_PREFIX = "K9REMOTE:";
|
||||
|
||||
|
||||
public static final String K9MAIL_IDENTITY = "X-K9mail-Identity";
|
||||
|
||||
|
||||
/**
|
||||
* Specifies how many messages will be shown in a folder by default. This number is set
|
||||
* on each new folder and can be incremented with "Load more messages..." by the
|
||||
|
@ -125,7 +131,7 @@ public class Email extends Application {
|
|||
* Number of additioanl messages to load when a user selectes "Load more messages..."
|
||||
*/
|
||||
public static int VISIBLE_LIMIT_INCREMENT = 25;
|
||||
|
||||
|
||||
public static int MAX_SEND_ATTEMPTS = 5;
|
||||
|
||||
/**
|
||||
|
@ -135,16 +141,16 @@ public class Email extends Application {
|
|||
* 6.8MB downloaded but only 5MB saved.
|
||||
*/
|
||||
public static final int MAX_ATTACHMENT_DOWNLOAD_SIZE = (5 * 1024 * 1024);
|
||||
|
||||
|
||||
/**
|
||||
* Max time (in millis) the wake lock will be held for when background sync is happening
|
||||
* Max time (in millis) the wake lock will be held for when background sync is happening
|
||||
*/
|
||||
public static final int WAKE_LOCK_TIMEOUT = 600000;
|
||||
|
||||
|
||||
public static final int MANUAL_WAKE_LOCK_TIMEOUT = 120000;
|
||||
|
||||
|
||||
public static final int PUSH_WAKE_LOCK_TIMEOUT = 60000;
|
||||
|
||||
|
||||
public static final int MAIL_SERVICE_WAKE_LOCK_TIMEOUT = 30000;
|
||||
|
||||
public static final int BOOT_RECEIVER_WAKE_LOCK_TIMEOUT = 60000;
|
||||
|
@ -158,38 +164,39 @@ public class Email extends Application {
|
|||
/**
|
||||
* Time the LED is on when blicking on new email notification
|
||||
*/
|
||||
public static final int NOTIFICATION_LED_ON_TIME = 500;
|
||||
public static final int NOTIFICATION_LED_ON_TIME = 500;
|
||||
|
||||
/**
|
||||
* Time the LED is off when blicking on new email notification
|
||||
*/
|
||||
public static final int NOTIFICATION_LED_OFF_TIME = 2000;
|
||||
|
||||
|
||||
public static final boolean NOTIFICATION_LED_WHILE_SYNCING = false;
|
||||
public static final int NOTIFICATION_LED_DIM_COLOR = 0x77770077;
|
||||
public static final int NOTIFICATION_LED_FAST_ON_TIME = 100;
|
||||
public static final int NOTIFICATION_LED_FAST_OFF_TIME = 100;
|
||||
|
||||
|
||||
public static final int NOTIFICATION_LED_SENDING_FAILURE_COLOR = 0xffff0000;
|
||||
|
||||
// Must not conflict with an account number
|
||||
public static final int FETCHING_EMAIL_NOTIFICATION_ID = -4;
|
||||
public static final int FETCHING_EMAIL_NOTIFICATION_ID = -4;
|
||||
public static final int FETCHING_EMAIL_NOTIFICATION_MULTI_ACCOUNT_ID = -1;
|
||||
public static final int FETCHING_EMAIL_NOTIFICATION_NO_ACCOUNT = -2;
|
||||
public static final int CONNECTIVITY_ID = -3;
|
||||
|
||||
|
||||
// Backup formats in case they can't be fetched from the system
|
||||
public static final String BACKUP_DATE_FORMAT = "MM-dd-yyyy";
|
||||
public static final String TIME_FORMAT_12 = "h:mm a";
|
||||
public static final String TIME_FORMAT_24 = "H:mm";
|
||||
|
||||
|
||||
public static final int FLAGGED_COLOR = 0xff4444;
|
||||
|
||||
/*
|
||||
* http://www.w3schools.com/media/media_mimeref.asp
|
||||
* + png
|
||||
*/
|
||||
public static final String[][] CONTENT_TYPE_BY_EXTENSION_MAP = new String[][] {
|
||||
public static final String[][] CONTENT_TYPE_BY_EXTENSION_MAP = new String[][]
|
||||
{
|
||||
{ "", "application/octet-stream" },
|
||||
{ "323", "text/h323"},
|
||||
{ "acx", "application/internet-property-stream"},
|
||||
|
@ -381,9 +388,11 @@ public class Email extends Application {
|
|||
{ "zip", "application/zip"}
|
||||
};
|
||||
|
||||
public class Intents {
|
||||
public class Intents
|
||||
{
|
||||
|
||||
public class EmailReceived {
|
||||
public class EmailReceived
|
||||
{
|
||||
public static final String ACTION_EMAIL_RECEIVED = "com.android.email.intent.action.EMAIL_RECEIVED";
|
||||
public static final String EXTRA_ACCOUNT = "com.android.email.intent.extra.ACCOUNT";
|
||||
public static final String EXTRA_FOLDER = "com.android.email.intent.extra.FOLDER";
|
||||
|
@ -395,7 +404,7 @@ public class Email extends Application {
|
|||
public static final String EXTRA_SUBJECT = "com.android.email.intent.extra.SUBJECT";
|
||||
public static final String EXTRA_FROM_SELF = "com.android.email.intent.extra.FROM_SELF";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -403,24 +412,28 @@ public class Email extends Application {
|
|||
* enables or disables the Compose activity, the boot receiver and the service based on
|
||||
* whether any accounts are configured.
|
||||
*/
|
||||
public static void setServicesEnabled(Context context) {
|
||||
|
||||
public static void setServicesEnabled(Context context)
|
||||
{
|
||||
|
||||
int acctLength = Preferences.getPreferences(context).getAccounts().length;
|
||||
|
||||
|
||||
setServicesEnabled(context, acctLength > 0, null);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static void setServicesEnabled(Context context, Integer wakeLockId) {
|
||||
|
||||
public static void setServicesEnabled(Context context, Integer wakeLockId)
|
||||
{
|
||||
setServicesEnabled(context, Preferences.getPreferences(context).getAccounts().length > 0, wakeLockId);
|
||||
}
|
||||
|
||||
public static void setServicesEnabled(Context context, boolean enabled, Integer wakeLockId) {
|
||||
|
||||
public static void setServicesEnabled(Context context, boolean enabled, Integer wakeLockId)
|
||||
{
|
||||
|
||||
PackageManager pm = context.getPackageManager();
|
||||
|
||||
|
||||
if (!enabled && pm.getComponentEnabledSetting(new ComponentName(context, MailService.class)) ==
|
||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
|
||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED)
|
||||
{
|
||||
/*
|
||||
* If no accounts now exist but the service is still enabled we're about to disable it
|
||||
* so we'll reschedule to kill off any existing alarms.
|
||||
|
@ -428,34 +441,35 @@ public class Email extends Application {
|
|||
MailService.actionReschedule(context, wakeLockId);
|
||||
}
|
||||
Class[] classes = { MessageCompose.class, BootReceiver.class, MailService.class };
|
||||
|
||||
|
||||
for (Class clazz : classes)
|
||||
{
|
||||
|
||||
boolean alreadyEnabled = pm.getComponentEnabledSetting(new ComponentName(context, clazz)) ==
|
||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
|
||||
|
||||
|
||||
boolean alreadyEnabled = pm.getComponentEnabledSetting(new ComponentName(context, clazz)) ==
|
||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
|
||||
|
||||
if (enabled != alreadyEnabled)
|
||||
{
|
||||
pm.setComponentEnabledSetting(
|
||||
new ComponentName(context, clazz),
|
||||
enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||
PackageManager.DONT_KILL_APP);
|
||||
new ComponentName(context, clazz),
|
||||
enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||
PackageManager.DONT_KILL_APP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (enabled && pm.getComponentEnabledSetting(new ComponentName(context, MailService.class)) ==
|
||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
|
||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED)
|
||||
{
|
||||
/*
|
||||
* And now if accounts do exist then we've just enabled the service and we want to
|
||||
* schedule alarms for the new accounts.
|
||||
*/
|
||||
MailService.actionReschedule(context, wakeLockId);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void save(SharedPreferences preferences)
|
||||
{
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
|
@ -467,14 +481,15 @@ public class Email extends Application {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
public void onCreate()
|
||||
{
|
||||
super.onCreate();
|
||||
app = this;
|
||||
Preferences prefs = Preferences.getPreferences(this);
|
||||
SharedPreferences sprefs = prefs.getPreferences();
|
||||
DEBUG = sprefs.getBoolean("enableDebugLogging", false);
|
||||
DEBUG_SENSITIVE = sprefs.getBoolean("enableSensitiveLogging", false);
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
setBackgroundOps(BACKGROUND_OPS.valueOf(sprefs.getString("backgroundOperations", "WHEN_CHECKED")));
|
||||
|
@ -483,7 +498,7 @@ public class Email extends Application {
|
|||
{
|
||||
setBackgroundOps(BACKGROUND_OPS.WHEN_CHECKED);
|
||||
}
|
||||
|
||||
|
||||
Email.setK9Theme(sprefs.getInt("theme", android.R.style.Theme_Light));
|
||||
MessagingController.getInstance(this).resetVisibleLimits(prefs.getAccounts());
|
||||
|
||||
|
@ -493,16 +508,19 @@ public class Email extends Application {
|
|||
*/
|
||||
BinaryTempFileBody.setTempDirectory(getCacheDir());
|
||||
|
||||
/*
|
||||
/*
|
||||
* Enable background sync of messages
|
||||
*/
|
||||
|
||||
|
||||
setServicesEnabled(this);
|
||||
|
||||
MessagingController.getInstance(this).addListener(new MessagingListener() {
|
||||
|
||||
MessagingController.getInstance(this).addListener(new MessagingListener()
|
||||
{
|
||||
@Override
|
||||
public void synchronizeMailboxNewMessage(Account account, String folder, Message message) {
|
||||
try {
|
||||
public void synchronizeMailboxNewMessage(Account account, String folder, Message message)
|
||||
{
|
||||
try
|
||||
{
|
||||
Uri uri = Uri.parse("email://messages/" + account.getAccountNumber() + "/" + Uri.encode(folder) + "/" + Uri.encode(message.getUid()));
|
||||
Intent intent = new Intent(Email.Intents.EmailReceived.ACTION_EMAIL_RECEIVED, uri);
|
||||
intent.putExtra(Email.Intents.EmailReceived.EXTRA_ACCOUNT, account.getDescription());
|
||||
|
@ -517,7 +535,8 @@ public class Email extends Application {
|
|||
Email.this.sendBroadcast(intent);
|
||||
Log.d(Email.LOG_TAG, "Broadcasted intent: " + message.getSubject());
|
||||
}
|
||||
catch (MessagingException e) {
|
||||
catch (MessagingException e)
|
||||
{
|
||||
Log.w(Email.LOG_TAG, "Account=" + account.getName() + " folder=" + folder + "message uid=" + message.getUid(), e);
|
||||
}
|
||||
}
|
||||
|
@ -544,7 +563,7 @@ public class Email extends Application {
|
|||
{
|
||||
Email.backgroundOps = backgroundOps;
|
||||
}
|
||||
|
||||
|
||||
public static void setBackgroundOps(String nbackgroundOps)
|
||||
{
|
||||
Email.backgroundOps = BACKGROUND_OPS.valueOf(nbackgroundOps);
|
||||
|
|
|
@ -29,7 +29,8 @@ import android.widget.TextView;
|
|||
|
||||
import com.android.email.mail.Address;
|
||||
|
||||
public class EmailAddressAdapter extends ResourceCursorAdapter {
|
||||
public class EmailAddressAdapter extends ResourceCursorAdapter
|
||||
{
|
||||
public static final int NAME_INDEX = 1;
|
||||
|
||||
public static final int DATA_INDEX = 2;
|
||||
|
@ -38,20 +39,23 @@ public class EmailAddressAdapter extends ResourceCursorAdapter {
|
|||
|
||||
private ContentResolver mContentResolver;
|
||||
|
||||
private static final String[] PROJECTION = {
|
||||
ContactMethods._ID, // 0
|
||||
ContactMethods.NAME, // 1
|
||||
ContactMethods.DATA
|
||||
// 2
|
||||
private static final String[] PROJECTION =
|
||||
{
|
||||
ContactMethods._ID, // 0
|
||||
ContactMethods.NAME, // 1
|
||||
ContactMethods.DATA
|
||||
// 2
|
||||
};
|
||||
|
||||
public EmailAddressAdapter(Context context) {
|
||||
public EmailAddressAdapter(Context context)
|
||||
{
|
||||
super(context, R.layout.recipient_dropdown_item, null);
|
||||
mContentResolver = context.getContentResolver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String convertToString(Cursor cursor) {
|
||||
public final String convertToString(Cursor cursor)
|
||||
{
|
||||
String name = cursor.getString(NAME_INDEX);
|
||||
String address = cursor.getString(DATA_INDEX);
|
||||
|
||||
|
@ -59,7 +63,8 @@ public class EmailAddressAdapter extends ResourceCursorAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public final void bindView(View view, Context context, Cursor cursor) {
|
||||
public final void bindView(View view, Context context, Cursor cursor)
|
||||
{
|
||||
TextView text1 = (TextView)view.findViewById(R.id.text1);
|
||||
TextView text2 = (TextView)view.findViewById(R.id.text2);
|
||||
text1.setText(cursor.getString(NAME_INDEX));
|
||||
|
@ -67,10 +72,12 @@ public class EmailAddressAdapter extends ResourceCursorAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
|
||||
public Cursor runQueryOnBackgroundThread(CharSequence constraint)
|
||||
{
|
||||
String where = null;
|
||||
|
||||
if (constraint != null) {
|
||||
if (constraint != null)
|
||||
{
|
||||
String filter = DatabaseUtils.sqlEscapeString(constraint.toString() + '%');
|
||||
|
||||
StringBuilder s = new StringBuilder();
|
||||
|
|
|
@ -5,12 +5,15 @@ import android.text.util.Rfc822Tokenizer;
|
|||
|
||||
import android.widget.AutoCompleteTextView.Validator;
|
||||
|
||||
public class EmailAddressValidator implements Validator {
|
||||
public CharSequence fixText(CharSequence invalidText) {
|
||||
public class EmailAddressValidator implements Validator
|
||||
{
|
||||
public CharSequence fixText(CharSequence invalidText)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public boolean isValid(CharSequence text) {
|
||||
public boolean isValid(CharSequence text)
|
||||
{
|
||||
return Rfc822Tokenizer.tokenize(text).length > 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.android.email;
|
||||
|
||||
public class EmailReceivedIntent {
|
||||
public class EmailReceivedIntent
|
||||
{
|
||||
|
||||
public static final String ACTION_EMAIL_RECEIVED = "com.android.email.intent.action.EMAIL_RECEIVED";
|
||||
public static final String EXTRA_ACCOUNT = "com.android.email.intent.extra.ACCOUNT";
|
||||
|
|
|
@ -7,54 +7,70 @@ import java.io.InputStream;
|
|||
/**
|
||||
* A filtering InputStream that stops allowing reads after the given length has been read. This
|
||||
* is used to allow a client to read directly from an underlying protocol stream without reading
|
||||
* past where the protocol handler intended the client to read.
|
||||
* past where the protocol handler intended the client to read.
|
||||
*/
|
||||
public class FixedLengthInputStream extends InputStream {
|
||||
public class FixedLengthInputStream extends InputStream
|
||||
{
|
||||
private InputStream mIn;
|
||||
private int mLength;
|
||||
private int mCount;
|
||||
|
||||
public FixedLengthInputStream(InputStream in, int length) {
|
||||
public FixedLengthInputStream(InputStream in, int length)
|
||||
{
|
||||
this.mIn = in;
|
||||
this.mLength = length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
public int available() throws IOException
|
||||
{
|
||||
return mLength - mCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (mCount < mLength) {
|
||||
public int read() throws IOException
|
||||
{
|
||||
if (mCount < mLength)
|
||||
{
|
||||
mCount++;
|
||||
return mIn.read();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int offset, int length) throws IOException {
|
||||
if (mCount < mLength) {
|
||||
public int read(byte[] b, int offset, int length) throws IOException
|
||||
{
|
||||
if (mCount < mLength)
|
||||
{
|
||||
int d = mIn.read(b, offset, Math.min(mLength - mCount, length));
|
||||
if (d == -1) {
|
||||
if (d == -1)
|
||||
{
|
||||
return -1;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
mCount += d;
|
||||
return d;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
public int read(byte[] b) throws IOException
|
||||
{
|
||||
return read(b, 0, b.length);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
public String toString()
|
||||
{
|
||||
return String.format("FixedLengthInputStream(in=%s, length=%d)", mIn.toString(), mLength);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,9 +5,11 @@ import android.app.Activity;
|
|||
import android.os.Bundle;
|
||||
|
||||
|
||||
public class K9Activity extends Activity {
|
||||
public class K9Activity extends Activity
|
||||
{
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
public void onCreate(Bundle icicle)
|
||||
{
|
||||
setTheme(Email.getK9Theme());
|
||||
super.onCreate(icicle);
|
||||
}
|
||||
|
|
|
@ -4,9 +4,11 @@ import android.app.ListActivity;
|
|||
import android.os.Bundle;
|
||||
|
||||
|
||||
public class K9ListActivity extends ListActivity {
|
||||
public class K9ListActivity extends ListActivity
|
||||
{
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
public void onCreate(Bundle icicle)
|
||||
{
|
||||
setTheme(Email.getK9Theme());
|
||||
super.onCreate(icicle);
|
||||
}
|
||||
|
|
|
@ -5,9 +5,11 @@ import android.os.Bundle;
|
|||
|
||||
|
||||
|
||||
public class K9PreferenceActivity extends PreferenceActivity {
|
||||
public class K9PreferenceActivity extends PreferenceActivity
|
||||
{
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
public void onCreate(Bundle icicle)
|
||||
{
|
||||
setTheme(Email.getK9Theme());
|
||||
super.onCreate(icicle);
|
||||
}
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
|
||||
package com.android.email;
|
||||
|
||||
public final class Manifest {
|
||||
public static final class permission {
|
||||
public final class Manifest
|
||||
{
|
||||
public static final class permission
|
||||
{
|
||||
public static final String READ_ATTACHMENT="com.android.email.permission.READ_ATTACHMENT";
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -16,146 +16,179 @@ import com.android.email.mail.Part;
|
|||
* this interface use the @Override annotation in their implementations to avoid being caught by
|
||||
* changes in this class.
|
||||
*/
|
||||
public class MessagingListener {
|
||||
|
||||
public void accountStatusChanged(Account account, int unreadMessageCount) {
|
||||
public class MessagingListener
|
||||
{
|
||||
|
||||
public void accountStatusChanged(Account account, int unreadMessageCount)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public void accountSizeChanged(Account account, long oldSize, long newSize)
|
||||
{
|
||||
}
|
||||
|
||||
public void listFoldersStarted(Account account) {
|
||||
public void listFoldersStarted(Account account)
|
||||
{
|
||||
}
|
||||
|
||||
public void listFolders(Account account, Folder[] folders) {
|
||||
public void listFolders(Account account, Folder[] folders)
|
||||
{
|
||||
}
|
||||
|
||||
public void listFoldersFailed(Account account, String message) {
|
||||
public void listFoldersFailed(Account account, String message)
|
||||
{
|
||||
}
|
||||
|
||||
public void listFoldersFinished(Account account) {
|
||||
public void listFoldersFinished(Account account)
|
||||
{
|
||||
}
|
||||
|
||||
public void listLocalMessagesStarted(Account account, String folder) {
|
||||
public void listLocalMessagesStarted(Account account, String folder)
|
||||
{
|
||||
}
|
||||
|
||||
public void listLocalMessages(Account account, String folder, Message[] messages) {
|
||||
}
|
||||
|
||||
public void listLocalMessagesAddMessages(Account account, String folder, List<Message> messages) {
|
||||
public void listLocalMessages(Account account, String folder, Message[] messages)
|
||||
{
|
||||
}
|
||||
|
||||
public void listLocalMessagesUpdateMessage(Account account, String folder, Message message) {
|
||||
public void listLocalMessagesAddMessages(Account account, String folder, List<Message> messages)
|
||||
{
|
||||
}
|
||||
|
||||
public void listLocalMessagesRemoveMessage(Account account, String folder, Message message) {
|
||||
public void listLocalMessagesUpdateMessage(Account account, String folder, Message message)
|
||||
{
|
||||
}
|
||||
|
||||
public void listLocalMessagesFailed(Account account, String folder, String message) {
|
||||
public void listLocalMessagesRemoveMessage(Account account, String folder, Message message)
|
||||
{
|
||||
}
|
||||
|
||||
public void listLocalMessagesFinished(Account account, String folder) {
|
||||
public void listLocalMessagesFailed(Account account, String folder, String message)
|
||||
{
|
||||
}
|
||||
|
||||
public void synchronizeMailboxStarted(Account account, String folder) {
|
||||
public void listLocalMessagesFinished(Account account, String folder)
|
||||
{
|
||||
}
|
||||
|
||||
public void synchronizeMailboxNewMessage(Account account, String folder, Message message) {
|
||||
public void synchronizeMailboxStarted(Account account, String folder)
|
||||
{
|
||||
}
|
||||
|
||||
public void synchronizeMailboxAddOrUpdateMessage(Account account, String folder, Message message) {
|
||||
public void synchronizeMailboxNewMessage(Account account, String folder, Message message)
|
||||
{
|
||||
}
|
||||
|
||||
public void synchronizeMailboxRemovedMessage(Account account, String folder,Message message) {
|
||||
public void synchronizeMailboxAddOrUpdateMessage(Account account, String folder, Message message)
|
||||
{
|
||||
}
|
||||
|
||||
public void synchronizeMailboxRemovedMessage(Account account, String folder,Message message)
|
||||
{
|
||||
}
|
||||
|
||||
public void synchronizeMailboxFinished(Account account, String folder,
|
||||
int totalMessagesInMailbox, int numNewMessages) {
|
||||
int totalMessagesInMailbox, int numNewMessages)
|
||||
{
|
||||
}
|
||||
|
||||
public void synchronizeMailboxFailed(Account account, String folder,
|
||||
String message) {
|
||||
String message)
|
||||
{
|
||||
}
|
||||
|
||||
public void loadMessageForViewStarted(Account account, String folder, String uid) {
|
||||
public void loadMessageForViewStarted(Account account, String folder, String uid)
|
||||
{
|
||||
}
|
||||
|
||||
public void loadMessageForViewHeadersAvailable(Account account, String folder, String uid,
|
||||
Message message) {
|
||||
Message message)
|
||||
{
|
||||
}
|
||||
|
||||
public void loadMessageForViewBodyAvailable(Account account, String folder, String uid,
|
||||
Message message) {
|
||||
Message message)
|
||||
{
|
||||
}
|
||||
|
||||
public void loadMessageForViewFinished(Account account, String folder, String uid,
|
||||
Message message) {
|
||||
Message message)
|
||||
{
|
||||
}
|
||||
|
||||
public void loadMessageForViewFailed(Account account, String folder, String uid, Throwable t) {
|
||||
public void loadMessageForViewFailed(Account account, String folder, String uid, Throwable t)
|
||||
{
|
||||
}
|
||||
|
||||
public void checkMailStarted(Context context, Account account) {
|
||||
public void checkMailStarted(Context context, Account account)
|
||||
{
|
||||
}
|
||||
|
||||
public void checkMailFinished(Context context, Account account) {
|
||||
}
|
||||
|
||||
public void checkMailFailed(Context context, Account account, String reason) {
|
||||
public void checkMailFinished(Context context, Account account)
|
||||
{
|
||||
}
|
||||
|
||||
public void sendPendingMessagesStarted(Account account) {
|
||||
public void checkMailFailed(Context context, Account account, String reason)
|
||||
{
|
||||
}
|
||||
|
||||
public void sendPendingMessagesCompleted(Account account) {
|
||||
public void sendPendingMessagesStarted(Account account)
|
||||
{
|
||||
}
|
||||
|
||||
public void sendPendingMessagesFailed(Account account) {
|
||||
|
||||
public void sendPendingMessagesCompleted(Account account)
|
||||
{
|
||||
}
|
||||
|
||||
public void sendPendingMessagesFailed(Account account)
|
||||
{
|
||||
}
|
||||
|
||||
public void messageDeleted(Account account, String folder, Message message)
|
||||
{
|
||||
|
||||
}
|
||||
public void emptyTrashCompleted(Account account) {
|
||||
}
|
||||
|
||||
public void folderStatusChanged(Account account, String folderName) {
|
||||
}
|
||||
|
||||
public void messageUidChanged(Account account, String folder, String oldUid, String newUid) {
|
||||
|
||||
}
|
||||
|
||||
public void emptyTrashCompleted(Account account)
|
||||
{
|
||||
}
|
||||
|
||||
public void folderStatusChanged(Account account, String folderName)
|
||||
{
|
||||
}
|
||||
|
||||
public void messageUidChanged(Account account, String folder, String oldUid, String newUid)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void setPushActive(Account account, String folderName, boolean enabled)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void loadAttachmentStarted(
|
||||
Account account,
|
||||
Message message,
|
||||
Part part,
|
||||
Object tag,
|
||||
boolean requiresDownload)
|
||||
Account account,
|
||||
Message message,
|
||||
Part part,
|
||||
Object tag,
|
||||
boolean requiresDownload)
|
||||
{
|
||||
}
|
||||
|
||||
public void loadAttachmentFinished(
|
||||
Account account,
|
||||
Message message,
|
||||
Part part,
|
||||
Object tag)
|
||||
Account account,
|
||||
Message message,
|
||||
Part part,
|
||||
Object tag)
|
||||
{
|
||||
}
|
||||
|
||||
public void loadAttachmentFailed(
|
||||
Account account,
|
||||
Message message,
|
||||
Part part,
|
||||
Object tag,
|
||||
String reason)
|
||||
Account account,
|
||||
Message message,
|
||||
Part part,
|
||||
Object tag,
|
||||
String reason)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -166,7 +199,8 @@ public class MessagingListener {
|
|||
* @param moreCommandsToRun True if the controller will continue on to another command
|
||||
* immediately.
|
||||
*/
|
||||
public void controllerCommandCompleted(boolean moreCommandsToRun) {
|
||||
public void controllerCommandCompleted(boolean moreCommandsToRun)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,29 +7,37 @@ import java.io.InputStream;
|
|||
/**
|
||||
* A filtering InputStream that allows single byte "peeks" without consuming the byte. The
|
||||
* client of this stream can call peek() to see the next available byte in the stream
|
||||
* and a subsequent read will still return the peeked byte.
|
||||
* and a subsequent read will still return the peeked byte.
|
||||
*/
|
||||
public class PeekableInputStream extends InputStream {
|
||||
public class PeekableInputStream extends InputStream
|
||||
{
|
||||
private InputStream mIn;
|
||||
private boolean mPeeked;
|
||||
private int mPeekedByte;
|
||||
|
||||
public PeekableInputStream(InputStream in) {
|
||||
public PeekableInputStream(InputStream in)
|
||||
{
|
||||
this.mIn = in;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (!mPeeked) {
|
||||
public int read() throws IOException
|
||||
{
|
||||
if (!mPeeked)
|
||||
{
|
||||
return mIn.read();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
mPeeked = false;
|
||||
return mPeekedByte;
|
||||
}
|
||||
}
|
||||
|
||||
public int peek() throws IOException {
|
||||
if (!mPeeked) {
|
||||
public int peek() throws IOException
|
||||
{
|
||||
if (!mPeeked)
|
||||
{
|
||||
mPeekedByte = read();
|
||||
mPeeked = true;
|
||||
}
|
||||
|
@ -37,28 +45,37 @@ public class PeekableInputStream extends InputStream {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int offset, int length) throws IOException {
|
||||
if (!mPeeked) {
|
||||
public int read(byte[] b, int offset, int length) throws IOException
|
||||
{
|
||||
if (!mPeeked)
|
||||
{
|
||||
return mIn.read(b, offset, length);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
b[0] = (byte)mPeekedByte;
|
||||
mPeeked = false;
|
||||
int r = mIn.read(b, offset + 1, length - 1);
|
||||
if (r == -1) {
|
||||
if (r == -1)
|
||||
{
|
||||
return 1;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return r + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
public int read(byte[] b) throws IOException
|
||||
{
|
||||
return read(b, 0, b.length);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
public String toString()
|
||||
{
|
||||
return String.format("PeekableInputStream(in=%s, peeked=%b, peekedByte=%d)",
|
||||
mIn.toString(), mPeeked, mPeekedByte);
|
||||
mIn.toString(), mPeeked, mPeekedByte);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,22 +10,24 @@ import android.net.Uri;
|
|||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
|
||||
public class Preferences {
|
||||
public class Preferences
|
||||
{
|
||||
private static Preferences preferences;
|
||||
|
||||
private Storage mStorage;
|
||||
|
||||
private Preferences(Context context) {
|
||||
mStorage = Storage.getStorage(context);
|
||||
if (mStorage.size() == 0)
|
||||
{
|
||||
Log.i(Email.LOG_TAG, "Preferences storage is zero-size, importing from Android-style preferences");
|
||||
Editor editor = mStorage.edit();
|
||||
editor.copy(context.getSharedPreferences("AndroidMail.Main", Context.MODE_PRIVATE));
|
||||
editor.commit();
|
||||
}
|
||||
private Preferences(Context context)
|
||||
{
|
||||
mStorage = Storage.getStorage(context);
|
||||
if (mStorage.size() == 0)
|
||||
{
|
||||
Log.i(Email.LOG_TAG, "Preferences storage is zero-size, importing from Android-style preferences");
|
||||
Editor editor = mStorage.edit();
|
||||
editor.copy(context.getSharedPreferences("AndroidMail.Main", Context.MODE_PRIVATE));
|
||||
editor.commit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* TODO need to think about what happens if this gets GCed along with the
|
||||
|
@ -35,8 +37,10 @@ public class Preferences {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
public static synchronized Preferences getPreferences(Context context) {
|
||||
if (preferences == null) {
|
||||
public static synchronized Preferences getPreferences(Context context)
|
||||
{
|
||||
if (preferences == null)
|
||||
{
|
||||
preferences = new Preferences(context);
|
||||
}
|
||||
return preferences;
|
||||
|
@ -48,20 +52,24 @@ public class Preferences {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
public Account[] getAccounts() {
|
||||
public Account[] getAccounts()
|
||||
{
|
||||
String accountUuids = getPreferences().getString("accountUuids", null);
|
||||
if (accountUuids == null || accountUuids.length() == 0) {
|
||||
if (accountUuids == null || accountUuids.length() == 0)
|
||||
{
|
||||
return new Account[] {};
|
||||
}
|
||||
String[] uuids = accountUuids.split(",");
|
||||
Account[] accounts = new Account[uuids.length];
|
||||
for (int i = 0, length = uuids.length; i < length; i++) {
|
||||
for (int i = 0, length = uuids.length; i < length; i++)
|
||||
{
|
||||
accounts[i] = new Account(this, uuids[i]);
|
||||
}
|
||||
return accounts;
|
||||
}
|
||||
|
||||
public Account getAccountByContentUri(Uri uri) {
|
||||
public Account getAccountByContentUri(Uri uri)
|
||||
{
|
||||
return new Account(this, uri.getPath().substring(1));
|
||||
}
|
||||
|
||||
|
@ -72,21 +80,27 @@ public class Preferences {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
public Account getDefaultAccount() {
|
||||
public Account getDefaultAccount()
|
||||
{
|
||||
String defaultAccountUuid = getPreferences().getString("defaultAccountUuid", null);
|
||||
Account defaultAccount = null;
|
||||
Account[] accounts = getAccounts();
|
||||
if (defaultAccountUuid != null) {
|
||||
for (Account account : accounts) {
|
||||
if (account.getUuid().equals(defaultAccountUuid)) {
|
||||
if (defaultAccountUuid != null)
|
||||
{
|
||||
for (Account account : accounts)
|
||||
{
|
||||
if (account.getUuid().equals(defaultAccountUuid))
|
||||
{
|
||||
defaultAccount = account;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultAccount == null) {
|
||||
if (accounts.length > 0) {
|
||||
if (defaultAccount == null)
|
||||
{
|
||||
if (accounts.length > 0)
|
||||
{
|
||||
defaultAccount = accounts[0];
|
||||
setDefaultAccount(defaultAccount);
|
||||
}
|
||||
|
@ -95,13 +109,17 @@ public class Preferences {
|
|||
return defaultAccount;
|
||||
}
|
||||
|
||||
public void setDefaultAccount(Account account) {
|
||||
public void setDefaultAccount(Account account)
|
||||
{
|
||||
getPreferences().edit().putString("defaultAccountUuid", account.getUuid()).commit();
|
||||
}
|
||||
|
||||
public void dump() {
|
||||
if (Config.LOGV) {
|
||||
for (String key : getPreferences().getAll().keySet()) {
|
||||
public void dump()
|
||||
{
|
||||
if (Config.LOGV)
|
||||
{
|
||||
for (String key : getPreferences().getAll().keySet())
|
||||
{
|
||||
Log.v(Email.LOG_TAG, key + " = " + getPreferences().getAll().get(key));
|
||||
}
|
||||
}
|
||||
|
@ -109,6 +127,6 @@ public class Preferences {
|
|||
|
||||
public SharedPreferences getPreferences()
|
||||
{
|
||||
return mStorage;
|
||||
return mStorage;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,21 +13,27 @@ import android.text.Editable;
|
|||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class Utility {
|
||||
public final static String readInputStream(InputStream in, String encoding) throws IOException {
|
||||
public class Utility
|
||||
{
|
||||
public final static String readInputStream(InputStream in, String encoding) throws IOException
|
||||
{
|
||||
InputStreamReader reader = new InputStreamReader(in, encoding);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
int count;
|
||||
char[] buf = new char[512];
|
||||
while ((count = reader.read(buf)) != -1) {
|
||||
while ((count = reader.read(buf)) != -1)
|
||||
{
|
||||
sb.append(buf, 0, count);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public final static boolean arrayContains(Object[] a, Object o) {
|
||||
for (int i = 0, count = a.length; i < count; i++) {
|
||||
if (a[i].equals(o)) {
|
||||
public final static boolean arrayContains(Object[] a, Object o)
|
||||
{
|
||||
for (int i = 0, count = a.length; i < count; i++)
|
||||
{
|
||||
if (a[i].equals(o))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -43,55 +49,70 @@ public class Utility {
|
|||
* @param seperator
|
||||
* @return
|
||||
*/
|
||||
public static String combine(Object[] parts, char seperator) {
|
||||
if (parts == null) {
|
||||
public static String combine(Object[] parts, char seperator)
|
||||
{
|
||||
if (parts == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
for (int i = 0; i < parts.length; i++)
|
||||
{
|
||||
sb.append(parts[i].toString());
|
||||
if (i < parts.length - 1) {
|
||||
if (i < parts.length - 1)
|
||||
{
|
||||
sb.append(seperator);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String base64Decode(String encoded) {
|
||||
if (encoded == null) {
|
||||
public static String base64Decode(String encoded)
|
||||
{
|
||||
if (encoded == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
byte[] decoded = new Base64().decode(encoded.getBytes());
|
||||
return new String(decoded);
|
||||
}
|
||||
|
||||
public static String base64Encode(String s) {
|
||||
if (s == null) {
|
||||
public static String base64Encode(String s)
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
byte[] encoded = new Base64().encode(s.getBytes());
|
||||
return new String(encoded);
|
||||
}
|
||||
|
||||
public static boolean requiredFieldValid(TextView view) {
|
||||
public static boolean requiredFieldValid(TextView view)
|
||||
{
|
||||
return view.getText() != null && view.getText().length() > 0;
|
||||
}
|
||||
|
||||
|
||||
public static boolean requiredFieldValid(Editable s) {
|
||||
|
||||
public static boolean requiredFieldValid(Editable s)
|
||||
{
|
||||
return s != null && s.length() > 0;
|
||||
}
|
||||
|
||||
public static boolean domainFieldValid(EditText view) {
|
||||
if (view.getText() != null) {
|
||||
public static boolean domainFieldValid(EditText view)
|
||||
{
|
||||
if (view.getText() != null)
|
||||
{
|
||||
String s = view.getText().toString();
|
||||
if (s.matches("^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$")) {
|
||||
if (s.matches("^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (s.matches("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$")) {
|
||||
if (s.matches("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if ((s.equalsIgnoreCase("localhost"))||(s.equalsIgnoreCase("localhost.localdomain"))) {
|
||||
if ((s.equalsIgnoreCase("localhost"))||(s.equalsIgnoreCase("localhost.localdomain")))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -112,14 +133,18 @@ public class Utility {
|
|||
* @param s
|
||||
* @return
|
||||
*/
|
||||
public static String quoteString(String s) {
|
||||
if (s == null) {
|
||||
public static String quoteString(String s)
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!s.matches("^\".*\"$")) {
|
||||
if (!s.matches("^\".*\"$"))
|
||||
{
|
||||
return "\"" + s + "\"";
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
@ -129,36 +154,45 @@ public class Utility {
|
|||
* allocations. This version is around 3x as fast as the standard one and I'm using it
|
||||
* hundreds of times in places that slow down the UI, so it helps.
|
||||
*/
|
||||
public static String fastUrlDecode(String s) {
|
||||
try {
|
||||
public static String fastUrlDecode(String s)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] bytes = s.getBytes("UTF-8");
|
||||
byte ch;
|
||||
int length = 0;
|
||||
for (int i = 0, count = bytes.length; i < count; i++) {
|
||||
for (int i = 0, count = bytes.length; i < count; i++)
|
||||
{
|
||||
ch = bytes[i];
|
||||
if (ch == '%') {
|
||||
if (ch == '%')
|
||||
{
|
||||
int h = (bytes[i + 1] - '0');
|
||||
int l = (bytes[i + 2] - '0');
|
||||
if (h > 9) {
|
||||
if (h > 9)
|
||||
{
|
||||
h -= 7;
|
||||
}
|
||||
if (l > 9) {
|
||||
if (l > 9)
|
||||
{
|
||||
l -= 7;
|
||||
}
|
||||
bytes[length] = (byte) ((h << 4) | l);
|
||||
bytes[length] = (byte)((h << 4) | l);
|
||||
i += 2;
|
||||
}
|
||||
else if (ch == '+') {
|
||||
else if (ch == '+')
|
||||
{
|
||||
bytes[length] = ' ';
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
bytes[length] = bytes[i];
|
||||
}
|
||||
length++;
|
||||
}
|
||||
return new String(bytes, 0, length, "UTF-8");
|
||||
}
|
||||
catch (UnsupportedEncodingException uee) {
|
||||
catch (UnsupportedEncodingException uee)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -168,11 +202,15 @@ public class Utility {
|
|||
* @param date
|
||||
* @return
|
||||
*/
|
||||
public static boolean isDateToday(Date date) {
|
||||
public static boolean isDateToday(Date date)
|
||||
{
|
||||
Date now = new Date();
|
||||
if (now.getTime() - 64800000 > date.getTime() || now.getTime() + 64800000 < date.getTime()) {
|
||||
if (now.getTime() - 64800000 > date.getTime() || now.getTime() + 64800000 < date.getTime())
|
||||
{
|
||||
return false;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -181,7 +219,8 @@ public class Utility {
|
|||
* TODO disabled this method globally. It is used in all the settings screens but I just
|
||||
* noticed that an unrelated icon was dimmed. Android must share drawables internally.
|
||||
*/
|
||||
public static void setCompoundDrawablesAlpha(TextView view, int alpha) {
|
||||
public static void setCompoundDrawablesAlpha(TextView view, int alpha)
|
||||
{
|
||||
// Drawable[] drawables = view.getCompoundDrawables();
|
||||
// for (Drawable drawable : drawables) {
|
||||
// if (drawable != null) {
|
||||
|
|
|
@ -53,7 +53,8 @@ import com.android.email.mail.Store;
|
|||
import com.android.email.mail.store.LocalStore;
|
||||
import com.android.email.mail.store.LocalStore.LocalFolder;
|
||||
|
||||
public class Accounts extends K9ListActivity implements OnItemClickListener, OnClickListener {
|
||||
public class Accounts extends K9ListActivity implements OnItemClickListener, OnClickListener
|
||||
{
|
||||
private static final int DIALOG_REMOVE_ACCOUNT = 1;
|
||||
private ConcurrentHashMap<String, Integer> unreadMessageCounts = new ConcurrentHashMap<String, Integer>();
|
||||
|
||||
|
@ -64,13 +65,15 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
private AccountsHandler mHandler = new AccountsHandler();
|
||||
private AccountsAdapter mAdapter;
|
||||
|
||||
private class AccountSizeChangedHolder {
|
||||
private class AccountSizeChangedHolder
|
||||
{
|
||||
Account account;
|
||||
long oldSize;
|
||||
long newSize;
|
||||
}
|
||||
|
||||
class AccountsHandler extends Handler {
|
||||
class AccountsHandler extends Handler
|
||||
{
|
||||
private static final int DATA_CHANGED = 1;
|
||||
private static final int MSG_ACCOUNT_SIZE_CHANGED = 2;
|
||||
private static final int MSG_WORKING_ACCOUNT = 3;
|
||||
|
@ -78,62 +81,71 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
private static final int MSG_FOLDER_SYNCING = 5;
|
||||
private static final int MSG_DEFINITE_PROGRESS = 6;
|
||||
|
||||
public void handleMessage(android.os.Message msg) {
|
||||
switch (msg.what) {
|
||||
case DATA_CHANGED:
|
||||
if (mAdapter != null) {
|
||||
mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
break;
|
||||
case MSG_WORKING_ACCOUNT: {
|
||||
Account account = (Account)msg.obj;
|
||||
int res = msg.arg1;
|
||||
String toastText = getString(res, account.getDescription());
|
||||
public void handleMessage(android.os.Message msg)
|
||||
{
|
||||
switch (msg.what)
|
||||
{
|
||||
case DATA_CHANGED:
|
||||
if (mAdapter != null)
|
||||
{
|
||||
mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
break;
|
||||
case MSG_WORKING_ACCOUNT:
|
||||
{
|
||||
Account account = (Account)msg.obj;
|
||||
int res = msg.arg1;
|
||||
String toastText = getString(res, account.getDescription());
|
||||
|
||||
Toast toast = Toast.makeText(getApplication(), toastText, Toast.LENGTH_SHORT);
|
||||
toast.show();
|
||||
break;
|
||||
}
|
||||
case MSG_ACCOUNT_SIZE_CHANGED: {
|
||||
AccountSizeChangedHolder holder = (AccountSizeChangedHolder)msg.obj;
|
||||
Account account = holder.account;
|
||||
Long oldSize = holder.oldSize;
|
||||
Long newSize = holder.newSize;
|
||||
String toastText = getString(R.string.account_size_changed, account.getDescription(),
|
||||
SizeFormatter.formatSize(getApplication(), oldSize), SizeFormatter.formatSize(getApplication(), newSize));;
|
||||
|
||||
Toast toast = Toast.makeText(getApplication(), toastText, Toast.LENGTH_LONG);
|
||||
toast.show();
|
||||
break;
|
||||
}
|
||||
case MSG_FOLDER_SYNCING: {
|
||||
String folderName = (String) ((Object[]) msg.obj)[0];
|
||||
String dispString;
|
||||
dispString = getString(R.string.accounts_title);
|
||||
if (folderName != null) {
|
||||
dispString += " (" + getString(R.string.status_loading)
|
||||
+ folderName + ")";
|
||||
Toast toast = Toast.makeText(getApplication(), toastText, Toast.LENGTH_SHORT);
|
||||
toast.show();
|
||||
break;
|
||||
}
|
||||
setTitle(dispString);
|
||||
break;
|
||||
}
|
||||
case MSG_PROGRESS:
|
||||
setProgressBarIndeterminateVisibility(msg.arg1 != 0);
|
||||
//setProgressBarVisibility(msg.arg1 != 0);
|
||||
break;
|
||||
case MSG_DEFINITE_PROGRESS:
|
||||
getWindow().setFeatureInt(Window.FEATURE_PROGRESS, msg.arg1);
|
||||
break;
|
||||
default:
|
||||
super.handleMessage(msg);
|
||||
case MSG_ACCOUNT_SIZE_CHANGED:
|
||||
{
|
||||
AccountSizeChangedHolder holder = (AccountSizeChangedHolder)msg.obj;
|
||||
Account account = holder.account;
|
||||
Long oldSize = holder.oldSize;
|
||||
Long newSize = holder.newSize;
|
||||
String toastText = getString(R.string.account_size_changed, account.getDescription(),
|
||||
SizeFormatter.formatSize(getApplication(), oldSize), SizeFormatter.formatSize(getApplication(), newSize));;
|
||||
|
||||
Toast toast = Toast.makeText(getApplication(), toastText, Toast.LENGTH_LONG);
|
||||
toast.show();
|
||||
break;
|
||||
}
|
||||
case MSG_FOLDER_SYNCING:
|
||||
{
|
||||
String folderName = (String)((Object[]) msg.obj)[0];
|
||||
String dispString;
|
||||
dispString = getString(R.string.accounts_title);
|
||||
if (folderName != null)
|
||||
{
|
||||
dispString += " (" + getString(R.string.status_loading)
|
||||
+ folderName + ")";
|
||||
}
|
||||
setTitle(dispString);
|
||||
break;
|
||||
}
|
||||
case MSG_PROGRESS:
|
||||
setProgressBarIndeterminateVisibility(msg.arg1 != 0);
|
||||
//setProgressBarVisibility(msg.arg1 != 0);
|
||||
break;
|
||||
case MSG_DEFINITE_PROGRESS:
|
||||
getWindow().setFeatureInt(Window.FEATURE_PROGRESS, msg.arg1);
|
||||
break;
|
||||
default:
|
||||
super.handleMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public void dataChanged() {
|
||||
public void dataChanged()
|
||||
{
|
||||
sendEmptyMessage(DATA_CHANGED);
|
||||
}
|
||||
|
||||
public void workingAccount(Account account, int res) {
|
||||
public void workingAccount(Account account, int res)
|
||||
{
|
||||
android.os.Message msg = new android.os.Message();
|
||||
msg.what = MSG_WORKING_ACCOUNT;
|
||||
msg.obj = account;
|
||||
|
@ -142,7 +154,8 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
sendMessage(msg);
|
||||
}
|
||||
|
||||
public void accountSizeChanged(Account account, long oldSize, long newSize) {
|
||||
public void accountSizeChanged(Account account, long oldSize, long newSize)
|
||||
{
|
||||
android.os.Message msg = new android.os.Message();
|
||||
msg.what = MSG_ACCOUNT_SIZE_CHANGED;
|
||||
AccountSizeChangedHolder holder = new AccountSizeChangedHolder();
|
||||
|
@ -153,19 +166,22 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
sendMessage(msg);
|
||||
}
|
||||
|
||||
public void progress(boolean progress) {
|
||||
public void progress(boolean progress)
|
||||
{
|
||||
android.os.Message msg = new android.os.Message();
|
||||
msg.what = MSG_PROGRESS;
|
||||
msg.arg1 = progress ? 1 : 0;
|
||||
sendMessage(msg);
|
||||
}
|
||||
public void progress(int progress) {
|
||||
public void progress(int progress)
|
||||
{
|
||||
android.os.Message msg = new android.os.Message();
|
||||
msg.what = MSG_DEFINITE_PROGRESS;
|
||||
msg.arg1 = progress ;
|
||||
sendMessage(msg);
|
||||
}
|
||||
public void folderSyncing(String folder) {
|
||||
public void folderSyncing(String folder)
|
||||
{
|
||||
android.os.Message msg = new android.os.Message();
|
||||
msg.what = MSG_FOLDER_SYNCING;
|
||||
msg.obj = new String[] { folder };
|
||||
|
@ -174,24 +190,30 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
|
||||
}
|
||||
|
||||
MessagingListener mListener = new MessagingListener() {
|
||||
MessagingListener mListener = new MessagingListener()
|
||||
{
|
||||
@Override
|
||||
public void accountStatusChanged(Account account, int unreadMessageCount) {
|
||||
public void accountStatusChanged(Account account, int unreadMessageCount)
|
||||
{
|
||||
unreadMessageCounts.put(account.getUuid(), unreadMessageCount);
|
||||
mHandler.dataChanged();
|
||||
pendingWork.remove(account);
|
||||
|
||||
|
||||
if (pendingWork.isEmpty()) {
|
||||
if (pendingWork.isEmpty())
|
||||
{
|
||||
mHandler.progress(Window.PROGRESS_END);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
int level = (Window.PROGRESS_END / mAdapter.getCount()) * (mAdapter.getCount() - pendingWork.size()) ;
|
||||
mHandler.progress(level);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accountSizeChanged(Account account, long oldSize, long newSize) {
|
||||
public void accountSizeChanged(Account account, long oldSize, long newSize)
|
||||
{
|
||||
|
||||
mHandler.accountSizeChanged(account, oldSize, newSize);
|
||||
|
||||
|
@ -202,7 +224,8 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
Account account,
|
||||
String folder,
|
||||
int totalMessagesInMailbox,
|
||||
int numNewMessages) {
|
||||
int numNewMessages)
|
||||
{
|
||||
MessagingController.getInstance(getApplication()).getAccountUnreadCount(Accounts.this, account, mListener);
|
||||
|
||||
mHandler.progress(false);
|
||||
|
@ -210,7 +233,8 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
}
|
||||
|
||||
@Override
|
||||
public void synchronizeMailboxStarted(Account account, String folder) {
|
||||
public void synchronizeMailboxStarted(Account account, String folder)
|
||||
{
|
||||
mHandler.progress(true);
|
||||
mHandler.folderSyncing(account.getDescription()
|
||||
+ getString(R.string.notification_bg_title_separator) + folder);
|
||||
|
@ -218,7 +242,8 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
|
||||
@Override
|
||||
public void synchronizeMailboxFailed(Account account, String folder,
|
||||
String message) {
|
||||
String message)
|
||||
{
|
||||
mHandler.progress(false);
|
||||
mHandler.folderSyncing(null);
|
||||
}
|
||||
|
@ -231,13 +256,15 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
public static final String EXTRA_STARTUP = "startup";
|
||||
|
||||
|
||||
public static void actionLaunch(Context context) {
|
||||
public static void actionLaunch(Context context)
|
||||
{
|
||||
Intent intent = new Intent(context, Accounts.class);
|
||||
intent.putExtra(EXTRA_STARTUP, true);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
public static void listAccounts(Context context) {
|
||||
public static void listAccounts(Context context)
|
||||
{
|
||||
Intent intent = new Intent(context, Accounts.class);
|
||||
intent.putExtra(EXTRA_STARTUP, false);
|
||||
context.startActivity(intent);
|
||||
|
@ -245,16 +272,20 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
public void onCreate(Bundle icicle)
|
||||
{
|
||||
super.onCreate(icicle);
|
||||
|
||||
Account[] accounts = Preferences.getPreferences(this).getAccounts();
|
||||
Intent intent = getIntent();
|
||||
boolean startup = (boolean)intent.getBooleanExtra(EXTRA_STARTUP, false);
|
||||
if (startup && accounts.length == 1) {
|
||||
if (startup && accounts.length == 1)
|
||||
{
|
||||
FolderList.actionHandleAccount(this, accounts[0], accounts[0].getAutoExpandFolderName());
|
||||
finish();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
||||
requestWindowFeature(Window.FEATURE_PROGRESS);
|
||||
|
||||
|
@ -266,13 +297,16 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
findViewById(R.id.next).setOnClickListener(this);
|
||||
registerForContextMenu(listView);
|
||||
|
||||
if (icicle != null && icicle.containsKey(SELECTED_CONTEXT_ACCOUNT)) {
|
||||
if (icicle != null && icicle.containsKey(SELECTED_CONTEXT_ACCOUNT))
|
||||
{
|
||||
mSelectedContextAccount = (Account) icicle.getSerializable("selectedContextAccount");
|
||||
}
|
||||
|
||||
if (icicle != null) {
|
||||
if (icicle != null)
|
||||
{
|
||||
Map<String, Integer> oldUnreadMessageCounts = (Map<String, Integer>)icicle.get(UNREAD_MESSAGE_COUNTS);
|
||||
if (oldUnreadMessageCounts != null) {
|
||||
if (oldUnreadMessageCounts != null)
|
||||
{
|
||||
unreadMessageCounts.putAll(oldUnreadMessageCounts);
|
||||
}
|
||||
}
|
||||
|
@ -280,16 +314,19 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
public void onSaveInstanceState(Bundle outState)
|
||||
{
|
||||
super.onSaveInstanceState(outState);
|
||||
if (mSelectedContextAccount != null) {
|
||||
if (mSelectedContextAccount != null)
|
||||
{
|
||||
outState.putSerializable(SELECTED_CONTEXT_ACCOUNT, mSelectedContextAccount);
|
||||
}
|
||||
outState.putSerializable(UNREAD_MESSAGE_COUNTS, unreadMessageCounts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
|
||||
refresh();
|
||||
|
@ -297,108 +334,136 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
public void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
MessagingController.getInstance(getApplication()).removeListener(mListener);
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
private void refresh()
|
||||
{
|
||||
Account[] accounts = Preferences.getPreferences(this).getAccounts();
|
||||
mAdapter = new AccountsAdapter(accounts);
|
||||
getListView().setAdapter(mAdapter);
|
||||
if (accounts.length > 0) {
|
||||
if (accounts.length > 0)
|
||||
{
|
||||
mHandler.progress(Window.PROGRESS_START);
|
||||
}
|
||||
pendingWork.clear();
|
||||
for (Account account : accounts) {
|
||||
for (Account account : accounts)
|
||||
{
|
||||
pendingWork.put(account, "true");
|
||||
MessagingController.getInstance(getApplication()).getAccountUnreadCount(Accounts.this, account, mListener);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void onAddNewAccount() {
|
||||
private void onAddNewAccount()
|
||||
{
|
||||
AccountSetupBasics.actionNewAccount(this);
|
||||
}
|
||||
|
||||
private void onEditAccount(Account account) {
|
||||
private void onEditAccount(Account account)
|
||||
{
|
||||
AccountSettings.actionSettings(this, account);
|
||||
}
|
||||
|
||||
private void onEditPrefs() {
|
||||
private void onEditPrefs()
|
||||
{
|
||||
Prefs.actionPrefs(this);
|
||||
}
|
||||
|
||||
|
||||
private void onCheckMail(Account account) {
|
||||
private void onCheckMail(Account account)
|
||||
{
|
||||
MessagingController.getInstance(getApplication()).checkMail(this, account, true, true, null);
|
||||
}
|
||||
|
||||
private void onClearCommands(Account account) {
|
||||
private void onClearCommands(Account account)
|
||||
{
|
||||
MessagingController.getInstance(getApplication()).clearAllPending(account);
|
||||
}
|
||||
|
||||
private void onEmptyTrash(Account account) {
|
||||
private void onEmptyTrash(Account account)
|
||||
{
|
||||
MessagingController.getInstance(getApplication()).emptyTrash(account, null);
|
||||
}
|
||||
|
||||
|
||||
private void onCompose() {
|
||||
private void onCompose()
|
||||
{
|
||||
Account defaultAccount = Preferences.getPreferences(this).getDefaultAccount();
|
||||
if (defaultAccount != null) {
|
||||
if (defaultAccount != null)
|
||||
{
|
||||
MessageCompose.actionCompose(this, defaultAccount);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
onAddNewAccount();
|
||||
}
|
||||
}
|
||||
|
||||
private void onOpenAccount(Account account) {
|
||||
private void onOpenAccount(Account account)
|
||||
{
|
||||
FolderList.actionHandleAccount(this, account, true);
|
||||
}
|
||||
|
||||
public void onClick(View view) {
|
||||
if (view.getId() == R.id.next) {
|
||||
public void onClick(View view)
|
||||
{
|
||||
if (view.getId() == R.id.next)
|
||||
{
|
||||
onAddNewAccount();
|
||||
}
|
||||
}
|
||||
|
||||
private void onDeleteAccount(Account account) {
|
||||
private void onDeleteAccount(Account account)
|
||||
{
|
||||
mSelectedContextAccount = account;
|
||||
showDialog(DIALOG_REMOVE_ACCOUNT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(int id) {
|
||||
switch (id) {
|
||||
case DIALOG_REMOVE_ACCOUNT:
|
||||
return createRemoveAccountDialog();
|
||||
public Dialog onCreateDialog(int id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case DIALOG_REMOVE_ACCOUNT:
|
||||
return createRemoveAccountDialog();
|
||||
}
|
||||
return super.onCreateDialog(id);
|
||||
}
|
||||
|
||||
public void onPrepareDialog(int id, Dialog d) {
|
||||
switch (id) {
|
||||
case DIALOG_REMOVE_ACCOUNT:
|
||||
AlertDialog alert = (AlertDialog) d;
|
||||
alert.setMessage(getString(R.string.account_delete_dlg_instructions_fmt,
|
||||
mSelectedContextAccount.getDescription()));
|
||||
break;
|
||||
public void onPrepareDialog(int id, Dialog d)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case DIALOG_REMOVE_ACCOUNT:
|
||||
AlertDialog alert = (AlertDialog) d;
|
||||
alert.setMessage(getString(R.string.account_delete_dlg_instructions_fmt,
|
||||
mSelectedContextAccount.getDescription()));
|
||||
break;
|
||||
}
|
||||
|
||||
super.onPrepareDialog(id, d);
|
||||
}
|
||||
|
||||
|
||||
private Dialog createRemoveAccountDialog() {
|
||||
private Dialog createRemoveAccountDialog()
|
||||
{
|
||||
return new AlertDialog.Builder(this)
|
||||
.setTitle(R.string.account_delete_dlg_title)
|
||||
.setMessage(getString(R.string.account_delete_dlg_instructions_fmt, mSelectedContextAccount.getDescription()))
|
||||
.setPositiveButton(R.string.okay_action, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
.setPositiveButton(R.string.okay_action, new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int whichButton)
|
||||
{
|
||||
dismissDialog(DIALOG_REMOVE_ACCOUNT);
|
||||
try {
|
||||
((LocalStore)Store.getInstance( mSelectedContextAccount.getLocalStoreUri(), getApplication())).delete();
|
||||
} catch (Exception e) {
|
||||
try
|
||||
{
|
||||
((LocalStore)Store.getInstance(mSelectedContextAccount.getLocalStoreUri(), getApplication())).delete();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
mSelectedContextAccount.delete(Preferences.getPreferences(Accounts.this));
|
||||
|
@ -406,90 +471,100 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
refresh();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel_action, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
.setNegativeButton(R.string.cancel_action, new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int whichButton)
|
||||
{
|
||||
dismissDialog(DIALOG_REMOVE_ACCOUNT);
|
||||
}
|
||||
})
|
||||
.create();
|
||||
}
|
||||
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
public boolean onContextItemSelected(MenuItem item)
|
||||
{
|
||||
AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo)item.getMenuInfo();
|
||||
Account account = (Account)getListView().getItemAtPosition(menuInfo.position);
|
||||
switch (item.getItemId()) {
|
||||
case R.id.edit_prefs:
|
||||
onEditPrefs();
|
||||
break;
|
||||
case R.id.delete_account:
|
||||
onDeleteAccount(account);
|
||||
break;
|
||||
case R.id.edit_account:
|
||||
onEditAccount(account);
|
||||
break;
|
||||
case R.id.open:
|
||||
onOpenAccount(account);
|
||||
break;
|
||||
case R.id.check_mail:
|
||||
onCheckMail(account);
|
||||
break;
|
||||
case R.id.clear_pending:
|
||||
onClearCommands(account);
|
||||
break;
|
||||
case R.id.empty_trash:
|
||||
onEmptyTrash(account);
|
||||
break;
|
||||
case R.id.compact:
|
||||
onCompact(account);
|
||||
break;
|
||||
case R.id.clear:
|
||||
onClear(account);
|
||||
break;
|
||||
switch (item.getItemId())
|
||||
{
|
||||
case R.id.edit_prefs:
|
||||
onEditPrefs();
|
||||
break;
|
||||
case R.id.delete_account:
|
||||
onDeleteAccount(account);
|
||||
break;
|
||||
case R.id.edit_account:
|
||||
onEditAccount(account);
|
||||
break;
|
||||
case R.id.open:
|
||||
onOpenAccount(account);
|
||||
break;
|
||||
case R.id.check_mail:
|
||||
onCheckMail(account);
|
||||
break;
|
||||
case R.id.clear_pending:
|
||||
onClearCommands(account);
|
||||
break;
|
||||
case R.id.empty_trash:
|
||||
onEmptyTrash(account);
|
||||
break;
|
||||
case R.id.compact:
|
||||
onCompact(account);
|
||||
break;
|
||||
case R.id.clear:
|
||||
onClear(account);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onCompact(Account account) {
|
||||
private void onCompact(Account account)
|
||||
{
|
||||
mHandler.workingAccount(account, R.string.compacting_account);
|
||||
MessagingController.getInstance(getApplication()).compact(account, null);
|
||||
}
|
||||
|
||||
private void onClear(Account account) {
|
||||
private void onClear(Account account)
|
||||
{
|
||||
mHandler.workingAccount(account, R.string.clearing_account);
|
||||
MessagingController.getInstance(getApplication()).clear(account, null);
|
||||
}
|
||||
|
||||
|
||||
public void onItemClick(AdapterView parent, View view, int position, long id) {
|
||||
public void onItemClick(AdapterView parent, View view, int position, long id)
|
||||
{
|
||||
Account account = (Account)parent.getItemAtPosition(position);
|
||||
onOpenAccount(account);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.add_new_account:
|
||||
onAddNewAccount();
|
||||
break;
|
||||
case R.id.edit_prefs:
|
||||
onEditPrefs();
|
||||
break;
|
||||
case R.id.check_mail:
|
||||
onCheckMail(null);
|
||||
break;
|
||||
case R.id.compose:
|
||||
onCompose();
|
||||
break;
|
||||
case R.id.about:
|
||||
onAbout();
|
||||
break;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
switch (item.getItemId())
|
||||
{
|
||||
case R.id.add_new_account:
|
||||
onAddNewAccount();
|
||||
break;
|
||||
case R.id.edit_prefs:
|
||||
onEditPrefs();
|
||||
break;
|
||||
case R.id.check_mail:
|
||||
onCheckMail(null);
|
||||
break;
|
||||
case R.id.compose:
|
||||
onCompose();
|
||||
break;
|
||||
case R.id.about:
|
||||
onAbout();
|
||||
break;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onAbout() {
|
||||
private void onAbout()
|
||||
{
|
||||
String appName = getString(R.string.app_name);
|
||||
WebView wv = new WebView(this);
|
||||
String html = "<h1>" + String.format(getString(R.string.about_title_fmt).toString(),
|
||||
|
@ -506,8 +581,10 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
new AlertDialog.Builder(this)
|
||||
.setView(wv)
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(R.string.okay_action, new DialogInterface.OnClickListener () {
|
||||
public void onClick(DialogInterface d, int c) {
|
||||
.setPositiveButton(R.string.okay_action, new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface d, int c)
|
||||
{
|
||||
d.dismiss();
|
||||
}
|
||||
})
|
||||
|
@ -519,57 +596,72 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
*
|
||||
* @return String version
|
||||
*/
|
||||
private String getVersionNumber() {
|
||||
private String getVersionNumber()
|
||||
{
|
||||
String version = "?";
|
||||
try {
|
||||
try
|
||||
{
|
||||
PackageInfo pi = getPackageManager().getPackageInfo(getPackageName(), 0);
|
||||
version = pi.versionName;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
}
|
||||
catch (PackageManager.NameNotFoundException e)
|
||||
{
|
||||
//Log.e(TAG, "Package name not found", e);
|
||||
};
|
||||
return version;
|
||||
}
|
||||
|
||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
public boolean onCreateOptionsMenu(Menu menu)
|
||||
{
|
||||
super.onCreateOptionsMenu(menu);
|
||||
getMenuInflater().inflate(R.menu.accounts_option, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
|
||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)
|
||||
{
|
||||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
menu.setHeaderTitle(R.string.accounts_context_menu_title);
|
||||
getMenuInflater().inflate(R.menu.accounts_context, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event)
|
||||
{
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
|
||||
class AccountsAdapter extends ArrayAdapter<Account> {
|
||||
public AccountsAdapter(Account[] accounts) {
|
||||
class AccountsAdapter extends ArrayAdapter<Account>
|
||||
{
|
||||
public AccountsAdapter(Account[] accounts)
|
||||
{
|
||||
super(Accounts.this, 0, accounts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
public View getView(int position, View convertView, ViewGroup parent)
|
||||
{
|
||||
Account account = getItem(position);
|
||||
View view;
|
||||
if (convertView != null) {
|
||||
if (convertView != null)
|
||||
{
|
||||
view = convertView;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
view = getLayoutInflater().inflate(R.layout.accounts_item, parent, false);
|
||||
}
|
||||
AccountViewHolder holder = (AccountViewHolder) view.getTag();
|
||||
if (holder == null) {
|
||||
if (holder == null)
|
||||
{
|
||||
holder = new AccountViewHolder();
|
||||
holder.description = (TextView) view.findViewById(R.id.description);
|
||||
holder.email = (TextView) view.findViewById(R.id.email);
|
||||
|
@ -578,15 +670,19 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
}
|
||||
holder.description.setText(account.getDescription());
|
||||
holder.email.setText(account.getEmail());
|
||||
if (account.getEmail().equals(account.getDescription())) {
|
||||
if (account.getEmail().equals(account.getDescription()))
|
||||
{
|
||||
holder.email.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
Integer unreadMessageCount = unreadMessageCounts.get(account.getUuid());
|
||||
if (unreadMessageCount != null) {
|
||||
if (unreadMessageCount != null)
|
||||
{
|
||||
holder.newMessageCount.setText(Integer.toString(unreadMessageCount));
|
||||
holder.newMessageCount.setVisibility(unreadMessageCount > 0 ? View.VISIBLE : View.GONE);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
//holder.newMessageCount.setText("-");
|
||||
holder.newMessageCount.setVisibility(View.GONE);
|
||||
}
|
||||
|
@ -594,7 +690,8 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||
return view;
|
||||
}
|
||||
|
||||
class AccountViewHolder {
|
||||
class AccountViewHolder
|
||||
{
|
||||
public TextView description;
|
||||
public TextView email;
|
||||
public TextView newMessageCount;
|
||||
|
|
|
@ -27,7 +27,8 @@ import com.android.email.R;
|
|||
import com.android.email.mail.Folder;
|
||||
import com.android.email.mail.MessagingException;
|
||||
|
||||
public class ChooseFolder extends K9ListActivity {
|
||||
public class ChooseFolder extends K9ListActivity
|
||||
{
|
||||
String mFolder;
|
||||
Account mAccount;
|
||||
String mUID;
|
||||
|
@ -47,7 +48,8 @@ public class ChooseFolder extends K9ListActivity {
|
|||
public static final String EXTRA_SHOW_DISPLAYABLE_ONLY = "com.android.email.ChooseFolder_showDisplayableOnly";
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
||||
|
@ -59,13 +61,16 @@ public class ChooseFolder extends K9ListActivity {
|
|||
mAccount = (Account) intent.getSerializableExtra(EXTRA_ACCOUNT);
|
||||
mUID = intent.getStringExtra(EXTRA_MESSAGE_UID);
|
||||
mFolder = intent.getStringExtra(EXTRA_CUR_FOLDER);
|
||||
if (intent.getStringExtra(EXTRA_SHOW_CURRENT) != null) {
|
||||
if (intent.getStringExtra(EXTRA_SHOW_CURRENT) != null)
|
||||
{
|
||||
hideCurrentFolder = false;
|
||||
}
|
||||
if (intent.getStringExtra(EXTRA_SHOW_FOLDER_NONE) != null) {
|
||||
if (intent.getStringExtra(EXTRA_SHOW_FOLDER_NONE) != null)
|
||||
{
|
||||
showOptionNone = true;
|
||||
}
|
||||
if (intent.getStringExtra(EXTRA_SHOW_DISPLAYABLE_ONLY) != null) {
|
||||
if (intent.getStringExtra(EXTRA_SHOW_DISPLAYABLE_ONLY) != null)
|
||||
{
|
||||
showDisplayableOnly = true;
|
||||
}
|
||||
if (mFolder == null)
|
||||
|
@ -80,12 +85,15 @@ public class ChooseFolder extends K9ListActivity {
|
|||
false, mListener);
|
||||
|
||||
|
||||
this.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
public void onItemClick(AdapterView adapterview, View view, int i, long l) {
|
||||
this.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener()
|
||||
{
|
||||
public void onItemClick(AdapterView adapterview, View view, int i, long l)
|
||||
{
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(EXTRA_CUR_FOLDER, mFolder);
|
||||
String destFolderName = (String)((TextView)view).getText();
|
||||
if (heldInbox != null && getString(R.string.special_mailbox_name_inbox).equals(destFolderName)) {
|
||||
if (heldInbox != null && getString(R.string.special_mailbox_name_inbox).equals(destFolderName))
|
||||
{
|
||||
destFolderName = heldInbox;
|
||||
}
|
||||
intent.putExtra(EXTRA_NEW_FOLDER, destFolderName);
|
||||
|
@ -97,93 +105,114 @@ public class ChooseFolder extends K9ListActivity {
|
|||
|
||||
}
|
||||
|
||||
class ChooseFolderHandler extends Handler {
|
||||
class ChooseFolderHandler extends Handler
|
||||
{
|
||||
|
||||
private static final int MSG_PROGRESS = 2;
|
||||
|
||||
private static final int MSG_DATA_CHANGED = 3;
|
||||
private static final int MSG_SET_SELECTED_FOLDER = 4;
|
||||
|
||||
public void handleMessage(android.os.Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_PROGRESS:
|
||||
setProgressBarIndeterminateVisibility(msg.arg1 != 0);
|
||||
break;
|
||||
case MSG_DATA_CHANGED:
|
||||
adapter.notifyDataSetChanged();
|
||||
break;
|
||||
case MSG_SET_SELECTED_FOLDER:
|
||||
// TODO: I want this to highlight the chosen folder, but this doesn't work.
|
||||
public void handleMessage(android.os.Message msg)
|
||||
{
|
||||
switch (msg.what)
|
||||
{
|
||||
case MSG_PROGRESS:
|
||||
setProgressBarIndeterminateVisibility(msg.arg1 != 0);
|
||||
break;
|
||||
case MSG_DATA_CHANGED:
|
||||
adapter.notifyDataSetChanged();
|
||||
break;
|
||||
case MSG_SET_SELECTED_FOLDER:
|
||||
// TODO: I want this to highlight the chosen folder, but this doesn't work.
|
||||
// getListView().setSelection(msg.arg1);
|
||||
// getListView().setItemChecked(msg.arg1, true);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void progress(boolean progress) {
|
||||
public void progress(boolean progress)
|
||||
{
|
||||
android.os.Message msg = new android.os.Message();
|
||||
msg.what = MSG_PROGRESS;
|
||||
msg.arg1 = progress ? 1 : 0;
|
||||
sendMessage(msg);
|
||||
}
|
||||
|
||||
public void setSelectedFolder(int position) {
|
||||
public void setSelectedFolder(int position)
|
||||
{
|
||||
android.os.Message msg = new android.os.Message();
|
||||
msg.what = MSG_SET_SELECTED_FOLDER;
|
||||
msg.arg1 = position;
|
||||
sendMessage(msg);
|
||||
}
|
||||
|
||||
public void dataChanged() {
|
||||
public void dataChanged()
|
||||
{
|
||||
sendEmptyMessage(MSG_DATA_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
private MessagingListener mListener = new MessagingListener() {
|
||||
public void listFoldersStarted(Account account) {
|
||||
if (!account.equals(mAccount)) {
|
||||
private MessagingListener mListener = new MessagingListener()
|
||||
{
|
||||
public void listFoldersStarted(Account account)
|
||||
{
|
||||
if (!account.equals(mAccount))
|
||||
{
|
||||
return;
|
||||
}
|
||||
mHandler.progress(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void listFoldersFailed(Account account, String message) {
|
||||
if (!account.equals(mAccount)) {
|
||||
public void listFoldersFailed(Account account, String message)
|
||||
{
|
||||
if (!account.equals(mAccount))
|
||||
{
|
||||
return;
|
||||
}
|
||||
mHandler.progress(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void listFoldersFinished(Account account) {
|
||||
if (!account.equals(mAccount)) {
|
||||
public void listFoldersFinished(Account account)
|
||||
{
|
||||
if (!account.equals(mAccount))
|
||||
{
|
||||
return;
|
||||
}
|
||||
mHandler.progress(false);
|
||||
}
|
||||
@Override
|
||||
public void listFolders(Account account, Folder[] folders) {
|
||||
if (!account.equals(mAccount)) {
|
||||
public void listFolders(Account account, Folder[] folders)
|
||||
{
|
||||
if (!account.equals(mAccount))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Account.FolderMode aMode = Account.FolderMode.ALL;
|
||||
if (showDisplayableOnly) {
|
||||
if (showDisplayableOnly)
|
||||
{
|
||||
aMode = account.getFolderDisplayMode();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
aMode = account.getFolderTargetMode();
|
||||
}
|
||||
Preferences prefs = Preferences.getPreferences(getApplication().getApplicationContext());
|
||||
ArrayList<String> localFolders = new ArrayList<String>();
|
||||
|
||||
for (Folder folder : folders) {
|
||||
for (Folder folder : folders)
|
||||
{
|
||||
String name = folder.getName();
|
||||
|
||||
// Inbox needs to be compared case-insensitively
|
||||
if (hideCurrentFolder && (name.equals(mFolder) || (Email.INBOX.equalsIgnoreCase(mFolder) && Email.INBOX.equalsIgnoreCase(name)))) {
|
||||
if (hideCurrentFolder && (name.equals(mFolder) || (Email.INBOX.equalsIgnoreCase(mFolder) && Email.INBOX.equalsIgnoreCase(name))))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
try
|
||||
{
|
||||
folder.refresh(prefs);
|
||||
Folder.FolderClass fMode = folder.getDisplayClass();
|
||||
|
||||
|
@ -191,10 +220,13 @@ public class ChooseFolder extends K9ListActivity {
|
|||
|| (aMode == Account.FolderMode.FIRST_AND_SECOND_CLASS &&
|
||||
fMode != Folder.FolderClass.FIRST_CLASS &&
|
||||
fMode != Folder.FolderClass.SECOND_CLASS)
|
||||
|| (aMode == Account.FolderMode.NOT_SECOND_CLASS && fMode == Folder.FolderClass.SECOND_CLASS)) {
|
||||
|| (aMode == Account.FolderMode.NOT_SECOND_CLASS && fMode == Folder.FolderClass.SECOND_CLASS))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
} catch (MessagingException me) {
|
||||
}
|
||||
catch (MessagingException me)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Couldn't get prefs to check for displayability of folder " + folder.getName(), me);
|
||||
}
|
||||
|
||||
|
@ -202,22 +234,29 @@ public class ChooseFolder extends K9ListActivity {
|
|||
|
||||
}
|
||||
|
||||
if (showOptionNone) {
|
||||
if (showOptionNone)
|
||||
{
|
||||
localFolders.add(Email.FOLDER_NONE);
|
||||
}
|
||||
|
||||
Collections.sort(localFolders, new Comparator<String>() {
|
||||
public int compare(String aName, String bName) {
|
||||
if (Email.FOLDER_NONE.equalsIgnoreCase(aName)) {
|
||||
Collections.sort(localFolders, new Comparator<String>()
|
||||
{
|
||||
public int compare(String aName, String bName)
|
||||
{
|
||||
if (Email.FOLDER_NONE.equalsIgnoreCase(aName))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (Email.FOLDER_NONE.equalsIgnoreCase(bName)) {
|
||||
if (Email.FOLDER_NONE.equalsIgnoreCase(bName))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (Email.INBOX.equalsIgnoreCase(aName)) {
|
||||
if (Email.INBOX.equalsIgnoreCase(aName))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (Email.INBOX.equalsIgnoreCase(bName)) {
|
||||
if (Email.INBOX.equalsIgnoreCase(bName))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -228,20 +267,26 @@ public class ChooseFolder extends K9ListActivity {
|
|||
adapter.clear();
|
||||
int selectedFolder = -1;
|
||||
int position = 0;
|
||||
for (String name : localFolders) {
|
||||
if (Email.INBOX.equalsIgnoreCase(name)) {
|
||||
for (String name : localFolders)
|
||||
{
|
||||
if (Email.INBOX.equalsIgnoreCase(name))
|
||||
{
|
||||
adapter.add(getString(R.string.special_mailbox_name_inbox));
|
||||
heldInbox = name;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
adapter.add(name);
|
||||
}
|
||||
|
||||
if ((name.equals(mFolder) || (Email.INBOX.equalsIgnoreCase(mFolder) && Email.INBOX.equalsIgnoreCase(name)))) {
|
||||
if ((name.equals(mFolder) || (Email.INBOX.equalsIgnoreCase(mFolder) && Email.INBOX.equalsIgnoreCase(name))))
|
||||
{
|
||||
selectedFolder = position;
|
||||
}
|
||||
position++;
|
||||
}
|
||||
if (selectedFolder != -1) {
|
||||
if (selectedFolder != -1)
|
||||
{
|
||||
mHandler.setSelectedFolder(selectedFolder);
|
||||
}
|
||||
mHandler.dataChanged();
|
||||
|
|
|
@ -19,7 +19,8 @@ import com.android.email.K9ListActivity;
|
|||
import com.android.email.Preferences;
|
||||
import com.android.email.R;
|
||||
|
||||
public class ChooseIdentity extends K9ListActivity {
|
||||
public class ChooseIdentity extends K9ListActivity
|
||||
{
|
||||
Account mAccount;
|
||||
String mUID;
|
||||
ArrayAdapter<String> adapter;
|
||||
|
@ -31,7 +32,8 @@ public class ChooseIdentity extends K9ListActivity {
|
|||
protected List<Account.Identity> identities = null;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
||||
|
@ -50,20 +52,24 @@ public class ChooseIdentity extends K9ListActivity {
|
|||
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
refreshView();
|
||||
}
|
||||
|
||||
|
||||
protected void refreshView() {
|
||||
protected void refreshView()
|
||||
{
|
||||
adapter.clear();
|
||||
|
||||
identities = mAccount.getIdentities();
|
||||
for (Account.Identity identity : identities) {
|
||||
for (Account.Identity identity : identities)
|
||||
{
|
||||
String email = identity.getEmail();
|
||||
String description = identity.getDescription();
|
||||
if (description == null || description.trim().length() == 0) {
|
||||
if (description == null || description.trim().length() == 0)
|
||||
{
|
||||
description = getString(R.string.message_view_from_format, identity.getName(), identity.getEmail());
|
||||
}
|
||||
adapter.add(description);
|
||||
|
@ -71,18 +77,24 @@ public class ChooseIdentity extends K9ListActivity {
|
|||
|
||||
}
|
||||
|
||||
protected void setupClickListeners() {
|
||||
this.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
public void onItemClick(AdapterView adapterview, View view, int i, long l) {
|
||||
protected void setupClickListeners()
|
||||
{
|
||||
this.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener()
|
||||
{
|
||||
public void onItemClick(AdapterView adapterview, View view, int i, long l)
|
||||
{
|
||||
Account.Identity identity = mAccount.getIdentity(i);
|
||||
String email = identity.getEmail();
|
||||
if (email != null && email.trim().equals("") == false) {
|
||||
if (email != null && email.trim().equals("") == false)
|
||||
{
|
||||
Intent intent = new Intent();
|
||||
|
||||
intent.putExtra(EXTRA_IDENTITY, mAccount.getIdentity(i));
|
||||
setResult(RESULT_OK, intent);
|
||||
finish();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.makeText(ChooseIdentity.this, getString(R.string.identity_has_no_email),
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
@ -91,30 +103,35 @@ public class ChooseIdentity extends K9ListActivity {
|
|||
|
||||
}
|
||||
|
||||
class ChooseIdentityHandler extends Handler {
|
||||
class ChooseIdentityHandler extends Handler
|
||||
{
|
||||
|
||||
private static final int MSG_PROGRESS = 2;
|
||||
private static final int MSG_DATA_CHANGED = 3;
|
||||
|
||||
public void handleMessage(android.os.Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_PROGRESS:
|
||||
setProgressBarIndeterminateVisibility(msg.arg1 != 0);
|
||||
break;
|
||||
case MSG_DATA_CHANGED:
|
||||
adapter.notifyDataSetChanged();
|
||||
break;
|
||||
public void handleMessage(android.os.Message msg)
|
||||
{
|
||||
switch (msg.what)
|
||||
{
|
||||
case MSG_PROGRESS:
|
||||
setProgressBarIndeterminateVisibility(msg.arg1 != 0);
|
||||
break;
|
||||
case MSG_DATA_CHANGED:
|
||||
adapter.notifyDataSetChanged();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void progress(boolean progress) {
|
||||
public void progress(boolean progress)
|
||||
{
|
||||
android.os.Message msg = new android.os.Message();
|
||||
msg.what = MSG_PROGRESS;
|
||||
msg.arg1 = progress ? 1 : 0;
|
||||
sendMessage(msg);
|
||||
}
|
||||
|
||||
public void dataChanged() {
|
||||
public void dataChanged()
|
||||
{
|
||||
sendEmptyMessage(MSG_DATA_CHANGED);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@ import android.os.Bundle;
|
|||
import android.view.KeyEvent;
|
||||
import android.widget.EditText;
|
||||
|
||||
public class EditIdentity extends K9Activity {
|
||||
public class EditIdentity extends K9Activity
|
||||
{
|
||||
|
||||
public static final String EXTRA_IDENTITY = "com.android.email.EditIdentity_identity";
|
||||
public static final String EXTRA_IDENTITY_INDEX = "com.android.email.EditIdentity_identity_index";
|
||||
|
@ -29,14 +30,16 @@ public class EditIdentity extends K9Activity {
|
|||
private EditText mNameView;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mIdentity = (Account.Identity)getIntent().getSerializableExtra(EXTRA_IDENTITY);
|
||||
mIdentityIndex = getIntent().getIntExtra(EXTRA_IDENTITY_INDEX, -1);
|
||||
mAccount = (Account) getIntent().getSerializableExtra(EXTRA_ACCOUNT);
|
||||
|
||||
if (mIdentityIndex == -1) {
|
||||
if (mIdentityIndex == -1)
|
||||
{
|
||||
mIdentity = mAccount.new Identity();
|
||||
}
|
||||
|
||||
|
@ -46,7 +49,8 @@ public class EditIdentity extends K9Activity {
|
|||
* If we're being reloaded we override the original account with the one
|
||||
* we saved
|
||||
*/
|
||||
if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_IDENTITY)) {
|
||||
if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_IDENTITY))
|
||||
{
|
||||
mIdentity = (Account.Identity)savedInstanceState.getSerializable(EXTRA_IDENTITY);
|
||||
}
|
||||
|
||||
|
@ -67,11 +71,13 @@ public class EditIdentity extends K9Activity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
private void saveIdentity() {
|
||||
private void saveIdentity()
|
||||
{
|
||||
|
||||
mIdentity.setDescription(mDescriptionView.getText().toString());
|
||||
mIdentity.setEmail(mEmailView.getText().toString());
|
||||
|
@ -80,9 +86,12 @@ public class EditIdentity extends K9Activity {
|
|||
mIdentity.setSignature(mSignatureView.getText().toString());
|
||||
|
||||
List<Account.Identity> identities = mAccount.getIdentities();
|
||||
if (mIdentityIndex == -1) {
|
||||
if (mIdentityIndex == -1)
|
||||
{
|
||||
identities.add(mIdentity);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
identities.remove(mIdentityIndex);
|
||||
identities.add(mIdentityIndex, mIdentity);
|
||||
}
|
||||
|
@ -93,8 +102,10 @@ public class EditIdentity extends K9Activity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event)
|
||||
{
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK)
|
||||
{
|
||||
saveIdentity();
|
||||
return true;
|
||||
}
|
||||
|
@ -102,7 +113,8 @@ public class EditIdentity extends K9Activity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
public void onSaveInstanceState(Bundle outState)
|
||||
{
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putSerializable(EXTRA_IDENTITY, mIdentity);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -16,14 +16,18 @@ import com.android.email.Account;
|
|||
import com.android.email.Preferences;
|
||||
import com.android.email.R;
|
||||
|
||||
public class ManageIdentities extends ChooseIdentity {
|
||||
public class ManageIdentities extends ChooseIdentity
|
||||
{
|
||||
private boolean mIdentitiesChanged = false;
|
||||
public static final String EXTRA_IDENTITIES = "com.android.email.EditIdentity_identities";
|
||||
|
||||
private static final int ACTIVITY_EDIT_IDENTITY = 1;
|
||||
protected void setupClickListeners() {
|
||||
this.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
public void onItemClick(AdapterView adapterview, View view, int i, long l) {
|
||||
protected void setupClickListeners()
|
||||
{
|
||||
this.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener()
|
||||
{
|
||||
public void onItemClick(AdapterView adapterview, View view, int i, long l)
|
||||
{
|
||||
editItem(i);
|
||||
}
|
||||
});
|
||||
|
@ -32,7 +36,8 @@ public class ManageIdentities extends ChooseIdentity {
|
|||
registerForContextMenu(listView);
|
||||
}
|
||||
|
||||
private void editItem(int i) {
|
||||
private void editItem(int i)
|
||||
{
|
||||
Intent intent = new Intent(ManageIdentities.this, EditIdentity.class);
|
||||
|
||||
intent.putExtra(EditIdentity.EXTRA_ACCOUNT, mAccount);
|
||||
|
@ -42,80 +47,92 @@ public class ManageIdentities extends ChooseIdentity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
public boolean onCreateOptionsMenu(Menu menu)
|
||||
{
|
||||
super.onCreateOptionsMenu(menu);
|
||||
getMenuInflater().inflate(R.menu.manage_identities_option, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.new_identity:
|
||||
Intent intent = new Intent(ManageIdentities.this, EditIdentity.class);
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
switch (item.getItemId())
|
||||
{
|
||||
case R.id.new_identity:
|
||||
Intent intent = new Intent(ManageIdentities.this, EditIdentity.class);
|
||||
|
||||
intent.putExtra(EditIdentity.EXTRA_ACCOUNT, mAccount);
|
||||
startActivityForResult(intent, ACTIVITY_EDIT_IDENTITY);
|
||||
break;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
intent.putExtra(EditIdentity.EXTRA_ACCOUNT, mAccount);
|
||||
startActivityForResult(intent, ACTIVITY_EDIT_IDENTITY);
|
||||
break;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
|
||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)
|
||||
{
|
||||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
menu.setHeaderTitle(R.string.manage_identities_context_menu_title);
|
||||
getMenuInflater().inflate(R.menu.manage_identities_context, menu);
|
||||
}
|
||||
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
public boolean onContextItemSelected(MenuItem item)
|
||||
{
|
||||
AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo)item.getMenuInfo();
|
||||
switch (item.getItemId()) {
|
||||
case R.id.edit:
|
||||
editItem(menuInfo.position);
|
||||
break;
|
||||
case R.id.up:
|
||||
if (menuInfo.position > 0) {
|
||||
Account.Identity identity = identities.remove(menuInfo.position);
|
||||
identities.add(menuInfo.position - 1, identity);
|
||||
mIdentitiesChanged = true;
|
||||
refreshView();
|
||||
}
|
||||
switch (item.getItemId())
|
||||
{
|
||||
case R.id.edit:
|
||||
editItem(menuInfo.position);
|
||||
break;
|
||||
case R.id.up:
|
||||
if (menuInfo.position > 0)
|
||||
{
|
||||
Account.Identity identity = identities.remove(menuInfo.position);
|
||||
identities.add(menuInfo.position - 1, identity);
|
||||
mIdentitiesChanged = true;
|
||||
refreshView();
|
||||
}
|
||||
|
||||
break;
|
||||
case R.id.down:
|
||||
if (menuInfo.position < identities.size() - 1) {
|
||||
break;
|
||||
case R.id.down:
|
||||
if (menuInfo.position < identities.size() - 1)
|
||||
{
|
||||
Account.Identity identity = identities.remove(menuInfo.position);
|
||||
identities.add(menuInfo.position + 1, identity);
|
||||
mIdentitiesChanged = true;
|
||||
refreshView();
|
||||
}
|
||||
break;
|
||||
case R.id.top:
|
||||
Account.Identity identity = identities.remove(menuInfo.position);
|
||||
identities.add(menuInfo.position + 1, identity);
|
||||
identities.add(0, identity);
|
||||
mIdentitiesChanged = true;
|
||||
refreshView();
|
||||
}
|
||||
break;
|
||||
case R.id.top:
|
||||
Account.Identity identity = identities.remove(menuInfo.position);
|
||||
identities.add(0, identity);
|
||||
mIdentitiesChanged = true;
|
||||
refreshView();
|
||||
break;
|
||||
case R.id.remove:
|
||||
if (identities.size() > 1) {
|
||||
identities.remove(menuInfo.position);
|
||||
mIdentitiesChanged = true;
|
||||
refreshView();
|
||||
} else {
|
||||
Toast.makeText(this, getString(R.string.no_removable_identity),
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case R.id.remove:
|
||||
if (identities.size() > 1)
|
||||
{
|
||||
identities.remove(menuInfo.position);
|
||||
mIdentitiesChanged = true;
|
||||
refreshView();
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.makeText(this, getString(R.string.no_removable_identity),
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
mAccount.refresh(Preferences.getPreferences(getApplication().getApplicationContext()));
|
||||
refreshView();
|
||||
|
@ -123,15 +140,19 @@ public class ManageIdentities extends ChooseIdentity {
|
|||
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event)
|
||||
{
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK)
|
||||
{
|
||||
saveIdentities();
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
private void saveIdentities() {
|
||||
if (mIdentitiesChanged) {
|
||||
private void saveIdentities()
|
||||
{
|
||||
if (mIdentitiesChanged)
|
||||
{
|
||||
mAccount.setIdentities(identities);
|
||||
mAccount.save(Preferences.getPreferences(getApplication().getApplicationContext()));
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -6,7 +6,8 @@ import android.content.Context;
|
|||
/**
|
||||
* A listener that the user can register for global, persistent progress events.
|
||||
*/
|
||||
public interface ProgressListener {
|
||||
public interface ProgressListener
|
||||
{
|
||||
/**
|
||||
* @param context
|
||||
* @param title
|
||||
|
|
|
@ -4,15 +4,20 @@ import android.content.Context;
|
|||
|
||||
import com.android.email.R;
|
||||
|
||||
public class SizeFormatter {
|
||||
public static String formatSize(Context context, long size) {
|
||||
if (size > 1024000000) {
|
||||
public class SizeFormatter
|
||||
{
|
||||
public static String formatSize(Context context, long size)
|
||||
{
|
||||
if (size > 1024000000)
|
||||
{
|
||||
return ((float)(size / 102400000) / 10) + context.getString(R.string.abbrev_gigabytes);
|
||||
}
|
||||
if (size > 1024000) {
|
||||
if (size > 1024000)
|
||||
{
|
||||
return ((float)(size / 102400) / 10) + context.getString(R.string.abbrev_megabytes);
|
||||
}
|
||||
if (size > 1024) {
|
||||
if (size > 1024)
|
||||
{
|
||||
return ((float)(size / 102) / 10) + context.getString(R.string.abbrev_kilobytes);
|
||||
}
|
||||
return size + context.getString(R.string.abbrev_bytes);
|
||||
|
|
|
@ -18,9 +18,11 @@ import android.os.Bundle;
|
|||
* If more than one account is configuref the user is takaen to the Accounts Activity so they
|
||||
* can select an account.
|
||||
*/
|
||||
public class Welcome extends K9Activity {
|
||||
public class Welcome extends K9Activity
|
||||
{
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
public void onCreate(Bundle icicle)
|
||||
{
|
||||
super.onCreate(icicle);
|
||||
|
||||
Accounts.actionLaunch(this);
|
||||
|
|
|
@ -28,7 +28,8 @@ import com.android.email.activity.ChooseIdentity;
|
|||
import com.android.email.activity.ManageIdentities;
|
||||
import com.android.email.mail.Store;
|
||||
|
||||
public class AccountSettings extends K9PreferenceActivity {
|
||||
public class AccountSettings extends K9PreferenceActivity
|
||||
{
|
||||
private static final String EXTRA_ACCOUNT = "account";
|
||||
|
||||
private static final int SELECT_AUTO_EXPAND_FOLDER = 1;
|
||||
|
@ -76,24 +77,29 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||
private ListPreference mDeletePolicy;
|
||||
private Preference mAutoExpandFolder;
|
||||
|
||||
public static void actionSettings(Context context, Account account) {
|
||||
public static void actionSettings(Context context, Account account)
|
||||
{
|
||||
Intent i = new Intent(context, AccountSettings.class);
|
||||
i.putExtra(EXTRA_ACCOUNT, account);
|
||||
context.startActivity(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mAccount = (Account)getIntent().getSerializableExtra(EXTRA_ACCOUNT);
|
||||
|
||||
boolean isPushCapable = false;
|
||||
Store store = null;
|
||||
try {
|
||||
try
|
||||
{
|
||||
store = Store.getInstance(mAccount.getStoreUri(), getApplication());
|
||||
isPushCapable = store.isPushCapable();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Could not get remote store", e);
|
||||
}
|
||||
|
||||
|
@ -105,8 +111,10 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||
mAccountDescription = (EditTextPreference) findPreference(PREFERENCE_DESCRIPTION);
|
||||
mAccountDescription.setSummary(mAccount.getDescription());
|
||||
mAccountDescription.setText(mAccount.getDescription());
|
||||
mAccountDescription.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mAccountDescription.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
|
||||
{
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue)
|
||||
{
|
||||
final String summary = newValue.toString();
|
||||
mAccountDescription.setSummary(summary);
|
||||
mAccountDescription.setText(summary);
|
||||
|
@ -118,8 +126,10 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||
mCheckFrequency = (ListPreference) findPreference(PREFERENCE_FREQUENCY);
|
||||
mCheckFrequency.setValue(String.valueOf(mAccount.getAutomaticCheckIntervalMinutes()));
|
||||
mCheckFrequency.setSummary(mCheckFrequency.getEntry());
|
||||
mCheckFrequency.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mCheckFrequency.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
|
||||
{
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue)
|
||||
{
|
||||
final String summary = newValue.toString();
|
||||
int index = mCheckFrequency.findIndexOfValue(summary);
|
||||
mCheckFrequency.setSummary(mCheckFrequency.getEntries()[index]);
|
||||
|
@ -131,8 +141,10 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||
mDisplayMode = (ListPreference) findPreference(PREFERENCE_DISPLAY_MODE);
|
||||
mDisplayMode.setValue(mAccount.getFolderDisplayMode().name());
|
||||
mDisplayMode.setSummary(mDisplayMode.getEntry());
|
||||
mDisplayMode.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mDisplayMode.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
|
||||
{
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue)
|
||||
{
|
||||
final String summary = newValue.toString();
|
||||
int index = mDisplayMode.findIndexOfValue(summary);
|
||||
mDisplayMode.setSummary(mDisplayMode.getEntries()[index]);
|
||||
|
@ -144,8 +156,10 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||
mSyncMode = (ListPreference) findPreference(PREFERENCE_SYNC_MODE);
|
||||
mSyncMode.setValue(mAccount.getFolderSyncMode().name());
|
||||
mSyncMode.setSummary(mSyncMode.getEntry());
|
||||
mSyncMode.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mSyncMode.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
|
||||
{
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue)
|
||||
{
|
||||
final String summary = newValue.toString();
|
||||
int index = mSyncMode.findIndexOfValue(summary);
|
||||
mSyncMode.setSummary(mSyncMode.getEntries()[index]);
|
||||
|
@ -158,8 +172,10 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||
mPushMode.setEnabled(isPushCapable);
|
||||
mPushMode.setValue(mAccount.getFolderPushMode().name());
|
||||
mPushMode.setSummary(mPushMode.getEntry());
|
||||
mPushMode.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mPushMode.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
|
||||
{
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue)
|
||||
{
|
||||
final String summary = newValue.toString();
|
||||
int index = mPushMode.findIndexOfValue(summary);
|
||||
mPushMode.setSummary(mPushMode.getEntries()[index]);
|
||||
|
@ -171,8 +187,10 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||
mTargetMode = (ListPreference) findPreference(PREFERENCE_TARGET_MODE);
|
||||
mTargetMode.setValue(mAccount.getFolderTargetMode().name());
|
||||
mTargetMode.setSummary(mTargetMode.getEntry());
|
||||
mTargetMode.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mTargetMode.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
|
||||
{
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue)
|
||||
{
|
||||
final String summary = newValue.toString();
|
||||
int index = mTargetMode.findIndexOfValue(summary);
|
||||
mTargetMode.setSummary(mTargetMode.getEntries()[index]);
|
||||
|
@ -184,8 +202,10 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||
mDeletePolicy = (ListPreference) findPreference(PREFERENCE_DELETE_POLICY);
|
||||
mDeletePolicy.setValue("" + mAccount.getDeletePolicy());
|
||||
mDeletePolicy.setSummary(mDeletePolicy.getEntry());
|
||||
mDeletePolicy.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mDeletePolicy.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
|
||||
{
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue)
|
||||
{
|
||||
final String summary = newValue.toString();
|
||||
int index = mDeletePolicy.findIndexOfValue(summary);
|
||||
mDeletePolicy.setSummary(mDeletePolicy.getEntries()[index]);
|
||||
|
@ -197,8 +217,10 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||
mDisplayCount = (ListPreference) findPreference(PREFERENCE_DISPLAY_COUNT);
|
||||
mDisplayCount.setValue(String.valueOf(mAccount.getDisplayCount()));
|
||||
mDisplayCount.setSummary(mDisplayCount.getEntry());
|
||||
mDisplayCount.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mDisplayCount.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
|
||||
{
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue)
|
||||
{
|
||||
final String summary = newValue.toString();
|
||||
int index = mDisplayCount.findIndexOfValue(summary);
|
||||
mDisplayCount.setSummary(mDisplayCount.getEntries()[index]);
|
||||
|
@ -214,8 +236,10 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||
mAccountHideButtons = (ListPreference) findPreference(PREFERENCE_HIDE_BUTTONS);
|
||||
mAccountHideButtons.setValue("" + mAccount.getHideMessageViewButtons());
|
||||
mAccountHideButtons.setSummary(mAccountHideButtons.getEntry());
|
||||
mAccountHideButtons.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mAccountHideButtons.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
|
||||
{
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue)
|
||||
{
|
||||
final String summary = newValue.toString();
|
||||
int index = mAccountHideButtons.findIndexOfValue(summary);
|
||||
mAccountHideButtons.setSummary(mAccountHideButtons.getEntries()[index]);
|
||||
|
@ -226,7 +250,7 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||
|
||||
mAccountNotify = (CheckBoxPreference) findPreference(PREFERENCE_NOTIFY);
|
||||
mAccountNotify.setChecked(mAccount.isNotifyNewMail());
|
||||
|
||||
|
||||
mAccountNotifySelf = (CheckBoxPreference) findPreference(PREFERENCE_NOTIFY_SELF);
|
||||
mAccountNotifySelf.setChecked(mAccount.isNotifySelfNewMail());
|
||||
|
||||
|
@ -248,40 +272,50 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||
mAutoExpandFolder.setSummary(translateFolder(mAccount.getAutoExpandFolderName()));
|
||||
|
||||
mAutoExpandFolder.setOnPreferenceClickListener(
|
||||
new Preference.OnPreferenceClickListener() {
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
new Preference.OnPreferenceClickListener()
|
||||
{
|
||||
public boolean onPreferenceClick(Preference preference)
|
||||
{
|
||||
onChooseAutoExpandFolder();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
findPreference(PREFERENCE_COMPOSITION).setOnPreferenceClickListener(
|
||||
new Preference.OnPreferenceClickListener() {
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
new Preference.OnPreferenceClickListener()
|
||||
{
|
||||
public boolean onPreferenceClick(Preference preference)
|
||||
{
|
||||
onCompositionSettings();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
findPreference(PREFERENCE_MANAGE_IDENTITIES).setOnPreferenceClickListener(
|
||||
new Preference.OnPreferenceClickListener() {
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
new Preference.OnPreferenceClickListener()
|
||||
{
|
||||
public boolean onPreferenceClick(Preference preference)
|
||||
{
|
||||
onManageIdentities();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
findPreference(PREFERENCE_INCOMING).setOnPreferenceClickListener(
|
||||
new Preference.OnPreferenceClickListener() {
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
new Preference.OnPreferenceClickListener()
|
||||
{
|
||||
public boolean onPreferenceClick(Preference preference)
|
||||
{
|
||||
onIncomingSettings();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
findPreference(PREFERENCE_OUTGOING).setOnPreferenceClickListener(
|
||||
new Preference.OnPreferenceClickListener() {
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
new Preference.OnPreferenceClickListener()
|
||||
{
|
||||
public boolean onPreferenceClick(Preference preference)
|
||||
{
|
||||
onOutgoingSettings();
|
||||
return true;
|
||||
}
|
||||
|
@ -289,13 +323,16 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
mAccount.refresh(Preferences.getPreferences(this));
|
||||
}
|
||||
|
||||
private void saveSettings() {
|
||||
if (mAccountDefault.isChecked()) {
|
||||
private void saveSettings()
|
||||
{
|
||||
if (mAccountDefault.isChecked())
|
||||
{
|
||||
Preferences.getPreferences(this).setDefaultAccount(mAccount);
|
||||
}
|
||||
mAccount.setDescription(mAccountDescription.getText());
|
||||
|
@ -320,44 +357,54 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
switch (requestCode) {
|
||||
case SELECT_AUTO_EXPAND_FOLDER:
|
||||
mAutoExpandFolder.setSummary(translateFolder(data.getStringExtra(ChooseFolder.EXTRA_NEW_FOLDER)));
|
||||
break;
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
if (resultCode == RESULT_OK)
|
||||
{
|
||||
switch (requestCode)
|
||||
{
|
||||
case SELECT_AUTO_EXPAND_FOLDER:
|
||||
mAutoExpandFolder.setSummary(translateFolder(data.getStringExtra(ChooseFolder.EXTRA_NEW_FOLDER)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event)
|
||||
{
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK)
|
||||
{
|
||||
saveSettings();
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
private void onCompositionSettings() {
|
||||
private void onCompositionSettings()
|
||||
{
|
||||
AccountSetupComposition.actionEditCompositionSettings(this, mAccount);
|
||||
}
|
||||
|
||||
private void onManageIdentities() {
|
||||
private void onManageIdentities()
|
||||
{
|
||||
Intent intent = new Intent(this, ManageIdentities.class);
|
||||
intent.putExtra(ChooseIdentity.EXTRA_ACCOUNT, mAccount);
|
||||
startActivityForResult(intent, ACTIVITY_MANAGE_IDENTITIES);
|
||||
}
|
||||
|
||||
private void onIncomingSettings() {
|
||||
private void onIncomingSettings()
|
||||
{
|
||||
AccountSetupIncoming.actionEditIncomingSettings(this, mAccount);
|
||||
}
|
||||
|
||||
private void onOutgoingSettings() {
|
||||
private void onOutgoingSettings()
|
||||
{
|
||||
AccountSetupOutgoing.actionEditOutgoingSettings(this, mAccount);
|
||||
}
|
||||
|
||||
public void onChooseAutoExpandFolder() {
|
||||
public void onChooseAutoExpandFolder()
|
||||
{
|
||||
Intent selectIntent = new Intent(this, ChooseFolder.class);
|
||||
selectIntent.putExtra(ChooseFolder.EXTRA_ACCOUNT, mAccount);
|
||||
|
||||
|
@ -369,20 +416,28 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||
|
||||
}
|
||||
|
||||
private String translateFolder(String in) {
|
||||
private String translateFolder(String in)
|
||||
{
|
||||
|
||||
if (Email.INBOX.equalsIgnoreCase(in)) {
|
||||
if (Email.INBOX.equalsIgnoreCase(in))
|
||||
{
|
||||
return getString(R.string.special_mailbox_name_inbox);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return in;
|
||||
}
|
||||
}
|
||||
|
||||
private String reverseTranslateFolder(String in) {
|
||||
private String reverseTranslateFolder(String in)
|
||||
{
|
||||
|
||||
if (getString(R.string.special_mailbox_name_inbox).equals(in)) {
|
||||
if (getString(R.string.special_mailbox_name_inbox).equals(in))
|
||||
{
|
||||
return Email.INBOX;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return in;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,8 @@ import com.android.email.activity.SizeFormatter;
|
|||
* passed in email address, password and makeDefault are then passed on to the
|
||||
* AccountSetupIncoming activity.
|
||||
*/
|
||||
public class AccountSetupAccountType extends K9Activity implements OnClickListener {
|
||||
public class AccountSetupAccountType extends K9Activity implements OnClickListener
|
||||
{
|
||||
private static final String EXTRA_ACCOUNT = "account";
|
||||
|
||||
private static final String EXTRA_MAKE_DEFAULT = "makeDefault";
|
||||
|
@ -33,7 +34,8 @@ public class AccountSetupAccountType extends K9Activity implements OnClickListen
|
|||
|
||||
private boolean mMakeDefault;
|
||||
|
||||
public static void actionSelectAccountType(Context context, Account account, boolean makeDefault) {
|
||||
public static void actionSelectAccountType(Context context, Account account, boolean makeDefault)
|
||||
{
|
||||
Intent i = new Intent(context, AccountSetupAccountType.class);
|
||||
i.putExtra(EXTRA_ACCOUNT, account);
|
||||
i.putExtra(EXTRA_MAKE_DEFAULT, makeDefault);
|
||||
|
@ -41,7 +43,8 @@ public class AccountSetupAccountType extends K9Activity implements OnClickListen
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.account_setup_account_type);
|
||||
((Button)findViewById(R.id.pop)).setOnClickListener(this);
|
||||
|
@ -52,59 +55,74 @@ public class AccountSetupAccountType extends K9Activity implements OnClickListen
|
|||
mMakeDefault = (boolean)getIntent().getBooleanExtra(EXTRA_MAKE_DEFAULT, false);
|
||||
}
|
||||
|
||||
private void onPop() {
|
||||
try {
|
||||
private void onPop()
|
||||
{
|
||||
try
|
||||
{
|
||||
URI uri = new URI(mAccount.getStoreUri());
|
||||
uri = new URI("pop3", uri.getUserInfo(), uri.getHost(), uri.getPort(), null, null, null);
|
||||
mAccount.setStoreUri(uri.toString());
|
||||
AccountSetupIncoming.actionIncomingSettings(this, mAccount, mMakeDefault);
|
||||
finish();
|
||||
} catch (Exception use) {
|
||||
}
|
||||
catch (Exception use)
|
||||
{
|
||||
failure(use);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void onImap() {
|
||||
try {
|
||||
private void onImap()
|
||||
{
|
||||
try
|
||||
{
|
||||
URI uri = new URI(mAccount.getStoreUri());
|
||||
uri = new URI("imap", uri.getUserInfo(), uri.getHost(), uri.getPort(), null, null, null);
|
||||
mAccount.setStoreUri(uri.toString());
|
||||
AccountSetupIncoming.actionIncomingSettings(this, mAccount, mMakeDefault);
|
||||
finish();
|
||||
} catch (Exception use) {
|
||||
}
|
||||
catch (Exception use)
|
||||
{
|
||||
failure(use);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void onWebDav() {
|
||||
try {
|
||||
private void onWebDav()
|
||||
{
|
||||
try
|
||||
{
|
||||
URI uri = new URI(mAccount.getStoreUri());
|
||||
uri = new URI("webdav", uri.getUserInfo(), uri.getHost(), uri.getPort(), null, null, null);
|
||||
mAccount.setStoreUri(uri.toString());
|
||||
AccountSetupIncoming.actionIncomingSettings(this, mAccount, mMakeDefault);
|
||||
finish();
|
||||
} catch (Exception use) {
|
||||
}
|
||||
catch (Exception use)
|
||||
{
|
||||
failure(use);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.pop:
|
||||
onPop();
|
||||
break;
|
||||
case R.id.imap:
|
||||
onImap();
|
||||
break;
|
||||
case R.id.webdav:
|
||||
onWebDav();
|
||||
break;
|
||||
public void onClick(View v)
|
||||
{
|
||||
switch (v.getId())
|
||||
{
|
||||
case R.id.pop:
|
||||
onPop();
|
||||
break;
|
||||
case R.id.imap:
|
||||
onImap();
|
||||
break;
|
||||
case R.id.webdav:
|
||||
onWebDav();
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void failure(Exception use) {
|
||||
private void failure(Exception use)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Failure", use);
|
||||
String toastText = getString(R.string.account_setup_bad_uri, use.getMessage());
|
||||
|
||||
|
|
|
@ -42,7 +42,8 @@ import com.android.email.Utility;
|
|||
* AccountSetupAccountType activity.
|
||||
*/
|
||||
public class AccountSetupBasics extends K9Activity
|
||||
implements OnClickListener, TextWatcher {
|
||||
implements OnClickListener, TextWatcher
|
||||
{
|
||||
private final static String EXTRA_ACCOUNT = "com.android.email.AccountSetupBasics.account";
|
||||
private final static int DIALOG_NOTE = 1;
|
||||
private final static String STATE_KEY_PROVIDER =
|
||||
|
@ -59,13 +60,15 @@ public class AccountSetupBasics extends K9Activity
|
|||
|
||||
private EmailAddressValidator mEmailValidator = new EmailAddressValidator();
|
||||
|
||||
public static void actionNewAccount(Context context) {
|
||||
public static void actionNewAccount(Context context)
|
||||
{
|
||||
Intent i = new Intent(context, AccountSetupBasics.class);
|
||||
context.startActivity(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.account_setup_basics);
|
||||
mPrefs = Preferences.getPreferences(this);
|
||||
|
@ -81,45 +84,55 @@ public class AccountSetupBasics extends K9Activity
|
|||
mEmailView.addTextChangedListener(this);
|
||||
mPasswordView.addTextChangedListener(this);
|
||||
|
||||
if (mPrefs.getAccounts().length > 0) {
|
||||
if (mPrefs.getAccounts().length > 0)
|
||||
{
|
||||
mDefaultView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_ACCOUNT)) {
|
||||
if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_ACCOUNT))
|
||||
{
|
||||
mAccount = (Account)savedInstanceState.getSerializable(EXTRA_ACCOUNT);
|
||||
}
|
||||
|
||||
if (savedInstanceState != null && savedInstanceState.containsKey(STATE_KEY_PROVIDER)) {
|
||||
if (savedInstanceState != null && savedInstanceState.containsKey(STATE_KEY_PROVIDER))
|
||||
{
|
||||
mProvider = (Provider)savedInstanceState.getSerializable(STATE_KEY_PROVIDER);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
validateFields();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
public void onSaveInstanceState(Bundle outState)
|
||||
{
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putSerializable(EXTRA_ACCOUNT, mAccount);
|
||||
if (mProvider != null) {
|
||||
if (mProvider != null)
|
||||
{
|
||||
outState.putSerializable(STATE_KEY_PROVIDER, mProvider);
|
||||
}
|
||||
}
|
||||
|
||||
public void afterTextChanged(Editable s) {
|
||||
public void afterTextChanged(Editable s)
|
||||
{
|
||||
validateFields();
|
||||
}
|
||||
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after)
|
||||
{
|
||||
}
|
||||
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count)
|
||||
{
|
||||
}
|
||||
|
||||
private void validateFields() {
|
||||
private void validateFields()
|
||||
{
|
||||
String email = mEmailView.getText().toString();
|
||||
boolean valid = Utility.requiredFieldValid(mEmailView)
|
||||
&& Utility.requiredFieldValid(mPasswordView)
|
||||
|
@ -135,56 +148,74 @@ public class AccountSetupBasics extends K9Activity
|
|||
Utility.setCompoundDrawablesAlpha(mNextButton, mNextButton.isEnabled() ? 255 : 128);
|
||||
}
|
||||
|
||||
private String getOwnerName() {
|
||||
private String getOwnerName()
|
||||
{
|
||||
String name = null;
|
||||
try {
|
||||
String projection[] = {
|
||||
try
|
||||
{
|
||||
String projection[] =
|
||||
{
|
||||
ContactMethods.NAME
|
||||
};
|
||||
Cursor c = getContentResolver().query(
|
||||
// TODO: For Android 2.0, needs to change to ContactsContract.People...
|
||||
Uri.withAppendedPath(Contacts.People.CONTENT_URI, "owner"), projection, null, null,
|
||||
null);
|
||||
if (c.getCount() > 0) {
|
||||
if (c.getCount() > 0)
|
||||
{
|
||||
c.moveToFirst();
|
||||
name = c.getString(0);
|
||||
c.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Could not get owner name, using default account name", e);
|
||||
}
|
||||
if (name == null || name.length() == 0) {
|
||||
try {
|
||||
if (name == null || name.length() == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
name = getDefaultAccountName();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Could not get default account name", e);
|
||||
}
|
||||
}
|
||||
if (name == null) {
|
||||
if (name == null)
|
||||
{
|
||||
name = "";
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private String getDefaultAccountName() {
|
||||
private String getDefaultAccountName()
|
||||
{
|
||||
String name = null;
|
||||
Account account = Preferences.getPreferences(this).getDefaultAccount();
|
||||
if (account != null) {
|
||||
if (account != null)
|
||||
{
|
||||
name = account.getName();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(int id) {
|
||||
if (id == DIALOG_NOTE) {
|
||||
if (mProvider != null && mProvider.note != null) {
|
||||
public Dialog onCreateDialog(int id)
|
||||
{
|
||||
if (id == DIALOG_NOTE)
|
||||
{
|
||||
if (mProvider != null && mProvider.note != null)
|
||||
{
|
||||
return new AlertDialog.Builder(this)
|
||||
.setMessage(mProvider.note)
|
||||
.setPositiveButton(
|
||||
getString(R.string.okay_action),
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
finishAutoSetup();
|
||||
}
|
||||
})
|
||||
|
@ -197,7 +228,8 @@ public class AccountSetupBasics extends K9Activity
|
|||
return null;
|
||||
}
|
||||
|
||||
private void finishAutoSetup() {
|
||||
private void finishAutoSetup()
|
||||
{
|
||||
String email = mEmailView.getText().toString();
|
||||
String password = mPasswordView.getText().toString();
|
||||
String[] emailParts = splitEmail(email);
|
||||
|
@ -205,7 +237,8 @@ public class AccountSetupBasics extends K9Activity
|
|||
String domain = emailParts[1];
|
||||
URI incomingUri = null;
|
||||
URI outgoingUri = null;
|
||||
try {
|
||||
try
|
||||
{
|
||||
String incomingUsername = mProvider.incomingUsernameTemplate;
|
||||
incomingUsername = incomingUsername.replaceAll("\\$email", email);
|
||||
incomingUsername = incomingUsername.replaceAll("\\$user", user);
|
||||
|
@ -225,7 +258,9 @@ public class AccountSetupBasics extends K9Activity
|
|||
outgoingUri = new URI(outgoingUriTemplate.getScheme(), outgoingUsername + ":"
|
||||
+ password, outgoingUriTemplate.getHost(), outgoingUriTemplate.getPort(), null,
|
||||
null, null);
|
||||
} catch (URISyntaxException use) {
|
||||
}
|
||||
catch (URISyntaxException use)
|
||||
{
|
||||
/*
|
||||
* If there is some problem with the URI we give up and go on to
|
||||
* manual setup.
|
||||
|
@ -246,14 +281,16 @@ public class AccountSetupBasics extends K9Activity
|
|||
AccountSetupCheckSettings.actionCheckSettings(this, mAccount, true, true);
|
||||
}
|
||||
|
||||
private void onNext() {
|
||||
private void onNext()
|
||||
{
|
||||
String email = mEmailView.getText().toString();
|
||||
String password = mPasswordView.getText().toString();
|
||||
String[] emailParts = splitEmail(email);
|
||||
String user = emailParts[0];
|
||||
String domain = emailParts[1];
|
||||
mProvider = findProviderForDomain(domain);
|
||||
if (mProvider == null) {
|
||||
if (mProvider == null)
|
||||
{
|
||||
/*
|
||||
* We don't have default settings for this account, start the manual
|
||||
* setup process.
|
||||
|
@ -262,19 +299,25 @@ public class AccountSetupBasics extends K9Activity
|
|||
return;
|
||||
}
|
||||
|
||||
if (mProvider.note != null) {
|
||||
if (mProvider.note != null)
|
||||
{
|
||||
showDialog(DIALOG_NOTE);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
finishAutoSetup();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
if (resultCode == RESULT_OK)
|
||||
{
|
||||
mAccount.setDescription(mAccount.getEmail());
|
||||
mAccount.save(Preferences.getPreferences(this));
|
||||
if (mDefaultView.isChecked()) {
|
||||
if (mDefaultView.isChecked())
|
||||
{
|
||||
Preferences.getPreferences(this).setDefaultAccount(mAccount);
|
||||
}
|
||||
Email.setServicesEnabled(this);
|
||||
|
@ -283,7 +326,8 @@ public class AccountSetupBasics extends K9Activity
|
|||
}
|
||||
}
|
||||
|
||||
private void onManualSetup() {
|
||||
private void onManualSetup()
|
||||
{
|
||||
String email = mEmailView.getText().toString();
|
||||
String password = mPasswordView.getText().toString();
|
||||
String[] emailParts = splitEmail(email);
|
||||
|
@ -293,12 +337,15 @@ public class AccountSetupBasics extends K9Activity
|
|||
mAccount = new Account(this);
|
||||
mAccount.setName(getOwnerName());
|
||||
mAccount.setEmail(email);
|
||||
try {
|
||||
try
|
||||
{
|
||||
URI uri = new URI("placeholder", user + ":" + password, "mail." + domain, -1, null,
|
||||
null, null);
|
||||
mAccount.setStoreUri(uri.toString());
|
||||
mAccount.setTransportUri(uri.toString());
|
||||
} catch (URISyntaxException use) {
|
||||
}
|
||||
catch (URISyntaxException use)
|
||||
{
|
||||
/*
|
||||
* If we can't set up the URL we just continue. It's only for
|
||||
* convenience.
|
||||
|
@ -313,14 +360,16 @@ public class AccountSetupBasics extends K9Activity
|
|||
finish();
|
||||
}
|
||||
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.next:
|
||||
onNext();
|
||||
break;
|
||||
case R.id.manual_setup:
|
||||
onManualSetup();
|
||||
break;
|
||||
public void onClick(View v)
|
||||
{
|
||||
switch (v.getId())
|
||||
{
|
||||
case R.id.next:
|
||||
onNext();
|
||||
break;
|
||||
case R.id.manual_setup:
|
||||
onManualSetup();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,60 +380,78 @@ public class AccountSetupBasics extends K9Activity
|
|||
* @param name
|
||||
* @return
|
||||
*/
|
||||
private String getXmlAttribute(XmlResourceParser xml, String name) {
|
||||
private String getXmlAttribute(XmlResourceParser xml, String name)
|
||||
{
|
||||
int resId = xml.getAttributeResourceValue(null, name, 0);
|
||||
if (resId == 0) {
|
||||
if (resId == 0)
|
||||
{
|
||||
return xml.getAttributeValue(null, name);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return getString(resId);
|
||||
}
|
||||
}
|
||||
|
||||
private Provider findProviderForDomain(String domain) {
|
||||
try {
|
||||
private Provider findProviderForDomain(String domain)
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlResourceParser xml = getResources().getXml(R.xml.providers);
|
||||
int xmlEventType;
|
||||
Provider provider = null;
|
||||
while ((xmlEventType = xml.next()) != XmlResourceParser.END_DOCUMENT) {
|
||||
while ((xmlEventType = xml.next()) != XmlResourceParser.END_DOCUMENT)
|
||||
{
|
||||
if (xmlEventType == XmlResourceParser.START_TAG
|
||||
&& "provider".equals(xml.getName())
|
||||
&& domain.equalsIgnoreCase(getXmlAttribute(xml, "domain"))) {
|
||||
&& domain.equalsIgnoreCase(getXmlAttribute(xml, "domain")))
|
||||
{
|
||||
provider = new Provider();
|
||||
provider.id = getXmlAttribute(xml, "id");
|
||||
provider.label = getXmlAttribute(xml, "label");
|
||||
provider.domain = getXmlAttribute(xml, "domain");
|
||||
provider.note = getXmlAttribute(xml, "note");
|
||||
} else if (xmlEventType == XmlResourceParser.START_TAG
|
||||
&& "incoming".equals(xml.getName())
|
||||
&& provider != null) {
|
||||
}
|
||||
else if (xmlEventType == XmlResourceParser.START_TAG
|
||||
&& "incoming".equals(xml.getName())
|
||||
&& provider != null)
|
||||
{
|
||||
provider.incomingUriTemplate = new URI(getXmlAttribute(xml, "uri"));
|
||||
provider.incomingUsernameTemplate = getXmlAttribute(xml, "username");
|
||||
} else if (xmlEventType == XmlResourceParser.START_TAG
|
||||
&& "outgoing".equals(xml.getName())
|
||||
&& provider != null) {
|
||||
}
|
||||
else if (xmlEventType == XmlResourceParser.START_TAG
|
||||
&& "outgoing".equals(xml.getName())
|
||||
&& provider != null)
|
||||
{
|
||||
provider.outgoingUriTemplate = new URI(getXmlAttribute(xml, "uri"));
|
||||
provider.outgoingUsernameTemplate = getXmlAttribute(xml, "username");
|
||||
} else if (xmlEventType == XmlResourceParser.END_TAG
|
||||
&& "provider".equals(xml.getName())
|
||||
&& provider != null) {
|
||||
}
|
||||
else if (xmlEventType == XmlResourceParser.END_TAG
|
||||
&& "provider".equals(xml.getName())
|
||||
&& provider != null)
|
||||
{
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Error while trying to load provider settings.", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String[] splitEmail(String email) {
|
||||
private String[] splitEmail(String email)
|
||||
{
|
||||
String[] retParts = new String[2];
|
||||
String[] emailParts = email.split("@");
|
||||
retParts[0] = (emailParts.length > 0 ) ? emailParts[0] : "";
|
||||
retParts[1] = (emailParts.length > 1 ) ? emailParts[1] : "";
|
||||
retParts[0] = (emailParts.length > 0) ? emailParts[0] : "";
|
||||
retParts[1] = (emailParts.length > 1) ? emailParts[1] : "";
|
||||
return retParts;
|
||||
}
|
||||
|
||||
static class Provider implements Serializable {
|
||||
static class Provider implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 8511656164616538989L;
|
||||
|
||||
public String id;
|
||||
|
|
|
@ -38,7 +38,8 @@ import com.android.email.mail.store.TrustManagerFactory;
|
|||
* XXX NOTE: The manifest for this app has it ignore config changes, because
|
||||
* it doesn't correctly deal with restarting while its thread is running.
|
||||
*/
|
||||
public class AccountSetupCheckSettings extends K9Activity implements OnClickListener {
|
||||
public class AccountSetupCheckSettings extends K9Activity implements OnClickListener
|
||||
{
|
||||
|
||||
public static final int ACTIVITY_REQUEST_CODE = 1;
|
||||
|
||||
|
@ -65,7 +66,8 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
|||
private boolean mDestroyed;
|
||||
|
||||
public static void actionCheckSettings(Activity context, Account account,
|
||||
boolean checkIncoming, boolean checkOutgoing) {
|
||||
boolean checkIncoming, boolean checkOutgoing)
|
||||
{
|
||||
Intent i = new Intent(context, AccountSetupCheckSettings.class);
|
||||
i.putExtra(EXTRA_ACCOUNT, account);
|
||||
i.putExtra(EXTRA_CHECK_INCOMING, checkIncoming);
|
||||
|
@ -74,7 +76,8 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.account_setup_check_settings);
|
||||
mMessageView = (TextView)findViewById(R.id.message);
|
||||
|
@ -88,61 +91,78 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
|||
mCheckIncoming = (boolean)getIntent().getBooleanExtra(EXTRA_CHECK_INCOMING, false);
|
||||
mCheckOutgoing = (boolean)getIntent().getBooleanExtra(EXTRA_CHECK_OUTGOING, false);
|
||||
|
||||
new Thread() {
|
||||
public void run() {
|
||||
new Thread()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
Store store = null;
|
||||
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
|
||||
try {
|
||||
if (mDestroyed) {
|
||||
try
|
||||
{
|
||||
if (mDestroyed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (mCanceled) {
|
||||
if (mCanceled)
|
||||
{
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
if (mCheckIncoming) {
|
||||
if (mCheckIncoming)
|
||||
{
|
||||
setMessage(R.string.account_setup_check_settings_check_incoming_msg);
|
||||
store = Store.getInstance(mAccount.getStoreUri(), getApplication());
|
||||
store.checkSettings();
|
||||
|
||||
MessagingController.getInstance(getApplication()).listFolders(mAccount, true, null);
|
||||
MessagingController.getInstance(getApplication()).synchronizeMailbox( mAccount, Email.INBOX , null);
|
||||
MessagingController.getInstance(getApplication()).synchronizeMailbox(mAccount, Email.INBOX , null);
|
||||
|
||||
}
|
||||
if (mDestroyed) {
|
||||
if (mDestroyed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (mCanceled) {
|
||||
if (mCanceled)
|
||||
{
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
if (mCheckOutgoing) {
|
||||
if (mCheckOutgoing)
|
||||
{
|
||||
setMessage(R.string.account_setup_check_settings_check_outgoing_msg);
|
||||
Transport transport = Transport.getInstance(mAccount.getTransportUri());
|
||||
transport.close();
|
||||
transport.open();
|
||||
transport.close();
|
||||
}
|
||||
if (mDestroyed) {
|
||||
if (mDestroyed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (mCanceled) {
|
||||
if (mCanceled)
|
||||
{
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
} catch (final AuthenticationFailedException afe) {
|
||||
}
|
||||
catch (final AuthenticationFailedException afe)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Error while testing settings", afe);
|
||||
showErrorDialog(
|
||||
R.string.account_setup_failed_dlg_auth_message_fmt,
|
||||
afe.getMessage() == null ? "" : afe.getMessage());
|
||||
} catch (final CertificateValidationException cve) {
|
||||
}
|
||||
catch (final CertificateValidationException cve)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Error while testing settings", cve);
|
||||
acceptKeyDialog(
|
||||
R.string.account_setup_failed_dlg_certificate_message_fmt,
|
||||
cve);
|
||||
} catch (final Throwable t) {
|
||||
}
|
||||
catch (final Throwable t)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Error while testing settings", t);
|
||||
showErrorDialog(
|
||||
R.string.account_setup_failed_dlg_server_message_fmt,
|
||||
|
@ -156,16 +176,21 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
public void onDestroy()
|
||||
{
|
||||
super.onDestroy();
|
||||
mDestroyed = true;
|
||||
mCanceled = true;
|
||||
}
|
||||
|
||||
private void setMessage(final int resId) {
|
||||
mHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (mDestroyed) {
|
||||
private void setMessage(final int resId)
|
||||
{
|
||||
mHandler.post(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
if (mDestroyed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
mMessageView.setText(getString(resId));
|
||||
|
@ -173,10 +198,14 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
|||
});
|
||||
}
|
||||
|
||||
private void showErrorDialog(final int msgResId, final Object... args) {
|
||||
mHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (mDestroyed) {
|
||||
private void showErrorDialog(final int msgResId, final Object... args)
|
||||
{
|
||||
mHandler.post(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
if (mDestroyed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
mProgressBar.setIndeterminate(false);
|
||||
|
@ -187,8 +216,10 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
|||
.setNegativeButton(
|
||||
getString(R.string.account_setup_failed_dlg_continue_action),
|
||||
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
mCanceled=false;
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
|
@ -196,8 +227,10 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
|||
})
|
||||
.setPositiveButton(
|
||||
getString(R.string.account_setup_failed_dlg_edit_details_action),
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
finish();
|
||||
}
|
||||
})
|
||||
|
@ -205,32 +238,44 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
|||
}
|
||||
});
|
||||
}
|
||||
private void acceptKeyDialog(final int msgResId, final Object... args) {
|
||||
mHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (mDestroyed) {
|
||||
private void acceptKeyDialog(final int msgResId, final Object... args)
|
||||
{
|
||||
mHandler.post(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
if (mDestroyed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
final X509Certificate[] chain = TrustManagerFactory.getLastCertChain();
|
||||
String exMessage = "Unknown Error";
|
||||
|
||||
Exception ex = ((Exception)args[0]);
|
||||
if (ex != null) {
|
||||
if (ex.getCause() != null) {
|
||||
if (ex.getCause().getCause() != null) {
|
||||
if (ex != null)
|
||||
{
|
||||
if (ex.getCause() != null)
|
||||
{
|
||||
if (ex.getCause().getCause() != null)
|
||||
{
|
||||
exMessage = ex.getCause().getCause().getMessage();
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
exMessage = ex.getCause().getMessage();
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
exMessage = ex.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
mProgressBar.setIndeterminate(false);
|
||||
StringBuffer chainInfo = new StringBuffer(100);
|
||||
for (int i = 0; i < chain.length; i++) {
|
||||
for (int i = 0; i < chain.length; i++)
|
||||
{
|
||||
// display certificate chain information
|
||||
chainInfo.append("Certificate chain[" + i + "]:\n");
|
||||
chainInfo.append("Subject: " + chain[i].getSubjectDN().toString() + "\n");
|
||||
|
@ -246,18 +291,25 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
|||
.setCancelable(true)
|
||||
.setPositiveButton(
|
||||
getString(R.string.account_setup_failed_dlg_invalid_certificate_accept),
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
try {
|
||||
new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
try
|
||||
{
|
||||
String alias = mAccount.getUuid();
|
||||
if (mCheckIncoming) {
|
||||
if (mCheckIncoming)
|
||||
{
|
||||
alias = alias + ".incoming";
|
||||
}
|
||||
if (mCheckOutgoing) {
|
||||
if (mCheckOutgoing)
|
||||
{
|
||||
alias = alias + ".outgoing";
|
||||
}
|
||||
TrustManagerFactory.addCertificateChain(alias, chain);
|
||||
} catch (CertificateException e) {
|
||||
}
|
||||
catch (CertificateException e)
|
||||
{
|
||||
showErrorDialog(
|
||||
R.string.account_setup_failed_dlg_certificate_message_fmt,
|
||||
e.getMessage() == null ? "" : e.getMessage());
|
||||
|
@ -268,8 +320,10 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
|||
})
|
||||
.setNegativeButton(
|
||||
getString(R.string.account_setup_failed_dlg_invalid_certificate_reject),
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
finish();
|
||||
}
|
||||
})
|
||||
|
@ -278,22 +332,26 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
|||
});
|
||||
}
|
||||
|
||||
public void onActivityResult(int reqCode, int resCode, Intent data) {
|
||||
public void onActivityResult(int reqCode, int resCode, Intent data)
|
||||
{
|
||||
setResult(resCode);
|
||||
finish();
|
||||
}
|
||||
|
||||
|
||||
private void onCancel() {
|
||||
private void onCancel()
|
||||
{
|
||||
mCanceled = true;
|
||||
setMessage(R.string.account_setup_check_settings_canceling_msg);
|
||||
}
|
||||
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.cancel:
|
||||
onCancel();
|
||||
break;
|
||||
public void onClick(View v)
|
||||
{
|
||||
switch (v.getId())
|
||||
{
|
||||
case R.id.cancel:
|
||||
onCancel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@ import com.android.email.Email;
|
|||
import com.android.email.Preferences;
|
||||
import com.android.email.R;
|
||||
|
||||
public class AccountSetupComposition extends K9Activity {
|
||||
public class AccountSetupComposition extends K9Activity
|
||||
{
|
||||
|
||||
private static final String EXTRA_ACCOUNT = "account";
|
||||
|
||||
|
@ -27,7 +28,8 @@ public class AccountSetupComposition extends K9Activity {
|
|||
private RadioButton mAccountSignatureAfterLocation;
|
||||
|
||||
|
||||
public static void actionEditCompositionSettings(Activity context, Account account) {
|
||||
public static void actionEditCompositionSettings(Activity context, Account account)
|
||||
{
|
||||
Intent i = new Intent(context, AccountSetupComposition.class);
|
||||
i.setAction(Intent.ACTION_EDIT);
|
||||
i.putExtra(EXTRA_ACCOUNT, account);
|
||||
|
@ -36,7 +38,8 @@ public class AccountSetupComposition extends K9Activity {
|
|||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mAccount = (Account)getIntent().getSerializableExtra(EXTRA_ACCOUNT);
|
||||
|
@ -47,7 +50,8 @@ public class AccountSetupComposition extends K9Activity {
|
|||
* If we're being reloaded we override the original account with the one
|
||||
* we saved
|
||||
*/
|
||||
if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_ACCOUNT)) {
|
||||
if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_ACCOUNT))
|
||||
{
|
||||
mAccount = (Account)savedInstanceState.getSerializable(EXTRA_ACCOUNT);
|
||||
}
|
||||
|
||||
|
@ -71,12 +75,14 @@ public class AccountSetupComposition extends K9Activity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
mAccount.refresh(Preferences.getPreferences(this));
|
||||
}
|
||||
|
||||
private void saveSettings() {
|
||||
private void saveSettings()
|
||||
{
|
||||
mAccount.setEmail(mAccountEmail.getText().toString());
|
||||
mAccount.setAlwaysBcc(mAccountAlwaysBcc.getText().toString());
|
||||
mAccount.setName(mAccountName.getText().toString());
|
||||
|
@ -88,21 +94,25 @@ public class AccountSetupComposition extends K9Activity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event)
|
||||
{
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK)
|
||||
{
|
||||
saveSettings();
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
public void onSaveInstanceState(Bundle outState)
|
||||
{
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putSerializable(EXTRA_ACCOUNT, mAccount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
mAccount.save(Preferences.getPreferences(this));
|
||||
finish();
|
||||
}
|
||||
|
|
|
@ -30,7 +30,8 @@ import com.android.email.R;
|
|||
import com.android.email.Utility;
|
||||
import com.android.email.activity.ChooseFolder;
|
||||
|
||||
public class AccountSetupIncoming extends K9Activity implements OnClickListener {
|
||||
public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
||||
{
|
||||
private static final String EXTRA_ACCOUNT = "account";
|
||||
private static final String EXTRA_MAKE_DEFAULT = "makeDefault";
|
||||
|
||||
|
@ -39,22 +40,28 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
|||
private static final int SELECT_TRASH_FOLDER = 102;
|
||||
private static final int SELECT_OUTBOX_FOLDER = 103;
|
||||
|
||||
private static final int popPorts[] = {
|
||||
private static final int popPorts[] =
|
||||
{
|
||||
110, 995, 995, 110, 110
|
||||
};
|
||||
private static final String popSchemes[] = {
|
||||
private static final String popSchemes[] =
|
||||
{
|
||||
"pop3", "pop3+ssl", "pop3+ssl+", "pop3+tls", "pop3+tls+"
|
||||
};
|
||||
private static final int imapPorts[] = {
|
||||
private static final int imapPorts[] =
|
||||
{
|
||||
143, 993, 993, 143, 143
|
||||
};
|
||||
private static final String imapSchemes[] = {
|
||||
private static final String imapSchemes[] =
|
||||
{
|
||||
"imap", "imap+ssl", "imap+ssl+", "imap+tls", "imap+tls+"
|
||||
};
|
||||
private static final int webdavPorts[] = {
|
||||
private static final int webdavPorts[] =
|
||||
{
|
||||
80, 443, 443, 443, 443
|
||||
};
|
||||
private static final String webdavSchemes[] = {
|
||||
private static final String webdavSchemes[] =
|
||||
{
|
||||
"webdav", "webdav+ssl", "webdav+ssl+", "webdav+tls", "webdav+tls+"
|
||||
};
|
||||
|
||||
|
@ -77,14 +84,16 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
|||
private Account mAccount;
|
||||
private boolean mMakeDefault;
|
||||
|
||||
public static void actionIncomingSettings(Activity context, Account account, boolean makeDefault) {
|
||||
public static void actionIncomingSettings(Activity context, Account account, boolean makeDefault)
|
||||
{
|
||||
Intent i = new Intent(context, AccountSetupIncoming.class);
|
||||
i.putExtra(EXTRA_ACCOUNT, account);
|
||||
i.putExtra(EXTRA_MAKE_DEFAULT, makeDefault);
|
||||
context.startActivity(i);
|
||||
}
|
||||
|
||||
public static void actionEditIncomingSettings(Activity context, Account account) {
|
||||
public static void actionEditIncomingSettings(Activity context, Account account)
|
||||
{
|
||||
Intent i = new Intent(context, AccountSetupIncoming.class);
|
||||
i.setAction(Intent.ACTION_EDIT);
|
||||
i.putExtra(EXTRA_ACCOUNT, account);
|
||||
|
@ -92,7 +101,8 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.account_setup_incoming);
|
||||
|
||||
|
@ -118,7 +128,8 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
|||
mImapFolderOutbox.setOnClickListener(this);
|
||||
mNextButton.setOnClickListener(this);
|
||||
|
||||
SpinnerOption securityTypes[] = {
|
||||
SpinnerOption securityTypes[] =
|
||||
{
|
||||
new SpinnerOption(0, getString(R.string.account_setup_incoming_security_none_label)),
|
||||
new SpinnerOption(1,
|
||||
getString(R.string.account_setup_incoming_security_ssl_optional_label)),
|
||||
|
@ -137,12 +148,15 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
|||
* Updates the port when the user changes the security type. This allows
|
||||
* us to show a reasonable default which the user can change.
|
||||
*/
|
||||
mSecurityTypeView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3) {
|
||||
mSecurityTypeView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
|
||||
{
|
||||
public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3)
|
||||
{
|
||||
updatePortFromSecurityType();
|
||||
}
|
||||
|
||||
public void onNothingSelected(AdapterView<?> arg0) {
|
||||
public void onNothingSelected(AdapterView<?> arg0)
|
||||
{
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -150,15 +164,19 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
|||
* Calls validateFields() which enables or disables the Next button
|
||||
* based on the fields' validity.
|
||||
*/
|
||||
TextWatcher validationTextWatcher = new TextWatcher() {
|
||||
public void afterTextChanged(Editable s) {
|
||||
TextWatcher validationTextWatcher = new TextWatcher()
|
||||
{
|
||||
public void afterTextChanged(Editable s)
|
||||
{
|
||||
validateFields();
|
||||
}
|
||||
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after)
|
||||
{
|
||||
}
|
||||
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count)
|
||||
{
|
||||
}
|
||||
};
|
||||
mUsernameView.addTextChangedListener(validationTextWatcher);
|
||||
|
@ -178,27 +196,33 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
|||
* If we're being reloaded we override the original account with the one
|
||||
* we saved
|
||||
*/
|
||||
if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_ACCOUNT)) {
|
||||
if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_ACCOUNT))
|
||||
{
|
||||
mAccount = (Account)savedInstanceState.getSerializable(EXTRA_ACCOUNT);
|
||||
}
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
URI uri = new URI(mAccount.getStoreUri());
|
||||
String username = null;
|
||||
String password = null;
|
||||
if (uri.getUserInfo() != null) {
|
||||
if (uri.getUserInfo() != null)
|
||||
{
|
||||
String[] userInfoParts = uri.getUserInfo().split(":", 2);
|
||||
username = userInfoParts[0];
|
||||
if (userInfoParts.length > 1) {
|
||||
if (userInfoParts.length > 1)
|
||||
{
|
||||
password = userInfoParts[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (username != null) {
|
||||
if (username != null)
|
||||
{
|
||||
mUsernameView.setText(username);
|
||||
}
|
||||
|
||||
if (password != null) {
|
||||
if (password != null)
|
||||
{
|
||||
mPasswordView.setText(password);
|
||||
}
|
||||
|
||||
|
@ -207,7 +231,8 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
|||
mImapFolderTrash.setText(mAccount.getTrashFolderName());
|
||||
mImapFolderOutbox.setText(mAccount.getOutboxFolderName());
|
||||
|
||||
if (uri.getScheme().startsWith("pop3")) {
|
||||
if (uri.getScheme().startsWith("pop3"))
|
||||
{
|
||||
serverLabelView.setText(R.string.account_setup_incoming_pop_server_label);
|
||||
mAccountPorts = popPorts;
|
||||
mAccountSchemes = popSchemes;
|
||||
|
@ -219,23 +244,29 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
|||
mAccount.setDeletePolicy(Account.DELETE_POLICY_NEVER);
|
||||
|
||||
|
||||
} else if (uri.getScheme().startsWith("imap")) {
|
||||
}
|
||||
else if (uri.getScheme().startsWith("imap"))
|
||||
{
|
||||
serverLabelView.setText(R.string.account_setup_incoming_imap_server_label);
|
||||
mAccountPorts = imapPorts;
|
||||
mAccountSchemes = imapSchemes;
|
||||
|
||||
if (uri.getPath() != null && uri.getPath().length() > 0) {
|
||||
if (uri.getPath() != null && uri.getPath().length() > 0)
|
||||
{
|
||||
mImapPathPrefixView.setText(uri.getPath().substring(1));
|
||||
}
|
||||
findViewById(R.id.webdav_path_prefix_section).setVisibility(View.GONE);
|
||||
findViewById(R.id.webdav_path_debug_section).setVisibility(View.GONE);
|
||||
mAccount.setDeletePolicy(Account.DELETE_POLICY_ON_DELETE);
|
||||
|
||||
if (! Intent.ACTION_EDIT.equals(getIntent().getAction())) {
|
||||
if (! Intent.ACTION_EDIT.equals(getIntent().getAction()))
|
||||
{
|
||||
findViewById(R.id.imap_folder_setup_section).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
} else if (uri.getScheme().startsWith("webdav")) {
|
||||
}
|
||||
else if (uri.getScheme().startsWith("webdav"))
|
||||
{
|
||||
serverLabelView.setText(R.string.account_setup_incoming_webdav_server_label);
|
||||
mAccountPorts = webdavPorts;
|
||||
mAccountSchemes = webdavSchemes;
|
||||
|
@ -243,63 +274,85 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
|||
/** Hide the unnecessary fields */
|
||||
findViewById(R.id.imap_path_prefix_section).setVisibility(View.GONE);
|
||||
findViewById(R.id.imap_folder_setup_section).setVisibility(View.GONE);
|
||||
if (uri.getPath() != null && uri.getPath().length() > 0) {
|
||||
if (uri.getPath() != null && uri.getPath().length() > 0)
|
||||
{
|
||||
String[] pathParts = uri.getPath().split("\\|");
|
||||
|
||||
for (int i = 0, count = pathParts.length; i < count; i++) {
|
||||
if (i == 0) {
|
||||
for (int i = 0, count = pathParts.length; i < count; i++)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
if (pathParts[0] != null &&
|
||||
pathParts[0].length() > 1) {
|
||||
pathParts[0].length() > 1)
|
||||
{
|
||||
mWebdavPathPrefixView.setText(pathParts[0].substring(1));
|
||||
}
|
||||
} else if (i == 1) {
|
||||
}
|
||||
else if (i == 1)
|
||||
{
|
||||
if (pathParts[1] != null &&
|
||||
pathParts[1].length() > 1) {
|
||||
pathParts[1].length() > 1)
|
||||
{
|
||||
mWebdavAuthPathView.setText(pathParts[1]);
|
||||
}
|
||||
} else if (i == 2) {
|
||||
}
|
||||
else if (i == 2)
|
||||
{
|
||||
if (pathParts[2] != null &&
|
||||
pathParts[2].length() > 1) {
|
||||
pathParts[2].length() > 1)
|
||||
{
|
||||
mWebdavMailboxPathView.setText(pathParts[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mAccount.setDeletePolicy(Account.DELETE_POLICY_ON_DELETE);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unknown account type: " + mAccount.getStoreUri());
|
||||
}
|
||||
|
||||
for (int i = 0; i < mAccountSchemes.length; i++) {
|
||||
if (mAccountSchemes[i].equals(uri.getScheme())) {
|
||||
for (int i = 0; i < mAccountSchemes.length; i++)
|
||||
{
|
||||
if (mAccountSchemes[i].equals(uri.getScheme()))
|
||||
{
|
||||
SpinnerOption.setSpinnerOptionValue(mSecurityTypeView, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (uri.getHost() != null) {
|
||||
if (uri.getHost() != null)
|
||||
{
|
||||
mServerView.setText(uri.getHost());
|
||||
}
|
||||
|
||||
if (uri.getPort() != -1) {
|
||||
if (uri.getPort() != -1)
|
||||
{
|
||||
mPortView.setText(Integer.toString(uri.getPort()));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
updatePortFromSecurityType();
|
||||
}
|
||||
|
||||
validateFields();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
failure(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
public void onSaveInstanceState(Bundle outState)
|
||||
{
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putSerializable(EXTRA_ACCOUNT, mAccount);
|
||||
}
|
||||
|
||||
private void validateFields() {
|
||||
private void validateFields()
|
||||
{
|
||||
mNextButton
|
||||
.setEnabled(Utility.requiredFieldValid(mUsernameView)
|
||||
&& Utility.requiredFieldValid(mPasswordView)
|
||||
|
@ -308,39 +361,48 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
|||
Utility.setCompoundDrawablesAlpha(mNextButton, mNextButton.isEnabled() ? 255 : 128);
|
||||
}
|
||||
|
||||
private void updatePortFromSecurityType() {
|
||||
if (mAccountPorts != null) {
|
||||
private void updatePortFromSecurityType()
|
||||
{
|
||||
if (mAccountPorts != null)
|
||||
{
|
||||
int securityType = (Integer)((SpinnerOption)mSecurityTypeView.getSelectedItem()).value;
|
||||
mPortView.setText(Integer.toString(mAccountPorts[securityType]));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
switch (requestCode) {
|
||||
case SELECT_DRAFT_FOLDER:
|
||||
mImapFolderDrafts.setText(data.getStringExtra(ChooseFolder.EXTRA_NEW_FOLDER));
|
||||
return;
|
||||
case SELECT_SENT_FOLDER:
|
||||
mImapFolderSent.setText(data.getStringExtra(ChooseFolder.EXTRA_NEW_FOLDER));
|
||||
return;
|
||||
case SELECT_TRASH_FOLDER:
|
||||
mImapFolderTrash.setText(data.getStringExtra(ChooseFolder.EXTRA_NEW_FOLDER));
|
||||
return;
|
||||
case SELECT_OUTBOX_FOLDER:
|
||||
mImapFolderOutbox.setText(data.getStringExtra(ChooseFolder.EXTRA_NEW_FOLDER));
|
||||
return;
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
if (resultCode == RESULT_OK)
|
||||
{
|
||||
switch (requestCode)
|
||||
{
|
||||
case SELECT_DRAFT_FOLDER:
|
||||
mImapFolderDrafts.setText(data.getStringExtra(ChooseFolder.EXTRA_NEW_FOLDER));
|
||||
return;
|
||||
case SELECT_SENT_FOLDER:
|
||||
mImapFolderSent.setText(data.getStringExtra(ChooseFolder.EXTRA_NEW_FOLDER));
|
||||
return;
|
||||
case SELECT_TRASH_FOLDER:
|
||||
mImapFolderTrash.setText(data.getStringExtra(ChooseFolder.EXTRA_NEW_FOLDER));
|
||||
return;
|
||||
case SELECT_OUTBOX_FOLDER:
|
||||
mImapFolderOutbox.setText(data.getStringExtra(ChooseFolder.EXTRA_NEW_FOLDER));
|
||||
return;
|
||||
}
|
||||
if (Intent.ACTION_EDIT.equals(getIntent().getAction())) {
|
||||
if (Intent.ACTION_EDIT.equals(getIntent().getAction()))
|
||||
{
|
||||
mAccount.save(Preferences.getPreferences(this));
|
||||
finish();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Set the username and password for the outgoing settings to the username and
|
||||
* password the user just set for incoming.
|
||||
*/
|
||||
try {
|
||||
try
|
||||
{
|
||||
URI oldUri = new URI(mAccount.getTransportUri());
|
||||
URI uri = new URI(
|
||||
oldUri.getScheme(),
|
||||
|
@ -351,7 +413,9 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
|||
null,
|
||||
null);
|
||||
mAccount.setTransportUri(uri.toString());
|
||||
} catch (URISyntaxException use) {
|
||||
}
|
||||
catch (URISyntaxException use)
|
||||
{
|
||||
/*
|
||||
* If we can't set up the URL we just continue. It's only for
|
||||
* convenience.
|
||||
|
@ -365,13 +429,18 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
|||
}
|
||||
}
|
||||
|
||||
private void onNext() {
|
||||
try {
|
||||
private void onNext()
|
||||
{
|
||||
try
|
||||
{
|
||||
int securityType = (Integer)((SpinnerOption)mSecurityTypeView.getSelectedItem()).value;
|
||||
String path = null;
|
||||
if (mAccountSchemes[securityType].startsWith("imap")) {
|
||||
if (mAccountSchemes[securityType].startsWith("imap"))
|
||||
{
|
||||
path = "/" + mImapPathPrefixView.getText();
|
||||
} else if (mAccountSchemes[securityType].startsWith("webdav")) {
|
||||
}
|
||||
else if (mAccountSchemes[securityType].startsWith("webdav"))
|
||||
{
|
||||
path = "/" + mWebdavPathPrefixView.getText();
|
||||
path = path + "|" + mWebdavAuthPathView.getText();
|
||||
path = path + "|" + mWebdavMailboxPathView.getText();
|
||||
|
@ -393,54 +462,63 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
|||
mAccount.setTrashFolderName(mImapFolderTrash.getText().toString());
|
||||
mAccount.setOutboxFolderName(mImapFolderOutbox.getText().toString());
|
||||
AccountSetupCheckSettings.actionCheckSettings(this, mAccount, true, false);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
failure(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
switch (v.getId()) {
|
||||
case R.id.next:
|
||||
onNext();
|
||||
break;
|
||||
case R.id.account_imap_folder_drafts:
|
||||
selectImapFolder(SELECT_DRAFT_FOLDER);
|
||||
break;
|
||||
case R.id.account_imap_folder_sent:
|
||||
selectImapFolder(SELECT_SENT_FOLDER);
|
||||
break;
|
||||
case R.id.account_imap_folder_trash:
|
||||
selectImapFolder(SELECT_TRASH_FOLDER);
|
||||
break;
|
||||
case R.id.account_imap_folder_outbox:
|
||||
selectImapFolder(SELECT_OUTBOX_FOLDER);
|
||||
break;
|
||||
public void onClick(View v)
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (v.getId())
|
||||
{
|
||||
case R.id.next:
|
||||
onNext();
|
||||
break;
|
||||
case R.id.account_imap_folder_drafts:
|
||||
selectImapFolder(SELECT_DRAFT_FOLDER);
|
||||
break;
|
||||
case R.id.account_imap_folder_sent:
|
||||
selectImapFolder(SELECT_SENT_FOLDER);
|
||||
break;
|
||||
case R.id.account_imap_folder_trash:
|
||||
selectImapFolder(SELECT_TRASH_FOLDER);
|
||||
break;
|
||||
case R.id.account_imap_folder_outbox:
|
||||
selectImapFolder(SELECT_OUTBOX_FOLDER);
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
failure(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void selectImapFolder(int activityCode) {
|
||||
private void selectImapFolder(int activityCode)
|
||||
{
|
||||
String curFolder = null;
|
||||
switch (activityCode) {
|
||||
case SELECT_DRAFT_FOLDER:
|
||||
curFolder = mImapFolderDrafts.getText().toString();
|
||||
break;
|
||||
case SELECT_SENT_FOLDER:
|
||||
curFolder = mImapFolderSent.getText().toString();
|
||||
break;
|
||||
case SELECT_TRASH_FOLDER:
|
||||
curFolder = mImapFolderTrash.getText().toString();
|
||||
break;
|
||||
case SELECT_OUTBOX_FOLDER:
|
||||
curFolder = mImapFolderOutbox.getText().toString();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Cannot select folder for: " + activityCode);
|
||||
switch (activityCode)
|
||||
{
|
||||
case SELECT_DRAFT_FOLDER:
|
||||
curFolder = mImapFolderDrafts.getText().toString();
|
||||
break;
|
||||
case SELECT_SENT_FOLDER:
|
||||
curFolder = mImapFolderSent.getText().toString();
|
||||
break;
|
||||
case SELECT_TRASH_FOLDER:
|
||||
curFolder = mImapFolderTrash.getText().toString();
|
||||
break;
|
||||
case SELECT_OUTBOX_FOLDER:
|
||||
curFolder = mImapFolderOutbox.getText().toString();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Cannot select folder for: " + activityCode);
|
||||
}
|
||||
|
||||
Intent selectIntent = new Intent(this, ChooseFolder.class);
|
||||
|
@ -450,7 +528,8 @@ public class AccountSetupIncoming extends K9Activity implements OnClickListener
|
|||
startActivityForResult(selectIntent, activityCode);
|
||||
}
|
||||
|
||||
private void failure(Exception use) {
|
||||
private void failure(Exception use)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Failure", use);
|
||||
String toastText = getString(R.string.account_setup_bad_uri, use.getMessage());
|
||||
|
||||
|
|
|
@ -21,7 +21,8 @@ import com.android.email.R;
|
|||
import com.android.email.Utility;
|
||||
import com.android.email.activity.FolderList;
|
||||
|
||||
public class AccountSetupNames extends K9Activity implements OnClickListener {
|
||||
public class AccountSetupNames extends K9Activity implements OnClickListener
|
||||
{
|
||||
private static final String EXTRA_ACCOUNT = "account";
|
||||
|
||||
private EditText mDescription;
|
||||
|
@ -32,14 +33,16 @@ public class AccountSetupNames extends K9Activity implements OnClickListener {
|
|||
|
||||
private Button mDoneButton;
|
||||
|
||||
public static void actionSetNames(Context context, Account account) {
|
||||
public static void actionSetNames(Context context, Account account)
|
||||
{
|
||||
Intent i = new Intent(context, AccountSetupNames.class);
|
||||
i.putExtra(EXTRA_ACCOUNT, account);
|
||||
context.startActivity(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.account_setup_names);
|
||||
mDescription = (EditText)findViewById(R.id.account_description);
|
||||
|
@ -47,15 +50,19 @@ public class AccountSetupNames extends K9Activity implements OnClickListener {
|
|||
mDoneButton = (Button)findViewById(R.id.done);
|
||||
mDoneButton.setOnClickListener(this);
|
||||
|
||||
TextWatcher validationTextWatcher = new TextWatcher() {
|
||||
public void afterTextChanged(Editable s) {
|
||||
TextWatcher validationTextWatcher = new TextWatcher()
|
||||
{
|
||||
public void afterTextChanged(Editable s)
|
||||
{
|
||||
validateFields();
|
||||
}
|
||||
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after)
|
||||
{
|
||||
}
|
||||
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count)
|
||||
{
|
||||
}
|
||||
};
|
||||
mName.addTextChangedListener(validationTextWatcher);
|
||||
|
@ -70,21 +77,26 @@ public class AccountSetupNames extends K9Activity implements OnClickListener {
|
|||
* just leave the saved value alone.
|
||||
*/
|
||||
// mDescription.setText(mAccount.getDescription());
|
||||
if (mAccount.getName() != null) {
|
||||
if (mAccount.getName() != null)
|
||||
{
|
||||
mName.setText(mAccount.getName());
|
||||
}
|
||||
if (!Utility.requiredFieldValid(mName)) {
|
||||
if (!Utility.requiredFieldValid(mName))
|
||||
{
|
||||
mDoneButton.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateFields() {
|
||||
private void validateFields()
|
||||
{
|
||||
mDoneButton.setEnabled(Utility.requiredFieldValid(mName));
|
||||
Utility.setCompoundDrawablesAlpha(mDoneButton, mDoneButton.isEnabled() ? 255 : 128);
|
||||
}
|
||||
|
||||
private void onNext() {
|
||||
if (Utility.requiredFieldValid(mDescription)) {
|
||||
private void onNext()
|
||||
{
|
||||
if (Utility.requiredFieldValid(mDescription))
|
||||
{
|
||||
mAccount.setDescription(mDescription.getText().toString());
|
||||
}
|
||||
mAccount.setName(mName.getText().toString());
|
||||
|
@ -93,11 +105,13 @@ public class AccountSetupNames extends K9Activity implements OnClickListener {
|
|||
finish();
|
||||
}
|
||||
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.done:
|
||||
onNext();
|
||||
break;
|
||||
public void onClick(View v)
|
||||
{
|
||||
switch (v.getId())
|
||||
{
|
||||
case R.id.done:
|
||||
onNext();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,8 @@ import com.android.email.Preferences;
|
|||
import com.android.email.mail.Store;
|
||||
import com.android.email.R;
|
||||
|
||||
public class AccountSetupOptions extends K9Activity implements OnClickListener {
|
||||
public class AccountSetupOptions extends K9Activity implements OnClickListener
|
||||
{
|
||||
private static final String EXTRA_ACCOUNT = "account";
|
||||
|
||||
private static final String EXTRA_MAKE_DEFAULT = "makeDefault";
|
||||
|
@ -34,7 +35,8 @@ public class AccountSetupOptions extends K9Activity implements OnClickListener {
|
|||
|
||||
private Account mAccount;
|
||||
|
||||
public static void actionOptions(Context context, Account account, boolean makeDefault) {
|
||||
public static void actionOptions(Context context, Account account, boolean makeDefault)
|
||||
{
|
||||
Intent i = new Intent(context, AccountSetupOptions.class);
|
||||
i.putExtra(EXTRA_ACCOUNT, account);
|
||||
i.putExtra(EXTRA_MAKE_DEFAULT, makeDefault);
|
||||
|
@ -42,7 +44,8 @@ public class AccountSetupOptions extends K9Activity implements OnClickListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.account_setup_options);
|
||||
|
||||
|
@ -54,7 +57,8 @@ public class AccountSetupOptions extends K9Activity implements OnClickListener {
|
|||
|
||||
findViewById(R.id.next).setOnClickListener(this);
|
||||
|
||||
SpinnerOption checkFrequencies[] = {
|
||||
SpinnerOption checkFrequencies[] =
|
||||
{
|
||||
new SpinnerOption(-1,
|
||||
getString(R.string.account_setup_options_mail_check_frequency_never)),
|
||||
new SpinnerOption(1,
|
||||
|
@ -88,7 +92,8 @@ public class AccountSetupOptions extends K9Activity implements OnClickListener {
|
|||
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
mCheckFrequencyView.setAdapter(checkFrequenciesAdapter);
|
||||
|
||||
SpinnerOption displayCounts[] = {
|
||||
SpinnerOption displayCounts[] =
|
||||
{
|
||||
new SpinnerOption(10,
|
||||
getString(R.string.account_setup_options_mail_display_count_10)),
|
||||
new SpinnerOption(25,
|
||||
|
@ -115,24 +120,31 @@ public class AccountSetupOptions extends K9Activity implements OnClickListener {
|
|||
|
||||
|
||||
boolean isPushCapable = false;
|
||||
try {
|
||||
try
|
||||
{
|
||||
Store store = Store.getInstance(mAccount.getStoreUri(), getApplication());
|
||||
isPushCapable = store.isPushCapable();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Could not get remote store", e);
|
||||
}
|
||||
|
||||
|
||||
if (!isPushCapable) {
|
||||
if (!isPushCapable)
|
||||
{
|
||||
mPushEnable.setVisibility(View.GONE);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
mPushEnable.setChecked(true);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void onDone() {
|
||||
private void onDone()
|
||||
{
|
||||
mAccount.setDescription(mAccount.getEmail());
|
||||
mAccount.setNotifyNewMail(mNotifyView.isChecked());
|
||||
mAccount.setShowOngoing(mNotifySyncView.isChecked());
|
||||
|
@ -141,15 +153,19 @@ public class AccountSetupOptions extends K9Activity implements OnClickListener {
|
|||
mAccount.setDisplayCount((Integer)((SpinnerOption)mDisplayCountView
|
||||
.getSelectedItem()).value);
|
||||
|
||||
if (mPushEnable.isChecked()) {
|
||||
if (mPushEnable.isChecked())
|
||||
{
|
||||
mAccount.setFolderPushMode(Account.FolderMode.FIRST_CLASS);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
mAccount.setFolderPushMode(Account.FolderMode.NONE);
|
||||
}
|
||||
|
||||
mAccount.save(Preferences.getPreferences(this));
|
||||
if (mAccount.equals(Preferences.getPreferences(this).getDefaultAccount()) ||
|
||||
getIntent().getBooleanExtra(EXTRA_MAKE_DEFAULT, false) ) {
|
||||
getIntent().getBooleanExtra(EXTRA_MAKE_DEFAULT, false))
|
||||
{
|
||||
Preferences.getPreferences(this).setDefaultAccount(mAccount);
|
||||
}
|
||||
Email.setServicesEnabled(this);
|
||||
|
@ -157,11 +173,13 @@ public class AccountSetupOptions extends K9Activity implements OnClickListener {
|
|||
finish();
|
||||
}
|
||||
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.next:
|
||||
onDone();
|
||||
break;
|
||||
public void onClick(View v)
|
||||
{
|
||||
switch (v.getId())
|
||||
{
|
||||
case R.id.next:
|
||||
onDone();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,22 +32,27 @@ import com.android.email.R;
|
|||
import com.android.email.Utility;
|
||||
|
||||
public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
|
||||
OnCheckedChangeListener {
|
||||
OnCheckedChangeListener
|
||||
{
|
||||
private static final String EXTRA_ACCOUNT = "account";
|
||||
|
||||
private static final String EXTRA_MAKE_DEFAULT = "makeDefault";
|
||||
|
||||
private static final int smtpPorts[] = {
|
||||
private static final int smtpPorts[] =
|
||||
{
|
||||
25, 465, 465, 25, 25
|
||||
};
|
||||
|
||||
private static final String smtpSchemes[] = {
|
||||
private static final String smtpSchemes[] =
|
||||
{
|
||||
"smtp", "smtp+ssl", "smtp+ssl+", "smtp+tls", "smtp+tls+"
|
||||
};
|
||||
private static final int webdavPorts[] = {
|
||||
private static final int webdavPorts[] =
|
||||
{
|
||||
80, 443, 443, 443, 443
|
||||
};
|
||||
private static final String webdavSchemes[] = {
|
||||
private static final String webdavSchemes[] =
|
||||
{
|
||||
"webdav", "webdav+ssl", "webdav+ssl+", "webdav+tls", "webdav+tls+"
|
||||
};
|
||||
|
||||
|
@ -62,14 +67,16 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
|
|||
private Account mAccount;
|
||||
private boolean mMakeDefault;
|
||||
|
||||
public static void actionOutgoingSettings(Context context, Account account, boolean makeDefault) {
|
||||
public static void actionOutgoingSettings(Context context, Account account, boolean makeDefault)
|
||||
{
|
||||
Intent i = new Intent(context, AccountSetupOutgoing.class);
|
||||
i.putExtra(EXTRA_ACCOUNT, account);
|
||||
i.putExtra(EXTRA_MAKE_DEFAULT, makeDefault);
|
||||
context.startActivity(i);
|
||||
}
|
||||
|
||||
public static void actionEditOutgoingSettings(Context context, Account account) {
|
||||
public static void actionEditOutgoingSettings(Context context, Account account)
|
||||
{
|
||||
Intent i = new Intent(context, AccountSetupOutgoing.class);
|
||||
i.setAction(Intent.ACTION_EDIT);
|
||||
i.putExtra(EXTRA_ACCOUNT, account);
|
||||
|
@ -77,18 +84,23 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.account_setup_outgoing);
|
||||
|
||||
mAccount = (Account)getIntent().getSerializableExtra(EXTRA_ACCOUNT);
|
||||
|
||||
try {
|
||||
if (new URI(mAccount.getStoreUri()).getScheme().startsWith("webdav")) {
|
||||
try
|
||||
{
|
||||
if (new URI(mAccount.getStoreUri()).getScheme().startsWith("webdav"))
|
||||
{
|
||||
mAccount.setTransportUri(mAccount.getStoreUri());
|
||||
AccountSetupCheckSettings.actionCheckSettings(this, mAccount, false, true);
|
||||
}
|
||||
} catch (URISyntaxException e) {
|
||||
}
|
||||
catch (URISyntaxException e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -106,7 +118,8 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
|
|||
mNextButton.setOnClickListener(this);
|
||||
mRequireLoginView.setOnCheckedChangeListener(this);
|
||||
|
||||
SpinnerOption securityTypes[] = {
|
||||
SpinnerOption securityTypes[] =
|
||||
{
|
||||
new SpinnerOption(0, getString(R.string.account_setup_incoming_security_none_label)),
|
||||
new SpinnerOption(1,
|
||||
getString(R.string.account_setup_incoming_security_ssl_optional_label)),
|
||||
|
@ -125,12 +138,15 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
|
|||
* Updates the port when the user changes the security type. This allows
|
||||
* us to show a reasonable default which the user can change.
|
||||
*/
|
||||
mSecurityTypeView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3) {
|
||||
mSecurityTypeView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
|
||||
{
|
||||
public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3)
|
||||
{
|
||||
updatePortFromSecurityType();
|
||||
}
|
||||
|
||||
public void onNothingSelected(AdapterView<?> arg0) {
|
||||
public void onNothingSelected(AdapterView<?> arg0)
|
||||
{
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -138,15 +154,19 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
|
|||
* Calls validateFields() which enables or disables the Next button
|
||||
* based on the fields' validity.
|
||||
*/
|
||||
TextWatcher validationTextWatcher = new TextWatcher() {
|
||||
public void afterTextChanged(Editable s) {
|
||||
TextWatcher validationTextWatcher = new TextWatcher()
|
||||
{
|
||||
public void afterTextChanged(Editable s)
|
||||
{
|
||||
validateFields();
|
||||
}
|
||||
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after)
|
||||
{
|
||||
}
|
||||
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count)
|
||||
{
|
||||
}
|
||||
};
|
||||
mUsernameView.addTextChangedListener(validationTextWatcher);
|
||||
|
@ -166,49 +186,63 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
|
|||
* If we're being reloaded we override the original account with the one
|
||||
* we saved
|
||||
*/
|
||||
if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_ACCOUNT)) {
|
||||
if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_ACCOUNT))
|
||||
{
|
||||
mAccount = (Account)savedInstanceState.getSerializable(EXTRA_ACCOUNT);
|
||||
}
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
URI uri = new URI(mAccount.getTransportUri());
|
||||
String username = null;
|
||||
String password = null;
|
||||
if (uri.getUserInfo() != null) {
|
||||
if (uri.getUserInfo() != null)
|
||||
{
|
||||
String[] userInfoParts = uri.getUserInfo().split(":", 2);
|
||||
username = userInfoParts[0];
|
||||
if (userInfoParts.length > 1) {
|
||||
if (userInfoParts.length > 1)
|
||||
{
|
||||
password = userInfoParts[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (username != null) {
|
||||
if (username != null)
|
||||
{
|
||||
mUsernameView.setText(username);
|
||||
mRequireLoginView.setChecked(true);
|
||||
}
|
||||
|
||||
if (password != null) {
|
||||
if (password != null)
|
||||
{
|
||||
mPasswordView.setText(password);
|
||||
}
|
||||
|
||||
for (int i = 0; i < smtpSchemes.length; i++) {
|
||||
if (smtpSchemes[i].equals(uri.getScheme())) {
|
||||
for (int i = 0; i < smtpSchemes.length; i++)
|
||||
{
|
||||
if (smtpSchemes[i].equals(uri.getScheme()))
|
||||
{
|
||||
SpinnerOption.setSpinnerOptionValue(mSecurityTypeView, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (uri.getHost() != null) {
|
||||
if (uri.getHost() != null)
|
||||
{
|
||||
mServerView.setText(uri.getHost());
|
||||
}
|
||||
|
||||
if (uri.getPort() != -1) {
|
||||
if (uri.getPort() != -1)
|
||||
{
|
||||
mPortView.setText(Integer.toString(uri.getPort()));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
updatePortFromSecurityType();
|
||||
}
|
||||
|
||||
validateFields();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
/*
|
||||
* We should always be able to parse our own settings.
|
||||
*/
|
||||
|
@ -218,12 +252,14 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
public void onSaveInstanceState(Bundle outState)
|
||||
{
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putSerializable(EXTRA_ACCOUNT, mAccount);
|
||||
}
|
||||
|
||||
private void validateFields() {
|
||||
private void validateFields()
|
||||
{
|
||||
mNextButton
|
||||
.setEnabled(
|
||||
Utility.domainFieldValid(mServerView) &&
|
||||
|
@ -234,30 +270,39 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
|
|||
Utility.setCompoundDrawablesAlpha(mNextButton, mNextButton.isEnabled() ? 255 : 128);
|
||||
}
|
||||
|
||||
private void updatePortFromSecurityType() {
|
||||
private void updatePortFromSecurityType()
|
||||
{
|
||||
int securityType = (Integer)((SpinnerOption)mSecurityTypeView.getSelectedItem()).value;
|
||||
mPortView.setText(Integer.toString(smtpPorts[securityType]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
if (Intent.ACTION_EDIT.equals(getIntent().getAction())) {
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
if (resultCode == RESULT_OK)
|
||||
{
|
||||
if (Intent.ACTION_EDIT.equals(getIntent().getAction()))
|
||||
{
|
||||
mAccount.save(Preferences.getPreferences(this));
|
||||
finish();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
AccountSetupOptions.actionOptions(this, mAccount, mMakeDefault);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onNext() {
|
||||
private void onNext()
|
||||
{
|
||||
int securityType = (Integer)((SpinnerOption)mSecurityTypeView.getSelectedItem()).value;
|
||||
URI uri;
|
||||
try {
|
||||
try
|
||||
{
|
||||
String userInfo = null;
|
||||
if (mRequireLoginView.isChecked()) {
|
||||
if (mRequireLoginView.isChecked())
|
||||
{
|
||||
userInfo = mUsernameView.getText().toString() + ":"
|
||||
+ mPasswordView.getText().toString();
|
||||
}
|
||||
|
@ -265,7 +310,9 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
|
|||
Integer.parseInt(mPortView.getText().toString()), null, null, null);
|
||||
mAccount.setTransportUri(uri.toString());
|
||||
AccountSetupCheckSettings.actionCheckSettings(this, mAccount, false, true);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
/*
|
||||
* It's unrecoverable if we cannot create a URI from components that
|
||||
* we validated to be safe.
|
||||
|
@ -275,19 +322,23 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
|
|||
|
||||
}
|
||||
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.next:
|
||||
onNext();
|
||||
break;
|
||||
public void onClick(View v)
|
||||
{
|
||||
switch (v.getId())
|
||||
{
|
||||
case R.id.next:
|
||||
onNext();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
|
||||
{
|
||||
mRequireLoginSettingsView.setVisibility(isChecked ? View.VISIBLE : View.GONE);
|
||||
validateFields();
|
||||
}
|
||||
private void failure(Exception use) {
|
||||
private void failure(Exception use)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Failure", use);
|
||||
String toastText = getString(R.string.account_setup_bad_uri, use.getMessage());
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@ import com.android.email.mail.Store;
|
|||
import com.android.email.mail.Folder.FolderClass;
|
||||
import com.android.email.mail.store.LocalStore.LocalFolder;
|
||||
|
||||
public class FolderSettings extends K9PreferenceActivity {
|
||||
public class FolderSettings extends K9PreferenceActivity
|
||||
{
|
||||
|
||||
private static final String EXTRA_FOLDER_NAME = "com.android.email.folderName";
|
||||
private static final String EXTRA_ACCOUNT = "com.android.email.account";
|
||||
|
@ -40,7 +41,8 @@ public class FolderSettings extends K9PreferenceActivity {
|
|||
private ListPreference mSyncClass;
|
||||
private ListPreference mPushClass;
|
||||
|
||||
public static void actionSettings(Context context, Account account, String folderName) {
|
||||
public static void actionSettings(Context context, Account account, String folderName)
|
||||
{
|
||||
Intent i = new Intent(context, FolderSettings.class);
|
||||
i.putExtra(EXTRA_FOLDER_NAME, folderName);
|
||||
i.putExtra(EXTRA_ACCOUNT, account);
|
||||
|
@ -48,28 +50,35 @@ public class FolderSettings extends K9PreferenceActivity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
String folderName = (String)getIntent().getSerializableExtra(EXTRA_FOLDER_NAME);
|
||||
Account mAccount = (Account)getIntent().getSerializableExtra(EXTRA_ACCOUNT);
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
Store localStore = Store.getInstance(mAccount.getLocalStoreUri(),
|
||||
getApplication());
|
||||
mFolder = (LocalFolder) localStore.getFolder(folderName);
|
||||
mFolder.refresh(Preferences.getPreferences(this));
|
||||
} catch (MessagingException me) {
|
||||
}
|
||||
catch (MessagingException me)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Unable to edit folder " + folderName + " preferences", me);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isPushCapable = false;
|
||||
Store store = null;
|
||||
try {
|
||||
try
|
||||
{
|
||||
store = Store.getInstance(mAccount.getStoreUri(), getApplication());
|
||||
isPushCapable = store.isPushCapable();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Could not get remote store", e);
|
||||
}
|
||||
|
||||
|
@ -81,8 +90,10 @@ public class FolderSettings extends K9PreferenceActivity {
|
|||
mDisplayClass = (ListPreference) findPreference(PREFERENCE_DISPLAY_CLASS);
|
||||
mDisplayClass.setValue(mFolder.getDisplayClass().name());
|
||||
mDisplayClass.setSummary(mDisplayClass.getEntry());
|
||||
mDisplayClass.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mDisplayClass.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
|
||||
{
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue)
|
||||
{
|
||||
final String summary = newValue.toString();
|
||||
int index = mDisplayClass.findIndexOfValue(summary);
|
||||
mDisplayClass.setSummary(mDisplayClass.getEntries()[index]);
|
||||
|
@ -94,8 +105,10 @@ public class FolderSettings extends K9PreferenceActivity {
|
|||
mSyncClass = (ListPreference) findPreference(PREFERENCE_SYNC_CLASS);
|
||||
mSyncClass.setValue(mFolder.getRawSyncClass().name());
|
||||
mSyncClass.setSummary(mSyncClass.getEntry());
|
||||
mSyncClass.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mSyncClass.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
|
||||
{
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue)
|
||||
{
|
||||
final String summary = newValue.toString();
|
||||
int index = mSyncClass.findIndexOfValue(summary);
|
||||
mSyncClass.setSummary(mSyncClass.getEntries()[index]);
|
||||
|
@ -108,8 +121,10 @@ public class FolderSettings extends K9PreferenceActivity {
|
|||
mPushClass.setEnabled(isPushCapable);
|
||||
mPushClass.setValue(mFolder.getRawPushClass().name());
|
||||
mPushClass.setSummary(mPushClass.getEntry());
|
||||
mPushClass.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mPushClass.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
|
||||
{
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue)
|
||||
{
|
||||
final String summary = newValue.toString();
|
||||
int index = mPushClass.findIndexOfValue(summary);
|
||||
mPushClass.setSummary(mPushClass.getEntries()[index]);
|
||||
|
@ -120,31 +135,41 @@ public class FolderSettings extends K9PreferenceActivity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
try {
|
||||
try
|
||||
{
|
||||
mFolder.refresh(Preferences.getPreferences(this));
|
||||
} catch (MessagingException me) {
|
||||
}
|
||||
catch (MessagingException me)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Could not refresh folder preferences for folder " + mFolder.getName(), me);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveSettings() {
|
||||
private void saveSettings()
|
||||
{
|
||||
mFolder.setDisplayClass(FolderClass.valueOf(mDisplayClass.getValue()));
|
||||
mFolder.setSyncClass(FolderClass.valueOf(mSyncClass.getValue()));
|
||||
mFolder.setPushClass(FolderClass.valueOf(mPushClass.getValue()));
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
mFolder.save(Preferences.getPreferences(this));
|
||||
Email.setServicesEnabled(this);
|
||||
} catch (MessagingException me) {
|
||||
}
|
||||
catch (MessagingException me)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Could not refresh folder preferences for folder " + mFolder.getName(), me);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event)
|
||||
{
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK)
|
||||
{
|
||||
saveSettings();
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
|
|
|
@ -24,7 +24,8 @@ import com.android.email.Preferences;
|
|||
import com.android.email.R;
|
||||
import com.android.email.service.MailService;
|
||||
|
||||
public class Prefs extends K9PreferenceActivity {
|
||||
public class Prefs extends K9PreferenceActivity
|
||||
{
|
||||
|
||||
private static final String PREFERENCE_TOP_CATERGORY = "preferences";
|
||||
private static final String PREFERENCE_THEME = "theme";
|
||||
|
@ -40,13 +41,15 @@ public class Prefs extends K9PreferenceActivity {
|
|||
private String initBackgroundOps;
|
||||
|
||||
|
||||
public static void actionPrefs(Context context) {
|
||||
public static void actionPrefs(Context context)
|
||||
{
|
||||
Intent i = new Intent(context, Prefs.class);
|
||||
context.startActivity(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
|
||||
|
@ -55,8 +58,10 @@ public class Prefs extends K9PreferenceActivity {
|
|||
mTheme = (ListPreference) findPreference(PREFERENCE_THEME);
|
||||
mTheme.setValue(String.valueOf(Email.getK9Theme() == android.R.style.Theme ? "dark" : "light"));
|
||||
mTheme.setSummary(mTheme.getEntry());
|
||||
mTheme.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mTheme.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
|
||||
{
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue)
|
||||
{
|
||||
final String summary = newValue.toString();
|
||||
int index = mTheme.findIndexOfValue(summary);
|
||||
mTheme.setSummary(mTheme.getEntries()[index]);
|
||||
|
@ -69,8 +74,10 @@ public class Prefs extends K9PreferenceActivity {
|
|||
initBackgroundOps = Email.getBackgroundOps().toString();
|
||||
mBackgroundOps.setValue(initBackgroundOps);
|
||||
mBackgroundOps.setSummary(mBackgroundOps.getEntry());
|
||||
mBackgroundOps.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mBackgroundOps.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
|
||||
{
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue)
|
||||
{
|
||||
final String summary = newValue.toString();
|
||||
int index = mBackgroundOps.findIndexOfValue(summary);
|
||||
mBackgroundOps.setSummary(mBackgroundOps.getEntries()[index]);
|
||||
|
@ -88,11 +95,13 @@ public class Prefs extends K9PreferenceActivity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
private void saveSettings() {
|
||||
private void saveSettings()
|
||||
{
|
||||
SharedPreferences preferences = Preferences.getPreferences(this).getPreferences();
|
||||
Email.setK9Theme(mTheme.getValue().equals("dark") ? android.R.style.Theme : android.R.style.Theme_Light);
|
||||
Email.DEBUG = mDebugLogging.isChecked();
|
||||
|
@ -100,14 +109,17 @@ public class Prefs extends K9PreferenceActivity {
|
|||
String newBackgroundOps = mBackgroundOps.getValue();
|
||||
Email.setBackgroundOps(newBackgroundOps);
|
||||
Email.save(preferences);
|
||||
if (newBackgroundOps.equals(initBackgroundOps) == false) {
|
||||
if (newBackgroundOps.equals(initBackgroundOps) == false)
|
||||
{
|
||||
MailService.backgroundDataChanged(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event)
|
||||
{
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK)
|
||||
{
|
||||
saveSettings();
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
|
|
|
@ -6,28 +6,34 @@ package com.android.email.activity.setup;
|
|||
|
||||
import android.widget.Spinner;
|
||||
|
||||
public class SpinnerOption {
|
||||
public class SpinnerOption
|
||||
{
|
||||
public Object value;
|
||||
|
||||
public String label;
|
||||
|
||||
public static void setSpinnerOptionValue(Spinner spinner, Object value) {
|
||||
for (int i = 0, count = spinner.getCount(); i < count; i++) {
|
||||
public static void setSpinnerOptionValue(Spinner spinner, Object value)
|
||||
{
|
||||
for (int i = 0, count = spinner.getCount(); i < count; i++)
|
||||
{
|
||||
SpinnerOption so = (SpinnerOption)spinner.getItemAtPosition(i);
|
||||
if (so.value.equals(value)) {
|
||||
if (so.value.equals(value))
|
||||
{
|
||||
spinner.setSelection(i, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SpinnerOption(Object value, String label) {
|
||||
public SpinnerOption(Object value, String label)
|
||||
{
|
||||
this.value = value;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
public String toString()
|
||||
{
|
||||
return label;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,8 @@ import java.math.BigInteger;
|
|||
* @since 1.0-dev
|
||||
* @version $Id$
|
||||
*/
|
||||
public class Base64 implements BinaryEncoder, BinaryDecoder {
|
||||
public class Base64 implements BinaryEncoder, BinaryDecoder
|
||||
{
|
||||
/**
|
||||
* Chunk size per RFC 2045 section 6.8.
|
||||
*
|
||||
|
@ -66,12 +67,13 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* Thanks to "commons" project in ws.apache.org for this code.
|
||||
* http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
|
||||
*/
|
||||
private static final byte[] intToBase64 = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
|
||||
private static final byte[] intToBase64 =
|
||||
{
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -89,14 +91,15 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* Thanks to "commons" project in ws.apache.org for this code.
|
||||
* http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
|
||||
*/
|
||||
private static final byte[] base64ToInt = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
|
||||
55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
|
||||
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
|
||||
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
|
||||
private static final byte[] base64ToInt =
|
||||
{
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
|
||||
55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
|
||||
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
|
||||
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
|
||||
};
|
||||
|
||||
/** Mask used to extract 6 bits, used when encoding */
|
||||
|
@ -178,7 +181,8 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* Default constructor: lineLength is 76, and the lineSeparator is CRLF
|
||||
* when encoding, and all forms can be decoded.
|
||||
*/
|
||||
public Base64() {
|
||||
public Base64()
|
||||
{
|
||||
this(CHUNK_SIZE, CHUNK_SEPARATOR);
|
||||
}
|
||||
|
||||
|
@ -197,7 +201,8 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* If lineLength <= 0, then the output will not be divided into lines (chunks).
|
||||
* Ignored when decoding.
|
||||
*/
|
||||
public Base64(int lineLength) {
|
||||
public Base64(int lineLength)
|
||||
{
|
||||
this(lineLength, CHUNK_SEPARATOR);
|
||||
}
|
||||
|
||||
|
@ -219,21 +224,29 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* @throws IllegalArgumentException The provided lineSeparator included
|
||||
* some base64 characters. That's not going to work!
|
||||
*/
|
||||
public Base64(int lineLength, byte[] lineSeparator) {
|
||||
public Base64(int lineLength, byte[] lineSeparator)
|
||||
{
|
||||
this.lineLength = lineLength;
|
||||
this.lineSeparator = new byte[lineSeparator.length];
|
||||
System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length);
|
||||
if (lineLength > 0) {
|
||||
if (lineLength > 0)
|
||||
{
|
||||
this.encodeSize = 4 + lineSeparator.length;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
this.encodeSize = 4;
|
||||
}
|
||||
this.decodeSize = encodeSize - 1;
|
||||
if (containsBase64Byte(lineSeparator)) {
|
||||
if (containsBase64Byte(lineSeparator))
|
||||
{
|
||||
String sep;
|
||||
try {
|
||||
try
|
||||
{
|
||||
sep = new String(lineSeparator, "UTF-8");
|
||||
} catch (UnsupportedEncodingException uee) {
|
||||
}
|
||||
catch (UnsupportedEncodingException uee)
|
||||
{
|
||||
sep = new String(lineSeparator);
|
||||
}
|
||||
throw new IllegalArgumentException("lineSeperator must not contain base64 characters: [" + sep + "]");
|
||||
|
@ -245,22 +258,32 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
*
|
||||
* @return true if there is Base64 object still available for reading.
|
||||
*/
|
||||
boolean hasData() { return buf != null; }
|
||||
boolean hasData()
|
||||
{
|
||||
return buf != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of buffered data available for reading.
|
||||
*
|
||||
* @return The amount of buffered data available for reading.
|
||||
*/
|
||||
int avail() { return buf != null ? pos - readPos : 0; }
|
||||
int avail()
|
||||
{
|
||||
return buf != null ? pos - readPos : 0;
|
||||
}
|
||||
|
||||
/** Doubles our buffer. */
|
||||
private void resizeBuf() {
|
||||
if (buf == null) {
|
||||
private void resizeBuf()
|
||||
{
|
||||
if (buf == null)
|
||||
{
|
||||
buf = new byte[8192];
|
||||
pos = 0;
|
||||
readPos = 0;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] b = new byte[buf.length * 2];
|
||||
System.arraycopy(buf, 0, b, 0, buf.length);
|
||||
buf = b;
|
||||
|
@ -279,22 +302,30 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* @return The number of bytes successfully extracted into the provided
|
||||
* byte[] array.
|
||||
*/
|
||||
int readResults(byte[] b, int bPos, int bAvail) {
|
||||
if (buf != null) {
|
||||
int readResults(byte[] b, int bPos, int bAvail)
|
||||
{
|
||||
if (buf != null)
|
||||
{
|
||||
int len = Math.min(avail(), bAvail);
|
||||
if (buf != b) {
|
||||
if (buf != b)
|
||||
{
|
||||
System.arraycopy(buf, readPos, b, bPos, len);
|
||||
readPos += len;
|
||||
if (readPos >= pos) {
|
||||
if (readPos >= pos)
|
||||
{
|
||||
buf = null;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Re-using the original consumer's output array is only
|
||||
// allowed for one round.
|
||||
buf = null;
|
||||
}
|
||||
return len;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return eof ? -1 : 0;
|
||||
}
|
||||
}
|
||||
|
@ -308,10 +339,12 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* @param outPos Position to start buffering into.
|
||||
* @param outAvail Amount of bytes available for direct buffering.
|
||||
*/
|
||||
void setInitialBuffer(byte[] out, int outPos, int outAvail) {
|
||||
void setInitialBuffer(byte[] out, int outPos, int outAvail)
|
||||
{
|
||||
// We can re-use consumer's original output array under
|
||||
// special circumstances, saving on some System.arraycopy().
|
||||
if (out != null && out.length == outAvail) {
|
||||
if (out != null && out.length == outAvail)
|
||||
{
|
||||
buf = out;
|
||||
pos = outPos;
|
||||
readPos = outPos;
|
||||
|
@ -334,19 +367,24 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* @param inPos Position to start reading data from.
|
||||
* @param inAvail Amount of bytes available from input for encoding.
|
||||
*/
|
||||
void encode(byte[] in, int inPos, int inAvail) {
|
||||
if (eof) {
|
||||
void encode(byte[] in, int inPos, int inAvail)
|
||||
{
|
||||
if (eof)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// inAvail < 0 is how we're informed of EOF in the underlying data we're
|
||||
// encoding.
|
||||
if (inAvail < 0) {
|
||||
if (inAvail < 0)
|
||||
{
|
||||
eof = true;
|
||||
if (buf == null || buf.length - pos < encodeSize) {
|
||||
if (buf == null || buf.length - pos < encodeSize)
|
||||
{
|
||||
resizeBuf();
|
||||
}
|
||||
switch (modulus) {
|
||||
switch (modulus)
|
||||
{
|
||||
case 1:
|
||||
buf[pos++] = intToBase64[(x >> 2) & MASK_6BITS];
|
||||
buf[pos++] = intToBase64[(x << 4) & MASK_6BITS];
|
||||
|
@ -361,26 +399,36 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
buf[pos++] = PAD;
|
||||
break;
|
||||
}
|
||||
if (lineLength > 0) {
|
||||
if (lineLength > 0)
|
||||
{
|
||||
System.arraycopy(lineSeparator, 0, buf, pos, lineSeparator.length);
|
||||
pos += lineSeparator.length;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < inAvail; i++) {
|
||||
if (buf == null || buf.length - pos < encodeSize) {
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < inAvail; i++)
|
||||
{
|
||||
if (buf == null || buf.length - pos < encodeSize)
|
||||
{
|
||||
resizeBuf();
|
||||
}
|
||||
modulus = (++modulus) % 3;
|
||||
int b = in[inPos++];
|
||||
if (b < 0) { b += 256; }
|
||||
if (b < 0)
|
||||
{
|
||||
b += 256;
|
||||
}
|
||||
x = (x << 8) + b;
|
||||
if (0 == modulus) {
|
||||
if (0 == modulus)
|
||||
{
|
||||
buf[pos++] = intToBase64[(x >> 18) & MASK_6BITS];
|
||||
buf[pos++] = intToBase64[(x >> 12) & MASK_6BITS];
|
||||
buf[pos++] = intToBase64[(x >> 6) & MASK_6BITS];
|
||||
buf[pos++] = intToBase64[x & MASK_6BITS];
|
||||
currentLinePos += 4;
|
||||
if (lineLength > 0 && lineLength <= currentLinePos) {
|
||||
if (lineLength > 0 && lineLength <= currentLinePos)
|
||||
{
|
||||
System.arraycopy(lineSeparator, 0, buf, pos, lineSeparator.length);
|
||||
pos += lineSeparator.length;
|
||||
currentLinePos = 0;
|
||||
|
@ -411,43 +459,55 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* @param inPos Position to start reading data from.
|
||||
* @param inAvail Amount of bytes available from input for encoding.
|
||||
*/
|
||||
void decode(byte[] in, int inPos, int inAvail) {
|
||||
if (eof) {
|
||||
void decode(byte[] in, int inPos, int inAvail)
|
||||
{
|
||||
if (eof)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (inAvail < 0) {
|
||||
if (inAvail < 0)
|
||||
{
|
||||
eof = true;
|
||||
}
|
||||
for (int i = 0; i < inAvail; i++) {
|
||||
if (buf == null || buf.length - pos < decodeSize) {
|
||||
for (int i = 0; i < inAvail; i++)
|
||||
{
|
||||
if (buf == null || buf.length - pos < decodeSize)
|
||||
{
|
||||
resizeBuf();
|
||||
}
|
||||
byte b = in[inPos++];
|
||||
if (b == PAD) {
|
||||
if (b == PAD)
|
||||
{
|
||||
x = x << 6;
|
||||
switch (modulus) {
|
||||
switch (modulus)
|
||||
{
|
||||
case 2:
|
||||
x = x << 6;
|
||||
buf[pos++] = (byte) ((x >> 16) & MASK_8BITS);
|
||||
buf[pos++] = (byte)((x >> 16) & MASK_8BITS);
|
||||
break;
|
||||
case 3:
|
||||
buf[pos++] = (byte) ((x >> 16) & MASK_8BITS);
|
||||
buf[pos++] = (byte) ((x >> 8) & MASK_8BITS);
|
||||
buf[pos++] = (byte)((x >> 16) & MASK_8BITS);
|
||||
buf[pos++] = (byte)((x >> 8) & MASK_8BITS);
|
||||
break;
|
||||
}
|
||||
// WE'RE DONE!!!!
|
||||
eof = true;
|
||||
return;
|
||||
} else {
|
||||
if (b >= 0 && b < base64ToInt.length) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (b >= 0 && b < base64ToInt.length)
|
||||
{
|
||||
int result = base64ToInt[b];
|
||||
if (result >= 0) {
|
||||
if (result >= 0)
|
||||
{
|
||||
modulus = (++modulus) % 4;
|
||||
x = (x << 6) + result;
|
||||
if (modulus == 0) {
|
||||
buf[pos++] = (byte) ((x >> 16) & MASK_8BITS);
|
||||
buf[pos++] = (byte) ((x >> 8) & MASK_8BITS);
|
||||
buf[pos++] = (byte) (x & MASK_8BITS);
|
||||
if (modulus == 0)
|
||||
{
|
||||
buf[pos++] = (byte)((x >> 16) & MASK_8BITS);
|
||||
buf[pos++] = (byte)((x >> 8) & MASK_8BITS);
|
||||
buf[pos++] = (byte)(x & MASK_8BITS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -462,7 +522,8 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* The value to test
|
||||
* @return <code>true</code> if the value is defined in the the base 64 alphabet, <code>false</code> otherwise.
|
||||
*/
|
||||
public static boolean isBase64(byte octet) {
|
||||
public static boolean isBase64(byte octet)
|
||||
{
|
||||
return octet == PAD || (octet >= 0 && octet < base64ToInt.length && base64ToInt[octet] != -1);
|
||||
}
|
||||
|
||||
|
@ -475,9 +536,12 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* @return <code>true</code> if all bytes are valid characters in the Base64 alphabet or if the byte array is
|
||||
* empty; false, otherwise
|
||||
*/
|
||||
public static boolean isArrayByteBase64(byte[] arrayOctet) {
|
||||
for (int i = 0; i < arrayOctet.length; i++) {
|
||||
if (!isBase64(arrayOctet[i]) && !isWhiteSpace(arrayOctet[i])) {
|
||||
public static boolean isArrayByteBase64(byte[] arrayOctet)
|
||||
{
|
||||
for (int i = 0; i < arrayOctet.length; i++)
|
||||
{
|
||||
if (!isBase64(arrayOctet[i]) && !isWhiteSpace(arrayOctet[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -491,9 +555,12 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* byte array to test
|
||||
* @return <code>true</code> if any byte is a valid character in the Base64 alphabet; false herwise
|
||||
*/
|
||||
private static boolean containsBase64Byte(byte[] arrayOctet) {
|
||||
for (int i = 0; i < arrayOctet.length; i++) {
|
||||
if (isBase64(arrayOctet[i])) {
|
||||
private static boolean containsBase64Byte(byte[] arrayOctet)
|
||||
{
|
||||
for (int i = 0; i < arrayOctet.length; i++)
|
||||
{
|
||||
if (isBase64(arrayOctet[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -507,7 +574,8 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* binary data to encode
|
||||
* @return Base64 characters
|
||||
*/
|
||||
public static byte[] encodeBase64(byte[] binaryData) {
|
||||
public static byte[] encodeBase64(byte[] binaryData)
|
||||
{
|
||||
return encodeBase64(binaryData, false);
|
||||
}
|
||||
|
||||
|
@ -518,7 +586,8 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* binary data to encode
|
||||
* @return Base64 characters chunked in 76 character blocks
|
||||
*/
|
||||
public static byte[] encodeBase64Chunked(byte[] binaryData) {
|
||||
public static byte[] encodeBase64Chunked(byte[] binaryData)
|
||||
{
|
||||
return encodeBase64(binaryData, true);
|
||||
}
|
||||
|
||||
|
@ -532,8 +601,10 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* @throws DecoderException
|
||||
* if the parameter supplied is not of type byte[]
|
||||
*/
|
||||
public Object decode(Object pObject) throws DecoderException {
|
||||
if (!(pObject instanceof byte[])) {
|
||||
public Object decode(Object pObject) throws DecoderException
|
||||
{
|
||||
if (!(pObject instanceof byte[]))
|
||||
{
|
||||
throw new DecoderException("Parameter supplied to Base64 decode is not a byte[]");
|
||||
}
|
||||
return decode((byte[]) pObject);
|
||||
|
@ -546,7 +617,8 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* A byte array containing Base64 character data
|
||||
* @return a byte array containing binary data
|
||||
*/
|
||||
public byte[] decode(byte[] pArray) {
|
||||
public byte[] decode(byte[] pArray)
|
||||
{
|
||||
return decodeBase64(pArray);
|
||||
}
|
||||
|
||||
|
@ -561,24 +633,29 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* @throws IllegalArgumentException
|
||||
* Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}
|
||||
*/
|
||||
public static byte[] encodeBase64(byte[] binaryData, boolean isChunked) {
|
||||
if (binaryData == null || binaryData.length == 0) {
|
||||
public static byte[] encodeBase64(byte[] binaryData, boolean isChunked)
|
||||
{
|
||||
if (binaryData == null || binaryData.length == 0)
|
||||
{
|
||||
return binaryData;
|
||||
}
|
||||
Base64 b64 = isChunked ? new Base64() : new Base64(0);
|
||||
|
||||
long len = (binaryData.length * 4) / 3;
|
||||
long mod = len % 4;
|
||||
if (mod != 0) {
|
||||
if (mod != 0)
|
||||
{
|
||||
len += 4 - mod;
|
||||
}
|
||||
if (isChunked) {
|
||||
if (isChunked)
|
||||
{
|
||||
len += (1 + (len / CHUNK_SIZE)) * CHUNK_SEPARATOR.length;
|
||||
}
|
||||
|
||||
if (len > Integer.MAX_VALUE) {
|
||||
if (len > Integer.MAX_VALUE)
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
"Input array too big, output array would be bigger than Integer.MAX_VALUE=" + Integer.MAX_VALUE);
|
||||
"Input array too big, output array would be bigger than Integer.MAX_VALUE=" + Integer.MAX_VALUE);
|
||||
}
|
||||
byte[] buf = new byte[(int) len];
|
||||
b64.setInitialBuffer(buf, 0, buf.length);
|
||||
|
@ -586,7 +663,8 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
b64.encode(binaryData, 0, -1); // Notify encoder of EOF.
|
||||
|
||||
// Encoder might have resized, even though it was unnecessary.
|
||||
if (b64.buf != buf) {
|
||||
if (b64.buf != buf)
|
||||
{
|
||||
b64.readResults(buf, 0, buf.length);
|
||||
}
|
||||
return buf;
|
||||
|
@ -598,8 +676,10 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* @param base64Data Byte array containing Base64 data
|
||||
* @return Array containing decoded data.
|
||||
*/
|
||||
public static byte[] decodeBase64(byte[] base64Data) {
|
||||
if (base64Data == null || base64Data.length == 0) {
|
||||
public static byte[] decodeBase64(byte[] base64Data)
|
||||
{
|
||||
if (base64Data == null || base64Data.length == 0)
|
||||
{
|
||||
return base64Data;
|
||||
}
|
||||
Base64 b64 = new Base64();
|
||||
|
@ -625,12 +705,15 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* @return The data, less whitespace (see RFC 2045).
|
||||
* @deprecated This method is no longer needed
|
||||
*/
|
||||
static byte[] discardWhitespace(byte[] data) {
|
||||
static byte[] discardWhitespace(byte[] data)
|
||||
{
|
||||
byte groomedData[] = new byte[data.length];
|
||||
int bytesCopied = 0;
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
switch (data[i]) {
|
||||
for (int i = 0; i < data.length; i++)
|
||||
{
|
||||
switch (data[i])
|
||||
{
|
||||
case ' ' :
|
||||
case '\n' :
|
||||
case '\r' :
|
||||
|
@ -655,15 +738,17 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* @param byteToCheck the byte to check
|
||||
* @return true if byte is whitespace, false otherwise
|
||||
*/
|
||||
private static boolean isWhiteSpace(byte byteToCheck){
|
||||
switch (byteToCheck) {
|
||||
case ' ' :
|
||||
case '\n' :
|
||||
case '\r' :
|
||||
case '\t' :
|
||||
return true;
|
||||
default :
|
||||
return false;
|
||||
private static boolean isWhiteSpace(byte byteToCheck)
|
||||
{
|
||||
switch (byteToCheck)
|
||||
{
|
||||
case ' ' :
|
||||
case '\n' :
|
||||
case '\r' :
|
||||
case '\t' :
|
||||
return true;
|
||||
default :
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -675,12 +760,15 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* The base-64 encoded data to groom
|
||||
* @return The data, less non-base64 characters (see RFC 2045).
|
||||
*/
|
||||
static byte[] discardNonBase64(byte[] data) {
|
||||
static byte[] discardNonBase64(byte[] data)
|
||||
{
|
||||
byte groomedData[] = new byte[data.length];
|
||||
int bytesCopied = 0;
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
if (isBase64(data[i])) {
|
||||
for (int i = 0; i < data.length; i++)
|
||||
{
|
||||
if (isBase64(data[i]))
|
||||
{
|
||||
groomedData[bytesCopied++] = data[i];
|
||||
}
|
||||
}
|
||||
|
@ -704,8 +792,10 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* @throws EncoderException
|
||||
* if the parameter supplied is not of type byte[]
|
||||
*/
|
||||
public Object encode(Object pObject) throws EncoderException {
|
||||
if (!(pObject instanceof byte[])) {
|
||||
public Object encode(Object pObject) throws EncoderException
|
||||
{
|
||||
if (!(pObject instanceof byte[]))
|
||||
{
|
||||
throw new EncoderException("Parameter supplied to Base64 encode is not a byte[]");
|
||||
}
|
||||
return encode((byte[]) pObject);
|
||||
|
@ -718,7 +808,8 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* a byte array containing binary data
|
||||
* @return A byte array containing only Base64 character data
|
||||
*/
|
||||
public byte[] encode(byte[] pArray) {
|
||||
public byte[] encode(byte[] pArray)
|
||||
{
|
||||
return encodeBase64(pArray, false);
|
||||
}
|
||||
|
||||
|
@ -730,7 +821,8 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* @param pArray a byte array containing base64 character data
|
||||
* @return A BigInteger
|
||||
*/
|
||||
public static BigInteger decodeInteger(byte[] pArray) {
|
||||
public static BigInteger decodeInteger(byte[] pArray)
|
||||
{
|
||||
return new BigInteger(1, decodeBase64(pArray));
|
||||
}
|
||||
|
||||
|
@ -742,8 +834,10 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* @return A byte array containing base64 character data
|
||||
* @throws NullPointerException if null is passed in
|
||||
*/
|
||||
public static byte[] encodeInteger(BigInteger bigInt) {
|
||||
if(bigInt == null) {
|
||||
public static byte[] encodeInteger(BigInteger bigInt)
|
||||
{
|
||||
if (bigInt == null)
|
||||
{
|
||||
throw new NullPointerException("encodeInteger called with null parameter");
|
||||
}
|
||||
|
||||
|
@ -757,14 +851,16 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
* @param bigInt <code>BigInteger</code> to be converted
|
||||
* @return a byte array representation of the BigInteger parameter
|
||||
*/
|
||||
static byte[] toIntegerBytes(BigInteger bigInt) {
|
||||
static byte[] toIntegerBytes(BigInteger bigInt)
|
||||
{
|
||||
int bitlen = bigInt.bitLength();
|
||||
// round bitlen
|
||||
bitlen = ((bitlen + 7) >> 3) << 3;
|
||||
byte[] bigBytes = bigInt.toByteArray();
|
||||
|
||||
if(((bigInt.bitLength() % 8) != 0) &&
|
||||
(((bigInt.bitLength() / 8) + 1) == (bitlen / 8))) {
|
||||
if (((bigInt.bitLength() % 8) != 0) &&
|
||||
(((bigInt.bitLength() / 8) + 1) == (bitlen / 8)))
|
||||
{
|
||||
return bigBytes;
|
||||
}
|
||||
|
||||
|
@ -773,7 +869,8 @@ public class Base64 implements BinaryEncoder, BinaryDecoder {
|
|||
int len = bigBytes.length;
|
||||
|
||||
// if bigInt is exactly byte-aligned, just skip signbit in copy
|
||||
if((bigInt.bitLength() % 8) == 0) {
|
||||
if ((bigInt.bitLength() % 8) == 0)
|
||||
{
|
||||
startSrc = 1;
|
||||
len--;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,8 @@ import java.io.OutputStream;
|
|||
* @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
|
||||
* @since 1.0-dev
|
||||
*/
|
||||
public class Base64OutputStream extends FilterOutputStream {
|
||||
public class Base64OutputStream extends FilterOutputStream
|
||||
{
|
||||
private final boolean doEncode;
|
||||
private final Base64 base64;
|
||||
private final byte[] singleByte = new byte[1];
|
||||
|
@ -51,7 +52,8 @@ public class Base64OutputStream extends FilterOutputStream {
|
|||
*
|
||||
* @param out OutputStream to wrap.
|
||||
*/
|
||||
public Base64OutputStream(OutputStream out) {
|
||||
public Base64OutputStream(OutputStream out)
|
||||
{
|
||||
this(out, true);
|
||||
}
|
||||
|
||||
|
@ -63,7 +65,8 @@ public class Base64OutputStream extends FilterOutputStream {
|
|||
* @param doEncode true if we should encode all data written to us,
|
||||
* false if we should decode.
|
||||
*/
|
||||
public Base64OutputStream(OutputStream out, boolean doEncode) {
|
||||
public Base64OutputStream(OutputStream out, boolean doEncode)
|
||||
{
|
||||
super(out);
|
||||
this.doEncode = doEncode;
|
||||
this.base64 = new Base64();
|
||||
|
@ -85,7 +88,8 @@ public class Base64OutputStream extends FilterOutputStream {
|
|||
* If lineLength <= 0, the lineSeparator is not used.
|
||||
* If doEncode is false lineSeparator is ignored.
|
||||
*/
|
||||
public Base64OutputStream(OutputStream out, boolean doEncode, int lineLength, byte[] lineSeparator) {
|
||||
public Base64OutputStream(OutputStream out, boolean doEncode, int lineLength, byte[] lineSeparator)
|
||||
{
|
||||
super(out);
|
||||
this.doEncode = doEncode;
|
||||
this.base64 = new Base64(lineLength, lineSeparator);
|
||||
|
@ -94,7 +98,8 @@ public class Base64OutputStream extends FilterOutputStream {
|
|||
/**
|
||||
* Writes the specified <code>byte</code> to this output stream.
|
||||
*/
|
||||
public void write(int i) throws IOException {
|
||||
public void write(int i) throws IOException
|
||||
{
|
||||
singleByte[0] = (byte) i;
|
||||
write(singleByte, 0, 1);
|
||||
}
|
||||
|
@ -112,17 +117,28 @@ public class Base64OutputStream extends FilterOutputStream {
|
|||
* @throws NullPointerException if the byte array parameter is null
|
||||
* @throws IndexOutOfBoundsException if offset, len or buffer size are invalid
|
||||
*/
|
||||
public void write(byte b[], int offset, int len) throws IOException {
|
||||
if (b == null) {
|
||||
public void write(byte b[], int offset, int len) throws IOException
|
||||
{
|
||||
if (b == null)
|
||||
{
|
||||
throw new NullPointerException();
|
||||
} else if (offset < 0 || len < 0 || offset + len < 0) {
|
||||
}
|
||||
else if (offset < 0 || len < 0 || offset + len < 0)
|
||||
{
|
||||
throw new IndexOutOfBoundsException();
|
||||
} else if (offset > b.length || offset + len > b.length) {
|
||||
}
|
||||
else if (offset > b.length || offset + len > b.length)
|
||||
{
|
||||
throw new IndexOutOfBoundsException();
|
||||
} else if (len > 0) {
|
||||
if (doEncode) {
|
||||
}
|
||||
else if (len > 0)
|
||||
{
|
||||
if (doEncode)
|
||||
{
|
||||
base64.encode(b, offset, len);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
base64.decode(b, offset, len);
|
||||
}
|
||||
flush(false);
|
||||
|
@ -138,16 +154,20 @@ public class Base64OutputStream extends FilterOutputStream {
|
|||
* OutputStream should also be flushed.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
private void flush(boolean propogate) throws IOException {
|
||||
private void flush(boolean propogate) throws IOException
|
||||
{
|
||||
int avail = base64.avail();
|
||||
if (avail > 0) {
|
||||
if (avail > 0)
|
||||
{
|
||||
byte[] buf = new byte[avail];
|
||||
int c = base64.readResults(buf, 0, avail);
|
||||
if (c > 0) {
|
||||
if (c > 0)
|
||||
{
|
||||
out.write(buf, 0, c);
|
||||
}
|
||||
}
|
||||
if (propogate) {
|
||||
if (propogate)
|
||||
{
|
||||
out.flush();
|
||||
}
|
||||
}
|
||||
|
@ -158,7 +178,8 @@ public class Base64OutputStream extends FilterOutputStream {
|
|||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public void flush() throws IOException {
|
||||
public void flush() throws IOException
|
||||
{
|
||||
flush(true);
|
||||
}
|
||||
|
||||
|
@ -166,11 +187,15 @@ public class Base64OutputStream extends FilterOutputStream {
|
|||
* Closes this output stream, flushing any remaining bytes that must be encoded. The
|
||||
* underlying stream is flushed but not closed.
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
public void close() throws IOException
|
||||
{
|
||||
// Notify encoder of EOF (-1).
|
||||
if (doEncode) {
|
||||
if (doEncode)
|
||||
{
|
||||
base64.encode(singleByte, 0, -1);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
base64.decode(singleByte, 0, -1);
|
||||
}
|
||||
flush();
|
||||
|
|
|
@ -19,43 +19,54 @@ import java.util.List;
|
|||
import java.util.ArrayList;
|
||||
import org.apache.james.mime4j.codec.EncoderUtil;
|
||||
|
||||
public class Address {
|
||||
public class Address
|
||||
{
|
||||
String mAddress;
|
||||
|
||||
String mPersonal;
|
||||
|
||||
public Address(String address, String personal) {
|
||||
public Address(String address, String personal)
|
||||
{
|
||||
this.mAddress = address;
|
||||
if ("".equals(personal)) {
|
||||
if ("".equals(personal))
|
||||
{
|
||||
personal = null;
|
||||
}
|
||||
if (personal!=null) {
|
||||
if (personal!=null)
|
||||
{
|
||||
personal = personal.trim();
|
||||
}
|
||||
this.mPersonal = personal;
|
||||
}
|
||||
|
||||
public Address(String address) {
|
||||
public Address(String address)
|
||||
{
|
||||
this.mAddress = address;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
public String getAddress()
|
||||
{
|
||||
return mAddress;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
public void setAddress(String address)
|
||||
{
|
||||
this.mAddress = address;
|
||||
}
|
||||
|
||||
public String getPersonal() {
|
||||
public String getPersonal()
|
||||
{
|
||||
return mPersonal;
|
||||
}
|
||||
|
||||
public void setPersonal(String personal) {
|
||||
if ("".equals(personal)) {
|
||||
public void setPersonal(String personal)
|
||||
{
|
||||
if ("".equals(personal))
|
||||
{
|
||||
personal = null;
|
||||
}
|
||||
if (personal!=null) {
|
||||
if (personal!=null)
|
||||
{
|
||||
personal = personal.trim();
|
||||
}
|
||||
this.mPersonal = personal;
|
||||
|
@ -64,149 +75,191 @@ public class Address {
|
|||
/**
|
||||
* Parse a comma separated list of email addresses in human readable format and return an
|
||||
* array of Address objects, RFC-822 encoded.
|
||||
*
|
||||
*
|
||||
* @param addressList
|
||||
* @return An array of 0 or more Addresses.
|
||||
*/
|
||||
public static Address[] parseUnencoded(String addressList) {
|
||||
public static Address[] parseUnencoded(String addressList)
|
||||
{
|
||||
List<Address> addresses = new ArrayList<Address>();
|
||||
if (addressList!=null
|
||||
&& !"".equals(addressList)) {
|
||||
&& !"".equals(addressList))
|
||||
{
|
||||
Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(addressList);
|
||||
for (Rfc822Token token : tokens) {
|
||||
for (Rfc822Token token : tokens)
|
||||
{
|
||||
String address = token.getAddress();
|
||||
if (address!=null
|
||||
&& !"".equals(address)) {
|
||||
&& !"".equals(address))
|
||||
{
|
||||
addresses.add(new Address(token.getAddress(), token.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return addresses.toArray(new Address[0]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse a comma separated list of addresses in RFC-822 format and return an
|
||||
* array of Address objects.
|
||||
*
|
||||
*
|
||||
* @param addressList
|
||||
* @return An array of 0 or more Addresses.
|
||||
*/
|
||||
public static Address[] parse(String addressList) {
|
||||
public static Address[] parse(String addressList)
|
||||
{
|
||||
ArrayList<Address> addresses = new ArrayList<Address>();
|
||||
if (addressList == null
|
||||
&& !"".equals(addressList)) {
|
||||
&& !"".equals(addressList))
|
||||
{
|
||||
return new Address[] {};
|
||||
}
|
||||
try {
|
||||
try
|
||||
{
|
||||
MailboxList parsedList = AddressList.parse(addressList).flatten();
|
||||
for (int i = 0, count = parsedList.size(); i < count; i++) {
|
||||
for (int i = 0, count = parsedList.size(); i < count; i++)
|
||||
{
|
||||
org.apache.james.mime4j.field.address.Address address = parsedList.get(i);
|
||||
if (address instanceof NamedMailbox) {
|
||||
if (address instanceof NamedMailbox)
|
||||
{
|
||||
NamedMailbox namedMailbox = (NamedMailbox)address;
|
||||
addresses.add(new Address(namedMailbox.getLocalPart() + "@"
|
||||
+ namedMailbox.getDomain(), namedMailbox.getName()));
|
||||
} else if (address instanceof Mailbox) {
|
||||
+ namedMailbox.getDomain(), namedMailbox.getName()));
|
||||
}
|
||||
else if (address instanceof Mailbox)
|
||||
{
|
||||
Mailbox mailbox = (Mailbox)address;
|
||||
addresses.add(new Address(mailbox.getLocalPart() + "@" + mailbox.getDomain()));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Unknown address type from Mime4J: "
|
||||
+ address.getClass().toString());
|
||||
+ address.getClass().toString());
|
||||
}
|
||||
|
||||
}
|
||||
} catch (ParseException pe) {
|
||||
}
|
||||
catch (ParseException pe)
|
||||
{
|
||||
}
|
||||
return addresses.toArray(new Address[] {});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof Address) {
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (o instanceof Address)
|
||||
{
|
||||
return getAddress().equals(((Address) o).getAddress());
|
||||
}
|
||||
return super.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (mPersonal != null) {
|
||||
public String toString()
|
||||
{
|
||||
if (mPersonal != null)
|
||||
{
|
||||
return Utility.quoteString(mPersonal) + " <" + mAddress + ">";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return mAddress;
|
||||
}
|
||||
}
|
||||
|
||||
public static String toString(Address[] addresses) {
|
||||
if (addresses == null) {
|
||||
public static String toString(Address[] addresses)
|
||||
{
|
||||
if (addresses == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0; i < addresses.length; i++) {
|
||||
for (int i = 0; i < addresses.length; i++)
|
||||
{
|
||||
sb.append(addresses[i].toString());
|
||||
if (i < addresses.length - 1) {
|
||||
if (i < addresses.length - 1)
|
||||
{
|
||||
sb.append(',');
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String toEncodedString() {
|
||||
if (mPersonal != null) {
|
||||
public String toEncodedString()
|
||||
{
|
||||
if (mPersonal != null)
|
||||
{
|
||||
return EncoderUtil.encodeAddressDisplayName(mPersonal) + " <" + mAddress + ">";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return mAddress;
|
||||
}
|
||||
}
|
||||
|
||||
public static String toEncodedString(Address[] addresses) {
|
||||
if (addresses == null) {
|
||||
public static String toEncodedString(Address[] addresses)
|
||||
{
|
||||
if (addresses == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0; i < addresses.length; i++) {
|
||||
for (int i = 0; i < addresses.length; i++)
|
||||
{
|
||||
sb.append(addresses[i].toEncodedString());
|
||||
if (i < addresses.length - 1) {
|
||||
if (i < addresses.length - 1)
|
||||
{
|
||||
sb.append(',');
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns either the personal portion of the Address or the address portion if the personal
|
||||
* is not available.
|
||||
* @return
|
||||
*/
|
||||
public String toFriendly() {
|
||||
if (mPersonal != null && mPersonal.length() > 0) {
|
||||
public String toFriendly()
|
||||
{
|
||||
if (mPersonal != null && mPersonal.length() > 0)
|
||||
{
|
||||
return mPersonal;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
return mAddress;
|
||||
}
|
||||
}
|
||||
|
||||
public static String toFriendly(Address[] addresses) {
|
||||
if (addresses == null) {
|
||||
|
||||
public static String toFriendly(Address[] addresses)
|
||||
{
|
||||
if (addresses == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0; i < addresses.length; i++) {
|
||||
for (int i = 0; i < addresses.length; i++)
|
||||
{
|
||||
sb.append(addresses[i].toFriendly());
|
||||
if (i < addresses.length - 1) {
|
||||
if (i < addresses.length - 1)
|
||||
{
|
||||
sb.append(',');
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unpacks an address list previously packed with packAddressList()
|
||||
* @param list
|
||||
* @return
|
||||
*/
|
||||
public static Address[] unpack(String addressList) {
|
||||
if (addressList == null) {
|
||||
public static Address[] unpack(String addressList)
|
||||
{
|
||||
if (addressList == null)
|
||||
{
|
||||
return new Address[] { };
|
||||
}
|
||||
ArrayList<Address> addresses = new ArrayList<Address>();
|
||||
|
@ -214,18 +267,22 @@ public class Address {
|
|||
int pairStartIndex = 0;
|
||||
int pairEndIndex = 0;
|
||||
int addressEndIndex = 0;
|
||||
while (pairStartIndex < length) {
|
||||
while (pairStartIndex < length)
|
||||
{
|
||||
pairEndIndex = addressList.indexOf(",\u0000", pairStartIndex);
|
||||
if (pairEndIndex == -1) {
|
||||
if (pairEndIndex == -1)
|
||||
{
|
||||
pairEndIndex = length;
|
||||
}
|
||||
addressEndIndex = addressList.indexOf(";\u0000", pairStartIndex);
|
||||
String address = null;
|
||||
String personal = null;
|
||||
if (addressEndIndex == -1 || addressEndIndex > pairEndIndex) {
|
||||
if (addressEndIndex == -1 || addressEndIndex > pairEndIndex)
|
||||
{
|
||||
address = addressList.substring(pairStartIndex, pairEndIndex);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
address = addressList.substring(pairStartIndex, addressEndIndex);
|
||||
personal =addressList.substring(addressEndIndex + 2, pairEndIndex);
|
||||
}
|
||||
|
@ -234,7 +291,7 @@ public class Address {
|
|||
}
|
||||
return addresses.toArray(new Address[] { });
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Packs an address list into a String that is very quick to read
|
||||
* and parse. Packed lists can be unpacked with unpackAddressList()
|
||||
|
@ -243,24 +300,29 @@ public class Address {
|
|||
* @param list
|
||||
* @return
|
||||
*/
|
||||
public static String pack(Address[] addresses) {
|
||||
if (addresses == null) {
|
||||
public static String pack(Address[] addresses)
|
||||
{
|
||||
if (addresses == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0, count = addresses.length; i < count; i++) {
|
||||
for (int i = 0, count = addresses.length; i < count; i++)
|
||||
{
|
||||
Address address = addresses[i];
|
||||
sb.append(address.getAddress());
|
||||
String personal = address.getPersonal();
|
||||
if (personal != null) {
|
||||
sb.append(";\u0000");
|
||||
// Escape quotes in the address part on the way in
|
||||
personal.replaceAll("\"","\\\"");
|
||||
sb.append(personal);
|
||||
}
|
||||
if (i < count - 1) {
|
||||
sb.append(",\u0000");
|
||||
}
|
||||
sb.append(address.getAddress());
|
||||
String personal = address.getPersonal();
|
||||
if (personal != null)
|
||||
{
|
||||
sb.append(";\u0000");
|
||||
// Escape quotes in the address part on the way in
|
||||
personal.replaceAll("\"","\\\"");
|
||||
sb.append(personal);
|
||||
}
|
||||
if (i < count - 1)
|
||||
{
|
||||
sb.append(",\u0000");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
|
||||
package com.android.email.mail;
|
||||
|
||||
public class AuthenticationFailedException extends MessagingException {
|
||||
public class AuthenticationFailedException extends MessagingException
|
||||
{
|
||||
public static final long serialVersionUID = -1;
|
||||
|
||||
public AuthenticationFailedException(String message) {
|
||||
public AuthenticationFailedException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public AuthenticationFailedException(String message, Throwable throwable) {
|
||||
public AuthenticationFailedException(String message, Throwable throwable)
|
||||
{
|
||||
super(message, throwable);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public interface Body {
|
||||
public interface Body
|
||||
{
|
||||
public InputStream getInputStream() throws MessagingException;
|
||||
public void writeTo(OutputStream out) throws IOException, MessagingException;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
|
||||
package com.android.email.mail;
|
||||
|
||||
public abstract class BodyPart implements Part {
|
||||
public abstract class BodyPart implements Part
|
||||
{
|
||||
protected Multipart mParent;
|
||||
|
||||
public Multipart getParent() {
|
||||
public Multipart getParent()
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
|
||||
package com.android.email.mail;
|
||||
|
||||
public class CertificateValidationException extends MessagingException {
|
||||
public class CertificateValidationException extends MessagingException
|
||||
{
|
||||
public static final long serialVersionUID = -1;
|
||||
|
||||
public CertificateValidationException(String message) {
|
||||
public CertificateValidationException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CertificateValidationException(String message, Throwable throwable) {
|
||||
public CertificateValidationException(String message, Throwable throwable)
|
||||
{
|
||||
super(message, throwable);
|
||||
}
|
||||
}
|
|
@ -13,15 +13,17 @@ import java.util.ArrayList;
|
|||
* Part: Indicates that the given Part should be fetched. The provider
|
||||
* is expected have previously created the given BodyPart and stored
|
||||
* any information it needs to download the content.
|
||||
* </pre>
|
||||
* </pre>
|
||||
*/
|
||||
public class FetchProfile extends ArrayList {
|
||||
public class FetchProfile extends ArrayList
|
||||
{
|
||||
/**
|
||||
* Default items available for pre-fetching. It should be expected that any
|
||||
* item fetched by using these items could potentially include all of the
|
||||
* previous items.
|
||||
*/
|
||||
public enum Item {
|
||||
public enum Item
|
||||
{
|
||||
/**
|
||||
* Download the flags of the message.
|
||||
*/
|
||||
|
@ -39,7 +41,7 @@ public class FetchProfile extends ArrayList {
|
|||
* The provider should, if possible, fill in a properly formatted MIME structure in
|
||||
* the message without actually downloading any message data. If the provider is not
|
||||
* capable of this operation it should specifically set the body of the message to null
|
||||
* so that upper levels can detect that a full body download is needed.
|
||||
* so that upper levels can detect that a full body download is needed.
|
||||
*/
|
||||
STRUCTURE,
|
||||
|
||||
|
@ -48,7 +50,7 @@ public class FetchProfile extends ArrayList {
|
|||
* This should generaly be around 50kB.
|
||||
*/
|
||||
BODY_SANE,
|
||||
|
||||
|
||||
/**
|
||||
* The entire message.
|
||||
*/
|
||||
|
|
|
@ -4,7 +4,8 @@ package com.android.email.mail;
|
|||
/**
|
||||
* Flags that can be applied to Messages.
|
||||
*/
|
||||
public enum Flag {
|
||||
public enum Flag
|
||||
{
|
||||
DELETED,
|
||||
SEEN,
|
||||
ANSWERED,
|
||||
|
@ -49,7 +50,7 @@ public enum Flag {
|
|||
* This does not include attachments, which are never downloaded fully.
|
||||
*/
|
||||
X_DOWNLOADED_PARTIAL,
|
||||
|
||||
|
||||
/**
|
||||
* Indicates that the copy of a message to the Sent folder has started.
|
||||
*/
|
||||
|
|
|
@ -3,19 +3,23 @@ package com.android.email.mail;
|
|||
import com.android.email.Preferences;
|
||||
|
||||
|
||||
public abstract class Folder {
|
||||
private String status = null;
|
||||
private long lastChecked = 0;
|
||||
private long lastPush = 0;
|
||||
public enum OpenMode {
|
||||
public abstract class Folder
|
||||
{
|
||||
private String status = null;
|
||||
private long lastChecked = 0;
|
||||
private long lastPush = 0;
|
||||
public enum OpenMode
|
||||
{
|
||||
READ_WRITE, READ_ONLY,
|
||||
}
|
||||
// NONE is obsolete, it will be translated to NO_CLASS for display and to INHERITED for sync and push
|
||||
public enum FolderClass {
|
||||
NONE, NO_CLASS, INHERITED, FIRST_CLASS, SECOND_CLASS;
|
||||
public enum FolderClass
|
||||
{
|
||||
NONE, NO_CLASS, INHERITED, FIRST_CLASS, SECOND_CLASS;
|
||||
}
|
||||
|
||||
public enum FolderType {
|
||||
|
||||
public enum FolderType
|
||||
{
|
||||
HOLDS_FOLDERS, HOLDS_MESSAGES,
|
||||
}
|
||||
|
||||
|
@ -51,10 +55,11 @@ public abstract class Folder {
|
|||
public abstract boolean create(FolderType type) throws MessagingException;
|
||||
|
||||
/**
|
||||
* Create a new folder with a specified display limit. Not abstract to allow
|
||||
* Create a new folder with a specified display limit. Not abstract to allow
|
||||
* remote folders to not override or worry about this call if they don't care to.
|
||||
*/
|
||||
public boolean create(FolderType type, int displayLimit) throws MessagingException {
|
||||
public boolean create(FolderType type, int displayLimit) throws MessagingException
|
||||
{
|
||||
return create(type);
|
||||
}
|
||||
|
||||
|
@ -70,7 +75,7 @@ public abstract class Folder {
|
|||
public abstract Message getMessage(String uid) throws MessagingException;
|
||||
|
||||
public abstract Message[] getMessages(int start, int end, MessageRetrievalListener listener)
|
||||
throws MessagingException;
|
||||
throws MessagingException;
|
||||
|
||||
/**
|
||||
* Fetches the given list of messages. The specified listener is notified as
|
||||
|
@ -82,41 +87,42 @@ public abstract class Folder {
|
|||
* @param listener
|
||||
*/
|
||||
public abstract Message[] getMessages(MessageRetrievalListener listener)
|
||||
throws MessagingException;
|
||||
throws MessagingException;
|
||||
|
||||
public Message[] getMessages(MessageRetrievalListener listener, boolean includeDeleted) throws MessagingException {
|
||||
return getMessages(listener);
|
||||
public Message[] getMessages(MessageRetrievalListener listener, boolean includeDeleted) throws MessagingException
|
||||
{
|
||||
return getMessages(listener);
|
||||
}
|
||||
|
||||
public abstract Message[] getMessages(String[] uids, MessageRetrievalListener listener)
|
||||
throws MessagingException;
|
||||
throws MessagingException;
|
||||
|
||||
public abstract void appendMessages(Message[] messages) throws MessagingException;
|
||||
|
||||
public void copyMessages(Message[] msgs, Folder folder) throws MessagingException {} ;
|
||||
|
||||
|
||||
public void moveMessages(Message[] msgs, Folder folder) throws MessagingException {} ;
|
||||
|
||||
public abstract void setFlags(Message[] messages, Flag[] flags, boolean value)
|
||||
throws MessagingException;
|
||||
|
||||
public abstract void setFlags(Flag[] flags, boolean value) throws MessagingException;
|
||||
throws MessagingException;
|
||||
|
||||
public abstract void setFlags(Flag[] flags, boolean value) throws MessagingException;
|
||||
|
||||
public abstract String getUidFromMessageId(Message message) throws MessagingException;
|
||||
|
||||
public abstract Message[] expunge() throws MessagingException;
|
||||
|
||||
public abstract void fetch(Message[] messages, FetchProfile fp,
|
||||
MessageRetrievalListener listener) throws MessagingException;
|
||||
MessageRetrievalListener listener) throws MessagingException;
|
||||
|
||||
public abstract void delete(boolean recurse) throws MessagingException;
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
public abstract Flag[] getPermanentFlags() throws MessagingException;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param oldPushState
|
||||
* @param message
|
||||
* @return empty string to clear the pushState, null to leave the state as-is
|
||||
|
@ -126,68 +132,70 @@ public abstract class Folder {
|
|||
return null;
|
||||
}
|
||||
|
||||
public boolean supportsFetchingFlags() {
|
||||
public boolean supportsFetchingFlags()
|
||||
{
|
||||
return true;
|
||||
}//isFlagSupported
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
public String toString()
|
||||
{
|
||||
return getName();
|
||||
}
|
||||
|
||||
public long getLastChecked()
|
||||
{
|
||||
return lastChecked;
|
||||
}
|
||||
public long getLastChecked()
|
||||
{
|
||||
return lastChecked;
|
||||
}
|
||||
|
||||
public void setLastChecked(long lastChecked) throws MessagingException
|
||||
{
|
||||
this.lastChecked = lastChecked;
|
||||
}
|
||||
|
||||
public long getLastPush()
|
||||
{
|
||||
return lastPush;
|
||||
}
|
||||
public void setLastChecked(long lastChecked) throws MessagingException
|
||||
{
|
||||
this.lastChecked = lastChecked;
|
||||
}
|
||||
|
||||
public void setLastPush(long lastCheckedDisplay) throws MessagingException
|
||||
{
|
||||
this.lastPush = lastCheckedDisplay;
|
||||
}
|
||||
|
||||
public long getLastUpdate()
|
||||
{
|
||||
return Math.max(getLastChecked(), getLastPush());
|
||||
}
|
||||
public long getLastPush()
|
||||
{
|
||||
return lastPush;
|
||||
}
|
||||
|
||||
public void setLastPush(long lastCheckedDisplay) throws MessagingException
|
||||
{
|
||||
this.lastPush = lastCheckedDisplay;
|
||||
}
|
||||
|
||||
public long getLastUpdate()
|
||||
{
|
||||
return Math.max(getLastChecked(), getLastPush());
|
||||
}
|
||||
|
||||
public FolderClass getDisplayClass()
|
||||
{
|
||||
return FolderClass.NO_CLASS;
|
||||
}
|
||||
|
||||
public FolderClass getSyncClass()
|
||||
{
|
||||
return getDisplayClass();
|
||||
}
|
||||
public FolderClass getPushClass()
|
||||
{
|
||||
return getSyncClass();
|
||||
}
|
||||
|
||||
public FolderClass getDisplayClass()
|
||||
{
|
||||
return FolderClass.NO_CLASS;
|
||||
}
|
||||
|
||||
public FolderClass getSyncClass()
|
||||
{
|
||||
return getDisplayClass();
|
||||
}
|
||||
public FolderClass getPushClass()
|
||||
{
|
||||
return getSyncClass();
|
||||
}
|
||||
|
||||
public void refresh(Preferences preferences) throws MessagingException
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public String getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
public String getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) throws MessagingException
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) throws MessagingException
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -4,8 +4,10 @@ package com.android.email.mail;
|
|||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
|
||||
public abstract class Message implements Part, Body {
|
||||
public enum RecipientType {
|
||||
public abstract class Message implements Part, Body
|
||||
{
|
||||
public enum RecipientType
|
||||
{
|
||||
TO, CC, BCC,
|
||||
}
|
||||
|
||||
|
@ -17,15 +19,18 @@ public abstract class Message implements Part, Body {
|
|||
|
||||
protected Folder mFolder;
|
||||
|
||||
public String getUid() {
|
||||
public String getUid()
|
||||
{
|
||||
return mUid;
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
public void setUid(String uid)
|
||||
{
|
||||
this.mUid = uid;
|
||||
}
|
||||
|
||||
public Folder getFolder() {
|
||||
public Folder getFolder()
|
||||
{
|
||||
return mFolder;
|
||||
}
|
||||
|
||||
|
@ -33,11 +38,13 @@ public abstract class Message implements Part, Body {
|
|||
|
||||
public abstract void setSubject(String subject) throws MessagingException;
|
||||
|
||||
public Date getInternalDate() {
|
||||
public Date getInternalDate()
|
||||
{
|
||||
return mInternalDate;
|
||||
}
|
||||
|
||||
public void setInternalDate(Date internalDate) {
|
||||
public void setInternalDate(Date internalDate)
|
||||
{
|
||||
this.mInternalDate = internalDate;
|
||||
}
|
||||
|
||||
|
@ -50,10 +57,12 @@ public abstract class Message implements Part, Body {
|
|||
public abstract Address[] getRecipients(RecipientType type) throws MessagingException;
|
||||
|
||||
public abstract void setRecipients(RecipientType type, Address[] addresses)
|
||||
throws MessagingException;
|
||||
throws MessagingException;
|
||||
|
||||
public void setRecipient(RecipientType type, Address address) throws MessagingException {
|
||||
setRecipients(type, new Address[] {
|
||||
public void setRecipient(RecipientType type, Address address) throws MessagingException
|
||||
{
|
||||
setRecipients(type, new Address[]
|
||||
{
|
||||
address
|
||||
});
|
||||
}
|
||||
|
@ -67,13 +76,13 @@ public abstract class Message implements Part, Body {
|
|||
public abstract void setReplyTo(Address[] from) throws MessagingException;
|
||||
|
||||
public abstract String getMessageId() throws MessagingException;
|
||||
|
||||
|
||||
public abstract void setInReplyTo(String inReplyTo) throws MessagingException;
|
||||
|
||||
|
||||
public abstract String[] getReferences() throws MessagingException;
|
||||
|
||||
|
||||
public abstract void setReferences(String references) throws MessagingException;
|
||||
|
||||
|
||||
public abstract Body getBody() throws MessagingException;
|
||||
|
||||
public abstract String getContentType() throws MessagingException;
|
||||
|
@ -88,23 +97,29 @@ public abstract class Message implements Part, Body {
|
|||
|
||||
public abstract void setBody(Body body) throws MessagingException;
|
||||
|
||||
public boolean isMimeType(String mimeType) throws MessagingException {
|
||||
public boolean isMimeType(String mimeType) throws MessagingException
|
||||
{
|
||||
return getContentType().startsWith(mimeType);
|
||||
}
|
||||
|
||||
|
||||
public void delete(String trashFolderName) throws MessagingException {} ;
|
||||
|
||||
/*
|
||||
* TODO Refactor Flags at some point to be able to store user defined flags.
|
||||
* TODO Refactor Flags at some point to be able to store user defined flags.
|
||||
*/
|
||||
public Flag[] getFlags() {
|
||||
public Flag[] getFlags()
|
||||
{
|
||||
return mFlags.toArray(new Flag[] {});
|
||||
}
|
||||
|
||||
public void setFlag(Flag flag, boolean set) throws MessagingException {
|
||||
if (set) {
|
||||
public void setFlag(Flag flag, boolean set) throws MessagingException
|
||||
{
|
||||
if (set)
|
||||
{
|
||||
mFlags.add(flag);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
mFlags.remove(flag);
|
||||
}
|
||||
}
|
||||
|
@ -114,13 +129,16 @@ public abstract class Message implements Part, Body {
|
|||
* @param flags
|
||||
* @param set
|
||||
*/
|
||||
public void setFlags(Flag[] flags, boolean set) throws MessagingException {
|
||||
for (Flag flag : flags) {
|
||||
public void setFlags(Flag[] flags, boolean set) throws MessagingException
|
||||
{
|
||||
for (Flag flag : flags)
|
||||
{
|
||||
setFlag(flag, set);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSet(Flag flag) {
|
||||
public boolean isSet(Flag flag)
|
||||
{
|
||||
return mFlags.contains(flag);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,16 +3,25 @@ package com.android.email.mail;
|
|||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class MessageDateComparator implements Comparator<Message> {
|
||||
public int compare(Message o1, Message o2) {
|
||||
try {
|
||||
if (o1.getSentDate() == null) {
|
||||
public class MessageDateComparator implements Comparator<Message>
|
||||
{
|
||||
public int compare(Message o1, Message o2)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (o1.getSentDate() == null)
|
||||
{
|
||||
return 1;
|
||||
} else if (o2.getSentDate() == null) {
|
||||
}
|
||||
else if (o2.getSentDate() == null)
|
||||
{
|
||||
return -1;
|
||||
} else
|
||||
}
|
||||
else
|
||||
return o2.getSentDate().compareTo(o1.getSentDate());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
|
||||
package com.android.email.mail;
|
||||
|
||||
public interface MessageRetrievalListener {
|
||||
public interface MessageRetrievalListener
|
||||
{
|
||||
public void messageStarted(String uid, int number, int ofTotal);
|
||||
|
||||
public void messageFinished(Message message, int number, int ofTotal);
|
||||
|
||||
|
||||
public void messagesFinished(int total);
|
||||
}
|
||||
|
|
|
@ -1,38 +1,43 @@
|
|||
|
||||
package com.android.email.mail;
|
||||
|
||||
public class MessagingException extends Exception {
|
||||
public class MessagingException extends Exception
|
||||
{
|
||||
public static final long serialVersionUID = -1;
|
||||
|
||||
|
||||
boolean permanentFailure = false;
|
||||
|
||||
public MessagingException(String message) {
|
||||
|
||||
public MessagingException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public MessagingException(String message, boolean perm) {
|
||||
|
||||
public MessagingException(String message, boolean perm)
|
||||
{
|
||||
super(message);
|
||||
permanentFailure = perm;
|
||||
}
|
||||
|
||||
public MessagingException(String message, Throwable throwable) {
|
||||
public MessagingException(String message, Throwable throwable)
|
||||
{
|
||||
super(message, throwable);
|
||||
}
|
||||
|
||||
public MessagingException(String message, boolean perm, Throwable throwable) {
|
||||
|
||||
public MessagingException(String message, boolean perm, Throwable throwable)
|
||||
{
|
||||
super(message, throwable);
|
||||
permanentFailure = perm;
|
||||
}
|
||||
|
||||
public boolean isPermanentFailure()
|
||||
{
|
||||
return permanentFailure;
|
||||
return permanentFailure;
|
||||
}
|
||||
|
||||
public void setPermanentFailure(boolean permanentFailure)
|
||||
{
|
||||
this.permanentFailure = permanentFailure;
|
||||
this.permanentFailure = permanentFailure;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -3,46 +3,56 @@ package com.android.email.mail;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public abstract class Multipart implements Body {
|
||||
public abstract class Multipart implements Body
|
||||
{
|
||||
protected Part mParent;
|
||||
|
||||
protected ArrayList<BodyPart> mParts = new ArrayList<BodyPart>();
|
||||
|
||||
protected String mContentType;
|
||||
|
||||
public void addBodyPart(BodyPart part) throws MessagingException {
|
||||
public void addBodyPart(BodyPart part) throws MessagingException
|
||||
{
|
||||
mParts.add(part);
|
||||
}
|
||||
|
||||
public void addBodyPart(BodyPart part, int index) throws MessagingException {
|
||||
public void addBodyPart(BodyPart part, int index) throws MessagingException
|
||||
{
|
||||
mParts.add(index, part);
|
||||
}
|
||||
|
||||
public BodyPart getBodyPart(int index) throws MessagingException {
|
||||
public BodyPart getBodyPart(int index) throws MessagingException
|
||||
{
|
||||
return mParts.get(index);
|
||||
}
|
||||
|
||||
public String getContentType() throws MessagingException {
|
||||
public String getContentType() throws MessagingException
|
||||
{
|
||||
return mContentType;
|
||||
}
|
||||
|
||||
public int getCount() throws MessagingException {
|
||||
public int getCount() throws MessagingException
|
||||
{
|
||||
return mParts.size();
|
||||
}
|
||||
|
||||
public boolean removeBodyPart(BodyPart part) throws MessagingException {
|
||||
public boolean removeBodyPart(BodyPart part) throws MessagingException
|
||||
{
|
||||
return mParts.remove(part);
|
||||
}
|
||||
|
||||
public void removeBodyPart(int index) throws MessagingException {
|
||||
public void removeBodyPart(int index) throws MessagingException
|
||||
{
|
||||
mParts.remove(index);
|
||||
}
|
||||
|
||||
public Part getParent() throws MessagingException {
|
||||
public Part getParent() throws MessagingException
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
|
||||
public void setParent(Part parent) throws MessagingException {
|
||||
public void setParent(Part parent) throws MessagingException
|
||||
{
|
||||
this.mParent = parent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
|
||||
package com.android.email.mail;
|
||||
|
||||
public class NoSuchProviderException extends MessagingException {
|
||||
public class NoSuchProviderException extends MessagingException
|
||||
{
|
||||
public static final long serialVersionUID = -1;
|
||||
|
||||
public NoSuchProviderException(String message) {
|
||||
public NoSuchProviderException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public NoSuchProviderException(String message, Throwable throwable) {
|
||||
public NoSuchProviderException(String message, Throwable throwable)
|
||||
{
|
||||
super(message, throwable);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@ package com.android.email.mail;
|
|||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public interface Part {
|
||||
public interface Part
|
||||
{
|
||||
public void addHeader(String name, String value) throws MessagingException;
|
||||
|
||||
public void removeHeader(String name) throws MessagingException;
|
||||
|
@ -20,7 +21,7 @@ public interface Part {
|
|||
public String[] getHeader(String name) throws MessagingException;
|
||||
|
||||
public int getSize() throws MessagingException;
|
||||
|
||||
|
||||
public boolean isMimeType(String mimeType) throws MessagingException;
|
||||
|
||||
public String getMimeType() throws MessagingException;
|
||||
|
|
|
@ -7,7 +7,7 @@ public interface Pusher
|
|||
public void refresh();
|
||||
public void stop();
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return milliseconds of required refresh interval
|
||||
*/
|
||||
public int getRefreshInterval();
|
||||
|
|
|
@ -19,7 +19,8 @@ import com.android.email.mail.store.WebDavStore;
|
|||
* performance on mobile devices. Implementations of this class should focus on
|
||||
* making as few network connections as possible.
|
||||
*/
|
||||
public abstract class Store {
|
||||
public abstract class Store
|
||||
{
|
||||
/**
|
||||
* A global suggestion to Store implementors on how much of the body
|
||||
* should be returned on FetchProfile.Item.BODY_SANE requests.
|
||||
|
@ -48,26 +49,37 @@ public abstract class Store {
|
|||
* @return
|
||||
* @throws MessagingException
|
||||
*/
|
||||
public synchronized static Store getInstance(String uri, Application application) throws MessagingException {
|
||||
public synchronized static Store getInstance(String uri, Application application) throws MessagingException
|
||||
{
|
||||
Store store = mStores.get(uri);
|
||||
if (store == null) {
|
||||
if (uri.startsWith("imap")) {
|
||||
if (store == null)
|
||||
{
|
||||
if (uri.startsWith("imap"))
|
||||
{
|
||||
store = new ImapStore(uri);
|
||||
} else if (uri.startsWith("pop3")) {
|
||||
}
|
||||
else if (uri.startsWith("pop3"))
|
||||
{
|
||||
store = new Pop3Store(uri);
|
||||
} else if (uri.startsWith("local")) {
|
||||
}
|
||||
else if (uri.startsWith("local"))
|
||||
{
|
||||
store = new LocalStore(uri, application);
|
||||
} else if (uri.startsWith("webdav")) {
|
||||
}
|
||||
else if (uri.startsWith("webdav"))
|
||||
{
|
||||
store = new WebDavStore(uri);
|
||||
}
|
||||
|
||||
|
||||
if (store != null) {
|
||||
if (store != null)
|
||||
{
|
||||
mStores.put(uri, store);
|
||||
}
|
||||
}
|
||||
|
||||
if (store == null) {
|
||||
if (store == null)
|
||||
{
|
||||
throw new MessagingException("Unable to locate an applicable Store for " + uri);
|
||||
}
|
||||
|
||||
|
@ -79,21 +91,24 @@ public abstract class Store {
|
|||
public abstract Folder[] getPersonalNamespaces() throws MessagingException;
|
||||
|
||||
public abstract void checkSettings() throws MessagingException;
|
||||
|
||||
public boolean isCopyCapable() {
|
||||
return false;
|
||||
|
||||
public boolean isCopyCapable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public boolean isMoveCapable() {
|
||||
return false;
|
||||
public boolean isMoveCapable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public boolean isPushCapable() {
|
||||
public boolean isPushCapable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public boolean isSendCapable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public void sendMessages(Message[] messages) throws MessagingException
|
||||
{
|
||||
}
|
||||
|
|
|
@ -4,18 +4,25 @@ package com.android.email.mail;
|
|||
import com.android.email.mail.transport.SmtpTransport;
|
||||
import com.android.email.mail.transport.WebDavTransport;
|
||||
|
||||
public abstract class Transport {
|
||||
public abstract class Transport
|
||||
{
|
||||
protected static final int SOCKET_CONNECT_TIMEOUT = 10000;
|
||||
|
||||
// RFC 1047
|
||||
protected static final int SOCKET_READ_TIMEOUT = 300000;
|
||||
|
||||
public synchronized static Transport getInstance(String uri) throws MessagingException {
|
||||
if (uri.startsWith("smtp")) {
|
||||
public synchronized static Transport getInstance(String uri) throws MessagingException
|
||||
{
|
||||
if (uri.startsWith("smtp"))
|
||||
{
|
||||
return new SmtpTransport(uri);
|
||||
} else if (uri.startsWith("webdav")) {
|
||||
return new WebDavTransport(uri);
|
||||
} else {
|
||||
}
|
||||
else if (uri.startsWith("webdav"))
|
||||
{
|
||||
return new WebDavTransport(uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new MessagingException("Unable to locate an applicable Transport for " + uri);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,38 +24,47 @@ import com.android.email.mail.MessagingException;
|
|||
* and writeTo one time. After writeTo is called, or the InputStream returned from
|
||||
* getInputStream is closed the file is deleted and the Body should be considered disposed of.
|
||||
*/
|
||||
public class BinaryTempFileBody implements Body {
|
||||
public class BinaryTempFileBody implements Body
|
||||
{
|
||||
private static File mTempDirectory;
|
||||
|
||||
private File mFile;
|
||||
|
||||
public static void setTempDirectory(File tempDirectory) {
|
||||
public static void setTempDirectory(File tempDirectory)
|
||||
{
|
||||
mTempDirectory = tempDirectory;
|
||||
}
|
||||
|
||||
public BinaryTempFileBody() throws IOException {
|
||||
if (mTempDirectory == null) {
|
||||
public BinaryTempFileBody() throws IOException
|
||||
{
|
||||
if (mTempDirectory == null)
|
||||
{
|
||||
throw new
|
||||
RuntimeException("setTempDirectory has not been called on BinaryTempFileBody!");
|
||||
RuntimeException("setTempDirectory has not been called on BinaryTempFileBody!");
|
||||
}
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
public OutputStream getOutputStream() throws IOException
|
||||
{
|
||||
mFile = File.createTempFile("body", null, mTempDirectory);
|
||||
mFile.deleteOnExit();
|
||||
return new FileOutputStream(mFile);
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws MessagingException {
|
||||
try {
|
||||
public InputStream getInputStream() throws MessagingException
|
||||
{
|
||||
try
|
||||
{
|
||||
return new BinaryTempFileBodyInputStream(new FileInputStream(mFile));
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
catch (IOException ioe)
|
||||
{
|
||||
throw new MessagingException("Unable to open body", ioe);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeTo(OutputStream out) throws IOException, MessagingException {
|
||||
public void writeTo(OutputStream out) throws IOException, MessagingException
|
||||
{
|
||||
InputStream in = getInputStream();
|
||||
Base64OutputStream base64Out = new Base64OutputStream(out);
|
||||
IOUtils.copy(in, base64Out);
|
||||
|
@ -63,13 +72,16 @@ public class BinaryTempFileBody implements Body {
|
|||
mFile.delete();
|
||||
}
|
||||
|
||||
class BinaryTempFileBodyInputStream extends FilterInputStream {
|
||||
public BinaryTempFileBodyInputStream(InputStream in) {
|
||||
class BinaryTempFileBodyInputStream extends FilterInputStream
|
||||
{
|
||||
public BinaryTempFileBodyInputStream(InputStream in)
|
||||
{
|
||||
super(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
public void close() throws IOException
|
||||
{
|
||||
super.close();
|
||||
mFile.delete();
|
||||
}
|
||||
|
|
|
@ -14,61 +14,76 @@ import com.android.email.mail.MessagingException;
|
|||
* TODO this is a close approximation of Message, need to update along with
|
||||
* Message.
|
||||
*/
|
||||
public class MimeBodyPart extends BodyPart {
|
||||
public class MimeBodyPart extends BodyPart
|
||||
{
|
||||
protected MimeHeader mHeader = new MimeHeader();
|
||||
protected Body mBody;
|
||||
protected int mSize;
|
||||
|
||||
public MimeBodyPart() throws MessagingException {
|
||||
|
||||
public MimeBodyPart() throws MessagingException
|
||||
{
|
||||
this(null);
|
||||
}
|
||||
|
||||
public MimeBodyPart(Body body) throws MessagingException {
|
||||
public MimeBodyPart(Body body) throws MessagingException
|
||||
{
|
||||
this(body, null);
|
||||
}
|
||||
|
||||
public MimeBodyPart(Body body, String mimeType) throws MessagingException {
|
||||
if (mimeType != null) {
|
||||
public MimeBodyPart(Body body, String mimeType) throws MessagingException
|
||||
{
|
||||
if (mimeType != null)
|
||||
{
|
||||
addHeader(MimeHeader.HEADER_CONTENT_TYPE, mimeType);
|
||||
}
|
||||
setBody(body);
|
||||
}
|
||||
|
||||
protected String getFirstHeader(String name) throws MessagingException {
|
||||
protected String getFirstHeader(String name) throws MessagingException
|
||||
{
|
||||
return mHeader.getFirstHeader(name);
|
||||
}
|
||||
|
||||
public void addHeader(String name, String value) throws MessagingException {
|
||||
public void addHeader(String name, String value) throws MessagingException
|
||||
{
|
||||
mHeader.addHeader(name, value);
|
||||
}
|
||||
|
||||
public void setHeader(String name, String value) throws MessagingException {
|
||||
public void setHeader(String name, String value) throws MessagingException
|
||||
{
|
||||
mHeader.setHeader(name, value);
|
||||
}
|
||||
|
||||
public String[] getHeader(String name) throws MessagingException {
|
||||
public String[] getHeader(String name) throws MessagingException
|
||||
{
|
||||
return mHeader.getHeader(name);
|
||||
}
|
||||
|
||||
public void removeHeader(String name) throws MessagingException {
|
||||
public void removeHeader(String name) throws MessagingException
|
||||
{
|
||||
mHeader.removeHeader(name);
|
||||
}
|
||||
|
||||
public Body getBody() throws MessagingException {
|
||||
public Body getBody() throws MessagingException
|
||||
{
|
||||
return mBody;
|
||||
}
|
||||
|
||||
public void setBody(Body body) throws MessagingException {
|
||||
public void setBody(Body body) throws MessagingException
|
||||
{
|
||||
this.mBody = body;
|
||||
if (body instanceof com.android.email.mail.Multipart) {
|
||||
if (body instanceof com.android.email.mail.Multipart)
|
||||
{
|
||||
com.android.email.mail.Multipart multipart = ((com.android.email.mail.Multipart)body);
|
||||
multipart.setParent(this);
|
||||
setHeader(MimeHeader.HEADER_CONTENT_TYPE, multipart.getContentType());
|
||||
}
|
||||
else if (body instanceof TextBody) {
|
||||
else if (body instanceof TextBody)
|
||||
{
|
||||
String contentType = String.format("%s;\n charset=utf-8", getMimeType());
|
||||
String name = MimeUtility.getHeaderParameter(getContentType(), "name");
|
||||
if (name != null) {
|
||||
if (name != null)
|
||||
{
|
||||
contentType += String.format(";\n name=\"%s\"", name);
|
||||
}
|
||||
setHeader(MimeHeader.HEADER_CONTENT_TYPE, contentType);
|
||||
|
@ -80,45 +95,58 @@ public class MimeBodyPart extends BodyPart {
|
|||
}
|
||||
}
|
||||
|
||||
public String getContentType() throws MessagingException {
|
||||
public String getContentType() throws MessagingException
|
||||
{
|
||||
String contentType = getFirstHeader(MimeHeader.HEADER_CONTENT_TYPE);
|
||||
if (contentType == null) {
|
||||
if (contentType == null)
|
||||
{
|
||||
return "text/plain";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return contentType.toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
public String getDisposition() throws MessagingException {
|
||||
public String getDisposition() throws MessagingException
|
||||
{
|
||||
String contentDisposition = getFirstHeader(MimeHeader.HEADER_CONTENT_DISPOSITION);
|
||||
if (contentDisposition == null) {
|
||||
if (contentDisposition == null)
|
||||
{
|
||||
return null;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return contentDisposition;
|
||||
}
|
||||
}
|
||||
|
||||
public String getMimeType() throws MessagingException {
|
||||
public String getMimeType() throws MessagingException
|
||||
{
|
||||
return MimeUtility.getHeaderParameter(getContentType(), null);
|
||||
}
|
||||
|
||||
public boolean isMimeType(String mimeType) throws MessagingException {
|
||||
public boolean isMimeType(String mimeType) throws MessagingException
|
||||
{
|
||||
return getMimeType().equals(mimeType);
|
||||
}
|
||||
|
||||
public int getSize() throws MessagingException {
|
||||
public int getSize() throws MessagingException
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the MimeMessage out in MIME format.
|
||||
*/
|
||||
public void writeTo(OutputStream out) throws IOException, MessagingException {
|
||||
public void writeTo(OutputStream out) throws IOException, MessagingException
|
||||
{
|
||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
|
||||
mHeader.writeTo(out);
|
||||
writer.write("\r\n");
|
||||
writer.flush();
|
||||
if (mBody != null) {
|
||||
if (mBody != null)
|
||||
{
|
||||
mBody.writeTo(out);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@ import com.android.email.Utility;
|
|||
import com.android.email.mail.MessagingException;
|
||||
import org.apache.james.mime4j.codec.EncoderUtil;
|
||||
|
||||
public class MimeHeader {
|
||||
public class MimeHeader
|
||||
{
|
||||
/**
|
||||
* Application specific header that contains Store specific information about an attachment.
|
||||
* In IMAP this contains the IMAP BODYSTRUCTURE part id so that the ImapStore can later
|
||||
|
@ -30,7 +31,8 @@ public class MimeHeader {
|
|||
/**
|
||||
* Fields that should be omitted when writing the header using writeTo()
|
||||
*/
|
||||
private static final String[] writeOmitFields = {
|
||||
private static final String[] writeOmitFields =
|
||||
{
|
||||
// HEADER_ANDROID_ATTACHMENT_DOWNLOADED,
|
||||
// HEADER_ANDROID_ATTACHMENT_ID,
|
||||
HEADER_ANDROID_ATTACHMENT_STORE_DATA
|
||||
|
@ -38,24 +40,30 @@ public class MimeHeader {
|
|||
|
||||
protected ArrayList<Field> mFields = new ArrayList<Field>();
|
||||
|
||||
public void clear() {
|
||||
public void clear()
|
||||
{
|
||||
mFields.clear();
|
||||
}
|
||||
|
||||
public String getFirstHeader(String name) {
|
||||
public String getFirstHeader(String name)
|
||||
{
|
||||
String[] header = getHeader(name);
|
||||
if (header == null) {
|
||||
if (header == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return header[0];
|
||||
}
|
||||
|
||||
public void addHeader(String name, String value) {
|
||||
public void addHeader(String name, String value)
|
||||
{
|
||||
mFields.add(new Field(name, MimeUtility.foldAndEncode(value)));
|
||||
}
|
||||
|
||||
public void setHeader(String name, String value) {
|
||||
if (name == null || value == null) {
|
||||
public void setHeader(String name, String value)
|
||||
{
|
||||
if (name == null || value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
removeHeader(name);
|
||||
|
@ -65,46 +73,58 @@ public class MimeHeader {
|
|||
public List<String> getHeaderNames()
|
||||
{
|
||||
ArrayList<String> names = new ArrayList<String>();
|
||||
for (Field field : mFields) {
|
||||
for (Field field : mFields)
|
||||
{
|
||||
names.add(field.name);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
public String[] getHeader(String name) {
|
||||
public String[] getHeader(String name)
|
||||
{
|
||||
ArrayList<String> values = new ArrayList<String>();
|
||||
for (Field field : mFields) {
|
||||
if (field.name.equalsIgnoreCase(name)) {
|
||||
for (Field field : mFields)
|
||||
{
|
||||
if (field.name.equalsIgnoreCase(name))
|
||||
{
|
||||
values.add(field.value);
|
||||
}
|
||||
}
|
||||
if (values.size() == 0) {
|
||||
if (values.size() == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return values.toArray(new String[] {});
|
||||
}
|
||||
|
||||
public void removeHeader(String name) {
|
||||
public void removeHeader(String name)
|
||||
{
|
||||
ArrayList<Field> removeFields = new ArrayList<Field>();
|
||||
for (Field field : mFields) {
|
||||
if (field.name.equalsIgnoreCase(name)) {
|
||||
for (Field field : mFields)
|
||||
{
|
||||
if (field.name.equalsIgnoreCase(name))
|
||||
{
|
||||
removeFields.add(field);
|
||||
}
|
||||
}
|
||||
mFields.removeAll(removeFields);
|
||||
}
|
||||
|
||||
public void writeTo(OutputStream out) throws IOException, MessagingException {
|
||||
public void writeTo(OutputStream out) throws IOException, MessagingException
|
||||
{
|
||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
|
||||
for (Field field : mFields) {
|
||||
if (!Utility.arrayContains(writeOmitFields, field.name)) {
|
||||
for (Field field : mFields)
|
||||
{
|
||||
if (!Utility.arrayContains(writeOmitFields, field.name))
|
||||
{
|
||||
String v = field.value;
|
||||
|
||||
if (hasToBeEncoded(v)) {
|
||||
if (hasToBeEncoded(v))
|
||||
{
|
||||
v = EncoderUtil.encodeEncodedWord(
|
||||
field.value,
|
||||
EncoderUtil.Usage.WORD_ENTITY
|
||||
);
|
||||
field.value,
|
||||
EncoderUtil.Usage.WORD_ENTITY
|
||||
);
|
||||
}
|
||||
|
||||
writer.write(field.name + ": " + v + "\r\n");
|
||||
|
@ -114,11 +134,15 @@ public class MimeHeader {
|
|||
}
|
||||
|
||||
// encode non printable characters except LF/CR codes.
|
||||
public boolean hasToBeEncoded(String text) {
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
public boolean hasToBeEncoded(String text)
|
||||
{
|
||||
for (int i = 0; i < text.length(); i++)
|
||||
{
|
||||
char c = text.charAt(i);
|
||||
if (c < 0x20 || 0x7e < c) { // non printable
|
||||
if (c != 0x0a && c != 0x0d) { // non LF/CR
|
||||
if (c < 0x20 || 0x7e < c) // non printable
|
||||
{
|
||||
if (c != 0x0a && c != 0x0d) // non LF/CR
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -127,12 +151,14 @@ public class MimeHeader {
|
|||
return false;
|
||||
}
|
||||
|
||||
class Field {
|
||||
class Field
|
||||
{
|
||||
String name;
|
||||
|
||||
String value;
|
||||
|
||||
public Field(String name, String value) {
|
||||
public Field(String name, String value)
|
||||
{
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
|
|
@ -33,38 +33,42 @@ import com.android.email.mail.Part;
|
|||
* An implementation of Message that stores all of it's metadata in RFC 822 and
|
||||
* RFC 2045 style headers.
|
||||
*/
|
||||
public class MimeMessage extends Message {
|
||||
public class MimeMessage extends Message
|
||||
{
|
||||
protected MimeHeader mHeader = new MimeHeader();
|
||||
protected Address[] mFrom;
|
||||
protected Address[] mTo;
|
||||
protected Address[] mCc;
|
||||
protected Address[] mBcc;
|
||||
protected Address[] mReplyTo;
|
||||
|
||||
|
||||
protected String mMessageId;
|
||||
protected String[] mReferences;
|
||||
protected String[] mInReplyTo;
|
||||
|
||||
|
||||
protected Date mSentDate;
|
||||
protected SimpleDateFormat mDateFormat;
|
||||
|
||||
|
||||
protected Body mBody;
|
||||
protected int mSize;
|
||||
|
||||
public MimeMessage() {
|
||||
|
||||
public MimeMessage()
|
||||
{
|
||||
addHeader("Message-ID", generateMessageId());
|
||||
}
|
||||
|
||||
private String generateMessageId() {
|
||||
private String generateMessageId()
|
||||
{
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("<");
|
||||
for (int i = 0; i < 24; i++) {
|
||||
for (int i = 0; i < 24; i++)
|
||||
{
|
||||
sb.append(Integer.toString((int)(Math.random() * 35), 36));
|
||||
}
|
||||
sb.append(".");
|
||||
sb.append(Long.toString(System.currentTimeMillis()));
|
||||
sb.append("@email.android.com>");
|
||||
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
@ -75,24 +79,26 @@ public class MimeMessage extends Message {
|
|||
* @throws IOException
|
||||
* @throws MessagingException
|
||||
*/
|
||||
public MimeMessage(InputStream in) throws IOException, MessagingException {
|
||||
public MimeMessage(InputStream in) throws IOException, MessagingException
|
||||
{
|
||||
parse(in);
|
||||
}
|
||||
|
||||
protected void parse(InputStream in) throws IOException, MessagingException {
|
||||
protected void parse(InputStream in) throws IOException, MessagingException
|
||||
{
|
||||
mHeader.clear();
|
||||
mFrom = null;
|
||||
mTo = null;
|
||||
mCc = null;
|
||||
mBcc = null;
|
||||
mReplyTo = null;
|
||||
|
||||
|
||||
mMessageId = null;
|
||||
mReferences = null;
|
||||
mInReplyTo = null;
|
||||
|
||||
|
||||
mSentDate = null;
|
||||
|
||||
|
||||
mBody = null;
|
||||
|
||||
MimeStreamParser parser = new MimeStreamParser();
|
||||
|
@ -100,17 +106,23 @@ public class MimeMessage extends Message {
|
|||
parser.parse(new EOLConvertingInputStream(in));
|
||||
}
|
||||
|
||||
public Date getReceivedDate() throws MessagingException {
|
||||
public Date getReceivedDate() throws MessagingException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Date getSentDate() throws MessagingException {
|
||||
if (mSentDate == null) {
|
||||
try {
|
||||
public Date getSentDate() throws MessagingException
|
||||
{
|
||||
if (mSentDate == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
DateTimeField field = (DateTimeField)Field.parse("Date: "
|
||||
+ MimeUtility.unfoldAndDecode(getFirstHeader("Date")));
|
||||
+ MimeUtility.unfoldAndDecode(getFirstHeader("Date")));
|
||||
mSentDate = field.getDate();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -125,46 +137,60 @@ public class MimeMessage extends Message {
|
|||
* @param sentDate
|
||||
* @throws com.android.email.mail.MessagingException
|
||||
*/
|
||||
public void addSentDate(Date sentDate) throws MessagingException {
|
||||
if (mDateFormat == null) {
|
||||
public void addSentDate(Date sentDate) throws MessagingException
|
||||
{
|
||||
if (mDateFormat == null)
|
||||
{
|
||||
mDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
|
||||
}
|
||||
addHeader("Date", mDateFormat.format(sentDate));
|
||||
setInternalSentDate(sentDate);
|
||||
}
|
||||
|
||||
public void setSentDate(Date sentDate) throws MessagingException {
|
||||
public void setSentDate(Date sentDate) throws MessagingException
|
||||
{
|
||||
removeHeader("Date");
|
||||
addSentDate(sentDate);
|
||||
}
|
||||
|
||||
public void setInternalSentDate(Date sentDate) throws MessagingException {
|
||||
public void setInternalSentDate(Date sentDate) throws MessagingException
|
||||
{
|
||||
this.mSentDate = sentDate;
|
||||
}
|
||||
|
||||
public String getContentType() throws MessagingException {
|
||||
public String getContentType() throws MessagingException
|
||||
{
|
||||
String contentType = getFirstHeader(MimeHeader.HEADER_CONTENT_TYPE);
|
||||
if (contentType == null) {
|
||||
if (contentType == null)
|
||||
{
|
||||
return "text/plain";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return contentType.toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
public String getDisposition() throws MessagingException {
|
||||
public String getDisposition() throws MessagingException
|
||||
{
|
||||
String contentDisposition = getFirstHeader(MimeHeader.HEADER_CONTENT_DISPOSITION);
|
||||
if (contentDisposition == null) {
|
||||
if (contentDisposition == null)
|
||||
{
|
||||
return null;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return contentDisposition;
|
||||
}
|
||||
}
|
||||
|
||||
public String getMimeType() throws MessagingException {
|
||||
public String getMimeType() throws MessagingException
|
||||
{
|
||||
return MimeUtility.getHeaderParameter(getContentType(), null);
|
||||
}
|
||||
|
||||
public int getSize() throws MessagingException {
|
||||
public int getSize() throws MessagingException
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
|
@ -172,53 +198,81 @@ public class MimeMessage extends Message {
|
|||
* Returns a list of the given recipient type from this message. If no addresses are
|
||||
* found the method returns an empty array.
|
||||
*/
|
||||
public Address[] getRecipients(RecipientType type) throws MessagingException {
|
||||
if (type == RecipientType.TO) {
|
||||
if (mTo == null) {
|
||||
public Address[] getRecipients(RecipientType type) throws MessagingException
|
||||
{
|
||||
if (type == RecipientType.TO)
|
||||
{
|
||||
if (mTo == null)
|
||||
{
|
||||
mTo = Address.parse(MimeUtility.unfold(getFirstHeader("To")));
|
||||
}
|
||||
return mTo;
|
||||
} else if (type == RecipientType.CC) {
|
||||
if (mCc == null) {
|
||||
}
|
||||
else if (type == RecipientType.CC)
|
||||
{
|
||||
if (mCc == null)
|
||||
{
|
||||
mCc = Address.parse(MimeUtility.unfold(getFirstHeader("CC")));
|
||||
}
|
||||
return mCc;
|
||||
} else if (type == RecipientType.BCC) {
|
||||
if (mBcc == null) {
|
||||
}
|
||||
else if (type == RecipientType.BCC)
|
||||
{
|
||||
if (mBcc == null)
|
||||
{
|
||||
mBcc = Address.parse(MimeUtility.unfold(getFirstHeader("BCC")));
|
||||
}
|
||||
return mBcc;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new MessagingException("Unrecognized recipient type.");
|
||||
}
|
||||
}
|
||||
|
||||
public void setRecipients(RecipientType type, Address[] addresses) throws MessagingException {
|
||||
if (type == RecipientType.TO) {
|
||||
if (addresses == null || addresses.length == 0) {
|
||||
public void setRecipients(RecipientType type, Address[] addresses) throws MessagingException
|
||||
{
|
||||
if (type == RecipientType.TO)
|
||||
{
|
||||
if (addresses == null || addresses.length == 0)
|
||||
{
|
||||
removeHeader("To");
|
||||
this.mTo = null;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
setHeader("To", Address.toEncodedString(addresses));
|
||||
this.mTo = addresses;
|
||||
}
|
||||
} else if (type == RecipientType.CC) {
|
||||
if (addresses == null || addresses.length == 0) {
|
||||
}
|
||||
else if (type == RecipientType.CC)
|
||||
{
|
||||
if (addresses == null || addresses.length == 0)
|
||||
{
|
||||
removeHeader("CC");
|
||||
this.mCc = null;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
setHeader("CC", Address.toEncodedString(addresses));
|
||||
this.mCc = addresses;
|
||||
}
|
||||
} else if (type == RecipientType.BCC) {
|
||||
if (addresses == null || addresses.length == 0) {
|
||||
}
|
||||
else if (type == RecipientType.BCC)
|
||||
{
|
||||
if (addresses == null || addresses.length == 0)
|
||||
{
|
||||
removeHeader("BCC");
|
||||
this.mBcc = null;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
setHeader("BCC", Address.toEncodedString(addresses));
|
||||
this.mBcc = addresses;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new MessagingException("Unrecognized recipient type.");
|
||||
}
|
||||
}
|
||||
|
@ -226,18 +280,23 @@ public class MimeMessage extends Message {
|
|||
/**
|
||||
* Returns the unfolded, decoded value of the Subject header.
|
||||
*/
|
||||
public String getSubject() throws MessagingException {
|
||||
public String getSubject() throws MessagingException
|
||||
{
|
||||
return MimeUtility.unfoldAndDecode(getFirstHeader("Subject"));
|
||||
}
|
||||
|
||||
public void setSubject(String subject) throws MessagingException {
|
||||
public void setSubject(String subject) throws MessagingException
|
||||
{
|
||||
setHeader("Subject", subject);
|
||||
}
|
||||
|
||||
public Address[] getFrom() throws MessagingException {
|
||||
if (mFrom == null) {
|
||||
public Address[] getFrom() throws MessagingException
|
||||
{
|
||||
if (mFrom == null)
|
||||
{
|
||||
String list = MimeUtility.unfold(getFirstHeader("From"));
|
||||
if (list == null || list.length() == 0) {
|
||||
if (list == null || list.length() == 0)
|
||||
{
|
||||
list = MimeUtility.unfold(getFirstHeader("Sender"));
|
||||
}
|
||||
mFrom = Address.parse(list);
|
||||
|
@ -245,96 +304,123 @@ public class MimeMessage extends Message {
|
|||
return mFrom;
|
||||
}
|
||||
|
||||
public void setFrom(Address from) throws MessagingException {
|
||||
if (from != null) {
|
||||
public void setFrom(Address from) throws MessagingException
|
||||
{
|
||||
if (from != null)
|
||||
{
|
||||
setHeader("From", from.toEncodedString());
|
||||
this.mFrom = new Address[] {
|
||||
from
|
||||
};
|
||||
} else {
|
||||
this.mFrom = new Address[]
|
||||
{
|
||||
from
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
this.mFrom = null;
|
||||
}
|
||||
}
|
||||
|
||||
public Address[] getReplyTo() throws MessagingException {
|
||||
if (mReplyTo == null) {
|
||||
public Address[] getReplyTo() throws MessagingException
|
||||
{
|
||||
if (mReplyTo == null)
|
||||
{
|
||||
mReplyTo = Address.parse(MimeUtility.unfold(getFirstHeader("Reply-to")));
|
||||
}
|
||||
return mReplyTo;
|
||||
}
|
||||
|
||||
public void setReplyTo(Address[] replyTo) throws MessagingException {
|
||||
if (replyTo == null || replyTo.length == 0) {
|
||||
public void setReplyTo(Address[] replyTo) throws MessagingException
|
||||
{
|
||||
if (replyTo == null || replyTo.length == 0)
|
||||
{
|
||||
removeHeader("Reply-to");
|
||||
mReplyTo = null;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
setHeader("Reply-to", Address.toEncodedString(replyTo));
|
||||
mReplyTo = replyTo;
|
||||
}
|
||||
}
|
||||
|
||||
public String getMessageId() throws MessagingException {
|
||||
if (mMessageId == null) {
|
||||
mMessageId = getFirstHeader("Message-ID");
|
||||
}
|
||||
return mMessageId;
|
||||
public String getMessageId() throws MessagingException
|
||||
{
|
||||
if (mMessageId == null)
|
||||
{
|
||||
mMessageId = getFirstHeader("Message-ID");
|
||||
}
|
||||
return mMessageId;
|
||||
}
|
||||
|
||||
public void setInReplyTo(String inReplyTo) throws MessagingException {
|
||||
setHeader("In-Reply-To", inReplyTo);
|
||||
|
||||
public void setInReplyTo(String inReplyTo) throws MessagingException
|
||||
{
|
||||
setHeader("In-Reply-To", inReplyTo);
|
||||
}
|
||||
|
||||
public String[] getReferences() throws MessagingException {
|
||||
if (mReferences == null) {
|
||||
mReferences = getHeader("References");
|
||||
}
|
||||
return mReferences;
|
||||
|
||||
public String[] getReferences() throws MessagingException
|
||||
{
|
||||
if (mReferences == null)
|
||||
{
|
||||
mReferences = getHeader("References");
|
||||
}
|
||||
return mReferences;
|
||||
}
|
||||
|
||||
public void setReferences(String references) throws MessagingException {
|
||||
setHeader("References", references);
|
||||
|
||||
public void setReferences(String references) throws MessagingException
|
||||
{
|
||||
setHeader("References", references);
|
||||
}
|
||||
|
||||
public void saveChanges() throws MessagingException {
|
||||
|
||||
public void saveChanges() throws MessagingException
|
||||
{
|
||||
throw new MessagingException("saveChanges not yet implemented");
|
||||
}
|
||||
|
||||
public Body getBody() throws MessagingException {
|
||||
public Body getBody() throws MessagingException
|
||||
{
|
||||
return mBody;
|
||||
}
|
||||
|
||||
public void setBody(Body body) throws MessagingException {
|
||||
public void setBody(Body body) throws MessagingException
|
||||
{
|
||||
this.mBody = body;
|
||||
if (body instanceof com.android.email.mail.Multipart) {
|
||||
if (body instanceof com.android.email.mail.Multipart)
|
||||
{
|
||||
com.android.email.mail.Multipart multipart = ((com.android.email.mail.Multipart)body);
|
||||
multipart.setParent(this);
|
||||
setHeader(MimeHeader.HEADER_CONTENT_TYPE, multipart.getContentType());
|
||||
setHeader("MIME-Version", "1.0");
|
||||
}
|
||||
else if (body instanceof TextBody) {
|
||||
else if (body instanceof TextBody)
|
||||
{
|
||||
setHeader(MimeHeader.HEADER_CONTENT_TYPE, String.format("%s;\n charset=utf-8",
|
||||
getMimeType()));
|
||||
getMimeType()));
|
||||
setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64");
|
||||
}
|
||||
}
|
||||
|
||||
protected String getFirstHeader(String name) {
|
||||
protected String getFirstHeader(String name)
|
||||
{
|
||||
return mHeader.getFirstHeader(name);
|
||||
}
|
||||
|
||||
public void addHeader(String name, String value) {
|
||||
public void addHeader(String name, String value)
|
||||
{
|
||||
mHeader.addHeader(name, value);
|
||||
}
|
||||
|
||||
public void setHeader(String name, String value) {
|
||||
public void setHeader(String name, String value)
|
||||
{
|
||||
mHeader.setHeader(name, value);
|
||||
}
|
||||
|
||||
public String[] getHeader(String name) {
|
||||
public String[] getHeader(String name)
|
||||
{
|
||||
return mHeader.getHeader(name);
|
||||
}
|
||||
|
||||
public void removeHeader(String name) {
|
||||
public void removeHeader(String name)
|
||||
{
|
||||
mHeader.removeHeader(name);
|
||||
}
|
||||
|
||||
|
@ -343,140 +429,183 @@ public class MimeMessage extends Message {
|
|||
return mHeader.getHeaderNames();
|
||||
}
|
||||
|
||||
public void writeTo(OutputStream out) throws IOException, MessagingException {
|
||||
public void writeTo(OutputStream out) throws IOException, MessagingException
|
||||
{
|
||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
|
||||
mHeader.writeTo(out);
|
||||
writer.write("\r\n");
|
||||
writer.flush();
|
||||
if (mBody != null) {
|
||||
if (mBody != null)
|
||||
{
|
||||
mBody.writeTo(out);
|
||||
}
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws MessagingException {
|
||||
public InputStream getInputStream() throws MessagingException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
class MimeMessageBuilder implements ContentHandler {
|
||||
class MimeMessageBuilder implements ContentHandler
|
||||
{
|
||||
private Stack stack = new Stack();
|
||||
|
||||
public MimeMessageBuilder() {
|
||||
public MimeMessageBuilder()
|
||||
{
|
||||
}
|
||||
|
||||
private void expect(Class c) {
|
||||
if (!c.isInstance(stack.peek())) {
|
||||
private void expect(Class c)
|
||||
{
|
||||
if (!c.isInstance(stack.peek()))
|
||||
{
|
||||
throw new IllegalStateException("Internal stack error: " + "Expected '"
|
||||
+ c.getName() + "' found '" + stack.peek().getClass().getName() + "'");
|
||||
+ c.getName() + "' found '" + stack.peek().getClass().getName() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
public void startMessage() {
|
||||
if (stack.isEmpty()) {
|
||||
public void startMessage()
|
||||
{
|
||||
if (stack.isEmpty())
|
||||
{
|
||||
stack.push(MimeMessage.this);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
expect(Part.class);
|
||||
try {
|
||||
try
|
||||
{
|
||||
MimeMessage m = new MimeMessage();
|
||||
((Part)stack.peek()).setBody(m);
|
||||
stack.push(m);
|
||||
} catch (MessagingException me) {
|
||||
}
|
||||
catch (MessagingException me)
|
||||
{
|
||||
throw new Error(me);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void endMessage() {
|
||||
public void endMessage()
|
||||
{
|
||||
expect(MimeMessage.class);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
public void startHeader() {
|
||||
public void startHeader()
|
||||
{
|
||||
expect(Part.class);
|
||||
}
|
||||
|
||||
public void field(String fieldData) {
|
||||
public void field(String fieldData)
|
||||
{
|
||||
expect(Part.class);
|
||||
try {
|
||||
try
|
||||
{
|
||||
String[] tokens = fieldData.split(":", 2);
|
||||
((Part)stack.peek()).addHeader(tokens[0], tokens[1].trim());
|
||||
} catch (MessagingException me) {
|
||||
}
|
||||
catch (MessagingException me)
|
||||
{
|
||||
throw new Error(me);
|
||||
}
|
||||
}
|
||||
|
||||
public void endHeader() {
|
||||
public void endHeader()
|
||||
{
|
||||
expect(Part.class);
|
||||
}
|
||||
|
||||
public void startMultipart(BodyDescriptor bd) {
|
||||
public void startMultipart(BodyDescriptor bd)
|
||||
{
|
||||
expect(Part.class);
|
||||
|
||||
Part e = (Part)stack.peek();
|
||||
try {
|
||||
try
|
||||
{
|
||||
MimeMultipart multiPart = new MimeMultipart(e.getContentType());
|
||||
e.setBody(multiPart);
|
||||
stack.push(multiPart);
|
||||
} catch (MessagingException me) {
|
||||
}
|
||||
catch (MessagingException me)
|
||||
{
|
||||
throw new Error(me);
|
||||
}
|
||||
}
|
||||
|
||||
public void body(BodyDescriptor bd, InputStream in) throws IOException {
|
||||
public void body(BodyDescriptor bd, InputStream in) throws IOException
|
||||
{
|
||||
expect(Part.class);
|
||||
Body body = MimeUtility.decodeBody(in, bd.getTransferEncoding());
|
||||
try {
|
||||
try
|
||||
{
|
||||
((Part)stack.peek()).setBody(body);
|
||||
} catch (MessagingException me) {
|
||||
}
|
||||
catch (MessagingException me)
|
||||
{
|
||||
throw new Error(me);
|
||||
}
|
||||
}
|
||||
|
||||
public void endMultipart() {
|
||||
public void endMultipart()
|
||||
{
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
public void startBodyPart() {
|
||||
public void startBodyPart()
|
||||
{
|
||||
expect(MimeMultipart.class);
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
MimeBodyPart bodyPart = new MimeBodyPart();
|
||||
((MimeMultipart)stack.peek()).addBodyPart(bodyPart);
|
||||
stack.push(bodyPart);
|
||||
} catch (MessagingException me) {
|
||||
}
|
||||
catch (MessagingException me)
|
||||
{
|
||||
throw new Error(me);
|
||||
}
|
||||
}
|
||||
|
||||
public void endBodyPart() {
|
||||
public void endBodyPart()
|
||||
{
|
||||
expect(BodyPart.class);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
public void epilogue(InputStream is) throws IOException {
|
||||
public void epilogue(InputStream is) throws IOException
|
||||
{
|
||||
expect(MimeMultipart.class);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
int b;
|
||||
while ((b = is.read()) != -1) {
|
||||
while ((b = is.read()) != -1)
|
||||
{
|
||||
sb.append((char)b);
|
||||
}
|
||||
// ((Multipart) stack.peek()).setEpilogue(sb.toString());
|
||||
}
|
||||
|
||||
public void preamble(InputStream is) throws IOException {
|
||||
public void preamble(InputStream is) throws IOException
|
||||
{
|
||||
expect(MimeMultipart.class);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
int b;
|
||||
while ((b = is.read()) != -1) {
|
||||
while ((b = is.read()) != -1)
|
||||
{
|
||||
sb.append((char)b);
|
||||
}
|
||||
try {
|
||||
try
|
||||
{
|
||||
((MimeMultipart)stack.peek()).setPreamble(sb.toString());
|
||||
} catch (MessagingException me) {
|
||||
}
|
||||
catch (MessagingException me)
|
||||
{
|
||||
throw new Error(me);
|
||||
}
|
||||
}
|
||||
|
||||
public void raw(InputStream is) throws IOException {
|
||||
public void raw(InputStream is) throws IOException
|
||||
{
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ import com.android.email.mail.BodyPart;
|
|||
import com.android.email.mail.MessagingException;
|
||||
import com.android.email.mail.Multipart;
|
||||
|
||||
public class MimeMultipart extends Multipart {
|
||||
public class MimeMultipart extends Multipart
|
||||
{
|
||||
protected String mPreamble;
|
||||
|
||||
protected String mContentType;
|
||||
|
@ -20,76 +21,93 @@ public class MimeMultipart extends Multipart {
|
|||
|
||||
protected String mSubType;
|
||||
|
||||
public MimeMultipart() throws MessagingException {
|
||||
public MimeMultipart() throws MessagingException
|
||||
{
|
||||
mBoundary = generateBoundary();
|
||||
setSubType("mixed");
|
||||
}
|
||||
|
||||
public MimeMultipart(String contentType) throws MessagingException {
|
||||
public MimeMultipart(String contentType) throws MessagingException
|
||||
{
|
||||
this.mContentType = contentType;
|
||||
try {
|
||||
try
|
||||
{
|
||||
mSubType = MimeUtility.getHeaderParameter(contentType, null).split("/")[1];
|
||||
mBoundary = MimeUtility.getHeaderParameter(contentType, "boundary");
|
||||
if (mBoundary == null) {
|
||||
if (mBoundary == null)
|
||||
{
|
||||
throw new MessagingException("MultiPart does not contain boundary: " + contentType);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new MessagingException(
|
||||
"Invalid MultiPart Content-Type; must contain subtype and boundary. ("
|
||||
+ contentType + ")", e);
|
||||
"Invalid MultiPart Content-Type; must contain subtype and boundary. ("
|
||||
+ contentType + ")", e);
|
||||
}
|
||||
}
|
||||
|
||||
public String generateBoundary() {
|
||||
public String generateBoundary()
|
||||
{
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("----");
|
||||
for (int i = 0; i < 30; i++) {
|
||||
for (int i = 0; i < 30; i++)
|
||||
{
|
||||
sb.append(Integer.toString((int)(Math.random() * 35), 36));
|
||||
}
|
||||
return sb.toString().toUpperCase();
|
||||
}
|
||||
|
||||
public String getPreamble() throws MessagingException {
|
||||
public String getPreamble() throws MessagingException
|
||||
{
|
||||
return mPreamble;
|
||||
}
|
||||
|
||||
public void setPreamble(String preamble) throws MessagingException {
|
||||
public void setPreamble(String preamble) throws MessagingException
|
||||
{
|
||||
this.mPreamble = preamble;
|
||||
}
|
||||
|
||||
public String getContentType() throws MessagingException {
|
||||
public String getContentType() throws MessagingException
|
||||
{
|
||||
return mContentType;
|
||||
}
|
||||
|
||||
public void setSubType(String subType) throws MessagingException {
|
||||
public void setSubType(String subType) throws MessagingException
|
||||
{
|
||||
this.mSubType = subType;
|
||||
mContentType = String.format("multipart/%s; boundary=\"%s\"", subType, mBoundary);
|
||||
}
|
||||
|
||||
public void writeTo(OutputStream out) throws IOException, MessagingException {
|
||||
public void writeTo(OutputStream out) throws IOException, MessagingException
|
||||
{
|
||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
|
||||
|
||||
if (mPreamble != null) {
|
||||
if (mPreamble != null)
|
||||
{
|
||||
writer.write(mPreamble + "\r\n");
|
||||
}
|
||||
|
||||
if(mParts.size() == 0){
|
||||
if (mParts.size() == 0)
|
||||
{
|
||||
writer.write("--" + mBoundary + "\r\n");
|
||||
}
|
||||
|
||||
for (int i = 0, count = mParts.size(); i < count; i++) {
|
||||
for (int i = 0, count = mParts.size(); i < count; i++)
|
||||
{
|
||||
BodyPart bodyPart = (BodyPart)mParts.get(i);
|
||||
writer.write("--" + mBoundary + "\r\n");
|
||||
writer.flush();
|
||||
bodyPart.writeTo(out);
|
||||
writer.write("\r\n");
|
||||
}
|
||||
|
||||
|
||||
writer.write("--" + mBoundary + "--\r\n");
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws MessagingException {
|
||||
public InputStream getInputStream() throws MessagingException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,29 +26,36 @@ import com.android.email.mail.MessagingException;
|
|||
import com.android.email.mail.Multipart;
|
||||
import com.android.email.mail.Part;
|
||||
|
||||
public class MimeUtility {
|
||||
public class MimeUtility
|
||||
{
|
||||
|
||||
|
||||
public static String unfold(String s) {
|
||||
if (s == null) {
|
||||
|
||||
public static String unfold(String s)
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return s.replaceAll("\r|\n", "");
|
||||
}
|
||||
|
||||
public static String decode(String s) {
|
||||
if (s == null) {
|
||||
public static String decode(String s)
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return DecoderUtil.decodeEncodedWords(s);
|
||||
}
|
||||
|
||||
public static String unfoldAndDecode(String s) {
|
||||
public static String unfoldAndDecode(String s)
|
||||
{
|
||||
return decode(unfold(s));
|
||||
}
|
||||
|
||||
// TODO implement proper foldAndEncode
|
||||
public static String foldAndEncode(String s) {
|
||||
public static String foldAndEncode(String s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -63,22 +70,29 @@ public class MimeUtility {
|
|||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public static String getHeaderParameter(String header, String name) {
|
||||
if (header == null) {
|
||||
public static String getHeaderParameter(String header, String name)
|
||||
{
|
||||
if (header == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
header = header.replaceAll("\r|\n", "");
|
||||
String[] parts = header.split(";");
|
||||
if (name == null) {
|
||||
if (name == null)
|
||||
{
|
||||
return parts[0];
|
||||
}
|
||||
for (String part : parts) {
|
||||
if (part.trim().toLowerCase().startsWith(name.toLowerCase())) {
|
||||
for (String part : parts)
|
||||
{
|
||||
if (part.trim().toLowerCase().startsWith(name.toLowerCase()))
|
||||
{
|
||||
String parameter = part.split("=", 2)[1].trim();
|
||||
if (parameter.startsWith("\"") && parameter.endsWith("\"")) {
|
||||
if (parameter.startsWith("\"") && parameter.endsWith("\""))
|
||||
{
|
||||
return parameter.substring(1, parameter.length() - 1);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
|
@ -87,38 +101,50 @@ public class MimeUtility {
|
|||
}
|
||||
|
||||
public static Part findFirstPartByMimeType(Part part, String mimeType)
|
||||
throws MessagingException {
|
||||
if (part.getBody() instanceof Multipart) {
|
||||
throws MessagingException
|
||||
{
|
||||
if (part.getBody() instanceof Multipart)
|
||||
{
|
||||
Multipart multipart = (Multipart)part.getBody();
|
||||
for (int i = 0, count = multipart.getCount(); i < count; i++) {
|
||||
for (int i = 0, count = multipart.getCount(); i < count; i++)
|
||||
{
|
||||
BodyPart bodyPart = multipart.getBodyPart(i);
|
||||
Part ret = findFirstPartByMimeType(bodyPart, mimeType);
|
||||
if (ret != null) {
|
||||
if (ret != null)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (part.getMimeType().equalsIgnoreCase(mimeType)) {
|
||||
else if (part.getMimeType().equalsIgnoreCase(mimeType))
|
||||
{
|
||||
return part;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Part findPartByContentId(Part part, String contentId) throws Exception {
|
||||
if (part.getBody() instanceof Multipart) {
|
||||
public static Part findPartByContentId(Part part, String contentId) throws Exception
|
||||
{
|
||||
if (part.getBody() instanceof Multipart)
|
||||
{
|
||||
Multipart multipart = (Multipart)part.getBody();
|
||||
for (int i = 0, count = multipart.getCount(); i < count; i++) {
|
||||
for (int i = 0, count = multipart.getCount(); i < count; i++)
|
||||
{
|
||||
BodyPart bodyPart = multipart.getBodyPart(i);
|
||||
Part ret = findPartByContentId(bodyPart, contentId);
|
||||
if (ret != null) {
|
||||
if (ret != null)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
String[] header = part.getHeader("Content-ID");
|
||||
if (header != null) {
|
||||
for (String s : header) {
|
||||
if (s.equals(contentId)) {
|
||||
if (header != null)
|
||||
{
|
||||
for (String s : header)
|
||||
{
|
||||
if (s.equals(contentId))
|
||||
{
|
||||
return part;
|
||||
}
|
||||
}
|
||||
|
@ -133,19 +159,25 @@ public class MimeUtility {
|
|||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static String getTextFromPart(Part part) {
|
||||
Charset mCharsetConverter;
|
||||
public static String getTextFromPart(Part part)
|
||||
{
|
||||
Charset mCharsetConverter;
|
||||
|
||||
try {
|
||||
if (part != null && part.getBody() != null) {
|
||||
try
|
||||
{
|
||||
if (part != null && part.getBody() != null)
|
||||
{
|
||||
Body body = part.getBody();
|
||||
if (body instanceof TextBody) {
|
||||
if (body instanceof TextBody)
|
||||
{
|
||||
return ((TextBody)body).getText();
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
InputStream in = part.getBody().getInputStream();
|
||||
String mimeType = part.getMimeType();
|
||||
if (mimeType != null && MimeUtility.mimeTypeMatches(mimeType, "text/*")) {
|
||||
if (mimeType != null && MimeUtility.mimeTypeMatches(mimeType, "text/*"))
|
||||
{
|
||||
/*
|
||||
* Now we read the part into a buffer for further processing. Because
|
||||
* the stream is now wrapped we'll remove any transfer encoding at this point.
|
||||
|
@ -161,20 +193,23 @@ public class MimeUtility {
|
|||
/*
|
||||
* We've got a text part, so let's see if it needs to be processed further.
|
||||
*/
|
||||
if (charset != null) {
|
||||
if (charset != null)
|
||||
{
|
||||
/*
|
||||
* See if there is conversion from the MIME charset to the Java one.
|
||||
*/
|
||||
mCharsetConverter = Charset.forName(charset);
|
||||
charset = mCharsetConverter.name();
|
||||
}
|
||||
if (charset != null) {
|
||||
if (charset != null)
|
||||
{
|
||||
/*
|
||||
* We've got a charset encoding, so decode using it.
|
||||
*/
|
||||
return new String(bytes, 0, bytes.length, charset);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
/*
|
||||
* No encoding, so use us-ascii, which is the standard.
|
||||
*/
|
||||
|
@ -184,7 +219,8 @@ public class MimeUtility {
|
|||
}
|
||||
}//if text body
|
||||
}
|
||||
catch (Exception e) {
|
||||
catch (Exception e)
|
||||
{
|
||||
/*
|
||||
* If we are not able to process the body there's nothing we can do about it. Return
|
||||
* null and let the upper layers handle the missing content.
|
||||
|
@ -201,10 +237,11 @@ public class MimeUtility {
|
|||
* * /*.
|
||||
* @return
|
||||
*/
|
||||
public static boolean mimeTypeMatches(String mimeType, String matchAgainst) {
|
||||
Pattern p = Pattern.compile(matchAgainst.replaceAll("\\*", "\\.\\*"),
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
return p.matcher(mimeType).matches();
|
||||
public static boolean mimeTypeMatches(String mimeType, String matchAgainst)
|
||||
{
|
||||
Pattern p = Pattern.compile(matchAgainst.replaceAll("\\*", "\\.\\*"),
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
return p.matcher(mimeType).matches();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -214,11 +251,14 @@ public class MimeUtility {
|
|||
* as image/* or * /*.
|
||||
* @return
|
||||
*/
|
||||
public static boolean mimeTypeMatches(String mimeType, String[] matchAgainst) {
|
||||
for (String matchType : matchAgainst) {
|
||||
if (mimeTypeMatches(mimeType, matchType)) {
|
||||
return true;
|
||||
}
|
||||
public static boolean mimeTypeMatches(String mimeType, String[] matchAgainst)
|
||||
{
|
||||
for (String matchType : matchAgainst)
|
||||
{
|
||||
if (mimeTypeMatches(mimeType, matchType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -227,17 +267,21 @@ public class MimeUtility {
|
|||
* Removes any content transfer encoding from the stream and returns a Body.
|
||||
*/
|
||||
public static Body decodeBody(InputStream in, String contentTransferEncoding)
|
||||
throws IOException {
|
||||
throws IOException
|
||||
{
|
||||
/*
|
||||
* We'll remove any transfer encoding by wrapping the stream.
|
||||
*/
|
||||
if (contentTransferEncoding != null) {
|
||||
if (contentTransferEncoding != null)
|
||||
{
|
||||
contentTransferEncoding =
|
||||
MimeUtility.getHeaderParameter(contentTransferEncoding, null);
|
||||
if ("quoted-printable".equalsIgnoreCase(contentTransferEncoding)) {
|
||||
if ("quoted-printable".equalsIgnoreCase(contentTransferEncoding))
|
||||
{
|
||||
in = new QuotedPrintableInputStream(in);
|
||||
}
|
||||
else if ("base64".equalsIgnoreCase(contentTransferEncoding)) {
|
||||
else if ("base64".equalsIgnoreCase(contentTransferEncoding))
|
||||
{
|
||||
in = new Base64InputStream(in);
|
||||
}
|
||||
}
|
||||
|
@ -260,11 +304,13 @@ public class MimeUtility {
|
|||
* @throws MessagingException
|
||||
*/
|
||||
public static void collectParts(Part part, ArrayList<Part> viewables,
|
||||
ArrayList<Part> attachments) throws MessagingException {
|
||||
ArrayList<Part> attachments) throws MessagingException
|
||||
{
|
||||
String disposition = part.getDisposition();
|
||||
String dispositionType = null;
|
||||
String dispositionFilename = null;
|
||||
if (disposition != null) {
|
||||
if (disposition != null)
|
||||
{
|
||||
dispositionType = MimeUtility.getHeaderParameter(disposition, null);
|
||||
dispositionFilename = MimeUtility.getHeaderParameter(disposition, "filename");
|
||||
}
|
||||
|
@ -273,17 +319,19 @@ public class MimeUtility {
|
|||
* A best guess that this part is intended to be an attachment and not inline.
|
||||
*/
|
||||
boolean attachment = ("attachment".equalsIgnoreCase(dispositionType))
|
||||
|| (dispositionFilename != null)
|
||||
&& (!"inline".equalsIgnoreCase(dispositionType));
|
||||
|| (dispositionFilename != null)
|
||||
&& (!"inline".equalsIgnoreCase(dispositionType));
|
||||
|
||||
/*
|
||||
* If the part is Multipart but not alternative it's either mixed or
|
||||
* something we don't know about, which means we treat it as mixed
|
||||
* per the spec. We just process it's pieces recursively.
|
||||
*/
|
||||
if (part.getBody() instanceof Multipart) {
|
||||
if (part.getBody() instanceof Multipart)
|
||||
{
|
||||
Multipart mp = (Multipart)part.getBody();
|
||||
for (int i = 0; i < mp.getCount(); i++) {
|
||||
for (int i = 0; i < mp.getCount(); i++)
|
||||
{
|
||||
collectParts(mp.getBodyPart(i), viewables, attachments);
|
||||
}
|
||||
}
|
||||
|
@ -291,7 +339,8 @@ public class MimeUtility {
|
|||
* If the part is an embedded message we just continue to process
|
||||
* it, pulling any viewables or attachments into the running list.
|
||||
*/
|
||||
else if (part.getBody() instanceof Message) {
|
||||
else if (part.getBody() instanceof Message)
|
||||
{
|
||||
Message message = (Message)part.getBody();
|
||||
collectParts(message, viewables, attachments);
|
||||
}
|
||||
|
@ -299,20 +348,23 @@ public class MimeUtility {
|
|||
* If the part is HTML and it got this far it's part of a mixed (et
|
||||
* al) and should be rendered inline.
|
||||
*/
|
||||
else if ((!attachment) && (part.getMimeType().equalsIgnoreCase("text/html"))) {
|
||||
else if ((!attachment) && (part.getMimeType().equalsIgnoreCase("text/html")))
|
||||
{
|
||||
viewables.add(part);
|
||||
}
|
||||
/*
|
||||
* If the part is plain text and it got this far it's part of a
|
||||
* mixed (et al) and should be rendered inline.
|
||||
*/
|
||||
else if ((!attachment) && (part.getMimeType().equalsIgnoreCase("text/plain"))) {
|
||||
else if ((!attachment) && (part.getMimeType().equalsIgnoreCase("text/plain")))
|
||||
{
|
||||
viewables.add(part);
|
||||
}
|
||||
/*
|
||||
* Finally, if it's nothing else we will include it as an attachment.
|
||||
*/
|
||||
else {
|
||||
else
|
||||
{
|
||||
attachments.add(part);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,43 +12,53 @@ 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;
|
||||
|
||||
public TextBody(String body) {
|
||||
public TextBody(String body)
|
||||
{
|
||||
this.mBody = body;
|
||||
}
|
||||
|
||||
public void writeTo(OutputStream out) throws IOException, MessagingException {
|
||||
if (mBody!=null) {
|
||||
public void writeTo(OutputStream out) throws IOException, MessagingException
|
||||
{
|
||||
if (mBody!=null)
|
||||
{
|
||||
byte[] bytes = mBody.getBytes("UTF-8");
|
||||
out.write(Base64.encodeBase64Chunked(bytes));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the text of the body in it's unencoded format.
|
||||
* Get the text of the body in it's unencoded format.
|
||||
* @return
|
||||
*/
|
||||
public String getText() {
|
||||
public String getText()
|
||||
{
|
||||
return mBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an InputStream that reads this body's text in UTF-8 format.
|
||||
*/
|
||||
public InputStream getInputStream() throws MessagingException {
|
||||
try {
|
||||
public InputStream getInputStream() throws MessagingException
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] b;
|
||||
if (mBody!=null) {
|
||||
if (mBody!=null)
|
||||
{
|
||||
b = mBody.getBytes("UTF-8");
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
b = new byte[0];
|
||||
}
|
||||
return new ByteArrayInputStream(b);
|
||||
}
|
||||
catch (UnsupportedEncodingException usee) {
|
||||
catch (UnsupportedEncodingException usee)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,15 +20,17 @@ import com.android.email.FixedLengthInputStream;
|
|||
import com.android.email.PeekableInputStream;
|
||||
import com.android.email.mail.MessagingException;
|
||||
|
||||
public class ImapResponseParser {
|
||||
public class ImapResponseParser
|
||||
{
|
||||
SimpleDateFormat mDateTimeFormat = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss Z", Locale.US);
|
||||
|
||||
SimpleDateFormat badDateTimeFormat = new SimpleDateFormat("dd MMM yyyy HH:mm:ss Z", Locale.US);
|
||||
|
||||
|
||||
PeekableInputStream mIn;
|
||||
InputStream mActiveLiteral;
|
||||
|
||||
public ImapResponseParser(PeekableInputStream in) {
|
||||
public ImapResponseParser(PeekableInputStream in)
|
||||
{
|
||||
this.mIn = in;
|
||||
}
|
||||
|
||||
|
@ -39,39 +41,51 @@ public class ImapResponseParser {
|
|||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public ImapResponse readResponse() throws IOException {
|
||||
public ImapResponse readResponse() throws IOException
|
||||
{
|
||||
ImapResponse response = new ImapResponse();
|
||||
if (mActiveLiteral != null) {
|
||||
if (mActiveLiteral != null)
|
||||
{
|
||||
while (mActiveLiteral.read() != -1)
|
||||
;
|
||||
mActiveLiteral = null;
|
||||
}
|
||||
int ch = mIn.peek();
|
||||
if (ch == '*') {
|
||||
if (ch == '*')
|
||||
{
|
||||
parseUntaggedResponse();
|
||||
readTokens(response);
|
||||
} else if (ch == '+') {
|
||||
}
|
||||
else if (ch == '+')
|
||||
{
|
||||
response.mCommandContinuationRequested =
|
||||
parseCommandContinuationRequest();
|
||||
parseCommandContinuationRequest();
|
||||
readTokens(response);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
response.mTag = parseTaggedResponse();
|
||||
readTokens(response);
|
||||
}
|
||||
if (Email.DEBUG) {
|
||||
if (Email.DEBUG)
|
||||
{
|
||||
Log.v(Email.LOG_TAG, "<<< " + response.toString());
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
private void readTokens(ImapResponse response) throws IOException {
|
||||
private void readTokens(ImapResponse response) throws IOException
|
||||
{
|
||||
response.clear();
|
||||
Object token;
|
||||
while ((token = readToken()) != null) {
|
||||
if (response != null) {
|
||||
while ((token = readToken()) != null)
|
||||
{
|
||||
if (response != null)
|
||||
{
|
||||
response.add(token);
|
||||
}
|
||||
if (mActiveLiteral != null) {
|
||||
if (mActiveLiteral != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -89,136 +103,192 @@ public class ImapResponseParser {
|
|||
* tokens.
|
||||
* @throws IOException
|
||||
*/
|
||||
public Object readToken() throws IOException {
|
||||
while (true) {
|
||||
public Object readToken() throws IOException
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Object token = parseToken();
|
||||
if (token == null || !token.equals(")") || !token.equals("]")) {
|
||||
if (token == null || !token.equals(")") || !token.equals("]"))
|
||||
{
|
||||
return token;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object parseToken() throws IOException {
|
||||
if (mActiveLiteral != null) {
|
||||
private Object parseToken() throws IOException
|
||||
{
|
||||
if (mActiveLiteral != null)
|
||||
{
|
||||
while (mActiveLiteral.read() != -1)
|
||||
;
|
||||
mActiveLiteral = null;
|
||||
}
|
||||
while (true) {
|
||||
while (true)
|
||||
{
|
||||
int ch = mIn.peek();
|
||||
if (ch == '(') {
|
||||
if (ch == '(')
|
||||
{
|
||||
return parseList();
|
||||
} else if (ch == '[') {
|
||||
}
|
||||
else if (ch == '[')
|
||||
{
|
||||
return parseSequence();
|
||||
} else if (ch == ')') {
|
||||
}
|
||||
else if (ch == ')')
|
||||
{
|
||||
expect(')');
|
||||
return ")";
|
||||
} else if (ch == ']') {
|
||||
expect(']');
|
||||
return "]";
|
||||
} else if (ch == '"') {
|
||||
}
|
||||
else if (ch == ']')
|
||||
{
|
||||
expect(']');
|
||||
return "]";
|
||||
}
|
||||
else if (ch == '"')
|
||||
{
|
||||
return parseQuoted();
|
||||
} else if (ch == '{') {
|
||||
}
|
||||
else if (ch == '{')
|
||||
{
|
||||
mActiveLiteral = parseLiteral();
|
||||
return mActiveLiteral;
|
||||
} else if (ch == ' ') {
|
||||
}
|
||||
else if (ch == ' ')
|
||||
{
|
||||
expect(' ');
|
||||
} else if (ch == '\r') {
|
||||
}
|
||||
else if (ch == '\r')
|
||||
{
|
||||
expect('\r');
|
||||
expect('\n');
|
||||
return null;
|
||||
} else if (ch == '\n') {
|
||||
}
|
||||
else if (ch == '\n')
|
||||
{
|
||||
expect('\n');
|
||||
return null;
|
||||
} else if (ch == '\t') {
|
||||
expect('\t');
|
||||
} else {
|
||||
}
|
||||
else if (ch == '\t')
|
||||
{
|
||||
expect('\t');
|
||||
}
|
||||
else
|
||||
{
|
||||
return parseAtom();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean parseCommandContinuationRequest() throws IOException {
|
||||
private boolean parseCommandContinuationRequest() throws IOException
|
||||
{
|
||||
expect('+');
|
||||
expect(' ');
|
||||
return true;
|
||||
}
|
||||
|
||||
// * OK [UIDNEXT 175] Predicted next UID
|
||||
private void parseUntaggedResponse() throws IOException {
|
||||
private void parseUntaggedResponse() throws IOException
|
||||
{
|
||||
expect('*');
|
||||
expect(' ');
|
||||
}
|
||||
|
||||
// 3 OK [READ-WRITE] Select completed.
|
||||
private String parseTaggedResponse() throws IOException {
|
||||
private String parseTaggedResponse() throws IOException
|
||||
{
|
||||
String tag = readStringUntil(' ');
|
||||
return tag;
|
||||
}
|
||||
|
||||
private ImapList parseList() throws IOException {
|
||||
private ImapList parseList() throws IOException
|
||||
{
|
||||
expect('(');
|
||||
ImapList list = new ImapList();
|
||||
Object token;
|
||||
while (true) {
|
||||
while (true)
|
||||
{
|
||||
token = parseToken();
|
||||
if (token == null) {
|
||||
if (token == null)
|
||||
{
|
||||
break;
|
||||
} else if (token instanceof InputStream) {
|
||||
list.add(token);
|
||||
break;
|
||||
} else if (token.equals(")")) {
|
||||
break;
|
||||
} else {
|
||||
list.add(token);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private ImapList parseSequence() throws IOException {
|
||||
expect('[');
|
||||
ImapList list = new ImapList();
|
||||
Object token;
|
||||
while (true) {
|
||||
token = parseToken();
|
||||
if (token == null) {
|
||||
break;
|
||||
} else if (token instanceof InputStream) {
|
||||
else if (token instanceof InputStream)
|
||||
{
|
||||
list.add(token);
|
||||
break;
|
||||
} else if (token.equals("]")) {
|
||||
}
|
||||
else if (token.equals(")"))
|
||||
{
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
list.add(token);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private String parseAtom() throws IOException {
|
||||
private ImapList parseSequence() throws IOException
|
||||
{
|
||||
expect('[');
|
||||
ImapList list = new ImapList();
|
||||
Object token;
|
||||
while (true)
|
||||
{
|
||||
token = parseToken();
|
||||
if (token == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (token instanceof InputStream)
|
||||
{
|
||||
list.add(token);
|
||||
break;
|
||||
}
|
||||
else if (token.equals("]"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
list.add(token);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private String parseAtom() throws IOException
|
||||
{
|
||||
StringBuffer sb = new StringBuffer();
|
||||
int ch;
|
||||
while (true) {
|
||||
while (true)
|
||||
{
|
||||
ch = mIn.peek();
|
||||
if (ch == -1) {
|
||||
if (ch == -1)
|
||||
{
|
||||
throw new IOException("parseAtom(): end of stream reached");
|
||||
} else if (ch == '(' || ch == ')' || ch == '{' || ch == ' ' ||
|
||||
ch == '[' || ch == ']' ||
|
||||
// docs claim that flags are \ atom but atom isn't supposed to
|
||||
// contain
|
||||
// * and some falgs contain *
|
||||
// ch == '%' || ch == '*' ||
|
||||
}
|
||||
else if (ch == '(' || ch == ')' || ch == '{' || ch == ' ' ||
|
||||
ch == '[' || ch == ']' ||
|
||||
// docs claim that flags are \ atom but atom isn't supposed to
|
||||
// contain
|
||||
// * and some falgs contain *
|
||||
// ch == '%' || ch == '*' ||
|
||||
// ch == '%' ||
|
||||
// TODO probably should not allow \ and should recognize
|
||||
// it as a flag instead
|
||||
// ch == '"' || ch == '\' ||
|
||||
ch == '"' || (ch >= 0x00 && ch <= 0x1f) || ch == 0x7f) {
|
||||
if (sb.length() == 0) {
|
||||
// TODO probably should not allow \ and should recognize
|
||||
// it as a flag instead
|
||||
// ch == '"' || ch == '\' ||
|
||||
ch == '"' || (ch >= 0x00 && ch <= 0x1f) || ch == 0x7f)
|
||||
{
|
||||
if (sb.length() == 0)
|
||||
{
|
||||
throw new IOException(String.format("parseAtom(): (%04x %c)", (int)ch, ch));
|
||||
}
|
||||
return sb.toString();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append((char)mIn.read());
|
||||
}
|
||||
}
|
||||
|
@ -231,7 +301,8 @@ public class ImapResponseParser {
|
|||
* @param mListener
|
||||
* @throws IOException
|
||||
*/
|
||||
private InputStream parseLiteral() throws IOException {
|
||||
private InputStream parseLiteral() throws IOException
|
||||
{
|
||||
expect('{');
|
||||
int size = Integer.parseInt(readStringUntil('}'));
|
||||
expect('\r');
|
||||
|
@ -247,29 +318,37 @@ public class ImapResponseParser {
|
|||
* @param mListener
|
||||
* @throws IOException
|
||||
*/
|
||||
private String parseQuoted() throws IOException {
|
||||
private String parseQuoted() throws IOException
|
||||
{
|
||||
expect('"');
|
||||
return readStringUntil('"');
|
||||
}
|
||||
|
||||
private String readStringUntil(char end) throws IOException {
|
||||
private String readStringUntil(char end) throws IOException
|
||||
{
|
||||
StringBuffer sb = new StringBuffer();
|
||||
int ch;
|
||||
while ((ch = mIn.read()) != -1) {
|
||||
if (ch == end) {
|
||||
while ((ch = mIn.read()) != -1)
|
||||
{
|
||||
if (ch == end)
|
||||
{
|
||||
return sb.toString();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append((char)ch);
|
||||
}
|
||||
}
|
||||
throw new IOException("readQuotedString(): end of stream reached");
|
||||
}
|
||||
|
||||
private int expect(char ch) throws IOException {
|
||||
private int expect(char ch) throws IOException
|
||||
{
|
||||
int d;
|
||||
if ((d = mIn.read()) != ch) {
|
||||
if ((d = mIn.read()) != ch)
|
||||
{
|
||||
throw new IOException(String.format("Expected %04x (%c) but got %04x (%c)", (int)ch,
|
||||
ch, d, (char)d));
|
||||
ch, d, (char)d));
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
@ -278,92 +357,113 @@ public class ImapResponseParser {
|
|||
* Represents an IMAP LIST response and is also the base class for the
|
||||
* ImapResponse.
|
||||
*/
|
||||
public class ImapList extends ArrayList<Object> {
|
||||
public ImapList getList(int index) {
|
||||
public class ImapList extends ArrayList<Object>
|
||||
{
|
||||
public ImapList getList(int index)
|
||||
{
|
||||
return (ImapList)get(index);
|
||||
}
|
||||
|
||||
|
||||
public Object getObject(int index)
|
||||
{
|
||||
return get(index);
|
||||
return get(index);
|
||||
}
|
||||
|
||||
public String getString(int index) {
|
||||
public String getString(int index)
|
||||
{
|
||||
return (String)get(index);
|
||||
}
|
||||
|
||||
public InputStream getLiteral(int index) {
|
||||
public InputStream getLiteral(int index)
|
||||
{
|
||||
return (InputStream)get(index);
|
||||
}
|
||||
|
||||
public int getNumber(int index) {
|
||||
public int getNumber(int index)
|
||||
{
|
||||
return Integer.parseInt(getString(index));
|
||||
}
|
||||
|
||||
public Date getDate(int index) throws MessagingException {
|
||||
try {
|
||||
public Date getDate(int index) throws MessagingException
|
||||
{
|
||||
try
|
||||
{
|
||||
return parseDate(getString(index));
|
||||
} catch (ParseException pe) {
|
||||
}
|
||||
catch (ParseException pe)
|
||||
{
|
||||
throw new MessagingException("Unable to parse IMAP datetime", pe);
|
||||
}
|
||||
}
|
||||
|
||||
public Object getKeyedValue(Object key) {
|
||||
for (int i = 0, count = size(); i < count; i++) {
|
||||
if (get(i).equals(key)) {
|
||||
public Object getKeyedValue(Object key)
|
||||
{
|
||||
for (int i = 0, count = size(); i < count; i++)
|
||||
{
|
||||
if (get(i).equals(key))
|
||||
{
|
||||
return get(i + 1);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ImapList getKeyedList(Object key) {
|
||||
public ImapList getKeyedList(Object key)
|
||||
{
|
||||
return (ImapList)getKeyedValue(key);
|
||||
}
|
||||
|
||||
public String getKeyedString(Object key) {
|
||||
public String getKeyedString(Object key)
|
||||
{
|
||||
return (String)getKeyedValue(key);
|
||||
}
|
||||
|
||||
public InputStream getKeyedLiteral(Object key) {
|
||||
public InputStream getKeyedLiteral(Object key)
|
||||
{
|
||||
return (InputStream)getKeyedValue(key);
|
||||
}
|
||||
|
||||
public int getKeyedNumber(Object key) {
|
||||
public int getKeyedNumber(Object key)
|
||||
{
|
||||
return Integer.parseInt(getKeyedString(key));
|
||||
}
|
||||
|
||||
public Date getKeyedDate(Object key) throws MessagingException {
|
||||
try {
|
||||
public Date getKeyedDate(Object key) throws MessagingException
|
||||
{
|
||||
try
|
||||
{
|
||||
String value = getKeyedString(key);
|
||||
if (value == null) {
|
||||
if (value == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return parseDate(value);
|
||||
} catch (ParseException pe) {
|
||||
}
|
||||
catch (ParseException pe)
|
||||
{
|
||||
throw new MessagingException("Unable to parse IMAP datetime", pe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Date parseDate(String value) throws ParseException
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized(mDateTimeFormat)
|
||||
synchronized (mDateTimeFormat)
|
||||
{
|
||||
return mDateTimeFormat.parse(value);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
synchronized(badDateTimeFormat)
|
||||
synchronized (badDateTimeFormat)
|
||||
{
|
||||
return badDateTimeFormat.parse(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -375,34 +475,43 @@ public class ImapResponseParser {
|
|||
* does not contain the entire response the caller must call more() to
|
||||
* continue reading the response until more returns false.
|
||||
*/
|
||||
public class ImapResponse extends ImapList {
|
||||
public class ImapResponse extends ImapList
|
||||
{
|
||||
private boolean mCompleted;
|
||||
|
||||
boolean mCommandContinuationRequested;
|
||||
String mTag;
|
||||
|
||||
public boolean more() throws IOException {
|
||||
if (mCompleted) {
|
||||
public boolean more() throws IOException
|
||||
{
|
||||
if (mCompleted)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
readTokens(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getAlertText() {
|
||||
if (size() > 1 && "[ALERT]".equals(get(1))) {
|
||||
public String getAlertText()
|
||||
{
|
||||
if (size() > 1 && "[ALERT]".equals(get(1)))
|
||||
{
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 2, count = size(); i < count; i++) {
|
||||
for (int i = 2, count = size(); i < count; i++)
|
||||
{
|
||||
sb.append(get(i).toString());
|
||||
sb.append(' ');
|
||||
}
|
||||
return sb.toString();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
public String toString()
|
||||
{
|
||||
return "#" + mTag + "# " + super.toString();
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -20,114 +20,148 @@ import javax.net.ssl.TrustManager;
|
|||
|
||||
import com.android.email.Email;
|
||||
|
||||
public final class TrustManagerFactory {
|
||||
public final class TrustManagerFactory
|
||||
{
|
||||
private static final String LOG_TAG = "TrustManagerFactory";
|
||||
|
||||
private static X509TrustManager defaultTrustManager;
|
||||
private static X509TrustManager unsecureTrustManager;
|
||||
private static X509TrustManager localTrustManager;
|
||||
|
||||
private static X509TrustManager localTrustManager;
|
||||
|
||||
private static X509Certificate[] lastCertChain = null;
|
||||
|
||||
|
||||
private static File keyStoreFile;
|
||||
private static KeyStore keyStore;
|
||||
|
||||
|
||||
private static class SimpleX509TrustManager implements X509TrustManager {
|
||||
private static class SimpleX509TrustManager implements X509TrustManager
|
||||
{
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType)
|
||||
throws CertificateException {
|
||||
throws CertificateException
|
||||
{
|
||||
}
|
||||
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType)
|
||||
throws CertificateException {
|
||||
throws CertificateException
|
||||
{
|
||||
}
|
||||
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
public X509Certificate[] getAcceptedIssuers()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class SecureX509TrustManager implements X509TrustManager {
|
||||
private static class SecureX509TrustManager implements X509TrustManager
|
||||
{
|
||||
private String mHost;
|
||||
private static SecureX509TrustManager me;
|
||||
|
||||
private SecureX509TrustManager() {
|
||||
private SecureX509TrustManager()
|
||||
{
|
||||
}
|
||||
|
||||
public static X509TrustManager getInstance(String host) {
|
||||
if (me == null) {
|
||||
me = new SecureX509TrustManager();
|
||||
}
|
||||
me.mHost = host;
|
||||
return me;
|
||||
}
|
||||
public static X509TrustManager getInstance(String host)
|
||||
{
|
||||
if (me == null)
|
||||
{
|
||||
me = new SecureX509TrustManager();
|
||||
}
|
||||
me.mHost = host;
|
||||
return me;
|
||||
}
|
||||
|
||||
public void setHost(String host){
|
||||
mHost = host;
|
||||
}
|
||||
public void setHost(String host)
|
||||
{
|
||||
mHost = host;
|
||||
}
|
||||
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType)
|
||||
throws CertificateException {
|
||||
throws CertificateException
|
||||
{
|
||||
defaultTrustManager.checkClientTrusted(chain, authType);
|
||||
}
|
||||
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType)
|
||||
throws CertificateException {
|
||||
TrustManagerFactory.setLastCertChain(chain);
|
||||
try {
|
||||
defaultTrustManager.checkServerTrusted(chain, authType);
|
||||
} catch (CertificateException e) {
|
||||
localTrustManager.checkServerTrusted(new X509Certificate[] {chain[0]}, authType);
|
||||
}
|
||||
if (!DomainNameChecker.match(chain[0], mHost)) {
|
||||
try {
|
||||
String dn = chain[0].getSubjectDN().toString();
|
||||
if ((dn != null) && (dn.equalsIgnoreCase(keyStore.getCertificateAlias(chain[0])))) {
|
||||
return;
|
||||
}
|
||||
} catch (KeyStoreException e) {
|
||||
throw new CertificateException("Certificate cannot be verified; KeyStore Exception: " + e);
|
||||
}
|
||||
throw new CertificateException("Certificate domain name does not match "
|
||||
+ mHost);
|
||||
}
|
||||
throws CertificateException
|
||||
{
|
||||
TrustManagerFactory.setLastCertChain(chain);
|
||||
try
|
||||
{
|
||||
defaultTrustManager.checkServerTrusted(chain, authType);
|
||||
}
|
||||
catch (CertificateException e)
|
||||
{
|
||||
localTrustManager.checkServerTrusted(new X509Certificate[] {chain[0]}, authType);
|
||||
}
|
||||
if (!DomainNameChecker.match(chain[0], mHost))
|
||||
{
|
||||
try
|
||||
{
|
||||
String dn = chain[0].getSubjectDN().toString();
|
||||
if ((dn != null) && (dn.equalsIgnoreCase(keyStore.getCertificateAlias(chain[0]))))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (KeyStoreException e)
|
||||
{
|
||||
throw new CertificateException("Certificate cannot be verified; KeyStore Exception: " + e);
|
||||
}
|
||||
throw new CertificateException("Certificate domain name does not match "
|
||||
+ mHost);
|
||||
}
|
||||
}
|
||||
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
public X509Certificate[] getAcceptedIssuers()
|
||||
{
|
||||
return defaultTrustManager.getAcceptedIssuers();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
static
|
||||
{
|
||||
try
|
||||
{
|
||||
javax.net.ssl.TrustManagerFactory tmf = javax.net.ssl.TrustManagerFactory.getInstance("X509");
|
||||
Application app = Email.app;
|
||||
keyStoreFile = new File(app.getDir("KeyStore", Context.MODE_PRIVATE) + File.separator + "KeyStore.bks");
|
||||
keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
java.io.FileInputStream fis;
|
||||
try {
|
||||
fis = new java.io.FileInputStream(keyStoreFile);
|
||||
} catch (FileNotFoundException e1) {
|
||||
fis = null;
|
||||
}
|
||||
try {
|
||||
keyStore.load(fis, "".toCharArray());
|
||||
//if (fis != null) {
|
||||
// fis.close();
|
||||
//}
|
||||
} catch (IOException e) {
|
||||
java.io.FileInputStream fis;
|
||||
try
|
||||
{
|
||||
fis = new java.io.FileInputStream(keyStoreFile);
|
||||
}
|
||||
catch (FileNotFoundException e1)
|
||||
{
|
||||
fis = null;
|
||||
}
|
||||
try
|
||||
{
|
||||
keyStore.load(fis, "".toCharArray());
|
||||
//if (fis != null) {
|
||||
// fis.close();
|
||||
//}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Log.e(LOG_TAG, "KeyStore IOException while initializing TrustManagerFactory ", e);
|
||||
keyStore = null;
|
||||
} catch (CertificateException e) {
|
||||
keyStore = null;
|
||||
}
|
||||
catch (CertificateException e)
|
||||
{
|
||||
Log.e(LOG_TAG, "KeyStore CertificateException while initializing TrustManagerFactory ", e);
|
||||
keyStore = null;
|
||||
}
|
||||
keyStore = null;
|
||||
}
|
||||
tmf.init(keyStore);
|
||||
TrustManager[] tms = tmf.getTrustManagers();
|
||||
if (tms != null) {
|
||||
for (TrustManager tm : tms) {
|
||||
if (tm instanceof X509TrustManager) {
|
||||
if (tms != null)
|
||||
{
|
||||
for (TrustManager tm : tms)
|
||||
{
|
||||
if (tm instanceof X509TrustManager)
|
||||
{
|
||||
localTrustManager = (X509TrustManager)tm;
|
||||
break;
|
||||
}
|
||||
|
@ -136,78 +170,106 @@ public final class TrustManagerFactory {
|
|||
tmf = javax.net.ssl.TrustManagerFactory.getInstance("X509");
|
||||
tmf.init((KeyStore)null);
|
||||
tms = tmf.getTrustManagers();
|
||||
if (tms != null) {
|
||||
for (TrustManager tm : tms) {
|
||||
if (tm instanceof X509TrustManager) {
|
||||
if (tms != null)
|
||||
{
|
||||
for (TrustManager tm : tms)
|
||||
{
|
||||
if (tm instanceof X509TrustManager)
|
||||
{
|
||||
defaultTrustManager = (X509TrustManager) tm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
}
|
||||
catch (NoSuchAlgorithmException e)
|
||||
{
|
||||
Log.e(LOG_TAG, "Unable to get X509 Trust Manager ", e);
|
||||
} catch (KeyStoreException e) {
|
||||
}
|
||||
catch (KeyStoreException e)
|
||||
{
|
||||
Log.e(LOG_TAG, "Key Store exception while initializing TrustManagerFactory ", e);
|
||||
}
|
||||
unsecureTrustManager = new SimpleX509TrustManager();
|
||||
}
|
||||
|
||||
private TrustManagerFactory() {
|
||||
private TrustManagerFactory()
|
||||
{
|
||||
}
|
||||
|
||||
public static X509TrustManager get(String host, boolean secure) {
|
||||
public static X509TrustManager get(String host, boolean secure)
|
||||
{
|
||||
return secure ? SecureX509TrustManager.getInstance(host) :
|
||||
unsecureTrustManager;
|
||||
unsecureTrustManager;
|
||||
}
|
||||
|
||||
public static KeyStore getKeyStore() {
|
||||
return keyStore;
|
||||
public static KeyStore getKeyStore()
|
||||
{
|
||||
return keyStore;
|
||||
}
|
||||
|
||||
public static void setLastCertChain(X509Certificate[] chain) {
|
||||
lastCertChain = chain;
|
||||
}
|
||||
public static X509Certificate[] getLastCertChain() {
|
||||
return lastCertChain;
|
||||
}
|
||||
public static void setLastCertChain(X509Certificate[] chain)
|
||||
{
|
||||
lastCertChain = chain;
|
||||
}
|
||||
public static X509Certificate[] getLastCertChain()
|
||||
{
|
||||
return lastCertChain;
|
||||
}
|
||||
|
||||
public static void addCertificateChain(String alias, X509Certificate[] chain) throws CertificateException {
|
||||
try {
|
||||
javax.net.ssl.TrustManagerFactory tmf = javax.net.ssl.TrustManagerFactory.getInstance("X509");
|
||||
for (int i = 0; i < chain.length; i++)
|
||||
public static void addCertificateChain(String alias, X509Certificate[] chain) throws CertificateException
|
||||
{
|
||||
try
|
||||
{
|
||||
javax.net.ssl.TrustManagerFactory tmf = javax.net.ssl.TrustManagerFactory.getInstance("X509");
|
||||
for (int i = 0; i < chain.length; i++)
|
||||
{
|
||||
keyStore.setCertificateEntry
|
||||
(chain[i].getSubjectDN().toString(), chain[i]);
|
||||
(chain[i].getSubjectDN().toString(), chain[i]);
|
||||
}
|
||||
|
||||
tmf.init(keyStore);
|
||||
TrustManager[] tms = tmf.getTrustManagers();
|
||||
if (tms != null) {
|
||||
for (TrustManager tm : tms) {
|
||||
if (tm instanceof X509TrustManager) {
|
||||
localTrustManager = (X509TrustManager) tm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
java.io.FileOutputStream keyStoreStream;
|
||||
try {
|
||||
keyStoreStream = new java.io.FileOutputStream(keyStoreFile);
|
||||
keyStore.store(keyStoreStream, "".toCharArray());
|
||||
keyStoreStream.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new CertificateException("Unable to write KeyStore: " + e.getMessage());
|
||||
} catch (CertificateException e) {
|
||||
throw new CertificateException("Unable to write KeyStore: " + e.getMessage());
|
||||
} catch (IOException e) {
|
||||
throw new CertificateException("Unable to write KeyStore: " + e.getMessage());
|
||||
}
|
||||
tmf.init(keyStore);
|
||||
TrustManager[] tms = tmf.getTrustManagers();
|
||||
if (tms != null)
|
||||
{
|
||||
for (TrustManager tm : tms)
|
||||
{
|
||||
if (tm instanceof X509TrustManager)
|
||||
{
|
||||
localTrustManager = (X509TrustManager) tm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
java.io.FileOutputStream keyStoreStream;
|
||||
try
|
||||
{
|
||||
keyStoreStream = new java.io.FileOutputStream(keyStoreFile);
|
||||
keyStore.store(keyStoreStream, "".toCharArray());
|
||||
keyStoreStream.close();
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
throw new CertificateException("Unable to write KeyStore: " + e.getMessage());
|
||||
}
|
||||
catch (CertificateException e)
|
||||
{
|
||||
throw new CertificateException("Unable to write KeyStore: " + e.getMessage());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new CertificateException("Unable to write KeyStore: " + e.getMessage());
|
||||
}
|
||||
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
Log.e(LOG_TAG, "Unable to get X509 Trust Manager ", e);
|
||||
} catch (KeyStoreException e) {
|
||||
Log.e(LOG_TAG, "Key Store exception while initializing TrustManagerFactory ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NoSuchAlgorithmException e)
|
||||
{
|
||||
Log.e(LOG_TAG, "Unable to get X509 Trust Manager ", e);
|
||||
}
|
||||
catch (KeyStoreException e)
|
||||
{
|
||||
Log.e(LOG_TAG, "Key Store exception while initializing TrustManagerFactory ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -7,18 +7,22 @@ import java.io.OutputStream;
|
|||
* A simple OutputStream that does nothing but count how many bytes are written to it and
|
||||
* makes that count available to callers.
|
||||
*/
|
||||
public class CountingOutputStream extends OutputStream {
|
||||
public class CountingOutputStream extends OutputStream
|
||||
{
|
||||
private long mCount;
|
||||
|
||||
public CountingOutputStream() {
|
||||
public CountingOutputStream()
|
||||
{
|
||||
}
|
||||
|
||||
public long getCount() {
|
||||
public long getCount()
|
||||
{
|
||||
return mCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int oneByte) throws IOException {
|
||||
public void write(int oneByte) throws IOException
|
||||
{
|
||||
mCount++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,17 +4,22 @@ import java.io.FilterOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class EOLConvertingOutputStream extends FilterOutputStream {
|
||||
public class EOLConvertingOutputStream extends FilterOutputStream
|
||||
{
|
||||
int lastChar;
|
||||
|
||||
public EOLConvertingOutputStream(OutputStream out) {
|
||||
public EOLConvertingOutputStream(OutputStream out)
|
||||
{
|
||||
super(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int oneByte) throws IOException {
|
||||
if (oneByte == '\n') {
|
||||
if (lastChar != '\r') {
|
||||
public void write(int oneByte) throws IOException
|
||||
{
|
||||
if (oneByte == '\n')
|
||||
{
|
||||
if (lastChar != '\r')
|
||||
{
|
||||
super.write('\r');
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +28,10 @@ public class EOLConvertingOutputStream extends FilterOutputStream {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
if (lastChar == '\r') {
|
||||
public void flush() throws IOException
|
||||
{
|
||||
if (lastChar == '\r')
|
||||
{
|
||||
super.write('\n');
|
||||
lastChar = '\n';
|
||||
}
|
||||
|
|
|
@ -36,7 +36,8 @@ import com.android.email.mail.CertificateValidationException;
|
|||
import com.android.email.mail.Message.RecipientType;
|
||||
import com.android.email.mail.store.TrustManagerFactory;
|
||||
|
||||
public class SmtpTransport extends Transport {
|
||||
public class SmtpTransport extends Transport
|
||||
{
|
||||
public static final int CONNECTION_SECURITY_NONE = 0;
|
||||
|
||||
public static final int CONNECTION_SECURITY_TLS_OPTIONAL = 1;
|
||||
|
@ -74,70 +75,94 @@ public class SmtpTransport extends Transport {
|
|||
*
|
||||
* @param _uri
|
||||
*/
|
||||
public SmtpTransport(String _uri) throws MessagingException {
|
||||
public SmtpTransport(String _uri) throws MessagingException
|
||||
{
|
||||
URI uri;
|
||||
try {
|
||||
try
|
||||
{
|
||||
uri = new URI(_uri);
|
||||
} catch (URISyntaxException use) {
|
||||
}
|
||||
catch (URISyntaxException use)
|
||||
{
|
||||
throw new MessagingException("Invalid SmtpTransport URI", use);
|
||||
}
|
||||
|
||||
String scheme = uri.getScheme();
|
||||
if (scheme.equals("smtp")) {
|
||||
if (scheme.equals("smtp"))
|
||||
{
|
||||
mConnectionSecurity = CONNECTION_SECURITY_NONE;
|
||||
mPort = 25;
|
||||
} else if (scheme.equals("smtp+tls")) {
|
||||
}
|
||||
else if (scheme.equals("smtp+tls"))
|
||||
{
|
||||
mConnectionSecurity = CONNECTION_SECURITY_TLS_OPTIONAL;
|
||||
mPort = 25;
|
||||
} else if (scheme.equals("smtp+tls+")) {
|
||||
}
|
||||
else if (scheme.equals("smtp+tls+"))
|
||||
{
|
||||
mConnectionSecurity = CONNECTION_SECURITY_TLS_REQUIRED;
|
||||
mPort = 25;
|
||||
} else if (scheme.equals("smtp+ssl+")) {
|
||||
}
|
||||
else if (scheme.equals("smtp+ssl+"))
|
||||
{
|
||||
mConnectionSecurity = CONNECTION_SECURITY_SSL_REQUIRED;
|
||||
mPort = 465;
|
||||
} else if (scheme.equals("smtp+ssl")) {
|
||||
}
|
||||
else if (scheme.equals("smtp+ssl"))
|
||||
{
|
||||
mConnectionSecurity = CONNECTION_SECURITY_SSL_OPTIONAL;
|
||||
mPort = 465;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new MessagingException("Unsupported protocol");
|
||||
}
|
||||
|
||||
mHost = uri.getHost();
|
||||
|
||||
if (uri.getPort() != -1) {
|
||||
if (uri.getPort() != -1)
|
||||
{
|
||||
mPort = uri.getPort();
|
||||
}
|
||||
|
||||
if (uri.getUserInfo() != null) {
|
||||
if (uri.getUserInfo() != null)
|
||||
{
|
||||
String[] userInfoParts = uri.getUserInfo().split(":", 2);
|
||||
mUsername = userInfoParts[0];
|
||||
if (userInfoParts.length > 1) {
|
||||
if (userInfoParts.length > 1)
|
||||
{
|
||||
mPassword = userInfoParts[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void open() throws MessagingException {
|
||||
try {
|
||||
public void open() throws MessagingException
|
||||
{
|
||||
try
|
||||
{
|
||||
SocketAddress socketAddress = new InetSocketAddress(mHost, mPort);
|
||||
if (mConnectionSecurity == CONNECTION_SECURITY_SSL_REQUIRED ||
|
||||
mConnectionSecurity == CONNECTION_SECURITY_SSL_OPTIONAL) {
|
||||
mConnectionSecurity == CONNECTION_SECURITY_SSL_OPTIONAL)
|
||||
{
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
boolean secure = mConnectionSecurity == CONNECTION_SECURITY_SSL_REQUIRED;
|
||||
sslContext.init(null, new TrustManager[] {
|
||||
TrustManagerFactory.get(mHost, secure)
|
||||
sslContext.init(null, new TrustManager[]
|
||||
{
|
||||
TrustManagerFactory.get(mHost, secure)
|
||||
}, new SecureRandom());
|
||||
mSocket = sslContext.getSocketFactory().createSocket();
|
||||
mSocket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
|
||||
mSecure = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
mSocket = new Socket();
|
||||
mSocket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
|
||||
}
|
||||
|
||||
// RFC 1047
|
||||
mSocket.setSoTimeout(SOCKET_READ_TIMEOUT);
|
||||
|
||||
|
||||
mIn = new PeekableInputStream(new BufferedInputStream(mSocket.getInputStream(), 1024));
|
||||
mOut = mSocket.getOutputStream();
|
||||
|
||||
|
@ -145,17 +170,22 @@ public class SmtpTransport extends Transport {
|
|||
executeSimpleCommand(null);
|
||||
|
||||
String localHost = "localhost.localdomain";
|
||||
try {
|
||||
try
|
||||
{
|
||||
InetAddress localAddress = InetAddress.getLocalHost();
|
||||
if (! localAddress.isLoopbackAddress()) {
|
||||
if (! localAddress.isLoopbackAddress())
|
||||
{
|
||||
// The loopback address will resolve to 'localhost'
|
||||
// some mail servers only accept qualified hostnames, so make sure
|
||||
// some mail servers only accept qualified hostnames, so make sure
|
||||
// never to override "localhost.localdomain" with "localhost"
|
||||
// TODO - this is a hack. but a better hack than what was there before
|
||||
localHost = localAddress.getHostName();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (Email.DEBUG) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Email.DEBUG)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Unable to look up localhost");
|
||||
}
|
||||
}
|
||||
|
@ -171,19 +201,22 @@ public class SmtpTransport extends Transport {
|
|||
* if not.
|
||||
*/
|
||||
if (mConnectionSecurity == CONNECTION_SECURITY_TLS_OPTIONAL
|
||||
|| mConnectionSecurity == CONNECTION_SECURITY_TLS_REQUIRED) {
|
||||
if (results.contains("STARTTLS")) {
|
||||
|| mConnectionSecurity == CONNECTION_SECURITY_TLS_REQUIRED)
|
||||
{
|
||||
if (results.contains("STARTTLS"))
|
||||
{
|
||||
executeSimpleCommand("STARTTLS");
|
||||
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
boolean secure = mConnectionSecurity == CONNECTION_SECURITY_TLS_REQUIRED;
|
||||
sslContext.init(null, new TrustManager[] {
|
||||
TrustManagerFactory.get(mHost, secure)
|
||||
sslContext.init(null, new TrustManager[]
|
||||
{
|
||||
TrustManagerFactory.get(mHost, secure)
|
||||
}, new SecureRandom());
|
||||
mSocket = sslContext.getSocketFactory().createSocket(mSocket, mHost, mPort,
|
||||
true);
|
||||
true);
|
||||
mIn = new PeekableInputStream(new BufferedInputStream(mSocket.getInputStream(),
|
||||
1024));
|
||||
1024));
|
||||
mOut = mSocket.getOutputStream();
|
||||
mSecure = true;
|
||||
/*
|
||||
|
@ -191,7 +224,9 @@ public class SmtpTransport extends Transport {
|
|||
* Exim.
|
||||
*/
|
||||
results = executeSimpleCommand("EHLO " + localHost);
|
||||
} else if (mConnectionSecurity == CONNECTION_SECURITY_TLS_REQUIRED) {
|
||||
}
|
||||
else if (mConnectionSecurity == CONNECTION_SECURITY_TLS_REQUIRED)
|
||||
{
|
||||
throw new MessagingException("TLS not supported but required");
|
||||
}
|
||||
}
|
||||
|
@ -200,7 +235,7 @@ public class SmtpTransport extends Transport {
|
|||
* result contains the results of the EHLO in concatenated form
|
||||
*/
|
||||
boolean authLoginSupported = false;
|
||||
boolean authPlainSupported = false;
|
||||
boolean authPlainSupported = false;
|
||||
for (String result : results)
|
||||
{
|
||||
if (result.matches(".*AUTH.*LOGIN.*$") == true)
|
||||
|
@ -214,80 +249,107 @@ public class SmtpTransport extends Transport {
|
|||
}
|
||||
|
||||
if (mUsername != null && mUsername.length() > 0 && mPassword != null
|
||||
&& mPassword.length() > 0) {
|
||||
if (authPlainSupported) {
|
||||
&& mPassword.length() > 0)
|
||||
{
|
||||
if (authPlainSupported)
|
||||
{
|
||||
saslAuthPlain(mUsername, mPassword);
|
||||
}
|
||||
else if (authLoginSupported) {
|
||||
else if (authLoginSupported)
|
||||
{
|
||||
saslAuthLogin(mUsername, mPassword);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
throw new MessagingException("No valid authentication mechanism found.");
|
||||
}
|
||||
}
|
||||
} catch (SSLException e) {
|
||||
}
|
||||
catch (SSLException e)
|
||||
{
|
||||
throw new CertificateValidationException(e.getMessage(), e);
|
||||
} catch (GeneralSecurityException gse) {
|
||||
}
|
||||
catch (GeneralSecurityException gse)
|
||||
{
|
||||
throw new MessagingException(
|
||||
"Unable to open connection to SMTP server due to security error.", gse);
|
||||
} catch (IOException ioe) {
|
||||
"Unable to open connection to SMTP server due to security error.", gse);
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
throw new MessagingException("Unable to open connection to SMTP server.", ioe);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMessage(Message message) throws MessagingException {
|
||||
public void sendMessage(Message message) throws MessagingException
|
||||
{
|
||||
close();
|
||||
open();
|
||||
Address[] from = message.getFrom();
|
||||
boolean possibleSend = false;
|
||||
try {
|
||||
try
|
||||
{
|
||||
executeSimpleCommand("MAIL FROM: " + "<" + from[0].getAddress() + ">");
|
||||
for (Address address : message.getRecipients(RecipientType.TO)) {
|
||||
for (Address address : message.getRecipients(RecipientType.TO))
|
||||
{
|
||||
executeSimpleCommand("RCPT TO: " + "<" + address.getAddress() + ">");
|
||||
}
|
||||
for (Address address : message.getRecipients(RecipientType.CC)) {
|
||||
for (Address address : message.getRecipients(RecipientType.CC))
|
||||
{
|
||||
executeSimpleCommand("RCPT TO: " + "<" + address.getAddress() + ">");
|
||||
}
|
||||
for (Address address : message.getRecipients(RecipientType.BCC)) {
|
||||
for (Address address : message.getRecipients(RecipientType.BCC))
|
||||
{
|
||||
executeSimpleCommand("RCPT TO: " + "<" + address.getAddress() + ">");
|
||||
}
|
||||
message.setRecipients(RecipientType.BCC, null);
|
||||
executeSimpleCommand("DATA");
|
||||
// TODO byte stuffing
|
||||
message.writeTo(
|
||||
new EOLConvertingOutputStream(
|
||||
new BufferedOutputStream(mOut, 1024)));
|
||||
|
||||
new EOLConvertingOutputStream(
|
||||
new BufferedOutputStream(mOut, 1024)));
|
||||
|
||||
possibleSend = true; // After the "\r\n." is attempted, we may have sent the message
|
||||
executeSimpleCommand("\r\n.");
|
||||
} catch (Exception e) {
|
||||
MessagingException me = new MessagingException("Unable to send message", e);
|
||||
me.setPermanentFailure(possibleSend);
|
||||
throw me;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessagingException me = new MessagingException("Unable to send message", e);
|
||||
me.setPermanentFailure(possibleSend);
|
||||
throw me;
|
||||
}
|
||||
finally
|
||||
{
|
||||
close();
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
public void close()
|
||||
{
|
||||
try
|
||||
{
|
||||
mIn.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
}
|
||||
try {
|
||||
try
|
||||
{
|
||||
mOut.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
}
|
||||
try {
|
||||
try
|
||||
{
|
||||
mSocket.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
}
|
||||
mIn = null;
|
||||
|
@ -295,28 +357,38 @@ public class SmtpTransport extends Transport {
|
|||
mSocket = null;
|
||||
}
|
||||
|
||||
private String readLine() throws IOException {
|
||||
private String readLine() throws IOException
|
||||
{
|
||||
StringBuffer sb = new StringBuffer();
|
||||
int d;
|
||||
while ((d = mIn.read()) != -1) {
|
||||
if (((char)d) == '\r') {
|
||||
while ((d = mIn.read()) != -1)
|
||||
{
|
||||
if (((char)d) == '\r')
|
||||
{
|
||||
continue;
|
||||
} else if (((char)d) == '\n') {
|
||||
}
|
||||
else if (((char)d) == '\n')
|
||||
{
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append((char)d);
|
||||
}
|
||||
}
|
||||
String ret = sb.toString();
|
||||
if (Email.DEBUG) {
|
||||
if (Email.DEBUG)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "SMTP <<< " + ret);
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void writeLine(String s) throws IOException {
|
||||
if (Email.DEBUG) {
|
||||
private void writeLine(String s) throws IOException
|
||||
{
|
||||
if (Email.DEBUG)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "SMTP >>> " + s);
|
||||
}
|
||||
mOut.write(s.getBytes());
|
||||
|
@ -327,22 +399,25 @@ public class SmtpTransport extends Transport {
|
|||
|
||||
private void checkLine(String line) throws MessagingException
|
||||
{
|
||||
if (line.length() < 1)
|
||||
{
|
||||
throw new MessagingException("SMTP response is 0 length");
|
||||
}
|
||||
if (line.length() < 1)
|
||||
{
|
||||
throw new MessagingException("SMTP response is 0 length");
|
||||
}
|
||||
char c = line.charAt(0);
|
||||
if ((c == '4') || (c == '5')) {
|
||||
if ((c == '4') || (c == '5'))
|
||||
{
|
||||
throw new MessagingException(line);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> executeSimpleCommand(String command) throws IOException, MessagingException {
|
||||
private List<String> executeSimpleCommand(String command) throws IOException, MessagingException
|
||||
{
|
||||
List<String> results = new ArrayList<String>();
|
||||
if (command != null) {
|
||||
if (command != null)
|
||||
{
|
||||
writeLine(command);
|
||||
}
|
||||
|
||||
|
||||
boolean cont = false;
|
||||
do
|
||||
{
|
||||
|
@ -360,7 +435,8 @@ public class SmtpTransport extends Transport {
|
|||
cont = false;
|
||||
}
|
||||
}
|
||||
} while (cont);
|
||||
}
|
||||
while (cont);
|
||||
return results;
|
||||
|
||||
}
|
||||
|
@ -384,32 +460,40 @@ public class SmtpTransport extends Transport {
|
|||
// S: 235 2.0.0 OK Authenticated
|
||||
|
||||
private void saslAuthLogin(String username, String password) throws MessagingException,
|
||||
AuthenticationFailedException, IOException {
|
||||
try {
|
||||
AuthenticationFailedException, IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
executeSimpleCommand("AUTH LOGIN");
|
||||
executeSimpleCommand(new String(Base64.encodeBase64(username.getBytes())));
|
||||
executeSimpleCommand(new String(Base64.encodeBase64(password.getBytes())));
|
||||
}
|
||||
catch (MessagingException me) {
|
||||
if (me.getMessage().length() > 1 && me.getMessage().charAt(1) == '3') {
|
||||
catch (MessagingException me)
|
||||
{
|
||||
if (me.getMessage().length() > 1 && me.getMessage().charAt(1) == '3')
|
||||
{
|
||||
throw new AuthenticationFailedException("AUTH LOGIN failed (" + me.getMessage()
|
||||
+ ")");
|
||||
+ ")");
|
||||
}
|
||||
throw me;
|
||||
}
|
||||
}
|
||||
|
||||
private void saslAuthPlain(String username, String password) throws MessagingException,
|
||||
AuthenticationFailedException, IOException {
|
||||
AuthenticationFailedException, IOException
|
||||
{
|
||||
byte[] data = ("\000" + username + "\000" + password).getBytes();
|
||||
data = new Base64().encode(data);
|
||||
try {
|
||||
try
|
||||
{
|
||||
executeSimpleCommand("AUTH PLAIN " + new String(data));
|
||||
}
|
||||
catch (MessagingException me) {
|
||||
if (me.getMessage().length() > 1 && me.getMessage().charAt(1) == '3') {
|
||||
catch (MessagingException me)
|
||||
{
|
||||
if (me.getMessage().length() > 1 && me.getMessage().charAt(1) == '3')
|
||||
{
|
||||
throw new AuthenticationFailedException("AUTH PLAIN failed (" + me.getMessage()
|
||||
+ ")");
|
||||
+ ")");
|
||||
}
|
||||
throw me;
|
||||
}
|
||||
|
|
|
@ -9,19 +9,24 @@ import com.android.email.Email;
|
|||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
|
||||
public class StatusOutputStream extends FilterOutputStream {
|
||||
public class StatusOutputStream extends FilterOutputStream
|
||||
{
|
||||
private long mCount = 0;
|
||||
|
||||
public StatusOutputStream(OutputStream out) {
|
||||
|
||||
public StatusOutputStream(OutputStream out)
|
||||
{
|
||||
super(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int oneByte) throws IOException {
|
||||
public void write(int oneByte) throws IOException
|
||||
{
|
||||
super.write(oneByte);
|
||||
mCount++;
|
||||
if (Config.LOGV) {
|
||||
if (mCount % 1024 == 0) {
|
||||
if (Config.LOGV)
|
||||
{
|
||||
if (mCount % 1024 == 0)
|
||||
{
|
||||
Log.v(Email.LOG_TAG, "# " + mCount);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,47 +19,55 @@ import org.apache.http.params.HttpParams;
|
|||
|
||||
import com.android.email.mail.store.TrustManagerFactory;
|
||||
|
||||
public class TrustedSocketFactory implements LayeredSocketFactory {
|
||||
private SSLSocketFactory mSocketFactory;
|
||||
private org.apache.http.conn.ssl.SSLSocketFactory mSchemeSocketFactory;
|
||||
|
||||
public TrustedSocketFactory(String host, boolean secure) throws NoSuchAlgorithmException, KeyManagementException{
|
||||
public class TrustedSocketFactory implements LayeredSocketFactory
|
||||
{
|
||||
private SSLSocketFactory mSocketFactory;
|
||||
private org.apache.http.conn.ssl.SSLSocketFactory mSchemeSocketFactory;
|
||||
|
||||
public TrustedSocketFactory(String host, boolean secure) throws NoSuchAlgorithmException, KeyManagementException
|
||||
{
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, new TrustManager[] {
|
||||
TrustManagerFactory.get(host, secure)
|
||||
sslContext.init(null, new TrustManager[]
|
||||
{
|
||||
TrustManagerFactory.get(host, secure)
|
||||
}, new SecureRandom());
|
||||
mSocketFactory = sslContext.getSocketFactory();
|
||||
mSchemeSocketFactory = org.apache.http.conn.ssl.SSLSocketFactory.getSocketFactory();
|
||||
mSchemeSocketFactory.setHostnameVerifier(
|
||||
org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
||||
}
|
||||
org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
||||
}
|
||||
|
||||
public Socket connectSocket(Socket sock, String host, int port,
|
||||
InetAddress localAddress, int localPort, HttpParams params)
|
||||
throws IOException, UnknownHostException, ConnectTimeoutException {
|
||||
return mSchemeSocketFactory.connectSocket(sock, host, port, localAddress, localPort, params);
|
||||
}
|
||||
public Socket connectSocket(Socket sock, String host, int port,
|
||||
InetAddress localAddress, int localPort, HttpParams params)
|
||||
throws IOException, UnknownHostException, ConnectTimeoutException
|
||||
{
|
||||
return mSchemeSocketFactory.connectSocket(sock, host, port, localAddress, localPort, params);
|
||||
}
|
||||
|
||||
public Socket createSocket() throws IOException {
|
||||
return mSocketFactory.createSocket();
|
||||
}
|
||||
public Socket createSocket() throws IOException
|
||||
{
|
||||
return mSocketFactory.createSocket();
|
||||
}
|
||||
|
||||
public boolean isSecure(Socket sock) throws IllegalArgumentException {
|
||||
return mSchemeSocketFactory.isSecure(sock);
|
||||
}
|
||||
public Socket createSocket(
|
||||
final Socket socket,
|
||||
final String host,
|
||||
final int port,
|
||||
final boolean autoClose
|
||||
) throws IOException, UnknownHostException {
|
||||
SSLSocket sslSocket = (SSLSocket) mSocketFactory.createSocket(
|
||||
socket,
|
||||
host,
|
||||
port,
|
||||
autoClose
|
||||
);
|
||||
//hostnameVerifier.verify(host, sslSocket);
|
||||
// verifyHostName() didn't blowup - good!
|
||||
return sslSocket;
|
||||
}}
|
||||
public boolean isSecure(Socket sock) throws IllegalArgumentException
|
||||
{
|
||||
return mSchemeSocketFactory.isSecure(sock);
|
||||
}
|
||||
public Socket createSocket(
|
||||
final Socket socket,
|
||||
final String host,
|
||||
final int port,
|
||||
final boolean autoClose
|
||||
) throws IOException, UnknownHostException
|
||||
{
|
||||
SSLSocket sslSocket = (SSLSocket) mSocketFactory.createSocket(
|
||||
socket,
|
||||
host,
|
||||
port,
|
||||
autoClose
|
||||
);
|
||||
//hostnameVerifier.verify(host, sslSocket);
|
||||
// verifyHostName() didn't blowup - good!
|
||||
return sslSocket;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,8 @@ import com.android.email.mail.store.WebDavStore.HttpGeneric;
|
|||
import com.android.email.mail.store.WebDavStore.DataSet;
|
||||
import com.android.email.mail.store.WebDavStore.WebDavHandler;
|
||||
|
||||
public class WebDavTransport extends Transport {
|
||||
public class WebDavTransport extends Transport
|
||||
{
|
||||
public static final int CONNECTION_SECURITY_NONE = 0;
|
||||
public static final int CONNECTION_SECURITY_TLS_OPTIONAL = 1;
|
||||
public static final int CONNECTION_SECURITY_TLS_REQUIRED = 2;
|
||||
|
@ -75,7 +76,7 @@ public class WebDavTransport extends Transport {
|
|||
Socket mSocket;
|
||||
PeekableInputStream mIn;
|
||||
OutputStream mOut;
|
||||
private WebDavStore store;
|
||||
private WebDavStore store;
|
||||
|
||||
/**
|
||||
* webdav://user:password@server:port CONNECTION_SECURITY_NONE
|
||||
|
@ -86,24 +87,28 @@ public class WebDavTransport extends Transport {
|
|||
*
|
||||
* @param _uri
|
||||
*/
|
||||
public WebDavTransport(String _uri) throws MessagingException {
|
||||
store = new WebDavStore(_uri);
|
||||
public WebDavTransport(String _uri) throws MessagingException
|
||||
{
|
||||
store = new WebDavStore(_uri);
|
||||
Log.d(Email.LOG_TAG, ">>> New WebDavTransport creation complete");
|
||||
}
|
||||
|
||||
public void open() throws MessagingException {
|
||||
public void open() throws MessagingException
|
||||
{
|
||||
Log.d(Email.LOG_TAG, ">>> open called on WebDavTransport ");
|
||||
store.getHttpClient();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
|
||||
public void close()
|
||||
{
|
||||
}
|
||||
|
||||
public void sendMessage(Message message) throws MessagingException {
|
||||
|
||||
|
||||
public void sendMessage(Message message) throws MessagingException
|
||||
{
|
||||
|
||||
store.sendMessages(new Message[] { message });
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,151 +11,152 @@ import android.util.Log;
|
|||
|
||||
public class Editor implements android.content.SharedPreferences.Editor
|
||||
{
|
||||
private Storage storage;
|
||||
private HashMap<String, String> changes = new HashMap<String, String>();
|
||||
private ArrayList<String> removals = new ArrayList<String>();
|
||||
private boolean removeAll = false;
|
||||
|
||||
Map<String, String> snapshot = new HashMap<String, String>();
|
||||
|
||||
|
||||
protected Editor(Storage storage)
|
||||
{
|
||||
this.storage = storage;
|
||||
snapshot.putAll(storage.getAll());
|
||||
}
|
||||
|
||||
public void copy(android.content.SharedPreferences input)
|
||||
{
|
||||
Map<String, ?> oldVals = input.getAll();
|
||||
for (Entry<String, ?> entry : oldVals.entrySet())
|
||||
private Storage storage;
|
||||
private HashMap<String, String> changes = new HashMap<String, String>();
|
||||
private ArrayList<String> removals = new ArrayList<String>();
|
||||
private boolean removeAll = false;
|
||||
|
||||
Map<String, String> snapshot = new HashMap<String, String>();
|
||||
|
||||
|
||||
protected Editor(Storage storage)
|
||||
{
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
if (key != null && value != null)
|
||||
{
|
||||
if (Email.DEBUG)
|
||||
this.storage = storage;
|
||||
snapshot.putAll(storage.getAll());
|
||||
}
|
||||
|
||||
public void copy(android.content.SharedPreferences input)
|
||||
{
|
||||
Map<String, ?> oldVals = input.getAll();
|
||||
for (Entry<String, ?> entry : oldVals.entrySet())
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Copying key '" + key + "', value '" + value + "'");
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
if (key != null && value != null)
|
||||
{
|
||||
if (Email.DEBUG)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Copying key '" + key + "', value '" + value + "'");
|
||||
}
|
||||
changes.put(key, "" + value);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Email.DEBUG)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Skipping copying key '" + key + "', value '" + value + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//@Override
|
||||
public android.content.SharedPreferences.Editor clear()
|
||||
{
|
||||
removeAll = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/* This method is poorly defined. It should throw an Exception on failure */
|
||||
//@Override
|
||||
public boolean commit()
|
||||
{
|
||||
try
|
||||
{
|
||||
commitChanges();
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Failed to save preferences", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void commitChanges() throws Exception
|
||||
{
|
||||
long startTime = System.currentTimeMillis();
|
||||
Log.i(Email.LOG_TAG, "Committing preference changes");
|
||||
Runnable committer = new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
if (removeAll)
|
||||
{
|
||||
storage.removeAll();
|
||||
}
|
||||
for (String removeKey : removals)
|
||||
{
|
||||
storage.remove(removeKey);
|
||||
}
|
||||
for (Entry<String, String> entry : changes.entrySet())
|
||||
{
|
||||
String key = entry.getKey();
|
||||
String newValue = entry.getValue();
|
||||
String oldValue = snapshot.get(key);
|
||||
if (removeAll || removals.contains(key) || newValue.equals(oldValue) != true)
|
||||
{
|
||||
storage.put(key, newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
storage.doInTransaction(committer);
|
||||
long endTime = System.currentTimeMillis();
|
||||
Log.i(Email.LOG_TAG, "Preferences commit took " + (endTime - startTime) + "ms");
|
||||
|
||||
}
|
||||
|
||||
//@Override
|
||||
public android.content.SharedPreferences.Editor putBoolean(String key,
|
||||
boolean value)
|
||||
{
|
||||
changes.put(key, "" + value);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Email.DEBUG)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Skipping copying key '" + key + "', value '" + value + "'");
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
//@Override
|
||||
public android.content.SharedPreferences.Editor clear()
|
||||
{
|
||||
removeAll = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/* This method is poorly defined. It should throw an Exception on failure */
|
||||
//@Override
|
||||
public boolean commit()
|
||||
{
|
||||
try
|
||||
//@Override
|
||||
public android.content.SharedPreferences.Editor putFloat(String key,
|
||||
float value)
|
||||
{
|
||||
commitChanges();
|
||||
return true;
|
||||
changes.put(key, "" + value);
|
||||
return this;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
//@Override
|
||||
public android.content.SharedPreferences.Editor putInt(String key, int value)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "Failed to save preferences", e);
|
||||
return false;
|
||||
changes.put(key, "" + value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public void commitChanges() throws Exception
|
||||
{
|
||||
long startTime = System.currentTimeMillis();
|
||||
Log.i(Email.LOG_TAG, "Committing preference changes");
|
||||
Runnable committer = new Runnable() {
|
||||
public void run()
|
||||
{
|
||||
if (removeAll)
|
||||
{
|
||||
storage.removeAll();
|
||||
}
|
||||
for (String removeKey : removals)
|
||||
{
|
||||
storage.remove(removeKey);
|
||||
}
|
||||
for (Entry<String, String> entry : changes.entrySet())
|
||||
{
|
||||
String key = entry.getKey();
|
||||
String newValue = entry.getValue();
|
||||
String oldValue = snapshot.get(key);
|
||||
if (removeAll || removals.contains(key) || newValue.equals(oldValue) != true)
|
||||
{
|
||||
storage.put(key, newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
storage.doInTransaction(committer);
|
||||
long endTime = System.currentTimeMillis();
|
||||
Log.i(Email.LOG_TAG, "Preferences commit took " + (endTime - startTime) + "ms");
|
||||
|
||||
}
|
||||
|
||||
//@Override
|
||||
public android.content.SharedPreferences.Editor putBoolean(String key,
|
||||
boolean value)
|
||||
{
|
||||
changes.put(key, "" + value);
|
||||
return this;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public android.content.SharedPreferences.Editor putFloat(String key,
|
||||
float value)
|
||||
{
|
||||
changes.put(key, "" + value);
|
||||
return this;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public android.content.SharedPreferences.Editor putInt(String key, int value)
|
||||
{
|
||||
changes.put(key, "" + value);
|
||||
return this;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public android.content.SharedPreferences.Editor putLong(String key, long value)
|
||||
{
|
||||
changes.put(key, "" + value);
|
||||
return this;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public android.content.SharedPreferences.Editor putString(String key,
|
||||
String value)
|
||||
{
|
||||
if (value == null)
|
||||
//@Override
|
||||
public android.content.SharedPreferences.Editor putLong(String key, long value)
|
||||
{
|
||||
remove(key);
|
||||
changes.put(key, "" + value);
|
||||
return this;
|
||||
}
|
||||
else
|
||||
{
|
||||
changes.put(key, value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public android.content.SharedPreferences.Editor remove(String key)
|
||||
{
|
||||
removals.add(key);
|
||||
return this;
|
||||
}
|
||||
//@Override
|
||||
public android.content.SharedPreferences.Editor putString(String key,
|
||||
String value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
remove(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
changes.put(key, value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public android.content.SharedPreferences.Editor remove(String key)
|
||||
{
|
||||
removals.add(key);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,285 +16,289 @@ import android.util.Log;
|
|||
|
||||
public class Storage implements SharedPreferences
|
||||
{
|
||||
private static ConcurrentHashMap<Context, Storage> storages =
|
||||
new ConcurrentHashMap<Context, Storage>();
|
||||
|
||||
private volatile ConcurrentHashMap<String, String> storage = new ConcurrentHashMap<String, String>();
|
||||
|
||||
private CopyOnWriteArrayList<OnSharedPreferenceChangeListener> listeners =
|
||||
new CopyOnWriteArrayList<OnSharedPreferenceChangeListener>();
|
||||
|
||||
private int DB_VERSION = 1; // CHANGING THIS WILL DESTROY ALL USER PREFERENCES!
|
||||
private String DB_NAME = "preferences_storage";
|
||||
|
||||
private ThreadLocal<ConcurrentHashMap<String, String>> workingStorage
|
||||
private static ConcurrentHashMap<Context, Storage> storages =
|
||||
new ConcurrentHashMap<Context, Storage>();
|
||||
|
||||
private volatile ConcurrentHashMap<String, String> storage = new ConcurrentHashMap<String, String>();
|
||||
|
||||
private CopyOnWriteArrayList<OnSharedPreferenceChangeListener> listeners =
|
||||
new CopyOnWriteArrayList<OnSharedPreferenceChangeListener>();
|
||||
|
||||
private int DB_VERSION = 1; // CHANGING THIS WILL DESTROY ALL USER PREFERENCES!
|
||||
private String DB_NAME = "preferences_storage";
|
||||
|
||||
private ThreadLocal<ConcurrentHashMap<String, String>> workingStorage
|
||||
= new ThreadLocal<ConcurrentHashMap<String, String>>();
|
||||
private ThreadLocal<SQLiteDatabase> workingDB =
|
||||
new ThreadLocal<SQLiteDatabase>();
|
||||
private ThreadLocal<ArrayList<String>> workingChangedKeys = new ThreadLocal<ArrayList<String>>();
|
||||
|
||||
|
||||
private Context context = null;
|
||||
|
||||
private SQLiteDatabase openDB()
|
||||
{
|
||||
SQLiteDatabase mDb = context.openOrCreateDatabase(DB_NAME, Context.MODE_PRIVATE, null);
|
||||
if (mDb.getVersion() != DB_VERSION)
|
||||
private ThreadLocal<SQLiteDatabase> workingDB =
|
||||
new ThreadLocal<SQLiteDatabase>();
|
||||
private ThreadLocal<ArrayList<String>> workingChangedKeys = new ThreadLocal<ArrayList<String>>();
|
||||
|
||||
|
||||
private Context context = null;
|
||||
|
||||
private SQLiteDatabase openDB()
|
||||
{
|
||||
Log.i(Email.LOG_TAG, "Creating Storage database");
|
||||
mDb.execSQL("DROP TABLE IF EXISTS preferences_storage");
|
||||
mDb.execSQL("CREATE TABLE preferences_storage " +
|
||||
"(primkey TEXT PRIMARY KEY ON CONFLICT REPLACE, value TEXT)");
|
||||
mDb.setVersion(DB_VERSION);
|
||||
}
|
||||
return mDb;
|
||||
}
|
||||
|
||||
|
||||
public static Storage getStorage(Context context)
|
||||
{
|
||||
Storage tmpStorage = storages.get(context);
|
||||
if (tmpStorage != null)
|
||||
{
|
||||
if (Email.DEBUG)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Returning already existing Storage");
|
||||
}
|
||||
return tmpStorage;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Email.DEBUG)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Creating provisional storage");
|
||||
}
|
||||
tmpStorage = new Storage(context);
|
||||
Storage oldStorage = storages.putIfAbsent(context, tmpStorage);
|
||||
if (oldStorage != null)
|
||||
{
|
||||
if (Email.DEBUG)
|
||||
SQLiteDatabase mDb = context.openOrCreateDatabase(DB_NAME, Context.MODE_PRIVATE, null);
|
||||
if (mDb.getVersion() != DB_VERSION)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Another thread beat us to creating the Storage, returning that one");
|
||||
Log.i(Email.LOG_TAG, "Creating Storage database");
|
||||
mDb.execSQL("DROP TABLE IF EXISTS preferences_storage");
|
||||
mDb.execSQL("CREATE TABLE preferences_storage " +
|
||||
"(primkey TEXT PRIMARY KEY ON CONFLICT REPLACE, value TEXT)");
|
||||
mDb.setVersion(DB_VERSION);
|
||||
}
|
||||
return oldStorage;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Email.DEBUG)
|
||||
return mDb;
|
||||
}
|
||||
|
||||
|
||||
public static Storage getStorage(Context context)
|
||||
{
|
||||
Storage tmpStorage = storages.get(context);
|
||||
if (tmpStorage != null)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Returning the Storage we created");
|
||||
if (Email.DEBUG)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Returning already existing Storage");
|
||||
}
|
||||
return tmpStorage;
|
||||
}
|
||||
return tmpStorage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadValues()
|
||||
{
|
||||
long startTime = System.currentTimeMillis();
|
||||
Log.i(Email.LOG_TAG, "Loading preferences from DB into Storage");
|
||||
Cursor cursor = null;
|
||||
SQLiteDatabase mDb = null;
|
||||
try {
|
||||
mDb = openDB();
|
||||
|
||||
cursor = mDb.rawQuery("SELECT primkey, value FROM preferences_storage", null);
|
||||
while (cursor.moveToNext()) {
|
||||
String key = cursor.getString(0);
|
||||
String value = cursor.getString(1);
|
||||
if (Email.DEBUG)
|
||||
else
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Loading key '" + key + "', value = '" + value + "'");
|
||||
if (Email.DEBUG)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Creating provisional storage");
|
||||
}
|
||||
tmpStorage = new Storage(context);
|
||||
Storage oldStorage = storages.putIfAbsent(context, tmpStorage);
|
||||
if (oldStorage != null)
|
||||
{
|
||||
if (Email.DEBUG)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Another thread beat us to creating the Storage, returning that one");
|
||||
}
|
||||
return oldStorage;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Email.DEBUG)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Returning the Storage we created");
|
||||
}
|
||||
return tmpStorage;
|
||||
}
|
||||
}
|
||||
storage.put(key, value);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
if (mDb != null)
|
||||
{
|
||||
mDb.close();
|
||||
}
|
||||
long endTime = System.currentTimeMillis();
|
||||
Log.i(Email.LOG_TAG, "Preferences load took " + (endTime - startTime) + "ms");
|
||||
}
|
||||
}
|
||||
|
||||
private Storage(Context context)
|
||||
{
|
||||
this.context = context;
|
||||
loadValues();
|
||||
}
|
||||
|
||||
private void keyChange(String key)
|
||||
{
|
||||
ArrayList<String> changedKeys = workingChangedKeys.get();
|
||||
if (changedKeys.contains(key) == false)
|
||||
{
|
||||
changedKeys.add(key);
|
||||
}
|
||||
}
|
||||
|
||||
protected void put(String key, String value)
|
||||
{
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put("primkey", key);
|
||||
cv.put("value", value);
|
||||
workingDB.get().insert("preferences_storage", "primkey", cv);
|
||||
workingStorage.get().put(key, value);
|
||||
|
||||
keyChange(key);
|
||||
}
|
||||
|
||||
protected void remove(String key)
|
||||
{
|
||||
workingDB.get().delete("preferences_storage", "primkey = ?", new String[] { key });
|
||||
workingStorage.get().remove(key);
|
||||
|
||||
keyChange(key);
|
||||
}
|
||||
|
||||
protected void removeAll()
|
||||
{
|
||||
for (String key : workingStorage.get().keySet())
|
||||
private void loadValues()
|
||||
{
|
||||
keyChange(key);
|
||||
}
|
||||
workingDB.get().execSQL("DELETE FROM preferences_storage");
|
||||
workingStorage.get().clear();
|
||||
}
|
||||
|
||||
protected void doInTransaction(Runnable dbWork)
|
||||
{
|
||||
ConcurrentHashMap<String, String> newStorage = new ConcurrentHashMap<String, String>();
|
||||
newStorage.putAll(storage);
|
||||
workingStorage.set(newStorage);
|
||||
|
||||
SQLiteDatabase mDb = openDB();
|
||||
workingDB.set(mDb);
|
||||
|
||||
ArrayList<String> changedKeys = new ArrayList<String>();
|
||||
workingChangedKeys.set(changedKeys);
|
||||
|
||||
mDb.beginTransaction();
|
||||
try
|
||||
{
|
||||
dbWork.run();
|
||||
mDb.setTransactionSuccessful();
|
||||
storage = newStorage;
|
||||
for (String changedKey : changedKeys)
|
||||
{
|
||||
for (OnSharedPreferenceChangeListener listener : listeners)
|
||||
long startTime = System.currentTimeMillis();
|
||||
Log.i(Email.LOG_TAG, "Loading preferences from DB into Storage");
|
||||
Cursor cursor = null;
|
||||
SQLiteDatabase mDb = null;
|
||||
try
|
||||
{
|
||||
listener.onSharedPreferenceChanged(this, changedKey);
|
||||
mDb = openDB();
|
||||
|
||||
cursor = mDb.rawQuery("SELECT primkey, value FROM preferences_storage", null);
|
||||
while (cursor.moveToNext())
|
||||
{
|
||||
String key = cursor.getString(0);
|
||||
String value = cursor.getString(1);
|
||||
if (Email.DEBUG)
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Loading key '" + key + "', value = '" + value + "'");
|
||||
}
|
||||
storage.put(key, value);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (cursor != null)
|
||||
{
|
||||
cursor.close();
|
||||
}
|
||||
if (mDb != null)
|
||||
{
|
||||
mDb.close();
|
||||
}
|
||||
long endTime = System.currentTimeMillis();
|
||||
Log.i(Email.LOG_TAG, "Preferences load took " + (endTime - startTime) + "ms");
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
||||
private Storage(Context context)
|
||||
{
|
||||
workingDB.remove();
|
||||
workingStorage.remove();
|
||||
workingChangedKeys.remove();
|
||||
mDb.endTransaction();
|
||||
if (mDb != null)
|
||||
{
|
||||
mDb.close();
|
||||
}
|
||||
this.context = context;
|
||||
loadValues();
|
||||
}
|
||||
}
|
||||
|
||||
public long size()
|
||||
{
|
||||
return storage.size();
|
||||
}
|
||||
|
||||
//@Override
|
||||
public boolean contains(String key)
|
||||
{
|
||||
return storage.contains(key);
|
||||
}
|
||||
|
||||
//@Override
|
||||
public com.android.email.preferences.Editor edit()
|
||||
{
|
||||
return new com.android.email.preferences.Editor(this);
|
||||
}
|
||||
|
||||
//@Override
|
||||
public Map<String, String> getAll()
|
||||
{
|
||||
return storage;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public boolean getBoolean(String key, boolean defValue)
|
||||
{
|
||||
String val = storage.get(key);
|
||||
if (val == null)
|
||||
private void keyChange(String key)
|
||||
{
|
||||
return defValue;
|
||||
ArrayList<String> changedKeys = workingChangedKeys.get();
|
||||
if (changedKeys.contains(key) == false)
|
||||
{
|
||||
changedKeys.add(key);
|
||||
}
|
||||
}
|
||||
return Boolean.parseBoolean(val);
|
||||
}
|
||||
|
||||
//@Override
|
||||
public float getFloat(String key, float defValue)
|
||||
{
|
||||
String val = storage.get(key);
|
||||
if (val == null)
|
||||
protected void put(String key, String value)
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
return Float.parseFloat(val);
|
||||
}
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put("primkey", key);
|
||||
cv.put("value", value);
|
||||
workingDB.get().insert("preferences_storage", "primkey", cv);
|
||||
workingStorage.get().put(key, value);
|
||||
|
||||
//@Override
|
||||
public int getInt(String key, int defValue)
|
||||
{
|
||||
String val = storage.get(key);
|
||||
if (val == null)
|
||||
keyChange(key);
|
||||
}
|
||||
|
||||
protected void remove(String key)
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
return Integer.parseInt(val);
|
||||
}
|
||||
workingDB.get().delete("preferences_storage", "primkey = ?", new String[] { key });
|
||||
workingStorage.get().remove(key);
|
||||
|
||||
//@Override
|
||||
public long getLong(String key, long defValue)
|
||||
{
|
||||
String val = storage.get(key);
|
||||
if (val == null)
|
||||
keyChange(key);
|
||||
}
|
||||
|
||||
protected void removeAll()
|
||||
{
|
||||
return defValue;
|
||||
for (String key : workingStorage.get().keySet())
|
||||
{
|
||||
keyChange(key);
|
||||
}
|
||||
workingDB.get().execSQL("DELETE FROM preferences_storage");
|
||||
workingStorage.get().clear();
|
||||
}
|
||||
return Long.parseLong(val);
|
||||
}
|
||||
|
||||
//@Override
|
||||
public String getString(String key, String defValue)
|
||||
{
|
||||
String val = storage.get(key);
|
||||
if (val == null)
|
||||
protected void doInTransaction(Runnable dbWork)
|
||||
{
|
||||
return defValue;
|
||||
ConcurrentHashMap<String, String> newStorage = new ConcurrentHashMap<String, String>();
|
||||
newStorage.putAll(storage);
|
||||
workingStorage.set(newStorage);
|
||||
|
||||
SQLiteDatabase mDb = openDB();
|
||||
workingDB.set(mDb);
|
||||
|
||||
ArrayList<String> changedKeys = new ArrayList<String>();
|
||||
workingChangedKeys.set(changedKeys);
|
||||
|
||||
mDb.beginTransaction();
|
||||
try
|
||||
{
|
||||
dbWork.run();
|
||||
mDb.setTransactionSuccessful();
|
||||
storage = newStorage;
|
||||
for (String changedKey : changedKeys)
|
||||
{
|
||||
for (OnSharedPreferenceChangeListener listener : listeners)
|
||||
{
|
||||
listener.onSharedPreferenceChanged(this, changedKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
workingDB.remove();
|
||||
workingStorage.remove();
|
||||
workingChangedKeys.remove();
|
||||
mDb.endTransaction();
|
||||
if (mDb != null)
|
||||
{
|
||||
mDb.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public void registerOnSharedPreferenceChangeListener(
|
||||
OnSharedPreferenceChangeListener listener)
|
||||
{
|
||||
listeners.addIfAbsent(listener);
|
||||
}
|
||||
public long size()
|
||||
{
|
||||
return storage.size();
|
||||
}
|
||||
|
||||
//@Override
|
||||
public void unregisterOnSharedPreferenceChangeListener(
|
||||
OnSharedPreferenceChangeListener listener)
|
||||
{
|
||||
listeners.remove(listener);
|
||||
}
|
||||
//@Override
|
||||
public boolean contains(String key)
|
||||
{
|
||||
return storage.contains(key);
|
||||
}
|
||||
|
||||
//@Override
|
||||
public com.android.email.preferences.Editor edit()
|
||||
{
|
||||
return new com.android.email.preferences.Editor(this);
|
||||
}
|
||||
|
||||
//@Override
|
||||
public Map<String, String> getAll()
|
||||
{
|
||||
return storage;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public boolean getBoolean(String key, boolean defValue)
|
||||
{
|
||||
String val = storage.get(key);
|
||||
if (val == null)
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
return Boolean.parseBoolean(val);
|
||||
}
|
||||
|
||||
//@Override
|
||||
public float getFloat(String key, float defValue)
|
||||
{
|
||||
String val = storage.get(key);
|
||||
if (val == null)
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
return Float.parseFloat(val);
|
||||
}
|
||||
|
||||
//@Override
|
||||
public int getInt(String key, int defValue)
|
||||
{
|
||||
String val = storage.get(key);
|
||||
if (val == null)
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
return Integer.parseInt(val);
|
||||
}
|
||||
|
||||
//@Override
|
||||
public long getLong(String key, long defValue)
|
||||
{
|
||||
String val = storage.get(key);
|
||||
if (val == null)
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
return Long.parseLong(val);
|
||||
}
|
||||
|
||||
//@Override
|
||||
public String getString(String key, String defValue)
|
||||
{
|
||||
String val = storage.get(key);
|
||||
if (val == null)
|
||||
{
|
||||
return defValue;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public void registerOnSharedPreferenceChangeListener(
|
||||
OnSharedPreferenceChangeListener listener)
|
||||
{
|
||||
listeners.addIfAbsent(listener);
|
||||
}
|
||||
|
||||
//@Override
|
||||
public void unregisterOnSharedPreferenceChangeListener(
|
||||
OnSharedPreferenceChangeListener listener)
|
||||
{
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,98 +30,113 @@ import com.android.email.mail.internet.MimeUtility;
|
|||
/*
|
||||
* A simple ContentProvider that allows file access to Email's attachments.
|
||||
*/
|
||||
public class AttachmentProvider extends ContentProvider {
|
||||
public static final Uri CONTENT_URI = Uri.parse( "content://com.fsck.k9.attachmentprovider");
|
||||
public class AttachmentProvider extends ContentProvider
|
||||
{
|
||||
public static final Uri CONTENT_URI = Uri.parse("content://com.fsck.k9.attachmentprovider");
|
||||
|
||||
private static final String FORMAT_RAW = "RAW";
|
||||
private static final String FORMAT_THUMBNAIL = "THUMBNAIL";
|
||||
|
||||
public static class AttachmentProviderColumns {
|
||||
public static class AttachmentProviderColumns
|
||||
{
|
||||
public static final String _ID = "_id";
|
||||
public static final String DATA = "_data";
|
||||
public static final String DISPLAY_NAME = "_display_name";
|
||||
public static final String SIZE = "_size";
|
||||
}
|
||||
|
||||
public static Uri getAttachmentUri(Account account, long id) {
|
||||
public static Uri getAttachmentUri(Account account, long id)
|
||||
{
|
||||
return CONTENT_URI.buildUpon()
|
||||
.appendPath(account.getUuid() + ".db")
|
||||
.appendPath(Long.toString(id))
|
||||
.appendPath(FORMAT_RAW)
|
||||
.build();
|
||||
.appendPath(account.getUuid() + ".db")
|
||||
.appendPath(Long.toString(id))
|
||||
.appendPath(FORMAT_RAW)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static Uri getAttachmentThumbnailUri(Account account, long id, int width, int height) {
|
||||
public static Uri getAttachmentThumbnailUri(Account account, long id, int width, int height)
|
||||
{
|
||||
return CONTENT_URI.buildUpon()
|
||||
.appendPath(account.getUuid() + ".db")
|
||||
.appendPath(Long.toString(id))
|
||||
.appendPath(FORMAT_THUMBNAIL)
|
||||
.appendPath(Integer.toString(width))
|
||||
.appendPath(Integer.toString(height))
|
||||
.build();
|
||||
.appendPath(account.getUuid() + ".db")
|
||||
.appendPath(Long.toString(id))
|
||||
.appendPath(FORMAT_THUMBNAIL)
|
||||
.appendPath(Integer.toString(width))
|
||||
.appendPath(Integer.toString(height))
|
||||
.build();
|
||||
}
|
||||
|
||||
public static Uri getAttachmentUri(String db, long id) {
|
||||
public static Uri getAttachmentUri(String db, long id)
|
||||
{
|
||||
return CONTENT_URI.buildUpon()
|
||||
.appendPath(db)
|
||||
.appendPath(Long.toString(id))
|
||||
.appendPath(FORMAT_RAW)
|
||||
.build();
|
||||
.appendPath(db)
|
||||
.appendPath(Long.toString(id))
|
||||
.appendPath(FORMAT_RAW)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
public boolean onCreate()
|
||||
{
|
||||
/*
|
||||
* We use the cache dir as a temporary directory (since Android doesn't give us one) so
|
||||
* on startup we'll clean up any .tmp files from the last run.
|
||||
*/
|
||||
File[] files = getContext().getCacheDir().listFiles();
|
||||
for (File file : files) {
|
||||
if (file.getName().endsWith(".tmp")) {
|
||||
for (File file : files)
|
||||
{
|
||||
if (file.getName().endsWith(".tmp"))
|
||||
{
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void clear(Context lContext) {
|
||||
/*
|
||||
* We use the cache dir as a temporary directory (since Android doesn't give us one) so
|
||||
* on startup we'll clean up any .tmp files from the last run.
|
||||
*/
|
||||
File[] files = lContext.getCacheDir().listFiles();
|
||||
for (File file : files) {
|
||||
try {
|
||||
Log.d(Email.LOG_TAG, "Deleting file " + file.getCanonicalPath());
|
||||
|
||||
public static void clear(Context lContext)
|
||||
{
|
||||
/*
|
||||
* We use the cache dir as a temporary directory (since Android doesn't give us one) so
|
||||
* on startup we'll clean up any .tmp files from the last run.
|
||||
*/
|
||||
File[] files = lContext.getCacheDir().listFiles();
|
||||
for (File file : files)
|
||||
{
|
||||
try
|
||||
{
|
||||
Log.d(Email.LOG_TAG, "Deleting file " + file.getCanonicalPath());
|
||||
}
|
||||
catch (IOException ioe) {} // No need to log failure to log
|
||||
file.delete();
|
||||
}
|
||||
catch (IOException ioe) {} // No need to log failure to log
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType(Uri uri) {
|
||||
public String getType(Uri uri)
|
||||
{
|
||||
List<String> segments = uri.getPathSegments();
|
||||
String dbName = segments.get(0);
|
||||
String id = segments.get(1);
|
||||
String format = segments.get(2);
|
||||
if (FORMAT_THUMBNAIL.equals(format)) {
|
||||
if (FORMAT_THUMBNAIL.equals(format))
|
||||
{
|
||||
return "image/png";
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
String path = getContext().getDatabasePath(dbName).getAbsolutePath();
|
||||
SQLiteDatabase db = null;
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
try
|
||||
{
|
||||
db = SQLiteDatabase.openDatabase(path, null, 0);
|
||||
cursor = db.query(
|
||||
"attachments",
|
||||
new String[] { "mime_type" },
|
||||
"id = ?",
|
||||
new String[] { id },
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
"attachments",
|
||||
new String[] { "mime_type" },
|
||||
"id = ?",
|
||||
new String[] { id },
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
cursor.moveToFirst();
|
||||
String type = cursor.getString(0);
|
||||
cursor.close();
|
||||
|
@ -129,11 +144,14 @@ public class AttachmentProvider extends ContentProvider {
|
|||
return type;
|
||||
|
||||
}
|
||||
finally {
|
||||
if (cursor != null) {
|
||||
finally
|
||||
{
|
||||
if (cursor != null)
|
||||
{
|
||||
cursor.close();
|
||||
}
|
||||
if (db != null) {
|
||||
if (db != null)
|
||||
{
|
||||
db.close();
|
||||
}
|
||||
|
||||
|
@ -142,23 +160,27 @@ public class AttachmentProvider extends ContentProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
|
||||
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException
|
||||
{
|
||||
List<String> segments = uri.getPathSegments();
|
||||
String dbName = segments.get(0);
|
||||
String id = segments.get(1);
|
||||
String format = segments.get(2);
|
||||
if (FORMAT_THUMBNAIL.equals(format)) {
|
||||
if (FORMAT_THUMBNAIL.equals(format))
|
||||
{
|
||||
int width = Integer.parseInt(segments.get(3));
|
||||
int height = Integer.parseInt(segments.get(4));
|
||||
String filename = "thmb_" + dbName + "_" + id;
|
||||
File dir = getContext().getCacheDir();
|
||||
File file = new File(dir, filename);
|
||||
if (!file.exists()) {
|
||||
if (!file.exists())
|
||||
{
|
||||
Uri attachmentUri = getAttachmentUri(dbName, Long.parseLong(id));
|
||||
String type = getType(attachmentUri);
|
||||
try {
|
||||
try
|
||||
{
|
||||
FileInputStream in = new FileInputStream(
|
||||
new File(getContext().getDatabasePath(dbName + "_att"), id));
|
||||
new File(getContext().getDatabasePath(dbName + "_att"), id));
|
||||
Bitmap thumbnail = createThumbnail(type, in);
|
||||
thumbnail = thumbnail.createScaledBitmap(thumbnail, width, height, true);
|
||||
FileOutputStream out = new FileOutputStream(file);
|
||||
|
@ -166,38 +188,45 @@ public class AttachmentProvider extends ContentProvider {
|
|||
out.close();
|
||||
in.close();
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
catch (IOException ioe)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
return ParcelFileDescriptor.open(
|
||||
new File(getContext().getDatabasePath(dbName + "_att"), id),
|
||||
ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
new File(getContext().getDatabasePath(dbName + "_att"), id),
|
||||
ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(Uri uri, String arg1, String[] arg2) {
|
||||
public int delete(Uri uri, String arg1, String[] arg2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri insert(Uri uri, ContentValues values) {
|
||||
public Uri insert(Uri uri, ContentValues values)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
||||
String sortOrder) {
|
||||
if (projection == null) {
|
||||
String sortOrder)
|
||||
{
|
||||
if (projection == null)
|
||||
{
|
||||
projection =
|
||||
new String[] {
|
||||
AttachmentProviderColumns._ID,
|
||||
AttachmentProviderColumns.DATA,
|
||||
};
|
||||
new String[]
|
||||
{
|
||||
AttachmentProviderColumns._ID,
|
||||
AttachmentProviderColumns.DATA,
|
||||
};
|
||||
}
|
||||
|
||||
List<String> segments = uri.getPathSegments();
|
||||
|
@ -209,45 +238,55 @@ public class AttachmentProvider extends ContentProvider {
|
|||
int size = -1;
|
||||
SQLiteDatabase db = null;
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
try
|
||||
{
|
||||
db = SQLiteDatabase.openDatabase(path, null, 0);
|
||||
cursor = db.query(
|
||||
"attachments",
|
||||
new String[] { "name", "size" },
|
||||
"id = ?",
|
||||
new String[] { id },
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
if (!cursor.moveToFirst()) {
|
||||
"attachments",
|
||||
new String[] { "name", "size" },
|
||||
"id = ?",
|
||||
new String[] { id },
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
if (!cursor.moveToFirst())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
name = cursor.getString(0);
|
||||
size = cursor.getInt(1);
|
||||
}
|
||||
finally {
|
||||
if (cursor != null) {
|
||||
finally
|
||||
{
|
||||
if (cursor != null)
|
||||
{
|
||||
cursor.close();
|
||||
}
|
||||
if (db != null) {
|
||||
if (db != null)
|
||||
{
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
|
||||
MatrixCursor ret = new MatrixCursor(projection);
|
||||
Object[] values = new Object[projection.length];
|
||||
for (int i = 0, count = projection.length; i < count; i++) {
|
||||
for (int i = 0, count = projection.length; i < count; i++)
|
||||
{
|
||||
String column = projection[i];
|
||||
if (AttachmentProviderColumns._ID.equals(column)) {
|
||||
if (AttachmentProviderColumns._ID.equals(column))
|
||||
{
|
||||
values[i] = id;
|
||||
}
|
||||
else if (AttachmentProviderColumns.DATA.equals(column)) {
|
||||
else if (AttachmentProviderColumns.DATA.equals(column))
|
||||
{
|
||||
values[i] = uri.toString();
|
||||
}
|
||||
else if (AttachmentProviderColumns.DISPLAY_NAME.equals(column)) {
|
||||
else if (AttachmentProviderColumns.DISPLAY_NAME.equals(column))
|
||||
{
|
||||
values[i] = name;
|
||||
}
|
||||
else if (AttachmentProviderColumns.SIZE.equals(column)) {
|
||||
else if (AttachmentProviderColumns.SIZE.equals(column))
|
||||
{
|
||||
values[i] = size;
|
||||
}
|
||||
}
|
||||
|
@ -256,23 +295,29 @@ public class AttachmentProvider extends ContentProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
private Bitmap createThumbnail(String type, InputStream data) {
|
||||
if(MimeUtility.mimeTypeMatches(type, "image/*")) {
|
||||
private Bitmap createThumbnail(String type, InputStream data)
|
||||
{
|
||||
if (MimeUtility.mimeTypeMatches(type, "image/*"))
|
||||
{
|
||||
return createImageThumbnail(data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Bitmap createImageThumbnail(InputStream data) {
|
||||
try {
|
||||
private Bitmap createImageThumbnail(InputStream data)
|
||||
{
|
||||
try
|
||||
{
|
||||
Bitmap bitmap = BitmapFactory.decodeStream(data);
|
||||
return bitmap;
|
||||
}
|
||||
catch (OutOfMemoryError oome) {
|
||||
catch (OutOfMemoryError oome)
|
||||
{
|
||||
/*
|
||||
* Improperly downloaded images, corrupt bitmaps and the like can commonly
|
||||
* cause OOME due to invalid allocation sizes. We're happy with a null bitmap in
|
||||
|
@ -281,7 +326,8 @@ public class AttachmentProvider extends ContentProvider {
|
|||
*/
|
||||
return null;
|
||||
}
|
||||
catch (Exception e) {
|
||||
catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,9 @@ import android.util.Log;
|
|||
|
||||
import com.android.email.Email;
|
||||
|
||||
public class BootReceiver extends BroadcastReceiver {
|
||||
|
||||
public class BootReceiver extends BroadcastReceiver
|
||||
{
|
||||
|
||||
public static String WAKE_LOCK_RELEASE = "com.android.email.service.BroadcastReceiver.wakeLockRelease";
|
||||
public static String FIRE_INTENT = "com.android.email.service.BroadcastReceiver.fireIntent";
|
||||
public static String SCHEDULE_INTENT = "com.android.email.service.BroadcastReceiver.scheduleIntent";
|
||||
|
@ -28,10 +29,10 @@ public class BootReceiver extends BroadcastReceiver {
|
|||
public static String WAKE_LOCK_ID = "com.android.email.service.BroadcastReceiver.wakeLockId";
|
||||
public static String ALARMED_INTENT = "com.android.email.service.BroadcastReceiver.pendingIntent";
|
||||
public static String AT_TIME = "com.android.email.service.BroadcastReceiver.atTime";
|
||||
|
||||
|
||||
private static ConcurrentHashMap<Integer, WakeLock> wakeLocks = new ConcurrentHashMap<Integer, WakeLock>();
|
||||
private static AtomicInteger wakeLockSeq = new AtomicInteger(0);
|
||||
|
||||
|
||||
private Integer getWakeLock(Context context)
|
||||
{
|
||||
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
|
@ -42,7 +43,7 @@ public class BootReceiver extends BroadcastReceiver {
|
|||
wakeLocks.put(tmpWakeLockId, wakeLock);
|
||||
return tmpWakeLockId;
|
||||
}
|
||||
|
||||
|
||||
private void releaseWakeLock(Integer wakeLockId)
|
||||
{
|
||||
if (wakeLockId != null)
|
||||
|
@ -58,31 +59,37 @@ public class BootReceiver extends BroadcastReceiver {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
Integer tmpWakeLockId = getWakeLock(context);
|
||||
try
|
||||
{
|
||||
Log.i(Email.LOG_TAG, "BootReceiver.onReceive" + intent);
|
||||
|
||||
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
|
||||
Email.setServicesEnabled(context, tmpWakeLockId);
|
||||
tmpWakeLockId = null;
|
||||
Log.i(Email.LOG_TAG, "BootReceiver.onReceive" + intent);
|
||||
|
||||
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction()))
|
||||
{
|
||||
Email.setServicesEnabled(context, tmpWakeLockId);
|
||||
tmpWakeLockId = null;
|
||||
}
|
||||
else if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(intent.getAction())) {
|
||||
else if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(intent.getAction()))
|
||||
{
|
||||
MailService.actionCancel(context, tmpWakeLockId);
|
||||
tmpWakeLockId = null;
|
||||
}
|
||||
else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(intent.getAction())) {
|
||||
else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(intent.getAction()))
|
||||
{
|
||||
MailService.actionReschedule(context, tmpWakeLockId);
|
||||
tmpWakeLockId = null;
|
||||
}
|
||||
else if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
|
||||
else if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction()))
|
||||
{
|
||||
boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
|
||||
MailService.connectivityChange(context, !noConnectivity, tmpWakeLockId);
|
||||
tmpWakeLockId = null;
|
||||
}
|
||||
else if (ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED.equals(intent.getAction())) {
|
||||
else if (ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED.equals(intent.getAction()))
|
||||
{
|
||||
MailService.backgroundDataChanged(context, tmpWakeLockId);
|
||||
tmpWakeLockId = null;
|
||||
}
|
||||
|
@ -90,7 +97,7 @@ public class BootReceiver extends BroadcastReceiver {
|
|||
{
|
||||
Intent alarmedIntent = intent.getParcelableExtra(ALARMED_INTENT);
|
||||
String alarmedAction = alarmedIntent.getAction();
|
||||
|
||||
|
||||
Log.i(Email.LOG_TAG, "BootReceiver Got alarm to fire alarmedIntent " + alarmedAction);
|
||||
alarmedIntent.putExtra(WAKE_LOCK_ID, tmpWakeLockId);
|
||||
tmpWakeLockId = null;
|
||||
|
@ -104,21 +111,21 @@ public class BootReceiver extends BroadcastReceiver {
|
|||
long atTime = intent.getLongExtra(AT_TIME, -1);
|
||||
Intent alarmedIntent = intent.getParcelableExtra(ALARMED_INTENT);
|
||||
Log.i(Email.LOG_TAG,"BootReceiver Scheduling intent " + alarmedIntent + " for " + new Date(atTime));
|
||||
|
||||
|
||||
PendingIntent pi = buildPendingIntent(context, intent);
|
||||
AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
|
||||
|
||||
alarmMgr.set(AlarmManager.RTC_WAKEUP, atTime, pi);
|
||||
|
||||
alarmMgr.set(AlarmManager.RTC_WAKEUP, atTime, pi);
|
||||
}
|
||||
else if (CANCEL_INTENT.equals(intent.getAction()))
|
||||
{
|
||||
Intent alarmedIntent = intent.getParcelableExtra(ALARMED_INTENT);
|
||||
Log.i(Email.LOG_TAG, "BootReceiver Canceling alarmedIntent " + alarmedIntent);
|
||||
|
||||
|
||||
PendingIntent pi = buildPendingIntent(context, intent);
|
||||
|
||||
|
||||
AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
|
||||
alarmMgr.cancel(pi);
|
||||
alarmMgr.cancel(pi);
|
||||
}
|
||||
else if (BootReceiver.WAKE_LOCK_RELEASE.equals(intent.getAction()))
|
||||
{
|
||||
|
@ -135,7 +142,7 @@ public class BootReceiver extends BroadcastReceiver {
|
|||
releaseWakeLock(tmpWakeLockId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private PendingIntent buildPendingIntent(Context context, Intent intent)
|
||||
{
|
||||
Intent alarmedIntent = intent.getParcelableExtra(ALARMED_INTENT);
|
||||
|
@ -149,7 +156,7 @@ public class BootReceiver extends BroadcastReceiver {
|
|||
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
|
||||
return pi;
|
||||
}
|
||||
|
||||
|
||||
public static void scheduleIntent(Context context, long atTime, Intent alarmedIntent)
|
||||
{
|
||||
Log.i(Email.LOG_TAG, "BootReceiver Got request to schedule alarmedIntent " + alarmedIntent.getAction());
|
||||
|
@ -160,7 +167,7 @@ public class BootReceiver extends BroadcastReceiver {
|
|||
i.putExtra(AT_TIME, atTime);
|
||||
context.sendBroadcast(i);
|
||||
}
|
||||
|
||||
|
||||
public static void cancelIntent(Context context, Intent alarmedIntent)
|
||||
{
|
||||
Log.i(Email.LOG_TAG, "BootReceiver Got request to cancel alarmedIntent " + alarmedIntent.getAction());
|
||||
|
@ -170,7 +177,7 @@ public class BootReceiver extends BroadcastReceiver {
|
|||
i.putExtra(ALARMED_INTENT, alarmedIntent);
|
||||
context.sendBroadcast(i);
|
||||
}
|
||||
|
||||
|
||||
public static void releaseWakeLock(Context context, int wakeLockId)
|
||||
{
|
||||
Log.i(Email.LOG_TAG, "BootReceiver Got request to release wakeLock " + wakeLockId);
|
||||
|
|
|
@ -12,7 +12,7 @@ import android.util.Log;
|
|||
|
||||
public abstract class CoreService extends Service
|
||||
{
|
||||
|
||||
|
||||
protected static void addWakeLockId(Intent i, Integer wakeLockId)
|
||||
{
|
||||
if (wakeLockId != null)
|
||||
|
@ -20,23 +20,24 @@ public abstract class CoreService extends Service
|
|||
i.putExtra(BootReceiver.WAKE_LOCK_ID, wakeLockId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onStart(Intent intent, int startId) {
|
||||
|
||||
public void onStart(Intent intent, int startId)
|
||||
{
|
||||
|
||||
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||
WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Email");
|
||||
wakeLock.setReferenceCounted(false);
|
||||
wakeLock.acquire(Email.MAIL_SERVICE_WAKE_LOCK_TIMEOUT);
|
||||
|
||||
|
||||
Log.i(Email.LOG_TAG, "CoreService: " + this.getClass().getName() + ".onStart(" + intent + ", " + startId);
|
||||
|
||||
|
||||
int wakeLockId = intent.getIntExtra(BootReceiver.WAKE_LOCK_ID, -1);
|
||||
if (wakeLockId != -1)
|
||||
{
|
||||
BootReceiver.releaseWakeLock(this, wakeLockId);
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
super.onStart(intent, startId);
|
||||
|
@ -49,23 +50,24 @@ public abstract class CoreService extends Service
|
|||
wakeLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public abstract void startService(Intent intent, int startId);
|
||||
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent arg0)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
Log.i(Email.LOG_TAG, "CoreService: " + this.getClass().getName() + ".onDestroy()");
|
||||
public void onDestroy()
|
||||
{
|
||||
Log.i(Email.LOG_TAG, "CoreService: " + this.getClass().getName() + ".onDestroy()");
|
||||
super.onDestroy();
|
||||
// MessagingController.getInstance(getApplication()).removeListener(mListener);
|
||||
// MessagingController.getInstance(getApplication()).removeListener(mListener);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,8 @@ import com.android.email.mail.Pusher;
|
|||
|
||||
/**
|
||||
*/
|
||||
public class MailService extends CoreService {
|
||||
public class MailService extends CoreService
|
||||
{
|
||||
private static final String ACTION_CHECK_MAIL = "com.android.email.intent.action.MAIL_SERVICE_WAKEUP";
|
||||
private static final String ACTION_RESCHEDULE = "com.android.email.intent.action.MAIL_SERVICE_RESCHEDULE";
|
||||
private static final String ACTION_RESCHEDULE_CHECK = "com.android.email.intent.action.MAIL_SERVICE_RESCHEDULE_CHECK";
|
||||
|
@ -42,37 +43,41 @@ public class MailService extends CoreService {
|
|||
private static final String CONNECTIVITY_CHANGE = "com.android.email.intent.action.MAIL_SERVICE_CONNECTIVITY_CHANGE";
|
||||
private static final String BACKGROUND_DATA_CHANGED = "com.android.email.intent.action.MAIL_SERVICE_BACKGROUND_DATA_CHANGED";
|
||||
private static final String CANCEL_CONNECTIVITY_NOTICE = "com.android.email.intent.action.MAIL_SERVICE_CANCEL_CONNECTIVITY_NOTICE";
|
||||
|
||||
|
||||
private static final String HAS_CONNECTIVITY = "com.android.email.intent.action.MAIL_SERVICE_HAS_CONNECTIVITY";
|
||||
|
||||
|
||||
private final ExecutorService threadPool = Executors.newFixedThreadPool(1); // Must be single threaded
|
||||
|
||||
|
||||
public static void actionReschedule(Context context, Integer wakeLockId) {
|
||||
|
||||
|
||||
public static void actionReschedule(Context context, Integer wakeLockId)
|
||||
{
|
||||
Intent i = new Intent();
|
||||
i.setClass(context, MailService.class);
|
||||
i.setAction(MailService.ACTION_RESCHEDULE);
|
||||
addWakeLockId(i, wakeLockId);
|
||||
context.startService(i);
|
||||
}
|
||||
|
||||
public static void rescheduleCheck(Context context, Integer wakeLockId) {
|
||||
|
||||
public static void rescheduleCheck(Context context, Integer wakeLockId)
|
||||
{
|
||||
Intent i = new Intent();
|
||||
i.setClass(context, MailService.class);
|
||||
i.setAction(MailService.ACTION_RESCHEDULE_CHECK);
|
||||
addWakeLockId(i, wakeLockId);
|
||||
context.startService(i);
|
||||
}
|
||||
|
||||
public static void actionCancel(Context context, Integer wakeLockId) {
|
||||
|
||||
public static void actionCancel(Context context, Integer wakeLockId)
|
||||
{
|
||||
Intent i = new Intent();
|
||||
i.setClass(context, MailService.class);
|
||||
i.setAction(MailService.ACTION_CANCEL);
|
||||
addWakeLockId(i, wakeLockId);
|
||||
context.startService(i);
|
||||
}
|
||||
|
||||
public static void connectivityChange(Context context, boolean hasConnectivity, Integer wakeLockId) {
|
||||
|
||||
public static void connectivityChange(Context context, boolean hasConnectivity, Integer wakeLockId)
|
||||
{
|
||||
Intent i = new Intent();
|
||||
i.setClass(context, MailService.class);
|
||||
i.setAction(MailService.CONNECTIVITY_CHANGE);
|
||||
|
@ -80,8 +85,9 @@ public class MailService extends CoreService {
|
|||
addWakeLockId(i, wakeLockId);
|
||||
context.startService(i);
|
||||
}
|
||||
|
||||
public static void backgroundDataChanged(Context context, Integer wakeLockId) {
|
||||
|
||||
public static void backgroundDataChanged(Context context, Integer wakeLockId)
|
||||
{
|
||||
Intent i = new Intent();
|
||||
i.setClass(context, MailService.class);
|
||||
i.setAction(MailService.BACKGROUND_DATA_CHANGED);
|
||||
|
@ -90,13 +96,15 @@ public class MailService extends CoreService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Log.v(Email.LOG_TAG, "***** MailService *****: onCreate");
|
||||
public void onCreate()
|
||||
{
|
||||
super.onCreate();
|
||||
Log.v(Email.LOG_TAG, "***** MailService *****: onCreate");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startService(Intent intent, int startId) {
|
||||
public void startService(Intent intent, int startId)
|
||||
{
|
||||
Integer startIdObj = startId;
|
||||
long startTime = System.currentTimeMillis();
|
||||
try
|
||||
|
@ -104,7 +112,7 @@ public class MailService extends CoreService {
|
|||
ConnectivityManager connectivityManager = (ConnectivityManager)getApplication().getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
boolean doBackground = true;
|
||||
boolean hasConnectivity = false;
|
||||
|
||||
|
||||
if (connectivityManager != null)
|
||||
{
|
||||
NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
|
||||
|
@ -114,54 +122,61 @@ public class MailService extends CoreService {
|
|||
hasConnectivity = state == State.CONNECTED;
|
||||
}
|
||||
boolean backgroundData = connectivityManager.getBackgroundDataSetting();
|
||||
|
||||
|
||||
Email.BACKGROUND_OPS bOps = Email.getBackgroundOps();
|
||||
doBackground = (backgroundData == true && bOps != Email.BACKGROUND_OPS.NEVER)
|
||||
| (backgroundData == false && bOps == Email.BACKGROUND_OPS.ALWAYS);
|
||||
|
||||
doBackground = (backgroundData == true && bOps != Email.BACKGROUND_OPS.NEVER)
|
||||
| (backgroundData == false && bOps == Email.BACKGROUND_OPS.ALWAYS);
|
||||
|
||||
}
|
||||
|
||||
setForeground(true); // if it gets killed once, it'll never restart
|
||||
Log.i(Email.LOG_TAG, "MailService.onStart(" + intent + ", " + startId
|
||||
+ "), hasConnectivity = " + hasConnectivity + ", doBackground = " + doBackground);
|
||||
|
||||
// MessagingController.getInstance(getApplication()).addListener(mListener);
|
||||
if (ACTION_CHECK_MAIL.equals(intent.getAction())) {
|
||||
Log.i(Email.LOG_TAG, "***** MailService *****: checking mail");
|
||||
|
||||
|
||||
setForeground(true); // if it gets killed once, it'll never restart
|
||||
Log.i(Email.LOG_TAG, "MailService.onStart(" + intent + ", " + startId
|
||||
+ "), hasConnectivity = " + hasConnectivity + ", doBackground = " + doBackground);
|
||||
|
||||
// MessagingController.getInstance(getApplication()).addListener(mListener);
|
||||
if (ACTION_CHECK_MAIL.equals(intent.getAction()))
|
||||
{
|
||||
Log.i(Email.LOG_TAG, "***** MailService *****: checking mail");
|
||||
|
||||
if (hasConnectivity && doBackground)
|
||||
{
|
||||
PollService.startService(this);
|
||||
}
|
||||
|
||||
|
||||
reschedule(startIdObj);
|
||||
startIdObj = null;
|
||||
}
|
||||
else if (ACTION_CANCEL.equals(intent.getAction())) {
|
||||
if (Config.LOGV) {
|
||||
else if (ACTION_CANCEL.equals(intent.getAction()))
|
||||
{
|
||||
if (Config.LOGV)
|
||||
{
|
||||
Log.v(Email.LOG_TAG, "***** MailService *****: cancel");
|
||||
}
|
||||
MessagingController.getInstance(getApplication()).log("***** MailService *****: cancel");
|
||||
|
||||
|
||||
cancel();
|
||||
}
|
||||
else if (ACTION_RESCHEDULE.equals(intent.getAction())) {
|
||||
if (Config.LOGV) {
|
||||
else if (ACTION_RESCHEDULE.equals(intent.getAction()))
|
||||
{
|
||||
if (Config.LOGV)
|
||||
{
|
||||
Log.v(Email.LOG_TAG, "***** MailService *****: reschedule");
|
||||
}
|
||||
rescheduleAll(hasConnectivity, doBackground, startIdObj);
|
||||
startIdObj = null;
|
||||
MessagingController.getInstance(getApplication()).log("***** MailService *****: reschedule");
|
||||
|
||||
|
||||
}
|
||||
else if (ACTION_RESCHEDULE_CHECK.equals(intent.getAction())) {
|
||||
if (Config.LOGV) {
|
||||
else if (ACTION_RESCHEDULE_CHECK.equals(intent.getAction()))
|
||||
{
|
||||
if (Config.LOGV)
|
||||
{
|
||||
Log.v(Email.LOG_TAG, "***** MailService *****: reschedule check");
|
||||
}
|
||||
reschedule(startIdObj);
|
||||
startIdObj = null;
|
||||
MessagingController.getInstance(getApplication()).log("***** MailService *****: reschedule");
|
||||
|
||||
|
||||
}
|
||||
else if (ACTION_REFRESH_PUSHERS.equals(intent.getAction()))
|
||||
{
|
||||
|
@ -173,7 +188,7 @@ public class MailService extends CoreService {
|
|||
}
|
||||
}
|
||||
else if (CONNECTIVITY_CHANGE.equals(intent.getAction()) ||
|
||||
BACKGROUND_DATA_CHANGED.equals(intent.getAction()))
|
||||
BACKGROUND_DATA_CHANGED.equals(intent.getAction()))
|
||||
{
|
||||
notifyConnectionStatus(hasConnectivity);
|
||||
rescheduleAll(hasConnectivity, doBackground, startIdObj);
|
||||
|
@ -195,13 +210,13 @@ public class MailService extends CoreService {
|
|||
long endTime = System.currentTimeMillis();
|
||||
Log.i(Email.LOG_TAG, "MailService.onStart took " + (endTime - startTime) + "ms");
|
||||
}
|
||||
|
||||
|
||||
private void rescheduleAll(final boolean hasConnectivity, final boolean doBackground, final Integer startId)
|
||||
{
|
||||
if (hasConnectivity && doBackground)
|
||||
{
|
||||
reschedule(null);
|
||||
reschedulePushers(startId);
|
||||
reschedule(null);
|
||||
reschedulePushers(startId);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -218,21 +233,21 @@ public class MailService extends CoreService {
|
|||
{
|
||||
String notice = getApplication().getString(R.string.no_connection_alert);
|
||||
String header = getApplication().getString(R.string.alert_header);
|
||||
|
||||
|
||||
|
||||
|
||||
Notification notif = new Notification(R.drawable.stat_notify_email_generic,
|
||||
header, System.currentTimeMillis());
|
||||
|
||||
header, System.currentTimeMillis());
|
||||
|
||||
Intent i = new Intent();
|
||||
i.setClassName(getApplication().getPackageName(), "com.android.email.service.MailService");
|
||||
i.setAction(MailService.CANCEL_CONNECTIVITY_NOTICE);
|
||||
|
||||
|
||||
PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
|
||||
|
||||
|
||||
notif.setLatestEventInfo(getApplication(), header, notice, pi);
|
||||
notif.flags = Notification.FLAG_ONGOING_EVENT;
|
||||
|
||||
notifMgr.notify(Email.CONNECTIVITY_ID, notif);
|
||||
|
||||
notifMgr.notify(Email.CONNECTIVITY_ID, notif);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -241,100 +256,110 @@ public class MailService extends CoreService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
Log.v(Email.LOG_TAG, "***** MailService *****: onDestroy()");
|
||||
public void onDestroy()
|
||||
{
|
||||
Log.v(Email.LOG_TAG, "***** MailService *****: onDestroy()");
|
||||
super.onDestroy();
|
||||
// MessagingController.getInstance(getApplication()).removeListener(mListener);
|
||||
// MessagingController.getInstance(getApplication()).removeListener(mListener);
|
||||
}
|
||||
|
||||
private void cancel() {
|
||||
private void cancel()
|
||||
{
|
||||
Intent i = new Intent();
|
||||
i.setClassName(getApplication().getPackageName(), "com.android.email.service.MailService");
|
||||
i.setAction(ACTION_CHECK_MAIL);
|
||||
BootReceiver.cancelIntent(this, i);
|
||||
}
|
||||
|
||||
private void reschedule(Integer startId) {
|
||||
execute(getApplication(), new Runnable()
|
||||
private void reschedule(Integer startId)
|
||||
{
|
||||
execute(getApplication(), new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
int shortestInterval = -1;
|
||||
|
||||
for (Account account : Preferences.getPreferences(MailService.this).getAccounts()) {
|
||||
|
||||
for (Account account : Preferences.getPreferences(MailService.this).getAccounts())
|
||||
{
|
||||
if (account.getAutomaticCheckIntervalMinutes() != -1
|
||||
&& (account.getAutomaticCheckIntervalMinutes() < shortestInterval || shortestInterval == -1)) {
|
||||
&& (account.getAutomaticCheckIntervalMinutes() < shortestInterval || shortestInterval == -1))
|
||||
{
|
||||
shortestInterval = account.getAutomaticCheckIntervalMinutes();
|
||||
}
|
||||
}
|
||||
|
||||
if (shortestInterval == -1) {
|
||||
Log.v(Email.LOG_TAG, "No next check scheduled for package " + getApplication().getPackageName());
|
||||
cancel();
|
||||
|
||||
if (shortestInterval == -1)
|
||||
{
|
||||
Log.v(Email.LOG_TAG, "No next check scheduled for package " + getApplication().getPackageName());
|
||||
cancel();
|
||||
}
|
||||
else
|
||||
{
|
||||
long delay = (shortestInterval * (60 * 1000));
|
||||
|
||||
long nextTime = System.currentTimeMillis() + delay;
|
||||
try
|
||||
{
|
||||
String checkString = "Next check for package " + getApplication().getPackageName() + " scheduled for " + new Date(nextTime);
|
||||
Log.i(Email.LOG_TAG, checkString);
|
||||
MessagingController.getInstance(getApplication()).log(checkString);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// I once got a NullPointerException deep in new Date();
|
||||
Log.e(Email.LOG_TAG, "Exception while logging", e);
|
||||
}
|
||||
|
||||
Intent i = new Intent();
|
||||
i.setClassName(getApplication().getPackageName(), "com.android.email.service.MailService");
|
||||
i.setAction(ACTION_CHECK_MAIL);
|
||||
long delay = (shortestInterval * (60 * 1000));
|
||||
|
||||
long nextTime = System.currentTimeMillis() + delay;
|
||||
try
|
||||
{
|
||||
String checkString = "Next check for package " + getApplication().getPackageName() + " scheduled for " + new Date(nextTime);
|
||||
Log.i(Email.LOG_TAG, checkString);
|
||||
MessagingController.getInstance(getApplication()).log(checkString);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// I once got a NullPointerException deep in new Date();
|
||||
Log.e(Email.LOG_TAG, "Exception while logging", e);
|
||||
}
|
||||
|
||||
Intent i = new Intent();
|
||||
i.setClassName(getApplication().getPackageName(), "com.android.email.service.MailService");
|
||||
i.setAction(ACTION_CHECK_MAIL);
|
||||
BootReceiver.scheduleIntent(MailService.this, nextTime, i);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}, Email.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
|
||||
}
|
||||
, Email.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
|
||||
}
|
||||
|
||||
|
||||
private void stopPushers(final Integer startId)
|
||||
{
|
||||
execute(getApplication(), new Runnable()
|
||||
execute(getApplication(), new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
MessagingController.getInstance(getApplication()).stopAllPushing();
|
||||
PushService.stopService(MailService.this);
|
||||
}
|
||||
}, Email.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId );
|
||||
}
|
||||
, Email.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
|
||||
}
|
||||
|
||||
|
||||
private void reschedulePushers(final Integer startId)
|
||||
{
|
||||
execute(getApplication(), new Runnable()
|
||||
execute(getApplication(), new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
|
||||
|
||||
Log.i(Email.LOG_TAG, "Rescheduling pushers");
|
||||
stopPushers(null);
|
||||
setupPushers(null);
|
||||
schedulePushers(startId);
|
||||
|
||||
|
||||
}
|
||||
}, Email.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, null );
|
||||
}
|
||||
, Email.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, null);
|
||||
}
|
||||
|
||||
|
||||
private void setupPushers(final Integer startId)
|
||||
{
|
||||
execute(getApplication(), new Runnable()
|
||||
execute(getApplication(), new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
boolean pushing = false;
|
||||
for (Account account : Preferences.getPreferences(MailService.this).getAccounts()) {
|
||||
for (Account account : Preferences.getPreferences(MailService.this).getAccounts())
|
||||
{
|
||||
Log.i(Email.LOG_TAG, "Setting up pushers for account " + account.getDescription());
|
||||
Pusher pusher = MessagingController.getInstance(getApplication()).setupPushing(account);
|
||||
if (pusher != null)
|
||||
|
@ -343,18 +368,19 @@ public class MailService extends CoreService {
|
|||
Log.i(Email.LOG_TAG, "Starting configured pusher for account " + account.getDescription());
|
||||
pusher.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pushing)
|
||||
{
|
||||
PushService.startService(MailService.this);
|
||||
}
|
||||
}
|
||||
}, Email.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
|
||||
}
|
||||
, Email.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
|
||||
}
|
||||
|
||||
|
||||
private void refreshPushers(final Integer startId)
|
||||
{
|
||||
execute(getApplication(), new Runnable()
|
||||
execute(getApplication(), new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
|
@ -372,17 +398,18 @@ public class MailService extends CoreService {
|
|||
Log.e(Email.LOG_TAG, "Exception while refreshing pushers", e);
|
||||
}
|
||||
}
|
||||
}, Email.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId );
|
||||
}
|
||||
, Email.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
|
||||
}
|
||||
|
||||
|
||||
private void schedulePushers(final Integer startId)
|
||||
{
|
||||
execute(getApplication(), new Runnable()
|
||||
execute(getApplication(), new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
int minInterval = -1;
|
||||
|
||||
|
||||
Collection<Pusher> pushers = MessagingController.getInstance(getApplication()).getPushers();
|
||||
for (Pusher pusher : pushers)
|
||||
{
|
||||
|
@ -408,10 +435,12 @@ public class MailService extends CoreService {
|
|||
i.setClassName(getApplication().getPackageName(), "com.android.email.service.MailService");
|
||||
i.setAction(ACTION_REFRESH_PUSHERS);
|
||||
BootReceiver.scheduleIntent(MailService.this, nextTime, i);
|
||||
}}
|
||||
}, Email.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
|
||||
}
|
||||
}
|
||||
}
|
||||
, Email.MAIL_SERVICE_WAKE_LOCK_TIMEOUT, startId);
|
||||
}
|
||||
|
||||
|
||||
public void execute(Context context, final Runnable runner, int wakeLockTime, final Integer startId)
|
||||
{
|
||||
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
|
@ -439,15 +468,16 @@ public class MailService extends CoreService {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
threadPool.execute(myRunner);
|
||||
}
|
||||
|
||||
public IBinder onBind(Intent intent) {
|
||||
public IBinder onBind(Intent intent)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -22,43 +22,45 @@ public class PollService extends CoreService
|
|||
private static String STOP_SERVICE = "com.android.email.service.PollService.stopService";
|
||||
|
||||
private Listener mListener = new Listener();
|
||||
|
||||
public static void startService(Context context) {
|
||||
|
||||
public static void startService(Context context)
|
||||
{
|
||||
Intent i = new Intent();
|
||||
i.setClass(context, PollService.class);
|
||||
i.setAction(PollService.START_SERVICE);
|
||||
context.startService(i);
|
||||
}
|
||||
|
||||
public static void stopService(Context context) {
|
||||
|
||||
public static void stopService(Context context)
|
||||
{
|
||||
Intent i = new Intent();
|
||||
i.setClass(context, PollService.class);
|
||||
i.setAction(PollService.STOP_SERVICE);
|
||||
context.startService(i);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void startService(Intent intent, int startId)
|
||||
{
|
||||
if (START_SERVICE.equals(intent.getAction()))
|
||||
if (START_SERVICE.equals(intent.getAction()))
|
||||
{
|
||||
Log.i(Email.LOG_TAG, "PollService started with startId = " + startId);
|
||||
|
||||
|
||||
MessagingController controller = MessagingController.getInstance(getApplication());
|
||||
Listener listener = (Listener)controller.getCheckMailListener();
|
||||
if (listener == null)
|
||||
{
|
||||
MessagingController.getInstance(getApplication()).log("***** PollService *****: starting new check");
|
||||
mListener.setStartId(startId);
|
||||
mListener.wakeLockAcquire();
|
||||
controller.setCheckMailListener(mListener);
|
||||
controller.checkMail(this, null, false, false, mListener);
|
||||
MessagingController.getInstance(getApplication()).log("***** PollService *****: starting new check");
|
||||
mListener.setStartId(startId);
|
||||
mListener.wakeLockAcquire();
|
||||
controller.setCheckMailListener(mListener);
|
||||
controller.checkMail(this, null, false, false, mListener);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessagingController.getInstance(getApplication()).log("***** PollService *****: renewing WakeLock");
|
||||
listener.setStartId(startId);
|
||||
listener.wakeLockAcquire();
|
||||
MessagingController.getInstance(getApplication()).log("***** PollService *****: renewing WakeLock");
|
||||
listener.setStartId(startId);
|
||||
listener.wakeLockAcquire();
|
||||
}
|
||||
}
|
||||
else if (STOP_SERVICE.equals(intent.getAction()))
|
||||
|
@ -66,16 +68,17 @@ public class PollService extends CoreService
|
|||
Log.i(Email.LOG_TAG, "PollService stopping");
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent arg0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
class Listener extends MessagingListener {
|
||||
|
||||
class Listener extends MessagingListener
|
||||
{
|
||||
HashMap<String, Integer> accountsChecked = new HashMap<String, Integer>();
|
||||
private WakeLock wakeLock = null;
|
||||
private int startId = -1;
|
||||
|
@ -84,7 +87,7 @@ public class PollService extends CoreService
|
|||
// don't want to take the chance of running wild
|
||||
public synchronized void wakeLockAcquire()
|
||||
{
|
||||
WakeLock oldWakeLock = wakeLock;
|
||||
WakeLock oldWakeLock = wakeLock;
|
||||
|
||||
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Email");
|
||||
|
@ -93,7 +96,7 @@ public class PollService extends CoreService
|
|||
|
||||
if (oldWakeLock != null)
|
||||
{
|
||||
oldWakeLock.release();
|
||||
oldWakeLock.release();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -106,28 +109,32 @@ public class PollService extends CoreService
|
|||
}
|
||||
}
|
||||
@Override
|
||||
public void checkMailStarted(Context context, Account account) {
|
||||
public void checkMailStarted(Context context, Account account)
|
||||
{
|
||||
accountsChecked.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMailFailed(Context context, Account account, String reason) {
|
||||
public void checkMailFailed(Context context, Account account, String reason)
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void synchronizeMailboxFinished(
|
||||
Account account,
|
||||
String folder,
|
||||
int totalMessagesInMailbox,
|
||||
int numNewMessages) {
|
||||
if (account.isNotifyNewMail()) {
|
||||
Integer existingNewMessages = accountsChecked.get(account.getUuid());
|
||||
if (existingNewMessages == null)
|
||||
{
|
||||
existingNewMessages = 0;
|
||||
}
|
||||
accountsChecked.put(account.getUuid(), existingNewMessages + numNewMessages);
|
||||
Account account,
|
||||
String folder,
|
||||
int totalMessagesInMailbox,
|
||||
int numNewMessages)
|
||||
{
|
||||
if (account.isNotifyNewMail())
|
||||
{
|
||||
Integer existingNewMessages = accountsChecked.get(account.getUuid());
|
||||
if (existingNewMessages == null)
|
||||
{
|
||||
existingNewMessages = 0;
|
||||
}
|
||||
accountsChecked.put(account.getUuid(), existingNewMessages + numNewMessages);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,40 +145,42 @@ public class PollService extends CoreService
|
|||
return;
|
||||
}
|
||||
|
||||
for (Account thisAccount : Preferences.getPreferences(context).getAccounts()) {
|
||||
for (Account thisAccount : Preferences.getPreferences(context).getAccounts())
|
||||
{
|
||||
Integer newMailCount = accountsChecked.get(thisAccount.getUuid());
|
||||
if (newMailCount != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
int unreadMessageCount = thisAccount.getUnreadMessageCount(context, getApplication());
|
||||
MessagingController.getInstance(getApplication()).notifyAccount(context, thisAccount,
|
||||
MessagingController.getInstance(getApplication()).notifyAccount(context, thisAccount,
|
||||
newMailCount, unreadMessageCount);
|
||||
|
||||
|
||||
}
|
||||
catch (MessagingException me)
|
||||
{
|
||||
Log.e(Email.LOG_TAG, "***** PollService *****: couldn't get unread count for account " +
|
||||
thisAccount.getDescription(), me);
|
||||
thisAccount.getDescription(), me);
|
||||
}
|
||||
}
|
||||
}//for accounts
|
||||
}//checkMailDone
|
||||
|
||||
|
||||
|
||||
|
||||
private void release()
|
||||
{
|
||||
MessagingController controller = MessagingController.getInstance(getApplication());
|
||||
controller.setCheckMailListener(null);
|
||||
MailService.rescheduleCheck(PollService.this, null);
|
||||
wakeLockRelease();
|
||||
Log.i(Email.LOG_TAG, "PollService stopping with startId = " + startId);
|
||||
|
||||
stopSelf(startId);
|
||||
MessagingController controller = MessagingController.getInstance(getApplication());
|
||||
controller.setCheckMailListener(null);
|
||||
MailService.rescheduleCheck(PollService.this, null);
|
||||
wakeLockRelease();
|
||||
Log.i(Email.LOG_TAG, "PollService stopping with startId = " + startId);
|
||||
|
||||
stopSelf(startId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMailFinished(Context context, Account account) {
|
||||
public void checkMailFinished(Context context, Account account)
|
||||
{
|
||||
|
||||
Log.v(Email.LOG_TAG, "***** PollService *****: checkMailFinished");
|
||||
try
|
||||
|
@ -180,7 +189,7 @@ public class PollService extends CoreService
|
|||
}
|
||||
finally
|
||||
{
|
||||
release();
|
||||
release();
|
||||
}
|
||||
}
|
||||
public int getStartId()
|
||||
|
@ -192,5 +201,5 @@ public class PollService extends CoreService
|
|||
this.startId = startId;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -11,21 +11,23 @@ public class PushService extends CoreService
|
|||
{
|
||||
private static String START_SERVICE = "com.android.email.service.PushService.startService";
|
||||
private static String STOP_SERVICE = "com.android.email.service.PushService.stopService";
|
||||
|
||||
public static void startService(Context context) {
|
||||
|
||||
public static void startService(Context context)
|
||||
{
|
||||
Intent i = new Intent();
|
||||
i.setClass(context, PushService.class);
|
||||
i.setAction(PushService.START_SERVICE);
|
||||
context.startService(i);
|
||||
}
|
||||
|
||||
public static void stopService(Context context) {
|
||||
|
||||
public static void stopService(Context context)
|
||||
{
|
||||
Intent i = new Intent();
|
||||
i.setClass(context, PushService.class);
|
||||
i.setAction(PushService.STOP_SERVICE);
|
||||
context.startService(i);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void startService(Intent intent, int startId)
|
||||
{
|
||||
|
@ -38,9 +40,9 @@ public class PushService extends CoreService
|
|||
Log.i(Email.LOG_TAG, "PushService stopping with startId = " + startId);
|
||||
stopSelf(startId);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent arg0)
|
||||
{
|
||||
|
|
|
@ -14,15 +14,15 @@ import com.android.email.Email;
|
|||
|
||||
public class SleepService extends CoreService
|
||||
{
|
||||
|
||||
|
||||
private static String ALARM_FIRED = "com.android.email.service.SleepService.ALARM_FIRED";
|
||||
private static String LATCH_ID = "com.android.email.service.SleepService.LATCH_ID_EXTRA";
|
||||
|
||||
|
||||
|
||||
|
||||
private static ConcurrentHashMap<Integer, SleepDatum> sleepData = new ConcurrentHashMap<Integer, SleepDatum>();
|
||||
|
||||
|
||||
private static AtomicInteger latchId = new AtomicInteger();
|
||||
|
||||
|
||||
public static void sleep(Context context, long sleepTime, WakeLock wakeLock, long wakeLockTimeout)
|
||||
{
|
||||
Integer id = latchId.getAndIncrement();
|
||||
|
@ -34,7 +34,7 @@ public class SleepService extends CoreService
|
|||
CountDownLatch latch = new CountDownLatch(1);
|
||||
sleepDatum.latch = latch;
|
||||
sleepData.put(id, sleepDatum);
|
||||
|
||||
|
||||
Intent i = new Intent();
|
||||
i.setClassName(context.getPackageName(), "com.android.email.service.SleepService");
|
||||
i.putExtra(LATCH_ID, id);
|
||||
|
@ -57,7 +57,7 @@ public class SleepService extends CoreService
|
|||
{
|
||||
Log.d(Email.LOG_TAG, "SleepService latch timed out for id = " + id + ", thread " + Thread.currentThread().getName());
|
||||
}
|
||||
// don't call endSleep here or remove the sleepDatum here, instead of the following block.
|
||||
// don't call endSleep here or remove the sleepDatum here, instead of the following block.
|
||||
// We might not get the wakeLock before
|
||||
// falling asleep again, so we have to get the wakeLock *first* The alarmed version will
|
||||
// already be running in a WakeLock due to the nature of AlarmManager
|
||||
|
@ -68,7 +68,7 @@ public class SleepService extends CoreService
|
|||
// OK, we have the wakeLock, now we can remove the sleepDatum
|
||||
sleepData.remove(id);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ie)
|
||||
|
@ -86,7 +86,7 @@ public class SleepService extends CoreService
|
|||
Log.w(Email.LOG_TAG, "SleepService sleep time too short: requested was " + sleepTime + ", actual was " + actualSleep);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void endSleep(Integer id)
|
||||
{
|
||||
if (id != -1)
|
||||
|
@ -118,13 +118,13 @@ public class SleepService extends CoreService
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void reacquireWakeLock(SleepDatum sleepDatum)
|
||||
{
|
||||
WakeLock wakeLock = sleepDatum.wakeLock;
|
||||
if (wakeLock != null)
|
||||
{
|
||||
synchronized(wakeLock)
|
||||
synchronized (wakeLock)
|
||||
{
|
||||
long timeout = sleepDatum.timeout;
|
||||
if (Email.DEBUG)
|
||||
|
@ -139,13 +139,14 @@ public class SleepService extends CoreService
|
|||
@Override
|
||||
public void startService(Intent intent, int startId)
|
||||
{
|
||||
if (intent.getAction().startsWith(ALARM_FIRED)) {
|
||||
if (intent.getAction().startsWith(ALARM_FIRED))
|
||||
{
|
||||
Integer id = intent.getIntExtra(LATCH_ID, -1);
|
||||
endSleep(id);
|
||||
}
|
||||
stopSelf(startId);
|
||||
}
|
||||
|
||||
|
||||
private static class SleepDatum
|
||||
{
|
||||
CountDownLatch latch;
|
||||
|
|
Loading…
Reference in a new issue