mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-23 09:52:16 -05:00
Merge branch 'master' into pgp_mime_preparations
Conflicts: k9mail/src/androidTest/java/com/fsck/k9/mailstore/LocalMessageTest.java
This commit is contained in:
commit
23c9398c03
@ -20,11 +20,12 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 17
|
||||
targetSdkVersion 21
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
abortOnError true
|
||||
warningsAsErrors true
|
||||
lintConfig file("$rootProject.projectDir/config/lint/lint.xml")
|
||||
}
|
||||
|
||||
|
@ -555,14 +555,14 @@ class ImapConnection {
|
||||
private static Socket connect(ImapSettings settings, TrustedSocketFactory socketFactory)
|
||||
throws GeneralSecurityException, MessagingException, IOException {
|
||||
// Try all IPv4 and IPv6 addresses of the host
|
||||
InetAddress[] addresses = InetAddress.getAllByName(settings.getHost());
|
||||
for (int i = 0; i < addresses.length; i++) {
|
||||
Exception connectException = null;
|
||||
for (InetAddress address : InetAddress.getAllByName(settings.getHost())) {
|
||||
try {
|
||||
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_IMAP) {
|
||||
Log.d(LOG_TAG, "Connecting to " + settings.getHost() + " as " + addresses[i]);
|
||||
Log.d(LOG_TAG, "Connecting to " + settings.getHost() + " as " + address);
|
||||
}
|
||||
|
||||
SocketAddress socketAddress = new InetSocketAddress(addresses[i], settings.getPort());
|
||||
SocketAddress socketAddress = new InetSocketAddress(address, settings.getPort());
|
||||
Socket socket;
|
||||
if (settings.getConnectionSecurity() == ConnectionSecurity.SSL_TLS_REQUIRED) {
|
||||
socket = socketFactory.createSocket(
|
||||
@ -576,15 +576,12 @@ class ImapConnection {
|
||||
socket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
|
||||
// Successfully connected to the server; don't try any other addresses
|
||||
return socket;
|
||||
} catch (SocketException e) {
|
||||
if (i < (addresses.length - 1)) {
|
||||
// There are still other addresses for that host to try
|
||||
continue;
|
||||
}
|
||||
throw new MessagingException("Cannot connect to host", e);
|
||||
} catch (IOException e) {
|
||||
Log.w(LOG_TAG, "could not connect to "+address, e);
|
||||
connectException = e;
|
||||
}
|
||||
}
|
||||
throw new MessagingException("Cannot connect to host");
|
||||
throw new MessagingException("Cannot connect to host", connectException);
|
||||
}
|
||||
|
||||
private void adjustDNSCacheTTL() {
|
||||
@ -601,10 +598,18 @@ class ImapConnection {
|
||||
}
|
||||
|
||||
private List<ImapResponse> receiveCapabilities(List<ImapResponse> responses) {
|
||||
capabilities = ImapResponseParser.parseCapabilities(responses);
|
||||
Set<String> receivedCapabilities = ImapResponseParser.parseCapabilities(responses);
|
||||
/* RFC 3501 6.2.3
|
||||
A server MAY include a CAPABILITY response code in the tagged OK
|
||||
response to a successful LOGIN command in order to send
|
||||
capabilities automatically. It is unnecessary for a client to
|
||||
send a separate CAPABILITY command if it recognizes these
|
||||
automatic capabilities.
|
||||
*/
|
||||
if (K9MailLib.isDebug()) {
|
||||
Log.d(LOG_TAG, "Saving " + capabilities + " capabilities for " + getLogId());
|
||||
Log.d(LOG_TAG, "Saving " + receivedCapabilities + " capabilities for " + getLogId());
|
||||
}
|
||||
capabilities.addAll(receivedCapabilities);
|
||||
return responses;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
|
||||
package com.fsck.k9.mail.store.pop3;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.util.Log;
|
||||
|
||||
import com.fsck.k9.mail.*;
|
||||
@ -278,6 +279,7 @@ public class Pop3Store extends RemoteStore {
|
||||
private InputStream mIn;
|
||||
private OutputStream mOut;
|
||||
private Map<String, Pop3Message> mUidToMsgMap = new HashMap<String, Pop3Message>();
|
||||
@SuppressLint("UseSparseArrays")
|
||||
private Map<Integer, Pop3Message> mMsgNumToMsgMap = new HashMap<Integer, Pop3Message>();
|
||||
private Map<String, Integer> mUidToMsgNumMap = new HashMap<String, Integer>();
|
||||
private String mName;
|
||||
|
@ -9,10 +9,8 @@ import com.fsck.k9.mail.ssl.TrustManagerFactory;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
@ -32,7 +30,7 @@ public class WebDavSocketFactory implements LayeredSocketFactory {
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, new TrustManager[] {
|
||||
TrustManagerFactory.get(host, port)
|
||||
}, new SecureRandom());
|
||||
}, null);
|
||||
mSocketFactory = sslContext.getSocketFactory();
|
||||
mSchemeSocketFactory = org.apache.http.conn.ssl.SSLSocketFactory.getSocketFactory();
|
||||
mSchemeSocketFactory.setHostnameVerifier(
|
||||
@ -41,7 +39,7 @@ public class WebDavSocketFactory implements LayeredSocketFactory {
|
||||
|
||||
public Socket connectSocket(Socket sock, String host, int port,
|
||||
InetAddress localAddress, int localPort, HttpParams params)
|
||||
throws IOException, UnknownHostException, ConnectTimeoutException {
|
||||
throws IOException, ConnectTimeoutException {
|
||||
return mSchemeSocketFactory.connectSocket(sock, host, port, localAddress, localPort, params);
|
||||
}
|
||||
|
||||
@ -57,7 +55,7 @@ public class WebDavSocketFactory implements LayeredSocketFactory {
|
||||
final String host,
|
||||
final int port,
|
||||
final boolean autoClose
|
||||
) throws IOException, UnknownHostException {
|
||||
) throws IOException {
|
||||
SSLSocket sslSocket = (SSLSocket) mSocketFactory.createSocket(
|
||||
socket,
|
||||
host,
|
||||
|
@ -5,6 +5,9 @@ apply from: '../gradle/plugins/findbugs-android.gradle'
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
url "https://oss.sonatype.org/content/repositories/snapshots/"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@ -21,16 +24,10 @@ dependencies {
|
||||
|
||||
androidTestCompile 'com.android.support.test:testing-support-lib:0.1'
|
||||
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.0'
|
||||
|
||||
androidTestCompile("com.icegreen:greenmail:1.3.1b") {
|
||||
// Use a better, later version
|
||||
exclude group: "javax.mail"
|
||||
androidTestCompile('com.icegreen:greenmail:1.4.1-SNAPSHOT') {
|
||||
exclude group: 'junit'
|
||||
}
|
||||
|
||||
// this version avoids some "Ignoring InnerClasses attribute for an anonymous inner class" warnings
|
||||
androidTestCompile "javax.mail:javax.mail-api:1.5.2"
|
||||
|
||||
androidTestCompile "com.madgag.spongycastle:pg:1.51.0.0"
|
||||
androidTestCompile 'com.madgag.spongycastle:pg:1.51.0.0'
|
||||
}
|
||||
|
||||
android {
|
||||
|
@ -1,21 +0,0 @@
|
||||
package com.fsck.k9.activity;
|
||||
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import com.fsck.k9.activity.Accounts;
|
||||
/**
|
||||
* This is a simple framework for a test of an Application. See
|
||||
* {@link android.test.ApplicationTestCase ApplicationTestCase} for more information on
|
||||
* how to write and extend Application tests.
|
||||
* <p/>
|
||||
* To run this test, you can type:
|
||||
* adb shell am instrument -w \
|
||||
* -e class com.fsck.k9.activity.AccountsTest \
|
||||
* com.fsck.k9.tests/android.test.InstrumentationTestRunner
|
||||
*/
|
||||
public class AccountsTest extends ActivityInstrumentationTestCase2<Accounts> {
|
||||
|
||||
public AccountsTest() {
|
||||
super("com.fsck.k9", Accounts.class);
|
||||
}
|
||||
|
||||
}
|
@ -1,14 +1,23 @@
|
||||
package com.fsck.k9.activity;
|
||||
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.fsck.k9.mail.Flag;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
public class MessageReferenceTest extends TestCase
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class MessageReferenceTest
|
||||
{
|
||||
/**
|
||||
* Typically happens during forwards. (You have a reference, but no flag since we don't currently consider FORWARDED a flag.)
|
||||
*/
|
||||
@Test
|
||||
public void testIdentityStringNoFlag()
|
||||
{
|
||||
MessageReference mr = new MessageReference();
|
||||
@ -22,6 +31,7 @@ public class MessageReferenceTest extends TestCase
|
||||
/**
|
||||
* Typically happens during replies.
|
||||
*/
|
||||
@Test
|
||||
public void testIdentityString()
|
||||
{
|
||||
MessageReference mr = new MessageReference();
|
||||
@ -33,6 +43,7 @@ public class MessageReferenceTest extends TestCase
|
||||
assertEquals("!:byBoYWkh:Zm9sZGVy:MTAxMDEwMTA=:ANSWERED", mr.toIdentityString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIdentityStringNoFlag() throws MessagingException
|
||||
{
|
||||
MessageReference mr = new MessageReference("!:byBoYWkh:Zm9sZGVy:MTAxMDEwMTA=");
|
||||
@ -42,6 +53,7 @@ public class MessageReferenceTest extends TestCase
|
||||
assertNull(mr.flag);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIdentityString() throws MessagingException
|
||||
{
|
||||
MessageReference mr = new MessageReference("!:byBoYWkh:Zm9sZGVy:MTAxMDEwMTA=:ANSWERED");
|
||||
@ -51,24 +63,20 @@ public class MessageReferenceTest extends TestCase
|
||||
assertEquals(Flag.ANSWERED, mr.flag);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadVersion() throws MessagingException
|
||||
{
|
||||
MessageReference mr = new MessageReference("@:byBoYWkh:Zm9sZGVy:MTAxMDEwMTA=:ANSWERED");
|
||||
assertNull(mr.accountUuid);
|
||||
}
|
||||
|
||||
@Test(expected = MessagingException.class)
|
||||
public void testNull() throws MessagingException
|
||||
{
|
||||
try
|
||||
{
|
||||
new MessageReference(null);
|
||||
assertTrue(false);
|
||||
} catch (MessagingException e)
|
||||
{
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = MessagingException.class)
|
||||
public void testCorruption() throws MessagingException
|
||||
{
|
||||
MessageReference mr = new MessageReference("!:%^&%^*$&$by&(BYWkh:Zm9%^@sZGVy:MT-35#$AxMDEwMTA=:ANSWERED");
|
||||
@ -78,13 +86,6 @@ public class MessageReferenceTest extends TestCase
|
||||
assertNotNull(mr.uid);
|
||||
|
||||
// Corruption in the Flag should throw MessagingException.
|
||||
try
|
||||
{
|
||||
new MessageReference("!:%^&%^*$&$by&(BYWkh:Zm9%^@sZGVy:MT-35#$AxMDEwMTA=:ANSWE!RED");
|
||||
assertTrue(false);
|
||||
} catch (MessagingException e)
|
||||
{
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package com.fsck.k9.endtoend;
|
||||
|
||||
import com.fsck.k9.activity.setup.WelcomeMessage;
|
||||
import com.fsck.k9.endtoend.pages.WelcomeMessagePage;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new IMAP account via the getting started flow.
|
||||
@ -12,13 +14,14 @@ public class A000_WelcomeAndSetupAccountIntegrationTest extends AbstractEndToEnd
|
||||
super(WelcomeMessage.class, false);
|
||||
}
|
||||
|
||||
public void testCreateAccount() throws Exception {
|
||||
new AccountSetupFlow(this).setupAccountFromWelcomePage(new WelcomeMessagePage());
|
||||
}
|
||||
|
||||
public void testCreateSecondAccount() throws Exception {
|
||||
new AccountSetupFlow(this).setupAccountFromWelcomePage(new WelcomeMessagePage());
|
||||
@Test
|
||||
public void createAccount() throws Exception {
|
||||
new AccountSetupFlow().setupAccountFromWelcomePage(new WelcomeMessagePage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createSecondAccount() throws Exception {
|
||||
new AccountSetupFlow().setupAccountFromWelcomePage(new WelcomeMessagePage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,8 @@ import com.fsck.k9.activity.Accounts;
|
||||
import com.fsck.k9.endtoend.framework.AccountForTest;
|
||||
import com.fsck.k9.endtoend.framework.ApplicationState;
|
||||
import com.fsck.k9.endtoend.pages.AccountsPage;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
/**
|
||||
* Creates and removes accounts.
|
||||
@ -17,14 +19,19 @@ public class A010_AccountIntegrationTest extends AbstractEndToEndTest<Accounts>{
|
||||
super(Accounts.class);
|
||||
}
|
||||
|
||||
public void testCreateAccountDirectly() throws Exception {
|
||||
new AccountSetupFlow(this).setupAccountFromAccountsPage(new AccountsPage());
|
||||
@Test
|
||||
public void createAccountDirectly() throws Exception {
|
||||
new AccountSetupFlow().setupAccountFromAccountsPage(new AccountsPage());
|
||||
}
|
||||
|
||||
public void testDeleteAccount() {
|
||||
|
||||
@Test
|
||||
public void deleteAccount() {
|
||||
AccountsPage accountsPage = new AccountsPage();
|
||||
|
||||
// TODO should not have cross-test-dependencies
|
||||
assertFalse("NB: this test is order dependent and requires A000_WelcomeAndSetupAccountIntegrationTest to run first",
|
||||
ApplicationState.getInstance().accounts.isEmpty());
|
||||
|
||||
AccountForTest accountForTest = ApplicationState.getInstance().accounts.get(0);
|
||||
accountsPage.assertAccountExists(accountForTest.description);
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
package com.fsck.k9.endtoend;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.espresso.assertion.ViewAssertions;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.util.Log;
|
||||
|
||||
@ -8,16 +11,18 @@ import com.fsck.k9.R;
|
||||
import com.fsck.k9.endtoend.framework.ApplicationState;
|
||||
import com.fsck.k9.endtoend.framework.StubMailServer;
|
||||
import com.fsck.k9.endtoend.pages.WelcomeMessagePage;
|
||||
import android.support.test.espresso.assertion.ViewAssertions;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static android.support.test.espresso.Espresso.onView;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withId;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public abstract class AbstractEndToEndTest<T extends Activity> extends ActivityInstrumentationTestCase2<T> {
|
||||
|
||||
private ApplicationState state = ApplicationState.getInstance();
|
||||
private final boolean bypassWelcome;
|
||||
|
||||
public AbstractEndToEndTest(Class<T> activityClass) {
|
||||
@ -29,9 +34,22 @@ public abstract class AbstractEndToEndTest<T extends Activity> extends ActivityI
|
||||
this.bypassWelcome = bypassWelcome;
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
ApplicationState.getInstance().stubMailServer = new StubMailServer();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
ApplicationState.getInstance().stubMailServer.stop();
|
||||
}
|
||||
|
||||
@Before
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
injectInstrumentation(InstrumentationRegistry.getInstrumentation());
|
||||
|
||||
getActivity();
|
||||
|
||||
if (bypassWelcome) {
|
||||
@ -39,6 +57,12 @@ public abstract class AbstractEndToEndTest<T extends Activity> extends ActivityI
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
private void bypassWelcomeScreen() {
|
||||
try {
|
||||
onView(withId(R.id.welcome_message)).check(ViewAssertions.doesNotExist());
|
||||
@ -47,14 +71,12 @@ public abstract class AbstractEndToEndTest<T extends Activity> extends ActivityI
|
||||
* The view doesn't NOT exist == the view exists, and needs to be bypassed!
|
||||
*/
|
||||
Log.d(getClass().getName(), "Bypassing welcome");
|
||||
new AccountSetupFlow(this).setupAccountFromWelcomePage(new WelcomeMessagePage());
|
||||
new AccountSetupFlow().setupAccountFromWelcomePage(new WelcomeMessagePage());
|
||||
}
|
||||
}
|
||||
|
||||
protected StubMailServer setupMailServer() {
|
||||
if (null == state.stubMailServer) {
|
||||
state.stubMailServer = new StubMailServer();
|
||||
}
|
||||
return state.stubMailServer;
|
||||
|
||||
public void testEmpty() {
|
||||
// workaround, needs to be empty so that JUnit4 test gets picked up
|
||||
}
|
||||
}
|
||||
|
@ -24,12 +24,6 @@ public class AccountSetupFlow {
|
||||
|
||||
static final String ACCOUNT_NAME = "sendAndReceiveTestName";
|
||||
|
||||
private final AbstractEndToEndTest test;
|
||||
|
||||
public AccountSetupFlow(AbstractEndToEndTest test) {
|
||||
this.test = test;
|
||||
}
|
||||
|
||||
public AccountsPage setupAccountFromWelcomePage(WelcomeMessagePage welcomeMessagePage) {
|
||||
AccountSetupPage accountSetupPage = welcomeMessagePage.clickNext();
|
||||
return setupAccountFromSetupNewAccountActivity(accountSetupPage);
|
||||
@ -45,7 +39,8 @@ public class AccountSetupFlow {
|
||||
|
||||
IncomingServerSettingsPage incoming = accountTypePage.clickImap();
|
||||
|
||||
StubMailServer stubMailServer = test.setupMailServer();
|
||||
|
||||
StubMailServer stubMailServer = ApplicationState.getInstance().stubMailServer;
|
||||
|
||||
OutgoingServerSettingsPage outgoing = setupIncomingServerAndClickNext(incoming, stubMailServer);
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
package com.fsck.k9.endtoend.framework;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.fsck.k9.K9;
|
||||
import com.icegreen.greenmail.user.GreenMailUser;
|
||||
import com.icegreen.greenmail.util.GreenMail;
|
||||
import com.icegreen.greenmail.util.ServerSetup;
|
||||
|
||||
@ -18,7 +22,18 @@ public class StubMailServer {
|
||||
public StubMailServer() {
|
||||
|
||||
greenmail = new GreenMail(new ServerSetup[]{IMAP_SERVER_SETUP, SMTP_SERVER_SETUP});
|
||||
greenmail.setUser(UserForImap.TEST_USER.emailAddress, UserForImap.TEST_USER.loginUsername, UserForImap.TEST_USER.password);
|
||||
GreenMailUser user = greenmail
|
||||
.setUser(UserForImap.TEST_USER.emailAddress, UserForImap.TEST_USER.loginUsername,
|
||||
UserForImap.TEST_USER.password);
|
||||
|
||||
for (String mailbox : new String[] {"Drafts", "Spam"}) {
|
||||
Log.d(K9.LOG_TAG, "creating mailbox "+mailbox);
|
||||
try {
|
||||
greenmail.getManagers().getImapHostManager().createMailbox(user, mailbox);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
greenmail.start();
|
||||
}
|
||||
|
||||
@ -37,5 +52,9 @@ public class StubMailServer {
|
||||
public int getImapPort() {
|
||||
return IMAP_SERVER_SETUP.getPort();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
greenmail.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
package com.fsck.k9.endtoend.pages;
|
||||
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import android.support.test.espresso.NoMatchingViewException;
|
||||
import android.support.test.espresso.matcher.ViewMatchers;
|
||||
import android.util.Log;
|
||||
|
||||
import static android.support.test.espresso.Espresso.onView;
|
||||
import static android.support.test.espresso.action.ViewActions.clearText;
|
||||
@ -41,6 +43,7 @@ public class AccountSetupNamesPage extends AbstractPage {
|
||||
try {
|
||||
onView(ViewMatchers.withText("OK")).perform(click());
|
||||
} catch (NoMatchingViewException ex) {
|
||||
Log.w(K9.LOG_TAG, "did not find Changelog OK button - ignored");
|
||||
// Ignored. Not the best way of doing this, but Espresso rightly makes
|
||||
// conditional flow difficult.
|
||||
}
|
||||
|
@ -1,27 +1,37 @@
|
||||
package com.fsck.k9.helper;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import java.lang.String;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
public class FileHelperTest extends TestCase {
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class FileHelperTest {
|
||||
|
||||
@Test
|
||||
public void testSanitize1() {
|
||||
checkSanitization(".._bla_", "../bla_");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSanitize2() {
|
||||
checkSanitization("_etc_bla", "/etc/bla");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSanitize3() {
|
||||
checkSanitization("_пPп", "+пPп");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSanitize4() {
|
||||
checkSanitization(".東京_!", ".東京?!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSanitize5() {
|
||||
checkSanitization("Plan 9", "Plan 9");
|
||||
}
|
||||
|
@ -1,16 +1,24 @@
|
||||
package com.fsck.k9.helper;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
|
||||
public class HtmlConverterTest extends TestCase {
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class HtmlConverterTest {
|
||||
// Useful if you want to write stuff to a file for debugging in a browser.
|
||||
private static final boolean WRITE_TO_FILE = Boolean.parseBoolean(System.getProperty("k9.htmlConverterTest.writeToFile", "false"));
|
||||
private static final String OUTPUT_FILE = "C:/temp/parse.html";
|
||||
|
||||
@Test
|
||||
public void testTextQuoteToHtmlBlockquote() {
|
||||
String message = "Panama!\r\n" +
|
||||
"\r\n" +
|
||||
@ -29,25 +37,30 @@ public class HtmlConverterTest extends TestCase {
|
||||
+ "Panama!<br />"
|
||||
+ "<br />"
|
||||
+ "Bob Barker <bob@aol.com> wrote:<br />"
|
||||
+ "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #729fcf; padding-left: 1ex;\">"
|
||||
+
|
||||
"<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #729fcf; padding-left: 1ex;\">"
|
||||
+ " a canal<br />"
|
||||
+ "<br />"
|
||||
+ " Dorothy Jo Gideon <dorothy@aol.com> espoused:<br />"
|
||||
+ "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #ad7fa8; padding-left: 1ex;\">"
|
||||
+
|
||||
"<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #ad7fa8; padding-left: 1ex;\">"
|
||||
+ "A man, a plan...<br />"
|
||||
+ "</blockquote>"
|
||||
+ " Too easy!<br />"
|
||||
+ "</blockquote>"
|
||||
+ "<br />"
|
||||
+ "Nice job :)<br />"
|
||||
+ "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #729fcf; padding-left: 1ex;\">"
|
||||
+ "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #ad7fa8; padding-left: 1ex;\">"
|
||||
+
|
||||
"<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #729fcf; padding-left: 1ex;\">"
|
||||
+
|
||||
"<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #ad7fa8; padding-left: 1ex;\">"
|
||||
+ " Guess!"
|
||||
+ "</blockquote>"
|
||||
+ "</blockquote>"
|
||||
+ "</pre>", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTextQuoteToHtmlBlockquoteIndented() {
|
||||
String message = "*facepalm*\r\n" +
|
||||
"\r\n" +
|
||||
@ -73,6 +86,7 @@ public class HtmlConverterTest extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQuoteDepthColor() {
|
||||
assertEquals(HtmlConverter.getQuoteColor(1), HtmlConverter.QUOTE_COLOR_LEVEL_1);
|
||||
assertEquals(HtmlConverter.getQuoteColor(2), HtmlConverter.QUOTE_COLOR_LEVEL_2);
|
||||
@ -135,6 +149,7 @@ public class HtmlConverterTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreserveSpacesAtFirst() {
|
||||
String message = "foo\r\n"
|
||||
+ " bar\r\n"
|
||||
@ -148,6 +163,7 @@ public class HtmlConverterTest extends TestCase {
|
||||
+ "</pre>", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreserveSpacesAtFirstForSpecialCharacters() {
|
||||
String message =
|
||||
" \r\n"
|
||||
@ -168,6 +184,7 @@ public class HtmlConverterTest extends TestCase {
|
||||
+ "</pre>", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLinkifyBitcoinAndHttpUri() {
|
||||
String text = "bitcoin:19W6QZkx8SYPG7BBCS7odmWGRxqRph5jFU http://example.com/";
|
||||
|
||||
|
@ -1,21 +1,31 @@
|
||||
package com.fsck.k9.helper;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.text.SpannableString;
|
||||
|
||||
import com.fsck.k9.mail.Address;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
public class MessageHelperTest extends AndroidTestCase {
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class MessageHelperTest {
|
||||
private Contacts contacts;
|
||||
private Contacts mockContacts;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
contacts = new Contacts(getContext());
|
||||
mockContacts = new Contacts(getContext()) {
|
||||
Context context = InstrumentationRegistry.getTargetContext();
|
||||
contacts = new Contacts(context);
|
||||
mockContacts = new Contacts(context) {
|
||||
@Override public String getNameForAddress(String address) {
|
||||
if ("test@testor.com".equals(address)) {
|
||||
return "Tim Testor";
|
||||
@ -26,16 +36,19 @@ public class MessageHelperTest extends AndroidTestCase {
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToFriendlyShowsPersonalPartIfItExists() throws Exception {
|
||||
Address address = new Address("test@testor.com", "Tim Testor");
|
||||
assertEquals("Tim Testor", MessageHelper.toFriendly(address, contacts));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToFriendlyShowsEmailPartIfNoPersonalPartExists() throws Exception {
|
||||
Address address = new Address("test@testor.com");
|
||||
assertEquals("test@testor.com", MessageHelper.toFriendly(address, contacts));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToFriendlyArray() throws Exception {
|
||||
Address address1 = new Address("test@testor.com", "Tim Testor");
|
||||
Address address2 = new Address("foo@bar.com", "Foo Bar");
|
||||
@ -43,11 +56,13 @@ public class MessageHelperTest extends AndroidTestCase {
|
||||
assertEquals("Tim Testor,Foo Bar", MessageHelper.toFriendly(addresses, contacts).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToFriendlyWithContactLookup() throws Exception {
|
||||
Address address = new Address("test@testor.com");
|
||||
assertEquals("Tim Testor", MessageHelper.toFriendly(address, mockContacts).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToFriendlyWithChangeContactColor() throws Exception {
|
||||
Address address = new Address("test@testor.com");
|
||||
CharSequence friendly = MessageHelper.toFriendly(address, mockContacts, true, true, Color.RED);
|
||||
@ -55,6 +70,7 @@ public class MessageHelperTest extends AndroidTestCase {
|
||||
assertEquals("Tim Testor", friendly.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToFriendlyWithoutCorrespondentNames() throws Exception {
|
||||
Address address = new Address("test@testor.com", "Tim Testor");
|
||||
CharSequence friendly = MessageHelper.toFriendly(address, mockContacts, false, false, 0);
|
||||
|
@ -8,12 +8,8 @@ import java.io.OutputStream;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import com.fsck.k9.mail.internet.MimeMessageHelper;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.james.mime4j.codec.Base64InputStream;
|
||||
import org.apache.james.mime4j.util.MimeUtil;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.fsck.k9.mail.Message.RecipientType;
|
||||
import com.fsck.k9.mail.internet.BinaryTempFileBody;
|
||||
@ -22,13 +18,23 @@ import com.fsck.k9.mail.internet.CharsetSupport;
|
||||
import com.fsck.k9.mail.internet.MimeBodyPart;
|
||||
import com.fsck.k9.mail.internet.MimeHeader;
|
||||
import com.fsck.k9.mail.internet.MimeMessage;
|
||||
import com.fsck.k9.mail.internet.MimeMessageHelper;
|
||||
import com.fsck.k9.mail.internet.MimeMultipart;
|
||||
import com.fsck.k9.mail.internet.TextBody;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.james.mime4j.util.MimeUtil;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
public class MessageTest extends AndroidTestCase {
|
||||
@Override
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class MessageTest {
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Tokyo"));
|
||||
}
|
||||
|
||||
@ -272,10 +278,7 @@ public class MessageTest extends AndroidTestCase {
|
||||
|
||||
private int mMimeBoundary;
|
||||
|
||||
public MessageTest() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetSendDateSetsSentDate() throws Exception {
|
||||
Message message = sampleMessage();
|
||||
final int milliseconds = 0;
|
||||
@ -286,23 +289,26 @@ public class MessageTest extends AndroidTestCase {
|
||||
assertEquals(milliseconds, sentDate.getTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetSendDateFormatsHeaderCorrectlyWithCurrentTimeZone() throws Exception {
|
||||
Message message = sampleMessage();
|
||||
message.setSentDate(new Date(0), false);
|
||||
assertEquals("Thu, 01 Jan 1970 09:00:00 +0900", message.getHeader("Date")[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetSendDateFormatsHeaderCorrectlyWithoutTimeZone() throws Exception {
|
||||
Message message = sampleMessage();
|
||||
message.setSentDate(new Date(0), true);
|
||||
assertEquals("Thu, 01 Jan 1970 00:00:00 +0000", message.getHeader("Date")[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessage() throws MessagingException, IOException {
|
||||
MimeMessage message;
|
||||
ByteArrayOutputStream out;
|
||||
|
||||
BinaryTempFileBody.setTempDirectory(getContext().getCacheDir());
|
||||
BinaryTempFileBody.setTempDirectory(InstrumentationRegistry.getTargetContext().getCacheDir());
|
||||
|
||||
mMimeBoundary = 101;
|
||||
message = nestedMessage(nestedMessage(sampleMessage()));
|
||||
|
@ -6,10 +6,13 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.fsck.k9.mail.internet.BinaryTempFileBody;
|
||||
import com.fsck.k9.mail.internet.MimeMessage;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.spongycastle.openpgp.PGPCompressedData;
|
||||
import org.spongycastle.openpgp.PGPException;
|
||||
import org.spongycastle.openpgp.PGPObjectFactory;
|
||||
@ -22,8 +25,11 @@ import org.spongycastle.openpgp.bc.BcPGPObjectFactory;
|
||||
import org.spongycastle.openpgp.bc.BcPGPPublicKeyRingCollection;
|
||||
import org.spongycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider;
|
||||
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
public class PgpMimeMessageTest extends AndroidTestCase {
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class PgpMimeMessageTest {
|
||||
private static final String PUBLIC_KEY = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
|
||||
"Version: GnuPG v1\n" +
|
||||
"\n" +
|
||||
@ -150,6 +156,7 @@ public class PgpMimeMessageTest extends AndroidTestCase {
|
||||
"-----END PGP PUBLIC KEY BLOCK-----\n";
|
||||
|
||||
|
||||
@Test
|
||||
public void testSignedMessage() throws IOException, MessagingException, PGPException {
|
||||
String messageSource = "Date: Mon, 08 Dec 2014 17:44:18 +0100\r\n" +
|
||||
"From: cketti <cketti@googlemail.com>\r\n" +
|
||||
@ -209,7 +216,7 @@ public class PgpMimeMessageTest extends AndroidTestCase {
|
||||
"\r\n" +
|
||||
"--24Bem7EnUI1Ipn9jNXuLgsetqa6wOkIxM--\r\n";
|
||||
|
||||
BinaryTempFileBody.setTempDirectory(getContext().getCacheDir());
|
||||
BinaryTempFileBody.setTempDirectory(InstrumentationRegistry.getTargetContext().getCacheDir());
|
||||
|
||||
InputStream messageInputStream = new ByteArrayInputStream(messageSource.getBytes());
|
||||
MimeMessage message;
|
||||
|
@ -6,14 +6,22 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import com.fsck.k9.mail.internet.BinaryTempFileBody;
|
||||
import com.fsck.k9.mail.internet.MimeMessage;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
|
||||
public class ReconstructMessageTest extends AndroidTestCase {
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ReconstructMessageTest {
|
||||
|
||||
@Test
|
||||
public void testMessage() throws IOException, MessagingException {
|
||||
String messageSource =
|
||||
"From: from@example.com\r\n" +
|
||||
@ -45,7 +53,7 @@ public class ReconstructMessageTest extends AndroidTestCase {
|
||||
"------Boundary--\r\n" +
|
||||
"Hi, I'm the epilogue";
|
||||
|
||||
BinaryTempFileBody.setTempDirectory(getContext().getCacheDir());
|
||||
BinaryTempFileBody.setTempDirectory(InstrumentationRegistry.getTargetContext().getCacheDir());
|
||||
|
||||
InputStream messageInputStream = new ByteArrayInputStream(messageSource.getBytes());
|
||||
MimeMessage message;
|
||||
|
@ -1,18 +1,29 @@
|
||||
package com.fsck.k9.mail.ssl;
|
||||
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
|
||||
/**
|
||||
* Test the functionality of {@link TrustManagerFactory}.
|
||||
*/
|
||||
public class TrustManagerFactoryTest extends AndroidTestCase {
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TrustManagerFactoryTest {
|
||||
public static final String MATCHING_HOST = "k9.example.com";
|
||||
public static final String NOT_MATCHING_HOST = "bla.example.com";
|
||||
public static final int PORT1 = 993;
|
||||
@ -196,15 +207,16 @@ public class TrustManagerFactoryTest extends AndroidTestCase {
|
||||
new ByteArrayInputStream(encodedCert.getBytes()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mKeyStoreFile = File.createTempFile("localKeyStore", null, getContext().getCacheDir());
|
||||
mKeyStoreFile = File.createTempFile("localKeyStore", null,
|
||||
InstrumentationRegistry.getTargetContext().getCacheDir());
|
||||
mKeyStore = LocalKeyStore.getInstance();
|
||||
mKeyStore.setKeyStoreFile(mKeyStoreFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() {
|
||||
@After
|
||||
public void tearDown() {
|
||||
mKeyStoreFile.delete();
|
||||
}
|
||||
|
||||
@ -220,6 +232,7 @@ public class TrustManagerFactoryTest extends AndroidTestCase {
|
||||
* @throws Exception
|
||||
* if anything goes wrong
|
||||
*/
|
||||
@Test
|
||||
public void testDifferentCertificatesOnSameServer() throws Exception {
|
||||
mKeyStore.addCertificate(NOT_MATCHING_HOST, PORT1, mCert1);
|
||||
mKeyStore.addCertificate(NOT_MATCHING_HOST, PORT2, mCert2);
|
||||
@ -230,24 +243,28 @@ public class TrustManagerFactoryTest extends AndroidTestCase {
|
||||
trustManager1.checkServerTrusted(new X509Certificate[] { mCert1 }, "authType");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelfSignedCertificateMatchingHost() throws Exception {
|
||||
mKeyStore.addCertificate(MATCHING_HOST, PORT1, mCert1);
|
||||
X509TrustManager trustManager = TrustManagerFactory.get(MATCHING_HOST, PORT1);
|
||||
trustManager.checkServerTrusted(new X509Certificate[] { mCert1 }, "authType");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelfSignedCertificateNotMatchingHost() throws Exception {
|
||||
mKeyStore.addCertificate(NOT_MATCHING_HOST, PORT1, mCert1);
|
||||
X509TrustManager trustManager = TrustManagerFactory.get(NOT_MATCHING_HOST, PORT1);
|
||||
trustManager.checkServerTrusted(new X509Certificate[] { mCert1 }, "authType");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrongCertificate() throws Exception {
|
||||
mKeyStore.addCertificate(MATCHING_HOST, PORT1, mCert1);
|
||||
X509TrustManager trustManager = TrustManagerFactory.get(MATCHING_HOST, PORT1);
|
||||
assertCertificateRejection(trustManager, new X509Certificate[] { mCert2 });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCertificateOfOtherHost() throws Exception {
|
||||
mKeyStore.addCertificate(MATCHING_HOST, PORT1, mCert1);
|
||||
mKeyStore.addCertificate(MATCHING_HOST, PORT2, mCert2);
|
||||
@ -256,11 +273,13 @@ public class TrustManagerFactoryTest extends AndroidTestCase {
|
||||
assertCertificateRejection(trustManager, new X509Certificate[] { mCert2 });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUntrustedCertificateChain() throws Exception {
|
||||
X509TrustManager trustManager = TrustManagerFactory.get(MATCHING_HOST, PORT1);
|
||||
assertCertificateRejection(trustManager, new X509Certificate[] { mCert3, mCaCert });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocallyTrustedCertificateChain() throws Exception {
|
||||
mKeyStore.addCertificate(MATCHING_HOST, PORT1, mCert3);
|
||||
|
||||
@ -268,6 +287,7 @@ public class TrustManagerFactoryTest extends AndroidTestCase {
|
||||
trustManager.checkServerTrusted(new X509Certificate[] { mCert3, mCaCert }, "authType");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocallyTrustedCertificateChainNotMatchingHost() throws Exception {
|
||||
mKeyStore.addCertificate(NOT_MATCHING_HOST, PORT1, mCert3);
|
||||
|
||||
@ -275,17 +295,20 @@ public class TrustManagerFactoryTest extends AndroidTestCase {
|
||||
trustManager.checkServerTrusted(new X509Certificate[] { mCert3, mCaCert }, "authType");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGloballyTrustedCertificateChain() throws Exception {
|
||||
X509TrustManager trustManager = TrustManagerFactory.get("www.linux.com", PORT1);
|
||||
X509Certificate[] certificates = new X509Certificate[] { mLinuxComCert, mLinuxComFirstParentCert};
|
||||
trustManager.checkServerTrusted(certificates, "authType");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGloballyTrustedCertificateNotMatchingHost() throws Exception {
|
||||
X509TrustManager trustManager = TrustManagerFactory.get(NOT_MATCHING_HOST, PORT1);
|
||||
assertCertificateRejection(trustManager, new X509Certificate[] { mLinuxComCert, mLinuxComFirstParentCert});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGloballyTrustedCertificateNotMatchingHostOverride() throws Exception {
|
||||
mKeyStore.addCertificate(MATCHING_HOST, PORT1, mLinuxComCert);
|
||||
|
||||
@ -306,6 +329,7 @@ public class TrustManagerFactoryTest extends AndroidTestCase {
|
||||
assertFalse("The certificate should have been rejected but wasn't", certificateValid);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeyStoreLoading() throws Exception {
|
||||
mKeyStore.addCertificate(MATCHING_HOST, PORT1, mCert1);
|
||||
mKeyStore.addCertificate(NOT_MATCHING_HOST, PORT2, mCert2);
|
||||
|
@ -0,0 +1,204 @@
|
||||
package com.fsck.k9.mail.store.imap;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.fsck.k9.endtoend.framework.StubMailServer;
|
||||
import com.fsck.k9.endtoend.framework.UserForImap;
|
||||
import com.fsck.k9.mail.AuthType;
|
||||
import com.fsck.k9.mail.AuthenticationFailedException;
|
||||
import com.fsck.k9.mail.ConnectionSecurity;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ImapConnectionTest {
|
||||
private static final String[] CAPABILITIES = new String[] { "IMAP4REV1", "LITERAL+", "QUOTA" };
|
||||
|
||||
private StubMailServer stubMailServer;
|
||||
private ImapConnection connection;
|
||||
private TestImapSettings settings;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
stubMailServer = new StubMailServer();
|
||||
settings = new TestImapSettings(UserForImap.TEST_USER);
|
||||
connection = new ImapConnection(settings, null, null);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
stubMailServer.stop();
|
||||
}
|
||||
|
||||
@Test(expected = MessagingException.class)
|
||||
public void testOpenConnectionWithoutRunningServerThrowsMessagingException() throws Exception {
|
||||
stubMailServer.stop();
|
||||
connection.open();
|
||||
}
|
||||
|
||||
@Test(expected = AuthenticationFailedException.class)
|
||||
public void testOpenConnectionWithWrongCredentialsThrowsAuthenticationFailedException() throws Exception {
|
||||
connection = new ImapConnection(new TestImapSettings("wrong", "password"), null, null);
|
||||
connection.open();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionIsInitiallyClosed() throws Exception {
|
||||
assertFalse(connection.isOpen());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccessfulOpenConnectionTogglesOpenState() throws Exception {
|
||||
connection.open();
|
||||
assertTrue(connection.isOpen());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccessfulOpenAndCloseConnectionTogglesOpenState() throws Exception {
|
||||
connection.open();
|
||||
connection.close();
|
||||
assertFalse(connection.isOpen());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCapabilitiesAreInitiallyEmpty() throws Exception {
|
||||
assertTrue(connection.getCapabilities().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCapabilitiesListGetsParsedCorrectly() throws Exception {
|
||||
connection.open();
|
||||
List<String> capabilities = new ArrayList<String>(connection.getCapabilities());
|
||||
Collections.sort(capabilities);
|
||||
assertArrayEquals(CAPABILITIES, capabilities.toArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasCapabilityChecks() throws Exception {
|
||||
connection.open();
|
||||
for (String capability : CAPABILITIES) {
|
||||
assertTrue(connection.hasCapability(capability));
|
||||
}
|
||||
assertFalse(connection.hasCapability("FROBAZIFCATE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPathPrefixGetsSetCorrectly() throws Exception {
|
||||
connection.open();
|
||||
assertEquals("", settings.getPathPrefix());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPathDelimiterGetsParsedCorrectly() throws Exception {
|
||||
connection.open();
|
||||
assertEquals(".", settings.getPathDelimiter());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCombinedPrefixGetsSetCorrectly() throws Exception {
|
||||
connection.open();
|
||||
assertNull(settings.getCombinedPrefix());
|
||||
}
|
||||
|
||||
private class TestImapSettings implements ImapSettings {
|
||||
private String pathPrefix;
|
||||
private String pathDelimiter;
|
||||
private String username;
|
||||
private String password;
|
||||
private String combinedPrefix;
|
||||
|
||||
public TestImapSettings(UserForImap userForImap) {
|
||||
this(userForImap.loginUsername, userForImap.password);
|
||||
}
|
||||
|
||||
public TestImapSettings(String username, String password) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHost() {
|
||||
return stubMailServer.getImapBindAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPort() {
|
||||
return stubMailServer.getImapPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionSecurity getConnectionSecurity() {
|
||||
return ConnectionSecurity.NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthType getAuthType() {
|
||||
return AuthType.PLAIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientCertificateAlias() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useCompression(int type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPathPrefix() {
|
||||
return pathPrefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPathPrefix(String prefix) {
|
||||
pathPrefix = prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPathDelimiter() {
|
||||
return pathDelimiter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPathDelimiter(String delimiter) {
|
||||
pathDelimiter = delimiter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCombinedPrefix() {
|
||||
return combinedPrefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCombinedPrefix(String prefix) {
|
||||
combinedPrefix = prefix;
|
||||
}
|
||||
}
|
||||
}
|
@ -3,22 +3,30 @@ package com.fsck.k9.mailstore;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.fsck.k9.activity.K9ActivityCommon;
|
||||
import com.fsck.k9.mail.Address;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.Message.RecipientType;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.internet.MimeBodyPart;
|
||||
import com.fsck.k9.mail.internet.MimeMessage;
|
||||
import com.fsck.k9.mail.internet.MimeMessageHelper;
|
||||
import com.fsck.k9.mail.internet.MimeMultipart;
|
||||
import com.fsck.k9.mail.internet.TextBody;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static com.fsck.k9.mailstore.LocalMessageExtractor.extractTextAndAttachments;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
public class LocalMessageExtractorTest extends AndroidTestCase {
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class LocalMessageExtractorTest {
|
||||
|
||||
@Test
|
||||
public void testSimplePlainTextMessage() throws MessagingException {
|
||||
String bodyText = "K-9 Mail rocks :>";
|
||||
|
||||
@ -30,7 +38,7 @@ public class LocalMessageExtractorTest extends AndroidTestCase {
|
||||
MimeMessageHelper.setBody(message, body);
|
||||
|
||||
// Extract text
|
||||
ViewableContainer container = extractTextAndAttachments(getContext(), message);
|
||||
ViewableContainer container = extractTextAndAttachments(InstrumentationRegistry.getTargetContext(), message);
|
||||
|
||||
String expectedText = bodyText;
|
||||
String expectedHtml =
|
||||
@ -42,6 +50,7 @@ public class LocalMessageExtractorTest extends AndroidTestCase {
|
||||
assertEquals(expectedHtml, container.html);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleHtmlMessage() throws MessagingException {
|
||||
String bodyText = "<strong>K-9 Mail</strong> rocks :>";
|
||||
|
||||
@ -54,7 +63,7 @@ public class LocalMessageExtractorTest extends AndroidTestCase {
|
||||
MimeMessageHelper.setBody(message, body);
|
||||
|
||||
// Extract text
|
||||
ViewableContainer container = extractTextAndAttachments(getContext(), message);
|
||||
ViewableContainer container = extractTextAndAttachments(InstrumentationRegistry.getTargetContext(), message);
|
||||
|
||||
String expectedText = "K-9 Mail rocks :>";
|
||||
String expectedHtml =
|
||||
@ -64,6 +73,7 @@ public class LocalMessageExtractorTest extends AndroidTestCase {
|
||||
assertEquals(expectedHtml, container.html);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipartPlainTextMessage() throws MessagingException {
|
||||
String bodyText1 = "text body 1";
|
||||
String bodyText2 = "text body 2";
|
||||
@ -84,7 +94,7 @@ public class LocalMessageExtractorTest extends AndroidTestCase {
|
||||
MimeMessageHelper.setBody(message, multipart);
|
||||
|
||||
// Extract text
|
||||
ViewableContainer container = extractTextAndAttachments(getContext(), message);
|
||||
ViewableContainer container = extractTextAndAttachments(InstrumentationRegistry.getTargetContext(), message);
|
||||
|
||||
String expectedText =
|
||||
bodyText1 + "\r\n\r\n" +
|
||||
@ -105,8 +115,9 @@ public class LocalMessageExtractorTest extends AndroidTestCase {
|
||||
assertEquals(expectedHtml, container.html);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTextPlusRfc822Message() throws MessagingException {
|
||||
K9ActivityCommon.setLanguage(getContext(), "en");
|
||||
K9ActivityCommon.setLanguage(InstrumentationRegistry.getTargetContext(), "en");
|
||||
Locale.setDefault(Locale.US);
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("GMT+01:00"));
|
||||
|
||||
@ -140,7 +151,7 @@ public class LocalMessageExtractorTest extends AndroidTestCase {
|
||||
MimeMessageHelper.setBody(message, multipart);
|
||||
|
||||
// Extract text
|
||||
ViewableContainer container = extractTextAndAttachments(getContext(), message);
|
||||
ViewableContainer container = extractTextAndAttachments(InstrumentationRegistry.getTargetContext(), message);
|
||||
|
||||
String expectedText =
|
||||
bodyText +
|
||||
|
@ -1894,9 +1894,15 @@ public class Account implements BaseAccount, StoreConfig {
|
||||
public void deleteCertificates() {
|
||||
LocalKeyStore localKeyStore = LocalKeyStore.getInstance();
|
||||
|
||||
Uri uri = Uri.parse(getStoreUri());
|
||||
String storeUri = getStoreUri();
|
||||
if (storeUri != null) {
|
||||
Uri uri = Uri.parse(storeUri);
|
||||
localKeyStore.deleteCertificate(uri.getHost(), uri.getPort());
|
||||
uri = Uri.parse(getTransportUri());
|
||||
}
|
||||
String transportUri = getTransportUri();
|
||||
if (transportUri != null) {
|
||||
Uri uri = Uri.parse(transportUri);
|
||||
localKeyStore.deleteCertificate(uri.getHost(), uri.getPort());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,13 +8,12 @@ import android.app.FragmentTransaction;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Process;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
@ -87,7 +86,7 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
||||
setContentView(R.layout.account_setup_check_settings);
|
||||
mMessageView = (TextView)findViewById(R.id.message);
|
||||
mProgressBar = (ProgressBar)findViewById(R.id.progress);
|
||||
((Button)findViewById(R.id.cancel)).setOnClickListener(this);
|
||||
findViewById(R.id.cancel).setOnClickListener(this);
|
||||
|
||||
setMessage(R.string.account_setup_check_settings_retr_info_msg);
|
||||
mProgressBar.setIndeterminate(true);
|
||||
@ -96,82 +95,7 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
||||
mAccount = Preferences.getPreferences(this).getAccount(accountUuid);
|
||||
mDirection = (CheckDirection) getIntent().getSerializableExtra(EXTRA_CHECK_DIRECTION);
|
||||
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
Store store = null;
|
||||
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
|
||||
try {
|
||||
if (mDestroyed) {
|
||||
return;
|
||||
}
|
||||
if (mCanceled) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
final MessagingController ctrl = MessagingController.getInstance(getApplication());
|
||||
ctrl.clearCertificateErrorNotifications(AccountSetupCheckSettings.this,
|
||||
mAccount, mDirection);
|
||||
|
||||
if (mDirection == CheckDirection.INCOMING) {
|
||||
store = mAccount.getRemoteStore();
|
||||
|
||||
if (store instanceof WebDavStore) {
|
||||
setMessage(R.string.account_setup_check_settings_authenticate);
|
||||
} else {
|
||||
setMessage(R.string.account_setup_check_settings_check_incoming_msg);
|
||||
}
|
||||
store.checkSettings();
|
||||
|
||||
if (store instanceof WebDavStore) {
|
||||
setMessage(R.string.account_setup_check_settings_fetch);
|
||||
}
|
||||
MessagingController.getInstance(getApplication()).listFoldersSynchronous(mAccount, true, null);
|
||||
MessagingController.getInstance(getApplication()).synchronizeMailbox(mAccount, mAccount.getInboxFolderName(), null, null);
|
||||
}
|
||||
if (mDestroyed) {
|
||||
return;
|
||||
}
|
||||
if (mCanceled) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
if (mDirection == CheckDirection.OUTGOING) {
|
||||
if (!(mAccount.getRemoteStore() instanceof WebDavStore)) {
|
||||
setMessage(R.string.account_setup_check_settings_check_outgoing_msg);
|
||||
}
|
||||
Transport transport = Transport.getInstance(K9.app, mAccount);
|
||||
transport.close();
|
||||
transport.open();
|
||||
transport.close();
|
||||
}
|
||||
if (mDestroyed) {
|
||||
return;
|
||||
}
|
||||
if (mCanceled) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
} catch (final AuthenticationFailedException afe) {
|
||||
Log.e(K9.LOG_TAG, "Error while testing settings", afe);
|
||||
showErrorDialog(
|
||||
R.string.account_setup_failed_dlg_auth_message_fmt,
|
||||
afe.getMessage() == null ? "" : afe.getMessage());
|
||||
} catch (final CertificateValidationException cve) {
|
||||
handleCertificateValidationException(cve);
|
||||
} catch (final Throwable t) {
|
||||
Log.e(K9.LOG_TAG, "Error while testing settings", t);
|
||||
showErrorDialog(
|
||||
R.string.account_setup_failed_dlg_server_message_fmt,
|
||||
(t.getMessage() == null ? "" : t.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.start();
|
||||
new CheckAccountTask(mAccount).execute(mDirection);
|
||||
}
|
||||
|
||||
private void handleCertificateValidationException(CertificateValidationException cve) {
|
||||
@ -199,15 +123,8 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
||||
}
|
||||
|
||||
private void setMessage(final int resId) {
|
||||
mHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (mDestroyed) {
|
||||
return;
|
||||
}
|
||||
mMessageView.setText(getString(resId));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void acceptKeyDialog(final int msgResId, final CertificateValidationException ex) {
|
||||
mHandler.post(new Runnable() {
|
||||
@ -266,7 +183,7 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
||||
for (List<?> subjectAlternativeName : subjectAlternativeNames) {
|
||||
Integer type = (Integer)subjectAlternativeName.get(0);
|
||||
Object value = subjectAlternativeName.get(1);
|
||||
String name = "";
|
||||
String name;
|
||||
switch (type.intValue()) {
|
||||
case 0:
|
||||
Log.w(K9.LOG_TAG, "SubjectAltName of type OtherName not supported.");
|
||||
@ -473,4 +390,89 @@ public class AccountSetupCheckSettings extends K9Activity implements OnClickList
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
class CheckAccountTask extends AsyncTask<CheckDirection, Integer, Void> {
|
||||
private final Account account;
|
||||
|
||||
CheckAccountTask(Account account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(CheckDirection... params) {
|
||||
final CheckDirection direction = params[0];
|
||||
try {
|
||||
if (mDestroyed) {
|
||||
return null;
|
||||
}
|
||||
if (mCanceled) {
|
||||
finish();
|
||||
return null;
|
||||
}
|
||||
final MessagingController ctrl = MessagingController.getInstance(getApplication());
|
||||
ctrl.clearCertificateErrorNotifications(AccountSetupCheckSettings.this,
|
||||
account, direction);
|
||||
|
||||
if (direction == CheckDirection.INCOMING) {
|
||||
Store store = account.getRemoteStore();
|
||||
if (store instanceof WebDavStore) {
|
||||
publishProgress(R.string.account_setup_check_settings_authenticate);
|
||||
} else {
|
||||
publishProgress(R.string.account_setup_check_settings_check_incoming_msg);
|
||||
}
|
||||
store.checkSettings();
|
||||
|
||||
if (store instanceof WebDavStore) {
|
||||
publishProgress(R.string.account_setup_check_settings_fetch);
|
||||
}
|
||||
MessagingController.getInstance(getApplication()).listFoldersSynchronous(account, true, null);
|
||||
MessagingController.getInstance(getApplication())
|
||||
.synchronizeMailbox(account, account.getInboxFolderName(), null, null);
|
||||
}
|
||||
if (mDestroyed) {
|
||||
return null;
|
||||
}
|
||||
if (mCanceled) {
|
||||
finish();
|
||||
return null;
|
||||
}
|
||||
if (direction == CheckDirection.OUTGOING) {
|
||||
if (!(account.getRemoteStore() instanceof WebDavStore)) {
|
||||
publishProgress(R.string.account_setup_check_settings_check_outgoing_msg);
|
||||
}
|
||||
Transport transport = Transport.getInstance(K9.app, account);
|
||||
transport.close();
|
||||
transport.open();
|
||||
transport.close();
|
||||
}
|
||||
if (mDestroyed) {
|
||||
return null;
|
||||
}
|
||||
if (mCanceled) {
|
||||
finish();
|
||||
return null;
|
||||
}
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
} catch (AuthenticationFailedException afe) {
|
||||
Log.e(K9.LOG_TAG, "Error while testing settings", afe);
|
||||
showErrorDialog(
|
||||
R.string.account_setup_failed_dlg_auth_message_fmt,
|
||||
afe.getMessage() == null ? "" : afe.getMessage());
|
||||
} catch (CertificateValidationException cve) {
|
||||
handleCertificateValidationException(cve);
|
||||
} catch (Throwable t) {
|
||||
Log.e(K9.LOG_TAG, "Error while testing settings", t);
|
||||
showErrorDialog(
|
||||
R.string.account_setup_failed_dlg_server_message_fmt,
|
||||
(t.getMessage() == null ? "" : t.getMessage()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(Integer... values) {
|
||||
setMessage(values[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
54
k9mail/src/main/java/com/fsck/k9/helper/HtmlSanitizer.java
Normal file
54
k9mail/src/main/java/com/fsck/k9/helper/HtmlSanitizer.java
Normal file
@ -0,0 +1,54 @@
|
||||
package com.fsck.k9.helper;
|
||||
|
||||
|
||||
import org.htmlcleaner.CleanerProperties;
|
||||
import org.htmlcleaner.HtmlCleaner;
|
||||
import org.htmlcleaner.HtmlSerializer;
|
||||
import org.htmlcleaner.SimpleHtmlSerializer;
|
||||
import org.htmlcleaner.TagNode;
|
||||
|
||||
|
||||
public class HtmlSanitizer {
|
||||
private static final HtmlCleaner HTML_CLEANER;
|
||||
private static final HtmlSerializer HTML_SERIALIZER;
|
||||
|
||||
static {
|
||||
CleanerProperties properties = createCleanerProperties();
|
||||
HTML_CLEANER = new HtmlCleaner(properties);
|
||||
HTML_SERIALIZER = new SimpleHtmlSerializer(properties);
|
||||
}
|
||||
|
||||
|
||||
private HtmlSanitizer() {}
|
||||
|
||||
public static String sanitize(String html) {
|
||||
TagNode rootNode = HTML_CLEANER.clean(html);
|
||||
|
||||
removeMetaRefresh(rootNode);
|
||||
|
||||
return HTML_SERIALIZER.getAsString(rootNode, "UTF8");
|
||||
}
|
||||
|
||||
private static CleanerProperties createCleanerProperties() {
|
||||
CleanerProperties properties = new CleanerProperties();
|
||||
|
||||
// See http://htmlcleaner.sourceforge.net/parameters.php for descriptions
|
||||
properties.setNamespacesAware(false);
|
||||
properties.setAdvancedXmlEscape(false);
|
||||
properties.setOmitXmlDeclaration(true);
|
||||
properties.setOmitDoctypeDeclaration(false);
|
||||
properties.setTranslateSpecialEntities(false);
|
||||
properties.setRecognizeUnicodeChars(false);
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
private static void removeMetaRefresh(TagNode rootNode) {
|
||||
for (TagNode element : rootNode.getElementListByName("meta", true)) {
|
||||
String httpEquiv = element.getAttributeByName("http-equiv");
|
||||
if (httpEquiv != null && httpEquiv.trim().equalsIgnoreCase("refresh")) {
|
||||
element.removeFromTree();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -11,6 +11,8 @@ import android.widget.Toast;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.helper.HtmlConverter;
|
||||
import com.fsck.k9.helper.HtmlSanitizer;
|
||||
|
||||
|
||||
public class MessageWebView extends RigidWebView {
|
||||
|
||||
@ -123,7 +125,9 @@ public class MessageWebView extends RigidWebView {
|
||||
}
|
||||
content += HtmlConverter.cssStylePre();
|
||||
content += "</head><body>" + text + "</body></html>";
|
||||
loadDataWithBaseURL("http://", content, "text/html", "utf-8", null);
|
||||
|
||||
String sanitizedContent = HtmlSanitizer.sanitize(content);
|
||||
loadDataWithBaseURL("http://", sanitizedContent, "text/html", "utf-8", null);
|
||||
resumeTimers();
|
||||
}
|
||||
|
||||
|
@ -129,6 +129,10 @@
|
||||
<incoming uri="imap+ssl+://imap.gmx.com" username="$email" />
|
||||
<outgoing uri="smtp+ssl+://mail.gmx.com" username="$email" />
|
||||
</provider>
|
||||
<provider id="zoho.com" label="Zoho Mail" domain="zoho.com">
|
||||
<incoming uri="imap+ssl+://imap.zoho.com" username="$email" />
|
||||
<outgoing uri="smtp+tls+://smtp.zoho.com" username="$email" />
|
||||
</provider>
|
||||
|
||||
<!-- Yahoo! Mail Variants -->
|
||||
<provider id="yahoo" label="Yahoo" domain="yahoo.com">
|
||||
|
@ -0,0 +1,94 @@
|
||||
package com.fsck.k9.helper;
|
||||
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
|
||||
public class HtmlSanitizerTest {
|
||||
@Test
|
||||
public void shouldRemoveMetaRefreshInHead() {
|
||||
String html = "<html>" +
|
||||
"<head><meta http-equiv=\"refresh\" content=\"1; URL=http://example.com/\"></head>" +
|
||||
"<body>Message</body>" +
|
||||
"</html>";
|
||||
assertEquals("<html><head></head><body>Message</body></html>", HtmlSanitizer.sanitize(html));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveMetaRefreshBetweenHeadAndBody() {
|
||||
String html = "<html>" +
|
||||
"<head></head><meta http-equiv=\"refresh\" content=\"1; URL=http://example.com/\">" +
|
||||
"<body>Message</body>" +
|
||||
"</html>";
|
||||
assertEquals("<html><head></head><body>Message</body></html>", HtmlSanitizer.sanitize(html));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveMetaRefreshInBody() {
|
||||
String html = "<html>" +
|
||||
"<head></head>" +
|
||||
"<body><meta http-equiv=\"refresh\" content=\"1; URL=http://example.com/\">Message</body>" +
|
||||
"</html>";
|
||||
assertEquals("<html><head></head><body>Message</body></html>", HtmlSanitizer.sanitize(html));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveMetaRefreshWithUpperCaseAttributeValue() {
|
||||
String html = "<html>" +
|
||||
"<head><meta http-equiv=\"REFRESH\" content=\"1; URL=http://example.com/\"></head>" +
|
||||
"<body>Message</body>" +
|
||||
"</html>";
|
||||
assertEquals("<html><head></head><body>Message</body></html>", HtmlSanitizer.sanitize(html));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveMetaRefreshWithMixedCaseAttributeValue() {
|
||||
String html = "<html>" +
|
||||
"<head><meta http-equiv=\"Refresh\" content=\"1; URL=http://example.com/\"></head>" +
|
||||
"<body>Message</body>" +
|
||||
"</html>";
|
||||
assertEquals("<html><head></head><body>Message</body></html>", HtmlSanitizer.sanitize(html));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveMetaRefreshWithoutQuotesAroundAttributeValue() {
|
||||
String html = "<html>" +
|
||||
"<head><meta http-equiv=refresh content=\"1; URL=http://example.com/\"></head>" +
|
||||
"<body>Message</body>" +
|
||||
"</html>";
|
||||
assertEquals("<html><head></head><body>Message</body></html>", HtmlSanitizer.sanitize(html));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveMetaRefreshWithSpacesInAttributeValue() {
|
||||
String html = "<html>" +
|
||||
"<head><meta http-equiv=\"refresh \" content=\"1; URL=http://example.com/\"></head>" +
|
||||
"<body>Message</body>" +
|
||||
"</html>";
|
||||
assertEquals("<html><head></head><body>Message</body></html>", HtmlSanitizer.sanitize(html));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveMultipleMetaRefreshTags() {
|
||||
String html = "<html>" +
|
||||
"<head><meta http-equiv=\"refresh\" content=\"1; URL=http://example.com/\"></head>" +
|
||||
"<body><meta http-equiv=\"refresh\" content=\"1; URL=http://example.com/\">Message</body>" +
|
||||
"</html>";
|
||||
assertEquals("<html><head></head><body>Message</body></html>", HtmlSanitizer.sanitize(html));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveMetaRefreshButKeepOtherMetaTags() {
|
||||
String html = "<html>" +
|
||||
"<head>" +
|
||||
"<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">" +
|
||||
"<meta http-equiv=\"refresh\" content=\"1; URL=http://example.com/\">" +
|
||||
"</head>" +
|
||||
"<body>Message</body>" +
|
||||
"</html>";
|
||||
assertEquals("<html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\" /></head>" +
|
||||
"<body>Message</body></html>", HtmlSanitizer.sanitize(html));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user