Merge pull request #3965 from k9mail/cleanup_ProvidersXmlDiscovery

Clean up ProvidersXmlDiscovery
This commit is contained in:
cketti 2019-03-20 17:13:23 +01:00 committed by GitHub
commit 57062fd558
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 168 additions and 147 deletions

View file

@ -1,132 +0,0 @@
package com.fsck.k9.autodiscovery.providersxml;
import java.net.URI;
import java.net.URISyntaxException;
import android.content.res.XmlResourceParser;
import com.fsck.k9.autodiscovery.ConnectionSettings;
import com.fsck.k9.autodiscovery.ConnectionSettingsDiscovery;
import com.fsck.k9.backend.BackendManager;
import com.fsck.k9.helper.UrlEncodingHelper;
import com.fsck.k9.mail.ServerSettings;
import org.xmlpull.v1.XmlPullParser;
import timber.log.Timber;
public class ProvidersXmlDiscovery implements ConnectionSettingsDiscovery {
private final BackendManager backendManager;
private final ProvidersXmlProvider xmlProvider;
public ProvidersXmlDiscovery(BackendManager backendManager, ProvidersXmlProvider xmlProvider) {
this.backendManager = backendManager;
this.xmlProvider = xmlProvider;
}
private String[] splitEmail(String email) {
String[] retParts = new String[2];
String[] emailParts = email.split("@");
retParts[0] = (emailParts.length > 0) ? emailParts[0] : "";
retParts[1] = (emailParts.length > 1) ? emailParts[1] : "";
return retParts;
}
@Override
public ConnectionSettings discover(String email) {
String password = "";
String[] emailParts = splitEmail(email);
String user = emailParts[0];
String domain = emailParts[1];
Provider mProvider = findProviderForDomain(domain);
if (mProvider == null) {
return null;
}
try {
String userEnc = UrlEncodingHelper.encodeUtf8(user);
String passwordEnc = UrlEncodingHelper.encodeUtf8(password);
String incomingUsername = mProvider.incomingUsernameTemplate;
incomingUsername = incomingUsername.replaceAll("\\$email", email);
incomingUsername = incomingUsername.replaceAll("\\$user", userEnc);
incomingUsername = incomingUsername.replaceAll("\\$domain", domain);
URI incomingUriTemplate = mProvider.incomingUriTemplate;
URI incomingUri = new URI(incomingUriTemplate.getScheme(), incomingUsername + ":" + passwordEnc,
incomingUriTemplate.getHost(), incomingUriTemplate.getPort(), null, null, null);
String outgoingUsername = mProvider.outgoingUsernameTemplate;
URI outgoingUriTemplate = mProvider.outgoingUriTemplate;
URI outgoingUri;
if (outgoingUsername != null) {
outgoingUsername = outgoingUsername.replaceAll("\\$email", email);
outgoingUsername = outgoingUsername.replaceAll("\\$user", userEnc);
outgoingUsername = outgoingUsername.replaceAll("\\$domain", domain);
outgoingUri = new URI(outgoingUriTemplate.getScheme(), outgoingUsername + ":"
+ passwordEnc, outgoingUriTemplate.getHost(), outgoingUriTemplate.getPort(), null,
null, null);
} else {
outgoingUri = new URI(outgoingUriTemplate.getScheme(),
null, outgoingUriTemplate.getHost(), outgoingUriTemplate.getPort(), null,
null, null);
}
ServerSettings incomingSettings = backendManager.decodeStoreUri(incomingUri.toString());
ServerSettings outgoingSettings = backendManager.decodeTransportUri(outgoingUri.toString());
return new ConnectionSettings(incomingSettings, outgoingSettings);
} catch (URISyntaxException use) {
return null;
}
}
private Provider findProviderForDomain(String domain) {
try {
XmlResourceParser xml = xmlProvider.getXml();
int xmlEventType;
Provider provider = null;
while ((xmlEventType = xml.next()) != XmlPullParser.END_DOCUMENT) {
if (xmlEventType == XmlPullParser.START_TAG &&
"provider".equals(xml.getName()) &&
domain.equalsIgnoreCase(xml.getAttributeValue(null, "domain"))) {
provider = new Provider();
provider.id = xml.getAttributeValue(null, "id");
provider.label = xml.getAttributeValue(null, "label");
provider.domain = xml.getAttributeValue(null, "domain");
} else if (xmlEventType == XmlPullParser.START_TAG &&
"incoming".equals(xml.getName()) &&
provider != null) {
provider.incomingUriTemplate = new URI(xml.getAttributeValue(null, "uri"));
provider.incomingUsernameTemplate = xml.getAttributeValue(null, "username");
} else if (xmlEventType == XmlPullParser.START_TAG &&
"outgoing".equals(xml.getName()) &&
provider != null) {
provider.outgoingUriTemplate = new URI(xml.getAttributeValue(null, "uri"));
provider.outgoingUsernameTemplate = xml.getAttributeValue(null, "username");
} else if (xmlEventType == XmlPullParser.END_TAG &&
"provider".equals(xml.getName()) &&
provider != null) {
return provider;
}
}
} catch (Exception e) {
Timber.e(e, "Error while trying to load provider settings.");
}
return null;
}
static class Provider {
String id;
String label;
String domain;
URI incomingUriTemplate;
String incomingUsernameTemplate;
URI outgoingUriTemplate;
String outgoingUsernameTemplate;
}
}

