Add support for UTF-8 data in BODYSTRUCTURE response
This commit is contained in:
parent
dd3d103fd3
commit
037afd0596
4 changed files with 40 additions and 6 deletions
|
@ -26,6 +26,7 @@ internal const val SEMICOLON = ';'
|
|||
internal const val EQUALS_SIGN = '='
|
||||
internal const val ASTERISK = '*'
|
||||
internal const val SINGLE_QUOTE = '\''
|
||||
internal const val BACKSLASH = '\\'
|
||||
|
||||
internal fun Char.isTSpecial() = this in TSPECIALS
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ object MimeParameterEncoder {
|
|||
|
||||
private fun String.isQuotable() = all { it.isQuotable() }
|
||||
|
||||
fun String.quoted(): String {
|
||||
private fun String.quoted(): String {
|
||||
// quoted-string = [CFWS] DQUOTE *([FWS] qcontent) [FWS] DQUOTE [CFWS]
|
||||
// qcontent = qtext / quoted-pair
|
||||
// quoted-pair = ("\" (VCHAR / WSP))
|
||||
|
@ -165,6 +165,22 @@ object MimeParameterEncoder {
|
|||
}
|
||||
}
|
||||
|
||||
// RFC 6532-style header values
|
||||
// Right now we only create such values for internal use (see IMAP BODYSTRUCTURE response parsing code)
|
||||
fun String.quotedUtf8(): String {
|
||||
return buildString(capacity = length + 16) {
|
||||
append(DQUOTE)
|
||||
for (c in this@quotedUtf8) {
|
||||
if (c == DQUOTE || c == BACKSLASH) {
|
||||
append('\\').append(c)
|
||||
} else {
|
||||
append(c)
|
||||
}
|
||||
}
|
||||
append(DQUOTE)
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.quotedLength(): Int {
|
||||
var length = 2 /* start and end quote */
|
||||
for (c in this) {
|
||||
|
|
|
@ -16,14 +16,12 @@ import com.fsck.k9.mail.internet.MimeHeader
|
|||
import com.fsck.k9.mail.internet.MimeMessageHelper
|
||||
import com.fsck.k9.mail.internet.MimeMultipart
|
||||
import com.fsck.k9.mail.internet.MimeParameterEncoder.isToken
|
||||
import com.fsck.k9.mail.internet.MimeParameterEncoder.quoted
|
||||
import com.fsck.k9.mail.internet.MimeParameterEncoder.quotedUtf8
|
||||
import com.fsck.k9.mail.internet.MimeUtility
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.HashMap
|
||||
import java.util.LinkedHashSet
|
||||
import java.util.Locale
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
@ -891,7 +889,7 @@ internal class RealImapFolder(
|
|||
for (i in bodyParams.indices step 2) {
|
||||
val paramName = bodyParams.getString(i)
|
||||
val paramValue = bodyParams.getString(i + 1)
|
||||
val encodedValue = if (paramValue.isToken()) paramValue else paramValue.quoted()
|
||||
val encodedValue = if (paramValue.isToken()) paramValue else paramValue.quotedUtf8()
|
||||
contentType.append(String.format(";\r\n %s=%s", paramName, encodedValue))
|
||||
}
|
||||
}
|
||||
|
@ -918,7 +916,7 @@ internal class RealImapFolder(
|
|||
for (i in bodyDispositionParams.indices step 2) {
|
||||
val paramName = bodyDispositionParams.getString(i).lowercase()
|
||||
val paramValue = bodyDispositionParams.getString(i + 1)
|
||||
val encodedValue = if (paramValue.isToken()) paramValue else paramValue.quoted()
|
||||
val encodedValue = if (paramValue.isToken()) paramValue else paramValue.quotedUtf8()
|
||||
contentDisposition.append(String.format(";\r\n %s=%s", paramName, encodedValue))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -770,6 +770,15 @@ class RealImapFolderTest {
|
|||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch() with UTF-8 encoded content type parameter`() {
|
||||
testHeaderFromBodyStructure(
|
||||
bodyStructure = """("text" "plain" ("name" "filenäme.ext") NIL NIL "7bit" 42 23)""",
|
||||
headerName = MimeHeader.HEADER_CONTENT_TYPE,
|
||||
expectedHeaderValue = "text/plain;\r\n name=\"filenäme.ext\""
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch() with simple content disposition parameter`() {
|
||||
testHeaderFromBodyStructure(
|
||||
|
@ -810,6 +819,16 @@ class RealImapFolderTest {
|
|||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetch() with UTF-8 encoded content disposition parameter`() {
|
||||
testHeaderFromBodyStructure(
|
||||
bodyStructure = """("application" "octet-stream" NIL NIL NIL "8bit" 23 NIL """ +
|
||||
"""("attachment" ("filename" "filenäme.ext")) NIL NIL)""",
|
||||
headerName = MimeHeader.HEADER_CONTENT_DISPOSITION,
|
||||
expectedHeaderValue = "attachment;\r\n filename=\"filenäme.ext\";\r\n size=23"
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fetch_withBodySaneFetchProfile_shouldIssueRespectiveCommand() {
|
||||
val folder = createFolder("Folder")
|
||||
|
|
Loading…
Reference in a new issue