Added first version of import file validation

This commit is contained in:
cketti 2011-04-20 21:37:48 +02:00
parent 237302cc2b
commit 71f423d029
6 changed files with 665 additions and 20 deletions

View file

@ -50,10 +50,10 @@ public class Account implements BaseAccount {
public static final String TYPE_OTHER = "OTHER";
private static final String[] networkTypes = { TYPE_WIFI, TYPE_MOBILE, TYPE_OTHER };
private static final MessageFormat DEFAULT_MESSAGE_FORMAT = MessageFormat.HTML;
private static final QuoteStyle DEFAULT_QUOTE_STYLE = QuoteStyle.PREFIX;
private static final String DEFAULT_QUOTE_PREFIX = ">";
private static final boolean DEFAULT_REPLY_AFTER_QUOTE = false;
public static final MessageFormat DEFAULT_MESSAGE_FORMAT = MessageFormat.HTML;
public static final QuoteStyle DEFAULT_QUOTE_STYLE = QuoteStyle.PREFIX;
public static final String DEFAULT_QUOTE_PREFIX = ">";
public static final boolean DEFAULT_REPLY_AFTER_QUOTE = false;
public static final String ACCOUNT_DESCRIPTION_KEY = "description";

View file

@ -0,0 +1,258 @@
package com.fsck.k9.preferences;
import java.util.LinkedHashMap;
import java.util.Map;
import android.net.Uri;
import android.util.Log;
import com.fsck.k9.Account;
import com.fsck.k9.K9;
import com.fsck.k9.R;
import com.fsck.k9.Account.FolderMode;
import com.fsck.k9.Account.ScrollButtons;
import com.fsck.k9.crypto.Apg;
import com.fsck.k9.helper.Utility;
import com.fsck.k9.mail.store.StorageManager;
import com.fsck.k9.preferences.Settings.*;
public class AccountSettings {
public static final Map<String, SettingsDescription> SETTINGS;
static {
SETTINGS = new LinkedHashMap<String, SettingsDescription>();
// mandatory
SETTINGS.put("storeUri",
SD(SettingType.STRING, Settings.EXCEPTION_DEFAULT_VALUE, new StoreUriValidator()));
SETTINGS.put("transportUri",
SD(SettingType.STRING, Settings.EXCEPTION_DEFAULT_VALUE,
new TransportUriValidator()));
SETTINGS.put("archiveFolderName",
SD(SettingType.STRING, "Archive", null));
SETTINGS.put("autoExpandFolderName",
SD(SettingType.STRING, "INBOX", null));
SETTINGS.put("automaticCheckIntervalMinutes",
SD(SettingType.INTEGER, -1, new ResourceArrayValidator(
R.array.account_settings_check_frequency_values)));
SETTINGS.put("chipColor",
SD(SettingType.INTEGER, 0xff0000ff, Settings.SOLID_COLOR_VALIDATOR));
SETTINGS.put("cryptoApp",
SD(SettingType.STRING, Apg.NAME, null));
SETTINGS.put("cryptoAutoSignature",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("deletePolicy",
SD(SettingType.STRING, 0, new ResourceArrayValidator(
R.array.account_setup_delete_policy_values)));
SETTINGS.put("displayCount",
SD(SettingType.STRING, K9.DEFAULT_VISIBLE_LIMIT, new ResourceArrayValidator(
R.array.account_settings_display_count_values)));
SETTINGS.put("draftsFolderName",
SD(SettingType.STRING, "Drafts", null));
SETTINGS.put("enableMoveButtons",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("expungePolicy",
SD(SettingType.STRING, Account.EXPUNGE_IMMEDIATELY, new ResourceArrayValidator(
R.array.account_setup_expunge_policy_values)));
SETTINGS.put("folderDisplayMode",
SD(SettingType.ENUM, FolderMode.NOT_SECOND_CLASS, new ResourceArrayValidator(
R.array.account_settings_folder_display_mode_values)));
SETTINGS.put("folderPushMode",
SD(SettingType.ENUM, FolderMode.FIRST_CLASS, new ResourceArrayValidator(
R.array.account_settings_folder_push_mode_values)));
SETTINGS.put("folderSyncMode",
SD(SettingType.ENUM, FolderMode.FIRST_CLASS, new ResourceArrayValidator(
R.array.folder_settings_folder_sync_mode_values)));
SETTINGS.put("folderTargetMode",
SD(SettingType.ENUM, FolderMode.NOT_SECOND_CLASS, new ResourceArrayValidator(
R.array.account_settings_folder_target_mode_values)));
SETTINGS.put("goToUnreadMessageSearch",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("hideButtonsEnum",
SD(SettingType.ENUM, ScrollButtons.NEVER, new ResourceArrayValidator(
R.array.account_settings_hide_buttons_values)));
SETTINGS.put("hideMoveButtonsEnum",
SD(SettingType.ENUM, ScrollButtons.NEVER, new ResourceArrayValidator(
R.array.account_settings_hide_move_buttons_values)));
SETTINGS.put("idleRefreshMinutes",
SD(SettingType.INTEGER, 24, new ResourceArrayValidator(
R.array.idle_refresh_period_values)));
SETTINGS.put("led",
SD(SettingType.BOOLEAN, true, null));
SETTINGS.put("ledColor",
SD(SettingType.INTEGER, 0xff0000ff, Settings.SOLID_COLOR_VALIDATOR));
SETTINGS.put("localStorageProvider",
SD(SettingType.STRING, new StorageProviderDefaultValue(),
new StorageProviderValidator()));
SETTINGS.put("maxPushFolders",
SD(SettingType.INTEGER, 10, Settings.POSITIVE_INTEGER_VALIDATOR));
SETTINGS.put("maximumAutoDownloadMessageSize",
SD(SettingType.ENUM, 32768, new ResourceArrayValidator(
R.array.account_settings_autodownload_message_size_values)));
SETTINGS.put("maximumPolledMessageAge",
SD(SettingType.ENUM, -1, new ResourceArrayValidator(
R.array.account_settings_message_age_values)));
SETTINGS.put("messageFormat",
SD(SettingType.ENUM, Account.DEFAULT_MESSAGE_FORMAT, new ResourceArrayValidator(
R.array.account_settings_message_format_values)));
SETTINGS.put("notificationUnreadCount",
SD(SettingType.BOOLEAN, true, null));
SETTINGS.put("notifyMailCheck",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("notifyNewMail",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("notifySelfNewMail",
SD(SettingType.BOOLEAN, true, null));
SETTINGS.put("pushPollOnConnect",
SD(SettingType.BOOLEAN, true, null));
SETTINGS.put("quotePrefix",
SD(SettingType.STRING, Account.DEFAULT_QUOTE_PREFIX, null));
SETTINGS.put("quoteStyle",
SD(SettingType.ENUM, Account.DEFAULT_QUOTE_STYLE, new ResourceArrayValidator(
R.array.account_settings_quote_style_values)));
SETTINGS.put("replyAfterQuote",
SD(SettingType.BOOLEAN, Account.DEFAULT_REPLY_AFTER_QUOTE, null));
SETTINGS.put("ring",
SD(SettingType.BOOLEAN, true, null));
SETTINGS.put("ringtone",
SD(SettingType.STRING, "content://settings/system/notification_sound",
new RingtoneValidator()));
SETTINGS.put("saveAllHeaders",
SD(SettingType.BOOLEAN, true, null));
SETTINGS.put("searchableFolders",
SD(SettingType.ENUM, Account.Searchable.ALL, new ResourceArrayValidator(
R.array.account_settings_searchable_values)));
SETTINGS.put("sentFolderName",
SD(SettingType.STRING, "Sent", null));
SETTINGS.put("showPicturesEnum",
SD(SettingType.ENUM, Account.ShowPictures.NEVER, new ResourceArrayValidator(
R.array.account_settings_show_pictures_values)));
SETTINGS.put("signatureBeforeQuotedText",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("spamFolderName",
SD(SettingType.STRING, "Spam", null));
SETTINGS.put("subscribedFoldersOnly",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("syncRemoteDeletions",
SD(SettingType.BOOLEAN, true, null));
SETTINGS.put("trashFolderName",
SD(SettingType.STRING, "Trash", null));
SETTINGS.put("useCompression.MOBILE",
SD(SettingType.BOOLEAN, true, null));
SETTINGS.put("useCompression.OTHER",
SD(SettingType.BOOLEAN, true, null));
SETTINGS.put("useCompression.WIFI",
SD(SettingType.BOOLEAN, true, null));
SETTINGS.put("vibrate",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("vibratePattern",
SD(SettingType.INTEGER, 0, new ResourceArrayValidator(
R.array.account_settings_vibrate_pattern_values)));
SETTINGS.put("vibrateTimes",
SD(SettingType.INTEGER, 5, new ResourceArrayValidator(
R.array.account_settings_vibrate_times_label)));
}
// Just to have shorter lines in SETTINGS initialization
private static SettingsDescription SD(SettingType type,
Object defaultValue, ISettingValidator validator) {
return new SettingsDescription(type, defaultValue, validator);
}
public static Map<String, String> validate(Map<String, String> importedSettings) {
return Settings.validate(SETTINGS, importedSettings);
}
public static class StorageProviderDefaultValue implements IDefaultValue {
@Override
public Object computeDefaultValue(String key, Map<String, String> validatedSettings) {
return StorageManager.getInstance(K9.app).getDefaultProviderId();
}
}
public static class StorageProviderValidator implements ISettingValidator {
@Override
public boolean isValid(String key, String value, Map<String, String> validatedSettings) {
Map<String, String> providers = StorageManager.getInstance(K9.app).getAvailableProviders();
for (String storageProvider : providers.keySet()) {
if (storageProvider.equals(value)) {
return true;
}
}
return false;
}
}
public static class RingtoneValidator implements ISettingValidator {
@Override
public boolean isValid(String key, String value, Map<String, String> validatedSettings) {
// TODO implement
return true;
}
}
public static class StoreUriValidator implements ISettingValidator {
@Override
public boolean isValid(String key, String value, Map<String, String> validatedSettings) {
try {
String uriString = Utility.base64Decode(value);
if (!uriString.startsWith("imap") && !uriString.startsWith("pop3") &&
!uriString.startsWith("webdav")) {
return false;
}
//TODO: check complete scheme (imap+ssl etc.)
Uri uri = Uri.parse(uriString);
String[] userInfoParts = uri.getUserInfo().split(":");
if (userInfoParts.length < 2) {
return false;
}
//TODO: check if username and password are urlencoded
String host = uri.getHost();
if (host == null || host.length() == 0) {
return false;
}
//TODO: check store specifics
return true;
} catch (Exception e) { Log.e(K9.LOG_TAG, "oops", e); /* Ignore */ }
return false;
}
}
public static class TransportUriValidator implements ISettingValidator {
@Override
public boolean isValid(String key, String value, Map<String, String> validatedSettings) {
try {
String uriString = Utility.base64Decode(value);
if (!uriString.startsWith("smtp") && !uriString.startsWith("webdav")) {
return false;
}
//TODO: check complete scheme (smtp+ssl etc.)
Uri uri = Uri.parse(uriString);
String[] userInfoParts = uri.getUserInfo().split(":");
if (userInfoParts.length < 2) {
return false;
}
//TODO: check if username and password are urlencoded
String host = uri.getHost();
if (host == null || host.length() == 0) {
return false;
}
//TODO: check store specifics
return true;
} catch (Exception e) { Log.e(K9.LOG_TAG, "oops", e); /* Ignore */ }
return false;
}
}
}

View file

@ -0,0 +1,195 @@
package com.fsck.k9.preferences;
import java.text.SimpleDateFormat;
import java.util.LinkedHashMap;
import java.util.Map;
import com.fsck.k9.FontSizes;
import com.fsck.k9.K9;
import com.fsck.k9.R;
import com.fsck.k9.helper.DateFormatter;
import com.fsck.k9.preferences.Settings.*;
public class GlobalSettings {
public static final ISettingValidator FONT_SIZE_VALIDATOR = new DipFontSizeValidator();
public static final ISettingValidator TIME_VALIDATOR = new TimeValidator();
public static final Map<String, SettingsDescription> SETTINGS;
static {
SETTINGS = new LinkedHashMap<String, SettingsDescription>();
SETTINGS.put("animations",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("backgroundOperations",
SD(SettingType.ENUM, K9.BACKGROUND_OPS.WHEN_CHECKED, new ResourceArrayValidator(
R.array.background_ops_values)));
SETTINGS.put("changeRegisteredNameColor",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("compactLayouts",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("confirmDelete",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("countSearchMessages",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("dateFormat",
SD(SettingType.ENUM, DateFormatter.DEFAULT_FORMAT, new DateFormatValidator()));
SETTINGS.put("enableDebugLogging",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("enableSensitiveLogging",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("fontSizeAccountDescription",
SD(SettingType.INTEGER, 14, FONT_SIZE_VALIDATOR));
SETTINGS.put("fontSizeAccountName",
SD(SettingType.INTEGER, 18, FONT_SIZE_VALIDATOR));
SETTINGS.put("fontSizeFolderName",
SD(SettingType.INTEGER, 22, FONT_SIZE_VALIDATOR));
SETTINGS.put("fontSizeFolderStatus",
SD(SettingType.INTEGER, 14, FONT_SIZE_VALIDATOR));
SETTINGS.put("fontSizeMessageListDate",
SD(SettingType.INTEGER, 14, FONT_SIZE_VALIDATOR));
SETTINGS.put("fontSizeMessageListPreview",
SD(SettingType.INTEGER, 14, FONT_SIZE_VALIDATOR));
SETTINGS.put("fontSizeMessageListSender",
SD(SettingType.INTEGER, 14, FONT_SIZE_VALIDATOR));
SETTINGS.put("fontSizeMessageListSubject",
SD(SettingType.INTEGER, 16, FONT_SIZE_VALIDATOR));
SETTINGS.put("fontSizeMessageViewAdditionalHeaders",
SD(SettingType.INTEGER, 12, FONT_SIZE_VALIDATOR));
SETTINGS.put("fontSizeMessageViewCC",
SD(SettingType.INTEGER, 12, FONT_SIZE_VALIDATOR));
SETTINGS.put("fontSizeMessageViewContent",
SD(SettingType.INTEGER, 3, new WebViewFontSizeValidator()));
SETTINGS.put("fontSizeMessageViewDate",
SD(SettingType.INTEGER, 10, FONT_SIZE_VALIDATOR));
SETTINGS.put("fontSizeMessageViewSender",
SD(SettingType.INTEGER, 14, FONT_SIZE_VALIDATOR));
SETTINGS.put("fontSizeMessageViewSubject",
SD(SettingType.INTEGER, 12, FONT_SIZE_VALIDATOR));
SETTINGS.put("fontSizeMessageViewTime",
SD(SettingType.INTEGER, 10, FONT_SIZE_VALIDATOR));
SETTINGS.put("fontSizeMessageViewTo",
SD(SettingType.INTEGER, 12, FONT_SIZE_VALIDATOR));
SETTINGS.put("gesturesEnabled",
SD(SettingType.BOOLEAN, true, null));
SETTINGS.put("hideSpecialAccounts",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("keyguardPrivacy",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("language",
SD(SettingType.STRING, "", new ResourceArrayValidator(
R.array.settings_language_values)));
SETTINGS.put("manageBack",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("measureAccounts",
SD(SettingType.BOOLEAN, true, null));
SETTINGS.put("messageListCheckboxes",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("messageListPreviewLines",
SD(SettingType.INTEGER, 2, Settings.POSITIVE_INTEGER_VALIDATOR));
SETTINGS.put("messageListStars",
SD(SettingType.BOOLEAN, true, null));
SETTINGS.put("messageListTouchable",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("messageViewFixedWidthFont",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("messageViewReturnToList",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("mobileOptimizedLayout",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("quietTimeEnabled",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("quietTimeEnds",
SD(SettingType.STRING, "7:00", TIME_VALIDATOR));
SETTINGS.put("quietTimeStarts",
SD(SettingType.STRING, "21:00", TIME_VALIDATOR));
SETTINGS.put("registeredNameColor",
SD(SettingType.INTEGER, 0xFF00008F, Settings.SOLID_COLOR_VALIDATOR));
SETTINGS.put("showContactName",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("showCorrespondentNames",
SD(SettingType.BOOLEAN, true, null));
SETTINGS.put("startIntegratedInbox",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("theme",
SD(SettingType.INTEGER, android.R.style.Theme_Light, new ThemeValidator()));
SETTINGS.put("useGalleryBugWorkaround",
SD(SettingType.BOOLEAN, new GalleryBugWorkaroundDefaultValue(), null));
SETTINGS.put("useVolumeKeysForListNavigation",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("useVolumeKeysForNavigation",
SD(SettingType.BOOLEAN, false, null));
SETTINGS.put("zoomControlsEnabled",
SD(SettingType.BOOLEAN, false, null));
}
// Just to have shorter lines in SETTINGS initialization
private static SettingsDescription SD(SettingType type,
Object defaultValue, ISettingValidator validator) {
return new SettingsDescription(type, defaultValue, validator);
}
public static Map<String, String> validate(Map<String, String> importedSettings) {
return Settings.validate(SETTINGS, importedSettings);
}
public static class GalleryBugWorkaroundDefaultValue implements IDefaultValue {
@Override
public Object computeDefaultValue(String key, Map<String, String> validatedSettings) {
return K9.isGalleryBuggy();
}
}
public static class DipFontSizeValidator implements ISettingValidator {
@Override
public boolean isValid(String key, String value, Map<String, String> validatedSettings) {
int val = Integer.parseInt(value);
switch (val) {
case FontSizes.FONT_10DIP:
case FontSizes.FONT_12DIP:
case FontSizes.SMALL:
case FontSizes.FONT_16DIP:
case FontSizes.MEDIUM:
case FontSizes.FONT_20DIP:
case FontSizes.LARGE:
return true;
default:
return false;
}
}
}
public static class WebViewFontSizeValidator implements ISettingValidator {
@Override
public boolean isValid(String key, String value, Map<String, String> validatedSettings) {
int val = Integer.parseInt(value);
return (val >= 1 && val <= 5);
}
}
public static class TimeValidator implements ISettingValidator {
@Override
public boolean isValid(String key, String value, Map<String, String> validatedSettings) {
return value.matches(TimePickerPreference.VALIDATION_EXPRESSION);
}
}
public static class DateFormatValidator implements ISettingValidator {
@Override
public boolean isValid(String key, String value, Map<String, String> validatedSettings) {
try {
new SimpleDateFormat(value);
return true;
} catch (Exception e) {
return false;
}
}
}
public static class ThemeValidator implements ISettingValidator {
@Override
public boolean isValid(String key, String value, Map<String, String> validatedSettings) {
int val = Integer.parseInt(value);
return (val == android.R.style.Theme_Light || val == android.R.style.Theme);
}
}
}

View file

@ -0,0 +1,193 @@
package com.fsck.k9.preferences;
import java.util.HashMap;
import java.util.Map;
import android.util.Log;
import com.fsck.k9.K9;
/*
* TODO:
* - add support for different settings versions (validate old version and upgrade to new format)
* - use the default values defined in GlobalSettings and AccountSettings when creating new
* accounts
* - use the settings description to decide which keys to export
* - convert internal representation to a "pretty" format when exporting (e.g. we want to export
* the value "light" rather than the integer constant for android.R.style.Theme_Light); revert
* that conversion when importing
* - think of a better way to validate enums than to use the resource arrays (i.e. get rid of
* ResourceArrayValidator); maybe even use the settings description for the settings UI
* - add unit test that validates the default values are actually valid according to the validator
*/
public class Settings {
public static final IDefaultValue EXCEPTION_DEFAULT_VALUE = new ExceptionDefaultValue();
public static final ISettingValidator BOOLEAN_VALIDATOR = new BooleanValidator();
public static final ISettingValidator INTEGER_VALIDATOR = new IntegerValidator();
public static final ISettingValidator POSITIVE_INTEGER_VALIDATOR = new PositiveIntegerValidator();
public static final ISettingValidator SOLID_COLOR_VALIDATOR = new SolidColorValidator();
public static Map<String, String> validate(Map<String, SettingsDescription> settings,
Map<String, String> importedSettings) {
Map<String, String> validatedSettings = new HashMap<String, String>();
for (Map.Entry<String, SettingsDescription> setting : settings.entrySet()) {
String key = setting.getKey();
SettingsDescription desc = setting.getValue();
boolean useDefaultValue;
if (!importedSettings.containsKey(key)) {
Log.v(K9.LOG_TAG, "Key \"" + key + "\" wasn't found in the imported file. Using default value.");
useDefaultValue = true;
} else {
String importedValue = importedSettings.get(key);
if (Settings.isValid(desc, key, importedValue, validatedSettings)) {
validatedSettings.put(key, importedValue);
useDefaultValue = false;
} else {
Log.v(K9.LOG_TAG, "Key \"" + key + "\" has invalid value \"" + importedValue + "\" in " +
"imported file. Using default value.");
useDefaultValue = true;
}
}
if (useDefaultValue) {
Object defaultValue;
if (desc.defaultValue instanceof IDefaultValue) {
defaultValue = ((IDefaultValue)desc.defaultValue).computeDefaultValue(key, validatedSettings);
} else {
defaultValue = desc.defaultValue;
}
validatedSettings.put(key, defaultValue.toString());
}
}
return validatedSettings;
}
public static boolean isValid(SettingsDescription desc, String key, String value,
Map<String, String> validatedSettings) {
try {
switch (desc.type) {
case BOOLEAN:
if (!Settings.BOOLEAN_VALIDATOR.isValid(key, value, validatedSettings)) {
return false;
}
break;
case INTEGER:
if (!Settings.INTEGER_VALIDATOR.isValid(key, value, validatedSettings)) {
return false;
}
break;
default:
break;
}
if (desc.validator != null) {
return desc.validator.isValid(key, value, validatedSettings);
}
return true;
} catch (Exception e) {
Log.e(K9.LOG_TAG, "Exception while running validator for value \"" + value + "\"", e);
return false;
}
}
public enum SettingType {
BOOLEAN,
INTEGER,
STRING,
ENUM
}
public static class SettingsDescription {
public final SettingType type;
public final Object defaultValue;
public final ISettingValidator validator;
protected SettingsDescription(SettingType type,
Object defaultValue, ISettingValidator validator) {
this.type = type;
this.defaultValue = defaultValue;
this.validator = validator;
}
}
public interface IDefaultValue {
Object computeDefaultValue(String key, Map<String, String> validatedSettings);
}
public static class ExceptionDefaultValue implements IDefaultValue {
@Override
public Object computeDefaultValue(String key, Map<String, String> validatedSettings) {
throw new RuntimeException("There is no default value for key \"" + key + "\".");
}
}
public interface ISettingValidator {
boolean isValid(String key, String value, Map<String, String> validatedSettings);
}
public static class BooleanValidator implements ISettingValidator {
@Override
public boolean isValid(String key, String value, Map<String, String> validatedSettings) {
return Boolean.TRUE.toString().equals(value) || Boolean.FALSE.toString().equals(value);
}
}
public static class IntegerValidator implements ISettingValidator {
@Override
public boolean isValid(String key, String value, Map<String, String> validatedSettings) {
try {
Integer.parseInt(value);
return true;
} catch (NumberFormatException e) {
return false;
}
}
}
public static class PositiveIntegerValidator implements ISettingValidator {
@Override
public boolean isValid(String key, String value, Map<String, String> validatedSettings) {
return (Integer.parseInt(value) >= 0);
}
}
public static class ResourceArrayValidator implements ISettingValidator {
private final int mResource;
public ResourceArrayValidator(int res) {
mResource = res;
}
@Override
public boolean isValid(String key, String value, Map<String, String> validatedSettings) {
try {
String[] values = K9.app.getResources().getStringArray(mResource);
for (String validValue : values) {
if (validValue.equals(value)) {
return true;
}
}
} catch (Exception e) {
Log.e(K9.LOG_TAG, "Something went wrong during validation of key " + key, e);
}
return false;
}
}
public static class SolidColorValidator implements ISettingValidator {
@Override
public boolean isValid(String key, String value, Map<String, String> validatedSettings) {
int color = Integer.parseInt(value);
return ((color & 0xFF000000) == 0xFF000000);
}
}
}

View file

@ -200,15 +200,13 @@ public class StorageImporter {
private static void importGlobalSettings(SharedPreferences.Editor editor,
ImportedSettings settings) {
//TODO: input validation
for (Map.Entry<String, String> setting : settings.settings.entrySet()) {
Map<String, String> writeSettings = GlobalSettings.validate(settings.settings);
for (Map.Entry<String, String> setting : writeSettings.entrySet()) {
String key = setting.getKey();
String value = setting.getValue();
//FIXME: drop this key during input validation. then remove this check
if ("accountUuids".equals(key)) {
continue;
}
Log.v(K9.LOG_TAG, "Write " + key + "=" + value);
editor.putString(key, value);
}
}
@ -216,8 +214,14 @@ public class StorageImporter {
private static String importAccount(Context context, SharedPreferences.Editor editor,
ImportedAccount account, boolean overwrite) {
//TODO: input validation
//TODO: remove latestOldMessageSeenTime?
// Validate input and ignore malformed values when possible
Map<String, String> validatedSettings =
AccountSettings.validate(account.settings.settings);
//TODO: validate account name
//TODO: validate identity settings
//TODO: validate folder settings
Preferences prefs = Preferences.getPreferences(context);
Account[] accounts = prefs.getAccounts();
@ -246,12 +250,7 @@ public class StorageImporter {
editor.putString(accountKeyPrefix + Account.ACCOUNT_DESCRIPTION_KEY, accountName);
// Write account settings
for (Map.Entry<String, String> setting : account.settings.settings.entrySet()) {
//FIXME: drop this key during input validation. then remove this check
if ("accountNumber".equals(setting.getKey())) {
continue;
}
for (Map.Entry<String, String> setting : validatedSettings.entrySet()) {
String key = accountKeyPrefix + setting.getKey();
String value = setting.getValue();
editor.putString(key, value);
@ -429,7 +428,7 @@ public class StorageImporter {
int eventType = xpp.next();
if (eventType != XmlPullParser.TEXT) {
return null;
return "";
}
return xpp.getText();
}

View file

@ -19,7 +19,7 @@ public class TimePickerPreference extends DialogPreference implements
/**
* The validation expression for this preference
*/
private static final String VALIDATION_EXPRESSION = "[0-2]*[0-9]:[0-5]*[0-9]";
public static final String VALIDATION_EXPRESSION = "[0-2]*[0-9]:[0-5]*[0-9]";
/**
* The default value for this preference