Loading mail/common/src/main/java/com/fsck/k9/mail/internet/FormatFlowedHelper.kt +21 −23 Original line number Diff line number Diff line package com.fsck.k9.mail.internet; package com.fsck.k9.mail.internet import java.util.Locale import static com.fsck.k9.mail.internet.MimeUtility.getHeaderParameter; import static com.fsck.k9.mail.internet.MimeUtility.isSameMimeType; internal object FormatFlowedHelper { private const val TEXT_PLAIN = "text/plain" private const val HEADER_PARAM_FORMAT = "format" private const val HEADER_FORMAT_FLOWED = "flowed" private const val HEADER_PARAM_DELSP = "delsp" private const val HEADER_DELSP_YES = "yes" @JvmStatic fun checkFormatFlowed(contentTypeHeaderValue: String?): FormatFlowedResult { if (contentTypeHeaderValue == null) return negativeResult() class FormatFlowedHelper { private static final String TEXT_PLAIN = "text/plain"; private static final String HEADER_PARAM_FORMAT = "format"; private static final String HEADER_FORMAT_FLOWED = "flowed"; private static final String HEADER_PARAM_DELSP = "delsp"; private static final String HEADER_DELSP_YES = "yes"; val mimeValue = MimeParameterDecoder.decode(contentTypeHeaderValue) if (!MimeUtility.isSameMimeType(TEXT_PLAIN, mimeValue.value)) return negativeResult() val formatParameter = mimeValue.parameters[HEADER_PARAM_FORMAT]?.toLowerCase(Locale.ROOT) if (formatParameter != HEADER_FORMAT_FLOWED) return negativeResult() static boolean isFormatFlowed(String contentType) { String mimeType = getHeaderParameter(contentType, null); if (isSameMimeType(TEXT_PLAIN, mimeType)) { String formatParameter = getHeaderParameter(contentType, HEADER_PARAM_FORMAT); return HEADER_FORMAT_FLOWED.equalsIgnoreCase(formatParameter); } return false; } val delSpParameter = mimeValue.parameters[HEADER_PARAM_DELSP]?.toLowerCase(Locale.ROOT) static boolean isDelSp(String contentType) { if (isFormatFlowed(contentType)) { String delSpParameter = getHeaderParameter(contentType, HEADER_PARAM_DELSP); return HEADER_DELSP_YES.equalsIgnoreCase(delSpParameter); } return false; return FormatFlowedResult(isFormatFlowed = true, isDelSp = delSpParameter == HEADER_DELSP_YES) } private fun negativeResult() = FormatFlowedResult(isFormatFlowed = false, isDelSp = false) } internal data class FormatFlowedResult(val isFormatFlowed: Boolean, val isDelSp: Boolean) mail/common/src/main/java/com/fsck/k9/mail/internet/MessageExtractor.java +5 −8 Original line number Diff line number Diff line Loading @@ -120,16 +120,13 @@ public class MessageExtractor { } catch (IOException e) { /* Ignore */ } } if (isSameMimeType(mimeType, "text/plain")) { String contentType = part.getContentType(); if (FormatFlowedHelper.isFormatFlowed(contentType)) { boolean delSp = FormatFlowedHelper.isDelSp(contentType); return FlowedMessageUtils.deflow(text, delSp); } } FormatFlowedResult result = FormatFlowedHelper.checkFormatFlowed(part.getContentType()); if (result.isFormatFlowed()) { return FlowedMessageUtils.deflow(text, result.isDelSp()); } else { return text; } } public static boolean hasMissingParts(Part part) { Body body = part.getBody(); Loading mail/common/src/test/java/com/fsck/k9/mail/internet/FormatFlowedHelperTest.kt +42 −25 Original line number Diff line number Diff line package com.fsck.k9.mail.internet; package com.fsck.k9.mail.internet import com.google.common.truth.Truth.assertThat import org.junit.Test import org.junit.Test; import static com.fsck.k9.mail.internet.FormatFlowedHelper.isDelSp; import static com.fsck.k9.mail.internet.FormatFlowedHelper.isFormatFlowed; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; class FormatFlowedHelperTest { @Test fun `plain text and format=flowed`() { val contentTypeHeader = "text/plain; format=flowed" val result = FormatFlowedHelper.checkFormatFlowed(contentTypeHeader) public class FormatFlowedHelperTest { @Test public void isFormatFlowed_withTextPlainFormatFlowed_shouldReturnTrue() throws Exception { assertTrue(isFormatFlowed("text/plain; format=flowed")); assertThat(result.isFormatFlowed).isTrue() assertThat(result.isDelSp).isFalse() } @Test public void isFormatFlowed_withTextPlain_shouldReturnFalse() throws Exception { assertFalse(isFormatFlowed("text/plain")); } fun `plain text and format=flowed and delsp=yes`() { val contentTypeHeader = "text/plain; format=flowed; delsp=yes" @Test public void isFormatFlowed_withTextHtmlFormatFlowed_shouldReturnFalse() throws Exception { assertFalse(isFormatFlowed("text/html; format=flowed")); val result = FormatFlowedHelper.checkFormatFlowed(contentTypeHeader) assertThat(result.isFormatFlowed).isTrue() assertThat(result.isDelSp).isTrue() } @Test public void isDelSp_withFormatFlowed_shouldReturnTrue() throws Exception { assertTrue(isDelSp("text/plain; format=flowed; delsp=yes")); fun `plain text without format=flowed`() { val contentTypeHeader = "text/plain" val result = FormatFlowedHelper.checkFormatFlowed(contentTypeHeader) assertThat(result.isFormatFlowed).isFalse() } @Test public void isDelSp_withTextPlainFormatFlowed_shoulReturnFalse() throws Exception { assertFalse(isDelSp("text/plain; format=flowed")); fun `plain text without format=flowed but delsp=yes`() { val contentTypeHeader = "text/plain; delsp=yes" val result = FormatFlowedHelper.checkFormatFlowed(contentTypeHeader) assertThat(result.isFormatFlowed).isFalse() assertThat(result.isDelSp).isFalse() } @Test public void isDelSp_withoutFormatFlowed_shouldReturnFalse() throws Exception { assertFalse(isDelSp("text/plain; delsp=yes")); fun `HTML and format=flowed`() { val contentTypeHeader = "text/html; format=flowed" val result = FormatFlowedHelper.checkFormatFlowed(contentTypeHeader) assertThat(result.isFormatFlowed).isFalse() } @Test public void idDelSp_withTextHtmlFormatFlowed_shouldReturnFalse() throws Exception { assertFalse(isDelSp("text/html; format=flowed; delsp=yes")); fun `HTML and format=flowed and delsp=yes`() { val contentTypeHeader = "text/html; format=flowed; delsp=yes" val result = FormatFlowedHelper.checkFormatFlowed(contentTypeHeader) assertThat(result.isFormatFlowed).isFalse() assertThat(result.isDelSp).isFalse() } } Loading
mail/common/src/main/java/com/fsck/k9/mail/internet/FormatFlowedHelper.kt +21 −23 Original line number Diff line number Diff line package com.fsck.k9.mail.internet; package com.fsck.k9.mail.internet import java.util.Locale import static com.fsck.k9.mail.internet.MimeUtility.getHeaderParameter; import static com.fsck.k9.mail.internet.MimeUtility.isSameMimeType; internal object FormatFlowedHelper { private const val TEXT_PLAIN = "text/plain" private const val HEADER_PARAM_FORMAT = "format" private const val HEADER_FORMAT_FLOWED = "flowed" private const val HEADER_PARAM_DELSP = "delsp" private const val HEADER_DELSP_YES = "yes" @JvmStatic fun checkFormatFlowed(contentTypeHeaderValue: String?): FormatFlowedResult { if (contentTypeHeaderValue == null) return negativeResult() class FormatFlowedHelper { private static final String TEXT_PLAIN = "text/plain"; private static final String HEADER_PARAM_FORMAT = "format"; private static final String HEADER_FORMAT_FLOWED = "flowed"; private static final String HEADER_PARAM_DELSP = "delsp"; private static final String HEADER_DELSP_YES = "yes"; val mimeValue = MimeParameterDecoder.decode(contentTypeHeaderValue) if (!MimeUtility.isSameMimeType(TEXT_PLAIN, mimeValue.value)) return negativeResult() val formatParameter = mimeValue.parameters[HEADER_PARAM_FORMAT]?.toLowerCase(Locale.ROOT) if (formatParameter != HEADER_FORMAT_FLOWED) return negativeResult() static boolean isFormatFlowed(String contentType) { String mimeType = getHeaderParameter(contentType, null); if (isSameMimeType(TEXT_PLAIN, mimeType)) { String formatParameter = getHeaderParameter(contentType, HEADER_PARAM_FORMAT); return HEADER_FORMAT_FLOWED.equalsIgnoreCase(formatParameter); } return false; } val delSpParameter = mimeValue.parameters[HEADER_PARAM_DELSP]?.toLowerCase(Locale.ROOT) static boolean isDelSp(String contentType) { if (isFormatFlowed(contentType)) { String delSpParameter = getHeaderParameter(contentType, HEADER_PARAM_DELSP); return HEADER_DELSP_YES.equalsIgnoreCase(delSpParameter); } return false; return FormatFlowedResult(isFormatFlowed = true, isDelSp = delSpParameter == HEADER_DELSP_YES) } private fun negativeResult() = FormatFlowedResult(isFormatFlowed = false, isDelSp = false) } internal data class FormatFlowedResult(val isFormatFlowed: Boolean, val isDelSp: Boolean)
mail/common/src/main/java/com/fsck/k9/mail/internet/MessageExtractor.java +5 −8 Original line number Diff line number Diff line Loading @@ -120,16 +120,13 @@ public class MessageExtractor { } catch (IOException e) { /* Ignore */ } } if (isSameMimeType(mimeType, "text/plain")) { String contentType = part.getContentType(); if (FormatFlowedHelper.isFormatFlowed(contentType)) { boolean delSp = FormatFlowedHelper.isDelSp(contentType); return FlowedMessageUtils.deflow(text, delSp); } } FormatFlowedResult result = FormatFlowedHelper.checkFormatFlowed(part.getContentType()); if (result.isFormatFlowed()) { return FlowedMessageUtils.deflow(text, result.isDelSp()); } else { return text; } } public static boolean hasMissingParts(Part part) { Body body = part.getBody(); Loading
mail/common/src/test/java/com/fsck/k9/mail/internet/FormatFlowedHelperTest.kt +42 −25 Original line number Diff line number Diff line package com.fsck.k9.mail.internet; package com.fsck.k9.mail.internet import com.google.common.truth.Truth.assertThat import org.junit.Test import org.junit.Test; import static com.fsck.k9.mail.internet.FormatFlowedHelper.isDelSp; import static com.fsck.k9.mail.internet.FormatFlowedHelper.isFormatFlowed; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; class FormatFlowedHelperTest { @Test fun `plain text and format=flowed`() { val contentTypeHeader = "text/plain; format=flowed" val result = FormatFlowedHelper.checkFormatFlowed(contentTypeHeader) public class FormatFlowedHelperTest { @Test public void isFormatFlowed_withTextPlainFormatFlowed_shouldReturnTrue() throws Exception { assertTrue(isFormatFlowed("text/plain; format=flowed")); assertThat(result.isFormatFlowed).isTrue() assertThat(result.isDelSp).isFalse() } @Test public void isFormatFlowed_withTextPlain_shouldReturnFalse() throws Exception { assertFalse(isFormatFlowed("text/plain")); } fun `plain text and format=flowed and delsp=yes`() { val contentTypeHeader = "text/plain; format=flowed; delsp=yes" @Test public void isFormatFlowed_withTextHtmlFormatFlowed_shouldReturnFalse() throws Exception { assertFalse(isFormatFlowed("text/html; format=flowed")); val result = FormatFlowedHelper.checkFormatFlowed(contentTypeHeader) assertThat(result.isFormatFlowed).isTrue() assertThat(result.isDelSp).isTrue() } @Test public void isDelSp_withFormatFlowed_shouldReturnTrue() throws Exception { assertTrue(isDelSp("text/plain; format=flowed; delsp=yes")); fun `plain text without format=flowed`() { val contentTypeHeader = "text/plain" val result = FormatFlowedHelper.checkFormatFlowed(contentTypeHeader) assertThat(result.isFormatFlowed).isFalse() } @Test public void isDelSp_withTextPlainFormatFlowed_shoulReturnFalse() throws Exception { assertFalse(isDelSp("text/plain; format=flowed")); fun `plain text without format=flowed but delsp=yes`() { val contentTypeHeader = "text/plain; delsp=yes" val result = FormatFlowedHelper.checkFormatFlowed(contentTypeHeader) assertThat(result.isFormatFlowed).isFalse() assertThat(result.isDelSp).isFalse() } @Test public void isDelSp_withoutFormatFlowed_shouldReturnFalse() throws Exception { assertFalse(isDelSp("text/plain; delsp=yes")); fun `HTML and format=flowed`() { val contentTypeHeader = "text/html; format=flowed" val result = FormatFlowedHelper.checkFormatFlowed(contentTypeHeader) assertThat(result.isFormatFlowed).isFalse() } @Test public void idDelSp_withTextHtmlFormatFlowed_shouldReturnFalse() throws Exception { assertFalse(isDelSp("text/html; format=flowed; delsp=yes")); fun `HTML and format=flowed and delsp=yes`() { val contentTypeHeader = "text/html; format=flowed; delsp=yes" val result = FormatFlowedHelper.checkFormatFlowed(contentTypeHeader) assertThat(result.isFormatFlowed).isFalse() assertThat(result.isDelSp).isFalse() } }