2009-07-22 22:13:30 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2009 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package com.android.email.activity.setup;
|
|
|
|
|
2012-06-28 17:40:46 +00:00
|
|
|
import android.content.ContentResolver;
|
2009-07-22 22:13:30 +00:00
|
|
|
import android.content.ContentValues;
|
|
|
|
import android.content.Context;
|
2010-03-04 06:19:41 +00:00
|
|
|
import android.content.res.XmlResourceParser;
|
2011-01-20 00:40:15 +00:00
|
|
|
import android.text.Editable;
|
2012-06-28 17:40:46 +00:00
|
|
|
import android.text.TextUtils;
|
2010-03-04 06:19:41 +00:00
|
|
|
import android.util.Log;
|
2011-01-20 00:40:15 +00:00
|
|
|
import android.widget.EditText;
|
2010-03-04 06:19:41 +00:00
|
|
|
|
2011-09-14 23:24:32 +00:00
|
|
|
import com.android.email.R;
|
|
|
|
import com.android.email.provider.AccountBackupRestore;
|
|
|
|
import com.android.emailcommon.Logging;
|
2012-06-29 16:42:05 +00:00
|
|
|
import com.android.emailcommon.VendorPolicyLoader;
|
|
|
|
import com.android.emailcommon.VendorPolicyLoader.Provider;
|
2011-09-14 23:24:32 +00:00
|
|
|
import com.android.emailcommon.provider.Account;
|
2012-06-28 17:40:46 +00:00
|
|
|
import com.android.emailcommon.provider.HostAuth;
|
2011-09-14 23:24:32 +00:00
|
|
|
import com.android.emailcommon.provider.EmailContent.AccountColumns;
|
2012-06-28 17:40:46 +00:00
|
|
|
import com.android.emailcommon.provider.QuickResponse;
|
|
|
|
import com.android.emailcommon.utility.Utility;
|
2011-09-14 23:24:32 +00:00
|
|
|
import com.google.common.annotations.VisibleForTesting;
|
|
|
|
|
2010-03-04 06:19:41 +00:00
|
|
|
import java.io.Serializable;
|
2009-07-22 22:13:30 +00:00
|
|
|
|
|
|
|
public class AccountSettingsUtils {
|
|
|
|
|
2011-09-14 23:24:32 +00:00
|
|
|
/** Pattern to match any part of a domain */
|
|
|
|
private final static String WILD_STRING = "*";
|
2011-03-28 23:21:15 +00:00
|
|
|
/** Will match any, single character */
|
|
|
|
private final static char WILD_CHARACTER = '?';
|
2011-09-14 23:24:32 +00:00
|
|
|
private final static String DOMAIN_SEPARATOR = "\\.";
|
2011-03-28 23:21:15 +00:00
|
|
|
|
2009-07-22 22:13:30 +00:00
|
|
|
/**
|
|
|
|
* Commits the UI-related settings of an account to the provider. This is static so that it
|
|
|
|
* can be used by the various account activities. If the account has never been saved, this
|
|
|
|
* method saves it; otherwise, it just saves the settings.
|
|
|
|
* @param context the context of the caller
|
|
|
|
* @param account the account whose settings will be committed
|
|
|
|
*/
|
2011-06-13 22:32:27 +00:00
|
|
|
public static void commitSettings(Context context, Account account) {
|
2009-07-22 22:13:30 +00:00
|
|
|
if (!account.isSaved()) {
|
|
|
|
account.save(context);
|
2012-06-28 17:40:46 +00:00
|
|
|
|
|
|
|
// Set up default quick responses here...
|
|
|
|
String[] defaultQuickResponses =
|
|
|
|
context.getResources().getStringArray(R.array.default_quick_responses);
|
|
|
|
ContentValues cv = new ContentValues();
|
|
|
|
cv.put(QuickResponse.ACCOUNT_KEY, account.mId);
|
|
|
|
ContentResolver resolver = context.getContentResolver();
|
|
|
|
for (String quickResponse: defaultQuickResponses) {
|
|
|
|
// Allow empty entries (some localizations may not want to have the maximum
|
|
|
|
// number)
|
|
|
|
if (!TextUtils.isEmpty(quickResponse)) {
|
|
|
|
cv.put(QuickResponse.TEXT, quickResponse);
|
|
|
|
resolver.insert(QuickResponse.CONTENT_URI, cv);
|
|
|
|
}
|
|
|
|
}
|
2009-07-22 22:13:30 +00:00
|
|
|
} else {
|
2010-12-22 21:55:19 +00:00
|
|
|
ContentValues cv = getAccountContentValues(account);
|
2009-07-22 22:13:30 +00:00
|
|
|
account.update(context, cv);
|
|
|
|
}
|
2012-06-28 17:40:46 +00:00
|
|
|
|
2010-01-20 09:36:01 +00:00
|
|
|
// Update the backup (side copy) of the accounts
|
2011-05-06 19:07:39 +00:00
|
|
|
AccountBackupRestore.backup(context);
|
2009-07-22 22:13:30 +00:00
|
|
|
}
|
2010-03-04 06:19:41 +00:00
|
|
|
|
2010-12-22 21:55:19 +00:00
|
|
|
/**
|
2011-04-28 00:12:06 +00:00
|
|
|
* Returns a set of content values to commit account changes (not including the foreign keys
|
|
|
|
* for the two host auth's and policy) to the database. Does not actually commit anything.
|
2010-12-22 21:55:19 +00:00
|
|
|
*/
|
2011-06-13 22:32:27 +00:00
|
|
|
public static ContentValues getAccountContentValues(Account account) {
|
2010-12-22 21:55:19 +00:00
|
|
|
ContentValues cv = new ContentValues();
|
|
|
|
cv.put(AccountColumns.IS_DEFAULT, account.mIsDefault);
|
|
|
|
cv.put(AccountColumns.DISPLAY_NAME, account.getDisplayName());
|
|
|
|
cv.put(AccountColumns.SENDER_NAME, account.getSenderName());
|
|
|
|
cv.put(AccountColumns.SIGNATURE, account.getSignature());
|
|
|
|
cv.put(AccountColumns.SYNC_INTERVAL, account.mSyncInterval);
|
|
|
|
cv.put(AccountColumns.RINGTONE_URI, account.mRingtoneUri);
|
|
|
|
cv.put(AccountColumns.FLAGS, account.mFlags);
|
|
|
|
cv.put(AccountColumns.SYNC_LOOKBACK, account.mSyncLookback);
|
|
|
|
cv.put(AccountColumns.SECURITY_SYNC_KEY, account.mSecuritySyncKey);
|
|
|
|
return cv;
|
|
|
|
}
|
|
|
|
|
2010-03-04 06:19:41 +00:00
|
|
|
/**
|
|
|
|
* Search the list of known Email providers looking for one that matches the user's email
|
|
|
|
* domain. We check for vendor supplied values first, then we look in providers_product.xml,
|
|
|
|
* and finally by the entries in platform providers.xml. This provides a nominal override
|
|
|
|
* capability.
|
|
|
|
*
|
|
|
|
* A match is defined as any provider entry for which the "domain" attribute matches.
|
|
|
|
*
|
|
|
|
* @param domain The domain portion of the user's email address
|
|
|
|
* @return suitable Provider definition, or null if no match found
|
|
|
|
*/
|
|
|
|
public static Provider findProviderForDomain(Context context, String domain) {
|
|
|
|
Provider p = VendorPolicyLoader.getInstance(context).findProviderForDomain(domain);
|
|
|
|
if (p == null) {
|
|
|
|
p = findProviderForDomain(context, domain, R.xml.providers_product);
|
|
|
|
}
|
|
|
|
if (p == null) {
|
|
|
|
p = findProviderForDomain(context, domain, R.xml.providers);
|
|
|
|
}
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Search a single resource containing known Email provider definitions.
|
|
|
|
*
|
|
|
|
* @param domain The domain portion of the user's email address
|
|
|
|
* @param resourceId Id of the provider resource to scan
|
|
|
|
* @return suitable Provider definition, or null if no match found
|
|
|
|
*/
|
2011-03-28 23:21:15 +00:00
|
|
|
/*package*/ static Provider findProviderForDomain(
|
|
|
|
Context context, String domain, int resourceId) {
|
2010-03-04 06:19:41 +00:00
|
|
|
try {
|
|
|
|
XmlResourceParser xml = context.getResources().getXml(resourceId);
|
|
|
|
int xmlEventType;
|
|
|
|
Provider provider = null;
|
|
|
|
while ((xmlEventType = xml.next()) != XmlResourceParser.END_DOCUMENT) {
|
|
|
|
if (xmlEventType == XmlResourceParser.START_TAG
|
2011-03-28 23:21:15 +00:00
|
|
|
&& "provider".equals(xml.getName())) {
|
|
|
|
String providerDomain = getXmlAttribute(context, xml, "domain");
|
|
|
|
try {
|
2011-09-14 23:24:32 +00:00
|
|
|
if (matchProvider(domain, providerDomain)) {
|
2011-03-28 23:21:15 +00:00
|
|
|
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");
|
|
|
|
}
|
2010-03-04 06:19:41 +00:00
|
|
|
}
|
|
|
|
else if (xmlEventType == XmlResourceParser.START_TAG
|
|
|
|
&& "incoming".equals(xml.getName())
|
|
|
|
&& provider != null) {
|
2011-02-04 17:29:13 +00:00
|
|
|
provider.incomingUriTemplate = getXmlAttribute(context, xml, "uri");
|
2010-03-04 06:19:41 +00:00
|
|
|
provider.incomingUsernameTemplate = getXmlAttribute(context, xml, "username");
|
|
|
|
}
|
|
|
|
else if (xmlEventType == XmlResourceParser.START_TAG
|
|
|
|
&& "outgoing".equals(xml.getName())
|
|
|
|
&& provider != null) {
|
2011-02-04 17:29:13 +00:00
|
|
|
provider.outgoingUriTemplate = getXmlAttribute(context, xml, "uri");
|
2010-03-04 06:19:41 +00:00
|
|
|
provider.outgoingUsernameTemplate = getXmlAttribute(context, xml, "username");
|
|
|
|
}
|
|
|
|
else if (xmlEventType == XmlResourceParser.END_TAG
|
|
|
|
&& "provider".equals(xml.getName())
|
|
|
|
&& provider != null) {
|
|
|
|
return provider;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception e) {
|
2011-02-11 23:05:17 +00:00
|
|
|
Log.e(Logging.LOG_TAG, "Error while trying to load provider settings.", e);
|
2010-03-04 06:19:41 +00:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2011-03-28 23:21:15 +00:00
|
|
|
/**
|
2011-09-14 23:24:32 +00:00
|
|
|
* Returns true if the string <code>s1</code> matches the string <code>s2</code>. The string
|
|
|
|
* <code>s2</code> may contain any number of wildcards -- a '?' character -- and/or asterisk
|
|
|
|
* characters -- '*'. Wildcards match any single character, while the asterisk matches a domain
|
|
|
|
* part (i.e. substring demarcated by a period, '.')
|
2011-03-28 23:21:15 +00:00
|
|
|
*/
|
2011-09-14 23:24:32 +00:00
|
|
|
@VisibleForTesting
|
|
|
|
static boolean matchProvider(String testDomain, String providerDomain) {
|
|
|
|
String[] testParts = testDomain.split(DOMAIN_SEPARATOR);
|
|
|
|
String[] providerParts = providerDomain.split(DOMAIN_SEPARATOR);
|
|
|
|
if (testParts.length != providerParts.length) {
|
2011-03-28 23:21:15 +00:00
|
|
|
return false;
|
|
|
|
}
|
2011-09-14 23:24:32 +00:00
|
|
|
for (int i = 0; i < testParts.length; i++) {
|
|
|
|
String testPart = testParts[i].toLowerCase();
|
|
|
|
String providerPart = providerParts[i].toLowerCase();
|
|
|
|
if (!providerPart.equals(WILD_STRING) &&
|
|
|
|
!matchWithWildcards(testPart, providerPart)) {
|
|
|
|
return false;
|
|
|
|
}
|
2011-03-28 23:21:15 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-09-14 23:24:32 +00:00
|
|
|
private static boolean matchWithWildcards(String testPart, String providerPart) {
|
|
|
|
int providerLength = providerPart.length();
|
|
|
|
if (testPart.length() != providerLength){
|
2011-03-28 23:21:15 +00:00
|
|
|
return false;
|
|
|
|
}
|
2011-09-14 23:24:32 +00:00
|
|
|
for (int i = 0; i < providerLength; i++) {
|
|
|
|
char testChar = testPart.charAt(i);
|
|
|
|
char providerChar = providerPart.charAt(i);
|
|
|
|
if (testChar != providerChar && providerChar != WILD_CHARACTER) {
|
|
|
|
return false;
|
|
|
|
}
|
2011-03-28 23:21:15 +00:00
|
|
|
}
|
2011-09-14 23:24:32 +00:00
|
|
|
return true;
|
2011-03-28 23:21:15 +00:00
|
|
|
}
|
|
|
|
|
2010-03-04 06:19:41 +00:00
|
|
|
/**
|
|
|
|
* Attempts to get the given attribute as a String resource first, and if it fails
|
|
|
|
* returns the attribute as a simple String value.
|
|
|
|
* @param xml
|
|
|
|
* @param name
|
|
|
|
* @return the requested resource
|
|
|
|
*/
|
|
|
|
private static String getXmlAttribute(Context context, XmlResourceParser xml, String name) {
|
|
|
|
int resId = xml.getAttributeResourceValue(null, name, 0);
|
|
|
|
if (resId == 0) {
|
|
|
|
return xml.getAttributeValue(null, name);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return context.getString(resId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-03 16:31:45 +00:00
|
|
|
/**
|
|
|
|
* Infer potential email server addresses from domain names
|
|
|
|
*
|
|
|
|
* Incoming: Prepend "imap" or "pop3" to domain, unless "pop", "pop3",
|
|
|
|
* "imap", or "mail" are found.
|
2012-06-28 17:40:46 +00:00
|
|
|
* Outgoing: Prepend "smtp" if domain starts with any in the host prefix array
|
2010-11-03 16:31:45 +00:00
|
|
|
*
|
|
|
|
* @param server name as we know it so far
|
|
|
|
* @param incoming "pop3" or "imap" (or null)
|
|
|
|
* @param outgoing "smtp" or null
|
|
|
|
* @return the post-processed name for use in the UI
|
|
|
|
*/
|
2012-06-28 17:40:46 +00:00
|
|
|
public static String inferServerName(Context context, String server, String incoming,
|
|
|
|
String outgoing) {
|
2010-11-03 16:31:45 +00:00
|
|
|
// Default values cause entire string to be kept, with prepended server string
|
|
|
|
int keepFirstChar = 0;
|
|
|
|
int firstDotIndex = server.indexOf('.');
|
|
|
|
if (firstDotIndex != -1) {
|
|
|
|
// look at first word and decide what to do
|
|
|
|
String firstWord = server.substring(0, firstDotIndex).toLowerCase();
|
2012-06-28 17:40:46 +00:00
|
|
|
String[] hostPrefixes =
|
|
|
|
context.getResources().getStringArray(R.array.smtp_host_prefixes);
|
|
|
|
boolean canSubstituteSmtp = Utility.arrayContains(hostPrefixes, firstWord);
|
2010-11-03 16:31:45 +00:00
|
|
|
boolean isMail = "mail".equals(firstWord);
|
|
|
|
// Now decide what to do
|
|
|
|
if (incoming != null) {
|
|
|
|
// For incoming, we leave imap/pop/pop3/mail alone, or prepend incoming
|
2012-06-28 17:40:46 +00:00
|
|
|
if (canSubstituteSmtp || isMail) {
|
2010-11-03 16:31:45 +00:00
|
|
|
return server;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// For outgoing, replace imap/pop/pop3 with outgoing, leave mail alone, or
|
|
|
|
// prepend outgoing
|
2012-06-28 17:40:46 +00:00
|
|
|
if (canSubstituteSmtp) {
|
2010-11-03 16:31:45 +00:00
|
|
|
keepFirstChar = firstDotIndex + 1;
|
|
|
|
} else if (isMail) {
|
|
|
|
return server;
|
|
|
|
} else {
|
|
|
|
// prepend
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ((incoming != null) ? incoming : outgoing) + '.' + server.substring(keepFirstChar);
|
|
|
|
}
|
2011-01-20 00:40:15 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper to set error status on password fields that have leading or trailing spaces
|
|
|
|
*/
|
|
|
|
public static void checkPasswordSpaces(Context context, EditText passwordField) {
|
|
|
|
Editable password = passwordField.getText();
|
|
|
|
int length = password.length();
|
|
|
|
if (length > 0) {
|
|
|
|
if (password.charAt(0) == ' ' || password.charAt(length-1) == ' ') {
|
|
|
|
passwordField.setError(context.getString(R.string.account_password_spaces_error));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-22 22:13:30 +00:00
|
|
|
}
|