Merge pull request #3965 from k9mail/cleanup_ProvidersXmlDiscovery
Clean up ProvidersXmlDiscovery
This commit is contained in:
commit
57062fd558
5 changed files with 168 additions and 147 deletions
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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?
|
||||||
|
)
|
||||||
|
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
15
app/core/src/main/java/com/fsck/k9/helper/EmailHelper.kt
Normal file
15
app/core/src/main/java/com/fsck/k9/helper/EmailHelper.kt
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,4 +28,39 @@ public class EmailHelperTest {
|
||||||
|
|
||||||
assertEquals("domain", result);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue