Added first version of import file validation
This commit is contained in:
parent
237302cc2b
commit
71f423d029
6 changed files with 665 additions and 20 deletions
|
@ -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";
|
||||
|
||||
|
|
258
src/com/fsck/k9/preferences/AccountSettings.java
Normal file
258
src/com/fsck/k9/preferences/AccountSettings.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
195
src/com/fsck/k9/preferences/GlobalSettings.java
Normal file
195
src/com/fsck/k9/preferences/GlobalSettings.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
193
src/com/fsck/k9/preferences/Settings.java
Normal file
193
src/com/fsck/k9/preferences/Settings.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue