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

Unverified Commit a5a55b58 authored by Arnt Gulbrandsen's avatar Arnt Gulbrandsen Committed by Wolf-Martell Montwé
Browse files

Add support for RFCs 5530 and 9755.

5530 (ENABLE) lets a client tell the server which extensions it would like
to use, and lets the server tell the client which extensions is has
enabled. Most IMAP extensions don't need to be enabled, but UTF8=ACCEPT
does.

9755 (UTF8=ACCEPT) requires four things of clients:
1. The client uses ENABLE (added with tests)
2. The client accepts UTF8 strings (worked already, this adds testing)
3. The client cannot use certain SEARCH syntax (tb already did not)
4. The client uses UTF8 for folder names instead of mUTF7

This commit contains a couple of unit tests that do nothing right now,
they merely guard against possible future breakage.
parent 6fa15e0a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -19,4 +19,6 @@ class Capabilities {
    public static final String UID_PLUS = "UIDPLUS";
    public static final String LIST_EXTENDED = "LIST-EXTENDED";
    public static final String MOVE = "MOVE";
    public static final String ENABLE = "ENABLE";
    public static final String UTF8_ACCEPT = "UTF8=ACCEPT";
}
+1 −0
Original line number Diff line number Diff line
@@ -21,4 +21,5 @@ class Commands {
    public static final String UID_COPY = "UID COPY";
    public static final String UID_MOVE = "UID MOVE";
    public static final String UID_EXPUNGE = "UID EXPUNGE";
    public static final String ENABLE = "ENABLE UTF8=ACCEPT";
}
+36 −0
Original line number Diff line number Diff line
package com.fsck.k9.mail.store.imap

import com.fsck.k9.mail.store.imap.ImapResponseParser.equalsIgnoreCase
import java.util.Locale

internal class EnabledResponse private constructor(val capabilities: Set<String>) {

    companion object {
        fun parse(responses: List<ImapResponse>): EnabledResponse? {
            var result: EnabledResponse? = null
            for (response in responses) {
                if (result == null && response.tag == null) {
                    result = parse(response)
                }
            }
            return result
        }

        private fun parse(capabilityList: ImapList): EnabledResponse? {
            if (capabilityList.isEmpty() || !equalsIgnoreCase(capabilityList[0], Responses.ENABLED)) {
                return null
            }
            val capabilities = mutableSetOf<String>()
            var isValid = true
            for (i in 1 until capabilityList.size) {
                if (!capabilityList.isString(i)) {
                    isValid = false
                    break
                }
                capabilities.add(capabilityList.getString(i).uppercase(Locale.US))
            }

            return if (isValid) EnabledResponse(capabilities) else null
        }
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ internal interface ImapConnection {
    val isConnected: Boolean
    val outputStream: OutputStream
    val isUidPlusCapable: Boolean
    val isUtf8AcceptCapable: Boolean
    val isIdleCapable: Boolean

    @Throws(IOException::class, MessagingException::class)
+16 −1
Original line number Diff line number Diff line
@@ -19,10 +19,17 @@ class ImapResponseParser {
    private PeekableInputStream inputStream;
    private ImapResponse response;
    private Exception exception;

    private boolean utf8Accept;
    private FolderNameCodec folderNameCodec;

    public ImapResponseParser(PeekableInputStream in) {
        this.inputStream = in;
        this.utf8Accept = false;
        this.folderNameCodec = new FolderNameCodec();
    }

    public void setUtf8Accepted(final boolean yes) {
        utf8Accept = yes;
    }

    public ImapResponse readResponse() throws IOException {
@@ -195,6 +202,14 @@ class ImapResponseParser {
        response.add(delimiter);
        expect(' ');
        String name = parseString();
        if (utf8Accept) {
            // RFCs 9051 and 9755 allow UTF8 in folder names. "The
            // "UTF8=ACCEPT" capability indicates that the server
            // ... can provide UTF-8 responses to the "LIST" and
            // "LSUB" commands."
        } else {
            name = folderNameCodec.decode(name);
        }
        response.add(name);
        expect('\r');
        expect('\n');
Loading