mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-17 06:55:03 -05:00
Merge commit '4.121' into issue-162-new
Conflicts: src/com/fsck/k9/mail/store/LocalStore.java
This commit is contained in:
commit
f57ee1181f
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest
|
<manifest
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:versionCode="15019"
|
android:versionCode="15020"
|
||||||
android:versionName="4.120" package="com.fsck.k9"
|
android:versionName="4.121" package="com.fsck.k9"
|
||||||
>
|
>
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="7"
|
android:minSdkVersion="7"
|
||||||
|
@ -502,6 +502,7 @@
|
|||||||
<item>dark</item>
|
<item>dark</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Note: If you change this make sure the code in Prefs.java is still working -->
|
||||||
<string-array name="background_ops_entries">
|
<string-array name="background_ops_entries">
|
||||||
<item>@string/background_ops_enabled</item>
|
<item>@string/background_ops_enabled</item>
|
||||||
<item>@string/background_ops_auto_sync</item>
|
<item>@string/background_ops_auto_sync</item>
|
||||||
|
@ -850,6 +850,7 @@ http://k9mail.googlecode.com/
|
|||||||
<string name="background_ops_always">Always</string>
|
<string name="background_ops_always">Always</string>
|
||||||
<string name="background_ops_enabled">When \'Background data\' is checked</string>
|
<string name="background_ops_enabled">When \'Background data\' is checked</string>
|
||||||
<string name="background_ops_auto_sync">When \'Background data\' & \'Auto-sync\' are checked</string>
|
<string name="background_ops_auto_sync">When \'Background data\' & \'Auto-sync\' are checked</string>
|
||||||
|
<string name="background_ops_auto_sync_only">When \'Auto-sync\' is checked</string>
|
||||||
|
|
||||||
<string name="no_message_seletected_toast">No message selected</string>
|
<string name="no_message_seletected_toast">No message selected</string>
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@ import com.fsck.k9.mail.store.StorageManager;
|
|||||||
import com.fsck.k9.mail.store.StorageManager.StorageProvider;
|
import com.fsck.k9.mail.store.StorageManager.StorageProvider;
|
||||||
import com.fsck.k9.view.ColorChip;
|
import com.fsck.k9.view.ColorChip;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
@ -10,7 +10,6 @@ import java.util.Map;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.util.Config;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import com.fsck.k9.preferences.Editor;
|
import com.fsck.k9.preferences.Editor;
|
||||||
import com.fsck.k9.preferences.Storage;
|
import com.fsck.k9.preferences.Storage;
|
||||||
@ -155,14 +154,6 @@ public class Preferences {
|
|||||||
getPreferences().edit().putString("defaultAccountUuid", account.getUuid()).commit();
|
getPreferences().edit().putString("defaultAccountUuid", account.getUuid()).commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dump() {
|
|
||||||
if (Config.LOGV) {
|
|
||||||
for (String key : getPreferences().getAll().keySet()) {
|
|
||||||
Log.v(K9.LOG_TAG, key + " = " + getPreferences().getAll().get(key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SharedPreferences getPreferences() {
|
public SharedPreferences getPreferences() {
|
||||||
return mStorage;
|
return mStorage;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@ import java.util.List;
|
|||||||
|
|
||||||
public class ChooseIdentity extends K9ListActivity {
|
public class ChooseIdentity extends K9ListActivity {
|
||||||
Account mAccount;
|
Account mAccount;
|
||||||
String mUID;
|
|
||||||
ArrayAdapter<String> adapter;
|
ArrayAdapter<String> adapter;
|
||||||
|
|
||||||
public static final String EXTRA_ACCOUNT = "com.fsck.k9.ChooseIdentity_account";
|
public static final String EXTRA_ACCOUNT = "com.fsck.k9.ChooseIdentity_account";
|
||||||
|
@ -11,7 +11,6 @@ import android.os.Handler;
|
|||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.util.Config;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
@ -1099,10 +1098,6 @@ public class FolderList extends K9ListActivity {
|
|||||||
if (account.equals(mAccount)) {
|
if (account.equals(mAccount)) {
|
||||||
|
|
||||||
mHandler.progress(false);
|
mHandler.progress(false);
|
||||||
|
|
||||||
if (Config.LOGV) {
|
|
||||||
Log.v(K9.LOG_TAG, "listFoldersFailed " + message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
super.listFoldersFailed(account, message);
|
super.listFoldersFailed(account, message);
|
||||||
}
|
}
|
||||||
|
@ -3432,11 +3432,9 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
static class IdentityAdapter extends BaseAdapter {
|
static class IdentityAdapter extends BaseAdapter {
|
||||||
private LayoutInflater mLayoutInflater;
|
private LayoutInflater mLayoutInflater;
|
||||||
private List<Object> mItems;
|
private List<Object> mItems;
|
||||||
private FontSizes mFontSizes;
|
|
||||||
|
|
||||||
public IdentityAdapter(Context context, LayoutInflater layoutInflater) {
|
public IdentityAdapter(Context context, LayoutInflater layoutInflater) {
|
||||||
mLayoutInflater = layoutInflater;
|
mLayoutInflater = layoutInflater;
|
||||||
mFontSizes = K9.getFontSizes();
|
|
||||||
|
|
||||||
List<Object> items = new ArrayList<Object>();
|
List<Object> items = new ArrayList<Object>();
|
||||||
Preferences prefs = Preferences.getPreferences(context.getApplicationContext());
|
Preferences prefs = Preferences.getPreferences(context.getApplicationContext());
|
||||||
|
@ -54,12 +54,10 @@ import android.widget.Toast;
|
|||||||
import com.fsck.k9.Account;
|
import com.fsck.k9.Account;
|
||||||
import com.fsck.k9.Account.SortType;
|
import com.fsck.k9.Account.SortType;
|
||||||
import com.fsck.k9.AccountStats;
|
import com.fsck.k9.AccountStats;
|
||||||
import com.fsck.k9.BaseAccount;
|
|
||||||
import com.fsck.k9.FontSizes;
|
import com.fsck.k9.FontSizes;
|
||||||
import com.fsck.k9.K9;
|
import com.fsck.k9.K9;
|
||||||
import com.fsck.k9.Preferences;
|
import com.fsck.k9.Preferences;
|
||||||
import com.fsck.k9.R;
|
import com.fsck.k9.R;
|
||||||
import com.fsck.k9.SearchAccount;
|
|
||||||
import com.fsck.k9.SearchSpecification;
|
import com.fsck.k9.SearchSpecification;
|
||||||
import com.fsck.k9.activity.setup.AccountSettings;
|
import com.fsck.k9.activity.setup.AccountSettings;
|
||||||
import com.fsck.k9.activity.setup.FolderSettings;
|
import com.fsck.k9.activity.setup.FolderSettings;
|
||||||
@ -272,8 +270,6 @@ public class MessageList
|
|||||||
private Account mAccount;
|
private Account mAccount;
|
||||||
private int mUnreadMessageCount = 0;
|
private int mUnreadMessageCount = 0;
|
||||||
|
|
||||||
private GestureDetector gestureDetector;
|
|
||||||
private View.OnTouchListener gestureListener;
|
|
||||||
/**
|
/**
|
||||||
* Stores the name of the folder that we want to open as soon as possible
|
* Stores the name of the folder that we want to open as soon as possible
|
||||||
* after load.
|
* after load.
|
||||||
@ -364,13 +360,13 @@ public class MessageList
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
for (MessageInfoHolder message : messages) {
|
for (MessageInfoHolder message : messages) {
|
||||||
if (message != null) {
|
if (message != null && (mFolderName == null || (
|
||||||
if (mFolderName == null || (message.folder != null && message.folder.name.equals(mFolderName))) {
|
message.folder != null &&
|
||||||
if (message.selected && mSelectedCount > 0) {
|
message.folder.name.equals(mFolderName)))) {
|
||||||
mSelectedCount--;
|
if (message.selected && mSelectedCount > 0) {
|
||||||
}
|
mSelectedCount--;
|
||||||
mAdapter.messages.remove(message);
|
|
||||||
}
|
}
|
||||||
|
mAdapter.messages.remove(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resetUnreadCountOnThread();
|
resetUnreadCountOnThread();
|
||||||
|
@ -6,6 +6,7 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Vibrator;
|
import android.os.Vibrator;
|
||||||
import android.preference.*;
|
import android.preference.*;
|
||||||
@ -50,6 +51,7 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||||||
private static final String PREFERENCE_SCREEN_COMPOSING = "composing";
|
private static final String PREFERENCE_SCREEN_COMPOSING = "composing";
|
||||||
private static final String PREFERENCE_SCREEN_INCOMING = "incoming_prefs";
|
private static final String PREFERENCE_SCREEN_INCOMING = "incoming_prefs";
|
||||||
private static final String PREFERENCE_SCREEN_PUSH_ADVANCED = "push_advanced";
|
private static final String PREFERENCE_SCREEN_PUSH_ADVANCED = "push_advanced";
|
||||||
|
private static final String PREFERENCE_SCREEN_NOTIFICATIONS = "notifications";
|
||||||
|
|
||||||
private static final String PREFERENCE_DESCRIPTION = "account_description";
|
private static final String PREFERENCE_DESCRIPTION = "account_description";
|
||||||
private static final String PREFERENCE_MARK_MESSAGE_AS_READ_ON_VIEW = "mark_message_as_read_on_view";
|
private static final String PREFERENCE_MARK_MESSAGE_AS_READ_ON_VIEW = "mark_message_as_read_on_view";
|
||||||
@ -581,8 +583,23 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||||||
mNotificationOpensUnread = (CheckBoxPreference)findPreference(PREFERENCE_NOTIFICATION_OPENS_UNREAD);
|
mNotificationOpensUnread = (CheckBoxPreference)findPreference(PREFERENCE_NOTIFICATION_OPENS_UNREAD);
|
||||||
mNotificationOpensUnread.setChecked(mAccount.goToUnreadMessageSearch());
|
mNotificationOpensUnread.setChecked(mAccount.goToUnreadMessageSearch());
|
||||||
|
|
||||||
mNotificationUnreadCount = (CheckBoxPreference)findPreference(PREFERENCE_NOTIFICATION_UNREAD_COUNT);
|
CheckBoxPreference notificationUnreadCount =
|
||||||
mNotificationUnreadCount.setChecked(mAccount.isNotificationShowsUnreadCount());
|
(CheckBoxPreference) findPreference(PREFERENCE_NOTIFICATION_UNREAD_COUNT);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Honeycomb and newer don't show the notification number as overlay on the notification
|
||||||
|
* icon in the status bar, so we hide the setting.
|
||||||
|
*
|
||||||
|
* See http://code.google.com/p/android/issues/detail?id=21477
|
||||||
|
*/
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||||
|
PreferenceScreen notificationsPrefs =
|
||||||
|
(PreferenceScreen) findPreference(PREFERENCE_SCREEN_NOTIFICATIONS);
|
||||||
|
notificationsPrefs.removePreference(notificationUnreadCount);
|
||||||
|
} else {
|
||||||
|
notificationUnreadCount.setChecked(mAccount.isNotificationShowsUnreadCount());
|
||||||
|
mNotificationUnreadCount = notificationUnreadCount;
|
||||||
|
}
|
||||||
|
|
||||||
new PopulateFolderPrefsTask().execute();
|
new PopulateFolderPrefsTask().execute();
|
||||||
|
|
||||||
@ -699,7 +716,9 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||||||
mAccount.getNotificationSetting().setVibrateTimes(Integer.parseInt(mAccountVibrateTimes.getValue()));
|
mAccount.getNotificationSetting().setVibrateTimes(Integer.parseInt(mAccountVibrateTimes.getValue()));
|
||||||
mAccount.getNotificationSetting().setLed(mAccountLed.isChecked());
|
mAccount.getNotificationSetting().setLed(mAccountLed.isChecked());
|
||||||
mAccount.setGoToUnreadMessageSearch(mNotificationOpensUnread.isChecked());
|
mAccount.setGoToUnreadMessageSearch(mNotificationOpensUnread.isChecked());
|
||||||
mAccount.setNotificationShowsUnreadCount(mNotificationUnreadCount.isChecked());
|
if (mNotificationUnreadCount != null) {
|
||||||
|
mAccount.setNotificationShowsUnreadCount(mNotificationUnreadCount.isChecked());
|
||||||
|
}
|
||||||
mAccount.setFolderTargetMode(Account.FolderMode.valueOf(mTargetMode.getValue()));
|
mAccount.setFolderTargetMode(Account.FolderMode.valueOf(mTargetMode.getValue()));
|
||||||
Log.d("ASH", "Setting delete policy to " + mDeletePolicy.getValue());
|
Log.d("ASH", "Setting delete policy to " + mDeletePolicy.getValue());
|
||||||
mAccount.setDeletePolicy(Integer.parseInt(mDeletePolicy.getValue()));
|
mAccount.setDeletePolicy(Integer.parseInt(mDeletePolicy.getValue()));
|
||||||
|
@ -319,11 +319,11 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
|||||||
if (name.equalsIgnoreCase(storeURIHost) || name.equalsIgnoreCase(transportURIHost)) {
|
if (name.equalsIgnoreCase(storeURIHost) || name.equalsIgnoreCase(transportURIHost)) {
|
||||||
//TODO: localize this string
|
//TODO: localize this string
|
||||||
altNamesText.append("Subject(alt): ").append(name).append(",...\n");
|
altNamesText.append("Subject(alt): ").append(name).append(",...\n");
|
||||||
} else if (name.startsWith("*.")) {
|
} else if (name.startsWith("*.") && (
|
||||||
if (storeURIHost.endsWith(name.substring(2)) || transportURIHost.endsWith(name.substring(2))) {
|
storeURIHost.endsWith(name.substring(2)) ||
|
||||||
//TODO: localize this string
|
transportURIHost.endsWith(name.substring(2)))) {
|
||||||
altNamesText.append("Subject(alt): ").append(name).append(",...\n");
|
//TODO: localize this string
|
||||||
}
|
altNamesText.append("Subject(alt): ").append(name).append(",...\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chainInfo.append(altNamesText);
|
chainInfo.append(altNamesText);
|
||||||
|
@ -33,6 +33,7 @@ import com.fsck.k9.preferences.CheckBoxListPreference;
|
|||||||
import com.fsck.k9.preferences.TimePickerPreference;
|
import com.fsck.k9.preferences.TimePickerPreference;
|
||||||
|
|
||||||
import com.fsck.k9.service.MailService;
|
import com.fsck.k9.service.MailService;
|
||||||
|
import com.fsck.k9.view.MessageWebView;
|
||||||
|
|
||||||
|
|
||||||
public class Prefs extends K9PreferenceActivity {
|
public class Prefs extends K9PreferenceActivity {
|
||||||
@ -284,13 +285,13 @@ public class Prefs extends K9PreferenceActivity {
|
|||||||
mZoomControlsEnabled.setChecked(K9.zoomControlsEnabled());
|
mZoomControlsEnabled.setChecked(K9.zoomControlsEnabled());
|
||||||
|
|
||||||
mMobileOptimizedLayout = (CheckBoxPreference) findPreference(PREFERENCE_MESSAGEVIEW_MOBILE_LAYOUT);
|
mMobileOptimizedLayout = (CheckBoxPreference) findPreference(PREFERENCE_MESSAGEVIEW_MOBILE_LAYOUT);
|
||||||
if (Build.VERSION.SDK_INT <= 7) {
|
if (!MessageWebView.isSingleColumnLayoutSupported()) {
|
||||||
mMobileOptimizedLayout.setEnabled(false);
|
mMobileOptimizedLayout.setEnabled(false);
|
||||||
|
mMobileOptimizedLayout.setChecked(false);
|
||||||
|
} else {
|
||||||
|
mMobileOptimizedLayout.setChecked(K9.mobileOptimizedLayout());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mMobileOptimizedLayout.setChecked(K9.mobileOptimizedLayout());
|
|
||||||
|
|
||||||
mQuietTimeEnabled = (CheckBoxPreference) findPreference(PREFERENCE_QUIET_TIME_ENABLED);
|
mQuietTimeEnabled = (CheckBoxPreference) findPreference(PREFERENCE_QUIET_TIME_ENABLED);
|
||||||
mQuietTimeEnabled.setChecked(K9.getQuietTimeEnabled());
|
mQuietTimeEnabled.setChecked(K9.getQuietTimeEnabled());
|
||||||
|
|
||||||
@ -320,6 +321,33 @@ public class Prefs extends K9PreferenceActivity {
|
|||||||
|
|
||||||
|
|
||||||
mBackgroundOps = setupListPreference(PREFERENCE_BACKGROUND_OPS, K9.getBackgroundOps().toString());
|
mBackgroundOps = setupListPreference(PREFERENCE_BACKGROUND_OPS, K9.getBackgroundOps().toString());
|
||||||
|
// In ICS+ there is no 'background data' setting that apps can chose to ignore anymore. So
|
||||||
|
// we hide that option for "Background Sync".
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
|
||||||
|
CharSequence[] oldEntries = mBackgroundOps.getEntries();
|
||||||
|
CharSequence[] newEntries = new CharSequence[3];
|
||||||
|
// Use "When 'Auto-sync' is checked" instead of "When 'Background data' & 'Auto-sync'
|
||||||
|
// are checked" as description.
|
||||||
|
newEntries[0] = getString(R.string.background_ops_auto_sync_only);
|
||||||
|
newEntries[1] = oldEntries[2];
|
||||||
|
newEntries[2] = oldEntries[3];
|
||||||
|
|
||||||
|
CharSequence[] oldValues = mBackgroundOps.getEntryValues();
|
||||||
|
CharSequence[] newValues = new CharSequence[3];
|
||||||
|
newValues[0] = oldValues[1];
|
||||||
|
newValues[1] = oldValues[2];
|
||||||
|
newValues[2] = oldValues[3];
|
||||||
|
|
||||||
|
mBackgroundOps.setEntries(newEntries);
|
||||||
|
mBackgroundOps.setEntryValues(newValues);
|
||||||
|
|
||||||
|
// Since ConnectivityManager.getBackgroundDataSetting() always returns 'true' on ICS+
|
||||||
|
// we map WHEN_CHECKED to ALWAYS.
|
||||||
|
if (K9.getBackgroundOps() == K9.BACKGROUND_OPS.WHEN_CHECKED) {
|
||||||
|
mBackgroundOps.setValue(K9.BACKGROUND_OPS.ALWAYS.toString());
|
||||||
|
mBackgroundOps.setSummary(mBackgroundOps.getEntry());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mUseGalleryBugWorkaround = (CheckBoxPreference)findPreference(PREFERENCE_GALLERY_BUG_WORKAROUND);
|
mUseGalleryBugWorkaround = (CheckBoxPreference)findPreference(PREFERENCE_GALLERY_BUG_WORKAROUND);
|
||||||
mUseGalleryBugWorkaround.setChecked(K9.useGalleryBugWorkaround());
|
mUseGalleryBugWorkaround.setChecked(K9.useGalleryBugWorkaround());
|
||||||
|
@ -21,6 +21,7 @@ import android.app.PendingIntent;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
@ -534,9 +535,6 @@ public class MessagingController implements Runnable {
|
|||||||
List<Message> pendingMessages = new ArrayList<Message>();
|
List<Message> pendingMessages = new ArrayList<Message>();
|
||||||
|
|
||||||
|
|
||||||
int totalDone = 0;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageStarted(String message, int number, int ofTotal) {}
|
public void messageStarted(String message, int number, int ofTotal) {}
|
||||||
@Override
|
@Override
|
||||||
@ -544,7 +542,6 @@ public class MessagingController implements Runnable {
|
|||||||
|
|
||||||
if (!isMessageSuppressed(account, folder, message)) {
|
if (!isMessageSuppressed(account, folder, message)) {
|
||||||
pendingMessages.add(message);
|
pendingMessages.add(message);
|
||||||
totalDone++;
|
|
||||||
if (pendingMessages.size() > 10) {
|
if (pendingMessages.size() > 10) {
|
||||||
addPendingMessages();
|
addPendingMessages();
|
||||||
}
|
}
|
||||||
@ -2317,13 +2314,14 @@ public class MessagingController implements Runnable {
|
|||||||
* upto speed with the remote UIDs of remote destionation folder.
|
* upto speed with the remote UIDs of remote destionation folder.
|
||||||
*/
|
*/
|
||||||
if (!localUidMap.isEmpty() && remoteUidMap != null && !remoteUidMap.isEmpty()) {
|
if (!localUidMap.isEmpty() && remoteUidMap != null && !remoteUidMap.isEmpty()) {
|
||||||
Set<String> remoteSrcUids = remoteUidMap.keySet();
|
Set<Map.Entry<String, String>> remoteSrcEntries = remoteUidMap.entrySet();
|
||||||
Iterator<String> remoteSrcUidsIterator = remoteSrcUids.iterator();
|
Iterator<Map.Entry<String, String>> remoteSrcEntriesIterator = remoteSrcEntries.iterator();
|
||||||
|
|
||||||
while (remoteSrcUidsIterator.hasNext()) {
|
while (remoteSrcEntriesIterator.hasNext()) {
|
||||||
String remoteSrcUid = remoteSrcUidsIterator.next();
|
Map.Entry<String, String> entry = remoteSrcEntriesIterator.next();
|
||||||
|
String remoteSrcUid = entry.getKey();
|
||||||
String localDestUid = localUidMap.get(remoteSrcUid);
|
String localDestUid = localUidMap.get(remoteSrcUid);
|
||||||
String newUid = remoteUidMap.get(remoteSrcUid);
|
String newUid = entry.getValue();
|
||||||
|
|
||||||
Message localDestMessage = localDestFolder.getMessage(localDestUid);
|
Message localDestMessage = localDestFolder.getMessage(localDestUid);
|
||||||
if (localDestMessage != null) {
|
if (localDestMessage != null) {
|
||||||
@ -3433,7 +3431,6 @@ public class MessagingController implements Runnable {
|
|||||||
// "don't even bother" functionality
|
// "don't even bother" functionality
|
||||||
if (getRootCauseMessage(e).startsWith("5")) {
|
if (getRootCauseMessage(e).startsWith("5")) {
|
||||||
localFolder.moveMessages(new Message[] { message }, (LocalFolder) localStore.getFolder(account.getDraftsFolderName()));
|
localFolder.moveMessages(new Message[] { message }, (LocalFolder) localStore.getFolder(account.getDraftsFolderName()));
|
||||||
} else {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message.setFlag(Flag.X_SEND_FAILED, true);
|
message.setFlag(Flag.X_SEND_FAILED, true);
|
||||||
@ -4562,7 +4559,10 @@ public class MessagingController implements Runnable {
|
|||||||
builder.setTicker(messageNotice);
|
builder.setTicker(messageNotice);
|
||||||
|
|
||||||
final int unreadCount = previousUnreadMessageCount + newMessageCount.get();
|
final int unreadCount = previousUnreadMessageCount + newMessageCount.get();
|
||||||
if (account.isNotificationShowsUnreadCount()) {
|
if (account.isNotificationShowsUnreadCount() ||
|
||||||
|
// Honeycomb and newer don't show the number as overlay on the notification icon.
|
||||||
|
// However, the number will appear in the detailed notification view.
|
||||||
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||||
builder.setNumber(unreadCount);
|
builder.setNumber(unreadCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.fsck.k9.helper;
|
package com.fsck.k9.helper;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.ClipboardManager;
|
import android.content.ClipboardManager;
|
||||||
@ -7,6 +8,7 @@ import android.content.ClipboardManager;
|
|||||||
/**
|
/**
|
||||||
* Access the system clipboard using the new {@link ClipboardManager} introduced with API 11
|
* Access the system clipboard using the new {@link ClipboardManager} introduced with API 11
|
||||||
*/
|
*/
|
||||||
|
@TargetApi(11)
|
||||||
public class ClipboardManagerApi11 extends com.fsck.k9.helper.ClipboardManager {
|
public class ClipboardManagerApi11 extends com.fsck.k9.helper.ClipboardManager {
|
||||||
|
|
||||||
public ClipboardManagerApi11(Context context) {
|
public ClipboardManagerApi11(Context context) {
|
||||||
|
@ -124,16 +124,14 @@ public class DomainNameChecker {
|
|||||||
List<?> altNameEntry = (List<?>)(subjectAltName);
|
List<?> altNameEntry = (List<?>)(subjectAltName);
|
||||||
if ((altNameEntry != null) && (2 <= altNameEntry.size())) {
|
if ((altNameEntry != null) && (2 <= altNameEntry.size())) {
|
||||||
Integer altNameType = (Integer)(altNameEntry.get(0));
|
Integer altNameType = (Integer)(altNameEntry.get(0));
|
||||||
if (altNameType != null) {
|
if (altNameType != null && altNameType.intValue() == ALT_IPA_NAME) {
|
||||||
if (altNameType == ALT_IPA_NAME) {
|
String altName = (String)(altNameEntry.get(1));
|
||||||
String altName = (String)(altNameEntry.get(1));
|
if (altName != null) {
|
||||||
if (altName != null) {
|
if (K9.DEBUG) {
|
||||||
if (K9.DEBUG) {
|
Log.v(K9.LOG_TAG, "alternative IP: " + altName);
|
||||||
Log.v(K9.LOG_TAG, "alternative IP: " + altName);
|
}
|
||||||
}
|
if (thisDomain.equalsIgnoreCase(altName)) {
|
||||||
if (thisDomain.equalsIgnoreCase(altName)) {
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,15 +164,11 @@ public class DomainNameChecker {
|
|||||||
List<?> altNameEntry = (List<?>)(i.next());
|
List<?> altNameEntry = (List<?>)(i.next());
|
||||||
if ((altNameEntry != null) && (2 <= altNameEntry.size())) {
|
if ((altNameEntry != null) && (2 <= altNameEntry.size())) {
|
||||||
Integer altNameType = (Integer)(altNameEntry.get(0));
|
Integer altNameType = (Integer)(altNameEntry.get(0));
|
||||||
if (altNameType != null) {
|
if (altNameType != null && altNameType.intValue() == ALT_DNS_NAME) {
|
||||||
if (altNameType.intValue() == ALT_DNS_NAME) {
|
hasDns = true;
|
||||||
hasDns = true;
|
String altName = (String)(altNameEntry.get(1));
|
||||||
String altName = (String)(altNameEntry.get(1));
|
if (altName != null && matchDns(thisDomain, altName)) {
|
||||||
if (altName != null) {
|
return true;
|
||||||
if (matchDns(thisDomain, altName)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.fsck.k9.helper;
|
package com.fsck.k9.helper;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -9,6 +10,7 @@ import android.net.Uri;
|
|||||||
/**
|
/**
|
||||||
* Create notifications using the new {@link android.app.Notification.Builder} class.
|
* Create notifications using the new {@link android.app.Notification.Builder} class.
|
||||||
*/
|
*/
|
||||||
|
@TargetApi(11)
|
||||||
public class NotificationBuilderApi11 extends NotificationBuilder {
|
public class NotificationBuilderApi11 extends NotificationBuilder {
|
||||||
private Notification.Builder mBuilder;
|
private Notification.Builder mBuilder;
|
||||||
|
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
package com.fsck.k9.mail.filter;
|
|
||||||
|
|
||||||
import android.util.Config;
|
|
||||||
import android.util.Log;
|
|
||||||
import com.fsck.k9.K9;
|
|
||||||
|
|
||||||
import java.io.FilterOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
public class StatusOutputStream extends FilterOutputStream {
|
|
||||||
private long mCount = 0;
|
|
||||||
|
|
||||||
public StatusOutputStream(OutputStream out) {
|
|
||||||
super(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(int oneByte) throws IOException {
|
|
||||||
super.write(oneByte);
|
|
||||||
mCount++;
|
|
||||||
if (Config.LOGV) {
|
|
||||||
if (mCount % 1024 == 0) {
|
|
||||||
Log.v(K9.LOG_TAG, "# " + mCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -122,10 +122,9 @@ public class MimeHeader {
|
|||||||
public boolean hasToBeEncoded(String text) {
|
public boolean hasToBeEncoded(String text) {
|
||||||
for (int i = 0; i < text.length(); i++) {
|
for (int i = 0; i < text.length(); i++) {
|
||||||
char c = text.charAt(i);
|
char c = text.charAt(i);
|
||||||
if (c < 0x20 || 0x7e < c) { // non printable
|
if ((c < 0x20 || 0x7e < c) && // non printable
|
||||||
if (c != 0x0a && c != 0x0d && c != 0x09) { // non LF/CR/TAB
|
(c != 0x0a && c != 0x0d && c != 0x09)) { // non LF/CR/TAB
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,6 +384,10 @@ public class ImapResponseParser {
|
|||||||
return (String)get(index);
|
return (String)get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getLong(int index) {
|
||||||
|
return Long.parseLong(getString(index));
|
||||||
|
}
|
||||||
|
|
||||||
public int getNumber(int index) {
|
public int getNumber(int index) {
|
||||||
return Integer.parseInt(getString(index));
|
return Integer.parseInt(getString(index));
|
||||||
}
|
}
|
||||||
|
@ -843,12 +843,12 @@ public class ImapStore extends Store {
|
|||||||
class ImapFolder extends Folder {
|
class ImapFolder extends Folder {
|
||||||
private String mName;
|
private String mName;
|
||||||
protected volatile int mMessageCount = -1;
|
protected volatile int mMessageCount = -1;
|
||||||
protected volatile int uidNext = -1;
|
protected volatile long uidNext = -1L;
|
||||||
protected volatile ImapConnection mConnection;
|
protected volatile ImapConnection mConnection;
|
||||||
private OpenMode mMode;
|
private OpenMode mMode;
|
||||||
private volatile boolean mExists;
|
private volatile boolean mExists;
|
||||||
private ImapStore store = null;
|
private ImapStore store = null;
|
||||||
Map<Integer, String> msgSeqUidMap = new ConcurrentHashMap<Integer, String>();
|
Map<Long, String> msgSeqUidMap = new ConcurrentHashMap<Long, String>();
|
||||||
|
|
||||||
|
|
||||||
public ImapFolder(ImapStore nStore, String name) {
|
public ImapFolder(ImapStore nStore, String name) {
|
||||||
@ -1350,7 +1350,7 @@ public class ImapStore extends Store {
|
|||||||
return getRemoteMessageCount("FLAGGED NOT DELETED");
|
return getRemoteMessageCount("FLAGGED NOT DELETED");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getHighestUid() {
|
protected long getHighestUid() {
|
||||||
try {
|
try {
|
||||||
ImapSearcher searcher = new ImapSearcher() {
|
ImapSearcher searcher = new ImapSearcher() {
|
||||||
public List<ImapResponse> search() throws IOException, MessagingException {
|
public List<ImapResponse> search() throws IOException, MessagingException {
|
||||||
@ -1359,12 +1359,12 @@ public class ImapStore extends Store {
|
|||||||
};
|
};
|
||||||
Message[] messages = search(searcher, null);
|
Message[] messages = search(searcher, null);
|
||||||
if (messages.length > 0) {
|
if (messages.length > 0) {
|
||||||
return Integer.parseInt(messages[0].getUid());
|
return Long.parseLong(messages[0].getUid());
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(K9.LOG_TAG, "Unable to find highest UID in folder " + getName(), e);
|
Log.e(K9.LOG_TAG, "Unable to find highest UID in folder " + getName(), e);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1L;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1404,7 +1404,7 @@ public class ImapStore extends Store {
|
|||||||
return search(searcher, listener);
|
return search(searcher, listener);
|
||||||
|
|
||||||
}
|
}
|
||||||
protected Message[] getMessages(final List<Integer> mesgSeqs, final boolean includeDeleted, final MessageRetrievalListener listener)
|
protected Message[] getMessages(final List<Long> mesgSeqs, final boolean includeDeleted, final MessageRetrievalListener listener)
|
||||||
throws MessagingException {
|
throws MessagingException {
|
||||||
ImapSearcher searcher = new ImapSearcher() {
|
ImapSearcher searcher = new ImapSearcher() {
|
||||||
public List<ImapResponse> search() throws IOException, MessagingException {
|
public List<ImapResponse> search() throws IOException, MessagingException {
|
||||||
@ -1429,13 +1429,13 @@ public class ImapStore extends Store {
|
|||||||
checkOpen();
|
checkOpen();
|
||||||
ArrayList<Message> messages = new ArrayList<Message>();
|
ArrayList<Message> messages = new ArrayList<Message>();
|
||||||
try {
|
try {
|
||||||
ArrayList<Integer> uids = new ArrayList<Integer>();
|
ArrayList<Long> uids = new ArrayList<Long>();
|
||||||
List<ImapResponse> responses = searcher.search(); //
|
List<ImapResponse> responses = searcher.search(); //
|
||||||
for (ImapResponse response : responses) {
|
for (ImapResponse response : responses) {
|
||||||
if (response.mTag == null) {
|
if (response.mTag == null) {
|
||||||
if (ImapResponseParser.equalsIgnoreCase(response.get(0), "SEARCH")) {
|
if (ImapResponseParser.equalsIgnoreCase(response.get(0), "SEARCH")) {
|
||||||
for (int i = 1, count = response.size(); i < count; i++) {
|
for (int i = 1, count = response.size(); i < count; i++) {
|
||||||
uids.add(Integer.parseInt(response.getString(i)));
|
uids.add(response.getLong(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1444,10 +1444,11 @@ public class ImapStore extends Store {
|
|||||||
// Sort the uids in numerically ascending order
|
// Sort the uids in numerically ascending order
|
||||||
Collections.sort(uids);
|
Collections.sort(uids);
|
||||||
for (int i = 0, count = uids.size(); i < count; i++) {
|
for (int i = 0, count = uids.size(); i < count; i++) {
|
||||||
|
String uid = uids.get(i).toString();
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
listener.messageStarted("" + uids.get(i), i, count);
|
listener.messageStarted(uid, i, count);
|
||||||
}
|
}
|
||||||
ImapMessage message = new ImapMessage("" + uids.get(i), this);
|
ImapMessage message = new ImapMessage(uid, this);
|
||||||
messages.add(message);
|
messages.add(message);
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
listener.messageFinished(message, i, count);
|
listener.messageFinished(message, i, count);
|
||||||
@ -1571,7 +1572,7 @@ public class ImapStore extends Store {
|
|||||||
if (response.mTag == null && ImapResponseParser.equalsIgnoreCase(response.get(1), "FETCH")) {
|
if (response.mTag == null && ImapResponseParser.equalsIgnoreCase(response.get(1), "FETCH")) {
|
||||||
ImapList fetchList = (ImapList)response.getKeyedValue("FETCH");
|
ImapList fetchList = (ImapList)response.getKeyedValue("FETCH");
|
||||||
String uid = fetchList.getKeyedString("UID");
|
String uid = fetchList.getKeyedString("UID");
|
||||||
int msgSeq = response.getNumber(0);
|
long msgSeq = response.getLong(0);
|
||||||
if (uid != null) {
|
if (uid != null) {
|
||||||
try {
|
try {
|
||||||
msgSeqUidMap.put(msgSeq, uid);
|
msgSeqUidMap.put(msgSeq, uid);
|
||||||
@ -1798,7 +1799,7 @@ public class ImapStore extends Store {
|
|||||||
if (keyObj instanceof String) {
|
if (keyObj instanceof String) {
|
||||||
String key = (String)keyObj;
|
String key = (String)keyObj;
|
||||||
if ("UIDNEXT".equalsIgnoreCase(key)) {
|
if ("UIDNEXT".equalsIgnoreCase(key)) {
|
||||||
uidNext = bracketed.getNumber(1);
|
uidNext = bracketed.getLong(1);
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG)
|
||||||
Log.d(K9.LOG_TAG, "Got UidNext = " + uidNext + " for " + getLogId());
|
Log.d(K9.LOG_TAG, "Got UidNext = " + uidNext + " for " + getLogId());
|
||||||
}
|
}
|
||||||
@ -2190,10 +2191,10 @@ public class ImapStore extends Store {
|
|||||||
public String getNewPushState(String oldPushStateS, Message message) {
|
public String getNewPushState(String oldPushStateS, Message message) {
|
||||||
try {
|
try {
|
||||||
String messageUidS = message.getUid();
|
String messageUidS = message.getUid();
|
||||||
int messageUid = Integer.parseInt(messageUidS);
|
long messageUid = Long.parseLong(messageUidS);
|
||||||
ImapPushState oldPushState = ImapPushState.parse(oldPushStateS);
|
ImapPushState oldPushState = ImapPushState.parse(oldPushStateS);
|
||||||
if (messageUid >= oldPushState.uidNext) {
|
if (messageUid >= oldPushState.uidNext) {
|
||||||
int uidNext = messageUid + 1;
|
long uidNext = messageUid + 1;
|
||||||
ImapPushState newPushState = new ImapPushState(uidNext);
|
ImapPushState newPushState = new ImapPushState(uidNext);
|
||||||
return newPushState.toString();
|
return newPushState.toString();
|
||||||
} else {
|
} else {
|
||||||
@ -2303,21 +2304,19 @@ public class ImapStore extends Store {
|
|||||||
capabilityList = response;
|
capabilityList = response;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (capabilityList != null) {
|
if (capabilityList != null && !capabilityList.isEmpty() &&
|
||||||
if (!capabilityList.isEmpty() && ImapResponseParser.equalsIgnoreCase(capabilityList.get(0), CAPABILITY_CAPABILITY)) {
|
ImapResponseParser.equalsIgnoreCase(capabilityList.get(0), CAPABILITY_CAPABILITY)) {
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "Saving " + capabilityList.size() + " capabilities for " + getLogId());
|
Log.d(K9.LOG_TAG, "Saving " + capabilityList.size() + " capabilities for " + getLogId());
|
||||||
|
}
|
||||||
|
for (Object capability : capabilityList) {
|
||||||
|
if (capability instanceof String) {
|
||||||
|
// if (K9.DEBUG)
|
||||||
|
// {
|
||||||
|
// Log.v(K9.LOG_TAG, "Saving capability '" + capability + "' for " + getLogId());
|
||||||
|
// }
|
||||||
|
capabilities.add(((String)capability).toUpperCase(Locale.US));
|
||||||
}
|
}
|
||||||
for (Object capability : capabilityList) {
|
|
||||||
if (capability instanceof String) {
|
|
||||||
// if (K9.DEBUG)
|
|
||||||
// {
|
|
||||||
// Log.v(K9.LOG_TAG, "Saving capability '" + capability + "' for " + getLogId());
|
|
||||||
// }
|
|
||||||
capabilities.add(((String)capability).toUpperCase(Locale.US));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2886,7 +2885,7 @@ public class ImapStore extends Store {
|
|||||||
|
|
||||||
while (!stop.get()) {
|
while (!stop.get()) {
|
||||||
try {
|
try {
|
||||||
int oldUidNext = -1;
|
long oldUidNext = -1L;
|
||||||
try {
|
try {
|
||||||
String pushStateS = receiver.getPushState(getName());
|
String pushStateS = receiver.getPushState(getName());
|
||||||
ImapPushState pushState = ImapPushState.parse(pushStateS);
|
ImapPushState pushState = ImapPushState.parse(pushStateS);
|
||||||
@ -2922,16 +2921,16 @@ public class ImapStore extends Store {
|
|||||||
if (stop.get()) {
|
if (stop.get()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int startUid = oldUidNext;
|
long startUid = oldUidNext;
|
||||||
|
|
||||||
int newUidNext = uidNext;
|
long newUidNext = uidNext;
|
||||||
|
|
||||||
if (newUidNext == -1) {
|
if (newUidNext == -1) {
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "uidNext is -1, using search to find highest UID");
|
Log.d(K9.LOG_TAG, "uidNext is -1, using search to find highest UID");
|
||||||
}
|
}
|
||||||
int highestUid = getHighestUid();
|
long highestUid = getHighestUid();
|
||||||
if (highestUid != -1) {
|
if (highestUid != -1L) {
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG)
|
||||||
Log.d(K9.LOG_TAG, "highest UID = " + highestUid);
|
Log.d(K9.LOG_TAG, "highest UID = " + highestUid);
|
||||||
newUidNext = highestUid + 1;
|
newUidNext = highestUid + 1;
|
||||||
@ -2952,7 +2951,7 @@ public class ImapStore extends Store {
|
|||||||
if (K9.DEBUG)
|
if (K9.DEBUG)
|
||||||
Log.i(K9.LOG_TAG, "Needs sync from uid " + startUid + " to " + newUidNext + " for " + getLogId());
|
Log.i(K9.LOG_TAG, "Needs sync from uid " + startUid + " to " + newUidNext + " for " + getLogId());
|
||||||
List<Message> messages = new ArrayList<Message>();
|
List<Message> messages = new ArrayList<Message>();
|
||||||
for (int uid = startUid; uid < newUidNext; uid++) {
|
for (long uid = startUid; uid < newUidNext; uid++) {
|
||||||
ImapMessage message = new ImapMessage("" + uid, ImapFolderPusher.this);
|
ImapMessage message = new ImapMessage("" + uid, ImapFolderPusher.this);
|
||||||
messages.add(message);
|
messages.add(message);
|
||||||
}
|
}
|
||||||
@ -3052,7 +3051,7 @@ public class ImapStore extends Store {
|
|||||||
if (oldMessageCount == -1) {
|
if (oldMessageCount == -1) {
|
||||||
skipSync = true;
|
skipSync = true;
|
||||||
}
|
}
|
||||||
List<Integer> flagSyncMsgSeqs = new ArrayList<Integer>();
|
List<Long> flagSyncMsgSeqs = new ArrayList<Long>();
|
||||||
List<String> removeMsgUids = new LinkedList<String>();
|
List<String> removeMsgUids = new LinkedList<String>();
|
||||||
|
|
||||||
for (ImapResponse response : responses) {
|
for (ImapResponse response : responses) {
|
||||||
@ -3078,7 +3077,7 @@ public class ImapStore extends Store {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void syncMessages(int end, boolean newArrivals) throws MessagingException {
|
private void syncMessages(int end, boolean newArrivals) throws MessagingException {
|
||||||
int oldUidNext = -1;
|
long oldUidNext = -1L;
|
||||||
try {
|
try {
|
||||||
String pushStateS = receiver.getPushState(getName());
|
String pushStateS = receiver.getPushState(getName());
|
||||||
ImapPushState pushState = ImapPushState.parse(pushStateS);
|
ImapPushState pushState = ImapPushState.parse(pushStateS);
|
||||||
@ -3091,10 +3090,10 @@ public class ImapStore extends Store {
|
|||||||
|
|
||||||
Message[] messageArray = getMessages(end, end, null, true, null);
|
Message[] messageArray = getMessages(end, end, null, true, null);
|
||||||
if (messageArray != null && messageArray.length > 0) {
|
if (messageArray != null && messageArray.length > 0) {
|
||||||
int newUid = Integer.parseInt(messageArray[0].getUid());
|
long newUid = Long.parseLong(messageArray[0].getUid());
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG)
|
||||||
Log.i(K9.LOG_TAG, "Got newUid " + newUid + " for message " + end + " on " + getLogId());
|
Log.i(K9.LOG_TAG, "Got newUid " + newUid + " for message " + end + " on " + getLogId());
|
||||||
int startUid = oldUidNext;
|
long startUid = oldUidNext;
|
||||||
if (startUid < newUid - 10) {
|
if (startUid < newUid - 10) {
|
||||||
startUid = newUid - 10;
|
startUid = newUid - 10;
|
||||||
}
|
}
|
||||||
@ -3106,8 +3105,8 @@ public class ImapStore extends Store {
|
|||||||
if (K9.DEBUG)
|
if (K9.DEBUG)
|
||||||
Log.i(K9.LOG_TAG, "Needs sync from uid " + startUid + " to " + newUid + " for " + getLogId());
|
Log.i(K9.LOG_TAG, "Needs sync from uid " + startUid + " to " + newUid + " for " + getLogId());
|
||||||
List<Message> messages = new ArrayList<Message>();
|
List<Message> messages = new ArrayList<Message>();
|
||||||
for (int uid = startUid; uid <= newUid; uid++) {
|
for (long uid = startUid; uid <= newUid; uid++) {
|
||||||
ImapMessage message = new ImapMessage("" + uid, ImapFolderPusher.this);
|
ImapMessage message = new ImapMessage(Long.toString(uid), ImapFolderPusher.this);
|
||||||
messages.add(message);
|
messages.add(message);
|
||||||
}
|
}
|
||||||
if (!messages.isEmpty()) {
|
if (!messages.isEmpty()) {
|
||||||
@ -3117,7 +3116,7 @@ public class ImapStore extends Store {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void syncMessages(List<Integer> flagSyncMsgSeqs) {
|
private void syncMessages(List<Long> flagSyncMsgSeqs) {
|
||||||
try {
|
try {
|
||||||
Message[] messageArray = null;
|
Message[] messageArray = null;
|
||||||
|
|
||||||
@ -3160,7 +3159,7 @@ public class ImapStore extends Store {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int processUntaggedResponse(int oldMessageCount, ImapResponse response, List<Integer> flagSyncMsgSeqs, List<String> removeMsgUids) {
|
protected int processUntaggedResponse(long oldMessageCount, ImapResponse response, List<Long> flagSyncMsgSeqs, List<String> removeMsgUids) {
|
||||||
super.handleUntaggedResponse(response);
|
super.handleUntaggedResponse(response);
|
||||||
int messageCountDelta = 0;
|
int messageCountDelta = 0;
|
||||||
if (response.mTag == null && response.size() > 1) {
|
if (response.mTag == null && response.size() > 1) {
|
||||||
@ -3168,7 +3167,7 @@ public class ImapStore extends Store {
|
|||||||
Object responseType = response.get(1);
|
Object responseType = response.get(1);
|
||||||
if (ImapResponseParser.equalsIgnoreCase(responseType, "FETCH")) {
|
if (ImapResponseParser.equalsIgnoreCase(responseType, "FETCH")) {
|
||||||
Log.i(K9.LOG_TAG, "Got FETCH " + response);
|
Log.i(K9.LOG_TAG, "Got FETCH " + response);
|
||||||
int msgSeq = response.getNumber(0);
|
long msgSeq = response.getLong(0);
|
||||||
|
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG)
|
||||||
Log.d(K9.LOG_TAG, "Got untagged FETCH for msgseq " + msgSeq + " for " + getLogId());
|
Log.d(K9.LOG_TAG, "Got untagged FETCH for msgseq " + msgSeq + " for " + getLogId());
|
||||||
@ -3178,17 +3177,17 @@ public class ImapStore extends Store {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ImapResponseParser.equalsIgnoreCase(responseType, "EXPUNGE")) {
|
if (ImapResponseParser.equalsIgnoreCase(responseType, "EXPUNGE")) {
|
||||||
int msgSeq = response.getNumber(0);
|
long msgSeq = response.getLong(0);
|
||||||
if (msgSeq <= oldMessageCount) {
|
if (msgSeq <= oldMessageCount) {
|
||||||
messageCountDelta = -1;
|
messageCountDelta = -1;
|
||||||
}
|
}
|
||||||
if (K9.DEBUG)
|
if (K9.DEBUG)
|
||||||
Log.d(K9.LOG_TAG, "Got untagged EXPUNGE for msgseq " + msgSeq + " for " + getLogId());
|
Log.d(K9.LOG_TAG, "Got untagged EXPUNGE for msgseq " + msgSeq + " for " + getLogId());
|
||||||
|
|
||||||
List<Integer> newSeqs = new ArrayList<Integer>();
|
List<Long> newSeqs = new ArrayList<Long>();
|
||||||
Iterator<Integer> flagIter = flagSyncMsgSeqs.iterator();
|
Iterator<Long> flagIter = flagSyncMsgSeqs.iterator();
|
||||||
while (flagIter.hasNext()) {
|
while (flagIter.hasNext()) {
|
||||||
Integer flagMsg = flagIter.next();
|
long flagMsg = flagIter.next();
|
||||||
if (flagMsg >= msgSeq) {
|
if (flagMsg >= msgSeq) {
|
||||||
flagIter.remove();
|
flagIter.remove();
|
||||||
if (flagMsg > msgSeq) {
|
if (flagMsg > msgSeq) {
|
||||||
@ -3199,14 +3198,13 @@ public class ImapStore extends Store {
|
|||||||
flagSyncMsgSeqs.addAll(newSeqs);
|
flagSyncMsgSeqs.addAll(newSeqs);
|
||||||
|
|
||||||
|
|
||||||
List<Integer> msgSeqs = new ArrayList<Integer>(msgSeqUidMap.keySet());
|
List<Long> msgSeqs = new ArrayList<Long>(msgSeqUidMap.keySet());
|
||||||
Collections.sort(msgSeqs); // Have to do comparisons in order because of msgSeq reductions
|
Collections.sort(msgSeqs); // Have to do comparisons in order because of msgSeq reductions
|
||||||
|
|
||||||
for (Integer msgSeqNumI : msgSeqs) {
|
for (long msgSeqNum : msgSeqs) {
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.v(K9.LOG_TAG, "Comparing EXPUNGEd msgSeq " + msgSeq + " to " + msgSeqNumI);
|
Log.v(K9.LOG_TAG, "Comparing EXPUNGEd msgSeq " + msgSeq + " to " + msgSeqNum);
|
||||||
}
|
}
|
||||||
int msgSeqNum = msgSeqNumI;
|
|
||||||
if (msgSeqNum == msgSeq) {
|
if (msgSeqNum == msgSeq) {
|
||||||
String uid = msgSeqUidMap.get(msgSeqNum);
|
String uid = msgSeqUidMap.get(msgSeqNum);
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
@ -3388,12 +3386,12 @@ public class ImapStore extends Store {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected static class ImapPushState {
|
protected static class ImapPushState {
|
||||||
protected int uidNext;
|
protected long uidNext;
|
||||||
protected ImapPushState(int nUidNext) {
|
protected ImapPushState(long nUidNext) {
|
||||||
uidNext = nUidNext;
|
uidNext = nUidNext;
|
||||||
}
|
}
|
||||||
protected static ImapPushState parse(String pushState) {
|
protected static ImapPushState parse(String pushState) {
|
||||||
int newUidNext = -1;
|
long newUidNext = -1L;
|
||||||
if (pushState != null) {
|
if (pushState != null) {
|
||||||
StringTokenizer tokenizer = new StringTokenizer(pushState, ";");
|
StringTokenizer tokenizer = new StringTokenizer(pushState, ";");
|
||||||
while (tokenizer.hasMoreTokens()) {
|
while (tokenizer.hasMoreTokens()) {
|
||||||
@ -3404,8 +3402,8 @@ public class ImapStore extends Store {
|
|||||||
if ("uidNext".equalsIgnoreCase(key) && thisState.hasMoreTokens()) {
|
if ("uidNext".equalsIgnoreCase(key) && thisState.hasMoreTokens()) {
|
||||||
String value = thisState.nextToken();
|
String value = thisState.nextToken();
|
||||||
try {
|
try {
|
||||||
newUidNext = Integer.parseInt(value);
|
newUidNext = Long.parseLong(value);
|
||||||
} catch (Exception e) {
|
} catch (NumberFormatException e) {
|
||||||
Log.e(K9.LOG_TAG, "Unable to part uidNext value " + value, e);
|
Log.e(K9.LOG_TAG, "Unable to part uidNext value " + value, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,216 +157,219 @@ public class LocalStore extends Store implements Serializable {
|
|||||||
|
|
||||||
AttachmentProvider.clear(mApplication);
|
AttachmentProvider.clear(mApplication);
|
||||||
|
|
||||||
|
db.beginTransaction();
|
||||||
try {
|
try {
|
||||||
// schema version 29 was when we moved to incremental updates
|
try {
|
||||||
// in the case of a new db or a < v29 db, we blow away and start from scratch
|
// schema version 29 was when we moved to incremental updates
|
||||||
if (db.getVersion() < 29) {
|
// in the case of a new db or a < v29 db, we blow away and start from scratch
|
||||||
|
if (db.getVersion() < 29) {
|
||||||
|
|
||||||
db.execSQL("DROP TABLE IF EXISTS folders");
|
db.execSQL("DROP TABLE IF EXISTS folders");
|
||||||
db.execSQL("CREATE TABLE folders (id INTEGER PRIMARY KEY, name TEXT, "
|
db.execSQL("CREATE TABLE folders (id INTEGER PRIMARY KEY, name TEXT, "
|
||||||
+ "last_updated INTEGER, unread_count INTEGER, visible_limit INTEGER, status TEXT, "
|
+ "last_updated INTEGER, unread_count INTEGER, visible_limit INTEGER, status TEXT, "
|
||||||
+ "push_state TEXT, last_pushed INTEGER, flagged_count INTEGER default 0, "
|
+ "push_state TEXT, last_pushed INTEGER, flagged_count INTEGER default 0, "
|
||||||
+ "integrate INTEGER, top_group INTEGER, poll_class TEXT, push_class TEXT, display_class TEXT, "
|
+ "integrate INTEGER, top_group INTEGER, poll_class TEXT, push_class TEXT, display_class TEXT, "
|
||||||
+ "local_only INTEGER default 0)");
|
+ "local_only INTEGER default 0)");
|
||||||
|
|
||||||
db.execSQL("CREATE INDEX IF NOT EXISTS folder_name ON folders (name)");
|
db.execSQL("CREATE INDEX IF NOT EXISTS folder_name ON folders (name)");
|
||||||
db.execSQL("DROP TABLE IF EXISTS messages");
|
db.execSQL("DROP TABLE IF EXISTS messages");
|
||||||
db.execSQL("CREATE TABLE messages (id INTEGER PRIMARY KEY, deleted INTEGER default 0, folder_id INTEGER, uid TEXT, subject TEXT, "
|
db.execSQL("CREATE TABLE messages (id INTEGER PRIMARY KEY, deleted INTEGER default 0, folder_id INTEGER, uid TEXT, subject TEXT, "
|
||||||
+ "date INTEGER, flags TEXT, sender_list TEXT, to_list TEXT, cc_list TEXT, bcc_list TEXT, reply_to_list TEXT, "
|
+ "date INTEGER, flags TEXT, sender_list TEXT, to_list TEXT, cc_list TEXT, bcc_list TEXT, reply_to_list TEXT, "
|
||||||
+ "html_content TEXT, text_content TEXT, attachment_count INTEGER, internal_date INTEGER, message_id TEXT, preview TEXT, "
|
+ "html_content TEXT, text_content TEXT, attachment_count INTEGER, internal_date INTEGER, message_id TEXT, preview TEXT, "
|
||||||
+ "mime_type TEXT)");
|
+ "mime_type TEXT)");
|
||||||
|
|
||||||
db.execSQL("DROP TABLE IF EXISTS headers");
|
db.execSQL("DROP TABLE IF EXISTS headers");
|
||||||
db.execSQL("CREATE TABLE headers (id INTEGER PRIMARY KEY, message_id INTEGER, name TEXT, value TEXT)");
|
db.execSQL("CREATE TABLE headers (id INTEGER PRIMARY KEY, message_id INTEGER, name TEXT, value TEXT)");
|
||||||
db.execSQL("CREATE INDEX IF NOT EXISTS header_folder ON headers (message_id)");
|
db.execSQL("CREATE INDEX IF NOT EXISTS header_folder ON headers (message_id)");
|
||||||
|
|
||||||
db.execSQL("CREATE INDEX IF NOT EXISTS msg_uid ON messages (uid, folder_id)");
|
db.execSQL("CREATE INDEX IF NOT EXISTS msg_uid ON messages (uid, folder_id)");
|
||||||
db.execSQL("DROP INDEX IF EXISTS msg_folder_id");
|
db.execSQL("DROP INDEX IF EXISTS msg_folder_id");
|
||||||
db.execSQL("DROP INDEX IF EXISTS msg_folder_id_date");
|
|
||||||
db.execSQL("CREATE INDEX IF NOT EXISTS msg_folder_id_deleted_date ON messages (folder_id,deleted,internal_date)");
|
|
||||||
db.execSQL("DROP TABLE IF EXISTS attachments");
|
|
||||||
db.execSQL("CREATE TABLE attachments (id INTEGER PRIMARY KEY, message_id INTEGER,"
|
|
||||||
+ "store_data TEXT, content_uri TEXT, size INTEGER, name TEXT,"
|
|
||||||
+ "mime_type TEXT, content_id TEXT, content_disposition TEXT)");
|
|
||||||
|
|
||||||
db.execSQL("DROP TABLE IF EXISTS pending_commands");
|
|
||||||
db.execSQL("CREATE TABLE pending_commands " +
|
|
||||||
"(id INTEGER PRIMARY KEY, command TEXT, arguments TEXT)");
|
|
||||||
|
|
||||||
db.execSQL("DROP TRIGGER IF EXISTS delete_folder");
|
|
||||||
db.execSQL("CREATE TRIGGER delete_folder BEFORE DELETE ON folders BEGIN DELETE FROM messages WHERE old.id = folder_id; END;");
|
|
||||||
|
|
||||||
db.execSQL("DROP TRIGGER IF EXISTS delete_message");
|
|
||||||
db.execSQL("CREATE TRIGGER delete_message BEFORE DELETE ON messages BEGIN DELETE FROM attachments WHERE old.id = message_id; "
|
|
||||||
+ "DELETE FROM headers where old.id = message_id; END;");
|
|
||||||
} else {
|
|
||||||
// in the case that we're starting out at 29 or newer, run all the needed updates
|
|
||||||
|
|
||||||
if (db.getVersion() < 30) {
|
|
||||||
try {
|
|
||||||
db.execSQL("ALTER TABLE messages ADD deleted INTEGER default 0");
|
|
||||||
} catch (SQLiteException e) {
|
|
||||||
if (! e.toString().startsWith("duplicate column name: deleted")) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (db.getVersion() < 31) {
|
|
||||||
db.execSQL("DROP INDEX IF EXISTS msg_folder_id_date");
|
db.execSQL("DROP INDEX IF EXISTS msg_folder_id_date");
|
||||||
db.execSQL("CREATE INDEX IF NOT EXISTS msg_folder_id_deleted_date ON messages (folder_id,deleted,internal_date)");
|
db.execSQL("CREATE INDEX IF NOT EXISTS msg_folder_id_deleted_date ON messages (folder_id,deleted,internal_date)");
|
||||||
}
|
db.execSQL("DROP TABLE IF EXISTS attachments");
|
||||||
if (db.getVersion() < 32) {
|
db.execSQL("CREATE TABLE attachments (id INTEGER PRIMARY KEY, message_id INTEGER,"
|
||||||
db.execSQL("UPDATE messages SET deleted = 1 WHERE flags LIKE '%DELETED%'");
|
+ "store_data TEXT, content_uri TEXT, size INTEGER, name TEXT,"
|
||||||
}
|
+ "mime_type TEXT, content_id TEXT, content_disposition TEXT)");
|
||||||
if (db.getVersion() < 33) {
|
|
||||||
|
|
||||||
try {
|
db.execSQL("DROP TABLE IF EXISTS pending_commands");
|
||||||
db.execSQL("ALTER TABLE messages ADD preview TEXT");
|
db.execSQL("CREATE TABLE pending_commands " +
|
||||||
} catch (SQLiteException e) {
|
"(id INTEGER PRIMARY KEY, command TEXT, arguments TEXT)");
|
||||||
if (! e.toString().startsWith("duplicate column name: preview")) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
db.execSQL("DROP TRIGGER IF EXISTS delete_folder");
|
||||||
if (db.getVersion() < 34) {
|
db.execSQL("CREATE TRIGGER delete_folder BEFORE DELETE ON folders BEGIN DELETE FROM messages WHERE old.id = folder_id; END;");
|
||||||
try {
|
|
||||||
db.execSQL("ALTER TABLE folders ADD flagged_count INTEGER default 0");
|
|
||||||
} catch (SQLiteException e) {
|
|
||||||
if (! e.getMessage().startsWith("duplicate column name: flagged_count")) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (db.getVersion() < 35) {
|
|
||||||
try {
|
|
||||||
db.execSQL("update messages set flags = replace(flags, 'X_NO_SEEN_INFO', 'X_BAD_FLAG')");
|
|
||||||
} catch (SQLiteException e) {
|
|
||||||
Log.e(K9.LOG_TAG, "Unable to get rid of obsolete flag X_NO_SEEN_INFO", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (db.getVersion() < 36) {
|
|
||||||
try {
|
|
||||||
db.execSQL("ALTER TABLE attachments ADD content_id TEXT");
|
|
||||||
} catch (SQLiteException e) {
|
|
||||||
Log.e(K9.LOG_TAG, "Unable to add content_id column to attachments");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (db.getVersion() < 37) {
|
|
||||||
try {
|
|
||||||
db.execSQL("ALTER TABLE attachments ADD content_disposition TEXT");
|
|
||||||
} catch (SQLiteException e) {
|
|
||||||
Log.e(K9.LOG_TAG, "Unable to add content_disposition column to attachments");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Database version 38 is solely to prune cached attachments now that we clear them better
|
db.execSQL("DROP TRIGGER IF EXISTS delete_message");
|
||||||
if (db.getVersion() < 39) {
|
db.execSQL("CREATE TRIGGER delete_message BEFORE DELETE ON messages BEGIN DELETE FROM attachments WHERE old.id = message_id; "
|
||||||
try {
|
+ "DELETE FROM headers where old.id = message_id; END;");
|
||||||
db.execSQL("DELETE FROM headers WHERE id in (SELECT headers.id FROM headers LEFT JOIN messages ON headers.message_id = messages.id WHERE messages.id IS NULL)");
|
} else {
|
||||||
} catch (SQLiteException e) {
|
// in the case that we're starting out at 29 or newer, run all the needed updates
|
||||||
Log.e(K9.LOG_TAG, "Unable to remove extra header data from the database");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// V40: Store the MIME type for a message.
|
if (db.getVersion() < 30) {
|
||||||
if (db.getVersion() < 40) {
|
try {
|
||||||
try {
|
db.execSQL("ALTER TABLE messages ADD deleted INTEGER default 0");
|
||||||
db.execSQL("ALTER TABLE messages ADD mime_type TEXT");
|
} catch (SQLiteException e) {
|
||||||
} catch (SQLiteException e) {
|
if (! e.toString().startsWith("duplicate column name: deleted")) {
|
||||||
Log.e(K9.LOG_TAG, "Unable to add mime_type column to messages");
|
throw e;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (db.getVersion() < 41) {
|
|
||||||
try {
|
|
||||||
db.execSQL("ALTER TABLE folders ADD integrate INTEGER");
|
|
||||||
db.execSQL("ALTER TABLE folders ADD top_group INTEGER");
|
|
||||||
db.execSQL("ALTER TABLE folders ADD poll_class TEXT");
|
|
||||||
db.execSQL("ALTER TABLE folders ADD push_class TEXT");
|
|
||||||
db.execSQL("ALTER TABLE folders ADD display_class TEXT");
|
|
||||||
} catch (SQLiteException e) {
|
|
||||||
if (! e.getMessage().startsWith("duplicate column name:")) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Cursor cursor = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
SharedPreferences prefs = getPreferences();
|
|
||||||
cursor = db.rawQuery("SELECT id, name FROM folders", null);
|
|
||||||
while (cursor.moveToNext()) {
|
|
||||||
try {
|
|
||||||
int id = cursor.getInt(0);
|
|
||||||
String name = cursor.getString(1);
|
|
||||||
update41Metadata(db, prefs, id, name);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(K9.LOG_TAG, " error trying to ugpgrade a folder class", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (db.getVersion() < 31) {
|
||||||
|
db.execSQL("DROP INDEX IF EXISTS msg_folder_id_date");
|
||||||
catch (SQLiteException e) {
|
db.execSQL("CREATE INDEX IF NOT EXISTS msg_folder_id_deleted_date ON messages (folder_id,deleted,internal_date)");
|
||||||
Log.e(K9.LOG_TAG, "Exception while upgrading database to v41. folder classes may have vanished", e);
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
Utility.closeQuietly(cursor);
|
|
||||||
}
|
}
|
||||||
}
|
if (db.getVersion() < 32) {
|
||||||
if (db.getVersion() == 41) {
|
db.execSQL("UPDATE messages SET deleted = 1 WHERE flags LIKE '%DELETED%'");
|
||||||
try {
|
}
|
||||||
long startTime = System.currentTimeMillis();
|
if (db.getVersion() < 33) {
|
||||||
SharedPreferences.Editor editor = getPreferences().edit();
|
|
||||||
|
|
||||||
List <? extends Folder > folders = getPersonalNamespaces(true);
|
try {
|
||||||
for (Folder folder : folders) {
|
db.execSQL("ALTER TABLE messages ADD preview TEXT");
|
||||||
if (folder instanceof LocalFolder) {
|
} catch (SQLiteException e) {
|
||||||
LocalFolder lFolder = (LocalFolder)folder;
|
if (! e.toString().startsWith("duplicate column name: preview")) {
|
||||||
lFolder.save(editor);
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.commit();
|
|
||||||
long endTime = System.currentTimeMillis();
|
|
||||||
Log.i(K9.LOG_TAG, "Putting folder preferences for " + folders.size() + " folders back into Preferences took " + (endTime - startTime) + " ms");
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(K9.LOG_TAG, "Could not replace Preferences in upgrade from DB_VERSION 41", e);
|
|
||||||
}
|
}
|
||||||
}
|
if (db.getVersion() < 34) {
|
||||||
if (db.getVersion() < 43) {
|
try {
|
||||||
try {
|
db.execSQL("ALTER TABLE folders ADD flagged_count INTEGER default 0");
|
||||||
// If folder "OUTBOX" (old, v3.800 - v3.802) exists, rename it to
|
} catch (SQLiteException e) {
|
||||||
// "K9MAIL_INTERNAL_OUTBOX" (new)
|
if (! e.getMessage().startsWith("duplicate column name: flagged_count")) {
|
||||||
LocalFolder oldOutbox = new LocalFolder("OUTBOX");
|
throw e;
|
||||||
if (oldOutbox.exists()) {
|
}
|
||||||
ContentValues cv = new ContentValues();
|
}
|
||||||
cv.put("name", Account.OUTBOX);
|
}
|
||||||
db.update("folders", cv, "name = ?", new String[] { "OUTBOX" });
|
if (db.getVersion() < 35) {
|
||||||
Log.i(K9.LOG_TAG, "Renamed folder OUTBOX to " + Account.OUTBOX);
|
try {
|
||||||
|
db.execSQL("update messages set flags = replace(flags, 'X_NO_SEEN_INFO', 'X_BAD_FLAG')");
|
||||||
|
} catch (SQLiteException e) {
|
||||||
|
Log.e(K9.LOG_TAG, "Unable to get rid of obsolete flag X_NO_SEEN_INFO", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (db.getVersion() < 36) {
|
||||||
|
try {
|
||||||
|
db.execSQL("ALTER TABLE attachments ADD content_id TEXT");
|
||||||
|
} catch (SQLiteException e) {
|
||||||
|
Log.e(K9.LOG_TAG, "Unable to add content_id column to attachments");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (db.getVersion() < 37) {
|
||||||
|
try {
|
||||||
|
db.execSQL("ALTER TABLE attachments ADD content_disposition TEXT");
|
||||||
|
} catch (SQLiteException e) {
|
||||||
|
Log.e(K9.LOG_TAG, "Unable to add content_disposition column to attachments");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Database version 38 is solely to prune cached attachments now that we clear them better
|
||||||
|
if (db.getVersion() < 39) {
|
||||||
|
try {
|
||||||
|
db.execSQL("DELETE FROM headers WHERE id in (SELECT headers.id FROM headers LEFT JOIN messages ON headers.message_id = messages.id WHERE messages.id IS NULL)");
|
||||||
|
} catch (SQLiteException e) {
|
||||||
|
Log.e(K9.LOG_TAG, "Unable to remove extra header data from the database");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// V40: Store the MIME type for a message.
|
||||||
|
if (db.getVersion() < 40) {
|
||||||
|
try {
|
||||||
|
db.execSQL("ALTER TABLE messages ADD mime_type TEXT");
|
||||||
|
} catch (SQLiteException e) {
|
||||||
|
Log.e(K9.LOG_TAG, "Unable to add mime_type column to messages");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (db.getVersion() < 41) {
|
||||||
|
try {
|
||||||
|
db.execSQL("ALTER TABLE folders ADD integrate INTEGER");
|
||||||
|
db.execSQL("ALTER TABLE folders ADD top_group INTEGER");
|
||||||
|
db.execSQL("ALTER TABLE folders ADD poll_class TEXT");
|
||||||
|
db.execSQL("ALTER TABLE folders ADD push_class TEXT");
|
||||||
|
db.execSQL("ALTER TABLE folders ADD display_class TEXT");
|
||||||
|
} catch (SQLiteException e) {
|
||||||
|
if (! e.getMessage().startsWith("duplicate column name:")) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Cursor cursor = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
SharedPreferences prefs = getPreferences();
|
||||||
|
cursor = db.rawQuery("SELECT id, name FROM folders", null);
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
try {
|
||||||
|
int id = cursor.getInt(0);
|
||||||
|
String name = cursor.getString(1);
|
||||||
|
update41Metadata(db, prefs, id, name);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(K9.LOG_TAG, " error trying to ugpgrade a folder class", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if old (pre v3.800) localized outbox folder exists
|
|
||||||
String localizedOutbox = K9.app.getString(R.string.special_mailbox_name_outbox);
|
|
||||||
LocalFolder obsoleteOutbox = new LocalFolder(localizedOutbox);
|
|
||||||
if (obsoleteOutbox.exists()) {
|
|
||||||
// Get all messages from the localized outbox ...
|
|
||||||
Message[] messages = obsoleteOutbox.getMessages(null, false);
|
|
||||||
|
|
||||||
if (messages.length > 0) {
|
catch (SQLiteException e) {
|
||||||
// ... and move them to the drafts folder (we don't want to
|
Log.e(K9.LOG_TAG, "Exception while upgrading database to v41. folder classes may have vanished", e);
|
||||||
// surprise the user by sending potentially very old messages)
|
|
||||||
LocalFolder drafts = new LocalFolder(mAccount.getDraftsFolderName());
|
} finally {
|
||||||
obsoleteOutbox.moveMessages(messages, drafts);
|
Utility.closeQuietly(cursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (db.getVersion() == 41) {
|
||||||
|
try {
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
SharedPreferences.Editor editor = getPreferences().edit();
|
||||||
|
|
||||||
|
List <? extends Folder > folders = getPersonalNamespaces(true);
|
||||||
|
for (Folder folder : folders) {
|
||||||
|
if (folder instanceof LocalFolder) {
|
||||||
|
LocalFolder lFolder = (LocalFolder)folder;
|
||||||
|
lFolder.save(editor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now get rid of the localized outbox
|
editor.commit();
|
||||||
obsoleteOutbox.delete();
|
long endTime = System.currentTimeMillis();
|
||||||
obsoleteOutbox.delete(true);
|
Log.i(K9.LOG_TAG, "Putting folder preferences for " + folders.size() + " folders back into Preferences took " + (endTime - startTime) + " ms");
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(K9.LOG_TAG, "Could not replace Preferences in upgrade from DB_VERSION 41", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (db.getVersion() < 43) {
|
||||||
|
try {
|
||||||
|
// If folder "OUTBOX" (old, v3.800 - v3.802) exists, rename it to
|
||||||
|
// "K9MAIL_INTERNAL_OUTBOX" (new)
|
||||||
|
LocalFolder oldOutbox = new LocalFolder("OUTBOX");
|
||||||
|
if (oldOutbox.exists()) {
|
||||||
|
ContentValues cv = new ContentValues();
|
||||||
|
cv.put("name", Account.OUTBOX);
|
||||||
|
db.update("folders", cv, "name = ?", new String[] { "OUTBOX" });
|
||||||
|
Log.i(K9.LOG_TAG, "Renamed folder OUTBOX to " + Account.OUTBOX);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if old (pre v3.800) localized outbox folder exists
|
||||||
|
String localizedOutbox = K9.app.getString(R.string.special_mailbox_name_outbox);
|
||||||
|
LocalFolder obsoleteOutbox = new LocalFolder(localizedOutbox);
|
||||||
|
if (obsoleteOutbox.exists()) {
|
||||||
|
// Get all messages from the localized outbox ...
|
||||||
|
Message[] messages = obsoleteOutbox.getMessages(null, false);
|
||||||
|
|
||||||
|
if (messages.length > 0) {
|
||||||
|
// ... and move them to the drafts folder (we don't want to
|
||||||
|
// surprise the user by sending potentially very old messages)
|
||||||
|
LocalFolder drafts = new LocalFolder(mAccount.getDraftsFolderName());
|
||||||
|
obsoleteOutbox.moveMessages(messages, drafts);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now get rid of the localized outbox
|
||||||
|
obsoleteOutbox.delete();
|
||||||
|
obsoleteOutbox.delete(true);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(K9.LOG_TAG, "Error trying to fix the outbox folders", e);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(K9.LOG_TAG, "Error trying to fix the outbox folders", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (db.getVersion() < 44) {
|
if (db.getVersion() < 44) {
|
||||||
@ -410,19 +413,19 @@ Log.d("ASH", "updatedb " + mAccount.getDescription());
|
|||||||
+ e);
|
+ e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (SQLiteException e) {
|
||||||
|
Log.e(K9.LOG_TAG, "Exception while upgrading database. Resetting the DB to v0");
|
||||||
|
db.setVersion(0);
|
||||||
|
throw new Error("Database upgrade failed! Resetting your DB version to 0 to force a full schema recreation.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db.setVersion(DB_VERSION);
|
||||||
|
|
||||||
|
db.setTransactionSuccessful();
|
||||||
|
} finally {
|
||||||
|
db.endTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (SQLiteException e) {
|
|
||||||
Log.e(K9.LOG_TAG, "Exception while upgrading database. Resetting the DB to v0");
|
|
||||||
db.setVersion(0);
|
|
||||||
throw new Error("Database upgrade failed! Resetting your DB version to 0 to force a full schema recreation.");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.setVersion(DB_VERSION);
|
|
||||||
|
|
||||||
if (db.getVersion() != DB_VERSION) {
|
if (db.getVersion() != DB_VERSION) {
|
||||||
throw new Error("Database upgrade failed!");
|
throw new Error("Database upgrade failed!");
|
||||||
}
|
}
|
||||||
@ -3496,10 +3499,8 @@ Log.v("ASH", mAccount.getDescription() + ":" + name + " is " + (localOnly == 1 ?
|
|||||||
|
|
||||||
if (!isSet(Flag.DELETED)) {
|
if (!isSet(Flag.DELETED)) {
|
||||||
|
|
||||||
if (flag == Flag.SEEN) {
|
if (flag == Flag.SEEN && set != isSet(Flag.SEEN)) {
|
||||||
if (set != isSet(Flag.SEEN)) {
|
folder.setUnreadMessageCount(folder.getUnreadMessageCount() + (set ? -1 : 1));
|
||||||
folder.setUnreadMessageCount(folder.getUnreadMessageCount() + (set ? -1 : 1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag == Flag.FLAGGED) {
|
if (flag == Flag.FLAGGED) {
|
||||||
|
@ -1996,11 +1996,6 @@ public class WebDavStore extends Store {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return super.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUidFromMessageId(Message message) throws MessagingException {
|
public String getUidFromMessageId(Message message) throws MessagingException {
|
||||||
Log.e(K9.LOG_TAG,
|
Log.e(K9.LOG_TAG,
|
||||||
|
@ -54,11 +54,8 @@ public class ImapUtility {
|
|||||||
for (String item : setItems) {
|
for (String item : setItems) {
|
||||||
if (item.indexOf(':') == -1) {
|
if (item.indexOf(':') == -1) {
|
||||||
// simple item
|
// simple item
|
||||||
try {
|
if (isNumberValid(item)) {
|
||||||
Integer.parseInt(item); // Don't need the value; just ensure it's valid
|
|
||||||
list.add(item);
|
list.add(item);
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
Log.d(K9.LOG_TAG, "Invalid UID value", e);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// range
|
// range
|
||||||
@ -91,23 +88,46 @@ public class ImapUtility {
|
|||||||
if (range != null) {
|
if (range != null) {
|
||||||
int colonPos = range.indexOf(':');
|
int colonPos = range.indexOf(':');
|
||||||
if (colonPos > 0) {
|
if (colonPos > 0) {
|
||||||
int first = Integer.parseInt(range.substring(0, colonPos));
|
long first = Long.parseLong(range.substring(0, colonPos));
|
||||||
int second = Integer.parseInt(range.substring(colonPos + 1));
|
long second = Long.parseLong(range.substring(colonPos + 1));
|
||||||
if (first < second) {
|
if (is32bitValue(first) && is32bitValue(second)) {
|
||||||
for (int i = first; i <= second; i++) {
|
if (first < second) {
|
||||||
list.add(Integer.toString(i));
|
for (long i = first; i <= second; i++) {
|
||||||
|
list.add(Long.toString(i));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (long i = first; i >= second; i--) {
|
||||||
|
list.add(Long.toString(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = first; i >= second; i--) {
|
Log.d(K9.LOG_TAG, "Invalid range: " + range);
|
||||||
list.add(Integer.toString(i));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
Log.d(K9.LOG_TAG, "Invalid range value", e);
|
Log.d(K9.LOG_TAG, "Invalid range value: " + range, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isNumberValid(String number) {
|
||||||
|
try {
|
||||||
|
long value = Long.parseLong(number);
|
||||||
|
if (is32bitValue(value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(K9.LOG_TAG, "Invalid UID value: " + number);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean is32bitValue(long value) {
|
||||||
|
return ((value & ~0xFFFFFFFFL) == 0L);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,6 @@ public class SmtpTransport extends Transport {
|
|||||||
String mPassword;
|
String mPassword;
|
||||||
String mAuthType;
|
String mAuthType;
|
||||||
int mConnectionSecurity;
|
int mConnectionSecurity;
|
||||||
boolean mSecure;
|
|
||||||
Socket mSocket;
|
Socket mSocket;
|
||||||
PeekableInputStream mIn;
|
PeekableInputStream mIn;
|
||||||
OutputStream mOut;
|
OutputStream mOut;
|
||||||
@ -245,7 +244,6 @@ public class SmtpTransport extends Transport {
|
|||||||
}, new SecureRandom());
|
}, new SecureRandom());
|
||||||
mSocket = sslContext.getSocketFactory().createSocket();
|
mSocket = sslContext.getSocketFactory().createSocket();
|
||||||
mSocket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
|
mSocket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
|
||||||
mSecure = true;
|
|
||||||
} else {
|
} else {
|
||||||
mSocket = new Socket();
|
mSocket = new Socket();
|
||||||
mSocket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
|
mSocket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
|
||||||
@ -308,7 +306,6 @@ public class SmtpTransport extends Transport {
|
|||||||
mIn = new PeekableInputStream(new BufferedInputStream(mSocket.getInputStream(),
|
mIn = new PeekableInputStream(new BufferedInputStream(mSocket.getInputStream(),
|
||||||
1024));
|
1024));
|
||||||
mOut = mSocket.getOutputStream();
|
mOut = mSocket.getOutputStream();
|
||||||
mSecure = true;
|
|
||||||
/*
|
/*
|
||||||
* Now resend the EHLO. Required by RFC2487 Sec. 5.2, and more specifically,
|
* Now resend the EHLO. Required by RFC2487 Sec. 5.2, and more specifically,
|
||||||
* Exim.
|
* Exim.
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.fsck.k9.view;
|
package com.fsck.k9.view;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
@ -24,6 +25,27 @@ public class MessageWebView extends WebView {
|
|||||||
*/
|
*/
|
||||||
public static final Method mGetBlockNetworkLoads = K9.getMethod(WebSettings.class, "setBlockNetworkLoads");
|
public static final Method mGetBlockNetworkLoads = K9.getMethod(WebSettings.class, "setBlockNetworkLoads");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the single column layout algorithm can be used on this version of Android.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Single column layout was broken on Android < 2.2 (see
|
||||||
|
* <a href="http://code.google.com/p/android/issues/detail?id=5024">issue 5024</a>).
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Android versions >= 3.0 have problems with unclickable links when single column layout is
|
||||||
|
* enabled (see
|
||||||
|
* <a href="http://code.google.com/p/android/issues/detail?id=34886">issue 34886</a>
|
||||||
|
* in Android's bug tracker, and
|
||||||
|
* <a href="http://code.google.com/p/k9mail/issues/detail?id=3820">issue 3820</a>
|
||||||
|
* in K-9 Mail's bug tracker).
|
||||||
|
*/
|
||||||
|
public static boolean isSingleColumnLayoutSupported() {
|
||||||
|
return (Build.VERSION.SDK_INT > 7 && Build.VERSION.SDK_INT < 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public MessageWebView(Context context) {
|
public MessageWebView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
@ -90,24 +112,13 @@ public class MessageWebView extends WebView {
|
|||||||
webSettings.setBuiltInZoomControls(true);
|
webSettings.setBuiltInZoomControls(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SINGLE_COLUMN layout was broken on Android < 2.2, so we
|
if (isSingleColumnLayoutSupported() && K9.mobileOptimizedLayout()) {
|
||||||
// administratively disable it
|
|
||||||
if (Build.VERSION.SDK_INT > 7 && K9.mobileOptimizedLayout()) {
|
|
||||||
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
|
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
|
||||||
} else {
|
} else {
|
||||||
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
|
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
disableOverscrolling();
|
||||||
* Build.VERSION.SDK is deprecated cause it just returns the
|
|
||||||
* "its raw String representation"
|
|
||||||
* http://developer.android.com/reference/android/os/Build.VERSION_CODES.html#GINGERBREAD
|
|
||||||
* http://developer.android.com/reference/android/os/Build.VERSION.html#SDK
|
|
||||||
*/
|
|
||||||
if (Build.VERSION.SDK_INT >= 9) {
|
|
||||||
setOverScrollMode(OVER_SCROLL_NEVER);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
webSettings.setTextSize(K9.getFontSizes().getMessageViewContent());
|
webSettings.setTextSize(K9.getFontSizes().getMessageViewContent());
|
||||||
|
|
||||||
@ -116,6 +127,13 @@ public class MessageWebView extends WebView {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TargetApi(9)
|
||||||
|
private void disableOverscrolling() {
|
||||||
|
if (Build.VERSION.SDK_INT >= 9) {
|
||||||
|
setOverScrollMode(OVER_SCROLL_NEVER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setText(String text, String contentType) {
|
public void setText(String text, String contentType) {
|
||||||
String content = text;
|
String content = text;
|
||||||
if (K9.getK9Theme() == K9.THEME_DARK) {
|
if (K9.getK9Theme() == K9.THEME_DARK) {
|
||||||
|
@ -104,6 +104,7 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
|||||||
private LinearLayout mInsideAttachmentsContainer;
|
private LinearLayout mInsideAttachmentsContainer;
|
||||||
private SavedState mSavedState;
|
private SavedState mSavedState;
|
||||||
private ClipboardManager mClipboardManager;
|
private ClipboardManager mClipboardManager;
|
||||||
|
private String mText;
|
||||||
|
|
||||||
|
|
||||||
public void initialize(Activity activity) {
|
public void initialize(Activity activity) {
|
||||||
@ -400,7 +401,10 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R.id.show_pictures: {
|
case R.id.show_pictures: {
|
||||||
|
// Allow network access first...
|
||||||
setLoadPictures(true);
|
setLoadPictures(true);
|
||||||
|
// ...then re-populate the WebView with the message text
|
||||||
|
loadBodyFromText(mText, "text/html");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -538,28 +542,20 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
|||||||
MessagingController controller, MessagingListener listener) throws MessagingException {
|
MessagingController controller, MessagingListener listener) throws MessagingException {
|
||||||
resetView();
|
resetView();
|
||||||
|
|
||||||
String type;
|
|
||||||
String text = null;
|
String text = null;
|
||||||
if (pgpData != null) {
|
if (pgpData != null) {
|
||||||
text = pgpData.getDecryptedData();
|
text = pgpData.getDecryptedData();
|
||||||
}
|
}
|
||||||
if (text != null) {
|
if (text != null) {
|
||||||
type = "text/html";
|
|
||||||
text = "<html><body><pre>" + text + "</pre></body></html>";
|
text = "<html><body><pre>" + text + "</pre></body></html>";
|
||||||
} else {
|
} else {
|
||||||
// getTextForDisplay() always returns HTML-ified content.
|
// getTextForDisplay() always returns HTML-ified content.
|
||||||
text = message.getTextForDisplay();
|
text = message.getTextForDisplay();
|
||||||
type = "text/html";
|
|
||||||
}
|
|
||||||
if (text != null) {
|
|
||||||
final String emailText = text;
|
|
||||||
final String contentType = type;
|
|
||||||
loadBodyFromText(emailText, contentType);
|
|
||||||
updateCryptoLayout(account.getCryptoProvider(), pgpData, message);
|
|
||||||
} else {
|
|
||||||
showStatusMessage(getContext().getString(R.string.webview_empty_message));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save the text so we can reset the WebView when the user clicks the "Show pictures" button
|
||||||
|
mText = text;
|
||||||
|
|
||||||
mHasAttachments = message.hasAttachments();
|
mHasAttachments = message.hasAttachments();
|
||||||
|
|
||||||
if (mHasAttachments) {
|
if (mHasAttachments) {
|
||||||
@ -607,6 +603,13 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (text != null) {
|
||||||
|
loadBodyFromText(text, "text/html");
|
||||||
|
updateCryptoLayout(account.getCryptoProvider(), pgpData, message);
|
||||||
|
} else {
|
||||||
|
showStatusMessage(getContext().getString(R.string.webview_empty_message));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showStatusMessage(String status) {
|
public void showStatusMessage(String status) {
|
||||||
|
@ -34,6 +34,14 @@ public class ImapUtilityTest extends TestCase {
|
|||||||
actual = ImapUtility.getImapSequenceValues("1");
|
actual = ImapUtility.getImapSequenceValues("1");
|
||||||
MoreAsserts.assertEquals(expected, actual.toArray());
|
MoreAsserts.assertEquals(expected, actual.toArray());
|
||||||
|
|
||||||
|
expected = new String[] {"2147483648"}; // Integer.MAX_VALUE + 1
|
||||||
|
actual = ImapUtility.getImapSequenceValues("2147483648");
|
||||||
|
MoreAsserts.assertEquals(expected, actual.toArray());
|
||||||
|
|
||||||
|
expected = new String[] {"4294967295"}; // 2^32 - 1
|
||||||
|
actual = ImapUtility.getImapSequenceValues("4294967295");
|
||||||
|
MoreAsserts.assertEquals(expected, actual.toArray());
|
||||||
|
|
||||||
expected = new String[] {"1", "3", "2"};
|
expected = new String[] {"1", "3", "2"};
|
||||||
actual = ImapUtility.getImapSequenceValues("1,3,2");
|
actual = ImapUtility.getImapSequenceValues("1,3,2");
|
||||||
MoreAsserts.assertEquals(expected, actual.toArray());
|
MoreAsserts.assertEquals(expected, actual.toArray());
|
||||||
@ -50,6 +58,11 @@ public class ImapUtilityTest extends TestCase {
|
|||||||
actual = ImapUtility.getImapSequenceValues("1,2:4,9:7");
|
actual = ImapUtility.getImapSequenceValues("1,2:4,9:7");
|
||||||
MoreAsserts.assertEquals(expected, actual.toArray());
|
MoreAsserts.assertEquals(expected, actual.toArray());
|
||||||
|
|
||||||
|
// Test numbers larger than Integer.MAX_VALUE (2147483647)
|
||||||
|
expected = new String[] {"2147483646", "2147483647", "2147483648"};
|
||||||
|
actual = ImapUtility.getImapSequenceValues("2147483646:2147483648");
|
||||||
|
MoreAsserts.assertEquals(expected, actual.toArray());
|
||||||
|
|
||||||
// Test partially invalid sets
|
// Test partially invalid sets
|
||||||
expected = new String[] { "1", "5" };
|
expected = new String[] { "1", "5" };
|
||||||
actual = ImapUtility.getImapSequenceValues("1,x,5");
|
actual = ImapUtility.getImapSequenceValues("1,x,5");
|
||||||
@ -75,6 +88,15 @@ public class ImapUtilityTest extends TestCase {
|
|||||||
expected = new String[0];
|
expected = new String[0];
|
||||||
actual = ImapUtility.getImapSequenceValues("1:x");
|
actual = ImapUtility.getImapSequenceValues("1:x");
|
||||||
MoreAsserts.assertEquals(expected, actual.toArray());
|
MoreAsserts.assertEquals(expected, actual.toArray());
|
||||||
|
|
||||||
|
// Test values larger than 2^32 - 1
|
||||||
|
expected = new String[0];
|
||||||
|
actual = ImapUtility.getImapSequenceValues("4294967296:4294967297");
|
||||||
|
MoreAsserts.assertEquals(expected, actual.toArray());
|
||||||
|
|
||||||
|
expected = new String[0];
|
||||||
|
actual = ImapUtility.getImapSequenceValues("4294967296"); // 2^32
|
||||||
|
MoreAsserts.assertEquals(expected, actual.toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user