Skip to content

Commit f6072d4

Browse files
Merge pull request #9831 from shamim-emon/fix-issue-9830
Rewrite AutocryptHeaderParser and AutocryptGossipHeaderParser in Kotlin
2 parents 9f93f93 + 563aa61 commit f6072d4

File tree

8 files changed

+150
-207
lines changed

8 files changed

+150
-207
lines changed

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

Lines changed: 0 additions & 95 deletions
This file was deleted.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.fsck.k9.autocrypt
2+
3+
import androidx.annotation.VisibleForTesting
4+
import com.fsck.k9.mail.Part
5+
import com.fsck.k9.mail.internet.MimeUtility
6+
import java.util.Collections
7+
import net.thunderbird.core.logging.legacy.Log
8+
import okio.ByteString.Companion.decodeBase64
9+
10+
internal object AutocryptGossipHeaderParser {
11+
12+
fun getAllAutocryptGossipHeaders(part: Part): List<AutocryptGossipHeader> {
13+
val headers = part.getHeader(AutocryptGossipHeader.AUTOCRYPT_GOSSIP_HEADER)
14+
val autocryptHeaders = parseAllAutocryptGossipHeaders(headers)
15+
return Collections.unmodifiableList(autocryptHeaders)
16+
}
17+
18+
@VisibleForTesting
19+
fun parseAutocryptGossipHeader(headerValue: String): AutocryptGossipHeader? {
20+
val parameters = MimeUtility.getAllHeaderParameters(headerValue).toMutableMap()
21+
22+
val type = parameters.remove(AutocryptHeader.AUTOCRYPT_PARAM_TYPE)
23+
val base64KeyData = parameters.remove(AutocryptHeader.AUTOCRYPT_PARAM_KEY_DATA)
24+
val addr = parameters.remove(AutocryptHeader.AUTOCRYPT_PARAM_ADDR)
25+
val decodedKey = base64KeyData?.decodeBase64()
26+
27+
return when {
28+
type != null && type != AutocryptHeader.AUTOCRYPT_TYPE_1 -> {
29+
Log.e("autocrypt: unsupported type parameter %s", type)
30+
null
31+
}
32+
33+
base64KeyData == null -> {
34+
Log.e("autocrypt: missing key parameter")
35+
null
36+
}
37+
38+
decodedKey == null -> {
39+
Log.e("autocrypt: error parsing base64 data")
40+
null
41+
}
42+
43+
addr == null -> {
44+
Log.e("autocrypt: no to header!")
45+
null
46+
}
47+
48+
hasCriticalParameters(parameters) -> {
49+
null
50+
}
51+
52+
else -> {
53+
AutocryptGossipHeader(addr, decodedKey.toByteArray())
54+
}
55+
}
56+
}
57+
58+
private fun hasCriticalParameters(parameters: Map<String, String>): Boolean {
59+
return parameters.keys.any { !it.startsWith("_") }
60+
}
61+
62+
private fun parseAllAutocryptGossipHeaders(headers: Array<String>): List<AutocryptGossipHeader> {
63+
return headers.mapNotNull { header ->
64+
parseAutocryptGossipHeader(header) ?: run {
65+
Log.e("Encountered malformed autocrypt-gossip header - skipping!")
66+
null
67+
}
68+
}
69+
}
70+
}

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

Lines changed: 0 additions & 99 deletions
This file was deleted.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.fsck.k9.autocrypt
2+
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
8+
9+
internal object AutocryptHeaderParser {
10+
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()
15+
}
16+
17+
@VisibleForTesting
18+
fun parseAutocryptHeader(headerValue: String): AutocryptHeader? {
19+
val parameters = MimeUtility.getAllHeaderParameters(headerValue).toMutableMap()
20+
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)
25+
26+
val decodedKeyData = base64KeyData?.decodeBase64()
27+
28+
return when {
29+
type != null && type != AutocryptHeader.AUTOCRYPT_TYPE_1 -> {
30+
Log.e(TAG, "Unsupported type parameter: $type")
31+
null
32+
}
33+
34+
base64KeyData == null -> {
35+
Log.e(TAG, "Missing key parameter")
36+
null
37+
}
38+
39+
decodedKeyData == null -> {
40+
Log.e(TAG, "Error parsing base64 data")
41+
null
42+
}
43+
44+
to == null -> {
45+
Log.e(TAG, "No 'to' header found")
46+
null
47+
}
48+
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+
}
61+
}
62+
63+
private fun hasCriticalParameters(parameters: Map<String, String>): Boolean {
64+
return parameters.keys.any { !it.startsWith("_") }
65+
}
66+
67+
private fun parseAllAutocryptHeaders(headers: Collection<String>): List<AutocryptHeader> {
68+
return headers.mapNotNull(::parseAutocryptHeader)
69+
}
70+
}

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.getInstance();
29-
AutocryptGossipHeaderParser autocryptGossipHeaderParser = AutocryptGossipHeaderParser.getInstance();
28+
final AutocryptHeaderParser autocryptHeaderParser = AutocryptHeaderParser.INSTANCE;
29+
final AutocryptGossipHeaderParser autocryptGossipHeaderParser = AutocryptGossipHeaderParser.INSTANCE;
3030
return new AutocryptOperations(autocryptHeaderParser, autocryptGossipHeaderParser);
3131
}
3232

0 commit comments

Comments
 (0)