mirror of
https://github.com/moparisthebest/k-9
synced 2025-01-10 13:18:09 -05:00
Merge branch 'master' into ms-eas. Format cleanup with astyle.
This commit is contained in:
commit
4d032a861e
@ -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="14013"
|
android:versionCode="15002"
|
||||||
android:versionName="3.913" package="com.fsck.k9"
|
android:versionName="4.102" package="com.fsck.k9"
|
||||||
>
|
>
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="7"
|
android:minSdkVersion="7"
|
||||||
|
1111
res/values-da/strings.xml
Normal file
1111
res/values-da/strings.xml
Normal file
File diff suppressed because it is too large
Load Diff
@ -491,6 +491,7 @@
|
|||||||
<item></item>
|
<item></item>
|
||||||
<item>ca</item>
|
<item>ca</item>
|
||||||
<item>cs</item>
|
<item>cs</item>
|
||||||
|
<item>da</item>
|
||||||
<item>de</item>
|
<item>de</item>
|
||||||
<item>en</item>
|
<item>en</item>
|
||||||
<item>es</item>
|
<item>es</item>
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
<string name="forward_action">Forward</string>
|
<string name="forward_action">Forward</string>
|
||||||
<string name="move_action">Move</string>
|
<string name="move_action">Move</string>
|
||||||
<string name="continue_action">Continue</string>
|
<string name="continue_action">Continue</string>
|
||||||
|
<string name="back_action">Back</string>
|
||||||
<string name="done_action">Done</string> <!-- Used to complete a multi-step process -->
|
<string name="done_action">Done</string> <!-- Used to complete a multi-step process -->
|
||||||
<string name="remove_action">Remove</string>
|
<string name="remove_action">Remove</string>
|
||||||
<string name="discard_action">Discard</string>
|
<string name="discard_action">Discard</string>
|
||||||
@ -597,6 +598,8 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin
|
|||||||
<string name="account_settings_crypto_app_not_available">not available</string>
|
<string name="account_settings_crypto_app_not_available">not available</string>
|
||||||
<string name="account_settings_crypto_auto_signature">Auto-sign</string>
|
<string name="account_settings_crypto_auto_signature">Auto-sign</string>
|
||||||
<string name="account_settings_crypto_auto_signature_summary">Use the account\'s email address to guess the signature key.</string>
|
<string name="account_settings_crypto_auto_signature_summary">Use the account\'s email address to guess the signature key.</string>
|
||||||
|
<string name="account_settings_crypto_auto_encrypt">Auto-encrypt</string>
|
||||||
|
<string name="account_settings_crypto_auto_encrypt_summary">Automatically set encrypt if a public key matches a recipient.</string>
|
||||||
|
|
||||||
<string name="account_settings_mail_check_frequency_label">Folder poll frequency</string>
|
<string name="account_settings_mail_check_frequency_label">Folder poll frequency</string>
|
||||||
<string name="account_settings_second_class_check_frequency_label">2nd class check frequency</string>
|
<string name="account_settings_second_class_check_frequency_label">2nd class check frequency</string>
|
||||||
@ -1023,6 +1026,12 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin
|
|||||||
<string name="save_or_discard_draft_message_dlg_title">Save draft message?</string>
|
<string name="save_or_discard_draft_message_dlg_title">Save draft message?</string>
|
||||||
<string name="save_or_discard_draft_message_instructions_fmt">Save or Discard this message?</string>
|
<string name="save_or_discard_draft_message_instructions_fmt">Save or Discard this message?</string>
|
||||||
|
|
||||||
|
<string name="refuse_to_save_draft_marked_encrypted_dlg_title">Refuse to save draft message.</string>
|
||||||
|
<string name="refuse_to_save_draft_marked_encrypted_instructions_fmt">Refuse to save draft message marked encrypted.</string>
|
||||||
|
|
||||||
|
<string name="continue_without_public_key_dlg_title">Continue without public key?</string>
|
||||||
|
<string name="continue_without_public_key_instructions_fmt">One or more recipients do not have a saved public key. Continue?</string>
|
||||||
|
|
||||||
<string name="charset_not_found">This message can\'t be displayed because the charset \"<xliff:g id="charset">%s</xliff:g>\" wasn\'t found.</string>
|
<string name="charset_not_found">This message can\'t be displayed because the charset \"<xliff:g id="charset">%s</xliff:g>\" wasn\'t found.</string>
|
||||||
|
|
||||||
<string name="select_text_now">Select text to copy.</string>
|
<string name="select_text_now">Select text to copy.</string>
|
||||||
|
@ -474,6 +474,13 @@
|
|||||||
android:summary="@string/account_settings_crypto_auto_signature_summary"
|
android:summary="@string/account_settings_crypto_auto_signature_summary"
|
||||||
android:dependency="crypto_app"/>
|
android:dependency="crypto_app"/>
|
||||||
|
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:persistent="false"
|
||||||
|
android:key="crypto_auto_encrypt"
|
||||||
|
android:title="@string/account_settings_crypto_auto_encrypt"
|
||||||
|
android:summary="@string/account_settings_crypto_auto_encrypt_summary"
|
||||||
|
android:dependency="crypto_app"/>
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
@ -152,6 +152,7 @@ public class Account implements BaseAccount {
|
|||||||
// The following 2 settings are currently only used by the EasStore.
|
// The following 2 settings are currently only used by the EasStore.
|
||||||
private String mSyncKey;
|
private String mSyncKey;
|
||||||
private String mSecurityKey;
|
private String mSecurityKey;
|
||||||
|
private boolean mCryptoAutoEncrypt;
|
||||||
|
|
||||||
private CryptoProvider mCryptoProvider = null;
|
private CryptoProvider mCryptoProvider = null;
|
||||||
|
|
||||||
@ -243,6 +244,7 @@ public class Account implements BaseAccount {
|
|||||||
mSyncRemoteDeletions = true;
|
mSyncRemoteDeletions = true;
|
||||||
mCryptoApp = Apg.NAME;
|
mCryptoApp = Apg.NAME;
|
||||||
mCryptoAutoSignature = false;
|
mCryptoAutoSignature = false;
|
||||||
|
mCryptoAutoEncrypt = false;
|
||||||
mEnabled = true;
|
mEnabled = true;
|
||||||
|
|
||||||
searchableFolders = Searchable.ALL;
|
searchableFolders = Searchable.ALL;
|
||||||
@ -411,92 +413,94 @@ public class Account implements BaseAccount {
|
|||||||
|
|
||||||
mCryptoApp = prefs.getString(mUuid + ".cryptoApp", Apg.NAME);
|
mCryptoApp = prefs.getString(mUuid + ".cryptoApp", Apg.NAME);
|
||||||
mCryptoAutoSignature = prefs.getBoolean(mUuid + ".cryptoAutoSignature", false);
|
mCryptoAutoSignature = prefs.getBoolean(mUuid + ".cryptoAutoSignature", false);
|
||||||
|
mCryptoAutoEncrypt = prefs.getBoolean(mUuid + ".cryptoAutoEncrypt", false);
|
||||||
mEnabled = prefs.getBoolean(mUuid + ".enabled", true);
|
mEnabled = prefs.getBoolean(mUuid + ".enabled", true);
|
||||||
mSyncKey = prefs.getString(mUuid + ".syncKey", "");
|
mSyncKey = prefs.getString(mUuid + ".syncKey", "");
|
||||||
mSecurityKey = prefs.getString(mUuid + ".securityKey", "");
|
mSecurityKey = prefs.getString(mUuid + ".securityKey", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized void delete(Preferences preferences) {
|
protected synchronized void delete(Preferences preferences) {
|
||||||
String uuidString = preferences.getPreferences().getString("accountUuids", "");
|
String uuidString = preferences.getPreferences().getString("accountUuids", "");
|
||||||
if (uuidString.contains(mUuid)) {
|
if (uuidString.contains(mUuid)) {
|
||||||
String[] uuids = uuidString.split(",");
|
String[] uuids = uuidString.split(",");
|
||||||
String[] newUuids = new String[uuids.length - 1];
|
String[] newUuids = new String[uuids.length - 1];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (String uuid : uuids) {
|
for (String uuid : uuids) {
|
||||||
if (uuid.equals(mUuid) == false) {
|
if (uuid.equals(mUuid) == false) {
|
||||||
newUuids[i++] = uuid;
|
newUuids[i++] = uuid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String accountUuids = Utility.combine(newUuids, ',');
|
String accountUuids = Utility.combine(newUuids, ',');
|
||||||
SharedPreferences.Editor editor = preferences.getPreferences().edit();
|
SharedPreferences.Editor editor = preferences.getPreferences().edit();
|
||||||
editor.putString("accountUuids", accountUuids);
|
editor.putString("accountUuids", accountUuids);
|
||||||
|
|
||||||
editor.remove(mUuid + ".storeUri");
|
editor.remove(mUuid + ".storeUri");
|
||||||
editor.remove(mUuid + ".localStoreUri");
|
editor.remove(mUuid + ".localStoreUri");
|
||||||
editor.remove(mUuid + ".transportUri");
|
editor.remove(mUuid + ".transportUri");
|
||||||
editor.remove(mUuid + ".description");
|
editor.remove(mUuid + ".description");
|
||||||
editor.remove(mUuid + ".name");
|
editor.remove(mUuid + ".name");
|
||||||
editor.remove(mUuid + ".email");
|
editor.remove(mUuid + ".email");
|
||||||
editor.remove(mUuid + ".alwaysBcc");
|
editor.remove(mUuid + ".alwaysBcc");
|
||||||
editor.remove(mUuid + ".automaticCheckIntervalMinutes");
|
editor.remove(mUuid + ".automaticCheckIntervalMinutes");
|
||||||
editor.remove(mUuid + ".pushPollOnConnect");
|
editor.remove(mUuid + ".pushPollOnConnect");
|
||||||
editor.remove(mUuid + ".saveAllHeaders");
|
editor.remove(mUuid + ".saveAllHeaders");
|
||||||
editor.remove(mUuid + ".idleRefreshMinutes");
|
editor.remove(mUuid + ".idleRefreshMinutes");
|
||||||
editor.remove(mUuid + ".lastAutomaticCheckTime");
|
editor.remove(mUuid + ".lastAutomaticCheckTime");
|
||||||
editor.remove(mUuid + ".latestOldMessageSeenTime");
|
editor.remove(mUuid + ".latestOldMessageSeenTime");
|
||||||
editor.remove(mUuid + ".notifyNewMail");
|
editor.remove(mUuid + ".notifyNewMail");
|
||||||
editor.remove(mUuid + ".notifySelfNewMail");
|
editor.remove(mUuid + ".notifySelfNewMail");
|
||||||
editor.remove(mUuid + ".deletePolicy");
|
editor.remove(mUuid + ".deletePolicy");
|
||||||
editor.remove(mUuid + ".draftsFolderName");
|
editor.remove(mUuid + ".draftsFolderName");
|
||||||
editor.remove(mUuid + ".sentFolderName");
|
editor.remove(mUuid + ".sentFolderName");
|
||||||
editor.remove(mUuid + ".trashFolderName");
|
editor.remove(mUuid + ".trashFolderName");
|
||||||
editor.remove(mUuid + ".archiveFolderName");
|
editor.remove(mUuid + ".archiveFolderName");
|
||||||
editor.remove(mUuid + ".spamFolderName");
|
editor.remove(mUuid + ".spamFolderName");
|
||||||
editor.remove(mUuid + ".autoExpandFolderName");
|
editor.remove(mUuid + ".autoExpandFolderName");
|
||||||
editor.remove(mUuid + ".accountNumber");
|
editor.remove(mUuid + ".accountNumber");
|
||||||
editor.remove(mUuid + ".vibrate");
|
editor.remove(mUuid + ".vibrate");
|
||||||
editor.remove(mUuid + ".vibratePattern");
|
editor.remove(mUuid + ".vibratePattern");
|
||||||
editor.remove(mUuid + ".vibrateTimes");
|
editor.remove(mUuid + ".vibrateTimes");
|
||||||
editor.remove(mUuid + ".ring");
|
editor.remove(mUuid + ".ring");
|
||||||
editor.remove(mUuid + ".ringtone");
|
editor.remove(mUuid + ".ringtone");
|
||||||
editor.remove(mUuid + ".lastFullSync");
|
editor.remove(mUuid + ".lastFullSync");
|
||||||
editor.remove(mUuid + ".folderDisplayMode");
|
editor.remove(mUuid + ".folderDisplayMode");
|
||||||
editor.remove(mUuid + ".folderSyncMode");
|
editor.remove(mUuid + ".folderSyncMode");
|
||||||
editor.remove(mUuid + ".folderPushMode");
|
editor.remove(mUuid + ".folderPushMode");
|
||||||
editor.remove(mUuid + ".folderTargetMode");
|
editor.remove(mUuid + ".folderTargetMode");
|
||||||
editor.remove(mUuid + ".hideButtonsEnum");
|
editor.remove(mUuid + ".hideButtonsEnum");
|
||||||
editor.remove(mUuid + ".signatureBeforeQuotedText");
|
editor.remove(mUuid + ".signatureBeforeQuotedText");
|
||||||
editor.remove(mUuid + ".expungePolicy");
|
editor.remove(mUuid + ".expungePolicy");
|
||||||
editor.remove(mUuid + ".syncRemoteDeletions");
|
editor.remove(mUuid + ".syncRemoteDeletions");
|
||||||
editor.remove(mUuid + ".maxPushFolders");
|
editor.remove(mUuid + ".maxPushFolders");
|
||||||
editor.remove(mUuid + ".searchableFolders");
|
editor.remove(mUuid + ".searchableFolders");
|
||||||
editor.remove(mUuid + ".chipColor");
|
editor.remove(mUuid + ".chipColor");
|
||||||
editor.remove(mUuid + ".led");
|
editor.remove(mUuid + ".led");
|
||||||
editor.remove(mUuid + ".ledColor");
|
editor.remove(mUuid + ".ledColor");
|
||||||
editor.remove(mUuid + ".goToUnreadMessageSearch");
|
editor.remove(mUuid + ".goToUnreadMessageSearch");
|
||||||
editor.remove(mUuid + ".notificationUnreadCount");
|
editor.remove(mUuid + ".notificationUnreadCount");
|
||||||
editor.remove(mUuid + ".subscribedFoldersOnly");
|
editor.remove(mUuid + ".subscribedFoldersOnly");
|
||||||
editor.remove(mUuid + ".maximumPolledMessageAge");
|
editor.remove(mUuid + ".maximumPolledMessageAge");
|
||||||
editor.remove(mUuid + ".maximumAutoDownloadMessageSize");
|
editor.remove(mUuid + ".maximumAutoDownloadMessageSize");
|
||||||
editor.remove(mUuid + ".messageFormatAuto");
|
editor.remove(mUuid + ".messageFormatAuto");
|
||||||
editor.remove(mUuid + ".quoteStyle");
|
editor.remove(mUuid + ".quoteStyle");
|
||||||
editor.remove(mUuid + ".quotePrefix");
|
editor.remove(mUuid + ".quotePrefix");
|
||||||
editor.remove(mUuid + ".showPicturesEnum");
|
editor.remove(mUuid + ".showPicturesEnum");
|
||||||
editor.remove(mUuid + ".replyAfterQuote");
|
editor.remove(mUuid + ".replyAfterQuote");
|
||||||
editor.remove(mUuid + ".stripSignature");
|
editor.remove(mUuid + ".stripSignature");
|
||||||
editor.remove(mUuid + ".cryptoApp");
|
editor.remove(mUuid + ".cryptoApp");
|
||||||
editor.remove(mUuid + ".cryptoAutoSignature");
|
editor.remove(mUuid + ".cryptoAutoSignature");
|
||||||
editor.remove(mUuid + ".enabled");
|
editor.remove(mUuid + ".cryptoAutoEncrypt");
|
||||||
editor.remove(mUuid + ".syncKey");
|
editor.remove(mUuid + ".enabled");
|
||||||
editor.remove(mUuid + ".securityKey");
|
editor.remove(mUuid + ".syncKey");
|
||||||
editor.remove(mUuid + ".enableMoveButtons");
|
editor.remove(mUuid + ".securityKey");
|
||||||
editor.remove(mUuid + ".hideMoveButtonsEnum");
|
editor.remove(mUuid + ".enableMoveButtons");
|
||||||
for (String type : networkTypes) {
|
editor.remove(mUuid + ".hideMoveButtonsEnum");
|
||||||
editor.remove(mUuid + ".useCompression." + type);
|
for (String type : networkTypes) {
|
||||||
}
|
editor.remove(mUuid + ".useCompression." + type);
|
||||||
deleteIdentities(preferences.getPreferences(), editor);
|
}
|
||||||
editor.commit();
|
deleteIdentities(preferences.getPreferences(), editor);
|
||||||
|
editor.commit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,21 +537,18 @@ public class Account implements BaseAccount {
|
|||||||
if (moveUp) {
|
if (moveUp) {
|
||||||
for (int i = 0; i < uuids.length; i++) {
|
for (int i = 0; i < uuids.length; i++) {
|
||||||
if (i > 0 && uuids[i].equals(mUuid)) {
|
if (i > 0 && uuids[i].equals(mUuid)) {
|
||||||
newUuids[i] = newUuids[i-1];
|
newUuids[i] = newUuids[i - 1];
|
||||||
newUuids[i-1] = mUuid;
|
newUuids[i - 1] = mUuid;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
newUuids[i] = uuids[i];
|
newUuids[i] = uuids[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
for (int i = uuids.length - 1; i >= 0; i--) {
|
for (int i = uuids.length - 1; i >= 0; i--) {
|
||||||
if (i < uuids.length - 1 && uuids[i].equals(mUuid)) {
|
if (i < uuids.length - 1 && uuids[i].equals(mUuid)) {
|
||||||
newUuids[i] = newUuids[i+1];
|
newUuids[i] = newUuids[i + 1];
|
||||||
newUuids[i+1] = mUuid;
|
newUuids[i + 1] = mUuid;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
newUuids[i] = uuids[i];
|
newUuids[i] = uuids[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -653,6 +654,7 @@ public class Account implements BaseAccount {
|
|||||||
editor.putBoolean(mUuid + ".stripSignature", mStripSignature);
|
editor.putBoolean(mUuid + ".stripSignature", mStripSignature);
|
||||||
editor.putString(mUuid + ".cryptoApp", mCryptoApp);
|
editor.putString(mUuid + ".cryptoApp", mCryptoApp);
|
||||||
editor.putBoolean(mUuid + ".cryptoAutoSignature", mCryptoAutoSignature);
|
editor.putBoolean(mUuid + ".cryptoAutoSignature", mCryptoAutoSignature);
|
||||||
|
editor.putBoolean(mUuid + ".cryptoAutoEncrypt", mCryptoAutoEncrypt);
|
||||||
editor.putBoolean(mUuid + ".enabled", mEnabled);
|
editor.putBoolean(mUuid + ".enabled", mEnabled);
|
||||||
editor.putString(mUuid + ".syncKey", mSyncKey);
|
editor.putString(mUuid + ".syncKey", mSyncKey);
|
||||||
editor.putString(mUuid + ".securityKey", mSecurityKey);
|
editor.putString(mUuid + ".securityKey", mSecurityKey);
|
||||||
@ -1494,6 +1496,14 @@ public class Account implements BaseAccount {
|
|||||||
mSecurityKey = key;
|
mSecurityKey = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isCryptoAutoEncrypt() {
|
||||||
|
return mCryptoAutoEncrypt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCryptoAutoEncrypt(boolean cryptoAutoEncrypt) {
|
||||||
|
mCryptoAutoEncrypt = cryptoAutoEncrypt;
|
||||||
|
}
|
||||||
|
|
||||||
public String getInboxFolderName() {
|
public String getInboxFolderName() {
|
||||||
return mInboxFolderName;
|
return mInboxFolderName;
|
||||||
}
|
}
|
||||||
|
@ -680,7 +680,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
String outgoingPassword = null;
|
String outgoingPassword = null;
|
||||||
if (mOutgoingPasswordView != null) {
|
if (mOutgoingPasswordView != null) {
|
||||||
outgoingPassword = (mUseIncomingView.isChecked()) ?
|
outgoingPassword = (mUseIncomingView.isChecked()) ?
|
||||||
incomingPassword : mOutgoingPasswordView.getText().toString();
|
incomingPassword : mOutgoingPasswordView.getText().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
@ -704,21 +704,21 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
|
|
||||||
// Use the dialog's layout inflater so its theme is used (and not the activity's theme).
|
// Use the dialog's layout inflater so its theme is used (and not the activity's theme).
|
||||||
View layout = mDialog.getLayoutInflater().inflate(
|
View layout = mDialog.getLayoutInflater().inflate(
|
||||||
R.layout.accounts_password_prompt, null);
|
R.layout.accounts_password_prompt, null);
|
||||||
|
|
||||||
// Set the intro text that tells the user what to do
|
// Set the intro text that tells the user what to do
|
||||||
TextView intro = (TextView) layout.findViewById(R.id.password_prompt_intro);
|
TextView intro = (TextView) layout.findViewById(R.id.password_prompt_intro);
|
||||||
String serverPasswords = activity.getResources().getQuantityString(
|
String serverPasswords = activity.getResources().getQuantityString(
|
||||||
R.plurals.settings_import_server_passwords,
|
R.plurals.settings_import_server_passwords,
|
||||||
(configureOutgoingServer) ? 2 : 1);
|
(configureOutgoingServer) ? 2 : 1);
|
||||||
intro.setText(activity.getString(R.string.settings_import_activate_account_intro,
|
intro.setText(activity.getString(R.string.settings_import_activate_account_intro,
|
||||||
mAccount.getDescription(), serverPasswords));
|
mAccount.getDescription(), serverPasswords));
|
||||||
|
|
||||||
// Display the hostname of the incoming server
|
// Display the hostname of the incoming server
|
||||||
TextView incomingText = (TextView) layout.findViewById(
|
TextView incomingText = (TextView) layout.findViewById(
|
||||||
R.id.password_prompt_incoming_server);
|
R.id.password_prompt_incoming_server);
|
||||||
incomingText.setText(activity.getString(R.string.settings_import_incoming_server,
|
incomingText.setText(activity.getString(R.string.settings_import_incoming_server,
|
||||||
incoming.host));
|
incoming.host));
|
||||||
|
|
||||||
mIncomingPasswordView = (EditText) layout.findViewById(R.id.incoming_server_password);
|
mIncomingPasswordView = (EditText) layout.findViewById(R.id.incoming_server_password);
|
||||||
mIncomingPasswordView.addTextChangedListener(this);
|
mIncomingPasswordView.addTextChangedListener(this);
|
||||||
@ -726,16 +726,16 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
if (configureOutgoingServer) {
|
if (configureOutgoingServer) {
|
||||||
// Display the hostname of the outgoing server
|
// Display the hostname of the outgoing server
|
||||||
TextView outgoingText = (TextView) layout.findViewById(
|
TextView outgoingText = (TextView) layout.findViewById(
|
||||||
R.id.password_prompt_outgoing_server);
|
R.id.password_prompt_outgoing_server);
|
||||||
outgoingText.setText(activity.getString(R.string.settings_import_outgoing_server,
|
outgoingText.setText(activity.getString(R.string.settings_import_outgoing_server,
|
||||||
outgoing.host));
|
outgoing.host));
|
||||||
|
|
||||||
mOutgoingPasswordView = (EditText) layout.findViewById(
|
mOutgoingPasswordView = (EditText) layout.findViewById(
|
||||||
R.id.outgoing_server_password);
|
R.id.outgoing_server_password);
|
||||||
mOutgoingPasswordView.addTextChangedListener(this);
|
mOutgoingPasswordView.addTextChangedListener(this);
|
||||||
|
|
||||||
mUseIncomingView = (CheckBox) layout.findViewById(
|
mUseIncomingView = (CheckBox) layout.findViewById(
|
||||||
R.id.use_incoming_server_password);
|
R.id.use_incoming_server_password);
|
||||||
mUseIncomingView.setChecked(true);
|
mUseIncomingView.setChecked(true);
|
||||||
mUseIncomingView.setOnCheckedChangeListener(new OnCheckedChangeListener() {
|
mUseIncomingView.setOnCheckedChangeListener(new OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
@ -786,7 +786,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
// If the checkbox to use the incoming server password is checked we need to make
|
// If the checkbox to use the incoming server password is checked we need to make
|
||||||
// sure that the password box for the outgoing server isn't empty.
|
// sure that the password box for the outgoing server isn't empty.
|
||||||
else if (mUseIncomingView.isChecked() ||
|
else if (mUseIncomingView.isChecked() ||
|
||||||
mOutgoingPasswordView.getText().length() > 0) {
|
mOutgoingPasswordView.getText().length() > 0) {
|
||||||
enable = true;
|
enable = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -817,8 +817,8 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
private Application mApplication;
|
private Application mApplication;
|
||||||
|
|
||||||
protected SetPasswordsAsyncTask(Activity activity, Account account,
|
protected SetPasswordsAsyncTask(Activity activity, Account account,
|
||||||
String incomingPassword, String outgoingPassword,
|
String incomingPassword, String outgoingPassword,
|
||||||
List<Account> remainingAccounts) {
|
List<Account> remainingAccounts) {
|
||||||
super(activity);
|
super(activity);
|
||||||
mAccount = account;
|
mAccount = account;
|
||||||
mIncomingPassword = incomingPassword;
|
mIncomingPassword = incomingPassword;
|
||||||
@ -832,7 +832,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
String title = mActivity.getString(R.string.settings_import_activate_account_header);
|
String title = mActivity.getString(R.string.settings_import_activate_account_header);
|
||||||
int passwordCount = (mOutgoingPassword == null) ? 1 : 2;
|
int passwordCount = (mOutgoingPassword == null) ? 1 : 2;
|
||||||
String message = mActivity.getResources().getQuantityString(
|
String message = mActivity.getResources().getQuantityString(
|
||||||
R.plurals.settings_import_setting_passwords, passwordCount);
|
R.plurals.settings_import_setting_passwords, passwordCount);
|
||||||
mProgressDialog = ProgressDialog.show(mActivity, title, message, true);
|
mProgressDialog = ProgressDialog.show(mActivity, title, message, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1218,19 +1218,16 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
item.setVisible(false);
|
item.setVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
EnumSet<ACCOUNT_LOCATION> accountLocation = accountLocation(account);
|
EnumSet<ACCOUNT_LOCATION> accountLocation = accountLocation(account);
|
||||||
if (accountLocation.contains(ACCOUNT_LOCATION.TOP)) {
|
if (accountLocation.contains(ACCOUNT_LOCATION.TOP)) {
|
||||||
menu.findItem(R.id.move_up).setEnabled(false);
|
menu.findItem(R.id.move_up).setEnabled(false);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
menu.findItem(R.id.move_up).setEnabled(true);
|
menu.findItem(R.id.move_up).setEnabled(true);
|
||||||
}
|
}
|
||||||
if (accountLocation.contains(ACCOUNT_LOCATION.BOTTOM)) {
|
if (accountLocation.contains(ACCOUNT_LOCATION.BOTTOM)) {
|
||||||
menu.findItem(R.id.move_down).setEnabled(false);
|
menu.findItem(R.id.move_down).setEnabled(false);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
menu.findItem(R.id.move_down).setEnabled(true);
|
menu.findItem(R.id.move_down).setEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1375,7 +1372,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
|
|
||||||
int imported = mImportResults.importedAccounts.size();
|
int imported = mImportResults.importedAccounts.size();
|
||||||
String accounts = activity.getResources().getQuantityString(
|
String accounts = activity.getResources().getQuantityString(
|
||||||
R.plurals.settings_import_success, imported, imported);
|
R.plurals.settings_import_success, imported, imported);
|
||||||
return activity.getString(R.string.settings_import_success, accounts, mFilename);
|
return activity.getString(R.string.settings_import_success, accounts, mFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1467,7 +1464,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
|
|
||||||
importSelectionView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
|
importSelectionView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
|
||||||
importSelectionView.setAdapter(new ArrayAdapter<String>(activity,
|
importSelectionView.setAdapter(new ArrayAdapter<String>(activity,
|
||||||
android.R.layout.simple_list_item_checked, contents));
|
android.R.layout.simple_list_item_checked, contents));
|
||||||
importSelectionView.setOnItemSelectedListener(new OnItemSelectedListener() {
|
importSelectionView.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
|
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
|
||||||
@ -1476,7 +1473,9 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNothingSelected(AdapterView<?> arg0) { /* Do nothing */ }
|
public void onNothingSelected(AdapterView<?> arg0) {
|
||||||
|
/* Do nothing */
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (selection != null) {
|
if (selection != null) {
|
||||||
@ -1494,47 +1493,47 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
builder.setView(importSelectionView);
|
builder.setView(importSelectionView);
|
||||||
builder.setInverseBackgroundForced(true);
|
builder.setInverseBackgroundForced(true);
|
||||||
builder.setPositiveButton(R.string.okay_action,
|
builder.setPositiveButton(R.string.okay_action,
|
||||||
new DialogInterface.OnClickListener() {
|
new DialogInterface.OnClickListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
ListAdapter adapter = importSelectionView.getAdapter();
|
ListAdapter adapter = importSelectionView.getAdapter();
|
||||||
int count = adapter.getCount();
|
int count = adapter.getCount();
|
||||||
SparseBooleanArray pos = importSelectionView.getCheckedItemPositions();
|
SparseBooleanArray pos = importSelectionView.getCheckedItemPositions();
|
||||||
|
|
||||||
boolean includeGlobals = mImportContents.globalSettings ? pos.get(0) : false;
|
boolean includeGlobals = mImportContents.globalSettings ? pos.get(0) : false;
|
||||||
List<String> accountUuids = new ArrayList<String>();
|
List<String> accountUuids = new ArrayList<String>();
|
||||||
int start = mImportContents.globalSettings ? 1 : 0;
|
int start = mImportContents.globalSettings ? 1 : 0;
|
||||||
for (int i = start; i < count; i++) {
|
for (int i = start; i < count; i++) {
|
||||||
if (pos.get(i)) {
|
if (pos.get(i)) {
|
||||||
accountUuids.add(mImportContents.accounts.get(i-start).uuid);
|
accountUuids.add(mImportContents.accounts.get(i - start).uuid);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO: Think some more about this. Overwriting could change the store
|
|
||||||
* type. This requires some additional code in order to work smoothly
|
|
||||||
* while the app is running.
|
|
||||||
*/
|
|
||||||
boolean overwrite = false;
|
|
||||||
|
|
||||||
dialog.dismiss();
|
|
||||||
activity.setNonConfigurationInstance(null);
|
|
||||||
|
|
||||||
ImportAsyncTask importAsyncTask = new ImportAsyncTask(activity,
|
|
||||||
includeGlobals, accountUuids, overwrite, mUri);
|
|
||||||
activity.setNonConfigurationInstance(importAsyncTask);
|
|
||||||
importAsyncTask.execute();
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
/*
|
||||||
|
* TODO: Think some more about this. Overwriting could change the store
|
||||||
|
* type. This requires some additional code in order to work smoothly
|
||||||
|
* while the app is running.
|
||||||
|
*/
|
||||||
|
boolean overwrite = false;
|
||||||
|
|
||||||
|
dialog.dismiss();
|
||||||
|
activity.setNonConfigurationInstance(null);
|
||||||
|
|
||||||
|
ImportAsyncTask importAsyncTask = new ImportAsyncTask(activity,
|
||||||
|
includeGlobals, accountUuids, overwrite, mUri);
|
||||||
|
activity.setNonConfigurationInstance(importAsyncTask);
|
||||||
|
importAsyncTask.execute();
|
||||||
|
}
|
||||||
|
});
|
||||||
builder.setNegativeButton(R.string.cancel_action,
|
builder.setNegativeButton(R.string.cancel_action,
|
||||||
new DialogInterface.OnClickListener() {
|
new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
activity.setNonConfigurationInstance(null);
|
activity.setNonConfigurationInstance(null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mDialog = builder.show();
|
mDialog = builder.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1772,7 +1771,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
|
|
||||||
|
|
||||||
private ExportAsyncTask(Accounts activity, boolean includeGlobals,
|
private ExportAsyncTask(Accounts activity, boolean includeGlobals,
|
||||||
Set<String> accountUuids) {
|
Set<String> accountUuids) {
|
||||||
super(activity);
|
super(activity);
|
||||||
mIncludeGlobals = includeGlobals;
|
mIncludeGlobals = includeGlobals;
|
||||||
mAccountUuids = accountUuids;
|
mAccountUuids = accountUuids;
|
||||||
@ -1789,7 +1788,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
protected Boolean doInBackground(Void... params) {
|
protected Boolean doInBackground(Void... params) {
|
||||||
try {
|
try {
|
||||||
mFileName = SettingsExporter.exportToFile(mContext, mIncludeGlobals,
|
mFileName = SettingsExporter.exportToFile(mContext, mIncludeGlobals,
|
||||||
mAccountUuids);
|
mAccountUuids);
|
||||||
} catch (SettingsImportExportException e) {
|
} catch (SettingsImportExportException e) {
|
||||||
Log.w(K9.LOG_TAG, "Exception during export", e);
|
Log.w(K9.LOG_TAG, "Exception during export", e);
|
||||||
return false;
|
return false;
|
||||||
@ -1808,11 +1807,11 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
activity.showSimpleDialog(R.string.settings_export_success_header,
|
activity.showSimpleDialog(R.string.settings_export_success_header,
|
||||||
R.string.settings_export_success, mFileName);
|
R.string.settings_export_success, mFileName);
|
||||||
} else {
|
} else {
|
||||||
//TODO: better error messages
|
//TODO: better error messages
|
||||||
activity.showSimpleDialog(R.string.settings_export_failed_header,
|
activity.showSimpleDialog(R.string.settings_export_failed_header,
|
||||||
R.string.settings_export_failure);
|
R.string.settings_export_failure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1828,7 +1827,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
private ImportResults mImportResults;
|
private ImportResults mImportResults;
|
||||||
|
|
||||||
private ImportAsyncTask(Accounts activity, boolean includeGlobals,
|
private ImportAsyncTask(Accounts activity, boolean includeGlobals,
|
||||||
List<String> accountUuids, boolean overwrite, Uri uri) {
|
List<String> accountUuids, boolean overwrite, Uri uri) {
|
||||||
super(activity);
|
super(activity);
|
||||||
mIncludeGlobals = includeGlobals;
|
mIncludeGlobals = includeGlobals;
|
||||||
mAccountUuids = accountUuids;
|
mAccountUuids = accountUuids;
|
||||||
@ -1849,11 +1848,13 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
InputStream is = mContext.getContentResolver().openInputStream(mUri);
|
InputStream is = mContext.getContentResolver().openInputStream(mUri);
|
||||||
try {
|
try {
|
||||||
mImportResults = SettingsImporter.importSettings(mContext, is,
|
mImportResults = SettingsImporter.importSettings(mContext, is,
|
||||||
mIncludeGlobals, mAccountUuids, mOverwrite);
|
mIncludeGlobals, mAccountUuids, mOverwrite);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
is.close();
|
is.close();
|
||||||
} catch (IOException e) { /* Ignore */ }
|
} catch (IOException e) {
|
||||||
|
/* Ignore */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (SettingsImportExportException e) {
|
} catch (SettingsImportExportException e) {
|
||||||
Log.w(K9.LOG_TAG, "Exception during import", e);
|
Log.w(K9.LOG_TAG, "Exception during import", e);
|
||||||
@ -1883,7 +1884,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
if (success && (globalSettings || imported > 0)) {
|
if (success && (globalSettings || imported > 0)) {
|
||||||
if (imported == 0) {
|
if (imported == 0) {
|
||||||
activity.showSimpleDialog(R.string.settings_import_success_header,
|
activity.showSimpleDialog(R.string.settings_import_success_header,
|
||||||
R.string.settings_import_global_settings_success, filename);
|
R.string.settings_import_global_settings_success, filename);
|
||||||
} else {
|
} else {
|
||||||
activity.showAccountsImportedDialog(mImportResults, filename);
|
activity.showAccountsImportedDialog(mImportResults, filename);
|
||||||
}
|
}
|
||||||
@ -1892,7 +1893,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
} else {
|
} else {
|
||||||
//TODO: better error messages
|
//TODO: better error messages
|
||||||
activity.showSimpleDialog(R.string.settings_import_failed_header,
|
activity.showSimpleDialog(R.string.settings_import_failed_header,
|
||||||
R.string.settings_import_failure, filename);
|
R.string.settings_import_failure, filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1924,13 +1925,14 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
is.close();
|
is.close();
|
||||||
} catch (IOException e) { /* Ignore */ }
|
} catch (IOException e) {
|
||||||
|
/* Ignore */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (SettingsImportExportException e) {
|
} catch (SettingsImportExportException e) {
|
||||||
Log.w(K9.LOG_TAG, "Exception during export", e);
|
Log.w(K9.LOG_TAG, "Exception during export", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
} catch (FileNotFoundException e) {
|
||||||
catch (FileNotFoundException e) {
|
|
||||||
Log.w(K9.LOG_TAG, "Couldn't read content from URI " + mUri);
|
Log.w(K9.LOG_TAG, "Couldn't read content from URI " + mUri);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1952,7 +1954,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
String filename = mUri.getLastPathSegment();
|
String filename = mUri.getLastPathSegment();
|
||||||
//TODO: better error messages
|
//TODO: better error messages
|
||||||
activity.showSimpleDialog(R.string.settings_import_failed_header,
|
activity.showSimpleDialog(R.string.settings_import_failed_header,
|
||||||
R.string.settings_import_failure, filename);
|
R.string.settings_import_failure, filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -367,8 +367,7 @@ public class FolderList extends K9ListActivity {
|
|||||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||||
//Shortcuts that work no matter what is selected
|
//Shortcuts that work no matter what is selected
|
||||||
switch (keyCode) {
|
switch (keyCode) {
|
||||||
case KeyEvent.KEYCODE_Q:
|
case KeyEvent.KEYCODE_Q: {
|
||||||
{
|
|
||||||
onAccounts();
|
onAccounts();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -122,10 +122,10 @@ class InsertableHtmlContent implements Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the footer insertion point.
|
* Get the footer insertion point.
|
||||||
* @return Footer insertion point
|
* @return Footer insertion point
|
||||||
*/
|
*/
|
||||||
public int getFooterInsertionPoint() {
|
public int getFooterInsertionPoint() {
|
||||||
return footerInsertionPoint;
|
return footerInsertionPoint;
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,8 @@ import com.fsck.k9.mail.store.LocalStore.LocalAttachmentBody;
|
|||||||
|
|
||||||
public class MessageCompose extends K9Activity implements OnClickListener, OnFocusChangeListener {
|
public class MessageCompose extends K9Activity implements OnClickListener, OnFocusChangeListener {
|
||||||
private static final int DIALOG_SAVE_OR_DISCARD_DRAFT_MESSAGE = 1;
|
private static final int DIALOG_SAVE_OR_DISCARD_DRAFT_MESSAGE = 1;
|
||||||
|
private static final int DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED = 2;
|
||||||
|
private static final int DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY = 3;
|
||||||
|
|
||||||
private static final String ACTION_COMPOSE = "com.fsck.k9.intent.action.COMPOSE";
|
private static final String ACTION_COMPOSE = "com.fsck.k9.intent.action.COMPOSE";
|
||||||
private static final String ACTION_REPLY = "com.fsck.k9.intent.action.REPLY";
|
private static final String ACTION_REPLY = "com.fsck.k9.intent.action.REPLY";
|
||||||
@ -112,6 +114,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
private static final String STATE_REFERENCES = "com.fsck.k9.activity.MessageCompose.references";
|
private static final String STATE_REFERENCES = "com.fsck.k9.activity.MessageCompose.references";
|
||||||
private static final String STATE_KEY_MESSAGE_FORMAT = "com.fsck.k9.activity.MessageCompose.messageFormat";
|
private static final String STATE_KEY_MESSAGE_FORMAT = "com.fsck.k9.activity.MessageCompose.messageFormat";
|
||||||
private static final String STATE_KEY_READ_RECEIPT = "com.fsck.k9.activity.MessageCompose.messageReadReceipt";
|
private static final String STATE_KEY_READ_RECEIPT = "com.fsck.k9.activity.MessageCompose.messageReadReceipt";
|
||||||
|
private static final String STATE_KEY_DRAFT_NEEDS_SAVING = "com.fsck.k9.activity.MessageCompose.mDraftNeedsSaving";
|
||||||
|
|
||||||
private static final int MSG_PROGRESS_ON = 1;
|
private static final int MSG_PROGRESS_ON = 1;
|
||||||
private static final int MSG_PROGRESS_OFF = 2;
|
private static final int MSG_PROGRESS_OFF = 2;
|
||||||
@ -207,6 +210,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
private ImageButton mAddBccFromContacts;
|
private ImageButton mAddBccFromContacts;
|
||||||
|
|
||||||
private PgpData mPgpData = null;
|
private PgpData mPgpData = null;
|
||||||
|
private boolean mAutoEncrypt = false;
|
||||||
|
private boolean mContinueWithoutPublicKey = false;
|
||||||
|
|
||||||
private String mReferences;
|
private String mReferences;
|
||||||
private String mInReplyTo;
|
private String mInReplyTo;
|
||||||
@ -218,6 +223,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
private boolean mDraftNeedsSaving = false;
|
private boolean mDraftNeedsSaving = false;
|
||||||
private boolean mPreventDraftSaving = false;
|
private boolean mPreventDraftSaving = false;
|
||||||
|
|
||||||
|
private boolean mIgnoreOnStop = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The draft uid of this message. This is used when saving drafts so that the same draft is
|
* The draft uid of this message. This is used when saving drafts so that the same draft is
|
||||||
* overwritten instead of being created anew. This property is null until the first save.
|
* overwritten instead of being created anew. This property is null until the first save.
|
||||||
@ -441,6 +448,30 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
public void afterTextChanged(android.text.Editable s) { }
|
public void afterTextChanged(android.text.Editable s) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// For watching changes to the To:, Cc:, and Bcc: fields for auto-encryption on a matching
|
||||||
|
// address.
|
||||||
|
TextWatcher recipientWatcher = new TextWatcher() {
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int before, int after) { }
|
||||||
|
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
mDraftNeedsSaving = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void afterTextChanged(android.text.Editable s) {
|
||||||
|
final CryptoProvider crypto = mAccount.getCryptoProvider();
|
||||||
|
if (mAutoEncrypt && crypto.isAvailable(getApplicationContext())) {
|
||||||
|
for (Address address : getRecipientAddresses()) {
|
||||||
|
if (crypto.hasPublicKeyForEmail(getApplicationContext(),
|
||||||
|
address.getAddress())) {
|
||||||
|
mEncryptCheckbox.setChecked(true);
|
||||||
|
mContinueWithoutPublicKey = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
TextWatcher sigwatcher = new TextWatcher() {
|
TextWatcher sigwatcher = new TextWatcher() {
|
||||||
public void beforeTextChanged(CharSequence s, int start,
|
public void beforeTextChanged(CharSequence s, int start,
|
||||||
int before, int after) { }
|
int before, int after) { }
|
||||||
@ -454,9 +485,9 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
public void afterTextChanged(android.text.Editable s) { }
|
public void afterTextChanged(android.text.Editable s) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
mToView.addTextChangedListener(watcher);
|
mToView.addTextChangedListener(recipientWatcher);
|
||||||
mCcView.addTextChangedListener(watcher);
|
mCcView.addTextChangedListener(recipientWatcher);
|
||||||
mBccView.addTextChangedListener(watcher);
|
mBccView.addTextChangedListener(recipientWatcher);
|
||||||
mSubjectView.addTextChangedListener(watcher);
|
mSubjectView.addTextChangedListener(watcher);
|
||||||
|
|
||||||
mMessageContentView.addTextChangedListener(watcher);
|
mMessageContentView.addTextChangedListener(watcher);
|
||||||
@ -615,6 +646,11 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
mCryptoSignatureUserId = (TextView)findViewById(R.id.userId);
|
mCryptoSignatureUserId = (TextView)findViewById(R.id.userId);
|
||||||
mCryptoSignatureUserIdRest = (TextView)findViewById(R.id.userIdRest);
|
mCryptoSignatureUserIdRest = (TextView)findViewById(R.id.userIdRest);
|
||||||
mEncryptCheckbox = (CheckBox)findViewById(R.id.cb_encrypt);
|
mEncryptCheckbox = (CheckBox)findViewById(R.id.cb_encrypt);
|
||||||
|
if (mSourceMessageBody != null) {
|
||||||
|
// mSourceMessageBody is set to something when replying to and forwarding decrypted
|
||||||
|
// messages, so the sender probably wants the message to be encrypted.
|
||||||
|
mEncryptCheckbox.setChecked(true);
|
||||||
|
}
|
||||||
|
|
||||||
initializeCrypto();
|
initializeCrypto();
|
||||||
final CryptoProvider crypto = mAccount.getCryptoProvider();
|
final CryptoProvider crypto = mAccount.getCryptoProvider();
|
||||||
@ -648,6 +684,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateEncryptLayout();
|
updateEncryptLayout();
|
||||||
|
mAutoEncrypt = mAccount.isCryptoAutoEncrypt();
|
||||||
} else {
|
} else {
|
||||||
mEncryptLayout.setVisibility(View.GONE);
|
mEncryptLayout.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
@ -681,8 +718,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
* Dear developer, if your application is using those EXTRAs you're doing
|
* Dear developer, if your application is using those EXTRAs you're doing
|
||||||
* it wrong! So go fix your program or get AOSP to change the documentation.
|
* it wrong! So go fix your program or get AOSP to change the documentation.
|
||||||
*/
|
*/
|
||||||
}
|
} else if (Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action)) {
|
||||||
else if (Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action)) {
|
|
||||||
/*
|
/*
|
||||||
* Note: Here we allow a slight deviation from the documentated behavior.
|
* Note: Here we allow a slight deviation from the documentated behavior.
|
||||||
* EXTRA_TEXT is used as message body (if available) regardless of the MIME
|
* EXTRA_TEXT is used as message body (if available) regardless of the MIME
|
||||||
@ -773,6 +809,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
mCryptoSignatureUserId.setVisibility(View.INVISIBLE);
|
mCryptoSignatureUserId.setVisibility(View.INVISIBLE);
|
||||||
mCryptoSignatureUserIdRest.setVisibility(View.INVISIBLE);
|
mCryptoSignatureUserIdRest.setVisibility(View.INVISIBLE);
|
||||||
} else {
|
} else {
|
||||||
|
mMessageFormat = MessageFormat.TEXT;
|
||||||
// if a signature key is selected, then the checkbox itself has no text
|
// if a signature key is selected, then the checkbox itself has no text
|
||||||
mCryptoSignatureCheckbox.setText("");
|
mCryptoSignatureCheckbox.setText("");
|
||||||
mCryptoSignatureCheckbox.setChecked(true);
|
mCryptoSignatureCheckbox.setChecked(true);
|
||||||
@ -800,14 +837,23 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
mIgnoreOnStop = false;
|
||||||
MessagingController.getInstance(getApplication()).addListener(mListener);
|
MessagingController.getInstance(getApplication()).addListener(mListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
saveIfNeeded();
|
|
||||||
MessagingController.getInstance(getApplication()).removeListener(mListener);
|
MessagingController.getInstance(getApplication()).removeListener(mListener);
|
||||||
|
// Save email as draft when activity is changed (go to home screen, call received) or screen locked
|
||||||
|
// don't do this if only changing orientations
|
||||||
|
if ((getChangingConfigurations() & ActivityInfo.CONFIG_ORIENTATION) == 0) {
|
||||||
|
// don't do this if selecting signature or if "Encrypt" is checked or if adding an attachment
|
||||||
|
if (!mPreventDraftSaving && !mEncryptCheckbox.isChecked() && !mIgnoreOnStop) {
|
||||||
|
saveIfNeeded();
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -821,7 +867,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
@Override
|
@Override
|
||||||
protected void onSaveInstanceState(Bundle outState) {
|
protected void onSaveInstanceState(Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
saveIfNeeded();
|
|
||||||
ArrayList<Uri> attachments = new ArrayList<Uri>();
|
ArrayList<Uri> attachments = new ArrayList<Uri>();
|
||||||
for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
|
for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
|
||||||
View view = mAttachments.getChildAt(i);
|
View view = mAttachments.getChildAt(i);
|
||||||
@ -842,6 +887,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
outState.putSerializable(STATE_KEY_HTML_QUOTE, mQuotedHtmlContent);
|
outState.putSerializable(STATE_KEY_HTML_QUOTE, mQuotedHtmlContent);
|
||||||
outState.putSerializable(STATE_KEY_MESSAGE_FORMAT, mMessageFormat);
|
outState.putSerializable(STATE_KEY_MESSAGE_FORMAT, mMessageFormat);
|
||||||
outState.putBoolean(STATE_KEY_READ_RECEIPT, mReadReceipt);
|
outState.putBoolean(STATE_KEY_READ_RECEIPT, mReadReceipt);
|
||||||
|
outState.putBoolean(STATE_KEY_DRAFT_NEEDS_SAVING, mDraftNeedsSaving);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -875,13 +921,13 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
mPgpData = (PgpData) savedInstanceState.getSerializable(STATE_PGP_DATA);
|
mPgpData = (PgpData) savedInstanceState.getSerializable(STATE_PGP_DATA);
|
||||||
mInReplyTo = savedInstanceState.getString(STATE_IN_REPLY_TO);
|
mInReplyTo = savedInstanceState.getString(STATE_IN_REPLY_TO);
|
||||||
mReferences = savedInstanceState.getString(STATE_REFERENCES);
|
mReferences = savedInstanceState.getString(STATE_REFERENCES);
|
||||||
|
mDraftNeedsSaving = savedInstanceState.getBoolean(STATE_KEY_DRAFT_NEEDS_SAVING);
|
||||||
|
|
||||||
initializeCrypto();
|
initializeCrypto();
|
||||||
updateFrom();
|
updateFrom();
|
||||||
updateSignature();
|
updateSignature();
|
||||||
updateEncryptLayout();
|
updateEncryptLayout();
|
||||||
|
|
||||||
mDraftNeedsSaving = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTitle() {
|
private void updateTitle() {
|
||||||
@ -916,6 +962,16 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
return Address.parseUnencoded(view.getText().toString().trim());
|
return Address.parseUnencoded(view.getText().toString().trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns an Address array of recipients this email will be sent to.
|
||||||
|
* @return Address array of recipients this email will be sent to.
|
||||||
|
*/
|
||||||
|
private Address[] getRecipientAddresses() {
|
||||||
|
String addresses = mToView.getText().toString() + mCcView.getText().toString()
|
||||||
|
+ mBccView.getText().toString();
|
||||||
|
return Address.parseUnencoded(addresses.trim());
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Build the Body that will contain the text of the message. We'll decide where to
|
* Build the Body that will contain the text of the message. We'll decide where to
|
||||||
* include it later. Draft messages are treated somewhat differently in that signatures are not
|
* include it later. Draft messages are treated somewhat differently in that signatures are not
|
||||||
@ -938,7 +994,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
String action = getIntent().getAction();
|
String action = getIntent().getAction();
|
||||||
if (mAccount.isReplyAfterQuote() &&
|
if (mAccount.isReplyAfterQuote() &&
|
||||||
(ACTION_REPLY.equals(action) || ACTION_REPLY_ALL.equals(action) ||
|
(ACTION_REPLY.equals(action) || ACTION_REPLY_ALL.equals(action) ||
|
||||||
ACTION_EDIT_DRAFT.equals(action))) {
|
ACTION_EDIT_DRAFT.equals(action))) {
|
||||||
replyAfterQuote = true;
|
replyAfterQuote = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -957,7 +1013,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
// Place the signature immediately after the reply.
|
// Place the signature immediately after the reply.
|
||||||
if (!isDraft) {
|
if (!isDraft) {
|
||||||
if (mQuoteStyle == QuoteStyle.HEADER || replyAfterQuote || mAccount.isSignatureBeforeQuotedText()) {
|
if (mQuoteStyle == QuoteStyle.HEADER || replyAfterQuote || mAccount.isSignatureBeforeQuotedText()) {
|
||||||
Log.d("ASH", "appending signature after new content");
|
|
||||||
text = appendSignature(text);
|
text = appendSignature(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1272,7 +1327,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
}
|
}
|
||||||
if (mQuotedHtmlContent != null) {
|
if (mQuotedHtmlContent != null) {
|
||||||
uri.appendQueryParameter(IdentityField.FOOTER_OFFSET.value(),
|
uri.appendQueryParameter(IdentityField.FOOTER_OFFSET.value(),
|
||||||
Integer.toString(mQuotedHtmlContent.getFooterInsertionPoint()));
|
Integer.toString(mQuotedHtmlContent.getFooterInsertionPoint()));
|
||||||
}
|
}
|
||||||
if (bodyPlain != null) {
|
if (bodyPlain != null) {
|
||||||
if (bodyPlain.getComposedMessageLength() != null && bodyPlain.getComposedMessageOffset() != null) {
|
if (bodyPlain.getComposedMessageLength() != null && bodyPlain.getComposedMessageOffset() != null) {
|
||||||
@ -1412,7 +1467,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
String signature = "";
|
String signature = "";
|
||||||
if (mIdentity.getSignatureUse()) {
|
if (mIdentity.getSignatureUse()) {
|
||||||
signature = mSignatureView.getText().toString();
|
signature = mSignatureView.getText().toString();
|
||||||
if(!StringUtils.isNullOrEmpty(signature)) {
|
if (!StringUtils.isNullOrEmpty(signature)) {
|
||||||
signature = HtmlConverter.textToHtmlFragment("\n" + signature);
|
signature = HtmlConverter.textToHtmlFragment("\n" + signature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1427,7 +1482,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void saveIfNeeded() {
|
private void saveIfNeeded() {
|
||||||
if (!mDraftNeedsSaving || mPreventDraftSaving || mPgpData.hasEncryptionKeys()) {
|
if (!mDraftNeedsSaving || mPreventDraftSaving || mPgpData.hasEncryptionKeys() ||
|
||||||
|
mEncryptCheckbox.isChecked()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1457,19 +1513,20 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
Toast.makeText(this, getString(R.string.message_compose_error_no_recipients), Toast.LENGTH_LONG).show();
|
Toast.makeText(this, getString(R.string.message_compose_error_no_recipients), Toast.LENGTH_LONG).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final CryptoProvider crypto = mAccount.getCryptoProvider();
|
||||||
if (mEncryptCheckbox.isChecked() && !mPgpData.hasEncryptionKeys()) {
|
if (mEncryptCheckbox.isChecked() && !mPgpData.hasEncryptionKeys()) {
|
||||||
|
mMessageFormat = MessageFormat.TEXT;
|
||||||
// key selection before encryption
|
// key selection before encryption
|
||||||
StringBuilder emails = new StringBuilder();
|
StringBuilder emails = new StringBuilder();
|
||||||
Address[][] addresses = new Address[][] { getAddresses(mToView),
|
for (Address address : getRecipientAddresses()) {
|
||||||
getAddresses(mCcView),
|
if (emails.length() != 0) {
|
||||||
getAddresses(mBccView)
|
emails.append(',');
|
||||||
};
|
}
|
||||||
for (Address[] addressArray : addresses) {
|
emails.append(address.getAddress());
|
||||||
for (Address address : addressArray) {
|
if (!mContinueWithoutPublicKey &&
|
||||||
if (emails.length() != 0) {
|
!crypto.hasPublicKeyForEmail(this, address.getAddress())) {
|
||||||
emails.append(',');
|
showDialog(DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY);
|
||||||
}
|
return;
|
||||||
emails.append(address.getAddress());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (emails.length() != 0) {
|
if (emails.length() != 0) {
|
||||||
@ -1478,7 +1535,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
emails.append(mIdentity.getEmail());
|
emails.append(mIdentity.getEmail());
|
||||||
|
|
||||||
mPreventDraftSaving = true;
|
mPreventDraftSaving = true;
|
||||||
if (!mAccount.getCryptoProvider().selectEncryptionKeys(MessageCompose.this, emails.toString(), mPgpData)) {
|
if (!crypto.selectEncryptionKeys(MessageCompose.this, emails.toString(), mPgpData)) {
|
||||||
mPreventDraftSaving = false;
|
mPreventDraftSaving = false;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -1487,7 +1544,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
if (mPgpData.getEncryptedData() == null) {
|
if (mPgpData.getEncryptedData() == null) {
|
||||||
String text = buildText(false).getText();
|
String text = buildText(false).getText();
|
||||||
mPreventDraftSaving = true;
|
mPreventDraftSaving = true;
|
||||||
if (!mAccount.getCryptoProvider().encrypt(this, text, mPgpData)) {
|
if (!crypto.encrypt(this, text, mPgpData)) {
|
||||||
mPreventDraftSaving = false;
|
mPreventDraftSaving = false;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -1520,7 +1577,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onSave() {
|
private void onSave() {
|
||||||
mDraftNeedsSaving = true;
|
|
||||||
saveIfNeeded();
|
saveIfNeeded();
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
@ -1547,6 +1603,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
* Kick off a picker for whatever kind of MIME types we'll accept and let Android take over.
|
* Kick off a picker for whatever kind of MIME types we'll accept and let Android take over.
|
||||||
*/
|
*/
|
||||||
private void onAddAttachment() {
|
private void onAddAttachment() {
|
||||||
|
mIgnoreOnStop = true;
|
||||||
if (K9.isGalleryBuggy()) {
|
if (K9.isGalleryBuggy()) {
|
||||||
if (K9.useGalleryBugWorkaround()) {
|
if (K9.useGalleryBugWorkaround()) {
|
||||||
Toast.makeText(MessageCompose.this,
|
Toast.makeText(MessageCompose.this,
|
||||||
@ -1853,7 +1910,11 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
onSend();
|
onSend();
|
||||||
break;
|
break;
|
||||||
case R.id.save:
|
case R.id.save:
|
||||||
onSave();
|
if (mEncryptCheckbox.isChecked()) {
|
||||||
|
showDialog(DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED);
|
||||||
|
} else {
|
||||||
|
onSave();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case R.id.discard:
|
case R.id.discard:
|
||||||
onDiscard();
|
onDiscard();
|
||||||
@ -1927,7 +1988,9 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBackPressed() {
|
public void onBackPressed() {
|
||||||
if (mDraftNeedsSaving) {
|
if (mEncryptCheckbox.isChecked()) {
|
||||||
|
showDialog(DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED);
|
||||||
|
} else if (mDraftNeedsSaving) {
|
||||||
showDialog(DIALOG_SAVE_OR_DISCARD_DRAFT_MESSAGE);
|
showDialog(DIALOG_SAVE_OR_DISCARD_DRAFT_MESSAGE);
|
||||||
} else {
|
} else {
|
||||||
super.onBackPressed();
|
super.onBackPressed();
|
||||||
@ -1954,6 +2017,34 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.create();
|
.create();
|
||||||
|
case DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED:
|
||||||
|
return new AlertDialog.Builder(this)
|
||||||
|
.setTitle(R.string.refuse_to_save_draft_marked_encrypted_dlg_title)
|
||||||
|
.setMessage(R.string.refuse_to_save_draft_marked_encrypted_instructions_fmt)
|
||||||
|
.setNeutralButton(R.string.okay_action, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
|
dismissDialog(DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.create();
|
||||||
|
case DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY:
|
||||||
|
return new AlertDialog.Builder(this)
|
||||||
|
.setTitle(R.string.continue_without_public_key_dlg_title)
|
||||||
|
.setMessage(R.string.continue_without_public_key_instructions_fmt)
|
||||||
|
.setPositiveButton(R.string.continue_action, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
|
dismissDialog(DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY);
|
||||||
|
mContinueWithoutPublicKey = true;
|
||||||
|
onSend();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.back_action, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
|
dismissDialog(DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY);
|
||||||
|
mContinueWithoutPublicKey = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.create();
|
||||||
}
|
}
|
||||||
return super.onCreateDialog(id);
|
return super.onCreateDialog(id);
|
||||||
}
|
}
|
||||||
@ -2220,17 +2311,17 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
? Integer.parseInt(k9identity.get(IdentityField.OFFSET))
|
? Integer.parseInt(k9identity.get(IdentityField.OFFSET))
|
||||||
: 0;
|
: 0;
|
||||||
Integer bodyFooterOffset = k9identity.get(IdentityField.FOOTER_OFFSET) != null
|
Integer bodyFooterOffset = k9identity.get(IdentityField.FOOTER_OFFSET) != null
|
||||||
? Integer.parseInt(k9identity.get(IdentityField.FOOTER_OFFSET))
|
? Integer.parseInt(k9identity.get(IdentityField.FOOTER_OFFSET))
|
||||||
: null;
|
: null;
|
||||||
Integer bodyPlainLength = k9identity.get(IdentityField.PLAIN_LENGTH) != null
|
Integer bodyPlainLength = k9identity.get(IdentityField.PLAIN_LENGTH) != null
|
||||||
? Integer.parseInt(k9identity.get(IdentityField.PLAIN_LENGTH))
|
? Integer.parseInt(k9identity.get(IdentityField.PLAIN_LENGTH))
|
||||||
: null;
|
: null;
|
||||||
Integer bodyPlainOffset = k9identity.get(IdentityField.PLAIN_OFFSET) != null
|
Integer bodyPlainOffset = k9identity.get(IdentityField.PLAIN_OFFSET) != null
|
||||||
? Integer.parseInt(k9identity.get(IdentityField.PLAIN_OFFSET))
|
? Integer.parseInt(k9identity.get(IdentityField.PLAIN_OFFSET))
|
||||||
: null;
|
: null;
|
||||||
mQuoteStyle = k9identity.get(IdentityField.QUOTE_STYLE) != null
|
mQuoteStyle = k9identity.get(IdentityField.QUOTE_STYLE) != null
|
||||||
? QuoteStyle.valueOf(k9identity.get(IdentityField.QUOTE_STYLE))
|
? QuoteStyle.valueOf(k9identity.get(IdentityField.QUOTE_STYLE))
|
||||||
: mAccount.getQuoteStyle();
|
: mAccount.getQuoteStyle();
|
||||||
|
|
||||||
// Always respect the user's current composition format preference, even if the
|
// Always respect the user's current composition format preference, even if the
|
||||||
// draft was saved in a different format.
|
// draft was saved in a different format.
|
||||||
@ -2319,7 +2410,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
* @throws MessagingException
|
* @throws MessagingException
|
||||||
*/
|
*/
|
||||||
private void processSourceMessageText(Message message, Integer bodyOffset, Integer bodyLength,
|
private void processSourceMessageText(Message message, Integer bodyOffset, Integer bodyLength,
|
||||||
boolean viewMessageContent) throws MessagingException {
|
boolean viewMessageContent) throws MessagingException {
|
||||||
Part textPart = MimeUtility.findFirstPartByMimeType(message, "text/plain");
|
Part textPart = MimeUtility.findFirstPartByMimeType(message, "text/plain");
|
||||||
if (textPart != null) {
|
if (textPart != null) {
|
||||||
String text = MimeUtility.getTextFromPart(textPart);
|
String text = MimeUtility.getTextFromPart(textPart);
|
||||||
@ -2338,7 +2429,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
// top-posting: ignore two newlines at start of quote
|
// top-posting: ignore two newlines at start of quote
|
||||||
quotedText.append(text.substring(bodyLength + 2));
|
quotedText.append(text.substring(bodyLength + 2));
|
||||||
} else if (bodyOffset + bodyLength == text.length() &&
|
} else if (bodyOffset + bodyLength == text.length() &&
|
||||||
text.substring(bodyOffset - 1, bodyOffset).equals("\n")) {
|
text.substring(bodyOffset - 1, bodyOffset).equals("\n")) {
|
||||||
// bottom-posting: ignore newline at end of quote
|
// bottom-posting: ignore newline at end of quote
|
||||||
quotedText.append(text.substring(0, bodyOffset - 1));
|
quotedText.append(text.substring(0, bodyOffset - 1));
|
||||||
} else {
|
} else {
|
||||||
@ -2367,8 +2458,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
private void populateUIWithQuotedMessage(boolean shown) throws MessagingException {
|
private void populateUIWithQuotedMessage(boolean shown) throws MessagingException {
|
||||||
if (mMessageFormat == MessageFormat.AUTO) {
|
if (mMessageFormat == MessageFormat.AUTO) {
|
||||||
mMessageFormat = MimeUtility.findFirstPartByMimeType(mSourceMessage, "text/html") == null
|
mMessageFormat = MimeUtility.findFirstPartByMimeType(mSourceMessage, "text/html") == null
|
||||||
? MessageFormat.TEXT
|
? MessageFormat.TEXT
|
||||||
: MessageFormat.HTML;
|
: MessageFormat.HTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO -- I am assuming that mSourceMessageBody will always be a text part. Is this a safe assumption?
|
// TODO -- I am assuming that mSourceMessageBody will always be a text part. Is this a safe assumption?
|
||||||
@ -2390,15 +2481,15 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
List<Integer> start = new ArrayList<Integer>();
|
List<Integer> start = new ArrayList<Integer>();
|
||||||
List<Integer> end = new ArrayList<Integer>();
|
List<Integer> end = new ArrayList<Integer>();
|
||||||
|
|
||||||
while(blockquoteStart.find()) {
|
while (blockquoteStart.find()) {
|
||||||
start.add(blockquoteStart.start());
|
start.add(blockquoteStart.start());
|
||||||
}
|
}
|
||||||
while(blockquoteEnd.find()) {
|
while (blockquoteEnd.find()) {
|
||||||
end.add(blockquoteEnd.start());
|
end.add(blockquoteEnd.start());
|
||||||
}
|
}
|
||||||
if (start.size() != end.size()) {
|
if (start.size() != end.size()) {
|
||||||
Log.d(K9.LOG_TAG, "There are " + start.size() + " <blockquote> tags, but " +
|
Log.d(K9.LOG_TAG, "There are " + start.size() + " <blockquote> tags, but " +
|
||||||
end.size() + " </blockquote> tags. Refusing to strip.");
|
end.size() + " </blockquote> tags. Refusing to strip.");
|
||||||
} else if (start.size() > 0) {
|
} else if (start.size() > 0) {
|
||||||
// Ignore quoted signatures in blockquotes.
|
// Ignore quoted signatures in blockquotes.
|
||||||
dashSignatureHtml.region(0, start.get(0));
|
dashSignatureHtml.region(0, start.get(0));
|
||||||
@ -2408,8 +2499,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < start.size() - 1; i++) {
|
for (int i = 0; i < start.size() - 1; i++) {
|
||||||
// within blockquotes.
|
// within blockquotes.
|
||||||
if (end.get(i) < start.get(i+1)) {
|
if (end.get(i) < start.get(i + 1)) {
|
||||||
dashSignatureHtml.region(end.get(i), start.get(i+1));
|
dashSignatureHtml.region(end.get(i), start.get(i + 1));
|
||||||
if (dashSignatureHtml.find()) {
|
if (dashSignatureHtml.find()) {
|
||||||
content = content.substring(0, dashSignatureHtml.start());
|
content = content.substring(0, dashSignatureHtml.start());
|
||||||
break;
|
break;
|
||||||
@ -2457,7 +2548,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
// Load the message with the reply header.
|
// Load the message with the reply header.
|
||||||
mQuotedHTML.loadDataWithBaseURL("http://", mQuotedHtmlContent.getQuotedContent(), "text/html", "utf-8", null);
|
mQuotedHTML.loadDataWithBaseURL("http://", mQuotedHtmlContent.getQuotedContent(), "text/html", "utf-8", null);
|
||||||
mQuotedText.setText(quoteOriginalTextMessage(mSourceMessage,
|
mQuotedText.setText(quoteOriginalTextMessage(mSourceMessage,
|
||||||
getBodyTextFromMessage(mSourceMessage, MessageFormat.TEXT), mQuoteStyle));
|
getBodyTextFromMessage(mSourceMessage, MessageFormat.TEXT), mQuoteStyle));
|
||||||
|
|
||||||
} else if (mMessageFormat == MessageFormat.TEXT) {
|
} else if (mMessageFormat == MessageFormat.TEXT) {
|
||||||
if (mAccount.isStripSignature() && (ACTION_REPLY_ALL.equals(getIntent().getAction()) ||
|
if (mAccount.isStripSignature() && (ACTION_REPLY_ALL.equals(getIntent().getAction()) ||
|
||||||
@ -2824,7 +2915,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
private class SaveMessageTask extends AsyncTask<Void, Void, Void> {
|
private class SaveMessageTask extends AsyncTask<Void, Void, Void> {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create the message from all the data the user has entered.
|
* Create the message from all the data the user has entered.
|
||||||
*/
|
*/
|
||||||
@ -2855,10 +2945,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
|
|||||||
Message draftMessage = messagingController.saveDraft(mAccount, message);
|
Message draftMessage = messagingController.saveDraft(mAccount, message);
|
||||||
mDraftUid = draftMessage.getUid();
|
mDraftUid = draftMessage.getUid();
|
||||||
|
|
||||||
// Don't display the toast if the user is just changing the orientation
|
mHandler.sendEmptyMessage(MSG_SAVED_DRAFT);
|
||||||
if ((getChangingConfigurations() & ActivityInfo.CONFIG_ORIENTATION) == 0) {
|
|
||||||
mHandler.sendEmptyMessage(MSG_SAVED_DRAFT);
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -526,13 +526,13 @@ public class MessageList
|
|||||||
}
|
}
|
||||||
|
|
||||||
String dispString = mAdapter.mListener.formatHeader(MessageList.this,
|
String dispString = mAdapter.mListener.formatHeader(MessageList.this,
|
||||||
getString(R.string.message_list_title, mAccount.getDescription(), displayName),
|
getString(R.string.message_list_title, mAccount.getDescription(), displayName),
|
||||||
mUnreadMessageCount, getTimeFormat());
|
mUnreadMessageCount, getTimeFormat());
|
||||||
setTitle(dispString);
|
setTitle(dispString);
|
||||||
} else if (mQueryString != null) {
|
} else if (mQueryString != null) {
|
||||||
if (mTitle != null) {
|
if (mTitle != null) {
|
||||||
String dispString = mAdapter.mListener.formatHeader(MessageList.this, mTitle,
|
String dispString = mAdapter.mListener.formatHeader(MessageList.this, mTitle,
|
||||||
mUnreadMessageCount, getTimeFormat());
|
mUnreadMessageCount, getTimeFormat());
|
||||||
setTitle(dispString);
|
setTitle(dispString);
|
||||||
} else {
|
} else {
|
||||||
setTitle(getString(R.string.search_results) + ": " + mQueryString);
|
setTitle(getString(R.string.search_results) + ": " + mQueryString);
|
||||||
@ -657,7 +657,7 @@ public class MessageList
|
|||||||
if (account != null && account.equals(mAccount) &&
|
if (account != null && account.equals(mAccount) &&
|
||||||
folderName != null && folderName.equals(mFolderName) &&
|
folderName != null && folderName.equals(mFolderName) &&
|
||||||
((queryString != null && queryString.equals(mQueryString)) ||
|
((queryString != null && queryString.equals(mQueryString)) ||
|
||||||
(queryString == null && mQueryString == null))) {
|
(queryString == null && mQueryString == null))) {
|
||||||
// We're likely just returning from the MessageView activity with "Manage back button"
|
// We're likely just returning from the MessageView activity with "Manage back button"
|
||||||
// enabled. So just leave the activity in the state it was left in.
|
// enabled. So just leave the activity in the state it was left in.
|
||||||
return;
|
return;
|
||||||
|
@ -92,7 +92,9 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMount(String providerId) { /* no-op */ }
|
public void onMount(String providerId) {
|
||||||
|
/* no-op */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -117,7 +119,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||||
boolean ret = false;
|
boolean ret = false;
|
||||||
if (KeyEvent.ACTION_DOWN == event.getAction()) {
|
if (KeyEvent.ACTION_DOWN == event.getAction()) {
|
||||||
ret = onKeyDown(event.getKeyCode(), event);
|
ret = onCustomKeyDown(event.getKeyCode(), event);
|
||||||
}
|
}
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
ret = super.dispatchKeyEvent(event);
|
ret = super.dispatchKeyEvent(event);
|
||||||
@ -125,29 +127,36 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public boolean onKeyDown(final int keyCode, final KeyEvent event) {
|
* Handle hotkeys
|
||||||
if (
|
*
|
||||||
// XXX TODO - when we go to android 2.0, uncomment this
|
* <p>
|
||||||
// android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ECLAIR &&
|
* This method is called by {@link #dispatchKeyEvent(KeyEvent)} before any view had the chance
|
||||||
keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
|
* to consume this key event.
|
||||||
// Take care of calling this method on earlier versions of
|
* </p>
|
||||||
// the platform where it doesn't exist.
|
*
|
||||||
onBackPressed();
|
* @param keyCode
|
||||||
return true;
|
* The value in {@code event.getKeyCode()}.
|
||||||
}
|
* @param event
|
||||||
|
* Description of the key event.
|
||||||
|
*
|
||||||
|
* @return {@code true} if this event was consumed.
|
||||||
|
*/
|
||||||
|
public boolean onCustomKeyDown(final int keyCode, final KeyEvent event) {
|
||||||
switch (keyCode) {
|
switch (keyCode) {
|
||||||
case KeyEvent.KEYCODE_VOLUME_UP: {
|
case KeyEvent.KEYCODE_VOLUME_UP: {
|
||||||
if (K9.useVolumeKeysForNavigationEnabled()) {
|
if (K9.useVolumeKeysForNavigationEnabled()) {
|
||||||
onNext();
|
onNext();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case KeyEvent.KEYCODE_VOLUME_DOWN: {
|
case KeyEvent.KEYCODE_VOLUME_DOWN: {
|
||||||
if (K9.useVolumeKeysForNavigationEnabled()) {
|
if (K9.useVolumeKeysForNavigationEnabled()) {
|
||||||
onPrevious();
|
onPrevious();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case KeyEvent.KEYCODE_SHIFT_LEFT:
|
case KeyEvent.KEYCODE_SHIFT_LEFT:
|
||||||
case KeyEvent.KEYCODE_SHIFT_RIGHT: {
|
case KeyEvent.KEYCODE_SHIFT_RIGHT: {
|
||||||
@ -222,7 +231,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return super.onKeyDown(keyCode, event);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -301,7 +310,7 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void actionView(Context context, MessageReference messRef,
|
public static void actionView(Context context, MessageReference messRef,
|
||||||
ArrayList<MessageReference> messReferences) {
|
ArrayList<MessageReference> messReferences) {
|
||||||
Intent i = new Intent(context, MessageView.class);
|
Intent i = new Intent(context, MessageView.class);
|
||||||
i.putExtra(EXTRA_MESSAGE_REFERENCE, messRef);
|
i.putExtra(EXTRA_MESSAGE_REFERENCE, messRef);
|
||||||
i.putParcelableArrayListExtra(EXTRA_MESSAGE_REFERENCES, messReferences);
|
i.putParcelableArrayListExtra(EXTRA_MESSAGE_REFERENCES, messReferences);
|
||||||
@ -1078,8 +1087,8 @@ public class MessageView extends K9Activity implements OnClickListener {
|
|||||||
mTopView.scrollTo(0, 0);
|
mTopView.scrollTo(0, 0);
|
||||||
try {
|
try {
|
||||||
if (MessageView.this.mMessage != null
|
if (MessageView.this.mMessage != null
|
||||||
&& MessageView.this.mMessage.isSet(Flag.X_DOWNLOADED_PARTIAL)
|
&& MessageView.this.mMessage.isSet(Flag.X_DOWNLOADED_PARTIAL)
|
||||||
&& message.isSet(Flag.X_DOWNLOADED_FULL)) {
|
&& message.isSet(Flag.X_DOWNLOADED_FULL)) {
|
||||||
mMessageView.setHeaders(message, account);
|
mMessageView.setHeaders(message, account);
|
||||||
}
|
}
|
||||||
MessageView.this.mMessage = message;
|
MessageView.this.mMessage = message;
|
||||||
|
@ -28,7 +28,7 @@ import android.os.AsyncTask;
|
|||||||
* @see #retain()
|
* @see #retain()
|
||||||
*/
|
*/
|
||||||
public abstract class ExtendedAsyncTask<Params, Progress, Result>
|
public abstract class ExtendedAsyncTask<Params, Progress, Result>
|
||||||
extends AsyncTask<Params, Progress, Result> implements NonConfigurationInstance {
|
extends AsyncTask<Params, Progress, Result> implements NonConfigurationInstance {
|
||||||
protected Activity mActivity;
|
protected Activity mActivity;
|
||||||
protected Context mContext;
|
protected Context mContext;
|
||||||
protected ProgressDialog mProgressDialog;
|
protected ProgressDialog mProgressDialog;
|
||||||
|
@ -96,6 +96,7 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||||||
private static final String PREFERENCE_SYNC_REMOTE_DELETIONS = "account_sync_remote_deletetions";
|
private static final String PREFERENCE_SYNC_REMOTE_DELETIONS = "account_sync_remote_deletetions";
|
||||||
private static final String PREFERENCE_CRYPTO_APP = "crypto_app";
|
private static final String PREFERENCE_CRYPTO_APP = "crypto_app";
|
||||||
private static final String PREFERENCE_CRYPTO_AUTO_SIGNATURE = "crypto_auto_signature";
|
private static final String PREFERENCE_CRYPTO_AUTO_SIGNATURE = "crypto_auto_signature";
|
||||||
|
private static final String PREFERENCE_CRYPTO_AUTO_ENCRYPT = "crypto_auto_encrypt";
|
||||||
|
|
||||||
private static final String PREFERENCE_LOCAL_STORAGE_PROVIDER = "local_storage_provider";
|
private static final String PREFERENCE_LOCAL_STORAGE_PROVIDER = "local_storage_provider";
|
||||||
|
|
||||||
@ -160,6 +161,7 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||||||
private ListPreference mMaxPushFolders;
|
private ListPreference mMaxPushFolders;
|
||||||
private ListPreference mCryptoApp;
|
private ListPreference mCryptoApp;
|
||||||
private CheckBoxPreference mCryptoAutoSignature;
|
private CheckBoxPreference mCryptoAutoSignature;
|
||||||
|
private CheckBoxPreference mCryptoAutoEncrypt;
|
||||||
|
|
||||||
private ListPreference mLocalStorageProvider;
|
private ListPreference mLocalStorageProvider;
|
||||||
|
|
||||||
@ -340,17 +342,17 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||||||
|
|
||||||
mExpungePolicy = (ListPreference) findPreference(PREFERENCE_EXPUNGE_POLICY);
|
mExpungePolicy = (ListPreference) findPreference(PREFERENCE_EXPUNGE_POLICY);
|
||||||
if (mIsExpungeCapable) {
|
if (mIsExpungeCapable) {
|
||||||
mExpungePolicy.setValue(mAccount.getExpungePolicy());
|
mExpungePolicy.setValue(mAccount.getExpungePolicy());
|
||||||
mExpungePolicy.setSummary(mExpungePolicy.getEntry());
|
mExpungePolicy.setSummary(mExpungePolicy.getEntry());
|
||||||
mExpungePolicy.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
mExpungePolicy.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
final String summary = newValue.toString();
|
final String summary = newValue.toString();
|
||||||
int index = mExpungePolicy.findIndexOfValue(summary);
|
int index = mExpungePolicy.findIndexOfValue(summary);
|
||||||
mExpungePolicy.setSummary(mExpungePolicy.getEntries()[index]);
|
mExpungePolicy.setSummary(mExpungePolicy.getEntries()[index]);
|
||||||
mExpungePolicy.setValue(summary);
|
mExpungePolicy.setValue(summary);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
((PreferenceScreen) findPreference(PREFERENCE_SCREEN_INCOMING)).removePreference(mExpungePolicy);
|
((PreferenceScreen) findPreference(PREFERENCE_SCREEN_INCOMING)).removePreference(mExpungePolicy);
|
||||||
}
|
}
|
||||||
@ -394,18 +396,18 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||||||
|
|
||||||
if (!mAccount.isSearchByDateCapable()) {
|
if (!mAccount.isSearchByDateCapable()) {
|
||||||
((PreferenceScreen) findPreference(PREFERENCE_SCREEN_INCOMING)).removePreference(mMessageAge);
|
((PreferenceScreen) findPreference(PREFERENCE_SCREEN_INCOMING)).removePreference(mMessageAge);
|
||||||
} else {
|
} else {
|
||||||
mMessageAge.setValue(String.valueOf(mAccount.getMaximumPolledMessageAge()));
|
mMessageAge.setValue(String.valueOf(mAccount.getMaximumPolledMessageAge()));
|
||||||
mMessageAge.setSummary(mMessageAge.getEntry());
|
mMessageAge.setSummary(mMessageAge.getEntry());
|
||||||
mMessageAge.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
mMessageAge.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
final String summary = newValue.toString();
|
final String summary = newValue.toString();
|
||||||
int index = mMessageAge.findIndexOfValue(summary);
|
int index = mMessageAge.findIndexOfValue(summary);
|
||||||
mMessageAge.setSummary(mMessageAge.getEntries()[index]);
|
mMessageAge.setSummary(mMessageAge.getEntries()[index]);
|
||||||
mMessageAge.setValue(summary);
|
mMessageAge.setValue(summary);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -526,22 +528,22 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mPushMode = (ListPreference) findPreference(PREFERENCE_PUSH_MODE);
|
mPushMode = (ListPreference) findPreference(PREFERENCE_PUSH_MODE);
|
||||||
mPushMode.setValue(mAccount.getFolderPushMode().name());
|
mPushMode.setValue(mAccount.getFolderPushMode().name());
|
||||||
mPushMode.setSummary(mPushMode.getEntry());
|
mPushMode.setSummary(mPushMode.getEntry());
|
||||||
mPushMode.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
mPushMode.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
final String summary = newValue.toString();
|
final String summary = newValue.toString();
|
||||||
int index = mPushMode.findIndexOfValue(summary);
|
int index = mPushMode.findIndexOfValue(summary);
|
||||||
mPushMode.setSummary(mPushMode.getEntries()[index]);
|
mPushMode.setSummary(mPushMode.getEntries()[index]);
|
||||||
mPushMode.setValue(summary);
|
mPushMode.setValue(summary);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
PreferenceScreen incomingPrefs = (PreferenceScreen) findPreference(PREFERENCE_SCREEN_INCOMING);
|
PreferenceScreen incomingPrefs = (PreferenceScreen) findPreference(PREFERENCE_SCREEN_INCOMING);
|
||||||
incomingPrefs.removePreference( (PreferenceScreen) findPreference(PREFERENCE_SCREEN_PUSH_ADVANCED));
|
incomingPrefs.removePreference((PreferenceScreen) findPreference(PREFERENCE_SCREEN_PUSH_ADVANCED));
|
||||||
incomingPrefs.removePreference( (ListPreference) findPreference(PREFERENCE_PUSH_MODE));
|
incomingPrefs.removePreference((ListPreference) findPreference(PREFERENCE_PUSH_MODE));
|
||||||
}
|
}
|
||||||
|
|
||||||
mAccountNotify = (CheckBoxPreference) findPreference(PREFERENCE_NOTIFY);
|
mAccountNotify = (CheckBoxPreference) findPreference(PREFERENCE_NOTIFY);
|
||||||
@ -680,14 +682,19 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||||||
mCryptoAutoSignature = (CheckBoxPreference) findPreference(PREFERENCE_CRYPTO_AUTO_SIGNATURE);
|
mCryptoAutoSignature = (CheckBoxPreference) findPreference(PREFERENCE_CRYPTO_AUTO_SIGNATURE);
|
||||||
mCryptoAutoSignature.setChecked(mAccount.getCryptoAutoSignature());
|
mCryptoAutoSignature.setChecked(mAccount.getCryptoAutoSignature());
|
||||||
|
|
||||||
|
mCryptoAutoEncrypt = (CheckBoxPreference) findPreference(PREFERENCE_CRYPTO_AUTO_ENCRYPT);
|
||||||
|
mCryptoAutoEncrypt.setChecked(mAccount.isCryptoAutoEncrypt());
|
||||||
|
|
||||||
handleCryptoAppDependencies();
|
handleCryptoAppDependencies();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleCryptoAppDependencies() {
|
private void handleCryptoAppDependencies() {
|
||||||
if ("".equals(mCryptoApp.getValue())) {
|
if ("".equals(mCryptoApp.getValue())) {
|
||||||
mCryptoAutoSignature.setEnabled(false);
|
mCryptoAutoSignature.setEnabled(false);
|
||||||
|
mCryptoAutoEncrypt.setEnabled(false);
|
||||||
} else {
|
} else {
|
||||||
mCryptoAutoSignature.setEnabled(true);
|
mCryptoAutoSignature.setEnabled(true);
|
||||||
|
mCryptoAutoEncrypt.setEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -733,6 +740,7 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||||||
mAccount.setStripSignature(mStripSignature.isChecked());
|
mAccount.setStripSignature(mStripSignature.isChecked());
|
||||||
mAccount.setCryptoApp(mCryptoApp.getValue());
|
mAccount.setCryptoApp(mCryptoApp.getValue());
|
||||||
mAccount.setCryptoAutoSignature(mCryptoAutoSignature.isChecked());
|
mAccount.setCryptoAutoSignature(mCryptoAutoSignature.isChecked());
|
||||||
|
mAccount.setCryptoAutoEncrypt(mCryptoAutoEncrypt.isChecked());
|
||||||
mAccount.setLocalStorageProviderId(mLocalStorageProvider.getValue());
|
mAccount.setLocalStorageProviderId(mLocalStorageProvider.getValue());
|
||||||
|
|
||||||
// In webdav account we use the exact folder name also for inbox,
|
// In webdav account we use the exact folder name also for inbox,
|
||||||
@ -783,21 +791,21 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||||||
mAccount.setShowPictures(Account.ShowPictures.valueOf(mAccountShowPictures.getValue()));
|
mAccount.setShowPictures(Account.ShowPictures.valueOf(mAccountShowPictures.getValue()));
|
||||||
mAccount.save(Preferences.getPreferences(this));
|
mAccount.save(Preferences.getPreferences(this));
|
||||||
|
|
||||||
if (mIsPushCapable) {
|
if (mIsPushCapable) {
|
||||||
boolean needsPushRestart = mAccount.setFolderPushMode(Account.FolderMode.valueOf(mPushMode.getValue()));
|
boolean needsPushRestart = mAccount.setFolderPushMode(Account.FolderMode.valueOf(mPushMode.getValue()));
|
||||||
if (mAccount.getFolderPushMode() != FolderMode.NONE) {
|
if (mAccount.getFolderPushMode() != FolderMode.NONE) {
|
||||||
needsPushRestart |= displayModeChanged;
|
needsPushRestart |= displayModeChanged;
|
||||||
needsPushRestart |= mIncomingChanged;
|
needsPushRestart |= mIncomingChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needsRefresh && needsPushRestart) {
|
if (needsRefresh && needsPushRestart) {
|
||||||
MailService.actionReset(this, null);
|
MailService.actionReset(this, null);
|
||||||
} else if (needsRefresh) {
|
} else if (needsRefresh) {
|
||||||
MailService.actionReschedulePoll(this, null);
|
MailService.actionReschedulePoll(this, null);
|
||||||
} else if (needsPushRestart) {
|
} else if (needsPushRestart) {
|
||||||
MailService.actionRestartPushers(this, null);
|
MailService.actionRestartPushers(this, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: refresh folder list here
|
// TODO: refresh folder list here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,8 +170,8 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
|||||||
cve);
|
cve);
|
||||||
} else {
|
} else {
|
||||||
showErrorDialog(
|
showErrorDialog(
|
||||||
R.string.account_setup_failed_dlg_server_message_fmt,
|
R.string.account_setup_failed_dlg_server_message_fmt,
|
||||||
(cve.getMessage() == null ? "" : cve.getMessage()));
|
(cve.getMessage() == null ? "" : cve.getMessage()));
|
||||||
}
|
}
|
||||||
} catch (final Throwable t) {
|
} catch (final Throwable t) {
|
||||||
Log.e(K9.LOG_TAG, "Error while testing settings", t);
|
Log.e(K9.LOG_TAG, "Error while testing settings", t);
|
||||||
|
@ -89,7 +89,7 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
|
|||||||
mAccount = Preferences.getPreferences(this).getAccount(accountUuid);
|
mAccount = Preferences.getPreferences(this).getAccount(accountUuid);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String scheme = new URI(mAccount.getStoreUri()).getScheme();
|
String scheme = new URI(mAccount.getStoreUri()).getScheme();
|
||||||
if (scheme.startsWith("webdav") || scheme.startsWith("eas")) {
|
if (scheme.startsWith("webdav") || scheme.startsWith("eas")) {
|
||||||
mAccount.setTransportUri(mAccount.getStoreUri());
|
mAccount.setTransportUri(mAccount.getStoreUri());
|
||||||
AccountSetupCheckSettings.actionCheckSettings(this, mAccount, false, true);
|
AccountSetupCheckSettings.actionCheckSettings(this, mAccount, false, true);
|
||||||
|
@ -467,23 +467,23 @@ public class MessagingController implements Runnable {
|
|||||||
localFolderNames.add(localFolder.getRemoteName());
|
localFolderNames.add(localFolder.getRemoteName());
|
||||||
}
|
}
|
||||||
for (Folder remoteFolder : remoteFolders) {
|
for (Folder remoteFolder : remoteFolders) {
|
||||||
LocalFolder localFolder = null;
|
LocalFolder localFolder = null;
|
||||||
if (localFolderNames.contains(remoteFolder.getRemoteName()) == false) {
|
if (localFolderNames.contains(remoteFolder.getRemoteName()) == false) {
|
||||||
localFolder = localStore.getFolder(remoteFolder.getRemoteName(),
|
localFolder = localStore.getFolder(remoteFolder.getRemoteName(),
|
||||||
remoteFolder.getName());
|
remoteFolder.getName());
|
||||||
foldersToCreate.add(localFolder);
|
foldersToCreate.add(localFolder);
|
||||||
} else {
|
} else {
|
||||||
for (Folder folder : localFolders) {
|
for (Folder folder : localFolders) {
|
||||||
if (folder.getRemoteName().equals(remoteFolder.getRemoteName())) {
|
if (folder.getRemoteName().equals(remoteFolder.getRemoteName())) {
|
||||||
localFolder = (LocalFolder)folder;
|
localFolder = (LocalFolder)folder;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
remoteFolderNames.add(remoteFolder.getRemoteName());
|
remoteFolderNames.add(remoteFolder.getRemoteName());
|
||||||
|
|
||||||
if (remoteFolder instanceof EasFolder) {
|
if (remoteFolder instanceof EasFolder) {
|
||||||
((EasFolder)remoteFolder).setLocalFolder(localFolder, false);
|
((EasFolder)remoteFolder).setLocalFolder(localFolder, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
localStore.createFolders(foldersToCreate, account.getDisplayCount());
|
localStore.createFolders(foldersToCreate, account.getDisplayCount());
|
||||||
@ -495,7 +495,7 @@ public class MessagingController implements Runnable {
|
|||||||
*/
|
*/
|
||||||
for (Folder localFolder : localFolders) {
|
for (Folder localFolder : localFolders) {
|
||||||
if (!account.isSpecialFolder(localFolder.getRemoteName()) &&
|
if (!account.isSpecialFolder(localFolder.getRemoteName()) &&
|
||||||
!remoteFolderNames.contains(localFolder.getRemoteName())) {
|
!remoteFolderNames.contains(localFolder.getRemoteName())) {
|
||||||
localFolder.delete(false);
|
localFolder.delete(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1019,18 +1019,18 @@ public class MessagingController implements Runnable {
|
|||||||
if (account.syncRemoteDeletions()) {
|
if (account.syncRemoteDeletions()) {
|
||||||
ArrayList<Message> destroyMessages = new ArrayList<Message>();
|
ArrayList<Message> destroyMessages = new ArrayList<Message>();
|
||||||
if (remoteFolder.isSyncMode()) {
|
if (remoteFolder.isSyncMode()) {
|
||||||
for (Message localMessage : localMessages) {
|
for (Message localMessage : localMessages) {
|
||||||
Message remoteMessage = remoteUidMap.get(localMessage.getUid());
|
Message remoteMessage = remoteUidMap.get(localMessage.getUid());
|
||||||
if (remoteMessage != null && remoteMessage.isSet(Flag.DELETED)) {
|
if (remoteMessage != null && remoteMessage.isSet(Flag.DELETED)) {
|
||||||
destroyMessages.add(localMessage);
|
destroyMessages.add(localMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (Message localMessage : localMessages) {
|
for (Message localMessage : localMessages) {
|
||||||
if (remoteUidMap.get(localMessage.getUid()) == null) {
|
if (remoteUidMap.get(localMessage.getUid()) == null) {
|
||||||
destroyMessages.add(localMessage);
|
destroyMessages.add(localMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4312,7 +4312,7 @@ public class MessagingController implements Runnable {
|
|||||||
|
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
putBackground("Push messageArrived of account " + account.getDescription()
|
putBackground("Push messageArrived of account " + account.getDescription()
|
||||||
+ ", folder " + remoteFolder.getName(), null, new Runnable() {
|
+ ", folder " + remoteFolder.getName(), null, new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
LocalFolder localFolder = null;
|
LocalFolder localFolder = null;
|
||||||
|
@ -232,6 +232,95 @@ public class Apg extends CryptoProvider {
|
|||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get public key ids based on a given email.
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param email The email in question.
|
||||||
|
* @return key ids
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long[] getPublicKeyIdsFromEmail(Context context, String email) {
|
||||||
|
long ids[] = null;
|
||||||
|
try {
|
||||||
|
Uri contentUri = Uri.withAppendedPath(Apg.CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS, email);
|
||||||
|
Cursor c = context.getContentResolver().query(contentUri,
|
||||||
|
new String[] { "master_key_id" }, null, null, null);
|
||||||
|
if (c != null && c.getCount() > 0) {
|
||||||
|
ids = new long[c.getCount()];
|
||||||
|
while (c.moveToNext()) {
|
||||||
|
ids[c.getPosition()] = c.getLong(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c != null) {
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
Toast.makeText(context,
|
||||||
|
context.getResources().getString(R.string.insufficient_apg_permissions),
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find out if a given email has a secret key.
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param email The email in question.
|
||||||
|
* @return true if there is a secret key for this email.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean hasSecretKeyForEmail(Context context, String email) {
|
||||||
|
try {
|
||||||
|
Uri contentUri = Uri.withAppendedPath(Apg.CONTENT_URI_SECRET_KEY_RING_BY_EMAILS, email);
|
||||||
|
Cursor c = context.getContentResolver().query(contentUri,
|
||||||
|
new String[] { "master_key_id" }, null, null, null);
|
||||||
|
if (c != null && c.getCount() > 0) {
|
||||||
|
c.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (c != null) {
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
Toast.makeText(context,
|
||||||
|
context.getResources().getString(R.string.insufficient_apg_permissions),
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find out if a given email has a public key.
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param email The email in question.
|
||||||
|
* @return true if there is a public key for this email.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean hasPublicKeyForEmail(Context context, String email) {
|
||||||
|
try {
|
||||||
|
Uri contentUri = Uri.withAppendedPath(Apg.CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS, email);
|
||||||
|
Cursor c = context.getContentResolver().query(contentUri,
|
||||||
|
new String[] { "master_key_id" }, null, null, null);
|
||||||
|
if (c != null && c.getCount() > 0) {
|
||||||
|
c.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (c != null) {
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
Toast.makeText(context,
|
||||||
|
context.getResources().getString(R.string.insufficient_apg_permissions),
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the user id based on the key id.
|
* Get the user id based on the key id.
|
||||||
*
|
*
|
||||||
|
@ -24,6 +24,9 @@ abstract public class CryptoProvider {
|
|||||||
abstract public boolean encrypt(Activity activity, String data, PgpData pgpData);
|
abstract public boolean encrypt(Activity activity, String data, PgpData pgpData);
|
||||||
abstract public boolean decrypt(Activity activity, String data, PgpData pgpData);
|
abstract public boolean decrypt(Activity activity, String data, PgpData pgpData);
|
||||||
abstract public long[] getSecretKeyIdsFromEmail(Context context, String email);
|
abstract public long[] getSecretKeyIdsFromEmail(Context context, String email);
|
||||||
|
abstract public long[] getPublicKeyIdsFromEmail(Context context, String email);
|
||||||
|
abstract public boolean hasSecretKeyForEmail(Context context, String email);
|
||||||
|
abstract public boolean hasPublicKeyForEmail(Context context, String email);
|
||||||
abstract public String getUserId(Context context, long keyId);
|
abstract public String getUserId(Context context, long keyId);
|
||||||
abstract public String getName();
|
abstract public String getName();
|
||||||
abstract public boolean test(Context context);
|
abstract public boolean test(Context context);
|
||||||
|
@ -37,6 +37,21 @@ public class None extends CryptoProvider {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long[] getPublicKeyIdsFromEmail(Context context, String email) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSecretKeyForEmail(Context context, String email) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasPublicKeyForEmail(Context context, String email) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUserId(Context context, long keyId) {
|
public String getUserId(Context context, long keyId) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -136,28 +136,28 @@ public class Regex {
|
|||||||
// matching as foo.su
|
// matching as foo.su
|
||||||
|
|
||||||
public static final Pattern IP_ADDRESS_PATTERN
|
public static final Pattern IP_ADDRESS_PATTERN
|
||||||
= Pattern.compile(
|
= Pattern.compile(
|
||||||
"((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
|
"((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
|
||||||
+ "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
|
+ "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
|
||||||
+ "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
|
+ "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
|
||||||
+ "|[1-9][0-9]|[0-9]))");
|
+ "|[1-9][0-9]|[0-9]))");
|
||||||
|
|
||||||
public static final Pattern DOMAIN_NAME_PATTERN
|
public static final Pattern DOMAIN_NAME_PATTERN
|
||||||
= Pattern.compile(
|
= Pattern.compile(
|
||||||
"(((([" + GOOD_IRI_CHAR + "][" + GOOD_IRI_CHAR + "\\-]*)*[" + GOOD_IRI_CHAR + "]\\.)+"
|
"(((([" + GOOD_IRI_CHAR + "][" + GOOD_IRI_CHAR + "\\-]*)*[" + GOOD_IRI_CHAR + "]\\.)+"
|
||||||
+ TOP_LEVEL_DOMAIN_PATTERN + ")|"
|
+ TOP_LEVEL_DOMAIN_PATTERN + ")|"
|
||||||
+ IP_ADDRESS_PATTERN + ")");
|
+ IP_ADDRESS_PATTERN + ")");
|
||||||
|
|
||||||
public static final Pattern EMAIL_ADDRESS_PATTERN
|
public static final Pattern EMAIL_ADDRESS_PATTERN
|
||||||
= Pattern.compile(
|
= Pattern.compile(
|
||||||
"[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" +
|
"[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" +
|
||||||
"\\@" +
|
"\\@" +
|
||||||
"[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" +
|
"[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" +
|
||||||
"(" +
|
"(" +
|
||||||
"\\." +
|
"\\." +
|
||||||
"[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" +
|
"[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" +
|
||||||
")+"
|
")+"
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This pattern is intended for searching for things that look like they
|
* This pattern is intended for searching for things that look like they
|
||||||
@ -174,10 +174,10 @@ public class Regex {
|
|||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public static final Pattern PHONE_PATTERN
|
public static final Pattern PHONE_PATTERN
|
||||||
= Pattern.compile( // sdd = space, dot, or dash
|
= Pattern.compile( // sdd = space, dot, or dash
|
||||||
"(\\+[0-9]+[\\- \\.]*)?" // +<digits><sdd>*
|
"(\\+[0-9]+[\\- \\.]*)?" // +<digits><sdd>*
|
||||||
+ "(\\([0-9]+\\)[\\- \\.]*)?" // (<digits>)<sdd>*
|
+ "(\\([0-9]+\\)[\\- \\.]*)?" // (<digits>)<sdd>*
|
||||||
+ "([0-9][0-9\\- \\.][0-9\\- \\.]+[0-9])"); // <digit><digit|sdd>+<digit>
|
+ "([0-9][0-9\\- \\.][0-9\\- \\.]+[0-9])"); // <digit><digit|sdd>+<digit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method to take all of the non-null matching groups in a
|
* Convenience method to take all of the non-null matching groups in a
|
||||||
|
@ -2,7 +2,7 @@ package com.fsck.k9.helper;
|
|||||||
|
|
||||||
public final class StringUtils {
|
public final class StringUtils {
|
||||||
|
|
||||||
public static boolean isNullOrEmpty(String string){
|
public static boolean isNullOrEmpty(String string) {
|
||||||
return string == null || string.length() == 0;
|
return string == null || string.length() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ public class Utility {
|
|||||||
if (view.getText() != null) {
|
if (view.getText() != null) {
|
||||||
String s = view.getText().toString();
|
String s = view.getText().toString();
|
||||||
if (s.matches("^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)*[a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?$") &&
|
if (s.matches("^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)*[a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?$") &&
|
||||||
s.length() <= 253) {
|
s.length() <= 253) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (s.matches("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$")) {
|
if (s.matches("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$")) {
|
||||||
|
@ -151,7 +151,7 @@ public class Address {
|
|||||||
} catch (MimeException pe) {
|
} catch (MimeException pe) {
|
||||||
Log.e(K9.LOG_TAG, "MimeException in Address.parse()", pe);
|
Log.e(K9.LOG_TAG, "MimeException in Address.parse()", pe);
|
||||||
//but we do an silent failover : we just use the given string as name with empty address
|
//but we do an silent failover : we just use the given string as name with empty address
|
||||||
addresses.add(new Address(null, addressList,false));
|
addresses.add(new Address(null, addressList, false));
|
||||||
}
|
}
|
||||||
return addresses.toArray(EMPTY_ADDRESS_ARRAY);
|
return addresses.toArray(EMPTY_ADDRESS_ARRAY);
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ public abstract class Folder {
|
|||||||
public abstract String getUidFromMessageId(Message message) throws MessagingException;
|
public abstract String getUidFromMessageId(Message message) throws MessagingException;
|
||||||
|
|
||||||
public void expunge() throws MessagingException
|
public void expunge() throws MessagingException
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public abstract void fetch(Message[] messages, FetchProfile fp,
|
public abstract void fetch(Message[] messages, FetchProfile fp,
|
||||||
MessageRetrievalListener listener) throws MessagingException;
|
MessageRetrievalListener listener) throws MessagingException;
|
||||||
@ -220,7 +220,7 @@ public abstract class Folder {
|
|||||||
return mAccount;
|
return mAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSyncMode() {
|
public boolean isSyncMode() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,8 +82,8 @@ public class ServerSettings {
|
|||||||
* see {@link ServerSettings#password}
|
* see {@link ServerSettings#password}
|
||||||
*/
|
*/
|
||||||
public ServerSettings(String type, String host, int port,
|
public ServerSettings(String type, String host, int port,
|
||||||
ConnectionSecurity connectionSecurity, String authenticationType, String username,
|
ConnectionSecurity connectionSecurity, String authenticationType, String username,
|
||||||
String password) {
|
String password) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.host = host;
|
this.host = host;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
@ -128,6 +128,6 @@ public class ServerSettings {
|
|||||||
|
|
||||||
public ServerSettings newPassword(String newPassword) {
|
public ServerSettings newPassword(String newPassword) {
|
||||||
return new ServerSettings(type, host, port, connectionSecurity, authenticationType,
|
return new ServerSettings(type, host, port, connectionSecurity, authenticationType,
|
||||||
username, newPassword);
|
username, newPassword);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,9 +10,9 @@ import java.io.InputStream;
|
|||||||
* past where the protocol handler intended the client to read.
|
* past where the protocol handler intended the client to read.
|
||||||
*/
|
*/
|
||||||
public class FixedLengthInputStream extends InputStream {
|
public class FixedLengthInputStream extends InputStream {
|
||||||
private InputStream mIn;
|
private final InputStream mIn;
|
||||||
private int mLength;
|
private final int mLength;
|
||||||
private int mCount;
|
private int mCount = 0;
|
||||||
|
|
||||||
public FixedLengthInputStream(InputStream in, int length) {
|
public FixedLengthInputStream(InputStream in, int length) {
|
||||||
this.mIn = in;
|
this.mIn = in;
|
||||||
@ -26,27 +26,28 @@ public class FixedLengthInputStream extends InputStream {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
if (mCount < mLength) {
|
if (mCount >= mLength) {
|
||||||
mCount++;
|
|
||||||
return mIn.read();
|
|
||||||
} else {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int d = mIn.read();
|
||||||
|
if (d != -1) {
|
||||||
|
mCount++;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(byte[] b, int offset, int length) throws IOException {
|
public int read(byte[] b, int offset, int length) throws IOException {
|
||||||
if (mCount < mLength) {
|
if (mCount >= mLength) {
|
||||||
int d = mIn.read(b, offset, Math.min(mLength - mCount, length));
|
|
||||||
if (d == -1) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
mCount += d;
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int d = mIn.read(b, offset, Math.min(mLength - mCount, length));
|
||||||
|
if (d != -1) {
|
||||||
|
mCount += d;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -54,6 +55,15 @@ public class FixedLengthInputStream extends InputStream {
|
|||||||
return read(b, 0, b.length);
|
return read(b, 0, b.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long skip(long n) throws IOException {
|
||||||
|
long d = mIn.skip(Math.min(n, available()));
|
||||||
|
if (d > 0) {
|
||||||
|
mCount += d;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("FixedLengthInputStream(in=%s, length=%d)", mIn.toString(), mLength);
|
return String.format("FixedLengthInputStream(in=%s, length=%d)", mIn.toString(), mLength);
|
||||||
|
@ -109,7 +109,10 @@ public class MimeHeader {
|
|||||||
v = EncoderUtil.encodeEncodedWord(field.value, charset);
|
v = EncoderUtil.encodeEncodedWord(field.value, charset);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.write(field.name + ": " + v + "\r\n");
|
writer.write(field.name);
|
||||||
|
writer.write(": ");
|
||||||
|
writer.write(v);
|
||||||
|
writer.write("\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writer.flush();
|
writer.flush();
|
||||||
|
@ -70,22 +70,29 @@ public class MimeMultipart extends Multipart {
|
|||||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
|
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
|
||||||
|
|
||||||
if (mPreamble != null) {
|
if (mPreamble != null) {
|
||||||
writer.write(mPreamble + "\r\n");
|
writer.write(mPreamble);
|
||||||
|
writer.write("\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mParts.isEmpty()) {
|
if (mParts.isEmpty()) {
|
||||||
writer.write("--" + mBoundary + "\r\n");
|
writer.write("--");
|
||||||
|
writer.write(mBoundary);
|
||||||
|
writer.write("\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0, count = mParts.size(); i < count; i++) {
|
for (int i = 0, count = mParts.size(); i < count; i++) {
|
||||||
BodyPart bodyPart = mParts.get(i);
|
BodyPart bodyPart = mParts.get(i);
|
||||||
writer.write("--" + mBoundary + "\r\n");
|
writer.write("--");
|
||||||
|
writer.write(mBoundary);
|
||||||
|
writer.write("\r\n");
|
||||||
writer.flush();
|
writer.flush();
|
||||||
bodyPart.writeTo(out);
|
bodyPart.writeTo(out);
|
||||||
writer.write("\r\n");
|
writer.write("\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.write("--" + mBoundary + "--\r\n");
|
writer.write("--");
|
||||||
|
writer.write(mBoundary);
|
||||||
|
writer.write("--\r\n");
|
||||||
writer.flush();
|
writer.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,7 +888,8 @@ public class MimeUtility {
|
|||||||
*/
|
*/
|
||||||
private static final String[][] MIME_TYPE_REPLACEMENT_MAP = new String[][] {
|
private static final String[][] MIME_TYPE_REPLACEMENT_MAP = new String[][] {
|
||||||
{"image/jpg", "image/jpeg"},
|
{"image/jpg", "image/jpeg"},
|
||||||
{"image/pjpeg", "image/jpeg"} // see issue 1712
|
{"image/pjpeg", "image/jpeg"}, // see issue 1712
|
||||||
|
{"application/x-zip-compressed", "application/zip"} // see issue 3791
|
||||||
};
|
};
|
||||||
|
|
||||||
public static String unfold(String s) {
|
public static String unfold(String s) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -223,7 +223,7 @@ public class ImapStore extends Store {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new ImapStoreSettings(host, port, connectionSecurity, authenticationType, username,
|
return new ImapStoreSettings(host, port, connectionSecurity, authenticationType, username,
|
||||||
password, pathPrefix);
|
password, pathPrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -243,30 +243,29 @@ public class ImapStore extends Store {
|
|||||||
try {
|
try {
|
||||||
userEnc = URLEncoder.encode(server.username, "UTF-8");
|
userEnc = URLEncoder.encode(server.username, "UTF-8");
|
||||||
passwordEnc = (server.password != null) ?
|
passwordEnc = (server.password != null) ?
|
||||||
URLEncoder.encode(server.password, "UTF-8") : "";
|
URLEncoder.encode(server.password, "UTF-8") : "";
|
||||||
}
|
} catch (UnsupportedEncodingException e) {
|
||||||
catch (UnsupportedEncodingException e) {
|
|
||||||
throw new IllegalArgumentException("Could not encode username or password", e);
|
throw new IllegalArgumentException("Could not encode username or password", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
String scheme;
|
String scheme;
|
||||||
switch (server.connectionSecurity) {
|
switch (server.connectionSecurity) {
|
||||||
case SSL_TLS_OPTIONAL:
|
case SSL_TLS_OPTIONAL:
|
||||||
scheme = "imap+ssl";
|
scheme = "imap+ssl";
|
||||||
break;
|
break;
|
||||||
case SSL_TLS_REQUIRED:
|
case SSL_TLS_REQUIRED:
|
||||||
scheme = "imap+ssl+";
|
scheme = "imap+ssl+";
|
||||||
break;
|
break;
|
||||||
case STARTTLS_OPTIONAL:
|
case STARTTLS_OPTIONAL:
|
||||||
scheme = "imap+tls";
|
scheme = "imap+tls";
|
||||||
break;
|
break;
|
||||||
case STARTTLS_REQUIRED:
|
case STARTTLS_REQUIRED:
|
||||||
scheme = "imap+tls+";
|
scheme = "imap+tls+";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
case NONE:
|
case NONE:
|
||||||
scheme = "imap";
|
scheme = "imap";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthType authType;
|
AuthType authType;
|
||||||
@ -274,16 +273,16 @@ public class ImapStore extends Store {
|
|||||||
authType = AuthType.valueOf(server.authenticationType);
|
authType = AuthType.valueOf(server.authenticationType);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IllegalArgumentException("Invalid authentication type: " +
|
throw new IllegalArgumentException("Invalid authentication type: " +
|
||||||
server.authenticationType);
|
server.authenticationType);
|
||||||
}
|
}
|
||||||
|
|
||||||
String userInfo = authType.toString() + ":" + userEnc + ":" + passwordEnc;
|
String userInfo = authType.toString() + ":" + userEnc + ":" + passwordEnc;
|
||||||
try {
|
try {
|
||||||
Map<String, String> extra = server.getExtra();
|
Map<String, String> extra = server.getExtra();
|
||||||
String prefix = (extra != null) ? extra.get(ImapStoreSettings.PATH_PREFIX_KEY) : null;
|
String path = (extra != null) ? "/" + extra.get(ImapStoreSettings.PATH_PREFIX_KEY) : null;
|
||||||
return new URI(scheme, userInfo, server.host, server.port,
|
return new URI(scheme, userInfo, server.host, server.port,
|
||||||
prefix,
|
path,
|
||||||
null, null).toString();
|
null, null).toString();
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
throw new IllegalArgumentException("Can't create ImapStore URI", e);
|
throw new IllegalArgumentException("Can't create ImapStore URI", e);
|
||||||
}
|
}
|
||||||
@ -300,9 +299,9 @@ public class ImapStore extends Store {
|
|||||||
public final String pathPrefix;
|
public final String pathPrefix;
|
||||||
|
|
||||||
protected ImapStoreSettings(String host, int port, ConnectionSecurity connectionSecurity,
|
protected ImapStoreSettings(String host, int port, ConnectionSecurity connectionSecurity,
|
||||||
String authenticationType, String username, String password, String pathPrefix) {
|
String authenticationType, String username, String password, String pathPrefix) {
|
||||||
super(STORE_TYPE, host, port, connectionSecurity, authenticationType, username,
|
super(STORE_TYPE, host, port, connectionSecurity, authenticationType, username,
|
||||||
password);
|
password);
|
||||||
this.pathPrefix = pathPrefix;
|
this.pathPrefix = pathPrefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,7 +315,7 @@ public class ImapStore extends Store {
|
|||||||
@Override
|
@Override
|
||||||
public ServerSettings newPassword(String newPassword) {
|
public ServerSettings newPassword(String newPassword) {
|
||||||
return new ImapStoreSettings(host, port, connectionSecurity, authenticationType,
|
return new ImapStoreSettings(host, port, connectionSecurity, authenticationType,
|
||||||
username, newPassword, pathPrefix);
|
username, newPassword, pathPrefix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -613,7 +612,7 @@ public class ImapStore extends Store {
|
|||||||
if (connection.capabilities.contains("XLIST")) {
|
if (connection.capabilities.contains("XLIST")) {
|
||||||
if (K9.DEBUG) Log.d(K9.LOG_TAG, "Folder auto-configuration: Using XLIST.");
|
if (K9.DEBUG) Log.d(K9.LOG_TAG, "Folder auto-configuration: Using XLIST.");
|
||||||
commandResponse = "XLIST";
|
commandResponse = "XLIST";
|
||||||
} else if(connection.capabilities.contains("SPECIAL-USE")) {
|
} else if (connection.capabilities.contains("SPECIAL-USE")) {
|
||||||
if (K9.DEBUG) Log.d(K9.LOG_TAG, "Folder auto-configuration: Using RFC6154/SPECIAL-USE.");
|
if (K9.DEBUG) Log.d(K9.LOG_TAG, "Folder auto-configuration: Using RFC6154/SPECIAL-USE.");
|
||||||
commandResponse = "LIST";
|
commandResponse = "LIST";
|
||||||
commandOptions = " (SPECIAL-USE)";
|
commandOptions = " (SPECIAL-USE)";
|
||||||
@ -624,7 +623,7 @@ public class ImapStore extends Store {
|
|||||||
|
|
||||||
final List<ImapResponse> responses =
|
final List<ImapResponse> responses =
|
||||||
connection.executeSimpleCommand(String.format("%s%s \"\" %s", commandResponse, commandOptions,
|
connection.executeSimpleCommand(String.format("%s%s \"\" %s", commandResponse, commandOptions,
|
||||||
encodeString(getCombinedPrefix() + "*")));
|
encodeString(getCombinedPrefix() + "*")));
|
||||||
|
|
||||||
for (ImapResponse response : responses) {
|
for (ImapResponse response : responses) {
|
||||||
if (ImapResponseParser.equalsIgnoreCase(response.get(0), commandResponse)) {
|
if (ImapResponseParser.equalsIgnoreCase(response.get(0), commandResponse)) {
|
||||||
@ -634,7 +633,7 @@ public class ImapStore extends Store {
|
|||||||
decodedFolderName = decodeFolderName(response.getString(3));
|
decodedFolderName = decodeFolderName(response.getString(3));
|
||||||
} catch (CharacterCodingException e) {
|
} catch (CharacterCodingException e) {
|
||||||
Log.w(K9.LOG_TAG, "Folder name not correctly encoded with the UTF-7 variant " +
|
Log.w(K9.LOG_TAG, "Folder name not correctly encoded with the UTF-7 variant " +
|
||||||
"as defined by RFC 3501: " + response.getString(3), e);
|
"as defined by RFC 3501: " + response.getString(3), e);
|
||||||
// We currently just skip folders with malformed names.
|
// We currently just skip folders with malformed names.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1757,8 +1756,8 @@ public class ImapStore extends Store {
|
|||||||
*/
|
*/
|
||||||
for (int i = 0, count = bodyParams.size(); i < count; i += 2) {
|
for (int i = 0, count = bodyParams.size(); i < count; i += 2) {
|
||||||
contentType.append(String.format(";\n %s=\"%s\"",
|
contentType.append(String.format(";\n %s=\"%s\"",
|
||||||
bodyParams.getString(i),
|
bodyParams.getString(i),
|
||||||
bodyParams.getString(i + 1)));
|
bodyParams.getString(i + 1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1792,8 +1791,8 @@ public class ImapStore extends Store {
|
|||||||
*/
|
*/
|
||||||
for (int i = 0, count = bodyDispositionParams.size(); i < count; i += 2) {
|
for (int i = 0, count = bodyDispositionParams.size(); i < count; i += 2) {
|
||||||
contentDisposition.append(String.format(";\n %s=\"%s\"",
|
contentDisposition.append(String.format(";\n %s=\"%s\"",
|
||||||
bodyDispositionParams.getString(i).toLowerCase(Locale.US),
|
bodyDispositionParams.getString(i).toLowerCase(Locale.US),
|
||||||
bodyDispositionParams.getString(i + 1)));
|
bodyDispositionParams.getString(i + 1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,8 +103,8 @@ public class LocalStore extends Store implements Serializable {
|
|||||||
+ "bcc_list, reply_to_list, attachment_count, internal_date, message_id, folder_id, preview ";
|
+ "bcc_list, reply_to_list, attachment_count, internal_date, message_id, folder_id, preview ";
|
||||||
|
|
||||||
static private String GET_FOLDER_COLS = "id, name, unread_count, visible_limit, last_updated, status, "
|
static private String GET_FOLDER_COLS = "id, name, unread_count, visible_limit, last_updated, status, "
|
||||||
+ "push_state, last_pushed, flagged_count, integrate, top_group, poll_class, push_class, "
|
+ "push_state, last_pushed, flagged_count, integrate, top_group, poll_class, push_class, "
|
||||||
+ "display_class, remote_name";
|
+ "display_class, remote_name";
|
||||||
|
|
||||||
protected static final int DB_VERSION = 44;
|
protected static final int DB_VERSION = 44;
|
||||||
|
|
||||||
@ -301,8 +301,7 @@ public class LocalStore extends Store implements Serializable {
|
|||||||
Log.e(K9.LOG_TAG, " error trying to ugpgrade a folder class", e);
|
Log.e(K9.LOG_TAG, " error trying to ugpgrade a folder class", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} catch (SQLiteException e) {
|
||||||
catch (SQLiteException e) {
|
|
||||||
Log.e(K9.LOG_TAG, "Exception while upgrading database to v41. folder classes may have vanished", e);
|
Log.e(K9.LOG_TAG, "Exception while upgrading database to v41. folder classes may have vanished", e);
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
@ -373,8 +372,7 @@ public class LocalStore extends Store implements Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} catch (SQLiteException e) {
|
||||||
catch (SQLiteException e) {
|
|
||||||
Log.e(K9.LOG_TAG, "Exception while upgrading database. Resetting the DB to v0");
|
Log.e(K9.LOG_TAG, "Exception while upgrading database. Resetting the DB to v0");
|
||||||
db.setVersion(0);
|
db.setVersion(0);
|
||||||
throw new Error("Database upgrade failed! Resetting your DB version to 0 to force a full schema recreation.");
|
throw new Error("Database upgrade failed! Resetting your DB version to 0 to force a full schema recreation.");
|
||||||
@ -645,9 +643,9 @@ public class LocalStore extends Store implements Serializable {
|
|||||||
while (cursor.moveToNext()) {
|
while (cursor.moveToNext()) {
|
||||||
LocalFolder folder = new LocalFolder(cursor.getString(1));
|
LocalFolder folder = new LocalFolder(cursor.getString(1));
|
||||||
folder.open(cursor.getInt(0), cursor.getString(14), cursor.getString(1), cursor.getInt(2),
|
folder.open(cursor.getInt(0), cursor.getString(14), cursor.getString(1), cursor.getInt(2),
|
||||||
cursor.getInt(3), cursor.getLong(4), cursor.getString(5), cursor.getString(6),
|
cursor.getInt(3), cursor.getLong(4), cursor.getString(5), cursor.getString(6),
|
||||||
cursor.getLong(7), cursor.getInt(8), cursor.getInt(9), cursor.getInt(10), cursor.getString(11),
|
cursor.getLong(7), cursor.getInt(8), cursor.getInt(9), cursor.getInt(10), cursor.getString(11),
|
||||||
cursor.getString(12), cursor.getString(13));
|
cursor.getString(12), cursor.getString(13));
|
||||||
folders.add(folder);
|
folders.add(folder);
|
||||||
}
|
}
|
||||||
return folders;
|
return folders;
|
||||||
@ -1075,7 +1073,7 @@ public class LocalStore extends Store implements Serializable {
|
|||||||
|
|
||||||
}
|
}
|
||||||
if (remoteName.equalsIgnoreCase(mAccount.getInboxFolderName()) ||
|
if (remoteName.equalsIgnoreCase(mAccount.getInboxFolderName()) ||
|
||||||
remoteName.equalsIgnoreCase(mAccount.getDraftsFolderName())) {
|
remoteName.equalsIgnoreCase(mAccount.getDraftsFolderName())) {
|
||||||
prefHolder.syncClass = LocalFolder.FolderClass.FIRST_CLASS;
|
prefHolder.syncClass = LocalFolder.FolderClass.FIRST_CLASS;
|
||||||
} else {
|
} else {
|
||||||
prefHolder.syncClass = LocalFolder.FolderClass.NO_CLASS;
|
prefHolder.syncClass = LocalFolder.FolderClass.NO_CLASS;
|
||||||
@ -1084,7 +1082,7 @@ public class LocalStore extends Store implements Serializable {
|
|||||||
folder.refresh(remoteName, prefHolder); // Recover settings from Preferences
|
folder.refresh(remoteName, prefHolder); // Recover settings from Preferences
|
||||||
|
|
||||||
db.execSQL("INSERT INTO folders (name, visible_limit, top_group, display_class, poll_class, push_class, integrate, remote_name)"
|
db.execSQL("INSERT INTO folders (name, visible_limit, top_group, display_class, poll_class, push_class, integrate, remote_name)"
|
||||||
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?)", new Object[] {
|
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?)", new Object[] {
|
||||||
folder.getName(),
|
folder.getName(),
|
||||||
visibleLimit,
|
visibleLimit,
|
||||||
prefHolder.inTopGroup ? 1 : 0,
|
prefHolder.inTopGroup ? 1 : 0,
|
||||||
@ -1179,8 +1177,8 @@ public class LocalStore extends Store implements Serializable {
|
|||||||
int folderId = cursor.getInt(0);
|
int folderId = cursor.getInt(0);
|
||||||
if (folderId > 0) {
|
if (folderId > 0) {
|
||||||
open(folderId, cursor.getString(14), cursor.getString(1), cursor.getInt(2), cursor.getInt(3),
|
open(folderId, cursor.getString(14), cursor.getString(1), cursor.getInt(2), cursor.getInt(3),
|
||||||
cursor.getLong(4), cursor.getString(5), cursor.getString(6), cursor.getLong(7), cursor.getInt(8),
|
cursor.getLong(4), cursor.getString(5), cursor.getString(6), cursor.getLong(7), cursor.getInt(8),
|
||||||
cursor.getInt(9), cursor.getInt(10), cursor.getString(11), cursor.getString(12), cursor.getString(13));
|
cursor.getInt(9), cursor.getInt(10), cursor.getString(11), cursor.getString(12), cursor.getString(13));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.w(K9.LOG_TAG, "Creating folder " + getName() + " with existing id " + getId());
|
Log.w(K9.LOG_TAG, "Creating folder " + getName() + " with existing id " + getId());
|
||||||
@ -1201,8 +1199,8 @@ public class LocalStore extends Store implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void open(int id, String remoteName, String name, int unreadCount, int visibleLimit, long lastChecked, String status,
|
private void open(int id, String remoteName, String name, int unreadCount, int visibleLimit, long lastChecked, String status,
|
||||||
String pushState, long lastPushed, int flaggedCount, int integrate, int topGroup, String syncClass,
|
String pushState, long lastPushed, int flaggedCount, int integrate, int topGroup, String syncClass,
|
||||||
String pushClass, String displayClass) throws MessagingException {
|
String pushClass, String displayClass) throws MessagingException {
|
||||||
mFolderId = id;
|
mFolderId = id;
|
||||||
mRemoteName = remoteName;
|
mRemoteName = remoteName;
|
||||||
mName = name;
|
mName = name;
|
||||||
@ -1235,7 +1233,7 @@ public class LocalStore extends Store implements Serializable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRemoteName() {
|
public String getRemoteName() {
|
||||||
return mRemoteName;
|
return mRemoteName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1251,7 +1249,7 @@ public class LocalStore extends Store implements Serializable {
|
|||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
try {
|
try {
|
||||||
cursor = db.rawQuery("SELECT id FROM folders where folders.remote_name = ?",
|
cursor = db.rawQuery("SELECT id FROM folders where folders.remote_name = ?",
|
||||||
new String[] { LocalFolder.this.getRemoteName() });
|
new String[] { LocalFolder.this.getRemoteName() });
|
||||||
if (cursor.moveToFirst()) {
|
if (cursor.moveToFirst()) {
|
||||||
int folderId = cursor.getInt(0);
|
int folderId = cursor.getInt(0);
|
||||||
return (folderId > 0);
|
return (folderId > 0);
|
||||||
@ -2399,7 +2397,9 @@ public class LocalStore extends Store implements Serializable {
|
|||||||
if (s != null) {
|
if (s != null) {
|
||||||
try {
|
try {
|
||||||
size = Integer.parseInt(s);
|
size = Integer.parseInt(s);
|
||||||
} catch (NumberFormatException e) { /* Ignore */ }
|
} catch (NumberFormatException e) {
|
||||||
|
/* Ignore */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2829,7 +2829,7 @@ public class LocalStore extends Store implements Serializable {
|
|||||||
mLastUid = lastUid;
|
mLastUid = lastUid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getOldestMessageDate() throws MessagingException {
|
public Long getOldestMessageDate() throws MessagingException {
|
||||||
return database.execute(false, new DbCallback<Long>() {
|
return database.execute(false, new DbCallback<Long>() {
|
||||||
@Override
|
@Override
|
||||||
public Long doDbWork(final SQLiteDatabase db) {
|
public Long doDbWork(final SQLiteDatabase db) {
|
||||||
|
@ -117,7 +117,7 @@ public class Pop3Store extends Store {
|
|||||||
int userIndex = 0, passwordIndex = 1;
|
int userIndex = 0, passwordIndex = 1;
|
||||||
String userinfo = pop3Uri.getUserInfo();
|
String userinfo = pop3Uri.getUserInfo();
|
||||||
String[] userInfoParts = userinfo.split(":");
|
String[] userInfoParts = userinfo.split(":");
|
||||||
if (userInfoParts.length > 2 || userinfo.endsWith(":") ) {
|
if (userInfoParts.length > 2 || userinfo.endsWith(":")) {
|
||||||
// If 'userinfo' ends with ":" the password is empty. This can only happen
|
// If 'userinfo' ends with ":" the password is empty. This can only happen
|
||||||
// after an account was imported (so authType and username are present).
|
// after an account was imported (so authType and username are present).
|
||||||
userIndex++;
|
userIndex++;
|
||||||
@ -135,7 +135,7 @@ public class Pop3Store extends Store {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new ServerSettings(STORE_TYPE, host, port, connectionSecurity, authType, username,
|
return new ServerSettings(STORE_TYPE, host, port, connectionSecurity, authType, username,
|
||||||
password);
|
password);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -155,43 +155,42 @@ public class Pop3Store extends Store {
|
|||||||
try {
|
try {
|
||||||
userEnc = URLEncoder.encode(server.username, "UTF-8");
|
userEnc = URLEncoder.encode(server.username, "UTF-8");
|
||||||
passwordEnc = (server.password != null) ?
|
passwordEnc = (server.password != null) ?
|
||||||
URLEncoder.encode(server.password, "UTF-8") : "";
|
URLEncoder.encode(server.password, "UTF-8") : "";
|
||||||
}
|
} catch (UnsupportedEncodingException e) {
|
||||||
catch (UnsupportedEncodingException e) {
|
|
||||||
throw new IllegalArgumentException("Could not encode username or password", e);
|
throw new IllegalArgumentException("Could not encode username or password", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
String scheme;
|
String scheme;
|
||||||
switch (server.connectionSecurity) {
|
switch (server.connectionSecurity) {
|
||||||
case SSL_TLS_OPTIONAL:
|
case SSL_TLS_OPTIONAL:
|
||||||
scheme = "pop3+ssl";
|
scheme = "pop3+ssl";
|
||||||
break;
|
break;
|
||||||
case SSL_TLS_REQUIRED:
|
case SSL_TLS_REQUIRED:
|
||||||
scheme = "pop3+ssl+";
|
scheme = "pop3+ssl+";
|
||||||
break;
|
break;
|
||||||
case STARTTLS_OPTIONAL:
|
case STARTTLS_OPTIONAL:
|
||||||
scheme = "pop3+tls";
|
scheme = "pop3+tls";
|
||||||
break;
|
break;
|
||||||
case STARTTLS_REQUIRED:
|
case STARTTLS_REQUIRED:
|
||||||
scheme = "pop3+tls+";
|
scheme = "pop3+tls+";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
case NONE:
|
case NONE:
|
||||||
scheme = "pop3";
|
scheme = "pop3";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
AuthType.valueOf(server.authenticationType);
|
AuthType.valueOf(server.authenticationType);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IllegalArgumentException("Invalid authentication type (" +
|
throw new IllegalArgumentException("Invalid authentication type (" +
|
||||||
server.authenticationType + ")");
|
server.authenticationType + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
String userInfo = server.authenticationType + ":" + userEnc + ":" + passwordEnc;
|
String userInfo = server.authenticationType + ":" + userEnc + ":" + passwordEnc;
|
||||||
try {
|
try {
|
||||||
return new URI(scheme, userInfo, server.host, server.port, null, null,
|
return new URI(scheme, userInfo, server.host, server.port, null, null,
|
||||||
null).toString();
|
null).toString();
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
throw new IllegalArgumentException("Can't create Pop3Store URI", e);
|
throw new IllegalArgumentException("Can't create Pop3Store URI", e);
|
||||||
}
|
}
|
||||||
@ -865,7 +864,7 @@ public class Pop3Store extends Store {
|
|||||||
|
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
executeSimpleCommand(String.format(RETR_COMMAND + " %d",
|
executeSimpleCommand(String.format(RETR_COMMAND + " %d",
|
||||||
mUidToMsgNumMap.get(message.getUid())));
|
mUidToMsgNumMap.get(message.getUid())));
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -185,7 +185,7 @@ public class WebDavStore extends Store {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new WebDavStoreSettings(host, port, connectionSecurity, null, username, password,
|
return new WebDavStoreSettings(host, port, connectionSecurity, null, username, password,
|
||||||
alias, path, authPath, mailboxPath);
|
alias, path, authPath, mailboxPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -205,30 +205,29 @@ public class WebDavStore extends Store {
|
|||||||
try {
|
try {
|
||||||
userEnc = URLEncoder.encode(server.username, "UTF-8");
|
userEnc = URLEncoder.encode(server.username, "UTF-8");
|
||||||
passwordEnc = (server.password != null) ?
|
passwordEnc = (server.password != null) ?
|
||||||
URLEncoder.encode(server.password, "UTF-8") : "";
|
URLEncoder.encode(server.password, "UTF-8") : "";
|
||||||
}
|
} catch (UnsupportedEncodingException e) {
|
||||||
catch (UnsupportedEncodingException e) {
|
|
||||||
throw new IllegalArgumentException("Could not encode username or password", e);
|
throw new IllegalArgumentException("Could not encode username or password", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
String scheme;
|
String scheme;
|
||||||
switch (server.connectionSecurity) {
|
switch (server.connectionSecurity) {
|
||||||
case SSL_TLS_OPTIONAL:
|
case SSL_TLS_OPTIONAL:
|
||||||
scheme = "webdav+ssl";
|
scheme = "webdav+ssl";
|
||||||
break;
|
break;
|
||||||
case SSL_TLS_REQUIRED:
|
case SSL_TLS_REQUIRED:
|
||||||
scheme = "webdav+ssl+";
|
scheme = "webdav+ssl+";
|
||||||
break;
|
break;
|
||||||
case STARTTLS_OPTIONAL:
|
case STARTTLS_OPTIONAL:
|
||||||
scheme = "webdav+tls";
|
scheme = "webdav+tls";
|
||||||
break;
|
break;
|
||||||
case STARTTLS_REQUIRED:
|
case STARTTLS_REQUIRED:
|
||||||
scheme = "webdav+tls+";
|
scheme = "webdav+tls+";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
case NONE:
|
case NONE:
|
||||||
scheme = "webdav";
|
scheme = "webdav";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
String userInfo = userEnc + ":" + passwordEnc;
|
String userInfo = userEnc + ":" + passwordEnc;
|
||||||
@ -242,14 +241,14 @@ public class WebDavStore extends Store {
|
|||||||
authPath = (authPath != null) ? authPath : "";
|
authPath = (authPath != null) ? authPath : "";
|
||||||
String mailboxPath = extra.get(WebDavStoreSettings.MAILBOX_PATH_KEY);
|
String mailboxPath = extra.get(WebDavStoreSettings.MAILBOX_PATH_KEY);
|
||||||
mailboxPath = (mailboxPath != null) ? mailboxPath : "";
|
mailboxPath = (mailboxPath != null) ? mailboxPath : "";
|
||||||
uriPath = path + "|" + authPath + "|" + mailboxPath;
|
uriPath = "/" + path + "|" + authPath + "|" + mailboxPath;
|
||||||
} else {
|
} else {
|
||||||
uriPath = "||";
|
uriPath = "/||";
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return new URI(scheme, userInfo, server.host, server.port, uriPath,
|
return new URI(scheme, userInfo, server.host, server.port, uriPath,
|
||||||
null, null).toString();
|
null, null).toString();
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
throw new IllegalArgumentException("Can't create WebDavStore URI", e);
|
throw new IllegalArgumentException("Can't create WebDavStore URI", e);
|
||||||
}
|
}
|
||||||
@ -273,10 +272,10 @@ public class WebDavStore extends Store {
|
|||||||
public final String mailboxPath;
|
public final String mailboxPath;
|
||||||
|
|
||||||
protected WebDavStoreSettings(String host, int port, ConnectionSecurity connectionSecurity,
|
protected WebDavStoreSettings(String host, int port, ConnectionSecurity connectionSecurity,
|
||||||
String authenticationType, String username, String password, String alias,
|
String authenticationType, String username, String password, String alias,
|
||||||
String path, String authPath, String mailboxPath) {
|
String path, String authPath, String mailboxPath) {
|
||||||
super(STORE_TYPE, host, port, connectionSecurity, authenticationType, username,
|
super(STORE_TYPE, host, port, connectionSecurity, authenticationType, username,
|
||||||
password);
|
password);
|
||||||
this.alias = alias;
|
this.alias = alias;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.authPath = authPath;
|
this.authPath = authPath;
|
||||||
@ -296,7 +295,7 @@ public class WebDavStore extends Store {
|
|||||||
@Override
|
@Override
|
||||||
public ServerSettings newPassword(String newPassword) {
|
public ServerSettings newPassword(String newPassword) {
|
||||||
return new WebDavStoreSettings(host, port, connectionSecurity, authenticationType,
|
return new WebDavStoreSettings(host, port, connectionSecurity, authenticationType,
|
||||||
username, newPassword, alias, path, authPath, mailboxPath);
|
username, newPassword, alias, path, authPath, mailboxPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1399,7 +1398,7 @@ public class WebDavStore extends Store {
|
|||||||
messageCount = dataset.getMessageCount();
|
messageCount = dataset.getMessageCount();
|
||||||
}
|
}
|
||||||
if (K9.DEBUG && K9.DEBUG_PROTOCOL_WEBDAV) {
|
if (K9.DEBUG && K9.DEBUG_PROTOCOL_WEBDAV) {
|
||||||
Log.v(K9.LOG_TAG, "Counted messages and webdav returned: "+messageCount);
|
Log.v(K9.LOG_TAG, "Counted messages and webdav returned: " + messageCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return messageCount;
|
return messageCount;
|
||||||
@ -1772,7 +1771,7 @@ public class WebDavStore extends Store {
|
|||||||
try {
|
try {
|
||||||
wdMessage.setFlagInternal(Flag.SEEN, uidToReadStatus.get(wdMessage.getUid()));
|
wdMessage.setFlagInternal(Flag.SEEN, uidToReadStatus.get(wdMessage.getUid()));
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
Log.v(K9.LOG_TAG,"Under some weird circumstances, setting the read status when syncing from webdav threw an NPE. Skipping.");
|
Log.v(K9.LOG_TAG, "Under some weird circumstances, setting the read status when syncing from webdav threw an NPE. Skipping.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
@ -1841,7 +1840,7 @@ public class WebDavStore extends Store {
|
|||||||
wdMessage.setNewHeaders(envelope);
|
wdMessage.setNewHeaders(envelope);
|
||||||
wdMessage.setFlagInternal(Flag.SEEN, envelope.getReadStatus());
|
wdMessage.setFlagInternal(Flag.SEEN, envelope.getReadStatus());
|
||||||
} else {
|
} else {
|
||||||
Log.e(K9.LOG_TAG,"Asked to get metadata for a non-existent message: "+wdMessage.getUid());
|
Log.e(K9.LOG_TAG, "Asked to get metadata for a non-existent message: " + wdMessage.getUid());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
|
@ -91,7 +91,7 @@ public class Eas {
|
|||||||
USER_LOG = true;
|
USER_LOG = true;
|
||||||
}
|
}
|
||||||
Log.d("Eas Debug", "Logging: " + (USER_LOG ? "User " : "") +
|
Log.d("Eas Debug", "Logging: " + (USER_LOG ? "User " : "") +
|
||||||
(PARSER_LOG ? "Parser " : "") + (FILE_LOG ? "File" : ""));
|
(PARSER_LOG ? "Parser " : "") + (FILE_LOG ? "File" : ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ public abstract class AbstractSyncParser extends Parser {
|
|||||||
// Status = 1 is success; everything else is a failure
|
// Status = 1 is success; everything else is a failure
|
||||||
status = getValueInt();
|
status = getValueInt();
|
||||||
if (status != 1) {
|
if (status != 1) {
|
||||||
Log.e(K9.LOG_TAG, "Sync failed: " + status);
|
Log.e(K9.LOG_TAG, "Sync failed: " + status);
|
||||||
// Status = 3 means invalid sync key
|
// Status = 3 means invalid sync key
|
||||||
if (status == 3) {
|
if (status == 3) {
|
||||||
// Must delete all of the data and start over with syncKey of "0"
|
// Must delete all of the data and start over with syncKey of "0"
|
||||||
@ -144,11 +144,11 @@ public abstract class AbstractSyncParser extends Parser {
|
|||||||
}
|
}
|
||||||
// If we were pushing (i.e. auto-start), now we'll become ping-triggered
|
// If we were pushing (i.e. auto-start), now we'll become ping-triggered
|
||||||
if (MailboxAdapter.mSyncInterval == MailboxAdapter.CHECK_INTERVAL_PUSH) {
|
if (MailboxAdapter.mSyncInterval == MailboxAdapter.CHECK_INTERVAL_PUSH) {
|
||||||
MailboxAdapter.mSyncInterval = MailboxAdapter.CHECK_INTERVAL_PING;
|
MailboxAdapter.mSyncInterval = MailboxAdapter.CHECK_INTERVAL_PING;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we don't have a new sync key, ignore moreAvailable (or we'll loop)
|
// If we don't have a new sync key, ignore moreAvailable (or we'll loop)
|
||||||
@ -194,11 +194,11 @@ public abstract class AbstractSyncParser extends Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void userLog(String ...strings) {
|
void userLog(String ...strings) {
|
||||||
Log.i(K9.LOG_TAG, Arrays.toString(strings));
|
Log.i(K9.LOG_TAG, Arrays.toString(strings));
|
||||||
}
|
}
|
||||||
|
|
||||||
void userLog(String string, int num, String string2) {
|
void userLog(String string, int num, String string2) {
|
||||||
Log.i(K9.LOG_TAG, string + num + string2);
|
Log.i(K9.LOG_TAG, string + num + string2);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,9 @@ import com.fsck.k9.mail.store.exchange.Eas;
|
|||||||
public class EasEmailSyncParser extends AbstractSyncParser {
|
public class EasEmailSyncParser extends AbstractSyncParser {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
ArrayList<EasMessage> newEmails = new ArrayList<EasMessage>();
|
ArrayList<EasMessage> newEmails = new ArrayList<EasMessage>();
|
||||||
ArrayList<String> deletedEmails = new ArrayList<String>();
|
ArrayList<String> deletedEmails = new ArrayList<String>();
|
||||||
ArrayList<ServerChange> changedEmails = new ArrayList<ServerChange>();
|
ArrayList<ServerChange> changedEmails = new ArrayList<ServerChange>();
|
||||||
|
|
||||||
@ -45,71 +45,71 @@ public class EasEmailSyncParser extends AbstractSyncParser {
|
|||||||
// Message.MAILBOX_KEY + "=" + mMailbox.mId, null);
|
// Message.MAILBOX_KEY + "=" + mMailbox.mId, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addData (EasMessage msg) throws IOException, MessagingException {
|
public void addData(EasMessage msg) throws IOException, MessagingException {
|
||||||
// ArrayList<Attachment> atts = new ArrayList<Attachment>();
|
// ArrayList<Attachment> atts = new ArrayList<Attachment>();
|
||||||
|
|
||||||
while (nextTag(Tags.SYNC_APPLICATION_DATA) != END) {
|
while (nextTag(Tags.SYNC_APPLICATION_DATA) != END) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.EMAIL_ATTACHMENTS:
|
case Tags.EMAIL_ATTACHMENTS:
|
||||||
case Tags.BASE_ATTACHMENTS: // BASE_ATTACHMENTS is used in EAS 12.0 and up
|
case Tags.BASE_ATTACHMENTS: // BASE_ATTACHMENTS is used in EAS 12.0 and up
|
||||||
attachmentsParser(msg);
|
attachmentsParser(msg);
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_TO:
|
case Tags.EMAIL_TO:
|
||||||
msg.setRecipients(RecipientType.TO, Address.parse(getValue()));
|
msg.setRecipients(RecipientType.TO, Address.parse(getValue()));
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_FROM:
|
case Tags.EMAIL_FROM:
|
||||||
Address[] froms = Address.parse(getValue());
|
Address[] froms = Address.parse(getValue());
|
||||||
if (froms != null && froms.length > 0) {
|
if (froms != null && froms.length > 0) {
|
||||||
// msg.mDisplayName = froms[0].toFriendly();
|
// msg.mDisplayName = froms[0].toFriendly();
|
||||||
msg.setFrom(froms[0]);
|
msg.setFrom(froms[0]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_CC:
|
case Tags.EMAIL_CC:
|
||||||
msg.setRecipients(RecipientType.CC, Address.parse(getValue()));
|
msg.setRecipients(RecipientType.CC, Address.parse(getValue()));
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_REPLY_TO:
|
case Tags.EMAIL_REPLY_TO:
|
||||||
msg.setReplyTo(Address.parse(getValue()));
|
msg.setReplyTo(Address.parse(getValue()));
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_DATE_RECEIVED:
|
case Tags.EMAIL_DATE_RECEIVED:
|
||||||
getValue();
|
getValue();
|
||||||
// Date receivedDate = Utility.parseEmailDateTimeToMillis(getValue());
|
// Date receivedDate = Utility.parseEmailDateTimeToMillis(getValue());
|
||||||
// msg.setInternalDate(receivedDate);
|
// msg.setInternalDate(receivedDate);
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_SUBJECT:
|
case Tags.EMAIL_SUBJECT:
|
||||||
msg.setSubject(getValue());
|
msg.setSubject(getValue());
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_READ:
|
case Tags.EMAIL_READ:
|
||||||
msg.setFlagInternal(Flag.SEEN, getValueInt() == 1);
|
msg.setFlagInternal(Flag.SEEN, getValueInt() == 1);
|
||||||
break;
|
break;
|
||||||
case Tags.BASE_BODY:
|
case Tags.BASE_BODY:
|
||||||
bodyParser(msg);
|
bodyParser(msg);
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_FLAG:
|
case Tags.EMAIL_FLAG:
|
||||||
msg.setFlagInternal(Flag.FLAGGED, flagParser());
|
msg.setFlagInternal(Flag.FLAGGED, flagParser());
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_BODY:
|
case Tags.EMAIL_BODY:
|
||||||
String body = getValue();
|
String body = getValue();
|
||||||
InputStream bodyStream = new ByteArrayInputStream(body.getBytes());
|
InputStream bodyStream = new ByteArrayInputStream(body.getBytes());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
msg.setBody(MimeUtility.decodeBody(bodyStream, null));
|
msg.setBody(MimeUtility.decodeBody(bodyStream, null));
|
||||||
} catch (MessagingException e) {
|
} catch (MessagingException e) {
|
||||||
throw new IOException(e);
|
throw new IOException(e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_MESSAGE_CLASS:
|
case Tags.EMAIL_MESSAGE_CLASS:
|
||||||
String messageClass = getValue();
|
String messageClass = getValue();
|
||||||
// if (messageClass.equals("IPM.Schedule.Meeting.Request")) {
|
// if (messageClass.equals("IPM.Schedule.Meeting.Request")) {
|
||||||
// msg.mFlags |= Message.FLAG_INCOMING_MEETING_INVITE;
|
// msg.mFlags |= Message.FLAG_INCOMING_MEETING_INVITE;
|
||||||
// } else if (messageClass.equals("IPM.Schedule.Meeting.Canceled")) {
|
// } else if (messageClass.equals("IPM.Schedule.Meeting.Canceled")) {
|
||||||
// msg.mFlags |= Message.FLAG_INCOMING_MEETING_CANCEL;
|
// msg.mFlags |= Message.FLAG_INCOMING_MEETING_CANCEL;
|
||||||
// }
|
// }
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_MEETING_REQUEST:
|
case Tags.EMAIL_MEETING_REQUEST:
|
||||||
meetingRequestParser(msg);
|
meetingRequestParser(msg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,40 +129,40 @@ public class EasEmailSyncParser extends AbstractSyncParser {
|
|||||||
// PackedString.Builder packedString = new PackedString.Builder();
|
// PackedString.Builder packedString = new PackedString.Builder();
|
||||||
while (nextTag(Tags.EMAIL_MEETING_REQUEST) != END) {
|
while (nextTag(Tags.EMAIL_MEETING_REQUEST) != END) {
|
||||||
String value;
|
String value;
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.EMAIL_DTSTAMP:
|
case Tags.EMAIL_DTSTAMP:
|
||||||
value = getValue();
|
value = getValue();
|
||||||
// packedString.put(MeetingInfo.MEETING_DTSTAMP, value);
|
// packedString.put(MeetingInfo.MEETING_DTSTAMP, value);
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_START_TIME:
|
case Tags.EMAIL_START_TIME:
|
||||||
value = getValue();
|
value = getValue();
|
||||||
// packedString.put(MeetingInfo.MEETING_DTSTART, value);
|
// packedString.put(MeetingInfo.MEETING_DTSTART, value);
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_END_TIME:
|
case Tags.EMAIL_END_TIME:
|
||||||
value = getValue();
|
value = getValue();
|
||||||
// packedString.put(MeetingInfo.MEETING_DTEND, value);
|
// packedString.put(MeetingInfo.MEETING_DTEND, value);
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_ORGANIZER:
|
case Tags.EMAIL_ORGANIZER:
|
||||||
value = getValue();
|
value = getValue();
|
||||||
// packedString.put(MeetingInfo.MEETING_ORGANIZER_EMAIL, value);
|
// packedString.put(MeetingInfo.MEETING_ORGANIZER_EMAIL, value);
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_LOCATION:
|
case Tags.EMAIL_LOCATION:
|
||||||
value = getValue();
|
value = getValue();
|
||||||
// packedString.put(MeetingInfo.MEETING_LOCATION, value);
|
// packedString.put(MeetingInfo.MEETING_LOCATION, value);
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_GLOBAL_OBJID:
|
case Tags.EMAIL_GLOBAL_OBJID:
|
||||||
value = getValue();
|
value = getValue();
|
||||||
// packedString.put(MeetingInfo.MEETING_UID,
|
// packedString.put(MeetingInfo.MEETING_UID,
|
||||||
// CalendarUtilities.getUidFromGlobalObjId(value));
|
// CalendarUtilities.getUidFromGlobalObjId(value));
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_CATEGORIES:
|
case Tags.EMAIL_CATEGORIES:
|
||||||
nullParser();
|
nullParser();
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_RECURRENCES:
|
case Tags.EMAIL_RECURRENCES:
|
||||||
recurrencesParser();
|
recurrencesParser();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if (msg.mSubject != null) {
|
// if (msg.mSubject != null) {
|
||||||
@ -180,54 +180,54 @@ public class EasEmailSyncParser extends AbstractSyncParser {
|
|||||||
private void recurrencesParser() throws IOException {
|
private void recurrencesParser() throws IOException {
|
||||||
while (nextTag(Tags.EMAIL_RECURRENCES) != END) {
|
while (nextTag(Tags.EMAIL_RECURRENCES) != END) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.EMAIL_RECURRENCE:
|
case Tags.EMAIL_RECURRENCE:
|
||||||
nullParser();
|
nullParser();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addParser(ArrayList<EasMessage> emails) throws IOException, MessagingException {
|
private void addParser(ArrayList<EasMessage> emails) throws IOException, MessagingException {
|
||||||
EasMessage msg = new EasMessage(null, mFolder);
|
EasMessage msg = new EasMessage(null, mFolder);
|
||||||
// msg.mAccountKey = mAccount.mId;
|
// msg.mAccountKey = mAccount.mId;
|
||||||
// msg.mMailboxKey = mMailbox.mId;
|
// msg.mMailboxKey = mMailbox.mId;
|
||||||
// msg.mFlagLoaded = Message.FLAG_LOADED_COMPLETE;
|
// msg.mFlagLoaded = Message.FLAG_LOADED_COMPLETE;
|
||||||
|
|
||||||
while (nextTag(Tags.SYNC_ADD) != END) {
|
while (nextTag(Tags.SYNC_ADD) != END) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.SYNC_SERVER_ID:
|
case Tags.SYNC_SERVER_ID:
|
||||||
String serverId = getValue();
|
String serverId = getValue();
|
||||||
msg.setUid(serverId);
|
msg.setUid(serverId);
|
||||||
break;
|
break;
|
||||||
case Tags.SYNC_APPLICATION_DATA:
|
case Tags.SYNC_APPLICATION_DATA:
|
||||||
addData(msg);
|
addData(msg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emails.add(msg);
|
emails.add(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fetchParser(ArrayList<EasMessage> emails) throws IOException, MessagingException {
|
private void fetchParser(ArrayList<EasMessage> emails) throws IOException, MessagingException {
|
||||||
EasMessage msg = new EasMessage(null, mFolder);
|
EasMessage msg = new EasMessage(null, mFolder);
|
||||||
// msg.mAccountKey = mAccount.mId;
|
// msg.mAccountKey = mAccount.mId;
|
||||||
// msg.mMailboxKey = mMailbox.mId;
|
// msg.mMailboxKey = mMailbox.mId;
|
||||||
// msg.mFlagLoaded = Message.FLAG_LOADED_COMPLETE;
|
// msg.mFlagLoaded = Message.FLAG_LOADED_COMPLETE;
|
||||||
|
|
||||||
while (nextTag(Tags.SYNC_FETCH) != END) {
|
while (nextTag(Tags.SYNC_FETCH) != END) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.SYNC_SERVER_ID:
|
case Tags.SYNC_SERVER_ID:
|
||||||
String serverId = getValue();
|
String serverId = getValue();
|
||||||
msg.setUid(serverId);
|
msg.setUid(serverId);
|
||||||
break;
|
break;
|
||||||
case Tags.SYNC_APPLICATION_DATA:
|
case Tags.SYNC_APPLICATION_DATA:
|
||||||
addData(msg);
|
addData(msg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emails.add(msg);
|
emails.add(msg);
|
||||||
@ -238,11 +238,11 @@ public class EasEmailSyncParser extends AbstractSyncParser {
|
|||||||
Boolean state = false;
|
Boolean state = false;
|
||||||
while (nextTag(Tags.EMAIL_FLAG) != END) {
|
while (nextTag(Tags.EMAIL_FLAG) != END) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.EMAIL_FLAG_STATUS:
|
case Tags.EMAIL_FLAG_STATUS:
|
||||||
state = getValueInt() == 2;
|
state = getValueInt() == 2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
@ -253,14 +253,14 @@ public class EasEmailSyncParser extends AbstractSyncParser {
|
|||||||
String body = "";
|
String body = "";
|
||||||
while (nextTag(Tags.EMAIL_BODY) != END) {
|
while (nextTag(Tags.EMAIL_BODY) != END) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.BASE_TYPE:
|
case Tags.BASE_TYPE:
|
||||||
bodyType = getValue();
|
bodyType = getValue();
|
||||||
break;
|
break;
|
||||||
case Tags.BASE_DATA:
|
case Tags.BASE_DATA:
|
||||||
body = getValue();
|
body = getValue();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,27 +271,27 @@ public class EasEmailSyncParser extends AbstractSyncParser {
|
|||||||
// msg.mText = body;
|
// msg.mText = body;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
InputStream bodyStream = new ByteArrayInputStream(body.getBytes());
|
InputStream bodyStream = new ByteArrayInputStream(body.getBytes());
|
||||||
//String contentTransferEncoding;
|
//String contentTransferEncoding;
|
||||||
// contentTransferEncoding = msg.getHeader(
|
// contentTransferEncoding = msg.getHeader(
|
||||||
// MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING)[0];
|
// MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING)[0];
|
||||||
// msg.setBody(MimeUtility.decodeBody(bodyStream, contentTransferEncoding));
|
// msg.setBody(MimeUtility.decodeBody(bodyStream, contentTransferEncoding));
|
||||||
((EasMessage) msg).parse(bodyStream);
|
((EasMessage) msg).parse(bodyStream);
|
||||||
} catch (MessagingException e) {
|
} catch (MessagingException e) {
|
||||||
throw new IOException(e);
|
throw new IOException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void attachmentsParser(Message msg) throws IOException {
|
private void attachmentsParser(Message msg) throws IOException {
|
||||||
while (nextTag(Tags.EMAIL_ATTACHMENTS) != END) {
|
while (nextTag(Tags.EMAIL_ATTACHMENTS) != END) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.EMAIL_ATTACHMENT:
|
case Tags.EMAIL_ATTACHMENT:
|
||||||
case Tags.BASE_ATTACHMENT: // BASE_ATTACHMENT is used in EAS 12.0 and up
|
case Tags.BASE_ATTACHMENT: // BASE_ATTACHMENT is used in EAS 12.0 and up
|
||||||
attachmentParser(msg);
|
attachmentParser(msg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -304,20 +304,20 @@ public class EasEmailSyncParser extends AbstractSyncParser {
|
|||||||
while (nextTag(Tags.EMAIL_ATTACHMENT) != END) {
|
while (nextTag(Tags.EMAIL_ATTACHMENT) != END) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
// We handle both EAS 2.5 and 12.0+ attachments here
|
// We handle both EAS 2.5 and 12.0+ attachments here
|
||||||
case Tags.EMAIL_DISPLAY_NAME:
|
case Tags.EMAIL_DISPLAY_NAME:
|
||||||
case Tags.BASE_DISPLAY_NAME:
|
case Tags.BASE_DISPLAY_NAME:
|
||||||
fileName = getValue();
|
fileName = getValue();
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_ATT_NAME:
|
case Tags.EMAIL_ATT_NAME:
|
||||||
case Tags.BASE_FILE_REFERENCE:
|
case Tags.BASE_FILE_REFERENCE:
|
||||||
location = getValue();
|
location = getValue();
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_ATT_SIZE:
|
case Tags.EMAIL_ATT_SIZE:
|
||||||
case Tags.BASE_ESTIMATED_DATA_SIZE:
|
case Tags.BASE_ESTIMATED_DATA_SIZE:
|
||||||
length = getValue();
|
length = getValue();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,18 +371,18 @@ public class EasEmailSyncParser extends AbstractSyncParser {
|
|||||||
/*package*/ void deleteParser(ArrayList<String> deletes, int entryTag) throws IOException {
|
/*package*/ void deleteParser(ArrayList<String> deletes, int entryTag) throws IOException {
|
||||||
while (nextTag(entryTag) != END) {
|
while (nextTag(entryTag) != END) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.SYNC_SERVER_ID:
|
case Tags.SYNC_SERVER_ID:
|
||||||
String serverId = getValue();
|
String serverId = getValue();
|
||||||
deletes.add(serverId);
|
deletes.add(serverId);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ServerChange {
|
class ServerChange {
|
||||||
String serverId;
|
String serverId;
|
||||||
Boolean read;
|
Boolean read;
|
||||||
Boolean flag;
|
Boolean flag;
|
||||||
|
|
||||||
@ -397,14 +397,14 @@ public class EasEmailSyncParser extends AbstractSyncParser {
|
|||||||
String serverId = null;
|
String serverId = null;
|
||||||
while (nextTag(Tags.SYNC_CHANGE) != END) {
|
while (nextTag(Tags.SYNC_CHANGE) != END) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.SYNC_SERVER_ID:
|
case Tags.SYNC_SERVER_ID:
|
||||||
serverId = getValue();
|
serverId = getValue();
|
||||||
break;
|
break;
|
||||||
case Tags.SYNC_APPLICATION_DATA:
|
case Tags.SYNC_APPLICATION_DATA:
|
||||||
changeApplicationDataParser(changes, serverId);
|
changeApplicationDataParser(changes, serverId);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -414,14 +414,14 @@ public class EasEmailSyncParser extends AbstractSyncParser {
|
|||||||
Boolean flag = null;
|
Boolean flag = null;
|
||||||
while (nextTag(Tags.SYNC_APPLICATION_DATA) != END) {
|
while (nextTag(Tags.SYNC_APPLICATION_DATA) != END) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.EMAIL_READ:
|
case Tags.EMAIL_READ:
|
||||||
read = getValueInt() == 1;
|
read = getValueInt() == 1;
|
||||||
break;
|
break;
|
||||||
case Tags.EMAIL_FLAG:
|
case Tags.EMAIL_FLAG:
|
||||||
flag = flagParser();
|
flag = flagParser();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
changes.add(new ServerChange(serverId, read, flag));
|
changes.add(new ServerChange(serverId, read, flag));
|
||||||
@ -535,32 +535,32 @@ public class EasEmailSyncParser extends AbstractSyncParser {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<EasMessage> getMessages() throws MessagingException {
|
public List<EasMessage> getMessages() throws MessagingException {
|
||||||
List<EasMessage> messages = new ArrayList<EasMessage>();
|
List<EasMessage> messages = new ArrayList<EasMessage>();
|
||||||
|
|
||||||
messages.addAll(newEmails);
|
messages.addAll(newEmails);
|
||||||
|
|
||||||
for (ServerChange srvChg : changedEmails) {
|
for (ServerChange srvChg : changedEmails) {
|
||||||
EasMessage msg = new EasMessage(srvChg.serverId, mFolder);
|
EasMessage msg = new EasMessage(srvChg.serverId, mFolder);
|
||||||
if (srvChg.read != null) {
|
if (srvChg.read != null) {
|
||||||
msg.setFlag(Flag.SEEN, srvChg.read);
|
msg.setFlag(Flag.SEEN, srvChg.read);
|
||||||
}
|
}
|
||||||
if (srvChg.flag != null) {
|
if (srvChg.flag != null) {
|
||||||
msg.setFlag(Flag.FLAGGED, srvChg.flag);
|
msg.setFlag(Flag.FLAGGED, srvChg.flag);
|
||||||
}
|
}
|
||||||
messages.add(msg);
|
messages.add(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String serverId : deletedEmails) {
|
for (String serverId : deletedEmails) {
|
||||||
EasMessage msg = new EasMessage(serverId, mFolder);
|
EasMessage msg = new EasMessage(serverId, mFolder);
|
||||||
msg.setFlag(Flag.DELETED, true);
|
msg.setFlag(Flag.DELETED, true);
|
||||||
messages.add(msg);
|
messages.add(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasMessages() {
|
public boolean hasMessages() {
|
||||||
return !newEmails.isEmpty() || !changedEmails.isEmpty() || !deletedEmails.isEmpty();
|
return !newEmails.isEmpty() || !changedEmails.isEmpty() || !deletedEmails.isEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -76,12 +76,12 @@ public class FolderSyncParser extends Parser {
|
|||||||
// private long mAccountId;
|
// private long mAccountId;
|
||||||
// private String mAccountIdAsString;
|
// private String mAccountIdAsString;
|
||||||
// private String[] mBindArguments = new String[2];
|
// private String[] mBindArguments = new String[2];
|
||||||
private List<Folder> folderList;
|
private List<Folder> folderList;
|
||||||
|
|
||||||
private EasStore easStore;
|
private EasStore easStore;
|
||||||
|
|
||||||
public FolderSyncParser(InputStream in, EasStore easStore, List<Folder> folderList) throws IOException {
|
public FolderSyncParser(InputStream in, EasStore easStore, List<Folder> folderList) throws IOException {
|
||||||
super(in);
|
super(in);
|
||||||
|
|
||||||
this.easStore = easStore;
|
this.easStore = easStore;
|
||||||
this.folderList = folderList;
|
this.folderList = folderList;
|
||||||
@ -113,12 +113,12 @@ public class FolderSyncParser extends Parser {
|
|||||||
} else {
|
} else {
|
||||||
// Other errors are at the server, so let's throw an error that will
|
// Other errors are at the server, so let's throw an error that will
|
||||||
// cause this sync to be retried at a later time
|
// cause this sync to be retried at a later time
|
||||||
Log.e(K9.LOG_TAG, "Throwing IOException; will retry later");
|
Log.e(K9.LOG_TAG, "Throwing IOException; will retry later");
|
||||||
throw new EasParserException("Folder status error");
|
throw new EasParserException("Folder status error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (tag == Tags.FOLDER_SYNC_KEY) {
|
} else if (tag == Tags.FOLDER_SYNC_KEY) {
|
||||||
easStore.setStoreSyncKey(getValue());
|
easStore.setStoreSyncKey(getValue());
|
||||||
userLog("New Account SyncKey: ", easStore.getStoreSyncKey());
|
userLog("New Account SyncKey: ", easStore.getStoreSyncKey());
|
||||||
} else if (tag == Tags.FOLDER_CHANGES) {
|
} else if (tag == Tags.FOLDER_CHANGES) {
|
||||||
changesParser();
|
changesParser();
|
||||||
@ -146,8 +146,8 @@ public class FolderSyncParser extends Parser {
|
|||||||
public void deleteParser(ArrayList<ContentProviderOperation> ops) throws IOException {
|
public void deleteParser(ArrayList<ContentProviderOperation> ops) throws IOException {
|
||||||
while (nextTag(Tags.FOLDER_DELETE) != END) {
|
while (nextTag(Tags.FOLDER_DELETE) != END) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.FOLDER_SERVER_ID:
|
case Tags.FOLDER_SERVER_ID:
|
||||||
String serverId = getValue();
|
String serverId = getValue();
|
||||||
// // Find the mailbox in this account with the given serverId
|
// // Find the mailbox in this account with the given serverId
|
||||||
// Cursor c = getServerIdCursor(serverId);
|
// Cursor c = getServerIdCursor(serverId);
|
||||||
// try {
|
// try {
|
||||||
@ -162,9 +162,9 @@ public class FolderSyncParser extends Parser {
|
|||||||
// } finally {
|
// } finally {
|
||||||
// c.close();
|
// c.close();
|
||||||
// }
|
// }
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,29 +177,29 @@ public class FolderSyncParser extends Parser {
|
|||||||
|
|
||||||
while (nextTag(Tags.FOLDER_ADD) != END) {
|
while (nextTag(Tags.FOLDER_ADD) != END) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.FOLDER_DISPLAY_NAME: {
|
case Tags.FOLDER_DISPLAY_NAME: {
|
||||||
name = getValue();
|
name = getValue();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Tags.FOLDER_TYPE: {
|
case Tags.FOLDER_TYPE: {
|
||||||
type = getValueInt();
|
type = getValueInt();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Tags.FOLDER_PARENT_ID: {
|
case Tags.FOLDER_PARENT_ID: {
|
||||||
parentId = getValue();
|
parentId = getValue();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Tags.FOLDER_SERVER_ID: {
|
case Tags.FOLDER_SERVER_ID: {
|
||||||
serverId = getValue();
|
serverId = getValue();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mValidFolderTypes.contains(type)) {
|
if (mValidFolderTypes.contains(type)) {
|
||||||
Folder folder = easStore.new EasFolder(name, serverId, type);
|
Folder folder = easStore.new EasFolder(name, serverId, type);
|
||||||
folderList.add(folder);
|
folderList.add(folder);
|
||||||
// Mailbox m = new Mailbox();
|
// Mailbox m = new Mailbox();
|
||||||
// m.mDisplayName = name;
|
// m.mDisplayName = name;
|
||||||
// m.mServerId = serverId;
|
// m.mServerId = serverId;
|
||||||
@ -258,18 +258,18 @@ public class FolderSyncParser extends Parser {
|
|||||||
String parentId = null;
|
String parentId = null;
|
||||||
while (nextTag(Tags.FOLDER_UPDATE) != END) {
|
while (nextTag(Tags.FOLDER_UPDATE) != END) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.FOLDER_SERVER_ID:
|
case Tags.FOLDER_SERVER_ID:
|
||||||
serverId = getValue();
|
serverId = getValue();
|
||||||
break;
|
break;
|
||||||
case Tags.FOLDER_DISPLAY_NAME:
|
case Tags.FOLDER_DISPLAY_NAME:
|
||||||
displayName = getValue();
|
displayName = getValue();
|
||||||
break;
|
break;
|
||||||
case Tags.FOLDER_PARENT_ID:
|
case Tags.FOLDER_PARENT_ID:
|
||||||
parentId = getValue();
|
parentId = getValue();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We'll make a change if one of parentId or displayName are specified
|
// We'll make a change if one of parentId or displayName are specified
|
||||||
@ -325,13 +325,13 @@ public class FolderSyncParser extends Parser {
|
|||||||
// Create the new mailboxes in a single batch operation
|
// Create the new mailboxes in a single batch operation
|
||||||
// Don't save any data if the service has been stopped
|
// Don't save any data if the service has been stopped
|
||||||
// synchronized (mService.getSynchronizer()) {
|
// synchronized (mService.getSynchronizer()) {
|
||||||
if (!ops.isEmpty()/* && !mService.isStopped()*/) {
|
if (!ops.isEmpty()/* && !mService.isStopped()*/) {
|
||||||
userLog("Applying ", ops.size(), " mailbox operations.");
|
userLog("Applying ", ops.size(), " mailbox operations.");
|
||||||
|
|
||||||
// Execute the batch
|
// Execute the batch
|
||||||
// try {
|
// try {
|
||||||
// mContentResolver.applyBatch(EmailProvider.EMAIL_AUTHORITY, ops);
|
// mContentResolver.applyBatch(EmailProvider.EMAIL_AUTHORITY, ops);
|
||||||
userLog("New Account SyncKey: ", easStore.getStoreSyncKey());
|
userLog("New Account SyncKey: ", easStore.getStoreSyncKey());
|
||||||
// } catch (RemoteException e) {
|
// } catch (RemoteException e) {
|
||||||
// // There is nothing to be done here; fail by returning null
|
// // There is nothing to be done here; fail by returning null
|
||||||
// } catch (OperationApplicationException e) {
|
// } catch (OperationApplicationException e) {
|
||||||
@ -362,16 +362,16 @@ public class FolderSyncParser extends Parser {
|
|||||||
// mContentResolver.delete(Mailbox.CONTENT_URI, WHERE_PARENT_SERVER_ID_AND_ACCOUNT,
|
// mContentResolver.delete(Mailbox.CONTENT_URI, WHERE_PARENT_SERVER_ID_AND_ACCOUNT,
|
||||||
// mBindArguments);
|
// mBindArguments);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void userLog(String ...strings) {
|
void userLog(String ...strings) {
|
||||||
Log.i(K9.LOG_TAG, Arrays.toString(strings));
|
Log.i(K9.LOG_TAG, Arrays.toString(strings));
|
||||||
}
|
}
|
||||||
|
|
||||||
void userLog(String string, int num, String string2) {
|
void userLog(String string, int num, String string2) {
|
||||||
Log.i(K9.LOG_TAG, string + num + string2);
|
Log.i(K9.LOG_TAG, string + num + string2);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,14 @@ package com.fsck.k9.mail.store.exchange.adapter;
|
|||||||
|
|
||||||
public class MailboxAdapter {
|
public class MailboxAdapter {
|
||||||
|
|
||||||
static final int CHECK_INTERVAL_PUSH = 0;
|
static final int CHECK_INTERVAL_PUSH = 0;
|
||||||
|
|
||||||
static final int CHECK_INTERVAL_PING = 0;
|
static final int CHECK_INTERVAL_PING = 0;
|
||||||
|
|
||||||
static String mSyncKey;
|
static String mSyncKey;
|
||||||
|
|
||||||
static int mSyncInterval;
|
static int mSyncInterval;
|
||||||
|
|
||||||
String mDisplayName;
|
String mDisplayName;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -227,7 +227,7 @@ public abstract class Parser {
|
|||||||
* @return the integer value of the current tag
|
* @return the integer value of the current tag
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public int getValueInt() throws IOException {
|
public int getValueInt() throws IOException {
|
||||||
// The true argument to getNext indicates the desire for an integer return value
|
// The true argument to getNext indicates the desire for an integer return value
|
||||||
getNext(true);
|
getNext(true);
|
||||||
if (type == END) {
|
if (type == END) {
|
||||||
@ -264,7 +264,7 @@ public abstract class Parser {
|
|||||||
if (type == START) {
|
if (type == START) {
|
||||||
tag = page | startTag;
|
tag = page | startTag;
|
||||||
return tag;
|
return tag;
|
||||||
// If we're at the ending tag we're looking for, return the END signal
|
// If we're at the ending tag we're looking for, return the END signal
|
||||||
} else if (type == END && startTag == endTag) {
|
} else if (type == END && startTag == endTag) {
|
||||||
return END;
|
return END;
|
||||||
}
|
}
|
||||||
@ -368,7 +368,7 @@ public abstract class Parser {
|
|||||||
text = null;
|
text = null;
|
||||||
name = null;
|
name = null;
|
||||||
|
|
||||||
int id = nextId ();
|
int id = nextId();
|
||||||
while (id == Wbxml.SWITCH_PAGE) {
|
while (id == Wbxml.SWITCH_PAGE) {
|
||||||
nextId = NOT_FETCHED;
|
nextId = NOT_FETCHED;
|
||||||
// Get the new page number
|
// Get the new page number
|
||||||
@ -382,51 +382,51 @@ public abstract class Parser {
|
|||||||
nextId = NOT_FETCHED;
|
nextId = NOT_FETCHED;
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case EOF_BYTE:
|
case EOF_BYTE:
|
||||||
// End of document
|
// End of document
|
||||||
type = DONE;
|
type = DONE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Wbxml.END:
|
case Wbxml.END:
|
||||||
// End of tag
|
// End of tag
|
||||||
type = END;
|
type = END;
|
||||||
if (logging) {
|
if (logging) {
|
||||||
name = nameArray[depth];
|
name = nameArray[depth];
|
||||||
//log("</" + name + '>');
|
//log("</" + name + '>');
|
||||||
}
|
}
|
||||||
// Retrieve the now-current startTag from our stack
|
// Retrieve the now-current startTag from our stack
|
||||||
startTag = endTag = startTagArray[depth];
|
startTag = endTag = startTagArray[depth];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Wbxml.STR_I:
|
case Wbxml.STR_I:
|
||||||
// Inline string
|
// Inline string
|
||||||
type = TEXT;
|
type = TEXT;
|
||||||
if (asInt) {
|
if (asInt) {
|
||||||
num = readInlineInt();
|
num = readInlineInt();
|
||||||
} else {
|
} else {
|
||||||
text = readInlineString();
|
text = readInlineString();
|
||||||
}
|
}
|
||||||
if (logging) {
|
if (logging) {
|
||||||
name = tagTable[startTag - TAG_BASE];
|
name = tagTable[startTag - TAG_BASE];
|
||||||
log(name + ": " + (asInt ? Integer.toString(num) : text));
|
log(name + ": " + (asInt ? Integer.toString(num) : text));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Start of tag
|
// Start of tag
|
||||||
type = START;
|
type = START;
|
||||||
// The tag is in the low 6 bits
|
// The tag is in the low 6 bits
|
||||||
startTag = id & 0x3F;
|
startTag = id & 0x3F;
|
||||||
// If the high bit is set, there is content (a value) to be read
|
// If the high bit is set, there is content (a value) to be read
|
||||||
noContent = (id & 0x40) == 0;
|
noContent = (id & 0x40) == 0;
|
||||||
depth++;
|
depth++;
|
||||||
if (logging) {
|
if (logging) {
|
||||||
name = tagTable[startTag - TAG_BASE];
|
name = tagTable[startTag - TAG_BASE];
|
||||||
//log('<' + name + '>');
|
//log('<' + name + '>');
|
||||||
nameArray[depth] = name;
|
nameArray[depth] = name;
|
||||||
}
|
}
|
||||||
// Save the startTag to our stack
|
// Save the startTag to our stack
|
||||||
startTagArray[depth] = startTag;
|
startTagArray[depth] = startTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the type of data we're dealing with
|
// Return the type of data we're dealing with
|
||||||
|
@ -18,10 +18,10 @@ public class PingParser extends Parser {
|
|||||||
|
|
||||||
public static final String TAG = "PingParser";
|
public static final String TAG = "PingParser";
|
||||||
|
|
||||||
private List<String> folderList;
|
private List<String> folderList;
|
||||||
|
|
||||||
public PingParser(InputStream in) throws IOException {
|
public PingParser(InputStream in) throws IOException {
|
||||||
super(in);
|
super(in);
|
||||||
|
|
||||||
this.folderList = new ArrayList<String>();
|
this.folderList = new ArrayList<String>();
|
||||||
}
|
}
|
||||||
@ -40,7 +40,7 @@ public class PingParser extends Parser {
|
|||||||
throw new IOException("Ping status error");
|
throw new IOException("Ping status error");
|
||||||
}
|
}
|
||||||
} else if (tag == Tags.PING_FOLDERS) {
|
} else if (tag == Tags.PING_FOLDERS) {
|
||||||
foldersParser();
|
foldersParser();
|
||||||
} else
|
} else
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
@ -50,26 +50,26 @@ public class PingParser extends Parser {
|
|||||||
public void foldersParser() throws IOException {
|
public void foldersParser() throws IOException {
|
||||||
while (nextTag(Tags.PING_FOLDERS) != END) {
|
while (nextTag(Tags.PING_FOLDERS) != END) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.PING_FOLDER:
|
case Tags.PING_FOLDER:
|
||||||
String serverId = getValue();
|
String serverId = getValue();
|
||||||
folderList.add(serverId);
|
folderList.add(serverId);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getFolderList() {
|
public List<String> getFolderList() {
|
||||||
return folderList;
|
return folderList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void userLog(String ...strings) {
|
void userLog(String ...strings) {
|
||||||
Log.i(K9.LOG_TAG, Arrays.toString(strings));
|
Log.i(K9.LOG_TAG, Arrays.toString(strings));
|
||||||
}
|
}
|
||||||
|
|
||||||
void userLog(String string, int num, String string2) {
|
void userLog(String string, int num, String string2) {
|
||||||
Log.i(K9.LOG_TAG, string + num + string2);
|
Log.i(K9.LOG_TAG, string + num + string2);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -69,51 +69,51 @@ public class ProvisionParser extends Parser {
|
|||||||
|
|
||||||
while (nextTag(Tags.PROVISION_EAS_PROVISION_DOC) != END) {
|
while (nextTag(Tags.PROVISION_EAS_PROVISION_DOC) != END) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.PROVISION_DEVICE_PASSWORD_ENABLED:
|
case Tags.PROVISION_DEVICE_PASSWORD_ENABLED:
|
||||||
if (getValueInt() == 1) {
|
if (getValueInt() == 1) {
|
||||||
if (passwordMode == PolicySet.PASSWORD_MODE_NONE) {
|
if (passwordMode == PolicySet.PASSWORD_MODE_NONE) {
|
||||||
passwordMode = PolicySet.PASSWORD_MODE_SIMPLE;
|
passwordMode = PolicySet.PASSWORD_MODE_SIMPLE;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case Tags.PROVISION_MIN_DEVICE_PASSWORD_LENGTH:
|
break;
|
||||||
minPasswordLength = getValueInt();
|
case Tags.PROVISION_MIN_DEVICE_PASSWORD_LENGTH:
|
||||||
break;
|
minPasswordLength = getValueInt();
|
||||||
case Tags.PROVISION_ALPHA_DEVICE_PASSWORD_ENABLED:
|
break;
|
||||||
if (getValueInt() == 1) {
|
case Tags.PROVISION_ALPHA_DEVICE_PASSWORD_ENABLED:
|
||||||
passwordMode = PolicySet.PASSWORD_MODE_STRONG;
|
if (getValueInt() == 1) {
|
||||||
}
|
passwordMode = PolicySet.PASSWORD_MODE_STRONG;
|
||||||
break;
|
}
|
||||||
case Tags.PROVISION_MAX_INACTIVITY_TIME_DEVICE_LOCK:
|
break;
|
||||||
// EAS gives us seconds, which is, happily, what the PolicySet requires
|
case Tags.PROVISION_MAX_INACTIVITY_TIME_DEVICE_LOCK:
|
||||||
maxScreenLockTime = getValueInt();
|
// EAS gives us seconds, which is, happily, what the PolicySet requires
|
||||||
break;
|
maxScreenLockTime = getValueInt();
|
||||||
case Tags.PROVISION_MAX_DEVICE_PASSWORD_FAILED_ATTEMPTS:
|
break;
|
||||||
maxPasswordFails = getValueInt();
|
case Tags.PROVISION_MAX_DEVICE_PASSWORD_FAILED_ATTEMPTS:
|
||||||
break;
|
maxPasswordFails = getValueInt();
|
||||||
case Tags.PROVISION_ALLOW_SIMPLE_DEVICE_PASSWORD:
|
break;
|
||||||
// Ignore this unless there's any MSFT documentation for what this means
|
case Tags.PROVISION_ALLOW_SIMPLE_DEVICE_PASSWORD:
|
||||||
// Hint: I haven't seen any that's more specific than "simple"
|
// Ignore this unless there's any MSFT documentation for what this means
|
||||||
getValue();
|
// Hint: I haven't seen any that's more specific than "simple"
|
||||||
break;
|
getValue();
|
||||||
|
break;
|
||||||
// The following policy, if false, can't be supported at the moment
|
// The following policy, if false, can't be supported at the moment
|
||||||
case Tags.PROVISION_ATTACHMENTS_ENABLED:
|
case Tags.PROVISION_ATTACHMENTS_ENABLED:
|
||||||
if (getValueInt() == 0) {
|
if (getValueInt() == 0) {
|
||||||
supported = false;
|
supported = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// The following policies, if true, can't be supported at the moment
|
// The following policies, if true, can't be supported at the moment
|
||||||
case Tags.PROVISION_DEVICE_ENCRYPTION_ENABLED:
|
case Tags.PROVISION_DEVICE_ENCRYPTION_ENABLED:
|
||||||
case Tags.PROVISION_PASSWORD_RECOVERY_ENABLED:
|
case Tags.PROVISION_PASSWORD_RECOVERY_ENABLED:
|
||||||
case Tags.PROVISION_DEVICE_PASSWORD_EXPIRATION:
|
case Tags.PROVISION_DEVICE_PASSWORD_EXPIRATION:
|
||||||
case Tags.PROVISION_DEVICE_PASSWORD_HISTORY:
|
case Tags.PROVISION_DEVICE_PASSWORD_HISTORY:
|
||||||
case Tags.PROVISION_MAX_ATTACHMENT_SIZE:
|
case Tags.PROVISION_MAX_ATTACHMENT_SIZE:
|
||||||
if (getValueInt() == 1) {
|
if (getValueInt() == 1) {
|
||||||
supported = false;
|
supported = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!supported) {
|
if (!supported) {
|
||||||
@ -123,7 +123,7 @@ public class ProvisionParser extends Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mPolicySet = new PolicySet(minPasswordLength, passwordMode,
|
mPolicySet = new PolicySet(minPasswordLength, passwordMode,
|
||||||
maxPasswordFails, maxScreenLockTime, true);
|
maxPasswordFails, maxScreenLockTime, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ShadowPolicySet {
|
class ShadowPolicySet {
|
||||||
@ -151,18 +151,18 @@ public class ProvisionParser extends Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (XmlPullParserException e) {
|
} catch (XmlPullParserException e) {
|
||||||
throw new IOException();
|
throw new IOException();
|
||||||
}
|
}
|
||||||
|
|
||||||
mPolicySet = new PolicySet(sps.mMinPasswordLength, sps.mPasswordMode, sps.mMaxPasswordFails,
|
mPolicySet = new PolicySet(sps.mMinPasswordLength, sps.mPasswordMode, sps.mMaxPasswordFails,
|
||||||
sps.mMaxScreenLockTime, true);
|
sps.mMaxScreenLockTime, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if password is required; otherwise false.
|
* Return true if password is required; otherwise false.
|
||||||
*/
|
*/
|
||||||
boolean parseSecurityPolicy(XmlPullParser parser, ShadowPolicySet sps)
|
boolean parseSecurityPolicy(XmlPullParser parser, ShadowPolicySet sps)
|
||||||
throws XmlPullParserException, IOException {
|
throws XmlPullParserException, IOException {
|
||||||
boolean passwordRequired = true;
|
boolean passwordRequired = true;
|
||||||
while (true) {
|
while (true) {
|
||||||
int type = parser.nextTag();
|
int type = parser.nextTag();
|
||||||
@ -185,7 +185,7 @@ public class ProvisionParser extends Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void parseCharacteristic(XmlPullParser parser, ShadowPolicySet sps)
|
void parseCharacteristic(XmlPullParser parser, ShadowPolicySet sps)
|
||||||
throws XmlPullParserException, IOException {
|
throws XmlPullParserException, IOException {
|
||||||
boolean enforceInactivityTimer = true;
|
boolean enforceInactivityTimer = true;
|
||||||
while (true) {
|
while (true) {
|
||||||
int type = parser.nextTag();
|
int type = parser.nextTag();
|
||||||
@ -200,7 +200,7 @@ public class ProvisionParser extends Parser {
|
|||||||
if (value.equals("0")) {
|
if (value.equals("0")) {
|
||||||
sps.mMaxScreenLockTime = 1;
|
sps.mMaxScreenLockTime = 1;
|
||||||
} else {
|
} else {
|
||||||
sps.mMaxScreenLockTime = 60*Integer.parseInt(value);
|
sps.mMaxScreenLockTime = 60 * Integer.parseInt(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (name.equals("AEFrequencyType")) {
|
} else if (name.equals("AEFrequencyType")) {
|
||||||
@ -227,22 +227,22 @@ public class ProvisionParser extends Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void parseRegistry(XmlPullParser parser, ShadowPolicySet sps)
|
void parseRegistry(XmlPullParser parser, ShadowPolicySet sps)
|
||||||
throws XmlPullParserException, IOException {
|
throws XmlPullParserException, IOException {
|
||||||
while (true) {
|
while (true) {
|
||||||
int type = parser.nextTag();
|
int type = parser.nextTag();
|
||||||
if (type == XmlPullParser.END_TAG && parser.getName().equals("characteristic")) {
|
if (type == XmlPullParser.END_TAG && parser.getName().equals("characteristic")) {
|
||||||
break;
|
break;
|
||||||
} else if (type == XmlPullParser.START_TAG) {
|
} else if (type == XmlPullParser.START_TAG) {
|
||||||
String name = parser.getName();
|
String name = parser.getName();
|
||||||
if (name.equals("characteristic")) {
|
if (name.equals("characteristic")) {
|
||||||
parseCharacteristic(parser, sps);
|
parseCharacteristic(parser, sps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void parseWapProvisioningDoc(XmlPullParser parser, ShadowPolicySet sps)
|
void parseWapProvisioningDoc(XmlPullParser parser, ShadowPolicySet sps)
|
||||||
throws XmlPullParserException, IOException {
|
throws XmlPullParserException, IOException {
|
||||||
while (true) {
|
while (true) {
|
||||||
int type = parser.nextTag();
|
int type = parser.nextTag();
|
||||||
if (type == XmlPullParser.END_TAG && parser.getName().equals("wap-provisioningdoc")) {
|
if (type == XmlPullParser.END_TAG && parser.getName().equals("wap-provisioningdoc")) {
|
||||||
@ -279,27 +279,27 @@ public class ProvisionParser extends Parser {
|
|||||||
String policyType = null;
|
String policyType = null;
|
||||||
while (nextTag(Tags.PROVISION_POLICY) != END) {
|
while (nextTag(Tags.PROVISION_POLICY) != END) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.PROVISION_POLICY_TYPE:
|
case Tags.PROVISION_POLICY_TYPE:
|
||||||
policyType = getValue();
|
policyType = getValue();
|
||||||
Log.i(K9.LOG_TAG, "Policy type: " + policyType);
|
Log.i(K9.LOG_TAG, "Policy type: " + policyType);
|
||||||
break;
|
break;
|
||||||
case Tags.PROVISION_POLICY_KEY:
|
case Tags.PROVISION_POLICY_KEY:
|
||||||
mPolicyKey = getValue();
|
mPolicyKey = getValue();
|
||||||
break;
|
break;
|
||||||
case Tags.PROVISION_STATUS:
|
case Tags.PROVISION_STATUS:
|
||||||
Log.i(K9.LOG_TAG, "Policy status: " + getValue());
|
Log.i(K9.LOG_TAG, "Policy status: " + getValue());
|
||||||
break;
|
break;
|
||||||
case Tags.PROVISION_DATA:
|
case Tags.PROVISION_DATA:
|
||||||
if (policyType.equalsIgnoreCase(EasStore.EAS_2_POLICY_TYPE)) {
|
if (policyType.equalsIgnoreCase(EasStore.EAS_2_POLICY_TYPE)) {
|
||||||
// Parse the old style XML document
|
// Parse the old style XML document
|
||||||
parseProvisionDocXml(getValue());
|
parseProvisionDocXml(getValue());
|
||||||
} else {
|
} else {
|
||||||
// Parse the newer WBXML data
|
// Parse the newer WBXML data
|
||||||
parseProvisionData();
|
parseProvisionData();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -322,20 +322,20 @@ public class ProvisionParser extends Parser {
|
|||||||
}
|
}
|
||||||
while (nextTag(START_DOCUMENT) != END_DOCUMENT) {
|
while (nextTag(START_DOCUMENT) != END_DOCUMENT) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Tags.PROVISION_STATUS:
|
case Tags.PROVISION_STATUS:
|
||||||
int status = getValueInt();
|
int status = getValueInt();
|
||||||
Log.i(K9.LOG_TAG, "Provision status: " + status);
|
Log.i(K9.LOG_TAG, "Provision status: " + status);
|
||||||
res = (status == 1);
|
res = (status == 1);
|
||||||
break;
|
break;
|
||||||
case Tags.PROVISION_POLICIES:
|
case Tags.PROVISION_POLICIES:
|
||||||
parsePolicies();
|
parsePolicies();
|
||||||
break;
|
break;
|
||||||
case Tags.PROVISION_REMOTE_WIPE:
|
case Tags.PROVISION_REMOTE_WIPE:
|
||||||
// Indicate remote wipe command received
|
// Indicate remote wipe command received
|
||||||
mRemoteWipe = true;
|
mRemoteWipe = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
skipTag();
|
skipTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
@ -347,32 +347,37 @@ public class ProvisionParser extends Parser {
|
|||||||
public static class PolicySet {
|
public static class PolicySet {
|
||||||
|
|
||||||
// Security (provisioning) flags
|
// Security (provisioning) flags
|
||||||
// bits 0..4: password length (0=no password required)
|
// bits 0..4: password length (0=no password required)
|
||||||
private static final int PASSWORD_LENGTH_MASK = 31;
|
private static final int PASSWORD_LENGTH_MASK = 31;
|
||||||
private static final int PASSWORD_LENGTH_SHIFT = 0;
|
private static final int PASSWORD_LENGTH_SHIFT = 0;
|
||||||
public static final int PASSWORD_LENGTH_MAX = 30;
|
public static final int PASSWORD_LENGTH_MAX = 30;
|
||||||
// bits 5..8: password mode
|
// bits 5..8: password mode
|
||||||
private static final int PASSWORD_MODE_SHIFT = 5;
|
private static final int PASSWORD_MODE_SHIFT = 5;
|
||||||
private static final int PASSWORD_MODE_MASK = 15 << PASSWORD_MODE_SHIFT;
|
private static final int PASSWORD_MODE_MASK = 15 << PASSWORD_MODE_SHIFT;
|
||||||
public static final int PASSWORD_MODE_NONE = 0 << PASSWORD_MODE_SHIFT;
|
public static final int PASSWORD_MODE_NONE = 0 << PASSWORD_MODE_SHIFT;
|
||||||
public static final int PASSWORD_MODE_SIMPLE = 1 << PASSWORD_MODE_SHIFT;
|
public static final int PASSWORD_MODE_SIMPLE = 1 << PASSWORD_MODE_SHIFT;
|
||||||
public static final int PASSWORD_MODE_STRONG = 2 << PASSWORD_MODE_SHIFT;
|
public static final int PASSWORD_MODE_STRONG = 2 << PASSWORD_MODE_SHIFT;
|
||||||
// bits 9..13: password failures -> wipe device (0=disabled)
|
// bits 9..13: password failures -> wipe device (0=disabled)
|
||||||
private static final int PASSWORD_MAX_FAILS_SHIFT = 9;
|
private static final int PASSWORD_MAX_FAILS_SHIFT = 9;
|
||||||
private static final int PASSWORD_MAX_FAILS_MASK = 31 << PASSWORD_MAX_FAILS_SHIFT;
|
private static final int PASSWORD_MAX_FAILS_MASK = 31 << PASSWORD_MAX_FAILS_SHIFT;
|
||||||
public static final int PASSWORD_MAX_FAILS_MAX = 31;
|
public static final int PASSWORD_MAX_FAILS_MAX = 31;
|
||||||
// bits 14..24: seconds to screen lock (0=not required)
|
// bits 14..24: seconds to screen lock (0=not required)
|
||||||
private static final int SCREEN_LOCK_TIME_SHIFT = 14;
|
private static final int SCREEN_LOCK_TIME_SHIFT = 14;
|
||||||
private static final int SCREEN_LOCK_TIME_MASK = 2047 << SCREEN_LOCK_TIME_SHIFT;
|
private static final int SCREEN_LOCK_TIME_MASK = 2047 << SCREEN_LOCK_TIME_SHIFT;
|
||||||
public static final int SCREEN_LOCK_TIME_MAX = 2047;
|
public static final int SCREEN_LOCK_TIME_MAX = 2047;
|
||||||
// bit 25: remote wipe capability required
|
// bit 25: remote wipe capability required
|
||||||
private static final int REQUIRE_REMOTE_WIPE = 1 << 25;
|
private static final int REQUIRE_REMOTE_WIPE = 1 << 25;
|
||||||
|
|
||||||
/*package*/ final int mMinPasswordLength;
|
/*package*/
|
||||||
/*package*/ final int mPasswordMode;
|
final int mMinPasswordLength;
|
||||||
/*package*/ final int mMaxPasswordFails;
|
/*package*/
|
||||||
/*package*/ final int mMaxScreenLockTime;
|
final int mPasswordMode;
|
||||||
/*package*/ final boolean mRequireRemoteWipe;
|
/*package*/
|
||||||
|
final int mMaxPasswordFails;
|
||||||
|
/*package*/
|
||||||
|
final int mMaxScreenLockTime;
|
||||||
|
/*package*/
|
||||||
|
final boolean mRequireRemoteWipe;
|
||||||
|
|
||||||
public int getMinPasswordLengthForTest() {
|
public int getMinPasswordLengthForTest() {
|
||||||
return mMinPasswordLength;
|
return mMinPasswordLength;
|
||||||
@ -404,7 +409,7 @@ public class ProvisionParser extends Parser {
|
|||||||
* @throws IllegalArgumentException for illegal arguments.
|
* @throws IllegalArgumentException for illegal arguments.
|
||||||
*/
|
*/
|
||||||
public PolicySet(int minPasswordLength, int passwordMode, int maxPasswordFails,
|
public PolicySet(int minPasswordLength, int passwordMode, int maxPasswordFails,
|
||||||
int maxScreenLockTime, boolean requireRemoteWipe) throws IllegalArgumentException {
|
int maxScreenLockTime, boolean requireRemoteWipe) throws IllegalArgumentException {
|
||||||
// If we're not enforcing passwords, make sure we clean up related values, since EAS
|
// If we're not enforcing passwords, make sure we clean up related values, since EAS
|
||||||
// can send non-zero values for any or all of these
|
// can send non-zero values for any or all of these
|
||||||
if (passwordMode == PASSWORD_MODE_NONE) {
|
if (passwordMode == PASSWORD_MODE_NONE) {
|
||||||
@ -464,12 +469,12 @@ public class ProvisionParser extends Parser {
|
|||||||
*/
|
*/
|
||||||
public int getDPManagerPasswordQuality() {
|
public int getDPManagerPasswordQuality() {
|
||||||
switch (mPasswordMode) {
|
switch (mPasswordMode) {
|
||||||
case PASSWORD_MODE_SIMPLE:
|
case PASSWORD_MODE_SIMPLE:
|
||||||
return DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
|
return DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
|
||||||
case PASSWORD_MODE_STRONG:
|
case PASSWORD_MODE_STRONG:
|
||||||
return DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
|
return DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
|
||||||
default:
|
default:
|
||||||
return DevicePolicyManager .PASSWORD_QUALITY_UNSPECIFIED;
|
return DevicePolicyManager .PASSWORD_QUALITY_UNSPECIFIED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -509,10 +514,10 @@ public class ProvisionParser extends Parser {
|
|||||||
if (o instanceof PolicySet) {
|
if (o instanceof PolicySet) {
|
||||||
PolicySet other = (PolicySet)o;
|
PolicySet other = (PolicySet)o;
|
||||||
return (this.mMinPasswordLength == other.mMinPasswordLength)
|
return (this.mMinPasswordLength == other.mMinPasswordLength)
|
||||||
&& (this.mPasswordMode == other.mPasswordMode)
|
&& (this.mPasswordMode == other.mPasswordMode)
|
||||||
&& (this.mMaxPasswordFails == other.mMaxPasswordFails)
|
&& (this.mMaxPasswordFails == other.mMaxPasswordFails)
|
||||||
&& (this.mMaxScreenLockTime == other.mMaxScreenLockTime)
|
&& (this.mMaxScreenLockTime == other.mMaxScreenLockTime)
|
||||||
&& (this.mRequireRemoteWipe == other.mRequireRemoteWipe);
|
&& (this.mRequireRemoteWipe == other.mRequireRemoteWipe);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -536,8 +541,8 @@ public class ProvisionParser extends Parser {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "{ " + "pw-len-min=" + mMinPasswordLength + " pw-mode=" + mPasswordMode
|
return "{ " + "pw-len-min=" + mMinPasswordLength + " pw-mode=" + mPasswordMode
|
||||||
+ " pw-fails-max=" + mMaxPasswordFails + " screenlock-max="
|
+ " pw-fails-max=" + mMaxPasswordFails + " screenlock-max="
|
||||||
+ mMaxScreenLockTime + " remote-wipe-req=" + mRequireRemoteWipe + "}";
|
+ mMaxScreenLockTime + " remote-wipe-req=" + mRequireRemoteWipe + "}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ public class Serializer {
|
|||||||
out.flush();
|
out.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startDocument() throws IOException{
|
public void startDocument() throws IOException {
|
||||||
out.write(0x03); // version 1.3
|
out.write(0x03); // version 1.3
|
||||||
out.write(0x01); // unknown or missing public identifier
|
out.write(0x01); // unknown or missing public identifier
|
||||||
out.write(106);
|
out.write(106);
|
||||||
@ -186,7 +186,7 @@ public class Serializer {
|
|||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
buf[idx++] = (byte) (i & 0x7f);
|
buf[idx++] = (byte)(i & 0x7f);
|
||||||
i = i >> 7;
|
i = i >> 7;
|
||||||
} while (i != 0);
|
} while (i != 0);
|
||||||
|
|
||||||
@ -205,7 +205,7 @@ public class Serializer {
|
|||||||
out.write(0);
|
out.write(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeStringValue (ContentValues cv, String key, int tag) throws IOException {
|
void writeStringValue(ContentValues cv, String key, int tag) throws IOException {
|
||||||
String value = cv.getAsString(key);
|
String value = cv.getAsString(key);
|
||||||
if (value != null && value.length() > 0) {
|
if (value != null && value.length() > 0) {
|
||||||
data(tag, value);
|
data(tag, value);
|
||||||
|
@ -214,7 +214,7 @@ public class Tags {
|
|||||||
public static final int FOLDER_UPDATE = FOLDER_PAGE + 0x11;
|
public static final int FOLDER_UPDATE = FOLDER_PAGE + 0x11;
|
||||||
public static final int FOLDER_SYNC_KEY = FOLDER_PAGE + 0x12;
|
public static final int FOLDER_SYNC_KEY = FOLDER_PAGE + 0x12;
|
||||||
public static final int FOLDER_FOLDER_CREATE = FOLDER_PAGE + 0x13;
|
public static final int FOLDER_FOLDER_CREATE = FOLDER_PAGE + 0x13;
|
||||||
public static final int FOLDER_FOLDER_DELETE= FOLDER_PAGE + 0x14;
|
public static final int FOLDER_FOLDER_DELETE = FOLDER_PAGE + 0x14;
|
||||||
public static final int FOLDER_FOLDER_UPDATE = FOLDER_PAGE + 0x15;
|
public static final int FOLDER_FOLDER_UPDATE = FOLDER_PAGE + 0x15;
|
||||||
public static final int FOLDER_FOLDER_SYNC = FOLDER_PAGE + 0x16;
|
public static final int FOLDER_FOLDER_SYNC = FOLDER_PAGE + 0x16;
|
||||||
public static final int FOLDER_COUNT = FOLDER_PAGE + 0x17;
|
public static final int FOLDER_COUNT = FOLDER_PAGE + 0x17;
|
||||||
@ -479,7 +479,8 @@ public class Tags {
|
|||||||
public static final int BASE_CONTENT_TYPE = BASE_PAGE + 0x17;
|
public static final int BASE_CONTENT_TYPE = BASE_PAGE + 0x17;
|
||||||
|
|
||||||
static public String[][] pages = {
|
static public String[][] pages = {
|
||||||
{ // 0x00 AirSync
|
{
|
||||||
|
// 0x00 AirSync
|
||||||
"Sync", "Responses", "Add", "Change", "Delete", "Fetch", "SyncKey", "ClientId",
|
"Sync", "Responses", "Add", "Change", "Delete", "Fetch", "SyncKey", "ClientId",
|
||||||
"ServerId", "Status", "Collection", "Class", "Version", "CollectionId", "GetChanges",
|
"ServerId", "Status", "Collection", "Class", "Version", "CollectionId", "GetChanges",
|
||||||
"MoreAvailable", "WindowSize", "Commands", "Options", "FilterType", "Truncation",
|
"MoreAvailable", "WindowSize", "Commands", "Options", "FilterType", "Truncation",
|
||||||
|
@ -117,7 +117,7 @@ public class SmtpTransport extends Transport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new ServerSettings(TRANSPORT_TYPE, host, port, connectionSecurity,
|
return new ServerSettings(TRANSPORT_TYPE, host, port, connectionSecurity,
|
||||||
authenticationType, username, password);
|
authenticationType, username, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -136,32 +136,31 @@ public class SmtpTransport extends Transport {
|
|||||||
String passwordEnc;
|
String passwordEnc;
|
||||||
try {
|
try {
|
||||||
userEnc = (server.username != null) ?
|
userEnc = (server.username != null) ?
|
||||||
URLEncoder.encode(server.username, "UTF-8") : "";
|
URLEncoder.encode(server.username, "UTF-8") : "";
|
||||||
passwordEnc = (server.password != null) ?
|
passwordEnc = (server.password != null) ?
|
||||||
URLEncoder.encode(server.password, "UTF-8") : "";
|
URLEncoder.encode(server.password, "UTF-8") : "";
|
||||||
}
|
} catch (UnsupportedEncodingException e) {
|
||||||
catch (UnsupportedEncodingException e) {
|
|
||||||
throw new IllegalArgumentException("Could not encode username or password", e);
|
throw new IllegalArgumentException("Could not encode username or password", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
String scheme;
|
String scheme;
|
||||||
switch (server.connectionSecurity) {
|
switch (server.connectionSecurity) {
|
||||||
case SSL_TLS_OPTIONAL:
|
case SSL_TLS_OPTIONAL:
|
||||||
scheme = "smtp+ssl";
|
scheme = "smtp+ssl";
|
||||||
break;
|
break;
|
||||||
case SSL_TLS_REQUIRED:
|
case SSL_TLS_REQUIRED:
|
||||||
scheme = "smtp+ssl+";
|
scheme = "smtp+ssl+";
|
||||||
break;
|
break;
|
||||||
case STARTTLS_OPTIONAL:
|
case STARTTLS_OPTIONAL:
|
||||||
scheme = "smtp+tls";
|
scheme = "smtp+tls";
|
||||||
break;
|
break;
|
||||||
case STARTTLS_REQUIRED:
|
case STARTTLS_REQUIRED:
|
||||||
scheme = "smtp+tls+";
|
scheme = "smtp+tls+";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
case NONE:
|
case NONE:
|
||||||
scheme = "smtp";
|
scheme = "smtp";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
String authType = server.authenticationType;
|
String authType = server.authenticationType;
|
||||||
@ -175,7 +174,7 @@ public class SmtpTransport extends Transport {
|
|||||||
String userInfo = userEnc + ":" + passwordEnc + ":" + authType;
|
String userInfo = userEnc + ":" + passwordEnc + ":" + authType;
|
||||||
try {
|
try {
|
||||||
return new URI(scheme, userInfo, server.host, server.port, null, null,
|
return new URI(scheme, userInfo, server.host, server.port, null, null,
|
||||||
null).toString();
|
null).toString();
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
throw new IllegalArgumentException("Can't create SmtpTransport URI", e);
|
throw new IllegalArgumentException("Can't create SmtpTransport URI", e);
|
||||||
}
|
}
|
||||||
|
@ -23,10 +23,11 @@ public class AccountSettings {
|
|||||||
s.put("archiveFolderName", new StringSetting("Archive"));
|
s.put("archiveFolderName", new StringSetting("Archive"));
|
||||||
s.put("autoExpandFolderName", new StringSetting("INBOX"));
|
s.put("autoExpandFolderName", new StringSetting("INBOX"));
|
||||||
s.put("automaticCheckIntervalMinutes",
|
s.put("automaticCheckIntervalMinutes",
|
||||||
new IntegerResourceSetting(-1, R.array.account_settings_check_frequency_values));
|
new IntegerResourceSetting(-1, R.array.account_settings_check_frequency_values));
|
||||||
s.put("chipColor", new ColorSetting(0xFF0000FF));
|
s.put("chipColor", new ColorSetting(0xFF0000FF));
|
||||||
s.put("cryptoApp", new StringSetting(Apg.NAME));
|
s.put("cryptoApp", new StringSetting(Apg.NAME));
|
||||||
s.put("cryptoAutoSignature", new BooleanSetting(false));
|
s.put("cryptoAutoSignature", new BooleanSetting(false));
|
||||||
|
s.put("cryptoAutoEncrypt", new BooleanSetting(false)); // added to version 3
|
||||||
s.put("defaultQuotedTextShown", new BooleanSetting(Account.DEFAULT_QUOTED_TEXT_SHOWN));
|
s.put("defaultQuotedTextShown", new BooleanSetting(Account.DEFAULT_QUOTED_TEXT_SHOWN));
|
||||||
s.put("deletePolicy", new DeletePolicySetting(Account.DELETE_POLICY_NEVER));
|
s.put("deletePolicy", new DeletePolicySetting(Account.DELETE_POLICY_NEVER));
|
||||||
s.put("displayCount", new IntegerResourceSetting(K9.DEFAULT_VISIBLE_LIMIT,
|
s.put("displayCount", new IntegerResourceSetting(K9.DEFAULT_VISIBLE_LIMIT,
|
||||||
@ -54,7 +55,7 @@ public class AccountSettings {
|
|||||||
s.put("maximumPolledMessageAge", new IntegerResourceSetting(-1,
|
s.put("maximumPolledMessageAge", new IntegerResourceSetting(-1,
|
||||||
R.array.account_settings_message_age_values));
|
R.array.account_settings_message_age_values));
|
||||||
s.put("messageFormat",
|
s.put("messageFormat",
|
||||||
new EnumSetting(Account.MessageFormat.class, Account.DEFAULT_MESSAGE_FORMAT));
|
new EnumSetting(Account.MessageFormat.class, Account.DEFAULT_MESSAGE_FORMAT));
|
||||||
s.put("messageFormatAuto", new BooleanSetting(Account.DEFAULT_MESSAGE_FORMAT_AUTO)); // added to version 2
|
s.put("messageFormatAuto", new BooleanSetting(Account.DEFAULT_MESSAGE_FORMAT_AUTO)); // added to version 2
|
||||||
s.put("messageReadReceipt", new BooleanSetting(Account.DEFAULT_MESSAGE_READ_RECEIPT));
|
s.put("messageReadReceipt", new BooleanSetting(Account.DEFAULT_MESSAGE_READ_RECEIPT));
|
||||||
s.put("notificationUnreadCount", new BooleanSetting(true));
|
s.put("notificationUnreadCount", new BooleanSetting(true));
|
||||||
@ -64,17 +65,17 @@ public class AccountSettings {
|
|||||||
s.put("pushPollOnConnect", new BooleanSetting(true));
|
s.put("pushPollOnConnect", new BooleanSetting(true));
|
||||||
s.put("quotePrefix", new StringSetting(Account.DEFAULT_QUOTE_PREFIX));
|
s.put("quotePrefix", new StringSetting(Account.DEFAULT_QUOTE_PREFIX));
|
||||||
s.put("quoteStyle",
|
s.put("quoteStyle",
|
||||||
new EnumSetting(Account.QuoteStyle.class, Account.DEFAULT_QUOTE_STYLE));
|
new EnumSetting(Account.QuoteStyle.class, Account.DEFAULT_QUOTE_STYLE));
|
||||||
s.put("replyAfterQuote", new BooleanSetting(Account.DEFAULT_REPLY_AFTER_QUOTE));
|
s.put("replyAfterQuote", new BooleanSetting(Account.DEFAULT_REPLY_AFTER_QUOTE));
|
||||||
s.put("stripSignature", new BooleanSetting(Account.DEFAULT_STRIP_SIGNATURE)); // added to version 2
|
s.put("stripSignature", new BooleanSetting(Account.DEFAULT_STRIP_SIGNATURE)); // added to version 2
|
||||||
s.put("ring", new BooleanSetting(true));
|
s.put("ring", new BooleanSetting(true));
|
||||||
s.put("ringtone", new RingtoneSetting("content://settings/system/notification_sound"));
|
s.put("ringtone", new RingtoneSetting("content://settings/system/notification_sound"));
|
||||||
s.put("saveAllHeaders", new BooleanSetting(true));
|
s.put("saveAllHeaders", new BooleanSetting(true));
|
||||||
s.put("searchableFolders",
|
s.put("searchableFolders",
|
||||||
new EnumSetting(Account.Searchable.class, Account.Searchable.ALL));
|
new EnumSetting(Account.Searchable.class, Account.Searchable.ALL));
|
||||||
s.put("sentFolderName", new StringSetting("Sent"));
|
s.put("sentFolderName", new StringSetting("Sent"));
|
||||||
s.put("showPicturesEnum",
|
s.put("showPicturesEnum",
|
||||||
new EnumSetting(Account.ShowPictures.class, Account.ShowPictures.NEVER));
|
new EnumSetting(Account.ShowPictures.class, Account.ShowPictures.NEVER));
|
||||||
s.put("signatureBeforeQuotedText", new BooleanSetting(false));
|
s.put("signatureBeforeQuotedText", new BooleanSetting(false));
|
||||||
s.put("spamFolderName", new StringSetting("Spam"));
|
s.put("spamFolderName", new StringSetting("Spam"));
|
||||||
s.put("subscribedFoldersOnly", new BooleanSetting(false));
|
s.put("subscribedFoldersOnly", new BooleanSetting(false));
|
||||||
@ -248,7 +249,9 @@ public class AccountSettings {
|
|||||||
if (mMapping.containsKey(deletePolicy)) {
|
if (mMapping.containsKey(deletePolicy)) {
|
||||||
return deletePolicy;
|
return deletePolicy;
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) { /* do nothing */ }
|
} catch (NumberFormatException e) {
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
throw new InvalidSettingValueException();
|
throw new InvalidSettingValueException();
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,9 @@ public class GlobalSettings {
|
|||||||
|
|
||||||
s.put("animations", new BooleanSetting(false));
|
s.put("animations", new BooleanSetting(false));
|
||||||
s.put("attachmentdefaultpath",
|
s.put("attachmentdefaultpath",
|
||||||
new DirectorySetting(Environment.getExternalStorageDirectory().toString()));
|
new DirectorySetting(Environment.getExternalStorageDirectory().toString()));
|
||||||
s.put("backgroundOperations",
|
s.put("backgroundOperations",
|
||||||
new EnumSetting(K9.BACKGROUND_OPS.class, K9.BACKGROUND_OPS.WHEN_CHECKED));
|
new EnumSetting(K9.BACKGROUND_OPS.class, K9.BACKGROUND_OPS.WHEN_CHECKED));
|
||||||
s.put("changeRegisteredNameColor", new BooleanSetting(false));
|
s.put("changeRegisteredNameColor", new BooleanSetting(false));
|
||||||
s.put("compactLayouts", new BooleanSetting(false));
|
s.put("compactLayouts", new BooleanSetting(false));
|
||||||
s.put("confirmDelete", new BooleanSetting(false));
|
s.put("confirmDelete", new BooleanSetting(false));
|
||||||
@ -186,7 +186,9 @@ public class GlobalSettings {
|
|||||||
if (mMapping.containsKey(theme)) {
|
if (mMapping.containsKey(theme)) {
|
||||||
return theme;
|
return theme;
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) { /* do nothing */ }
|
} catch (NumberFormatException e) {
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
throw new InvalidSettingValueException();
|
throw new InvalidSettingValueException();
|
||||||
}
|
}
|
||||||
@ -249,7 +251,9 @@ public class GlobalSettings {
|
|||||||
if (new File(value).isDirectory()) {
|
if (new File(value).isDirectory()) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
} catch (Exception e) { /* do nothing */ }
|
} catch (Exception e) {
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
throw new InvalidSettingValueException();
|
throw new InvalidSettingValueException();
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ public class Settings {
|
|||||||
*
|
*
|
||||||
* @see SettingsExporter
|
* @see SettingsExporter
|
||||||
*/
|
*/
|
||||||
public static final int VERSION = 2;
|
public static final int VERSION = 3;
|
||||||
|
|
||||||
public static Map<String, String> validate(Map<String, SettingsDescription> settings,
|
public static Map<String, String> validate(Map<String, SettingsDescription> settings,
|
||||||
Map<String, String> importedSettings, boolean useDefaultValues) {
|
Map<String, String> importedSettings, boolean useDefaultValues) {
|
||||||
@ -45,7 +45,7 @@ public class Settings {
|
|||||||
boolean useDefaultValue;
|
boolean useDefaultValue;
|
||||||
if (!importedSettings.containsKey(key)) {
|
if (!importedSettings.containsKey(key)) {
|
||||||
Log.v(K9.LOG_TAG, "Key \"" + key + "\" wasn't found in the imported file." +
|
Log.v(K9.LOG_TAG, "Key \"" + key + "\" wasn't found in the imported file." +
|
||||||
((useDefaultValues) ? " Using default value." : ""));
|
((useDefaultValues) ? " Using default value." : ""));
|
||||||
useDefaultValue = useDefaultValues;
|
useDefaultValue = useDefaultValues;
|
||||||
} else {
|
} else {
|
||||||
String prettyValue = importedSettings.get(key);
|
String prettyValue = importedSettings.get(key);
|
||||||
@ -56,8 +56,8 @@ public class Settings {
|
|||||||
useDefaultValue = false;
|
useDefaultValue = false;
|
||||||
} catch (InvalidSettingValueException e) {
|
} catch (InvalidSettingValueException e) {
|
||||||
Log.v(K9.LOG_TAG, "Key \"" + key + "\" has invalid value \"" + prettyValue +
|
Log.v(K9.LOG_TAG, "Key \"" + key + "\" has invalid value \"" + prettyValue +
|
||||||
"\" in imported file. " +
|
"\" in imported file. " +
|
||||||
((useDefaultValues) ? "Using default value." : "Skipping."));
|
((useDefaultValues) ? "Using default value." : "Skipping."));
|
||||||
useDefaultValue = useDefaultValues;
|
useDefaultValue = useDefaultValues;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -245,7 +245,9 @@ public class Settings {
|
|||||||
if (value.length() == 7) {
|
if (value.length() == 7) {
|
||||||
return Integer.parseInt(value.substring(1), 16) | 0xFF000000;
|
return Integer.parseInt(value.substring(1), 16) | 0xFF000000;
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) { /* do nothing */ }
|
} catch (NumberFormatException e) {
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
throw new InvalidSettingValueException();
|
throw new InvalidSettingValueException();
|
||||||
}
|
}
|
||||||
@ -259,9 +261,9 @@ public class Settings {
|
|||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public static class EnumSetting extends SettingsDescription {
|
public static class EnumSetting extends SettingsDescription {
|
||||||
private Class<? extends Enum<?>> mEnumClass;
|
private Class <? extends Enum<? >> mEnumClass;
|
||||||
|
|
||||||
public EnumSetting(Class<? extends Enum<?>> enumClass, Object defaultValue) {
|
public EnumSetting(Class <? extends Enum<? >> enumClass, Object defaultValue) {
|
||||||
super(defaultValue);
|
super(defaultValue);
|
||||||
mEnumClass = enumClass;
|
mEnumClass = enumClass;
|
||||||
}
|
}
|
||||||
@ -270,7 +272,7 @@ public class Settings {
|
|||||||
@Override
|
@Override
|
||||||
public Object fromString(String value) throws InvalidSettingValueException {
|
public Object fromString(String value) throws InvalidSettingValueException {
|
||||||
try {
|
try {
|
||||||
return Enum.valueOf((Class<? extends Enum>)mEnumClass, value);
|
return Enum.valueOf((Class <? extends Enum >)mEnumClass, value);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new InvalidSettingValueException();
|
throw new InvalidSettingValueException();
|
||||||
}
|
}
|
||||||
@ -339,7 +341,9 @@ public class Settings {
|
|||||||
if (mMapping.containsKey(fontSize)) {
|
if (mMapping.containsKey(fontSize)) {
|
||||||
return fontSize;
|
return fontSize;
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) { /* do nothing */ }
|
} catch (NumberFormatException e) {
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
throw new InvalidSettingValueException();
|
throw new InvalidSettingValueException();
|
||||||
}
|
}
|
||||||
@ -375,7 +379,9 @@ public class Settings {
|
|||||||
if (mMapping.containsKey(fontSize)) {
|
if (mMapping.containsKey(fontSize)) {
|
||||||
return fontSize;
|
return fontSize;
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) { /* do nothing */ }
|
} catch (NumberFormatException e) {
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
throw new InvalidSettingValueException();
|
throw new InvalidSettingValueException();
|
||||||
}
|
}
|
||||||
@ -401,7 +407,9 @@ public class Settings {
|
|||||||
if (mStart <= intValue && intValue <= mEnd) {
|
if (mStart <= intValue && intValue <= mEnd) {
|
||||||
return intValue;
|
return intValue;
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) { /* do nothing */ }
|
} catch (NumberFormatException e) {
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
throw new InvalidSettingValueException();
|
throw new InvalidSettingValueException();
|
||||||
}
|
}
|
||||||
|
@ -76,13 +76,12 @@ public class SettingsExporter {
|
|||||||
|
|
||||||
|
|
||||||
public static String exportToFile(Context context, boolean includeGlobals,
|
public static String exportToFile(Context context, boolean includeGlobals,
|
||||||
Set<String> accountUuids)
|
Set<String> accountUuids)
|
||||||
throws SettingsImportExportException {
|
throws SettingsImportExportException {
|
||||||
|
|
||||||
OutputStream os = null;
|
OutputStream os = null;
|
||||||
String filename = null;
|
String filename = null;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
File dir = new File(Environment.getExternalStorageDirectory() + File.separator
|
File dir = new File(Environment.getExternalStorageDirectory() + File.separator
|
||||||
+ context.getPackageName());
|
+ context.getPackageName());
|
||||||
dir.mkdirs();
|
dir.mkdirs();
|
||||||
@ -108,13 +107,13 @@ public class SettingsExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void exportPreferences(Context context, OutputStream os, boolean includeGlobals,
|
public static void exportPreferences(Context context, OutputStream os, boolean includeGlobals,
|
||||||
Set<String> accountUuids) throws SettingsImportExportException {
|
Set<String> accountUuids) throws SettingsImportExportException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
XmlSerializer serializer = Xml.newSerializer();
|
XmlSerializer serializer = Xml.newSerializer();
|
||||||
serializer.setOutput(os, "UTF-8");
|
serializer.setOutput(os, "UTF-8");
|
||||||
|
|
||||||
serializer.startDocument(null, Boolean.valueOf(true));
|
serializer.startDocument(null, Boolean.TRUE);
|
||||||
|
|
||||||
// Output with indentation
|
// Output with indentation
|
||||||
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
|
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
|
||||||
@ -122,7 +121,7 @@ public class SettingsExporter {
|
|||||||
serializer.startTag(null, ROOT_ELEMENT);
|
serializer.startTag(null, ROOT_ELEMENT);
|
||||||
serializer.attribute(null, VERSION_ATTRIBUTE, Integer.toString(Settings.VERSION));
|
serializer.attribute(null, VERSION_ATTRIBUTE, Integer.toString(Settings.VERSION));
|
||||||
serializer.attribute(null, FILE_FORMAT_ATTRIBUTE,
|
serializer.attribute(null, FILE_FORMAT_ATTRIBUTE,
|
||||||
Integer.toString(FILE_FORMAT_VERSION));
|
Integer.toString(FILE_FORMAT_VERSION));
|
||||||
|
|
||||||
Log.i(K9.LOG_TAG, "Exporting preferences");
|
Log.i(K9.LOG_TAG, "Exporting preferences");
|
||||||
|
|
||||||
@ -165,7 +164,7 @@ public class SettingsExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void writeSettings(XmlSerializer serializer,
|
private static void writeSettings(XmlSerializer serializer,
|
||||||
Map<String, Object> prefs) throws IOException {
|
Map<String, Object> prefs) throws IOException {
|
||||||
|
|
||||||
for (String key : GlobalSettings.SETTINGS.keySet()) {
|
for (String key : GlobalSettings.SETTINGS.keySet()) {
|
||||||
String valueString = (String) prefs.get(key);
|
String valueString = (String) prefs.get(key);
|
||||||
@ -177,12 +176,12 @@ public class SettingsExporter {
|
|||||||
writeKeyValue(serializer, key, outputValue);
|
writeKeyValue(serializer, key, outputValue);
|
||||||
} catch (InvalidSettingValueException e) {
|
} catch (InvalidSettingValueException e) {
|
||||||
Log.w(K9.LOG_TAG, "Global setting \"" + key + "\" has invalid value \"" +
|
Log.w(K9.LOG_TAG, "Global setting \"" + key + "\" has invalid value \"" +
|
||||||
valueString + "\" in preference storage. This shouldn't happen!");
|
valueString + "\" in preference storage. This shouldn't happen!");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "Couldn't find key \"" + key + "\" in preference storage." +
|
Log.d(K9.LOG_TAG, "Couldn't find key \"" + key + "\" in preference storage." +
|
||||||
"Using default value.");
|
"Using default value.");
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsDescription setting = GlobalSettings.SETTINGS.get(key);
|
SettingsDescription setting = GlobalSettings.SETTINGS.get(key);
|
||||||
@ -194,7 +193,7 @@ public class SettingsExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void writeAccount(XmlSerializer serializer, Account account,
|
private static void writeAccount(XmlSerializer serializer, Account account,
|
||||||
Map<String, Object> prefs) throws IOException {
|
Map<String, Object> prefs) throws IOException {
|
||||||
|
|
||||||
Set<Integer> identities = new HashSet<Integer>();
|
Set<Integer> identities = new HashSet<Integer>();
|
||||||
Set<String> folders = new HashSet<String>();
|
Set<String> folders = new HashSet<String>();
|
||||||
@ -293,7 +292,9 @@ public class SettingsExporter {
|
|||||||
// This is an identity key. Save identity index for later...
|
// This is an identity key. Save identity index for later...
|
||||||
try {
|
try {
|
||||||
identities.add(Integer.parseInt(thirdPart));
|
identities.add(Integer.parseInt(thirdPart));
|
||||||
} catch (NumberFormatException e) { /* ignore */ }
|
} catch (NumberFormatException e) {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
// ... but don't write it now.
|
// ... but don't write it now.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -320,8 +321,8 @@ public class SettingsExporter {
|
|||||||
writeKeyValue(serializer, keyPart, pretty);
|
writeKeyValue(serializer, keyPart, pretty);
|
||||||
} catch (InvalidSettingValueException e) {
|
} catch (InvalidSettingValueException e) {
|
||||||
Log.w(K9.LOG_TAG, "Account setting \"" + keyPart + "\" (" +
|
Log.w(K9.LOG_TAG, "Account setting \"" + keyPart + "\" (" +
|
||||||
account.getDescription() + ") has invalid value \"" + valueString +
|
account.getDescription() + ") has invalid value \"" + valueString +
|
||||||
"\" in preference storage. This shouldn't happen!");
|
"\" in preference storage. This shouldn't happen!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -352,7 +353,7 @@ public class SettingsExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void writeIdentity(XmlSerializer serializer, String accountUuid,
|
private static void writeIdentity(XmlSerializer serializer, String accountUuid,
|
||||||
String identity, Map<String, Object> prefs) throws IOException {
|
String identity, Map<String, Object> prefs) throws IOException {
|
||||||
|
|
||||||
serializer.startTag(null, IDENTITY_ELEMENT);
|
serializer.startTag(null, IDENTITY_ELEMENT);
|
||||||
|
|
||||||
@ -408,8 +409,8 @@ public class SettingsExporter {
|
|||||||
writeKeyValue(serializer, identityKey, outputValue);
|
writeKeyValue(serializer, identityKey, outputValue);
|
||||||
} catch (InvalidSettingValueException e) {
|
} catch (InvalidSettingValueException e) {
|
||||||
Log.w(K9.LOG_TAG, "Identity setting \"" + identityKey +
|
Log.w(K9.LOG_TAG, "Identity setting \"" + identityKey +
|
||||||
"\" has invalid value \"" + valueString +
|
"\" has invalid value \"" + valueString +
|
||||||
"\" in preference storage. This shouldn't happen!");
|
"\" in preference storage. This shouldn't happen!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -419,7 +420,7 @@ public class SettingsExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void writeFolder(XmlSerializer serializer, String accountUuid,
|
private static void writeFolder(XmlSerializer serializer, String accountUuid,
|
||||||
String folder, Map<String, Object> prefs) throws IOException {
|
String folder, Map<String, Object> prefs) throws IOException {
|
||||||
|
|
||||||
serializer.startTag(null, FOLDER_ELEMENT);
|
serializer.startTag(null, FOLDER_ELEMENT);
|
||||||
serializer.attribute(null, NAME_ATTRIBUTE, folder);
|
serializer.attribute(null, NAME_ATTRIBUTE, folder);
|
||||||
@ -453,8 +454,8 @@ public class SettingsExporter {
|
|||||||
writeKeyValue(serializer, folderKey, outputValue);
|
writeKeyValue(serializer, folderKey, outputValue);
|
||||||
} catch (InvalidSettingValueException e) {
|
} catch (InvalidSettingValueException e) {
|
||||||
Log.w(K9.LOG_TAG, "Folder setting \"" + folderKey +
|
Log.w(K9.LOG_TAG, "Folder setting \"" + folderKey +
|
||||||
"\" has invalid value \"" + valueString +
|
"\" has invalid value \"" + valueString +
|
||||||
"\" in preference storage. This shouldn't happen!");
|
"\" in preference storage. This shouldn't happen!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -463,7 +464,7 @@ public class SettingsExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void writeElement(XmlSerializer serializer, String elementName, String value)
|
private static void writeElement(XmlSerializer serializer, String elementName, String value)
|
||||||
throws IllegalArgumentException, IllegalStateException, IOException {
|
throws IllegalArgumentException, IllegalStateException, IOException {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
serializer.startTag(null, elementName);
|
serializer.startTag(null, elementName);
|
||||||
serializer.text(value);
|
serializer.text(value);
|
||||||
@ -472,7 +473,7 @@ public class SettingsExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void writeKeyValue(XmlSerializer serializer, String key, String value)
|
private static void writeKeyValue(XmlSerializer serializer, String key, String value)
|
||||||
throws IllegalArgumentException, IllegalStateException, IOException {
|
throws IllegalArgumentException, IllegalStateException, IOException {
|
||||||
serializer.startTag(null, VALUE_ELEMENT);
|
serializer.startTag(null, VALUE_ELEMENT);
|
||||||
serializer.attribute(null, KEY_ATTRIBUTE, key);
|
serializer.attribute(null, KEY_ATTRIBUTE, key);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
|
@ -83,7 +83,7 @@ public class SettingsImporter {
|
|||||||
public final boolean overwritten;
|
public final boolean overwritten;
|
||||||
|
|
||||||
private AccountDescriptionPair(AccountDescription original, AccountDescription imported,
|
private AccountDescriptionPair(AccountDescription original, AccountDescription imported,
|
||||||
boolean overwritten) {
|
boolean overwritten) {
|
||||||
this.original = original;
|
this.original = original;
|
||||||
this.imported = imported;
|
this.imported = imported;
|
||||||
this.overwritten = overwritten;
|
this.overwritten = overwritten;
|
||||||
@ -96,11 +96,11 @@ public class SettingsImporter {
|
|||||||
public final List<AccountDescription> errorneousAccounts;
|
public final List<AccountDescription> errorneousAccounts;
|
||||||
|
|
||||||
private ImportResults(boolean globalSettings,
|
private ImportResults(boolean globalSettings,
|
||||||
List<AccountDescriptionPair> importedAccounts,
|
List<AccountDescriptionPair> importedAccounts,
|
||||||
List<AccountDescription> errorneousAccounts) {
|
List<AccountDescription> errorneousAccounts) {
|
||||||
this.globalSettings = globalSettings;
|
this.globalSettings = globalSettings;
|
||||||
this.importedAccounts = importedAccounts;
|
this.importedAccounts = importedAccounts;
|
||||||
this.errorneousAccounts = errorneousAccounts;
|
this.errorneousAccounts = errorneousAccounts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ public class SettingsImporter {
|
|||||||
* In case of an error.
|
* In case of an error.
|
||||||
*/
|
*/
|
||||||
public static ImportContents getImportStreamContents(InputStream inputStream)
|
public static ImportContents getImportStreamContents(InputStream inputStream)
|
||||||
throws SettingsImportExportException {
|
throws SettingsImportExportException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Parse the import stream but don't save individual settings (overview=true)
|
// Parse the import stream but don't save individual settings (overview=true)
|
||||||
@ -176,8 +176,7 @@ public class SettingsImporter {
|
|||||||
boolean globalSettings, List<String> accountUuids, boolean overwrite)
|
boolean globalSettings, List<String> accountUuids, boolean overwrite)
|
||||||
throws SettingsImportExportException {
|
throws SettingsImportExportException {
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
boolean globalSettingsImported = false;
|
boolean globalSettingsImported = false;
|
||||||
List<AccountDescriptionPair> importedAccounts = new ArrayList<AccountDescriptionPair>();
|
List<AccountDescriptionPair> importedAccounts = new ArrayList<AccountDescriptionPair>();
|
||||||
List<AccountDescription> errorneousAccounts = new ArrayList<AccountDescription>();
|
List<AccountDescription> errorneousAccounts = new ArrayList<AccountDescription>();
|
||||||
@ -198,13 +197,13 @@ public class SettingsImporter {
|
|||||||
if (editor.commit()) {
|
if (editor.commit()) {
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.v(K9.LOG_TAG, "Committed global settings to the preference " +
|
Log.v(K9.LOG_TAG, "Committed global settings to the preference " +
|
||||||
"storage.");
|
"storage.");
|
||||||
}
|
}
|
||||||
globalSettingsImported = true;
|
globalSettingsImported = true;
|
||||||
} else {
|
} else {
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.v(K9.LOG_TAG, "Failed to commit global settings to the " +
|
Log.v(K9.LOG_TAG, "Failed to commit global settings to the " +
|
||||||
"preference storage");
|
"preference storage");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -222,7 +221,7 @@ public class SettingsImporter {
|
|||||||
SharedPreferences.Editor editor = storage.edit();
|
SharedPreferences.Editor editor = storage.edit();
|
||||||
|
|
||||||
AccountDescriptionPair importResult = importAccount(context,
|
AccountDescriptionPair importResult = importAccount(context,
|
||||||
editor, account, overwrite);
|
editor, account, overwrite);
|
||||||
|
|
||||||
String newUuid = importResult.imported.uuid;
|
String newUuid = importResult.imported.uuid;
|
||||||
if (!importResult.overwritten) {
|
if (!importResult.overwritten) {
|
||||||
@ -231,32 +230,32 @@ public class SettingsImporter {
|
|||||||
if (editor.commit()) {
|
if (editor.commit()) {
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.v(K9.LOG_TAG, "Committed settings for account \"" +
|
Log.v(K9.LOG_TAG, "Committed settings for account \"" +
|
||||||
importResult.imported.name +
|
importResult.imported.name +
|
||||||
"\" to the settings database.");
|
"\" to the settings database.");
|
||||||
}
|
}
|
||||||
importedAccounts.add(importResult);
|
importedAccounts.add(importResult);
|
||||||
} else {
|
} else {
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.w(K9.LOG_TAG, "Error while committing settings for " +
|
Log.w(K9.LOG_TAG, "Error while committing settings for " +
|
||||||
"account \"" + importResult.original.name +
|
"account \"" + importResult.original.name +
|
||||||
"\" to the settings database.");
|
"\" to the settings database.");
|
||||||
}
|
}
|
||||||
errorneousAccounts.add(importResult.original);
|
errorneousAccounts.add(importResult.original);
|
||||||
}
|
}
|
||||||
} catch (InvalidSettingValueException e) {
|
} catch (InvalidSettingValueException e) {
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.e(K9.LOG_TAG, "Encountered invalid setting while " +
|
Log.e(K9.LOG_TAG, "Encountered invalid setting while " +
|
||||||
"importing account \"" + account.name + "\"", e);
|
"importing account \"" + account.name + "\"", e);
|
||||||
}
|
}
|
||||||
errorneousAccounts.add(new AccountDescription(account.name, account.uuid));
|
errorneousAccounts.add(new AccountDescription(account.name, account.uuid));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(K9.LOG_TAG, "Exception while importing account \"" +
|
Log.e(K9.LOG_TAG, "Exception while importing account \"" +
|
||||||
account.name + "\"", e);
|
account.name + "\"", e);
|
||||||
errorneousAccounts.add(new AccountDescription(account.name, account.uuid));
|
errorneousAccounts.add(new AccountDescription(account.name, account.uuid));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.w(K9.LOG_TAG, "Was asked to import account with UUID " +
|
Log.w(K9.LOG_TAG, "Was asked to import account with UUID " +
|
||||||
accountUuid + ". But this account wasn't found.");
|
accountUuid + ". But this account wasn't found.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +318,7 @@ public class SettingsImporter {
|
|||||||
|
|
||||||
private static AccountDescriptionPair importAccount(Context context,
|
private static AccountDescriptionPair importAccount(Context context,
|
||||||
SharedPreferences.Editor editor, ImportedAccount account, boolean overwrite)
|
SharedPreferences.Editor editor, ImportedAccount account, boolean overwrite)
|
||||||
throws InvalidSettingValueException {
|
throws InvalidSettingValueException {
|
||||||
|
|
||||||
AccountDescription original = new AccountDescription(account.name, account.uuid);
|
AccountDescription original = new AccountDescription(account.name, account.uuid);
|
||||||
|
|
||||||
@ -365,7 +364,7 @@ public class SettingsImporter {
|
|||||||
|
|
||||||
// Mark account as disabled if the settings file didn't contain a password
|
// Mark account as disabled if the settings file didn't contain a password
|
||||||
boolean createAccountDisabled = (incoming.password == null ||
|
boolean createAccountDisabled = (incoming.password == null ||
|
||||||
incoming.password.length() == 0);
|
incoming.password.length() == 0);
|
||||||
|
|
||||||
if (account.outgoing == null && !WebDavStore.STORE_TYPE.equals(account.incoming.type)) {
|
if (account.outgoing == null && !WebDavStore.STORE_TYPE.equals(account.incoming.type)) {
|
||||||
// All account types except WebDAV need to provide outgoing server settings
|
// All account types except WebDAV need to provide outgoing server settings
|
||||||
@ -397,7 +396,7 @@ public class SettingsImporter {
|
|||||||
Map<String, String> writeSettings;
|
Map<String, String> writeSettings;
|
||||||
if (mergeImportedAccount) {
|
if (mergeImportedAccount) {
|
||||||
writeSettings = new HashMap<String, String>(
|
writeSettings = new HashMap<String, String>(
|
||||||
AccountSettings.getAccountSettings(prefs.getPreferences(), uuid));
|
AccountSettings.getAccountSettings(prefs.getPreferences(), uuid));
|
||||||
writeSettings.putAll(validatedSettings);
|
writeSettings.putAll(validatedSettings);
|
||||||
} else {
|
} else {
|
||||||
writeSettings = validatedSettings;
|
writeSettings = validatedSettings;
|
||||||
@ -438,7 +437,7 @@ public class SettingsImporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void importFolder(SharedPreferences.Editor editor, String uuid,
|
private static void importFolder(SharedPreferences.Editor editor, String uuid,
|
||||||
ImportedFolder folder, boolean overwrite, Preferences prefs) {
|
ImportedFolder folder, boolean overwrite, Preferences prefs) {
|
||||||
|
|
||||||
// Validate folder settings
|
// Validate folder settings
|
||||||
Map<String, String> validatedSettings =
|
Map<String, String> validatedSettings =
|
||||||
@ -448,7 +447,7 @@ public class SettingsImporter {
|
|||||||
Map<String, String> writeSettings;
|
Map<String, String> writeSettings;
|
||||||
if (overwrite) {
|
if (overwrite) {
|
||||||
writeSettings = FolderSettings.getFolderSettings(prefs.getPreferences(),
|
writeSettings = FolderSettings.getFolderSettings(prefs.getPreferences(),
|
||||||
uuid, folder.name);
|
uuid, folder.name);
|
||||||
writeSettings.putAll(validatedSettings);
|
writeSettings.putAll(validatedSettings);
|
||||||
} else {
|
} else {
|
||||||
writeSettings = validatedSettings;
|
writeSettings = validatedSettings;
|
||||||
@ -464,8 +463,8 @@ public class SettingsImporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void importIdentities(SharedPreferences.Editor editor, String uuid,
|
private static void importIdentities(SharedPreferences.Editor editor, String uuid,
|
||||||
ImportedAccount account, boolean overwrite, Account existingAccount,
|
ImportedAccount account, boolean overwrite, Account existingAccount,
|
||||||
Preferences prefs) throws InvalidSettingValueException {
|
Preferences prefs) throws InvalidSettingValueException {
|
||||||
|
|
||||||
String accountKeyPrefix = uuid + ".";
|
String accountKeyPrefix = uuid + ".";
|
||||||
|
|
||||||
@ -495,7 +494,7 @@ public class SettingsImporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String identityDescription = (identity.description == null) ?
|
String identityDescription = (identity.description == null) ?
|
||||||
"Imported" : identity.description;
|
"Imported" : identity.description;
|
||||||
if (isIdentityDescriptionUsed(identityDescription, existingIdentities)) {
|
if (isIdentityDescriptionUsed(identityDescription, existingIdentities)) {
|
||||||
// Identity description is already in use. So generate a new one by appending
|
// Identity description is already in use. So generate a new one by appending
|
||||||
// " (x)", where x is the first number >= 1 that results in an unused identity
|
// " (x)", where x is the first number >= 1 that results in an unused identity
|
||||||
@ -513,7 +512,7 @@ public class SettingsImporter {
|
|||||||
// Write name used in identity
|
// Write name used in identity
|
||||||
String identityName = (identity.name == null) ? "" : identity.name;
|
String identityName = (identity.name == null) ? "" : identity.name;
|
||||||
putString(editor, accountKeyPrefix + Account.IDENTITY_NAME_KEY + identitySuffix,
|
putString(editor, accountKeyPrefix + Account.IDENTITY_NAME_KEY + identitySuffix,
|
||||||
identityName);
|
identityName);
|
||||||
|
|
||||||
// Validate email address
|
// Validate email address
|
||||||
if (!IdentitySettings.isEmailAddressValid(identity.email)) {
|
if (!IdentitySettings.isEmailAddressValid(identity.email)) {
|
||||||
@ -522,11 +521,11 @@ public class SettingsImporter {
|
|||||||
|
|
||||||
// Write email address
|
// Write email address
|
||||||
putString(editor, accountKeyPrefix + Account.IDENTITY_EMAIL_KEY + identitySuffix,
|
putString(editor, accountKeyPrefix + Account.IDENTITY_EMAIL_KEY + identitySuffix,
|
||||||
identity.email);
|
identity.email);
|
||||||
|
|
||||||
// Write identity description
|
// Write identity description
|
||||||
putString(editor, accountKeyPrefix + Account.IDENTITY_DESCRIPTION_KEY + identitySuffix,
|
putString(editor, accountKeyPrefix + Account.IDENTITY_DESCRIPTION_KEY + identitySuffix,
|
||||||
identityDescription);
|
identityDescription);
|
||||||
|
|
||||||
if (identity.settings != null) {
|
if (identity.settings != null) {
|
||||||
// Validate identity settings
|
// Validate identity settings
|
||||||
@ -537,7 +536,7 @@ public class SettingsImporter {
|
|||||||
Map<String, String> writeSettings;
|
Map<String, String> writeSettings;
|
||||||
if (mergeSettings) {
|
if (mergeSettings) {
|
||||||
writeSettings = new HashMap<String, String>(IdentitySettings.getIdentitySettings(
|
writeSettings = new HashMap<String, String>(IdentitySettings.getIdentitySettings(
|
||||||
prefs.getPreferences(), uuid, writeIdentityIndex));
|
prefs.getPreferences(), uuid, writeIdentityIndex));
|
||||||
writeSettings.putAll(validatedSettings);
|
writeSettings.putAll(validatedSettings);
|
||||||
} else {
|
} else {
|
||||||
writeSettings = validatedSettings;
|
writeSettings = validatedSettings;
|
||||||
@ -572,7 +571,7 @@ public class SettingsImporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static int findIdentity(ImportedIdentity identity,
|
private static int findIdentity(ImportedIdentity identity,
|
||||||
List<Identity> identities) {
|
List<Identity> identities) {
|
||||||
for (int i = 0; i < identities.size(); i++) {
|
for (int i = 0; i < identities.size(); i++) {
|
||||||
Identity existingIdentity = identities.get(i);
|
Identity existingIdentity = identities.get(i);
|
||||||
if (existingIdentity.getName().equals(identity.name) &&
|
if (existingIdentity.getName().equals(identity.name) &&
|
||||||
@ -607,7 +606,7 @@ public class SettingsImporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Imported parseSettings(InputStream inputStream, boolean globalSettings,
|
private static Imported parseSettings(InputStream inputStream, boolean globalSettings,
|
||||||
List<String> accountUuids, boolean overview)
|
List<String> accountUuids, boolean overview)
|
||||||
throws SettingsImportExportException {
|
throws SettingsImportExportException {
|
||||||
|
|
||||||
if (!overview && accountUuids == null) {
|
if (!overview && accountUuids == null) {
|
||||||
@ -625,7 +624,7 @@ public class SettingsImporter {
|
|||||||
Imported imported = null;
|
Imported imported = null;
|
||||||
int eventType = xpp.getEventType();
|
int eventType = xpp.getEventType();
|
||||||
while (eventType != XmlPullParser.END_DOCUMENT) {
|
while (eventType != XmlPullParser.END_DOCUMENT) {
|
||||||
if(eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
if (SettingsExporter.ROOT_ELEMENT.equals(xpp.getName())) {
|
if (SettingsExporter.ROOT_ELEMENT.equals(xpp.getName())) {
|
||||||
imported = parseRoot(xpp, globalSettings, accountUuids, overview);
|
imported = parseRoot(xpp, globalSettings, accountUuids, overview);
|
||||||
} else {
|
} else {
|
||||||
@ -636,7 +635,7 @@ public class SettingsImporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (imported == null || (overview && imported.globalSettings == null &&
|
if (imported == null || (overview && imported.globalSettings == null &&
|
||||||
imported.accounts == null)) {
|
imported.accounts == null)) {
|
||||||
throw new SettingsImportExportException("Invalid import data");
|
throw new SettingsImportExportException("Invalid import data");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -666,24 +665,24 @@ public class SettingsImporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Imported parseRoot(XmlPullParser xpp, boolean globalSettings,
|
private static Imported parseRoot(XmlPullParser xpp, boolean globalSettings,
|
||||||
List<String> accountUuids, boolean overview)
|
List<String> accountUuids, boolean overview)
|
||||||
throws XmlPullParserException, IOException, SettingsImportExportException {
|
throws XmlPullParserException, IOException, SettingsImportExportException {
|
||||||
|
|
||||||
Imported result = new Imported();
|
Imported result = new Imported();
|
||||||
|
|
||||||
String fileFormatVersionString = xpp.getAttributeValue(null,
|
String fileFormatVersionString = xpp.getAttributeValue(null,
|
||||||
SettingsExporter.FILE_FORMAT_ATTRIBUTE);
|
SettingsExporter.FILE_FORMAT_ATTRIBUTE);
|
||||||
validateFileFormatVersion(fileFormatVersionString);
|
validateFileFormatVersion(fileFormatVersionString);
|
||||||
|
|
||||||
String contentVersionString = xpp.getAttributeValue(null,
|
String contentVersionString = xpp.getAttributeValue(null,
|
||||||
SettingsExporter.VERSION_ATTRIBUTE);
|
SettingsExporter.VERSION_ATTRIBUTE);
|
||||||
validateContentVersion(contentVersionString);
|
validateContentVersion(contentVersionString);
|
||||||
|
|
||||||
int eventType = xpp.next();
|
int eventType = xpp.next();
|
||||||
while (!(eventType == XmlPullParser.END_TAG &&
|
while (!(eventType == XmlPullParser.END_TAG &&
|
||||||
SettingsExporter.ROOT_ELEMENT.equals(xpp.getName()))) {
|
SettingsExporter.ROOT_ELEMENT.equals(xpp.getName()))) {
|
||||||
|
|
||||||
if(eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
String element = xpp.getName();
|
String element = xpp.getName();
|
||||||
if (SettingsExporter.GLOBAL_ELEMENT.equals(element)) {
|
if (SettingsExporter.GLOBAL_ELEMENT.equals(element)) {
|
||||||
if (overview || globalSettings) {
|
if (overview || globalSettings) {
|
||||||
@ -719,7 +718,7 @@ public class SettingsImporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static int validateFileFormatVersion(String versionString)
|
private static int validateFileFormatVersion(String versionString)
|
||||||
throws SettingsImportExportException {
|
throws SettingsImportExportException {
|
||||||
|
|
||||||
if (versionString == null) {
|
if (versionString == null) {
|
||||||
throw new SettingsImportExportException("Missing file format version");
|
throw new SettingsImportExportException("Missing file format version");
|
||||||
@ -730,19 +729,19 @@ public class SettingsImporter {
|
|||||||
version = Integer.parseInt(versionString);
|
version = Integer.parseInt(versionString);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new SettingsImportExportException("Invalid file format version: " +
|
throw new SettingsImportExportException("Invalid file format version: " +
|
||||||
versionString);
|
versionString);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version != SettingsExporter.FILE_FORMAT_VERSION) {
|
if (version != SettingsExporter.FILE_FORMAT_VERSION) {
|
||||||
throw new SettingsImportExportException("Unsupported file format version: " +
|
throw new SettingsImportExportException("Unsupported file format version: " +
|
||||||
versionString);
|
versionString);
|
||||||
}
|
}
|
||||||
|
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int validateContentVersion(String versionString)
|
private static int validateContentVersion(String versionString)
|
||||||
throws SettingsImportExportException {
|
throws SettingsImportExportException {
|
||||||
|
|
||||||
if (versionString == null) {
|
if (versionString == null) {
|
||||||
throw new SettingsImportExportException("Missing content version");
|
throw new SettingsImportExportException("Missing content version");
|
||||||
@ -753,12 +752,12 @@ public class SettingsImporter {
|
|||||||
version = Integer.parseInt(versionString);
|
version = Integer.parseInt(versionString);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new SettingsImportExportException("Invalid content version: " +
|
throw new SettingsImportExportException("Invalid content version: " +
|
||||||
versionString);
|
versionString);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version != Settings.VERSION) {
|
if (version != Settings.VERSION) {
|
||||||
throw new SettingsImportExportException("Unsupported content version: " +
|
throw new SettingsImportExportException("Unsupported content version: " +
|
||||||
versionString);
|
versionString);
|
||||||
}
|
}
|
||||||
|
|
||||||
return version;
|
return version;
|
||||||
@ -772,7 +771,7 @@ public class SettingsImporter {
|
|||||||
int eventType = xpp.next();
|
int eventType = xpp.next();
|
||||||
while (!(eventType == XmlPullParser.END_TAG && endTag.equals(xpp.getName()))) {
|
while (!(eventType == XmlPullParser.END_TAG && endTag.equals(xpp.getName()))) {
|
||||||
|
|
||||||
if(eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
String element = xpp.getName();
|
String element = xpp.getName();
|
||||||
if (SettingsExporter.VALUE_ELEMENT.equals(element)) {
|
if (SettingsExporter.VALUE_ELEMENT.equals(element)) {
|
||||||
String key = xpp.getAttributeValue(null, SettingsExporter.KEY_ATTRIBUTE);
|
String key = xpp.getAttributeValue(null, SettingsExporter.KEY_ATTRIBUTE);
|
||||||
@ -807,7 +806,7 @@ public class SettingsImporter {
|
|||||||
while (!(eventType == XmlPullParser.END_TAG &&
|
while (!(eventType == XmlPullParser.END_TAG &&
|
||||||
SettingsExporter.ACCOUNTS_ELEMENT.equals(xpp.getName()))) {
|
SettingsExporter.ACCOUNTS_ELEMENT.equals(xpp.getName()))) {
|
||||||
|
|
||||||
if(eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
String element = xpp.getName();
|
String element = xpp.getName();
|
||||||
if (SettingsExporter.ACCOUNT_ELEMENT.equals(element)) {
|
if (SettingsExporter.ACCOUNT_ELEMENT.equals(element)) {
|
||||||
if (accounts == null) {
|
if (accounts == null) {
|
||||||
@ -822,7 +821,7 @@ public class SettingsImporter {
|
|||||||
accounts.put(account.uuid, account);
|
accounts.put(account.uuid, account);
|
||||||
} else {
|
} else {
|
||||||
Log.w(K9.LOG_TAG, "Duplicate account entries with UUID " + account.uuid +
|
Log.w(K9.LOG_TAG, "Duplicate account entries with UUID " + account.uuid +
|
||||||
". Ignoring!");
|
". Ignoring!");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.w(K9.LOG_TAG, "Unexpected start tag: " + xpp.getName());
|
Log.w(K9.LOG_TAG, "Unexpected start tag: " + xpp.getName());
|
||||||
@ -856,7 +855,7 @@ public class SettingsImporter {
|
|||||||
while (!(eventType == XmlPullParser.END_TAG &&
|
while (!(eventType == XmlPullParser.END_TAG &&
|
||||||
SettingsExporter.ACCOUNT_ELEMENT.equals(xpp.getName()))) {
|
SettingsExporter.ACCOUNT_ELEMENT.equals(xpp.getName()))) {
|
||||||
|
|
||||||
if(eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
String element = xpp.getName();
|
String element = xpp.getName();
|
||||||
if (SettingsExporter.NAME_ELEMENT.equals(element)) {
|
if (SettingsExporter.NAME_ELEMENT.equals(element)) {
|
||||||
account.name = getText(xpp);
|
account.name = getText(xpp);
|
||||||
@ -912,7 +911,7 @@ public class SettingsImporter {
|
|||||||
|
|
||||||
int eventType = xpp.next();
|
int eventType = xpp.next();
|
||||||
while (!(eventType == XmlPullParser.END_TAG && endTag.equals(xpp.getName()))) {
|
while (!(eventType == XmlPullParser.END_TAG && endTag.equals(xpp.getName()))) {
|
||||||
if(eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
String element = xpp.getName();
|
String element = xpp.getName();
|
||||||
if (SettingsExporter.HOST_ELEMENT.equals(element)) {
|
if (SettingsExporter.HOST_ELEMENT.equals(element)) {
|
||||||
server.host = getText(xpp);
|
server.host = getText(xpp);
|
||||||
@ -946,7 +945,7 @@ public class SettingsImporter {
|
|||||||
while (!(eventType == XmlPullParser.END_TAG &&
|
while (!(eventType == XmlPullParser.END_TAG &&
|
||||||
SettingsExporter.IDENTITIES_ELEMENT.equals(xpp.getName()))) {
|
SettingsExporter.IDENTITIES_ELEMENT.equals(xpp.getName()))) {
|
||||||
|
|
||||||
if(eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
String element = xpp.getName();
|
String element = xpp.getName();
|
||||||
if (SettingsExporter.IDENTITY_ELEMENT.equals(element)) {
|
if (SettingsExporter.IDENTITY_ELEMENT.equals(element)) {
|
||||||
if (identities == null) {
|
if (identities == null) {
|
||||||
@ -973,7 +972,7 @@ public class SettingsImporter {
|
|||||||
while (!(eventType == XmlPullParser.END_TAG &&
|
while (!(eventType == XmlPullParser.END_TAG &&
|
||||||
SettingsExporter.IDENTITY_ELEMENT.equals(xpp.getName()))) {
|
SettingsExporter.IDENTITY_ELEMENT.equals(xpp.getName()))) {
|
||||||
|
|
||||||
if(eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
String element = xpp.getName();
|
String element = xpp.getName();
|
||||||
if (SettingsExporter.NAME_ELEMENT.equals(element)) {
|
if (SettingsExporter.NAME_ELEMENT.equals(element)) {
|
||||||
identity.name = getText(xpp);
|
identity.name = getText(xpp);
|
||||||
@ -1001,7 +1000,7 @@ public class SettingsImporter {
|
|||||||
while (!(eventType == XmlPullParser.END_TAG &&
|
while (!(eventType == XmlPullParser.END_TAG &&
|
||||||
SettingsExporter.FOLDERS_ELEMENT.equals(xpp.getName()))) {
|
SettingsExporter.FOLDERS_ELEMENT.equals(xpp.getName()))) {
|
||||||
|
|
||||||
if(eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
String element = xpp.getName();
|
String element = xpp.getName();
|
||||||
if (SettingsExporter.FOLDER_ELEMENT.equals(element)) {
|
if (SettingsExporter.FOLDER_ELEMENT.equals(element)) {
|
||||||
if (folders == null) {
|
if (folders == null) {
|
||||||
@ -1037,15 +1036,15 @@ public class SettingsImporter {
|
|||||||
|
|
||||||
public ImportedServerSettings(ImportedServer server) {
|
public ImportedServerSettings(ImportedServer server) {
|
||||||
super(server.type, server.host, convertPort(server.port),
|
super(server.type, server.host, convertPort(server.port),
|
||||||
convertConnectionSecurity(server.connectionSecurity),
|
convertConnectionSecurity(server.connectionSecurity),
|
||||||
server.authenticationType, server.username, server.password);
|
server.authenticationType, server.username, server.password);
|
||||||
mImportedServer = server;
|
mImportedServer = server;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, String> getExtra() {
|
public Map<String, String> getExtra() {
|
||||||
return (mImportedServer.extras != null) ?
|
return (mImportedServer.extras != null) ?
|
||||||
Collections.unmodifiableMap(mImportedServer.extras.settings) : null;
|
Collections.unmodifiableMap(mImportedServer.extras.settings) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int convertPort(String port) {
|
private static int convertPort(String port) {
|
||||||
|
@ -31,7 +31,7 @@ public class Storage implements SharedPreferences {
|
|||||||
private String DB_NAME = "preferences_storage";
|
private String DB_NAME = "preferences_storage";
|
||||||
|
|
||||||
private ThreadLocal<ConcurrentHashMap<String, String>> workingStorage
|
private ThreadLocal<ConcurrentHashMap<String, String>> workingStorage
|
||||||
= new ThreadLocal<ConcurrentHashMap<String, String>>();
|
= new ThreadLocal<ConcurrentHashMap<String, String>>();
|
||||||
private ThreadLocal<SQLiteDatabase> workingDB =
|
private ThreadLocal<SQLiteDatabase> workingDB =
|
||||||
new ThreadLocal<SQLiteDatabase>();
|
new ThreadLocal<SQLiteDatabase>();
|
||||||
private ThreadLocal<ArrayList<String>> workingChangedKeys = new ThreadLocal<ArrayList<String>>();
|
private ThreadLocal<ArrayList<String>> workingChangedKeys = new ThreadLocal<ArrayList<String>>();
|
||||||
|
@ -118,7 +118,7 @@ public abstract class CoreService extends Service {
|
|||||||
* lock is created, registered, and added to {@code intent}.
|
* lock is created, registered, and added to {@code intent}.
|
||||||
*/
|
*/
|
||||||
protected static void addWakeLockId(Context context, Intent intent, Integer wakeLockId,
|
protected static void addWakeLockId(Context context, Intent intent, Integer wakeLockId,
|
||||||
boolean createIfNotExists) {
|
boolean createIfNotExists) {
|
||||||
|
|
||||||
if (wakeLockId != null) {
|
if (wakeLockId != null) {
|
||||||
intent.putExtra(BootReceiver.WAKE_LOCK_ID, wakeLockId);
|
intent.putExtra(BootReceiver.WAKE_LOCK_ID, wakeLockId);
|
||||||
@ -126,7 +126,7 @@ public abstract class CoreService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (createIfNotExists) {
|
if (createIfNotExists) {
|
||||||
addWakeLock(context,intent);
|
addWakeLock(context, intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +144,7 @@ public abstract class CoreService extends Service {
|
|||||||
*/
|
*/
|
||||||
protected static void addWakeLock(Context context, Intent intent) {
|
protected static void addWakeLock(Context context, Intent intent) {
|
||||||
TracingWakeLock wakeLock = acquireWakeLock(context, "CoreService addWakeLock",
|
TracingWakeLock wakeLock = acquireWakeLock(context, "CoreService addWakeLock",
|
||||||
K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT);
|
K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT);
|
||||||
Integer tmpWakeLockId = registerWakeLock(wakeLock);
|
Integer tmpWakeLockId = registerWakeLock(wakeLock);
|
||||||
intent.putExtra(WAKE_LOCK_ID, tmpWakeLockId);
|
intent.putExtra(WAKE_LOCK_ID, tmpWakeLockId);
|
||||||
}
|
}
|
||||||
@ -216,7 +216,7 @@ public abstract class CoreService extends Service {
|
|||||||
|
|
||||||
// Acquire new wake lock
|
// Acquire new wake lock
|
||||||
TracingWakeLock wakeLock = acquireWakeLock(this, "CoreService onStart",
|
TracingWakeLock wakeLock = acquireWakeLock(this, "CoreService onStart",
|
||||||
K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT);
|
K9.MAIL_SERVICE_WAKE_LOCK_TIMEOUT);
|
||||||
|
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.i(K9.LOG_TAG, "CoreService: " + className + ".onStart(" + intent + ", " + startId + ")");
|
Log.i(K9.LOG_TAG, "CoreService: " + className + ".onStart(" + intent + ", " + startId + ")");
|
||||||
@ -243,7 +243,7 @@ public abstract class CoreService extends Service {
|
|||||||
if (coreWakeLock != null) {
|
if (coreWakeLock != null) {
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "Found core wake lock with id " + coreWakeLockId +
|
Log.d(K9.LOG_TAG, "Found core wake lock with id " + coreWakeLockId +
|
||||||
", releasing");
|
", releasing");
|
||||||
}
|
}
|
||||||
coreWakeLock.release();
|
coreWakeLock.release();
|
||||||
}
|
}
|
||||||
@ -258,7 +258,9 @@ public abstract class CoreService extends Service {
|
|||||||
try {
|
try {
|
||||||
// Release the wake lock acquired at the start of this method
|
// Release the wake lock acquired at the start of this method
|
||||||
wakeLock.release();
|
wakeLock.release();
|
||||||
} catch (Exception e) { /* ignore */ }
|
} catch (Exception e) {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// If there is no outstanding work to be done in a background thread we can stop
|
// If there is no outstanding work to be done in a background thread we can stop
|
||||||
@ -267,7 +269,9 @@ public abstract class CoreService extends Service {
|
|||||||
stopSelf(startId);
|
stopSelf(startId);
|
||||||
startFlag = START_NOT_STICKY;
|
startFlag = START_NOT_STICKY;
|
||||||
}
|
}
|
||||||
} catch (Exception e) { /* ignore */ }
|
} catch (Exception e) {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return startFlag;
|
return startFlag;
|
||||||
@ -290,14 +294,14 @@ public abstract class CoreService extends Service {
|
|||||||
* otherwise the auto shutdown code will stop the service.
|
* otherwise the auto shutdown code will stop the service.
|
||||||
*/
|
*/
|
||||||
public void execute(Context context, final Runnable runner, int wakeLockTime,
|
public void execute(Context context, final Runnable runner, int wakeLockTime,
|
||||||
final Integer startId) {
|
final Integer startId) {
|
||||||
|
|
||||||
boolean serviceShutdownScheduled = false;
|
boolean serviceShutdownScheduled = false;
|
||||||
final boolean autoShutdown = mAutoShutdown;
|
final boolean autoShutdown = mAutoShutdown;
|
||||||
|
|
||||||
// Acquire a new wakelock
|
// Acquire a new wakelock
|
||||||
final TracingWakeLock wakeLock = acquireWakeLock(context, "CoreService execute",
|
final TracingWakeLock wakeLock = acquireWakeLock(context, "CoreService execute",
|
||||||
wakeLockTime);
|
wakeLockTime);
|
||||||
|
|
||||||
// Wrap the supplied runner with code to release the wake lock and stop the service if
|
// Wrap the supplied runner with code to release the wake lock and stop the service if
|
||||||
// appropriate.
|
// appropriate.
|
||||||
@ -309,7 +313,7 @@ public abstract class CoreService extends Service {
|
|||||||
|
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "CoreService (" + className + ") running Runnable " +
|
Log.d(K9.LOG_TAG, "CoreService (" + className + ") running Runnable " +
|
||||||
runner.hashCode() + " with startId " + startId);
|
runner.hashCode() + " with startId " + startId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the supplied code
|
// Run the supplied code
|
||||||
@ -325,7 +329,7 @@ public abstract class CoreService extends Service {
|
|||||||
try {
|
try {
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "CoreService (" + className + ") completed " +
|
Log.d(K9.LOG_TAG, "CoreService (" + className + ") completed " +
|
||||||
"Runnable " + runner.hashCode() + " with startId " + startId);
|
"Runnable " + runner.hashCode() + " with startId " + startId);
|
||||||
}
|
}
|
||||||
wakeLock.release();
|
wakeLock.release();
|
||||||
} finally {
|
} finally {
|
||||||
@ -340,8 +344,8 @@ public abstract class CoreService extends Service {
|
|||||||
// TODO: remove this. we never set mThreadPool to null
|
// TODO: remove this. we never set mThreadPool to null
|
||||||
if (mThreadPool == null) {
|
if (mThreadPool == null) {
|
||||||
Log.e(K9.LOG_TAG, "CoreService.execute (" + className + ") called with no thread " +
|
Log.e(K9.LOG_TAG, "CoreService.execute (" + className + ") called with no thread " +
|
||||||
"pool available; running Runnable " + runner.hashCode() +
|
"pool available; running Runnable " + runner.hashCode() +
|
||||||
" in calling thread");
|
" in calling thread");
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
myRunner.run();
|
myRunner.run();
|
||||||
@ -350,7 +354,7 @@ public abstract class CoreService extends Service {
|
|||||||
} else {
|
} else {
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.d(K9.LOG_TAG, "CoreService (" + className + ") queueing Runnable " +
|
Log.d(K9.LOG_TAG, "CoreService (" + className + ") queueing Runnable " +
|
||||||
runner.hashCode() + " with startId " + startId);
|
runner.hashCode() + " with startId " + startId);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -364,7 +368,7 @@ public abstract class CoreService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Log.i(K9.LOG_TAG, "CoreService: " + className + " is shutting down, ignoring " +
|
Log.i(K9.LOG_TAG, "CoreService: " + className + " is shutting down, ignoring " +
|
||||||
"rejected execution exception: " + e.getMessage());
|
"rejected execution exception: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ public class MailService extends CoreService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void rescheduleAllInBackground(final boolean hasConnectivity,
|
private void rescheduleAllInBackground(final boolean hasConnectivity,
|
||||||
final boolean doBackground, Integer startId) {
|
final boolean doBackground, Integer startId) {
|
||||||
|
|
||||||
execute(getApplication(), new Runnable() {
|
execute(getApplication(), new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@ -211,7 +211,7 @@ public class MailService extends CoreService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void reschedulePollInBackground(final boolean hasConnectivity,
|
private void reschedulePollInBackground(final boolean hasConnectivity,
|
||||||
final boolean doBackground, Integer startId, final boolean considerLastCheckEnd) {
|
final boolean doBackground, Integer startId, final boolean considerLastCheckEnd) {
|
||||||
|
|
||||||
execute(getApplication(), new Runnable() {
|
execute(getApplication(), new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -231,7 +231,7 @@ public class MailService extends CoreService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void refreshPushersInBackground(boolean hasConnectivity, boolean doBackground,
|
private void refreshPushersInBackground(boolean hasConnectivity, boolean doBackground,
|
||||||
Integer startId) {
|
Integer startId) {
|
||||||
|
|
||||||
if (hasConnectivity && doBackground) {
|
if (hasConnectivity && doBackground) {
|
||||||
execute(getApplication(), new Runnable() {
|
execute(getApplication(), new Runnable() {
|
||||||
@ -244,12 +244,12 @@ public class MailService extends CoreService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void reschedulePoll(final boolean hasConnectivity, final boolean doBackground,
|
private void reschedulePoll(final boolean hasConnectivity, final boolean doBackground,
|
||||||
boolean considerLastCheckEnd) {
|
boolean considerLastCheckEnd) {
|
||||||
|
|
||||||
if (!(hasConnectivity && doBackground)) {
|
if (!(hasConnectivity && doBackground)) {
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.i(K9.LOG_TAG, "No connectivity, canceling check for " +
|
Log.i(K9.LOG_TAG, "No connectivity, canceling check for " +
|
||||||
getApplication().getPackageName());
|
getApplication().getPackageName());
|
||||||
}
|
}
|
||||||
|
|
||||||
nextCheck = -1;
|
nextCheck = -1;
|
||||||
@ -265,8 +265,8 @@ public class MailService extends CoreService {
|
|||||||
|
|
||||||
if (lastCheckEnd > System.currentTimeMillis()) {
|
if (lastCheckEnd > System.currentTimeMillis()) {
|
||||||
Log.i(K9.LOG_TAG, "The database claims that the last time mail was checked was in " +
|
Log.i(K9.LOG_TAG, "The database claims that the last time mail was checked was in " +
|
||||||
"the future (" + lastCheckEnd + "). To try to get things back to normal, " +
|
"the future (" + lastCheckEnd + "). To try to get things back to normal, " +
|
||||||
"the last check time has been reset to: " + System.currentTimeMillis());
|
"the last check time has been reset to: " + System.currentTimeMillis());
|
||||||
lastCheckEnd = System.currentTimeMillis();
|
lastCheckEnd = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,7 +275,7 @@ public class MailService extends CoreService {
|
|||||||
if (account.getAutomaticCheckIntervalMinutes() != -1 &&
|
if (account.getAutomaticCheckIntervalMinutes() != -1 &&
|
||||||
account.getFolderSyncMode() != FolderMode.NONE &&
|
account.getFolderSyncMode() != FolderMode.NONE &&
|
||||||
(account.getAutomaticCheckIntervalMinutes() < shortestInterval ||
|
(account.getAutomaticCheckIntervalMinutes() < shortestInterval ||
|
||||||
shortestInterval == -1)) {
|
shortestInterval == -1)) {
|
||||||
shortestInterval = account.getAutomaticCheckIntervalMinutes();
|
shortestInterval = account.getAutomaticCheckIntervalMinutes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -286,7 +286,7 @@ public class MailService extends CoreService {
|
|||||||
if (shortestInterval == -1) {
|
if (shortestInterval == -1) {
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.i(K9.LOG_TAG, "No next check scheduled for package " +
|
Log.i(K9.LOG_TAG, "No next check scheduled for package " +
|
||||||
getApplication().getPackageName());
|
getApplication().getPackageName());
|
||||||
}
|
}
|
||||||
|
|
||||||
nextCheck = -1;
|
nextCheck = -1;
|
||||||
@ -295,7 +295,7 @@ public class MailService extends CoreService {
|
|||||||
} else {
|
} else {
|
||||||
long delay = (shortestInterval * (60 * 1000));
|
long delay = (shortestInterval * (60 * 1000));
|
||||||
long base = (previousInterval == -1 || lastCheckEnd == -1 ||
|
long base = (previousInterval == -1 || lastCheckEnd == -1 ||
|
||||||
!considerLastCheckEnd ? System.currentTimeMillis() : lastCheckEnd);
|
!considerLastCheckEnd ? System.currentTimeMillis() : lastCheckEnd);
|
||||||
long nextTime = base + delay;
|
long nextTime = base + delay;
|
||||||
|
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
@ -311,8 +311,8 @@ public class MailService extends CoreService {
|
|||||||
try {
|
try {
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.i(K9.LOG_TAG, "Next check for package " +
|
Log.i(K9.LOG_TAG, "Next check for package " +
|
||||||
getApplication().getPackageName() + " scheduled for " +
|
getApplication().getPackageName() + " scheduled for " +
|
||||||
new Date(nextTime));
|
new Date(nextTime));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// I once got a NullPointerException deep in new Date();
|
// I once got a NullPointerException deep in new Date();
|
||||||
@ -345,7 +345,7 @@ public class MailService extends CoreService {
|
|||||||
if (!(hasConnectivity && doBackground)) {
|
if (!(hasConnectivity && doBackground)) {
|
||||||
if (K9.DEBUG) {
|
if (K9.DEBUG) {
|
||||||
Log.i(K9.LOG_TAG, "Not scheduling pushers: connectivity? " + hasConnectivity +
|
Log.i(K9.LOG_TAG, "Not scheduling pushers: connectivity? " + hasConnectivity +
|
||||||
" -- doBackground? " + doBackground);
|
" -- doBackground? " + doBackground);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -115,14 +115,13 @@ public class SleepService extends CoreService {
|
|||||||
@Override
|
@Override
|
||||||
public int startService(Intent intent, int startId) {
|
public int startService(Intent intent, int startId) {
|
||||||
try {
|
try {
|
||||||
if (intent.getAction().startsWith(ALARM_FIRED)) {
|
if (intent.getAction().startsWith(ALARM_FIRED)) {
|
||||||
Integer id = intent.getIntExtra(LATCH_ID, -1);
|
Integer id = intent.getIntExtra(LATCH_ID, -1);
|
||||||
endSleep(id);
|
endSleep(id);
|
||||||
}
|
}
|
||||||
return START_NOT_STICKY;
|
return START_NOT_STICKY;
|
||||||
}
|
} finally {
|
||||||
finally {
|
stopSelf(startId);
|
||||||
stopSelf(startId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,12 +319,12 @@ public class SingleMessageView extends LinearLayout {
|
|||||||
* @param listeners Set of listeners.
|
* @param listeners Set of listeners.
|
||||||
*/
|
*/
|
||||||
public void setListeners(final Set<MessagingListener> listeners) {
|
public void setListeners(final Set<MessagingListener> listeners) {
|
||||||
if(!mScreenReaderEnabled) {
|
if (!mScreenReaderEnabled) {
|
||||||
if(mMessageContentView != null) {
|
if (mMessageContentView != null) {
|
||||||
mMessageContentView.setListeners(listeners);
|
mMessageContentView.setListeners(listeners);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(mAccessibleMessageContentView != null) {
|
if (mAccessibleMessageContentView != null) {
|
||||||
mAccessibleMessageContentView.setListeners(listeners);
|
mAccessibleMessageContentView.setListeners(listeners);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ public class ToggleScrollView extends ScrollView {
|
|||||||
// We save only the Y coordinate instead of the percentage because I don't know how expensive the
|
// We save only the Y coordinate instead of the percentage because I don't know how expensive the
|
||||||
// computeVerticalScrollRange() call is.
|
// computeVerticalScrollRange() call is.
|
||||||
final int scrollRange = computeVerticalScrollRange();
|
final int scrollRange = computeVerticalScrollRange();
|
||||||
if(scrollRange == 0) {
|
if (scrollRange == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return (double) mCurrentYPosition / scrollRange;
|
return (double) mCurrentYPosition / scrollRange;
|
||||||
@ -119,11 +119,11 @@ public class ToggleScrollView extends ScrollView {
|
|||||||
class ScrollToLastLocationListener extends MessagingListener {
|
class ScrollToLastLocationListener extends MessagingListener {
|
||||||
public void messageViewFinished() {
|
public void messageViewFinished() {
|
||||||
// Don't scroll if our last position was at the top.
|
// Don't scroll if our last position was at the top.
|
||||||
if(mScrollPercentage != 0.0) {
|
if (mScrollPercentage != 0.0) {
|
||||||
final int scrollRange = computeVerticalScrollRange();
|
final int scrollRange = computeVerticalScrollRange();
|
||||||
final int newY = (int)(mScrollPercentage * scrollRange);
|
final int newY = (int)(mScrollPercentage * scrollRange);
|
||||||
Log.d(K9.LOG_TAG, "ToggleScrollView: requested " + (100 * mScrollPercentage) + "%, " +
|
Log.d(K9.LOG_TAG, "ToggleScrollView: requested " + (100 * mScrollPercentage) + "%, " +
|
||||||
"scrolling to " + newY + "/" + scrollRange);
|
"scrolling to " + newY + "/" + scrollRange);
|
||||||
scrollTo(0, newY);
|
scrollTo(0, newY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,7 +134,7 @@ public class ToggleScrollView extends ScrollView {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public MessagingListener getListener() {
|
public MessagingListener getListener() {
|
||||||
if(this.mListener != null) {
|
if (this.mListener != null) {
|
||||||
return this.mListener;
|
return this.mListener;
|
||||||
} else {
|
} else {
|
||||||
return this.mListener = new ScrollToLastLocationListener();
|
return this.mListener = new ScrollToLastLocationListener();
|
||||||
|
Loading…
Reference in New Issue
Block a user