Skip to content

Commit feb8cd6

Browse files
committed
refactor: port AutocryptHeaderParser from java to kotlin
1 parent 21e5112 commit feb8cd6

File tree

3 files changed

+54
-84
lines changed

3 files changed

+54
-84
lines changed
Lines changed: 51 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,70 @@
1-
package com.fsck.k9.autocrypt;
1+
package com.fsck.k9.autocrypt
22

3+
import androidx.annotation.VisibleForTesting
4+
import com.fsck.k9.mail.Message
5+
import com.fsck.k9.mail.internet.MimeUtility
6+
import net.thunderbird.core.logging.legacy.Log
7+
import okio.ByteString.Companion.decodeBase64
38

4-
import java.util.ArrayList;
5-
import java.util.Map;
9+
internal object AutocryptHeaderParser {
610

7-
import androidx.annotation.NonNull;
8-
import androidx.annotation.Nullable;
9-
import androidx.annotation.VisibleForTesting;
10-
11-
import com.fsck.k9.mail.Message;
12-
import com.fsck.k9.mail.internet.MimeUtility;
13-
import okio.ByteString;
14-
import net.thunderbird.core.logging.legacy.Log;
15-
16-
17-
class AutocryptHeaderParser {
18-
private static final AutocryptHeaderParser INSTANCE = new AutocryptHeaderParser();
19-
20-
21-
public static AutocryptHeaderParser getInstance() {
22-
return INSTANCE;
11+
private const val TAG = "AutocryptHeaderParser"
12+
fun getValidAutocryptHeader(currentMessage: Message): AutocryptHeader? {
13+
val headers = currentMessage.getHeader(AutocryptHeader.AUTOCRYPT_HEADER).orEmpty().asList()
14+
return parseAllAutocryptHeaders(headers).singleOrNull()
2315
}
2416

25-
private AutocryptHeaderParser() { }
26-
27-
28-
@Nullable
29-
AutocryptHeader getValidAutocryptHeader(Message currentMessage) {
30-
String[] headers = currentMessage.getHeader(AutocryptHeader.AUTOCRYPT_HEADER);
31-
ArrayList<AutocryptHeader> autocryptHeaders = parseAllAutocryptHeaders(headers);
32-
33-
boolean isSingleValidHeader = autocryptHeaders.size() == 1;
34-
return isSingleValidHeader ? autocryptHeaders.get(0) : null;
35-
}
36-
37-
@Nullable
3817
@VisibleForTesting
39-
AutocryptHeader parseAutocryptHeader(String headerValue) {
40-
Map<String,String> parameters = MimeUtility.getAllHeaderParameters(headerValue);
18+
fun parseAutocryptHeader(headerValue: String): AutocryptHeader? {
19+
val parameters = MimeUtility.getAllHeaderParameters(headerValue).toMutableMap()
4120

42-
String type = parameters.remove(AutocryptHeader.AUTOCRYPT_PARAM_TYPE);
43-
if (type != null && !type.equals(AutocryptHeader.AUTOCRYPT_TYPE_1)) {
44-
Log.e("autocrypt: unsupported type parameter %s", type);
45-
return null;
46-
}
21+
val type = parameters.remove(AutocryptHeader.AUTOCRYPT_PARAM_TYPE)
22+
val base64KeyData = parameters.remove(AutocryptHeader.AUTOCRYPT_PARAM_KEY_DATA)
23+
val to = parameters.remove(AutocryptHeader.AUTOCRYPT_PARAM_ADDR)
24+
val preferEncrypt = parameters.remove(AutocryptHeader.AUTOCRYPT_PARAM_PREFER_ENCRYPT)
4725

48-
String base64KeyData = parameters.remove(AutocryptHeader.AUTOCRYPT_PARAM_KEY_DATA);
49-
if (base64KeyData == null) {
50-
Log.e("autocrypt: missing key parameter");
51-
return null;
52-
}
26+
val decodedKeyData = base64KeyData?.decodeBase64()
5327

54-
ByteString byteString = ByteString.decodeBase64(base64KeyData);
55-
if (byteString == null) {
56-
Log.e("autocrypt: error parsing base64 data");
57-
return null;
58-
}
28+
return when {
29+
type != null && type != AutocryptHeader.AUTOCRYPT_TYPE_1 -> {
30+
Log.e(TAG, "Unsupported type parameter: $type")
31+
null
32+
}
5933

60-
String to = parameters.remove(AutocryptHeader.AUTOCRYPT_PARAM_ADDR);
61-
if (to == null) {
62-
Log.e("autocrypt: no to header!");
63-
return null;
64-
}
34+
base64KeyData == null -> {
35+
Log.e(TAG, "Missing key parameter")
36+
null
37+
}
6538

66-
boolean isPreferEncryptMutual = false;
67-
String preferEncrypt = parameters.remove(AutocryptHeader.AUTOCRYPT_PARAM_PREFER_ENCRYPT);
68-
if (AutocryptHeader.AUTOCRYPT_PREFER_ENCRYPT_MUTUAL.equalsIgnoreCase(preferEncrypt)) {
69-
isPreferEncryptMutual = true;
70-
}
39+
decodedKeyData == null -> {
40+
Log.e(TAG, "Error parsing base64 data")
41+
null
42+
}
7143

72-
if (hasCriticalParameters(parameters)) {
73-
return null;
74-
}
44+
to == null -> {
45+
Log.e(TAG, "No 'to' header found")
46+
null
47+
}
7548

76-
return new AutocryptHeader(parameters, to, byteString.toByteArray(), isPreferEncryptMutual);
49+
hasCriticalParameters(parameters) -> null
50+
51+
else -> AutocryptHeader(
52+
parameters = parameters,
53+
addr = to,
54+
keyData = decodedKeyData.toByteArray(),
55+
isPreferEncryptMutual = AutocryptHeader.AUTOCRYPT_PREFER_ENCRYPT_MUTUAL.equals(
56+
preferEncrypt,
57+
ignoreCase = true,
58+
),
59+
)
60+
}
7761
}
7862

79-
private boolean hasCriticalParameters(Map<String, String> parameters) {
80-
for (String parameterName : parameters.keySet()) {
81-
if (parameterName != null && !parameterName.startsWith("_")) {
82-
return true;
83-
}
84-
}
85-
return false;
63+
private fun hasCriticalParameters(parameters: Map<String, String>): Boolean {
64+
return parameters.keys.any { !it.startsWith("_") }
8665
}
8766

88-
@NonNull
89-
private ArrayList<AutocryptHeader> parseAllAutocryptHeaders(String[] headers) {
90-
ArrayList<AutocryptHeader> autocryptHeaders = new ArrayList<>();
91-
for (String header : headers) {
92-
AutocryptHeader autocryptHeader = parseAutocryptHeader(header);
93-
if (autocryptHeader != null) {
94-
autocryptHeaders.add(autocryptHeader);
95-
}
96-
}
97-
return autocryptHeaders;
67+
private fun parseAllAutocryptHeaders(headers: Collection<String>): List<AutocryptHeader> {
68+
return headers.mapNotNull(::parseAutocryptHeader)
9869
}
9970
}

legacy/core/src/main/java/com/fsck/k9/autocrypt/AutocryptOperations.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ public class AutocryptOperations {
2525

2626

2727
public static AutocryptOperations getInstance() {
28-
AutocryptHeaderParser autocryptHeaderParser = AutocryptHeaderParser.Companion.getInstance();
29-
AutocryptGossipHeaderParser autocryptGossipHeaderParser = AutocryptGossipHeaderParser.INSTANCE;
28+
final AutocryptHeaderParser autocryptHeaderParser = AutocryptHeaderParser.INSTANCE;
29+
final AutocryptGossipHeaderParser autocryptGossipHeaderParser = AutocryptGossipHeaderParser.INSTANCE;
3030
return new AutocryptOperations(autocryptHeaderParser, autocryptGossipHeaderParser);
3131
}
3232

legacy/ui/legacy/src/test/java/com/fsck/k9/autocrypt/AutocryptOperationsHelper.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@
99

1010

1111
public class AutocryptOperationsHelper {
12-
private static AutocryptHeaderParser INSTANCE = AutocryptHeaderParser.getInstance();
1312

1413
public static void assertMessageHasAutocryptHeader(
1514
MimeMessage message, String addr, boolean isPreferEncryptMutual, byte[] keyData) {
16-
AutocryptHeader autocryptHeader = INSTANCE.getValidAutocryptHeader(message);
15+
AutocryptHeader autocryptHeader = AutocryptHeaderParser.INSTANCE.getValidAutocryptHeader(message);
1716

1817
assertNotNull(autocryptHeader);
1918
assertEquals(addr, autocryptHeader.getAddr());

0 commit comments

Comments
 (0)