View file

@ -0,0 +1,118 @@
package com.fsck.k9.autodiscovery.providersxml
import android.content.res.XmlResourceParser
import com.fsck.k9.autodiscovery.ConnectionSettings
import com.fsck.k9.autodiscovery.ConnectionSettingsDiscovery
import com.fsck.k9.backend.BackendManager
import com.fsck.k9.helper.EmailHelper
import com.fsck.k9.helper.UrlEncodingHelper
import org.xmlpull.v1.XmlPullParser
import timber.log.Timber
import java.net.URI
import java.net.URISyntaxException
class ProvidersXmlDiscovery(
private val backendManager: BackendManager,
private val xmlProvider: ProvidersXmlProvider
) : ConnectionSettingsDiscovery {
override fun discover(email: String): ConnectionSettings? {
val password = ""
val user = EmailHelper.getLocalPartFromEmailAddress(email) ?: return null
val domain = EmailHelper.getDomainFromEmailAddress(email) ?: return null
val provider = findProviderForDomain(domain) ?: return null
try {
val userUrlEncoded = UrlEncodingHelper.encodeUtf8(user)
val emailUrlEncoded = UrlEncodingHelper.encodeUtf8(email)
val incomingUserUrlEncoded = provider.incomingUsernameTemplate
.replace("\$email", emailUrlEncoded)
.replace("\$user", userUrlEncoded)
.replace("\$domain", domain)
val incomingUri = with(URI(provider.incomingUriTemplate)) {
URI(scheme, "$incomingUserUrlEncoded:$password", host, port, null, null, null).toString()
}
val incomingSettings = backendManager.decodeStoreUri(incomingUri)
val outgoingUserUrlEncoded = provider.outgoingUsernameTemplate
?.replace("\$email", emailUrlEncoded)
?.replace("\$user", userUrlEncoded)
?.replace("\$domain", domain)
val outgoingUserInfo = if (outgoingUserUrlEncoded != null) "$outgoingUserUrlEncoded:$password" else null
val outgoingUri = with(URI(provider.outgoingUriTemplate)) {
URI(scheme, outgoingUserInfo, host, port, null, null, null).toString()
}
val outgoingSettings = backendManager.decodeTransportUri(outgoingUri)
return ConnectionSettings(incomingSettings, outgoingSettings)
} catch (use: URISyntaxException) {
return null
}
}
private fun findProviderForDomain(domain: String): Provider? {
return try {
xmlProvider.getXml().use { xml ->
parseProviders(xml, domain)
}
} catch (e: Exception) {
Timber.e(e, "Error while trying to load provider settings.")
null
}
}
private fun parseProviders(xml: XmlResourceParser, domain: String): Provider? {
do {
val xmlEventType = xml.next()
if (xmlEventType == XmlPullParser.START_TAG && xml.name == "provider") {
val providerDomain = xml.getAttributeValue(null, "domain")
if (domain.equals(providerDomain, ignoreCase = true)) {
val provider = parseProvider(xml)
if (provider != null) return provider
}
}
} while (xmlEventType != XmlPullParser.END_DOCUMENT)
return null
}
private fun parseProvider(xml: XmlResourceParser): Provider? {
var incomingUriTemplate: String? = null
var incomingUsernameTemplate: String? = null
var outgoingUriTemplate: String? = null
var outgoingUsernameTemplate: String? = null
do {
val xmlEventType = xml.next()
if (xmlEventType == XmlPullParser.START_TAG) {
when (xml.name) {
"incoming" -> {
incomingUriTemplate = xml.getAttributeValue(null, "uri")
incomingUsernameTemplate = xml.getAttributeValue(null, "username")
}
"outgoing" -> {
outgoingUriTemplate = xml.getAttributeValue(null, "uri")
outgoingUsernameTemplate = xml.getAttributeValue(null, "username")
}
}
}
} while (!(xmlEventType == XmlPullParser.END_TAG && xml.name == "provider"))
return if (incomingUriTemplate != null && incomingUsernameTemplate != null &&
outgoingUriTemplate != null) {
Provider(incomingUriTemplate, incomingUsernameTemplate, outgoingUriTemplate, outgoingUsernameTemplate)
} else {
null
}
}
internal data class Provider(
val incomingUriTemplate: String,
val incomingUsernameTemplate: String,
val outgoingUriTemplate: String,
val outgoingUsernameTemplate: String?
)
}

