Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 59dcdf6b authored by cketti's avatar cketti Committed by GitHub
Browse files

Merge pull request #1766 from k9mail/expert-signatures

Turn support for signed-only mails into an opt-in feature
parents d0b3caf9 58eb9b52
Loading
Loading
Loading
Loading
+48 −52
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@ public class Account implements BaseAccount, StoreConfig {
    /**
     * Default value for the inbox folder (never changes for POP3 and IMAP)
     */
    public static final String INBOX = "INBOX";
    private static final String INBOX = "INBOX";

    /**
     * This local folder is used to store messages to be sent.
@@ -119,7 +119,7 @@ public class Account implements BaseAccount, StoreConfig {
     * http://developer.android.com/design/style/color.html
     * Note: Order does matter, it's the order in which they will be picked.
     */
    public static final Integer[] PREDEFINED_COLORS = new Integer[] {
    private static final Integer[] PREDEFINED_COLORS = new Integer[] {
            Color.parseColor("#0099CC"),    // blue
            Color.parseColor("#669900"),    // green
            Color.parseColor("#FF8800"),    // orange
@@ -176,7 +176,6 @@ public class Account implements BaseAccount, StoreConfig {
    private int mAutomaticCheckIntervalMinutes;
    private int mDisplayCount;
    private int mChipColor;
    private long mLastAutomaticCheckTime;
    private long mLatestOldMessageSeenTime;
    private boolean mNotifyNewMail;
    private FolderMode mFolderNotifyNewMailMode;
@@ -197,14 +196,14 @@ public class Account implements BaseAccount, StoreConfig {
    private boolean mPushPollOnConnect;
    private boolean mNotifySync;
    private SortType mSortType;
    private Map<SortType, Boolean> mSortAscending = new HashMap<SortType, Boolean>();
    private Map<SortType, Boolean> mSortAscending = new HashMap<>();
    private ShowPictures mShowPictures;
    private boolean mIsSignatureBeforeQuotedText;
    private Expunge mExpungePolicy = Expunge.EXPUNGE_IMMEDIATELY;
    private int mMaxPushFolders;
    private int mIdleRefreshMinutes;
    private boolean goToUnreadMessageSearch;
    private final Map<NetworkType, Boolean> compressionMap = new ConcurrentHashMap<NetworkType, Boolean>();
    private final Map<NetworkType, Boolean> compressionMap = new ConcurrentHashMap<>();
    private Searchable searchableFolders;
    private boolean subscribedFoldersOnly;
    private int maximumPolledMessageAge;
@@ -223,6 +222,7 @@ public class Account implements BaseAccount, StoreConfig {
    private boolean mSyncRemoteDeletions;
    private String mCryptoApp;
    private long mCryptoKey;
    private boolean mCryptoSupportSignOnly;
    private boolean mMarkMessageAsReadOnView;
    private boolean mAlwaysShowCcBcc;
    private boolean mAllowRemoteSearch;
@@ -319,6 +319,7 @@ public class Account implements BaseAccount, StoreConfig {
        mSyncRemoteDeletions = true;
        mCryptoApp = NO_OPENPGP_PROVIDER;
        mCryptoKey = NO_OPENPGP_KEY;
        mCryptoSupportSignOnly = false;
        mAllowRemoteSearch = false;
        mRemoteSearchFullText = false;
        mRemoteSearchNumResults = DEFAULT_REMOTE_SEARCH_NUM_RESULTS;
@@ -328,7 +329,7 @@ public class Account implements BaseAccount, StoreConfig {

        searchableFolders = Searchable.ALL;

        identities = new ArrayList<Identity>();
        identities = new ArrayList<>();

        Identity identity = new Identity();
        identity.setSignatureUse(true);
@@ -353,7 +354,7 @@ public class Account implements BaseAccount, StoreConfig {
    private int pickColor(Context context) {
        List<Account> accounts = Preferences.getPreferences(context).getAccounts();

        List<Integer> availableColors = new ArrayList<Integer>(PREDEFINED_COLORS.length);
        List<Integer> availableColors = new ArrayList<>(PREDEFINED_COLORS.length);
        Collections.addAll(availableColors, PREDEFINED_COLORS);

        for (Account account : accounts) {
@@ -393,7 +394,6 @@ public class Account implements BaseAccount, StoreConfig {
        if (mDisplayCount < 0) {
            mDisplayCount = K9.DEFAULT_VISIBLE_LIMIT;
        }
        mLastAutomaticCheckTime = storage.getLong(mUuid + ".lastAutomaticCheckTime", 0);
        mLatestOldMessageSeenTime = storage.getLong(mUuid + ".latestOldMessageSeenTime", 0);
        mNotifyNewMail = storage.getBoolean(mUuid + ".notifyNewMail", false);

@@ -470,6 +470,7 @@ public class Account implements BaseAccount, StoreConfig {
        String cryptoApp = storage.getString(mUuid + ".cryptoApp", NO_OPENPGP_PROVIDER);
        setCryptoApp(cryptoApp);
        mCryptoKey = storage.getLong(mUuid + ".cryptoKey", NO_OPENPGP_KEY);
        mCryptoSupportSignOnly = storage.getBoolean(mUuid + ".cryptoSupportSignOnly", false);
        mAllowRemoteSearch = storage.getBoolean(mUuid + ".allowRemoteSearch", false);
        mRemoteSearchFullText = storage.getBoolean(mUuid + ".remoteSearchFullText", false);
        mRemoteSearchNumResults = storage.getInt(mUuid + ".remoteSearchNumResults", DEFAULT_REMOTE_SEARCH_NUM_RESULTS);
@@ -487,11 +488,13 @@ public class Account implements BaseAccount, StoreConfig {
    }

    protected synchronized void delete(Preferences preferences) {
        deleteCertificates();

        // Get the list of account UUIDs
        String[] uuids = preferences.getStorage().getString("accountUuids", "").split(",");

        // Create a list of all account UUIDs excluding this account
        List<String> newUuids = new ArrayList<String>(uuids.length);
        List<String> newUuids = new ArrayList<>(uuids.length);
        for (String uuid : uuids) {
            if (!uuid.equals(mUuid)) {
                newUuids.add(uuid);
@@ -559,6 +562,9 @@ public class Account implements BaseAccount, StoreConfig {
        editor.remove(mUuid + ".cryptoApp");
        editor.remove(mUuid + ".cryptoAutoSignature");
        editor.remove(mUuid + ".cryptoAutoEncrypt");
        editor.remove(mUuid + ".cryptoApp");
        editor.remove(mUuid + ".cryptoKey");
        editor.remove(mUuid + ".cryptoSupportSignOnly");
        editor.remove(mUuid + ".enabled");
        editor.remove(mUuid + ".markMessageAsReadOnView");
        editor.remove(mUuid + ".alwaysShowCcBcc");
@@ -581,7 +587,7 @@ public class Account implements BaseAccount, StoreConfig {
        editor.commit();
    }

    public static int findNewAccountNumber(List<Integer> accountNumbers) {
    private static int findNewAccountNumber(List<Integer> accountNumbers) {
        int newAccountNumber = -1;
        Collections.sort(accountNumbers);
        for (int accountNumber : accountNumbers) {
@@ -594,9 +600,9 @@ public class Account implements BaseAccount, StoreConfig {
        return newAccountNumber;
    }

    public static List<Integer> getExistingAccountNumbers(Preferences preferences) {
    private static List<Integer> getExistingAccountNumbers(Preferences preferences) {
        List<Account> accounts = preferences.getAccounts();
        List<Integer> accountNumbers = new ArrayList<Integer>(accounts.size());
        List<Integer> accountNumbers = new ArrayList<>(accounts.size());
        for (Account a : accounts) {
            accountNumbers.add(a.getAccountNumber());
        }
@@ -682,7 +688,6 @@ public class Account implements BaseAccount, StoreConfig {
        editor.putInt(mUuid + ".idleRefreshMinutes", mIdleRefreshMinutes);
        editor.putBoolean(mUuid + ".pushPollOnConnect", mPushPollOnConnect);
        editor.putInt(mUuid + ".displayCount", mDisplayCount);
        editor.putLong(mUuid + ".lastAutomaticCheckTime", mLastAutomaticCheckTime);
        editor.putLong(mUuid + ".latestOldMessageSeenTime", mLatestOldMessageSeenTime);
        editor.putBoolean(mUuid + ".notifyNewMail", mNotifyNewMail);
        editor.putString(mUuid + ".folderNotifyNewMailMode", mFolderNotifyNewMailMode.name());
@@ -733,6 +738,7 @@ public class Account implements BaseAccount, StoreConfig {
        editor.putBoolean(mUuid + ".stripSignature", mStripSignature);
        editor.putString(mUuid + ".cryptoApp", mCryptoApp);
        editor.putLong(mUuid + ".cryptoKey", mCryptoKey);
        editor.putBoolean(mUuid + ".cryptoSupportSignOnly", mCryptoSupportSignOnly);
        editor.putBoolean(mUuid + ".allowRemoteSearch", mAllowRemoteSearch);
        editor.putBoolean(mUuid + ".remoteSearchFullText", mRemoteSearchFullText);
        editor.putInt(mUuid + ".remoteSearchNumResults", mRemoteSearchNumResults);
@@ -760,7 +766,7 @@ public class Account implements BaseAccount, StoreConfig {

    }

    public void resetVisibleLimits() {
    private void resetVisibleLimits() {
        try {
            getLocalStore().resetVisibleLimits(getDisplayCount());
        } catch (MessagingException e) {
@@ -770,7 +776,6 @@ public class Account implements BaseAccount, StoreConfig {
    }

    /**
     * @param context
     * @return <code>null</code> if not available
     * @throws MessagingException
     * @see {@link #isAvailable(Context)}
@@ -800,7 +805,7 @@ public class Account implements BaseAccount, StoreConfig {

        // Use the LocalSearch instance to create a WHERE clause to query the content provider
        StringBuilder query = new StringBuilder();
        List<String> queryArgs = new ArrayList<String>();
        List<String> queryArgs = new ArrayList<>();
        ConditionsTreeNode conditions = search.getConditions();
        SqlQueryBuilder.buildWhereClause(this, conditions, query, queryArgs);

@@ -809,12 +814,12 @@ public class Account implements BaseAccount, StoreConfig {

        Cursor cursor = cr.query(uri, projection, selection, selectionArgs, null);
        try {
            if (cursor.moveToFirst()) {
            if (cursor != null && cursor.moveToFirst()) {
                stats.unreadMessageCount = cursor.getInt(0);
                stats.flaggedMessageCount = cursor.getInt(1);
            }
        } finally {
            cursor.close();
            Utility.closeQuietly(cursor);
        }

        LocalStore localStore = getLocalStore();
@@ -831,7 +836,7 @@ public class Account implements BaseAccount, StoreConfig {
        cacheChips();
    }

    public synchronized void cacheChips() {
    private synchronized void cacheChips() {
        mReadColorChip = new ColorChip(mChipColor, true, ColorChip.CIRCULAR);
        mUnreadColorChip = new ColorChip(mChipColor, false, ColorChip.CIRCULAR);
        mFlaggedReadColorChip = new ColorChip(mChipColor, true, ColorChip.STAR);
@@ -843,8 +848,7 @@ public class Account implements BaseAccount, StoreConfig {
    }


    public ColorChip generateColorChip(boolean messageRead, boolean toMe, boolean ccMe,
            boolean fromMe, boolean messageFlagged) {
    public ColorChip generateColorChip(boolean messageRead, boolean messageFlagged) {
        ColorChip chip;

        if (messageRead) {
@@ -869,10 +873,6 @@ public class Account implements BaseAccount, StoreConfig {
        return mUuid;
    }

    public Uri getContentUri() {
        return Uri.parse("content://accounts/" + getUuid());
    }

    public synchronized String getStoreUri() {
        return mStoreUri;
    }
@@ -965,12 +965,12 @@ public class Account implements BaseAccount, StoreConfig {
            } catch (MessagingException e) {
                Log.e(K9.LOG_TAG, "Switching local storage provider from " +
                      mLocalStorageProviderId + " to " + id + " failed.", e);
            } finally {
            }

            // if migration to/from SD-card failed once, it will fail again.
            if (!successful) {
                return;
            }
            }

            mLocalStorageProviderId = id;
        }
@@ -1007,14 +1007,6 @@ public class Account implements BaseAccount, StoreConfig {
        resetVisibleLimits();
    }

    public synchronized long getLastAutomaticCheckTime() {
        return mLastAutomaticCheckTime;
    }

    public synchronized void setLastAutomaticCheckTime(long lastAutomaticCheckTime) {
        this.mLastAutomaticCheckTime = lastAutomaticCheckTime;
    }

    public synchronized long getLatestOldMessageSeenTime() {
        return mLatestOldMessageSeenTime;
    }
@@ -1330,9 +1322,9 @@ public class Account implements BaseAccount, StoreConfig {
    }

    private synchronized List<Identity> loadIdentities(Storage storage) {
        List<Identity> newIdentities = new ArrayList<Identity>();
        List<Identity> newIdentities = new ArrayList<>();
        int ident = 0;
        boolean gotOne = false;
        boolean gotOne;
        do {
            gotOne = false;
            String name = storage.getString(mUuid + "." + IDENTITY_NAME_KEY + "." + ident, null);
@@ -1374,7 +1366,7 @@ public class Account implements BaseAccount, StoreConfig {

    private synchronized void deleteIdentities(Storage storage, StorageEditor editor) {
        int ident = 0;
        boolean gotOne = false;
        boolean gotOne;
        do {
            gotOne = false;
            String email = storage.getString(mUuid + "." + IDENTITY_EMAIL_KEY + "." + ident, null);
@@ -1411,7 +1403,7 @@ public class Account implements BaseAccount, StoreConfig {
    }

    public synchronized void setIdentities(List<Identity> newIdentities) {
        identities = new ArrayList<Identity>(newIdentities);
        identities = new ArrayList<>(newIdentities);
    }

    public synchronized Identity getIdentity(int i) {
@@ -1482,7 +1474,7 @@ public class Account implements BaseAccount, StoreConfig {
     *            Never <code>null</code>.
     * @throws MessagingException
     */
    public void switchLocalStorage(final String newStorageProviderId) throws MessagingException {
    private void switchLocalStorage(final String newStorageProviderId) throws MessagingException {
        if (!mLocalStorageProviderId.equals(newStorageProviderId)) {
            getLocalStore().switchLocalStorage(newStorageProviderId);
        }
@@ -1630,6 +1622,14 @@ public class Account implements BaseAccount, StoreConfig {
        mCryptoKey = keyId;
    }

    public boolean getCryptoSupportSignOnly() {
        return mCryptoSupportSignOnly;
    }

    public void setCryptoSupportSignOnly(boolean cryptoSupportSignOnly) {
        mCryptoSupportSignOnly = cryptoSupportSignOnly;
    }

    public boolean allowRemoteSearch() {
        return mAllowRemoteSearch;
    }
@@ -1691,10 +1691,8 @@ public class Account implements BaseAccount, StoreConfig {
     */
    public boolean isAvailable(Context context) {
        String localStorageProviderId = getLocalStorageProviderId();
        if (localStorageProviderId == null) {
            return true; // defaults to internal memory
        }
        return StorageManager.getInstance(context).isReady(localStorageProviderId);
        boolean storageProviderIsInternalMemory = localStorageProviderId == null;
        return storageProviderIsInternalMemory || StorageManager.getInstance(context).isReady(localStorageProviderId);
    }

    public synchronized boolean isEnabled() {
@@ -1843,8 +1841,7 @@ public class Account implements BaseAccount, StoreConfig {
    /**
     * Add a new certificate for the incoming or outgoing server to the local key store.
     */
    public void addCertificate(CheckDirection direction,
            X509Certificate certificate) throws CertificateException {
    public void addCertificate(CheckDirection direction, X509Certificate certificate) throws CertificateException {
        Uri uri;
        if (direction == CheckDirection.INCOMING) {
            uri = Uri.parse(getStoreUri());
@@ -1860,8 +1857,7 @@ public class Account implements BaseAccount, StoreConfig {
     * new host/port, then try and delete any (possibly non-existent) certificate stored for the
     * old host/port.
     */
    public void deleteCertificate(String newHost, int newPort,
            CheckDirection direction) {
    public void deleteCertificate(String newHost, int newPort, CheckDirection direction) {
        Uri uri;
        if (direction == CheckDirection.INCOMING) {
            uri = Uri.parse(getStoreUri());
@@ -1884,7 +1880,7 @@ public class Account implements BaseAccount, StoreConfig {
     * Examine the settings for the account and attempt to delete (possibly non-existent)
     * certificates for the incoming and outgoing servers.
     */
    public void deleteCertificates() {
    private void deleteCertificates() {
        LocalKeyStore localKeyStore = LocalKeyStore.getInstance();

        String storeUri = getStoreUri();
+0 −1
Original line number Diff line number Diff line
@@ -132,7 +132,6 @@ public class Preferences {
        }
        LocalStore.removeAccount(account);

        account.deleteCertificates();
        account.delete(this);

        if (newAccount == account) {
+2 −2
Original line number Diff line number Diff line
@@ -1795,8 +1795,8 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {

                holder.chip.setBackgroundColor(realAccount.getChipColor());

                holder.flaggedMessageCountIcon.setBackgroundDrawable( realAccount.generateColorChip(false, false, false, false,true).drawable() );
                holder.newMessageCountIcon.setBackgroundDrawable( realAccount.generateColorChip(false, false, false, false, false).drawable() );
                holder.flaggedMessageCountIcon.setBackgroundDrawable( realAccount.generateColorChip(false, true).drawable() );
                holder.newMessageCountIcon.setBackgroundDrawable( realAccount.generateColorChip(false, false).drawable() );

            } else {
                holder.chip.setBackgroundColor(0xff999999);
+2 −2
Original line number Diff line number Diff line
@@ -1050,7 +1050,7 @@ public class FolderList extends K9ListActivity {
                        createUnreadSearch(mAccount, folder));
                holder.newMessageCountWrapper.setVisibility(View.VISIBLE);
                holder.newMessageCountIcon.setBackgroundDrawable(
                        mAccount.generateColorChip(false, false, false, false, false).drawable());
                        mAccount.generateColorChip(false, false).drawable());
            } else {
                holder.newMessageCountWrapper.setVisibility(View.GONE);
            }
@@ -1072,7 +1072,7 @@ public class FolderList extends K9ListActivity {
                        createFlaggedSearch(mAccount, folder));
                holder.flaggedMessageCountWrapper.setVisibility(View.VISIBLE);
                holder.flaggedMessageCountIcon.setBackgroundDrawable(
                        mAccount.generateColorChip(false, false, false, false,true).drawable());
                        mAccount.generateColorChip(false, true).drawable());
            } else {
                holder.flaggedMessageCountWrapper.setVisibility(View.GONE);
            }
+15 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ public class ComposeCryptoStatus {

    private CryptoProviderState cryptoProviderState;
    private CryptoMode cryptoMode;
    private boolean cryptoSupportSignOnly;
    private boolean allKeysAvailable;
    private boolean allKeysVerified;
    private boolean hasRecipients;
@@ -99,6 +100,10 @@ public class ComposeCryptoStatus {
        return cryptoMode == CryptoMode.OPPORTUNISTIC;
    }

    public boolean isOpportunisticSignOnly() {
        return cryptoSupportSignOnly;
    }

    public boolean isSigningEnabled() {
        return cryptoMode != CryptoMode.DISABLE && signingKeyId != null;
    }
@@ -123,6 +128,7 @@ public class ComposeCryptoStatus {
        private Long selfEncryptKeyId;
        private List<Recipient> recipients;
        private Boolean enablePgpInline;
        private Boolean cryptoSupportSignOnly;

        public ComposeCryptoStatusBuilder setCryptoProviderState(CryptoProviderState cryptoProviderState) {
            this.cryptoProviderState = cryptoProviderState;
@@ -134,6 +140,11 @@ public class ComposeCryptoStatus {
            return this;
        }

        public ComposeCryptoStatusBuilder setCryptoSupportSignOnly(boolean cryptoSupportSignOnly) {
            this.cryptoSupportSignOnly = cryptoSupportSignOnly;
            return this;
        }

        public ComposeCryptoStatusBuilder setSigningKeyId(long signingKeyId) {
            this.signingKeyId = signingKeyId;
            return this;
@@ -167,6 +178,9 @@ public class ComposeCryptoStatus {
            if (enablePgpInline == null) {
                throw new AssertionError("enablePgpInline must be set!");
            }
            if (cryptoSupportSignOnly == null) {
                throw new AssertionError("supportSignOnly must be set!");
            }

            ArrayList<String> recipientAddresses = new ArrayList<>();
            boolean allKeysAvailable = true;
@@ -187,6 +201,7 @@ public class ComposeCryptoStatus {
            ComposeCryptoStatus result = new ComposeCryptoStatus();
            result.cryptoProviderState = cryptoProviderState;
            result.cryptoMode = cryptoMode;
            result.cryptoSupportSignOnly = cryptoSupportSignOnly;
            result.recipientAddresses = recipientAddresses.toArray(new String[0]);
            result.allKeysAvailable = allKeysAvailable;
            result.allKeysVerified = allKeysVerified;
Loading