From 08534762bdded437a7fa0e5e422d311c414e0621 Mon Sep 17 00:00:00 2001 From: Todd Kennedy Date: Mon, 28 Mar 2011 16:21:15 -0700 Subject: [PATCH] Allow globals in the providers.xml We now allow a single global character ['*'] to be specified somewhere in the domain attribute. Additionally, we will replace the string "$domain" with the matched domain in all attributes -- user name, password and URIs. bug 4090086 Change-Id: I46a637ed364c1a079e1230fa22393a1bac059b1f --- res/xml/providers.xml | 216 +----------------- .../activity/setup/AccountSettingsUtils.java | 81 ++++++- .../activity/setup/AccountSetupBasics.java | 23 +- tests/res/xml/test_providers.xml | 64 ++++++ .../setup/AccountSettingsUtilsTests.java | 162 +++++++++++++ 5 files changed, 306 insertions(+), 240 deletions(-) create mode 100644 tests/res/xml/test_providers.xml diff --git a/res/xml/providers.xml b/res/xml/providers.xml index 8a92f0b7d..ed8637125 100644 --- a/res/xml/providers.xml +++ b/res/xml/providers.xml @@ -233,220 +233,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/src/com/android/email/activity/setup/AccountSettingsUtils.java b/src/com/android/email/activity/setup/AccountSettingsUtils.java index 0634fd26c..99fff64ba 100644 --- a/src/com/android/email/activity/setup/AccountSettingsUtils.java +++ b/src/com/android/email/activity/setup/AccountSettingsUtils.java @@ -31,7 +31,6 @@ import android.util.Log; import android.widget.EditText; import java.io.Serializable; -import java.net.URI; public class AccountSettingsUtils { @@ -101,20 +100,28 @@ public class AccountSettingsUtils { * @param resourceId Id of the provider resource to scan * @return suitable Provider definition, or null if no match found */ - private static Provider findProviderForDomain(Context context, String domain, int resourceId) { + /*package*/ static Provider findProviderForDomain( + Context context, String domain, int resourceId) { try { XmlResourceParser xml = context.getResources().getXml(resourceId); int xmlEventType; Provider provider = null; while ((xmlEventType = xml.next()) != XmlResourceParser.END_DOCUMENT) { if (xmlEventType == XmlResourceParser.START_TAG - && "provider".equals(xml.getName()) - && domain.equalsIgnoreCase(getXmlAttribute(context, xml, "domain"))) { - provider = new Provider(); - provider.id = getXmlAttribute(context, xml, "id"); - provider.label = getXmlAttribute(context, xml, "label"); - provider.domain = getXmlAttribute(context, xml, "domain"); - provider.note = getXmlAttribute(context, xml, "note"); + && "provider".equals(xml.getName())) { + String providerDomain = getXmlAttribute(context, xml, "domain"); + try { + if (globMatchIgnoreCase(domain, providerDomain)) { + provider = new Provider(); + provider.id = getXmlAttribute(context, xml, "id"); + provider.label = getXmlAttribute(context, xml, "label"); + provider.domain = domain.toLowerCase(); + provider.note = getXmlAttribute(context, xml, "note"); + } + } catch (IllegalArgumentException e) { + Log.w(Logging.LOG_TAG, "providers line: " + xml.getLineNumber() + + "; Domain contains multiple globals"); + } } else if (xmlEventType == XmlResourceParser.START_TAG && "incoming".equals(xml.getName()) @@ -141,6 +148,42 @@ public class AccountSettingsUtils { return null; } + /** + * Compares the two strings. glob may have at most a single global character ('*') that + * will match any number of characters in the input string. + * @return true if the strings match. otherwise, false. + * @throws IllegalArgumentException if the strings are null or glob has multiple globals. + */ + /*package*/ static boolean globMatchIgnoreCase(String in, String glob) + throws IllegalArgumentException { + if (in == null || glob == null) { + throw new IllegalArgumentException("one or both strings are null"); + } + + // Handle the possible global in the domain name + String[] globParts = glob.split("\\*"); + String inLower = in.toLowerCase(); + switch (globParts.length) { + case 1: + // No globals; test for simple equality + if (!inLower.equals(globParts[0].toLowerCase())) { + return false; + } + break; + case 2: + // Global; test the front & end parts of the domain + String d1 = globParts[0].toLowerCase(); + String d2 = globParts[1].toLowerCase(); + if (!inLower.startsWith(d1) || !inLower.substring(d1.length()).endsWith(d2)) { + return false; + } + break; + default: + throw new IllegalArgumentException("Multiple globals"); + } + return true; + } + /** * Attempts to get the given attribute as a String resource first, and if it fails * returns the attribute as a simple String value. @@ -168,7 +211,27 @@ public class AccountSettingsUtils { public String incomingUsernameTemplate; public String outgoingUriTemplate; public String outgoingUsernameTemplate; + public String incomingUri; + public String incomingUsername; + public String outgoingUri; + public String outgoingUsername; public String note; + public void expandTemplates(String email) { + String[] emailParts = email.split("@"); + String user = emailParts[0]; + + incomingUri = expandTemplate(incomingUriTemplate, email, user); + incomingUsername = expandTemplate(incomingUsernameTemplate, email, user); + outgoingUri = expandTemplate(outgoingUriTemplate, email, user); + outgoingUsername = expandTemplate(outgoingUsernameTemplate, email, user); + } + private String expandTemplate(String template, String email, String user) { + String returnString = template; + returnString = returnString.replaceAll("\\$email", email); + returnString = returnString.replaceAll("\\$user", user); + returnString = returnString.replaceAll("\\$domain", domain); + return returnString; + } } /** diff --git a/src/com/android/email/activity/setup/AccountSetupBasics.java b/src/com/android/email/activity/setup/AccountSetupBasics.java index 01bf180c5..bd40f19cb 100644 --- a/src/com/android/email/activity/setup/AccountSetupBasics.java +++ b/src/com/android/email/activity/setup/AccountSetupBasics.java @@ -418,36 +418,25 @@ public class AccountSetupBasics extends AccountSetupActivity private void finishAutoSetup() { String email = mEmailView.getText().toString().trim(); String password = mPasswordView.getText().toString(); - String[] emailParts = email.split("@"); - String user = emailParts[0]; - String domain = emailParts[1]; try { - String incomingUsername = mProvider.incomingUsernameTemplate; - incomingUsername = incomingUsername.replaceAll("\\$email", email); - incomingUsername = incomingUsername.replaceAll("\\$user", user); - incomingUsername = incomingUsername.replaceAll("\\$domain", domain); + mProvider.expandTemplates(email); Account account = SetupData.getAccount(); HostAuth recvAuth = account.getOrCreateHostAuthRecv(this); - Utility.setHostAuthFromString(recvAuth, mProvider.incomingUriTemplate); - recvAuth.setLogin(incomingUsername, password); - - String outgoingUsername = mProvider.outgoingUsernameTemplate; - outgoingUsername = outgoingUsername.replaceAll("\\$email", email); - outgoingUsername = outgoingUsername.replaceAll("\\$user", user); - outgoingUsername = outgoingUsername.replaceAll("\\$domain", domain); + Utility.setHostAuthFromString(recvAuth, mProvider.incomingUri); + recvAuth.setLogin(mProvider.incomingUsername, password); HostAuth sendAuth = account.getOrCreateHostAuthSend(this); - Utility.setHostAuthFromString(sendAuth, mProvider.outgoingUriTemplate); - sendAuth.setLogin(outgoingUsername, password); + Utility.setHostAuthFromString(sendAuth, mProvider.outgoingUri); + sendAuth.setLogin(mProvider.outgoingUsername, password); // Populate the setup data, assuming that the duplicate account check will succeed populateSetupData(getOwnerName(), email, mDefaultView.isChecked()); // Stop here if the login credentials duplicate an existing account // Launch an Async task to do the work - new DuplicateCheckTask(this, recvAuth.mAddress, incomingUsername).execute(); + new DuplicateCheckTask(this, recvAuth.mAddress, mProvider.incomingUsername).execute(); } catch (URISyntaxException e) { /* * If there is some problem with the URI we give up and go on to manual setup. diff --git a/tests/res/xml/test_providers.xml b/tests/res/xml/test_providers.xml new file mode 100644 index 000000000..02642026e --- /dev/null +++ b/tests/res/xml/test_providers.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/src/com/android/email/activity/setup/AccountSettingsUtilsTests.java b/tests/src/com/android/email/activity/setup/AccountSettingsUtilsTests.java index 90282b3f4..86a4fb192 100644 --- a/tests/src/com/android/email/activity/setup/AccountSettingsUtilsTests.java +++ b/tests/src/com/android/email/activity/setup/AccountSettingsUtilsTests.java @@ -16,6 +16,10 @@ package com.android.email.activity.setup; +import com.android.email.tests.R; +import com.android.email.activity.setup.AccountSettingsUtils.Provider; + +import android.content.Context; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; @@ -28,6 +32,14 @@ import android.test.suitebuilder.annotation.SmallTest; @SmallTest public class AccountSettingsUtilsTests extends AndroidTestCase { + private Context mTestContext; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mTestContext = getTestContext(); + } + /** * Test server name inferences * @@ -51,4 +63,154 @@ public class AccountSettingsUtilsTests extends AndroidTestCase { assertEquals("MaiL.y.z", AccountSettingsUtils.inferServerName("MaiL.y.z", null, "bar")); } + public void testFindProviderForDomain() { + Provider testProvider; + // + // + // + // + testProvider = AccountSettingsUtils.findProviderForDomain( + mTestContext, "gmail.com", R.xml.test_providers); + assertNotNull(testProvider); + assertEquals("imap+ssl+://imap.gmail.com", testProvider.incomingUriTemplate); + assertEquals("smtp+ssl+://smtp.gmail.com", testProvider.outgoingUriTemplate); + assertEquals("gmail.com", testProvider.domain); + + // + // + // + // + testProvider = AccountSettingsUtils.findProviderForDomain( + mTestContext, "elmore.rr.com", R.xml.test_providers); + assertNotNull(testProvider); + assertEquals("pop3://pop-server.$domain", testProvider.incomingUriTemplate); + assertEquals("smtp://mobile-smtp.roadrunner.com", testProvider.outgoingUriTemplate); + assertEquals("elmore.rr.com", testProvider.domain); + + // Domain matches 2 providers; first one wins + testProvider = AccountSettingsUtils.findProviderForDomain( + mTestContext, "leonard.rr.com", R.xml.test_providers); + assertNotNull(testProvider); + assertEquals("pop3://pop-server.firstonewins.com", testProvider.incomingUriTemplate); + + // Domains that don't exist + testProvider = AccountSettingsUtils.findProviderForDomain( + mTestContext, "nonexist.com", R.xml.test_providers); + assertNull(testProvider); + } + + public void testGlobMatchIgnoreCase() { + boolean testMatch; + + assertTrue(AccountSettingsUtils.globMatchIgnoreCase( + "mail.yahoo.com", "mail*yahoo.com")); + assertTrue(AccountSettingsUtils.globMatchIgnoreCase( + "mail.foo.bar.yahoo.com", "mail*yahoo.com")); + assertTrue(AccountSettingsUtils.globMatchIgnoreCase( + "mail.notwhatyouwant.myyahoo.com", "mail*yahoo.com")); + + // Test other combinations + assertTrue(AccountSettingsUtils.globMatchIgnoreCase( + "yahoo.com", "yahoo.com")); + assertFalse(AccountSettingsUtils.globMatchIgnoreCase( + "yahoo.com.au", "yahoo.com")); + assertFalse(AccountSettingsUtils.globMatchIgnoreCase( + "yahoo.com", "yahoo.com.au")); + + // Try mixed case in the domain name + assertTrue(AccountSettingsUtils.globMatchIgnoreCase( + "GmAiL.cOm", "gMaIl.CoM")); + + assertFalse(AccountSettingsUtils.globMatchIgnoreCase( + "nonexist.frr.com", "*.rr.com")); + assertFalse(AccountSettingsUtils.globMatchIgnoreCase( + "rr.com", "*.rr.com")); + assertTrue(AccountSettingsUtils.globMatchIgnoreCase( + "abbc.com", "ab*bc.com")); + assertFalse(AccountSettingsUtils.globMatchIgnoreCase( + "abc.com", "ab*bc.com")); + + try { + AccountSettingsUtils.globMatchIgnoreCase( + "abc.com", "ab*bc*.com"); + fail("Should have thrown an IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + try { + AccountSettingsUtils.globMatchIgnoreCase( + null, "ab*bc*.com"); + fail("Should have thrown an IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + try { + AccountSettingsUtils.globMatchIgnoreCase( + "abc.com", null); + fail("Should have thrown an IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + } + + public void testExpandTemplates() { + Provider testProvider; + // + // + // + // + testProvider = new Provider(); + testProvider.domain = "cox.net"; + testProvider.incomingUriTemplate = "pop3+ssl+://pop.east.$domain"; + testProvider.outgoingUriTemplate = "smtp+ssl+://smtp.east.$domain"; + testProvider.incomingUsernameTemplate = "$user"; + testProvider.outgoingUsernameTemplate = "$user"; + testProvider.expandTemplates("replUser@cox.net"); + assertEquals("replUser", testProvider.incomingUsername); + assertEquals("replUser", testProvider.outgoingUsername); + assertEquals("pop3+ssl+://pop.east.cox.net", testProvider.incomingUri); + assertEquals("smtp+ssl+://smtp.east.cox.net", testProvider.outgoingUri); + + // + // + // + // + testProvider = new Provider(); + testProvider.domain = "earthlink.net"; + testProvider.incomingUriTemplate = "pop3://pop.earthlink.net"; + testProvider.outgoingUriTemplate = "smtp://smtpauth.earthlink.net:587"; + testProvider.incomingUsernameTemplate = "$email"; + testProvider.outgoingUsernameTemplate = "$email"; + testProvider.expandTemplates("replUser@earthlink.net"); + assertEquals("replUser@earthlink.net", testProvider.incomingUsername); + assertEquals("replUser@earthlink.net", testProvider.outgoingUsername); + assertEquals("pop3://pop.earthlink.net", testProvider.incomingUri); + assertEquals("smtp://smtpauth.earthlink.net:587", testProvider.outgoingUri); + + // + // + // + // + testProvider = new Provider(); + testProvider.domain = "tuffmail.com"; + testProvider.incomingUriTemplate = "imap+ssl+://mail.mxes.net"; + testProvider.outgoingUriTemplate = "smtp+ssl+://smtp.mxes.net"; + testProvider.incomingUsernameTemplate = "$user_$domain"; + testProvider.outgoingUsernameTemplate = "$user_$domain"; + testProvider.expandTemplates("replUser@tuffmail.com"); + assertEquals("replUser_tuffmail.com", testProvider.incomingUsername); + assertEquals("replUser_tuffmail.com", testProvider.outgoingUsername); + assertEquals("imap+ssl+://mail.mxes.net", testProvider.incomingUri); + assertEquals("smtp+ssl+://smtp.mxes.net", testProvider.outgoingUri); + + // Everything hardcoded; not effective in the wild + testProvider = new Provider(); + testProvider.domain = "yahoo.com"; + testProvider.incomingUriTemplate = "imap+ssl+://pop.yahoo.com"; + testProvider.outgoingUriTemplate = "smtp+ssl+://smtp.yahoo.com"; + testProvider.incomingUsernameTemplate = "joe_smith"; + testProvider.outgoingUsernameTemplate = "joe_smith"; + testProvider.expandTemplates("replUser@yahoo.com"); + assertEquals("joe_smith", testProvider.incomingUsername); + assertEquals("joe_smith", testProvider.outgoingUsername); + assertEquals("imap+ssl+://pop.yahoo.com", testProvider.incomingUri); + assertEquals("smtp+ssl+://smtp.yahoo.com", testProvider.outgoingUri); + } }