mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-16 22:45:04 -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"?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionCode="15019"
|
||||
android:versionName="4.120" package="com.fsck.k9"
|
||||
android:versionCode="15020"
|
||||
android:versionName="4.121" package="com.fsck.k9"
|
||||
>
|
||||
<uses-sdk
|
||||
android:minSdkVersion="7"
|
||||
|
@ -502,6 +502,7 @@
|
||||
<item>dark</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Note: If you change this make sure the code in Prefs.java is still working -->
|
||||
<string-array name="background_ops_entries">
|
||||
<item>@string/background_ops_enabled</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_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_only">When \'Auto-sync\' is checked</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.view.ColorChip;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
|
@ -10,7 +10,6 @@ import java.util.Map;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
import com.fsck.k9.preferences.Editor;
|
||||
import com.fsck.k9.preferences.Storage;
|
||||
@ -155,14 +154,6 @@ public class Preferences {
|
||||
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() {
|
||||
return mStorage;
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ import java.util.List;
|
||||
|
||||
public class ChooseIdentity extends K9ListActivity {
|
||||
Account mAccount;
|
||||
String mUID;
|
||||
ArrayAdapter<String> adapter;
|
||||
|
||||
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.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.*;
|
||||
@ -1099,10 +1098,6 @@ public class FolderList extends K9ListActivity {
|
||||
if (account.equals(mAccount)) {
|
||||
|
||||
mHandler.progress(false);
|
||||
|
||||
if (Config.LOGV) {
|
||||
Log.v(K9.LOG_TAG, "listFoldersFailed " + message);
|
||||
}
|
||||
}
|
||||
super.listFoldersFailed(account, message);
|
||||
}
|
||||
|
@ -3432,11 +3432,9 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
||||
static class IdentityAdapter extends BaseAdapter {
|
||||
private LayoutInflater mLayoutInflater;
|
||||
private List<Object> mItems;
|
||||
private FontSizes mFontSizes;
|
||||
|
||||
public IdentityAdapter(Context context, LayoutInflater layoutInflater) {
|
||||
mLayoutInflater = layoutInflater;
|
||||
mFontSizes = K9.getFontSizes();
|
||||
|
||||
List<Object> items = new ArrayList<Object>();
|
||||
Preferences prefs = Preferences.getPreferences(context.getApplicationContext());
|
||||
|
@ -54,12 +54,10 @@ import android.widget.Toast;
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.Account.SortType;
|
||||
import com.fsck.k9.AccountStats;
|
||||
import com.fsck.k9.BaseAccount;
|
||||
import com.fsck.k9.FontSizes;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.Preferences;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.SearchAccount;
|
||||
import com.fsck.k9.SearchSpecification;
|
||||
import com.fsck.k9.activity.setup.AccountSettings;
|
||||
import com.fsck.k9.activity.setup.FolderSettings;
|
||||
@ -272,8 +270,6 @@ public class MessageList
|
||||
private Account mAccount;
|
||||
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
|
||||
* after load.
|
||||
@ -364,13 +360,13 @@ public class MessageList
|
||||
@Override
|
||||
public void run() {
|
||||
for (MessageInfoHolder message : messages) {
|
||||
if (message != null) {
|
||||
if (mFolderName == null || (message.folder != null && message.folder.name.equals(mFolderName))) {
|
||||
if (message.selected && mSelectedCount > 0) {
|
||||
mSelectedCount--;
|
||||
}
|
||||
mAdapter.messages.remove(message);
|
||||
if (message != null && (mFolderName == null || (
|
||||
message.folder != null &&
|
||||
message.folder.name.equals(mFolderName)))) {
|
||||
if (message.selected && mSelectedCount > 0) {
|
||||
mSelectedCount--;
|
||||
}
|
||||
mAdapter.messages.remove(message);
|
||||
}
|
||||
}
|
||||
resetUnreadCountOnThread();
|
||||
|
@ -6,6 +6,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Vibrator;
|
||||
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_INCOMING = "incoming_prefs";
|
||||
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_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.setChecked(mAccount.goToUnreadMessageSearch());
|
||||
|
||||
mNotificationUnreadCount = (CheckBoxPreference)findPreference(PREFERENCE_NOTIFICATION_UNREAD_COUNT);
|
||||
mNotificationUnreadCount.setChecked(mAccount.isNotificationShowsUnreadCount());
|
||||
CheckBoxPreference notificationUnreadCount =
|
||||
(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();
|
||||
|
||||
@ -699,7 +716,9 @@ public class AccountSettings extends K9PreferenceActivity {
|
||||
mAccount.getNotificationSetting().setVibrateTimes(Integer.parseInt(mAccountVibrateTimes.getValue()));
|
||||
mAccount.getNotificationSetting().setLed(mAccountLed.isChecked());
|
||||
mAccount.setGoToUnreadMessageSearch(mNotificationOpensUnread.isChecked());
|
||||
mAccount.setNotificationShowsUnreadCount(mNotificationUnreadCount.isChecked());
|
||||
if (mNotificationUnreadCount != null) {
|
||||
mAccount.setNotificationShowsUnreadCount(mNotificationUnreadCount.isChecked());
|
||||
}
|
||||
mAccount.setFolderTargetMode(Account.FolderMode.valueOf(mTargetMode.getValue()));
|
||||
Log.d("ASH", "Setting delete policy to " + 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)) {
|
||||
//TODO: localize this string
|
||||
altNamesText.append("Subject(alt): ").append(name).append(",...\n");
|
||||
} else if (name.startsWith("*.")) {
|
||||
if (storeURIHost.endsWith(name.substring(2)) || transportURIHost.endsWith(name.substring(2))) {
|
||||
//TODO: localize this string
|
||||
altNamesText.append("Subject(alt): ").append(name).append(",...\n");
|
||||
}
|
||||
} else if (name.startsWith("*.") && (
|
||||
storeURIHost.endsWith(name.substring(2)) ||
|
||||
transportURIHost.endsWith(name.substring(2)))) {
|
||||
//TODO: localize this string
|
||||
altNamesText.append("Subject(alt): ").append(name).append(",...\n");
|
||||
}
|
||||
}
|
||||
chainInfo.append(altNamesText);
|
||||
|
@ -33,6 +33,7 @@ import com.fsck.k9.preferences.CheckBoxListPreference;
|
||||
import com.fsck.k9.preferences.TimePickerPreference;
|
||||
|
||||
import com.fsck.k9.service.MailService;
|
||||
import com.fsck.k9.view.MessageWebView;
|
||||
|
||||
|
||||
public class Prefs extends K9PreferenceActivity {
|
||||
@ -284,13 +285,13 @@ public class Prefs extends K9PreferenceActivity {
|
||||
mZoomControlsEnabled.setChecked(K9.zoomControlsEnabled());
|
||||
|
||||
mMobileOptimizedLayout = (CheckBoxPreference) findPreference(PREFERENCE_MESSAGEVIEW_MOBILE_LAYOUT);
|
||||
if (Build.VERSION.SDK_INT <= 7) {
|
||||
if (!MessageWebView.isSingleColumnLayoutSupported()) {
|
||||
mMobileOptimizedLayout.setEnabled(false);
|
||||
mMobileOptimizedLayout.setChecked(false);
|
||||
} else {
|
||||
mMobileOptimizedLayout.setChecked(K9.mobileOptimizedLayout());
|
||||
}
|
||||
|
||||
|
||||
mMobileOptimizedLayout.setChecked(K9.mobileOptimizedLayout());
|
||||
|
||||
mQuietTimeEnabled = (CheckBoxPreference) findPreference(PREFERENCE_QUIET_TIME_ENABLED);
|
||||
mQuietTimeEnabled.setChecked(K9.getQuietTimeEnabled());
|
||||
|
||||
@ -320,6 +321,33 @@ public class Prefs extends K9PreferenceActivity {
|
||||
|
||||
|
||||
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.setChecked(K9.useGalleryBugWorkaround());
|
||||
@ -359,7 +387,7 @@ public class Prefs extends K9PreferenceActivity {
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
mBatchButtonsMarkRead = (CheckBoxPreference)findPreference(PREFERENCE_BATCH_BUTTONS_MARK_READ);
|
||||
mBatchButtonsDelete = (CheckBoxPreference)findPreference(PREFERENCE_BATCH_BUTTONS_DELETE);
|
||||
mBatchButtonsArchive = (CheckBoxPreference)findPreference(PREFERENCE_BATCH_BUTTONS_ARCHIVE);
|
||||
|
@ -21,6 +21,7 @@ import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.PowerManager;
|
||||
import android.os.Process;
|
||||
import android.text.TextUtils;
|
||||
@ -534,9 +535,6 @@ public class MessagingController implements Runnable {
|
||||
List<Message> pendingMessages = new ArrayList<Message>();
|
||||
|
||||
|
||||
int totalDone = 0;
|
||||
|
||||
|
||||
@Override
|
||||
public void messageStarted(String message, int number, int ofTotal) {}
|
||||
@Override
|
||||
@ -544,7 +542,6 @@ public class MessagingController implements Runnable {
|
||||
|
||||
if (!isMessageSuppressed(account, folder, message)) {
|
||||
pendingMessages.add(message);
|
||||
totalDone++;
|
||||
if (pendingMessages.size() > 10) {
|
||||
addPendingMessages();
|
||||
}
|
||||
@ -2317,13 +2314,14 @@ public class MessagingController implements Runnable {
|
||||
* upto speed with the remote UIDs of remote destionation folder.
|
||||
*/
|
||||
if (!localUidMap.isEmpty() && remoteUidMap != null && !remoteUidMap.isEmpty()) {
|
||||
Set<String> remoteSrcUids = remoteUidMap.keySet();
|
||||
Iterator<String> remoteSrcUidsIterator = remoteSrcUids.iterator();
|
||||
Set<Map.Entry<String, String>> remoteSrcEntries = remoteUidMap.entrySet();
|
||||
Iterator<Map.Entry<String, String>> remoteSrcEntriesIterator = remoteSrcEntries.iterator();
|
||||
|
||||
while (remoteSrcUidsIterator.hasNext()) {
|
||||
String remoteSrcUid = remoteSrcUidsIterator.next();
|
||||
while (remoteSrcEntriesIterator.hasNext()) {
|
||||
Map.Entry<String, String> entry = remoteSrcEntriesIterator.next();
|
||||
String remoteSrcUid = entry.getKey();
|
||||
String localDestUid = localUidMap.get(remoteSrcUid);
|
||||
String newUid = remoteUidMap.get(remoteSrcUid);
|
||||
String newUid = entry.getValue();
|
||||
|
||||
Message localDestMessage = localDestFolder.getMessage(localDestUid);
|
||||
if (localDestMessage != null) {
|
||||
@ -3433,7 +3431,6 @@ public class MessagingController implements Runnable {
|
||||
// "don't even bother" functionality
|
||||
if (getRootCauseMessage(e).startsWith("5")) {
|
||||
localFolder.moveMessages(new Message[] { message }, (LocalFolder) localStore.getFolder(account.getDraftsFolderName()));
|
||||
} else {
|
||||
}
|
||||
|
||||
message.setFlag(Flag.X_SEND_FAILED, true);
|
||||
@ -4562,7 +4559,10 @@ public class MessagingController implements Runnable {
|
||||
builder.setTicker(messageNotice);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.fsck.k9.helper;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.ClipData;
|
||||
import android.content.Context;
|
||||
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
|
||||
*/
|
||||
@TargetApi(11)
|
||||
public class ClipboardManagerApi11 extends com.fsck.k9.helper.ClipboardManager {
|
||||
|
||||
public ClipboardManagerApi11(Context context) {
|
||||
|
@ -124,16 +124,14 @@ public class DomainNameChecker {
|
||||
List<?> altNameEntry = (List<?>)(subjectAltName);
|
||||
if ((altNameEntry != null) && (2 <= altNameEntry.size())) {
|
||||
Integer altNameType = (Integer)(altNameEntry.get(0));
|
||||
if (altNameType != null) {
|
||||
if (altNameType == ALT_IPA_NAME) {
|
||||
String altName = (String)(altNameEntry.get(1));
|
||||
if (altName != null) {
|
||||
if (K9.DEBUG) {
|
||||
Log.v(K9.LOG_TAG, "alternative IP: " + altName);
|
||||
}
|
||||
if (thisDomain.equalsIgnoreCase(altName)) {
|
||||
return true;
|
||||
}
|
||||
if (altNameType != null && altNameType.intValue() == ALT_IPA_NAME) {
|
||||
String altName = (String)(altNameEntry.get(1));
|
||||
if (altName != null) {
|
||||
if (K9.DEBUG) {
|
||||
Log.v(K9.LOG_TAG, "alternative IP: " + altName);
|
||||
}
|
||||
if (thisDomain.equalsIgnoreCase(altName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -166,15 +164,11 @@ public class DomainNameChecker {
|
||||
List<?> altNameEntry = (List<?>)(i.next());
|
||||
if ((altNameEntry != null) && (2 <= altNameEntry.size())) {
|
||||
Integer altNameType = (Integer)(altNameEntry.get(0));
|
||||
if (altNameType != null) {
|
||||
if (altNameType.intValue() == ALT_DNS_NAME) {
|
||||
hasDns = true;
|
||||
String altName = (String)(altNameEntry.get(1));
|
||||
if (altName != null) {
|
||||
if (matchDns(thisDomain, altName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (altNameType != null && altNameType.intValue() == ALT_DNS_NAME) {
|
||||
hasDns = true;
|
||||
String altName = (String)(altNameEntry.get(1));
|
||||
if (altName != null && matchDns(thisDomain, altName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.fsck.k9.helper;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
@ -9,6 +10,7 @@ import android.net.Uri;
|
||||
/**
|
||||
* Create notifications using the new {@link android.app.Notification.Builder} class.
|
||||
*/
|
||||
@TargetApi(11)
|
||||
public class NotificationBuilderApi11 extends NotificationBuilder {
|
||||
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) {
|
||||
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 && c != 0x09) { // non LF/CR/TAB
|
||||
return true;
|
||||
}
|
||||
if ((c < 0x20 || 0x7e < c) && // non printable
|
||||
(c != 0x0a && c != 0x0d && c != 0x09)) { // non LF/CR/TAB
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -384,6 +384,10 @@ public class ImapResponseParser {
|
||||
return (String)get(index);
|
||||
}
|
||||
|
||||
public long getLong(int index) {
|
||||
return Long.parseLong(getString(index));
|
||||
}
|
||||
|
||||
public int getNumber(int index) {
|
||||
return Integer.parseInt(getString(index));
|
||||
}
|
||||
|
@ -843,12 +843,12 @@ public class ImapStore extends Store {
|
||||
class ImapFolder extends Folder {
|
||||
private String mName;
|
||||
protected volatile int mMessageCount = -1;
|
||||
protected volatile int uidNext = -1;
|
||||
protected volatile long uidNext = -1L;
|
||||
protected volatile ImapConnection mConnection;
|
||||
private OpenMode mMode;
|
||||
private volatile boolean mExists;
|
||||
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) {
|
||||
@ -1350,7 +1350,7 @@ public class ImapStore extends Store {
|
||||
return getRemoteMessageCount("FLAGGED NOT DELETED");
|
||||
}
|
||||
|
||||
protected int getHighestUid() {
|
||||
protected long getHighestUid() {
|
||||
try {
|
||||
ImapSearcher searcher = new ImapSearcher() {
|
||||
public List<ImapResponse> search() throws IOException, MessagingException {
|
||||
@ -1359,12 +1359,12 @@ public class ImapStore extends Store {
|
||||
};
|
||||
Message[] messages = search(searcher, null);
|
||||
if (messages.length > 0) {
|
||||
return Integer.parseInt(messages[0].getUid());
|
||||
return Long.parseLong(messages[0].getUid());
|
||||
}
|
||||
} catch (Exception 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);
|
||||
|
||||
}
|
||||
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 {
|
||||
ImapSearcher searcher = new ImapSearcher() {
|
||||
public List<ImapResponse> search() throws IOException, MessagingException {
|
||||
@ -1429,13 +1429,13 @@ public class ImapStore extends Store {
|
||||
checkOpen();
|
||||
ArrayList<Message> messages = new ArrayList<Message>();
|
||||
try {
|
||||
ArrayList<Integer> uids = new ArrayList<Integer>();
|
||||
ArrayList<Long> uids = new ArrayList<Long>();
|
||||
List<ImapResponse> responses = searcher.search(); //
|
||||
for (ImapResponse response : responses) {
|
||||
if (response.mTag == null) {
|
||||
if (ImapResponseParser.equalsIgnoreCase(response.get(0), "SEARCH")) {
|
||||
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
|
||||
Collections.sort(uids);
|
||||
for (int i = 0, count = uids.size(); i < count; i++) {
|
||||
String uid = uids.get(i).toString();
|
||||
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);
|
||||
if (listener != null) {
|
||||
listener.messageFinished(message, i, count);
|
||||
@ -1571,7 +1572,7 @@ public class ImapStore extends Store {
|
||||
if (response.mTag == null && ImapResponseParser.equalsIgnoreCase(response.get(1), "FETCH")) {
|
||||
ImapList fetchList = (ImapList)response.getKeyedValue("FETCH");
|
||||
String uid = fetchList.getKeyedString("UID");
|
||||
int msgSeq = response.getNumber(0);
|
||||
long msgSeq = response.getLong(0);
|
||||
if (uid != null) {
|
||||
try {
|
||||
msgSeqUidMap.put(msgSeq, uid);
|
||||
@ -1798,7 +1799,7 @@ public class ImapStore extends Store {
|
||||
if (keyObj instanceof String) {
|
||||
String key = (String)keyObj;
|
||||
if ("UIDNEXT".equalsIgnoreCase(key)) {
|
||||
uidNext = bracketed.getNumber(1);
|
||||
uidNext = bracketed.getLong(1);
|
||||
if (K9.DEBUG)
|
||||
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) {
|
||||
try {
|
||||
String messageUidS = message.getUid();
|
||||
int messageUid = Integer.parseInt(messageUidS);
|
||||
long messageUid = Long.parseLong(messageUidS);
|
||||
ImapPushState oldPushState = ImapPushState.parse(oldPushStateS);
|
||||
if (messageUid >= oldPushState.uidNext) {
|
||||
int uidNext = messageUid + 1;
|
||||
long uidNext = messageUid + 1;
|
||||
ImapPushState newPushState = new ImapPushState(uidNext);
|
||||
return newPushState.toString();
|
||||
} else {
|
||||
@ -2303,21 +2304,19 @@ public class ImapStore extends Store {
|
||||
capabilityList = response;
|
||||
}
|
||||
|
||||
if (capabilityList != null) {
|
||||
if (!capabilityList.isEmpty() && ImapResponseParser.equalsIgnoreCase(capabilityList.get(0), CAPABILITY_CAPABILITY)) {
|
||||
if (K9.DEBUG) {
|
||||
Log.d(K9.LOG_TAG, "Saving " + capabilityList.size() + " capabilities for " + getLogId());
|
||||
if (capabilityList != null && !capabilityList.isEmpty() &&
|
||||
ImapResponseParser.equalsIgnoreCase(capabilityList.get(0), CAPABILITY_CAPABILITY)) {
|
||||
if (K9.DEBUG) {
|
||||
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()) {
|
||||
try {
|
||||
int oldUidNext = -1;
|
||||
long oldUidNext = -1L;
|
||||
try {
|
||||
String pushStateS = receiver.getPushState(getName());
|
||||
ImapPushState pushState = ImapPushState.parse(pushStateS);
|
||||
@ -2922,16 +2921,16 @@ public class ImapStore extends Store {
|
||||
if (stop.get()) {
|
||||
continue;
|
||||
}
|
||||
int startUid = oldUidNext;
|
||||
long startUid = oldUidNext;
|
||||
|
||||
int newUidNext = uidNext;
|
||||
long newUidNext = uidNext;
|
||||
|
||||
if (newUidNext == -1) {
|
||||
if (K9.DEBUG) {
|
||||
Log.d(K9.LOG_TAG, "uidNext is -1, using search to find highest UID");
|
||||
}
|
||||
int highestUid = getHighestUid();
|
||||
if (highestUid != -1) {
|
||||
long highestUid = getHighestUid();
|
||||
if (highestUid != -1L) {
|
||||
if (K9.DEBUG)
|
||||
Log.d(K9.LOG_TAG, "highest UID = " + highestUid);
|
||||
newUidNext = highestUid + 1;
|
||||
@ -2952,7 +2951,7 @@ public class ImapStore extends Store {
|
||||
if (K9.DEBUG)
|
||||
Log.i(K9.LOG_TAG, "Needs sync from uid " + startUid + " to " + newUidNext + " for " + getLogId());
|
||||
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);
|
||||
messages.add(message);
|
||||
}
|
||||
@ -3052,7 +3051,7 @@ public class ImapStore extends Store {
|
||||
if (oldMessageCount == -1) {
|
||||
skipSync = true;
|
||||
}
|
||||
List<Integer> flagSyncMsgSeqs = new ArrayList<Integer>();
|
||||
List<Long> flagSyncMsgSeqs = new ArrayList<Long>();
|
||||
List<String> removeMsgUids = new LinkedList<String>();
|
||||
|
||||
for (ImapResponse response : responses) {
|
||||
@ -3078,7 +3077,7 @@ public class ImapStore extends Store {
|
||||
}
|
||||
|
||||
private void syncMessages(int end, boolean newArrivals) throws MessagingException {
|
||||
int oldUidNext = -1;
|
||||
long oldUidNext = -1L;
|
||||
try {
|
||||
String pushStateS = receiver.getPushState(getName());
|
||||
ImapPushState pushState = ImapPushState.parse(pushStateS);
|
||||
@ -3091,10 +3090,10 @@ public class ImapStore extends Store {
|
||||
|
||||
Message[] messageArray = getMessages(end, end, null, true, null);
|
||||
if (messageArray != null && messageArray.length > 0) {
|
||||
int newUid = Integer.parseInt(messageArray[0].getUid());
|
||||
long newUid = Long.parseLong(messageArray[0].getUid());
|
||||
if (K9.DEBUG)
|
||||
Log.i(K9.LOG_TAG, "Got newUid " + newUid + " for message " + end + " on " + getLogId());
|
||||
int startUid = oldUidNext;
|
||||
long startUid = oldUidNext;
|
||||
if (startUid < newUid - 10) {
|
||||
startUid = newUid - 10;
|
||||
}
|
||||
@ -3106,8 +3105,8 @@ public class ImapStore extends Store {
|
||||
if (K9.DEBUG)
|
||||
Log.i(K9.LOG_TAG, "Needs sync from uid " + startUid + " to " + newUid + " for " + getLogId());
|
||||
List<Message> messages = new ArrayList<Message>();
|
||||
for (int uid = startUid; uid <= newUid; uid++) {
|
||||
ImapMessage message = new ImapMessage("" + uid, ImapFolderPusher.this);
|
||||
for (long uid = startUid; uid <= newUid; uid++) {
|
||||
ImapMessage message = new ImapMessage(Long.toString(uid), ImapFolderPusher.this);
|
||||
messages.add(message);
|
||||
}
|
||||
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 {
|
||||
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);
|
||||
int messageCountDelta = 0;
|
||||
if (response.mTag == null && response.size() > 1) {
|
||||
@ -3168,7 +3167,7 @@ public class ImapStore extends Store {
|
||||
Object responseType = response.get(1);
|
||||
if (ImapResponseParser.equalsIgnoreCase(responseType, "FETCH")) {
|
||||
Log.i(K9.LOG_TAG, "Got FETCH " + response);
|
||||
int msgSeq = response.getNumber(0);
|
||||
long msgSeq = response.getLong(0);
|
||||
|
||||
if (K9.DEBUG)
|
||||
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")) {
|
||||
int msgSeq = response.getNumber(0);
|
||||
long msgSeq = response.getLong(0);
|
||||
if (msgSeq <= oldMessageCount) {
|
||||
messageCountDelta = -1;
|
||||
}
|
||||
if (K9.DEBUG)
|
||||
Log.d(K9.LOG_TAG, "Got untagged EXPUNGE for msgseq " + msgSeq + " for " + getLogId());
|
||||
|
||||
List<Integer> newSeqs = new ArrayList<Integer>();
|
||||
Iterator<Integer> flagIter = flagSyncMsgSeqs.iterator();
|
||||
List<Long> newSeqs = new ArrayList<Long>();
|
||||
Iterator<Long> flagIter = flagSyncMsgSeqs.iterator();
|
||||
while (flagIter.hasNext()) {
|
||||
Integer flagMsg = flagIter.next();
|
||||
long flagMsg = flagIter.next();
|
||||
if (flagMsg >= msgSeq) {
|
||||
flagIter.remove();
|
||||
if (flagMsg > msgSeq) {
|
||||
@ -3199,14 +3198,13 @@ public class ImapStore extends Store {
|
||||
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
|
||||
|
||||
for (Integer msgSeqNumI : msgSeqs) {
|
||||
for (long msgSeqNum : msgSeqs) {
|
||||
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) {
|
||||
String uid = msgSeqUidMap.get(msgSeqNum);
|
||||
if (K9.DEBUG) {
|
||||
@ -3388,12 +3386,12 @@ public class ImapStore extends Store {
|
||||
}
|
||||
|
||||
protected static class ImapPushState {
|
||||
protected int uidNext;
|
||||
protected ImapPushState(int nUidNext) {
|
||||
protected long uidNext;
|
||||
protected ImapPushState(long nUidNext) {
|
||||
uidNext = nUidNext;
|
||||
}
|
||||
protected static ImapPushState parse(String pushState) {
|
||||
int newUidNext = -1;
|
||||
long newUidNext = -1L;
|
||||
if (pushState != null) {
|
||||
StringTokenizer tokenizer = new StringTokenizer(pushState, ";");
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
@ -3404,8 +3402,8 @@ public class ImapStore extends Store {
|
||||
if ("uidNext".equalsIgnoreCase(key) && thisState.hasMoreTokens()) {
|
||||
String value = thisState.nextToken();
|
||||
try {
|
||||
newUidNext = Integer.parseInt(value);
|
||||
} catch (Exception e) {
|
||||
newUidNext = Long.parseLong(value);
|
||||
} catch (NumberFormatException 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);
|
||||
|
||||
db.beginTransaction();
|
||||
try {
|
||||
// schema version 29 was when we moved to incremental updates
|
||||
// in the case of a new db or a < v29 db, we blow away and start from scratch
|
||||
if (db.getVersion() < 29) {
|
||||
try {
|
||||
// schema version 29 was when we moved to incremental updates
|
||||
// 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("CREATE TABLE folders (id INTEGER PRIMARY KEY, name TEXT, "
|
||||
+ "last_updated INTEGER, unread_count INTEGER, visible_limit INTEGER, status TEXT, "
|
||||
+ "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, "
|
||||
+ "local_only INTEGER default 0)");
|
||||
db.execSQL("DROP TABLE IF EXISTS folders");
|
||||
db.execSQL("CREATE TABLE folders (id INTEGER PRIMARY KEY, name TEXT, "
|
||||
+ "last_updated INTEGER, unread_count INTEGER, visible_limit INTEGER, status TEXT, "
|
||||
+ "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, "
|
||||
+ "local_only INTEGER default 0)");
|
||||
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS folder_name ON folders (name)");
|
||||
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, "
|
||||
+ "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, "
|
||||
+ "mime_type TEXT)");
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS folder_name ON folders (name)");
|
||||
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, "
|
||||
+ "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, "
|
||||
+ "mime_type TEXT)");
|
||||
|
||||
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 INDEX IF NOT EXISTS header_folder ON headers (message_id)");
|
||||
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 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("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("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_date");
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS msg_folder_id_deleted_date ON messages (folder_id,deleted,internal_date)");
|
||||
}
|
||||
if (db.getVersion() < 32) {
|
||||
db.execSQL("UPDATE messages SET deleted = 1 WHERE flags LIKE '%DELETED%'");
|
||||
}
|
||||
if (db.getVersion() < 33) {
|
||||
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)");
|
||||
|
||||
try {
|
||||
db.execSQL("ALTER TABLE messages ADD preview TEXT");
|
||||
} catch (SQLiteException e) {
|
||||
if (! e.toString().startsWith("duplicate column name: preview")) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
db.execSQL("DROP TABLE IF EXISTS pending_commands");
|
||||
db.execSQL("CREATE TABLE pending_commands " +
|
||||
"(id INTEGER PRIMARY KEY, command TEXT, arguments TEXT)");
|
||||
|
||||
}
|
||||
if (db.getVersion() < 34) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
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;");
|
||||
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
// 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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
catch (SQLiteException e) {
|
||||
Log.e(K9.LOG_TAG, "Exception while upgrading database to v41. folder classes may have vanished", e);
|
||||
|
||||
} finally {
|
||||
Utility.closeQuietly(cursor);
|
||||
if (db.getVersion() < 31) {
|
||||
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)");
|
||||
}
|
||||
}
|
||||
if (db.getVersion() == 41) {
|
||||
try {
|
||||
long startTime = System.currentTimeMillis();
|
||||
SharedPreferences.Editor editor = getPreferences().edit();
|
||||
if (db.getVersion() < 32) {
|
||||
db.execSQL("UPDATE messages SET deleted = 1 WHERE flags LIKE '%DELETED%'");
|
||||
}
|
||||
if (db.getVersion() < 33) {
|
||||
|
||||
List <? extends Folder > folders = getPersonalNamespaces(true);
|
||||
for (Folder folder : folders) {
|
||||
if (folder instanceof LocalFolder) {
|
||||
LocalFolder lFolder = (LocalFolder)folder;
|
||||
lFolder.save(editor);
|
||||
try {
|
||||
db.execSQL("ALTER TABLE messages ADD preview TEXT");
|
||||
} catch (SQLiteException e) {
|
||||
if (! e.toString().startsWith("duplicate column name: preview")) {
|
||||
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() < 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);
|
||||
if (db.getVersion() < 34) {
|
||||
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
|
||||
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) {
|
||||
// ... 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);
|
||||
catch (SQLiteException e) {
|
||||
Log.e(K9.LOG_TAG, "Exception while upgrading database to v41. folder classes may have vanished", e);
|
||||
|
||||
} finally {
|
||||
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
|
||||
obsoleteOutbox.delete();
|
||||
obsoleteOutbox.delete(true);
|
||||
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() < 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) {
|
||||
@ -410,19 +413,19 @@ Log.d("ASH", "updatedb " + mAccount.getDescription());
|
||||
+ 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) {
|
||||
throw new Error("Database upgrade failed!");
|
||||
}
|
||||
@ -3496,10 +3499,8 @@ Log.v("ASH", mAccount.getDescription() + ":" + name + " is " + (localOnly == 1 ?
|
||||
|
||||
if (!isSet(Flag.DELETED)) {
|
||||
|
||||
if (flag == Flag.SEEN) {
|
||||
if (set != isSet(Flag.SEEN)) {
|
||||
folder.setUnreadMessageCount(folder.getUnreadMessageCount() + (set ? -1 : 1));
|
||||
}
|
||||
if (flag == Flag.SEEN && set != isSet(Flag.SEEN)) {
|
||||
folder.setUnreadMessageCount(folder.getUnreadMessageCount() + (set ? -1 : 1));
|
||||
}
|
||||
|
||||
if (flag == Flag.FLAGGED) {
|
||||
|
@ -1996,11 +1996,6 @@ public class WebDavStore extends Store {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUidFromMessageId(Message message) throws MessagingException {
|
||||
Log.e(K9.LOG_TAG,
|
||||
|
@ -54,11 +54,8 @@ public class ImapUtility {
|
||||
for (String item : setItems) {
|
||||
if (item.indexOf(':') == -1) {
|
||||
// simple item
|
||||
try {
|
||||
Integer.parseInt(item); // Don't need the value; just ensure it's valid
|
||||
if (isNumberValid(item)) {
|
||||
list.add(item);
|
||||
} catch (NumberFormatException e) {
|
||||
Log.d(K9.LOG_TAG, "Invalid UID value", e);
|
||||
}
|
||||
} else {
|
||||
// range
|
||||
@ -91,23 +88,46 @@ public class ImapUtility {
|
||||
if (range != null) {
|
||||
int colonPos = range.indexOf(':');
|
||||
if (colonPos > 0) {
|
||||
int first = Integer.parseInt(range.substring(0, colonPos));
|
||||
int second = Integer.parseInt(range.substring(colonPos + 1));
|
||||
if (first < second) {
|
||||
for (int i = first; i <= second; i++) {
|
||||
list.add(Integer.toString(i));
|
||||
long first = Long.parseLong(range.substring(0, colonPos));
|
||||
long second = Long.parseLong(range.substring(colonPos + 1));
|
||||
if (is32bitValue(first) && is32bitValue(second)) {
|
||||
if (first < second) {
|
||||
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 {
|
||||
for (int i = first; i >= second; i--) {
|
||||
list.add(Integer.toString(i));
|
||||
}
|
||||
Log.d(K9.LOG_TAG, "Invalid range: " + range);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
Log.d(K9.LOG_TAG, "Invalid range value", e);
|
||||
Log.d(K9.LOG_TAG, "Invalid range value: " + range, e);
|
||||
}
|
||||
|
||||
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 mAuthType;
|
||||
int mConnectionSecurity;
|
||||
boolean mSecure;
|
||||
Socket mSocket;
|
||||
PeekableInputStream mIn;
|
||||
OutputStream mOut;
|
||||
@ -245,7 +244,6 @@ public class SmtpTransport extends Transport {
|
||||
}, new SecureRandom());
|
||||
mSocket = sslContext.getSocketFactory().createSocket();
|
||||
mSocket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
|
||||
mSecure = true;
|
||||
} else {
|
||||
mSocket = new Socket();
|
||||
mSocket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
|
||||
@ -308,7 +306,6 @@ public class SmtpTransport extends Transport {
|
||||
mIn = new PeekableInputStream(new BufferedInputStream(mSocket.getInputStream(),
|
||||
1024));
|
||||
mOut = mSocket.getOutputStream();
|
||||
mSecure = true;
|
||||
/*
|
||||
* Now resend the EHLO. Required by RFC2487 Sec. 5.2, and more specifically,
|
||||
* Exim.
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.fsck.k9.view;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
@ -24,6 +25,27 @@ public class MessageWebView extends WebView {
|
||||
*/
|
||||
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) {
|
||||
super(context);
|
||||
}
|
||||
@ -90,24 +112,13 @@ public class MessageWebView extends WebView {
|
||||
webSettings.setBuiltInZoomControls(true);
|
||||
}
|
||||
|
||||
// SINGLE_COLUMN layout was broken on Android < 2.2, so we
|
||||
// administratively disable it
|
||||
if (Build.VERSION.SDK_INT > 7 && K9.mobileOptimizedLayout()) {
|
||||
if (isSingleColumnLayoutSupported() && K9.mobileOptimizedLayout()) {
|
||||
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
|
||||
} else {
|
||||
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
disableOverscrolling();
|
||||
|
||||
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) {
|
||||
String content = text;
|
||||
if (K9.getK9Theme() == K9.THEME_DARK) {
|
||||
|
@ -104,6 +104,7 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
||||
private LinearLayout mInsideAttachmentsContainer;
|
||||
private SavedState mSavedState;
|
||||
private ClipboardManager mClipboardManager;
|
||||
private String mText;
|
||||
|
||||
|
||||
public void initialize(Activity activity) {
|
||||
@ -400,7 +401,10 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
||||
break;
|
||||
}
|
||||
case R.id.show_pictures: {
|
||||
// Allow network access first...
|
||||
setLoadPictures(true);
|
||||
// ...then re-populate the WebView with the message text
|
||||
loadBodyFromText(mText, "text/html");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -538,28 +542,20 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
||||
MessagingController controller, MessagingListener listener) throws MessagingException {
|
||||
resetView();
|
||||
|
||||
String type;
|
||||
String text = null;
|
||||
if (pgpData != null) {
|
||||
text = pgpData.getDecryptedData();
|
||||
}
|
||||
if (text != null) {
|
||||
type = "text/html";
|
||||
text = "<html><body><pre>" + text + "</pre></body></html>";
|
||||
} else {
|
||||
// getTextForDisplay() always returns HTML-ified content.
|
||||
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();
|
||||
|
||||
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) {
|
||||
|
@ -34,6 +34,14 @@ public class ImapUtilityTest extends TestCase {
|
||||
actual = ImapUtility.getImapSequenceValues("1");
|
||||
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"};
|
||||
actual = ImapUtility.getImapSequenceValues("1,3,2");
|
||||
MoreAsserts.assertEquals(expected, actual.toArray());
|
||||
@ -50,6 +58,11 @@ public class ImapUtilityTest extends TestCase {
|
||||
actual = ImapUtility.getImapSequenceValues("1,2:4,9:7");
|
||||
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
|
||||
expected = new String[] { "1", "5" };
|
||||
actual = ImapUtility.getImapSequenceValues("1,x,5");
|
||||
@ -75,6 +88,15 @@ public class ImapUtilityTest extends TestCase {
|
||||
expected = new String[0];
|
||||
actual = ImapUtility.getImapSequenceValues("1:x");
|
||||
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