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,6 +413,7 @@ 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", "");
|
||||||
@ -487,6 +490,7 @@ public class Account implements BaseAccount {
|
|||||||
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 + ".cryptoAutoEncrypt");
|
||||||
editor.remove(mUuid + ".enabled");
|
editor.remove(mUuid + ".enabled");
|
||||||
editor.remove(mUuid + ".syncKey");
|
editor.remove(mUuid + ".syncKey");
|
||||||
editor.remove(mUuid + ".securityKey");
|
editor.remove(mUuid + ".securityKey");
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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) {
|
||||||
@ -1507,7 +1506,7 @@ public class Accounts extends K9ListActivity implements OnItemClickListener, OnC
|
|||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1853,7 +1852,9 @@ 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 import", e);
|
Log.w(K9.LOG_TAG, "Exception during import", e);
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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),
|
|
||||||
getAddresses(mBccView)
|
|
||||||
};
|
|
||||||
for (Address[] addressArray : addresses) {
|
|
||||||
for (Address address : addressArray) {
|
|
||||||
if (emails.length() != 0) {
|
if (emails.length() != 0) {
|
||||||
emails.append(',');
|
emails.append(',');
|
||||||
}
|
}
|
||||||
emails.append(address.getAddress());
|
emails.append(address.getAddress());
|
||||||
|
if (!mContinueWithoutPublicKey &&
|
||||||
|
!crypto.hasPublicKeyForEmail(this, address.getAddress())) {
|
||||||
|
showDialog(DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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:
|
||||||
|
if (mEncryptCheckbox.isChecked()) {
|
||||||
|
showDialog(DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED);
|
||||||
|
} else {
|
||||||
onSave();
|
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);
|
||||||
}
|
}
|
||||||
@ -2390,10 +2481,10 @@ 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()) {
|
||||||
@ -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;
|
||||||
@ -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
|
|
||||||
if ((getChangingConfigurations() & ActivityInfo.CONFIG_ORIENTATION) == 0) {
|
|
||||||
mHandler.sendEmptyMessage(MSG_SAVED_DRAFT);
|
mHandler.sendEmptyMessage(MSG_SAVED_DRAFT);
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
@ -540,8 +542,8 @@ public class AccountSettings extends K9PreferenceActivity {
|
|||||||
});
|
});
|
||||||
} 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,
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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,34 +26,44 @@ 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) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int d = mIn.read(b, offset, Math.min(mLength - mCount, length));
|
int d = mIn.read(b, offset, Math.min(mLength - mCount, length));
|
||||||
if (d == -1) {
|
if (d != -1) {
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
mCount += d;
|
mCount += d;
|
||||||
|
}
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(byte[] b) throws IOException {
|
public int read(byte[] b) throws IOException {
|
||||||
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) {
|
||||||
|
@ -89,15 +89,15 @@ public class EasStore extends Store {
|
|||||||
// Command timeout is the the time allowed for reading data from an open connection before an
|
// Command timeout is the the time allowed for reading data from an open connection before an
|
||||||
// IOException is thrown. After a small added allowance, our watchdog alarm goes off (allowing
|
// IOException is thrown. After a small added allowance, our watchdog alarm goes off (allowing
|
||||||
// us to detect a silently dropped connection). The allowance is defined below.
|
// us to detect a silently dropped connection). The allowance is defined below.
|
||||||
static private final int COMMAND_TIMEOUT = 30*1000;
|
static private final int COMMAND_TIMEOUT = 30 * 1000;
|
||||||
// Connection timeout is the time given to connect to the server before reporting an IOException
|
// Connection timeout is the time given to connect to the server before reporting an IOException
|
||||||
static private final int CONNECTION_TIMEOUT = 20*1000;
|
static private final int CONNECTION_TIMEOUT = 20 * 1000;
|
||||||
|
|
||||||
// This needs to be long enough to send the longest reasonable message, without being so long
|
// This needs to be long enough to send the longest reasonable message, without being so long
|
||||||
// as to effectively "hang" sending of mail. The standard 30 second timeout isn't long enough
|
// as to effectively "hang" sending of mail. The standard 30 second timeout isn't long enough
|
||||||
// for pictures and the like. For now, we'll use 15 minutes, in the knowledge that any socket
|
// for pictures and the like. For now, we'll use 15 minutes, in the knowledge that any socket
|
||||||
// failure would probably generate an Exception before timing out anyway
|
// failure would probably generate an Exception before timing out anyway
|
||||||
public static final int SEND_MAIL_TIMEOUT = 15*60*1000;
|
public static final int SEND_MAIL_TIMEOUT = 15 * 60 * 1000;
|
||||||
|
|
||||||
// MSFT's custom HTTP result code indicating the need to provision
|
// MSFT's custom HTTP result code indicating the need to provision
|
||||||
static private final int HTTP_NEED_PROVISIONING = 449;
|
static private final int HTTP_NEED_PROVISIONING = 449;
|
||||||
@ -592,7 +592,7 @@ public class EasStore extends Store {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List <? extends Folder> getPersonalNamespaces(boolean forceListAll) throws MessagingException {
|
public List <? extends Folder > getPersonalNamespaces(boolean forceListAll) throws MessagingException {
|
||||||
if (forceListAll || getStoreSyncKey().equals(INITIAL_SYNC_KEY)) {
|
if (forceListAll || getStoreSyncKey().equals(INITIAL_SYNC_KEY)) {
|
||||||
if (forceListAll) {
|
if (forceListAll) {
|
||||||
// Reset the sync key so the Exchange server will return the entire folder list
|
// Reset the sync key so the Exchange server will return the entire folder list
|
||||||
@ -737,7 +737,7 @@ public class EasStore extends Store {
|
|||||||
try {
|
try {
|
||||||
LocalStore localStore = mAccount.getLocalStore();
|
LocalStore localStore = mAccount.getLocalStore();
|
||||||
if (localStore != null) {
|
if (localStore != null) {
|
||||||
List<? extends Folder> localFolders = localStore.getPersonalNamespaces(false);
|
List <? extends Folder > localFolders = localStore.getPersonalNamespaces(false);
|
||||||
synchronized (mFolderList) {
|
synchronized (mFolderList) {
|
||||||
for (Folder folder : localFolders) {
|
for (Folder folder : localFolders) {
|
||||||
int type = FolderSyncParser.USER_FOLDER_TYPE;
|
int type = FolderSyncParser.USER_FOLDER_TYPE;
|
||||||
@ -767,8 +767,7 @@ public class EasStore extends Store {
|
|||||||
if (getStoreSyncKey().equals(INITIAL_SYNC_KEY)) {
|
if (getStoreSyncKey().equals(INITIAL_SYNC_KEY)) {
|
||||||
try {
|
try {
|
||||||
getInitialFolderList();
|
getInitialFolderList();
|
||||||
}
|
} catch (MessagingException e) {
|
||||||
catch (MessagingException e) {
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1289,7 +1288,7 @@ public class EasStore extends Store {
|
|||||||
}
|
}
|
||||||
s.end();
|
s.end();
|
||||||
}
|
}
|
||||||
}.send(this);
|
} .send(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteServerMessages(final String[] uids) throws MessagingException {
|
private void deleteServerMessages(final String[] uids) throws MessagingException {
|
||||||
@ -1306,7 +1305,7 @@ public class EasStore extends Store {
|
|||||||
}
|
}
|
||||||
s.end();
|
s.end();
|
||||||
}
|
}
|
||||||
}.send(this);
|
} .send(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1586,7 +1585,7 @@ public class EasStore extends Store {
|
|||||||
.start(Tags.SYNC_COLLECTION)
|
.start(Tags.SYNC_COLLECTION)
|
||||||
.data(Tags.SYNC_CLASS, className)
|
.data(Tags.SYNC_CLASS, className)
|
||||||
.data(Tags.SYNC_SYNC_KEY, syncKey)
|
.data(Tags.SYNC_SYNC_KEY, syncKey)
|
||||||
.data(Tags.SYNC_COLLECTION_ID, folderServerId );
|
.data(Tags.SYNC_COLLECTION_ID, folderServerId);
|
||||||
|
|
||||||
prepareCommand(s);
|
prepareCommand(s);
|
||||||
|
|
||||||
|
@ -244,8 +244,7 @@ public class ImapStore extends Store {
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,9 +279,9 @@ public class ImapStore extends Store {
|
|||||||
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);
|
||||||
@ -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)";
|
||||||
|
@ -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.");
|
||||||
@ -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++;
|
||||||
@ -156,8 +156,7 @@ public class Pop3Store extends Store {
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,8 +206,7 @@ public class WebDavStore extends Store {
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,9 +241,9 @@ 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 {
|
||||||
@ -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) {
|
||||||
|
@ -45,7 +45,7 @@ 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) {
|
||||||
|
@ -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
|
||||||
|
@ -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")) {
|
||||||
@ -368,11 +368,16 @@ public class ProvisionParser extends Parser {
|
|||||||
// 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;
|
||||||
|
@ -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",
|
||||||
|
@ -139,8 +139,7 @@ public class SmtpTransport extends Transport {
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ public class AccountSettings {
|
|||||||
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,
|
||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -81,8 +81,7 @@ public class SettingsExporter {
|
|||||||
|
|
||||||
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();
|
||||||
@ -114,7 +113,7 @@ public class SettingsExporter {
|
|||||||
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);
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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>();
|
||||||
@ -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 {
|
||||||
@ -683,7 +682,7 @@ public class SettingsImporter {
|
|||||||
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) {
|
||||||
@ -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) {
|
||||||
@ -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) {
|
||||||
|
@ -126,7 +126,7 @@ public abstract class CoreService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (createIfNotExists) {
|
if (createIfNotExists) {
|
||||||
addWakeLock(context,intent);
|
addWakeLock(context, intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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;
|
||||||
|
@ -120,8 +120,7 @@ public class SleepService extends CoreService {
|
|||||||
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,7 +119,7 @@ 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) + "%, " +
|
||||||
@ -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