View file

@ -1,15 +0,0 @@
package com.fsck.k9.helper;
public final class EmailHelper {
private EmailHelper() {}
public static String getDomainFromEmailAddress(String email) {
int separatorIndex = email.lastIndexOf('@');
if (separatorIndex == -1 || separatorIndex + 1 == email.length()) {
return null;
}
return email.substring(separatorIndex + 1);
}
}

View file

@ -0,0 +1,15 @@
package com.fsck.k9.helper
object EmailHelper {
@JvmStatic
fun getLocalPartFromEmailAddress(email: String): String? {
val index = email.lastIndexOf('@')
return if (index == -1 || index == email.lastIndex) null else email.substring(0, index)
}
@JvmStatic
fun getDomainFromEmailAddress(email: String): String? {
val index = email.lastIndexOf('@')
return if (index == -1 || index == email.lastIndex) null else email.substring(index + 1)
}
}

View file

@ -28,4 +28,39 @@ public class EmailHelperTest {
assertEquals("domain", result);
}
@Test
public void getDomainFromEmailAddress_withEmptyDomain_shouldReturnNull() {
String result = EmailHelper.getDomainFromEmailAddress("user@");
assertNull(result);
}
@Test
public void getLocalPartFromEmailAddress_withRegularEmail_shouldReturnLocalPart() {
String result = EmailHelper.getLocalPartFromEmailAddress("user@domain.com");
assertEquals("user", result);
}
@Test
public void getLocalPartFromEmailAddress_withAtInLocalPart_shouldReturnLocalPart() {
String result = EmailHelper.getLocalPartFromEmailAddress("\"user@work\"@domain");
assertEquals("\"user@work\"", result);
}
@Test
public void getLocalPartFromEmailAddress_withInvalidEmail_shouldReturnNull() {
String result = EmailHelper.getLocalPartFromEmailAddress("user");
assertNull(result);
}
@Test
public void getLocalPartFromEmailAddress_withEmptyDomain_shouldReturnNull() {
String result = EmailHelper.getLocalPartFromEmailAddress("user@");
assertNull(result);
}
}