Remove unnecessary line breaks

This commit is contained in:
cketti 2017-01-24 22:55:35 +01:00
parent f5b8a56c8a
commit 2710fd3d8d
7 changed files with 116 additions and 204 deletions

View file

@ -56,8 +56,7 @@ public class AccountSettings {
new V(1, new StringSetting("INBOX")) new V(1, new StringSetting("INBOX"))
)); ));
s.put("automaticCheckIntervalMinutes", Settings.versions( s.put("automaticCheckIntervalMinutes", Settings.versions(
new V(1, new IntegerResourceSetting(-1, new V(1, new IntegerResourceSetting(-1, R.array.account_settings_check_frequency_values))
R.array.account_settings_check_frequency_values))
)); ));
s.put("chipColor", Settings.versions( s.put("chipColor", Settings.versions(
new V(1, new ColorSetting(0xFF0000FF)) new V(1, new ColorSetting(0xFF0000FF))
@ -120,16 +119,13 @@ public class AccountSettings {
new V(1, new IntegerRangeSetting(0, 100, 10)) new V(1, new IntegerRangeSetting(0, 100, 10))
)); ));
s.put("maximumAutoDownloadMessageSize", Settings.versions( s.put("maximumAutoDownloadMessageSize", Settings.versions(
new V(1, new IntegerResourceSetting(32768, new V(1, new IntegerResourceSetting(32768, R.array.account_settings_autodownload_message_size_values))
R.array.account_settings_autodownload_message_size_values))
)); ));
s.put("maximumPolledMessageAge", Settings.versions( s.put("maximumPolledMessageAge", Settings.versions(
new V(1, new IntegerResourceSetting(-1, new V(1, new IntegerResourceSetting(-1, R.array.account_settings_message_age_values))
R.array.account_settings_message_age_values))
)); ));
s.put("messageFormat", Settings.versions( s.put("messageFormat", Settings.versions(
new V(1, new EnumSetting<>( new V(1, new EnumSetting<>(MessageFormat.class, Account.DEFAULT_MESSAGE_FORMAT))
MessageFormat.class, Account.DEFAULT_MESSAGE_FORMAT))
)); ));
s.put("messageFormatAuto", Settings.versions( s.put("messageFormatAuto", Settings.versions(
new V(2, new BooleanSetting(Account.DEFAULT_MESSAGE_FORMAT_AUTO)) new V(2, new BooleanSetting(Account.DEFAULT_MESSAGE_FORMAT_AUTO))
@ -213,12 +209,10 @@ public class AccountSettings {
new V(1, new BooleanSetting(false)) new V(1, new BooleanSetting(false))
)); ));
s.put("vibratePattern", Settings.versions( s.put("vibratePattern", Settings.versions(
new V(1, new IntegerResourceSetting(0, new V(1, new IntegerResourceSetting(0, R.array.account_settings_vibrate_pattern_values))
R.array.account_settings_vibrate_pattern_values))
)); ));
s.put("vibrateTimes", Settings.versions( s.put("vibrateTimes", Settings.versions(
new V(1, new IntegerResourceSetting(5, new V(1, new IntegerResourceSetting(5, R.array.account_settings_vibrate_times_label))
R.array.account_settings_vibrate_times_label))
)); ));
s.put("allowRemoteSearch", Settings.versions( s.put("allowRemoteSearch", Settings.versions(
new V(18, new BooleanSetting(true)) new V(18, new BooleanSetting(true))
@ -241,8 +235,7 @@ public class AccountSettings {
UPGRADERS = Collections.unmodifiableMap(u); UPGRADERS = Collections.unmodifiableMap(u);
} }
static Map<String, Object> validate(int version, Map<String, String> importedSettings, static Map<String, Object> validate(int version, Map<String, String> importedSettings, boolean useDefaultValues) {
boolean useDefaultValues) {
return Settings.validate(version, SETTINGS, importedSettings, useDefaultValues); return Settings.validate(version, SETTINGS, importedSettings, useDefaultValues);
} }

View file

@ -48,8 +48,7 @@ class FolderSettings {
UPGRADERS = Collections.unmodifiableMap(u); UPGRADERS = Collections.unmodifiableMap(u);
} }
static Map<String, Object> validate(int version, Map<String, String> importedSettings, static Map<String, Object> validate(int version, Map<String, String> importedSettings, boolean useDefaultValues) {
boolean useDefaultValues) {
return Settings.validate(version, SETTINGS, importedSettings, useDefaultValues); return Settings.validate(version, SETTINGS, importedSettings, useDefaultValues);
} }
@ -61,8 +60,7 @@ class FolderSettings {
return Settings.convert(settings, SETTINGS); return Settings.convert(settings, SETTINGS);
} }
static Map<String, String> getFolderSettings(Storage storage, String uuid, static Map<String, String> getFolderSettings(Storage storage, String uuid, String folderName) {
String folderName) {
Map<String, String> result = new HashMap<>(); Map<String, String> result = new HashMap<>();
String prefix = uuid + "." + folderName + "."; String prefix = uuid + "." + folderName + ".";
for (String key : SETTINGS.keySet()) { for (String key : SETTINGS.keySet()) {

View file

@ -56,8 +56,7 @@ public class GlobalSettings {
Environment.DIRECTORY_DOWNLOADS))) Environment.DIRECTORY_DOWNLOADS)))
)); ));
s.put("backgroundOperations", Settings.versions( s.put("backgroundOperations", Settings.versions(
new V(1, new EnumSetting<>( new V(1, new EnumSetting<>(K9.BACKGROUND_OPS.class, K9.BACKGROUND_OPS.WHEN_CHECKED_AUTO_SYNC))
K9.BACKGROUND_OPS.class, K9.BACKGROUND_OPS.WHEN_CHECKED_AUTO_SYNC))
)); ));
s.put("changeRegisteredNameColor", Settings.versions( s.put("changeRegisteredNameColor", Settings.versions(
new V(1, new BooleanSetting(false)) new V(1, new BooleanSetting(false))
@ -214,8 +213,7 @@ public class GlobalSettings {
new V(22, new BooleanSetting(false)) new V(22, new BooleanSetting(false))
)); ));
s.put("notificationHideSubject", Settings.versions( s.put("notificationHideSubject", Settings.versions(
new V(12, new EnumSetting<>( new V(12, new EnumSetting<>(NotificationHideSubject.class, NotificationHideSubject.NEVER))
NotificationHideSubject.class, NotificationHideSubject.NEVER))
)); ));
s.put("useBackgroundAsUnreadIndicator", Settings.versions( s.put("useBackgroundAsUnreadIndicator", Settings.versions(
new V(19, new BooleanSetting(true)) new V(19, new BooleanSetting(true))
@ -276,8 +274,7 @@ public class GlobalSettings {
new V(38, new BooleanSetting(false)) new V(38, new BooleanSetting(false))
)); ));
s.put("notificationQuickDelete", Settings.versions( s.put("notificationQuickDelete", Settings.versions(
new V(38, new EnumSetting<>(NotificationQuickDelete.class, new V(38, new EnumSetting<>(NotificationQuickDelete.class, NotificationQuickDelete.NEVER))
NotificationQuickDelete.NEVER))
)); ));
s.put("notificationDuringQuietTimeEnabled", Settings.versions( s.put("notificationDuringQuietTimeEnabled", Settings.versions(
new V(39, new BooleanSetting(true)) new V(39, new BooleanSetting(true))

View file

@ -17,8 +17,7 @@ class IdentitySettings {
private static final Map<Integer, SettingsUpgrader> UPGRADERS; private static final Map<Integer, SettingsUpgrader> UPGRADERS;
static { static {
Map<String, TreeMap<Integer, SettingsDescription>> s = Map<String, TreeMap<Integer, SettingsDescription>> s = new LinkedHashMap<>();
new LinkedHashMap<>();
/** /**
* When adding new settings here, be sure to increment {@link Settings.VERSION} * When adding new settings here, be sure to increment {@link Settings.VERSION}
@ -42,8 +41,7 @@ class IdentitySettings {
UPGRADERS = Collections.unmodifiableMap(u); UPGRADERS = Collections.unmodifiableMap(u);
} }
static Map<String, Object> validate(int version, Map<String, String> importedSettings, static Map<String, Object> validate(int version, Map<String, String> importedSettings, boolean useDefaultValues) {
boolean useDefaultValues) {
return Settings.validate(version, SETTINGS, importedSettings, useDefaultValues); return Settings.validate(version, SETTINGS, importedSettings, useDefaultValues);
} }
@ -55,8 +53,7 @@ class IdentitySettings {
return Settings.convert(settings, SETTINGS); return Settings.convert(settings, SETTINGS);
} }
static Map<String, String> getIdentitySettings(Storage storage, String uuid, static Map<String, String> getIdentitySettings(Storage storage, String uuid, int identityIndex) {
int identityIndex) {
Map<String, String> result = new HashMap<>(); Map<String, String> result = new HashMap<>();
String prefix = uuid + "."; String prefix = uuid + ".";
String suffix = "." + Integer.toString(identityIndex); String suffix = "." + Integer.toString(identityIndex);

View file

@ -38,13 +38,11 @@ public class Settings {
*/ */
public static final int VERSION = 44; public static final int VERSION = 44;
static Map<String, Object> validate(int version, Map<String, static Map<String, Object> validate(int version, Map<String, TreeMap<Integer, SettingsDescription>> settings,
TreeMap<Integer, SettingsDescription>> settings,
Map<String, String> importedSettings, boolean useDefaultValues) { Map<String, String> importedSettings, boolean useDefaultValues) {
Map<String, Object> validatedSettings = new HashMap<>(); Map<String, Object> validatedSettings = new HashMap<>();
for (Map.Entry<String, TreeMap<Integer, SettingsDescription>> versionedSetting : for (Map.Entry<String, TreeMap<Integer, SettingsDescription>> versionedSetting : settings.entrySet()) {
settings.entrySet()) {
// Get the setting description with the highest version lower than or equal to the // Get the setting description with the highest version lower than or equal to the
// supplied content version. // supplied content version.
@ -112,8 +110,7 @@ public class Settings {
* if none were removed. * if none were removed.
*/ */
public static Set<String> upgrade(int version, Map<Integer, SettingsUpgrader> customUpgraders, public static Set<String> upgrade(int version, Map<Integer, SettingsUpgrader> customUpgraders,
Map<String, TreeMap<Integer, SettingsDescription>> settings, Map<String, TreeMap<Integer, SettingsDescription>> settings, Map<String, Object> validatedSettingsMutable) {
Map<String, Object> validatedSettingsMutable) {
Set<String> deletedSettings = null; Set<String> deletedSettings = null;
for (int toVersion = version + 1; toVersion <= VERSION; toVersion++) { for (int toVersion = version + 1; toVersion <= VERSION; toVersion++) {
@ -201,8 +198,7 @@ public class Settings {
String settingName = setting.getKey(); String settingName = setting.getKey();
Object internalValue = setting.getValue(); Object internalValue = setting.getValue();
TreeMap<Integer, SettingsDescription> versionedSetting = TreeMap<Integer, SettingsDescription> versionedSetting = settingDescriptions.get(settingName);
settingDescriptions.get(settingName);
Integer highestVersion = versionedSetting.lastKey(); Integer highestVersion = versionedSetting.lastKey();
SettingsDescription settingDesc = versionedSetting.get(highestVersion); SettingsDescription settingDesc = versionedSetting.get(highestVersion);

View file

@ -76,8 +76,7 @@ public class SettingsExporter {
static final String DESCRIPTION_ELEMENT = "description"; static final String DESCRIPTION_ELEMENT = "description";
public static String exportToFile(Context context, boolean includeGlobals, public static String exportToFile(Context context, boolean includeGlobals, Set<String> accountUuids)
Set<String> accountUuids)
throws SettingsImportExportException { throws SettingsImportExportException {
OutputStream os = null; OutputStream os = null;
@ -110,8 +109,8 @@ public class SettingsExporter {
} }
} }
static void exportPreferences(Context context, OutputStream os, boolean includeGlobals, static void exportPreferences(Context context, OutputStream os, boolean includeGlobals, Set<String> accountUuids)
Set<String> accountUuids) throws SettingsImportExportException { throws SettingsImportExportException {
try { try {
XmlSerializer serializer = Xml.newSerializer(); XmlSerializer serializer = Xml.newSerializer();
@ -124,8 +123,7 @@ public class SettingsExporter {
serializer.startTag(null, ROOT_ELEMENT); serializer.startTag(null, ROOT_ELEMENT);
serializer.attribute(null, VERSION_ATTRIBUTE, Integer.toString(Settings.VERSION)); serializer.attribute(null, VERSION_ATTRIBUTE, Integer.toString(Settings.VERSION));
serializer.attribute(null, FILE_FORMAT_ATTRIBUTE, serializer.attribute(null, FILE_FORMAT_ATTRIBUTE, Integer.toString(FILE_FORMAT_VERSION));
Integer.toString(FILE_FORMAT_VERSION));
Log.i(K9.LOG_TAG, "Exporting preferences"); Log.i(K9.LOG_TAG, "Exporting preferences");
@ -167,8 +165,7 @@ public class SettingsExporter {
} }
} }
private static void writeSettings(XmlSerializer serializer, private static void writeSettings(XmlSerializer serializer, Map<String, Object> prefs) throws IOException {
Map<String, Object> prefs) throws IOException {
for (Entry<String, TreeMap<Integer, SettingsDescription>> versionedSetting : for (Entry<String, TreeMap<Integer, SettingsDescription>> versionedSetting :
GlobalSettings.SETTINGS.entrySet()) { GlobalSettings.SETTINGS.entrySet()) {
@ -192,8 +189,7 @@ public class SettingsExporter {
} }
} else { } else {
if (K9.DEBUG) { if (K9.DEBUG) {
Log.d(K9.LOG_TAG, "Couldn't find key \"" + key + "\" in preference storage." + Log.d(K9.LOG_TAG, "Couldn't find key \"" + key + "\" in preference storage. Using default value.");
"Using default value.");
} }
writeKeyAndDefaultValueFromSetting(serializer, key, setting); writeKeyAndDefaultValueFromSetting(serializer, key, setting);
@ -201,8 +197,8 @@ public class SettingsExporter {
} }
} }
private static void writeAccount(XmlSerializer serializer, Account account, private static void writeAccount(XmlSerializer serializer, Account account, Map<String, Object> prefs)
Map<String, Object> prefs) throws IOException { throws IOException {
Set<Integer> identities = new HashSet<>(); Set<Integer> identities = new HashSet<>();
Set<String> folders = new HashSet<>(); Set<String> folders = new HashSet<>();
@ -218,7 +214,6 @@ public class SettingsExporter {
serializer.endTag(null, NAME_ELEMENT); serializer.endTag(null, NAME_ELEMENT);
} }
// Write incoming server settings // Write incoming server settings
ServerSettings incoming = RemoteStore.decodeStoreUri(account.getStoreUri()); ServerSettings incoming = RemoteStore.decodeStoreUri(account.getStoreUri());
serializer.startTag(null, INCOMING_SERVER_ELEMENT); serializer.startTag(null, INCOMING_SERVER_ELEMENT);
@ -326,8 +321,7 @@ public class SettingsExporter {
} }
} }
TreeMap<Integer, SettingsDescription> versionedSetting = TreeMap<Integer, SettingsDescription> versionedSetting = AccountSettings.SETTINGS.get(keyPart);
AccountSettings.SETTINGS.get(keyPart);
if (versionedSetting != null) { if (versionedSetting != null) {
Integer highestVersion = versionedSetting.lastKey(); Integer highestVersion = versionedSetting.lastKey();
@ -371,8 +365,8 @@ public class SettingsExporter {
serializer.endTag(null, ACCOUNT_ELEMENT); serializer.endTag(null, ACCOUNT_ELEMENT);
} }
private static void writeIdentity(XmlSerializer serializer, String accountUuid, private static void writeIdentity(XmlSerializer serializer, String accountUuid, String identity,
String identity, Map<String, Object> prefs) throws IOException { Map<String, Object> prefs) throws IOException {
serializer.startTag(null, IDENTITY_ELEMENT); serializer.startTag(null, IDENTITY_ELEMENT);
@ -419,8 +413,7 @@ public class SettingsExporter {
continue; continue;
} }
TreeMap<Integer, SettingsDescription> versionedSetting = TreeMap<Integer, SettingsDescription> versionedSetting = IdentitySettings.SETTINGS.get(identityKey);
IdentitySettings.SETTINGS.get(identityKey);
if (versionedSetting != null) { if (versionedSetting != null) {
Integer highestVersion = versionedSetting.lastKey(); Integer highestVersion = versionedSetting.lastKey();
@ -431,9 +424,8 @@ public class SettingsExporter {
try { try {
writeKeyAndPrettyValueFromSetting(serializer, identityKey, setting, valueString); writeKeyAndPrettyValueFromSetting(serializer, identityKey, setting, valueString);
} catch (InvalidSettingValueException e) { } catch (InvalidSettingValueException e) {
Log.w(K9.LOG_TAG, "Identity setting \"" + identityKey + Log.w(K9.LOG_TAG, "Identity setting \"" + identityKey + "\" has invalid value \"" +
"\" has invalid value \"" + valueString + valueString + "\" in preference storage. This shouldn't happen!");
"\" in preference storage. This shouldn't happen!");
} }
} }
} }
@ -443,8 +435,8 @@ public class SettingsExporter {
serializer.endTag(null, IDENTITY_ELEMENT); serializer.endTag(null, IDENTITY_ELEMENT);
} }
private static void writeFolder(XmlSerializer serializer, String accountUuid, private static void writeFolder(XmlSerializer serializer, String accountUuid, String folder,
String folder, Map<String, Object> prefs) throws IOException { Map<String, Object> prefs) throws IOException {
serializer.startTag(null, FOLDER_ELEMENT); serializer.startTag(null, FOLDER_ELEMENT);
serializer.attribute(null, NAME_ATTRIBUTE, folder); serializer.attribute(null, NAME_ATTRIBUTE, folder);
@ -470,8 +462,7 @@ public class SettingsExporter {
continue; continue;
} }
TreeMap<Integer, SettingsDescription> versionedSetting = TreeMap<Integer, SettingsDescription> versionedSetting = FolderSettings.SETTINGS.get(folderKey);
FolderSettings.SETTINGS.get(folderKey);
if (versionedSetting != null) { if (versionedSetting != null) {
Integer highestVersion = versionedSetting.lastKey(); Integer highestVersion = versionedSetting.lastKey();
@ -482,8 +473,7 @@ public class SettingsExporter {
try { try {
writeKeyAndPrettyValueFromSetting(serializer, folderKey, setting, valueString); writeKeyAndPrettyValueFromSetting(serializer, folderKey, setting, valueString);
} catch (InvalidSettingValueException e) { } catch (InvalidSettingValueException e) {
Log.w(K9.LOG_TAG, "Folder setting \"" + folderKey + Log.w(K9.LOG_TAG, "Folder setting \"" + folderKey + "\" has invalid value \"" + valueString +
"\" has invalid value \"" + valueString +
"\" in preference storage. This shouldn't happen!"); "\" in preference storage. This shouldn't happen!");
} }
} }
@ -502,8 +492,8 @@ public class SettingsExporter {
} }
} }
private static <A> void writeKeyAndPrettyValueFromSetting(XmlSerializer serializer, private static <A> void writeKeyAndPrettyValueFromSetting(XmlSerializer serializer, String key,
String key, SettingsDescription<A> setting, String valueString) SettingsDescription<A> setting, String valueString)
throws IllegalArgumentException, IllegalStateException, IOException, InvalidSettingValueException { throws IllegalArgumentException, IllegalStateException, IOException, InvalidSettingValueException {
A value = setting.fromString(valueString); A value = setting.fromString(valueString);
String outputValue = setting.toPrettyString(value); String outputValue = setting.toPrettyString(value);
@ -511,9 +501,8 @@ public class SettingsExporter {
writeKeyAndPrettyValueFromSetting(serializer, key, outputValue); writeKeyAndPrettyValueFromSetting(serializer, key, outputValue);
} }
private static <A> void writeKeyAndDefaultValueFromSetting(XmlSerializer serializer, private static <A> void writeKeyAndDefaultValueFromSetting(XmlSerializer serializer, String key,
String key, SettingsDescription<A> setting) SettingsDescription<A> setting) throws IllegalArgumentException, IllegalStateException, IOException {
throws IllegalArgumentException, IllegalStateException, IOException {
A value = setting.getDefaultValue(); A value = setting.getDefaultValue();
String outputValue = setting.toPrettyString(value); String outputValue = setting.toPrettyString(value);

View file

@ -83,8 +83,7 @@ public class SettingsImporter {
public final AccountDescription imported; public final AccountDescription imported;
public final boolean overwritten; public final boolean overwritten;
private AccountDescriptionPair(AccountDescription original, AccountDescription imported, private AccountDescriptionPair(AccountDescription original, AccountDescription imported, boolean overwritten) {
boolean overwritten) {
this.original = original; this.original = original;
this.imported = imported; this.imported = imported;
this.overwritten = overwritten; this.overwritten = overwritten;
@ -96,8 +95,7 @@ public class SettingsImporter {
public final List<AccountDescriptionPair> importedAccounts; public final List<AccountDescriptionPair> importedAccounts;
public final List<AccountDescription> errorneousAccounts; public final List<AccountDescription> errorneousAccounts;
private ImportResults(boolean globalSettings, private ImportResults(boolean globalSettings, List<AccountDescriptionPair> importedAccounts,
List<AccountDescriptionPair> importedAccounts,
List<AccountDescription> errorneousAccounts) { List<AccountDescription> errorneousAccounts) {
this.globalSettings = globalSettings; this.globalSettings = globalSettings;
this.importedAccounts = importedAccounts; this.importedAccounts = importedAccounts;
@ -174,9 +172,8 @@ public class SettingsImporter {
* @throws SettingsImportExportException * @throws SettingsImportExportException
* In case of an error. * In case of an error.
*/ */
public static ImportResults importSettings(Context context, InputStream inputStream, public static ImportResults importSettings(Context context, InputStream inputStream, boolean globalSettings,
boolean globalSettings, List<String> accountUuids, boolean overwrite) List<String> accountUuids, boolean overwrite) throws SettingsImportExportException {
throws SettingsImportExportException {
try try
{ {
@ -193,21 +190,18 @@ public class SettingsImporter {
try { try {
StorageEditor editor = storage.edit(); StorageEditor editor = storage.edit();
if (imported.globalSettings != null) { if (imported.globalSettings != null) {
importGlobalSettings(storage, editor, imported.contentVersion, importGlobalSettings(storage, editor, imported.contentVersion, imported.globalSettings);
imported.globalSettings);
} else { } else {
Log.w(K9.LOG_TAG, "Was asked to import global settings but none found."); Log.w(K9.LOG_TAG, "Was asked to import global settings but none found.");
} }
if (editor.commit()) { if (editor.commit()) {
if (K9.DEBUG) { if (K9.DEBUG) {
Log.v(K9.LOG_TAG, "Committed global settings to the preference " + Log.v(K9.LOG_TAG, "Committed global settings to the preference storage.");
"storage.");
} }
globalSettingsImported = true; globalSettingsImported = true;
} else { } else {
if (K9.DEBUG) { if (K9.DEBUG) {
Log.v(K9.LOG_TAG, "Failed to commit global settings to the " + Log.v(K9.LOG_TAG, "Failed to commit global settings to the preference storage");
"preference storage");
} }
} }
} catch (Exception e) { } catch (Exception e) {
@ -223,14 +217,13 @@ public class SettingsImporter {
try { try {
StorageEditor editor = storage.edit(); StorageEditor editor = storage.edit();
AccountDescriptionPair importResult = importAccount(context, AccountDescriptionPair importResult = importAccount(context, editor,
editor, imported.contentVersion, account, overwrite); imported.contentVersion, account, overwrite);
if (editor.commit()) { if (editor.commit()) {
if (K9.DEBUG) { if (K9.DEBUG) {
Log.v(K9.LOG_TAG, "Committed settings for account \"" + Log.v(K9.LOG_TAG, "Committed settings for account \"" +
importResult.imported.name + importResult.imported.name + "\" to the settings database.");
"\" to the settings database.");
} }
// Add UUID of the account we just imported to the list of // Add UUID of the account we just imported to the list of
@ -256,9 +249,8 @@ public class SettingsImporter {
importedAccounts.add(importResult); importedAccounts.add(importResult);
} else { } else {
if (K9.DEBUG) { if (K9.DEBUG) {
Log.w(K9.LOG_TAG, "Error while committing settings for " + Log.w(K9.LOG_TAG, "Error while committing settings for account \"" +
"account \"" + importResult.original.name + importResult.original.name + "\" to the settings database.");
"\" to the settings database.");
} }
errorneousAccounts.add(importResult.original); errorneousAccounts.add(importResult.original);
} }
@ -269,13 +261,12 @@ public class SettingsImporter {
} }
errorneousAccounts.add(new AccountDescription(account.name, account.uuid)); errorneousAccounts.add(new AccountDescription(account.name, account.uuid));
} catch (Exception e) { } catch (Exception e) {
Log.e(K9.LOG_TAG, "Exception while importing account \"" + Log.e(K9.LOG_TAG, "Exception while importing account \"" + account.name + "\"", e);
account.name + "\"", e);
errorneousAccounts.add(new AccountDescription(account.name, account.uuid)); errorneousAccounts.add(new AccountDescription(account.name, account.uuid));
} }
} else { } else {
Log.w(K9.LOG_TAG, "Was asked to import account with UUID " + Log.w(K9.LOG_TAG, "Was asked to import account with UUID " + accountUuid +
accountUuid + ". But this account wasn't found."); ". But this account wasn't found.");
} }
} }
@ -307,12 +298,11 @@ public class SettingsImporter {
} }
} }
private static void importGlobalSettings(Storage storage, private static void importGlobalSettings(Storage storage, StorageEditor editor, int contentVersion,
StorageEditor editor, int contentVersion, ImportedSettings settings) { ImportedSettings settings) {
// Validate global settings // Validate global settings
Map<String, Object> validatedSettings = GlobalSettings.validate(contentVersion, Map<String, Object> validatedSettings = GlobalSettings.validate(contentVersion, settings.settings);
settings.settings);
// Upgrade global settings to current content version // Upgrade global settings to current content version
if (contentVersion != Settings.VERSION) { if (contentVersion != Settings.VERSION) {
@ -322,10 +312,8 @@ public class SettingsImporter {
// Convert global settings to the string representation used in preference storage // Convert global settings to the string representation used in preference storage
Map<String, String> stringSettings = GlobalSettings.convert(validatedSettings); Map<String, String> stringSettings = GlobalSettings.convert(validatedSettings);
// Use current global settings as base and overwrite with validated settings read from the // Use current global settings as base and overwrite with validated settings read from the import file.
// import file. Map<String, String> mergedSettings = new HashMap<>(GlobalSettings.getGlobalSettings(storage));
Map<String, String> mergedSettings =
new HashMap<>(GlobalSettings.getGlobalSettings(storage));
mergedSettings.putAll(stringSettings); mergedSettings.putAll(stringSettings);
for (Map.Entry<String, String> setting : mergedSettings.entrySet()) { for (Map.Entry<String, String> setting : mergedSettings.entrySet()) {
@ -335,9 +323,8 @@ public class SettingsImporter {
} }
} }
private static AccountDescriptionPair importAccount(Context context, private static AccountDescriptionPair importAccount(Context context, StorageEditor editor, int contentVersion,
StorageEditor editor, int contentVersion, ImportedAccount account, ImportedAccount account, boolean overwrite) throws InvalidSettingValueException {
boolean overwrite) throws InvalidSettingValueException {
AccountDescription original = new AccountDescription(account.name, account.uuid); AccountDescription original = new AccountDescription(account.name, account.uuid);
@ -357,8 +344,8 @@ public class SettingsImporter {
// Make sure the account name is unique // Make sure the account name is unique
String accountName = account.name; String accountName = account.name;
if (isAccountNameUsed(accountName, accounts)) { if (isAccountNameUsed(accountName, accounts)) {
// Account name is already in use. So generate a new one by appending " (x)", where x // Account name is already in use. So generate a new one by appending " (x)", where x is the first
// is the first number >= 1 that results in an unused account name. // number >= 1 that results in an unused account name.
for (int i = 1; i <= accounts.size(); i++) { for (int i = 1; i <= accounts.size(); i++) {
accountName = account.name + " (" + i + ")"; accountName = account.name + " (" + i + ")";
if (!isAccountNameUsed(accountName, accounts)) { if (!isAccountNameUsed(accountName, accounts)) {
@ -398,11 +385,9 @@ public class SettingsImporter {
putString(editor, accountKeyPrefix + Account.TRANSPORT_URI_KEY, Base64.encode(transportUri)); putString(editor, accountKeyPrefix + Account.TRANSPORT_URI_KEY, Base64.encode(transportUri));
/* /*
* Mark account as disabled if the settings file contained a * Mark account as disabled if the settings file contained a username but no password. However, no password
* username but no password. However, no password is required for * is required for the outgoing server for WebDAV accounts, because incoming and outgoing servers are
* the outgoing server for WebDAV accounts, because incoming and * identical for this account type. Nor is a password required if the AuthType is EXTERNAL.
* outgoing servers are identical for this account type. Nor is a
* password required if the AuthType is EXTERNAL.
*/ */
boolean outgoingPasswordNeeded = AuthType.EXTERNAL != outgoing.authenticationType && boolean outgoingPasswordNeeded = AuthType.EXTERNAL != outgoing.authenticationType &&
!(ServerSettings.Type.WebDAV == outgoing.type) && !(ServerSettings.Type.WebDAV == outgoing.type) &&
@ -419,8 +404,7 @@ public class SettingsImporter {
// Validate account settings // Validate account settings
Map<String, Object> validatedSettings = Map<String, Object> validatedSettings =
AccountSettings.validate(contentVersion, account.settings.settings, AccountSettings.validate(contentVersion, account.settings.settings, !mergeImportedAccount);
!mergeImportedAccount);
// Upgrade account settings to current content version // Upgrade account settings to current content version
if (contentVersion != Settings.VERSION) { if (contentVersion != Settings.VERSION) {
@ -433,8 +417,7 @@ public class SettingsImporter {
// Merge account settings if necessary // Merge account settings if necessary
Map<String, String> writeSettings; Map<String, String> writeSettings;
if (mergeImportedAccount) { if (mergeImportedAccount) {
writeSettings = new HashMap<>( writeSettings = new HashMap<>(AccountSettings.getAccountSettings(prefs.getStorage(), uuid));
AccountSettings.getAccountSettings(prefs.getStorage(), uuid));
writeSettings.putAll(stringSettings); writeSettings.putAll(stringSettings);
} else { } else {
writeSettings = stringSettings; writeSettings = stringSettings;
@ -455,8 +438,7 @@ public class SettingsImporter {
// Write identities // Write identities
if (account.identities != null) { if (account.identities != null) {
importIdentities(editor, contentVersion, uuid, account, overwrite, existingAccount, importIdentities(editor, contentVersion, uuid, account, overwrite, existingAccount, prefs);
prefs);
} else if (!mergeImportedAccount) { } else if (!mergeImportedAccount) {
// Require accounts to at least have one identity // Require accounts to at least have one identity
throw new InvalidSettingValueException(); throw new InvalidSettingValueException();
@ -475,8 +457,8 @@ public class SettingsImporter {
return new AccountDescriptionPair(original, imported, mergeImportedAccount); return new AccountDescriptionPair(original, imported, mergeImportedAccount);
} }
private static void importFolder(StorageEditor editor, int contentVersion, private static void importFolder(StorageEditor editor, int contentVersion, String uuid, ImportedFolder folder,
String uuid, ImportedFolder folder, boolean overwrite, Preferences prefs) { boolean overwrite, Preferences prefs) {
// Validate folder settings // Validate folder settings
Map<String, Object> validatedSettings = Map<String, Object> validatedSettings =
@ -493,8 +475,7 @@ public class SettingsImporter {
// Merge folder settings if necessary // Merge folder settings if necessary
Map<String, String> writeSettings; Map<String, String> writeSettings;
if (overwrite) { if (overwrite) {
writeSettings = FolderSettings.getFolderSettings(prefs.getStorage(), writeSettings = FolderSettings.getFolderSettings(prefs.getStorage(), uuid, folder.name);
uuid, folder.name);
writeSettings.putAll(stringSettings); writeSettings.putAll(stringSettings);
} else { } else {
writeSettings = stringSettings; writeSettings = stringSettings;
@ -509,9 +490,8 @@ public class SettingsImporter {
} }
} }
private static void importIdentities(StorageEditor editor, int contentVersion, private static void importIdentities(StorageEditor editor, int contentVersion, String uuid, ImportedAccount account,
String uuid, ImportedAccount account, boolean overwrite, Account existingAccount, boolean overwrite, Account existingAccount, Preferences prefs) throws InvalidSettingValueException {
Preferences prefs) throws InvalidSettingValueException {
String accountKeyPrefix = uuid + "."; String accountKeyPrefix = uuid + ".";
@ -540,8 +520,7 @@ public class SettingsImporter {
nextIdentityIndex++; nextIdentityIndex++;
} }
String identityDescription = (identity.description == null) ? String identityDescription = (identity.description == null) ? "Imported" : identity.description;
"Imported" : identity.description;
if (isIdentityDescriptionUsed(identityDescription, existingIdentities)) { if (isIdentityDescriptionUsed(identityDescription, existingIdentities)) {
// Identity description is already in use. So generate a new one by appending // Identity description is already in use. So generate a new one by appending
// " (x)", where x is the first number >= 1 that results in an unused identity // " (x)", where x is the first number >= 1 that results in an unused identity
@ -558,8 +537,7 @@ public class SettingsImporter {
// Write name used in identity // Write name used in identity
String identityName = (identity.name == null) ? "" : identity.name; String identityName = (identity.name == null) ? "" : identity.name;
putString(editor, accountKeyPrefix + Account.IDENTITY_NAME_KEY + identitySuffix, putString(editor, accountKeyPrefix + Account.IDENTITY_NAME_KEY + identitySuffix, identityName);
identityName);
// Validate email address // Validate email address
if (!IdentitySettings.isEmailAddressValid(identity.email)) { if (!IdentitySettings.isEmailAddressValid(identity.email)) {
@ -567,8 +545,7 @@ public class SettingsImporter {
} }
// Write email address // Write email address
putString(editor, accountKeyPrefix + Account.IDENTITY_EMAIL_KEY + identitySuffix, putString(editor, accountKeyPrefix + Account.IDENTITY_EMAIL_KEY + identitySuffix, identity.email);
identity.email);
// Write identity description // Write identity description
putString(editor, accountKeyPrefix + Account.IDENTITY_DESCRIPTION_KEY + identitySuffix, putString(editor, accountKeyPrefix + Account.IDENTITY_DESCRIPTION_KEY + identitySuffix,
@ -629,8 +606,7 @@ public class SettingsImporter {
return false; return false;
} }
private static int findIdentity(ImportedIdentity identity, private static int findIdentity(ImportedIdentity identity, List<Identity> identities) {
List<Identity> identities) {
for (int i = 0; i < identities.size(); i++) { for (int i = 0; i < identities.size(); i++) {
Identity existingIdentity = identities.get(i); Identity existingIdentity = identities.get(i);
if (existingIdentity.getName().equals(identity.name) && if (existingIdentity.getName().equals(identity.name) &&
@ -655,8 +631,7 @@ public class SettingsImporter {
private static void putString(StorageEditor editor, String key, String value) { private static void putString(StorageEditor editor, String key, String value) {
if (K9.DEBUG) { if (K9.DEBUG) {
String outputValue = value; String outputValue = value;
if (!K9.DEBUG_SENSITIVE && if (!K9.DEBUG_SENSITIVE && (key.endsWith(".transportUri") || key.endsWith(".storeUri"))) {
(key.endsWith(".transportUri") || key.endsWith(".storeUri"))) {
outputValue = "*sensitive*"; outputValue = "*sensitive*";
} }
Log.v(K9.LOG_TAG, "Setting " + key + "=" + outputValue); Log.v(K9.LOG_TAG, "Setting " + key + "=" + outputValue);
@ -665,9 +640,8 @@ public class SettingsImporter {
} }
@VisibleForTesting @VisibleForTesting
static Imported parseSettings(InputStream inputStream, boolean globalSettings, static Imported parseSettings(InputStream inputStream, boolean globalSettings, List<String> accountUuids,
List<String> accountUuids, boolean overview) boolean overview) throws SettingsImportExportException {
throws SettingsImportExportException {
if (!overview && accountUuids == null) { if (!overview && accountUuids == null) {
throw new IllegalArgumentException("Argument 'accountUuids' must not be null."); throw new IllegalArgumentException("Argument 'accountUuids' must not be null.");
@ -694,8 +668,7 @@ public class SettingsImporter {
eventType = xpp.next(); eventType = xpp.next();
} }
if (imported == null || (overview && imported.globalSettings == null && if (imported == null || (overview && imported.globalSettings == null && imported.accounts == null)) {
imported.accounts == null)) {
throw new SettingsImportExportException("Invalid import data"); throw new SettingsImportExportException("Invalid import data");
} }
@ -705,18 +678,14 @@ public class SettingsImporter {
} }
} }
private static void skipToEndTag(XmlPullParser xpp, String endTag) private static void skipToEndTag(XmlPullParser xpp, String endTag) throws XmlPullParserException, IOException {
throws XmlPullParserException, IOException {
int eventType = xpp.next(); int eventType = xpp.next();
while (!(eventType == XmlPullParser.END_TAG && endTag.equals(xpp.getName()))) { while (!(eventType == XmlPullParser.END_TAG && endTag.equals(xpp.getName()))) {
eventType = xpp.next(); eventType = xpp.next();
} }
} }
private static String getText(XmlPullParser xpp) private static String getText(XmlPullParser xpp) throws XmlPullParserException, IOException {
throws XmlPullParserException, IOException {
int eventType = xpp.next(); int eventType = xpp.next();
if (eventType != XmlPullParser.TEXT) { if (eventType != XmlPullParser.TEXT) {
return ""; return "";
@ -724,24 +693,19 @@ public class SettingsImporter {
return xpp.getText(); return xpp.getText();
} }
private static Imported parseRoot(XmlPullParser xpp, boolean globalSettings, private static Imported parseRoot(XmlPullParser xpp, boolean globalSettings, List<String> accountUuids,
List<String> accountUuids, boolean overview) boolean overview) throws XmlPullParserException, IOException, SettingsImportExportException {
throws XmlPullParserException, IOException, SettingsImportExportException {
Imported result = new Imported(); Imported result = new Imported();
String fileFormatVersionString = xpp.getAttributeValue(null, String fileFormatVersionString = xpp.getAttributeValue(null, SettingsExporter.FILE_FORMAT_ATTRIBUTE);
SettingsExporter.FILE_FORMAT_ATTRIBUTE);
validateFileFormatVersion(fileFormatVersionString); validateFileFormatVersion(fileFormatVersionString);
String contentVersionString = xpp.getAttributeValue(null, String contentVersionString = xpp.getAttributeValue(null, SettingsExporter.VERSION_ATTRIBUTE);
SettingsExporter.VERSION_ATTRIBUTE);
result.contentVersion = validateContentVersion(contentVersionString); result.contentVersion = validateContentVersion(contentVersionString);
int eventType = xpp.next(); int eventType = xpp.next();
while (!(eventType == XmlPullParser.END_TAG && while (!(eventType == XmlPullParser.END_TAG && SettingsExporter.ROOT_ELEMENT.equals(xpp.getName()))) {
SettingsExporter.ROOT_ELEMENT.equals(xpp.getName()))) {
if(eventType == XmlPullParser.START_TAG) { if(eventType == XmlPullParser.START_TAG) {
String element = xpp.getName(); String element = xpp.getName();
if (SettingsExporter.GLOBAL_ELEMENT.equals(element)) { if (SettingsExporter.GLOBAL_ELEMENT.equals(element)) {
@ -777,9 +741,7 @@ public class SettingsImporter {
return result; return result;
} }
private static int validateFileFormatVersion(String versionString) private static int validateFileFormatVersion(String versionString) throws SettingsImportExportException {
throws SettingsImportExportException {
if (versionString == null) { if (versionString == null) {
throw new SettingsImportExportException("Missing file format version"); throw new SettingsImportExportException("Missing file format version");
} }
@ -788,21 +750,17 @@ public class SettingsImporter {
try { try {
version = Integer.parseInt(versionString); version = Integer.parseInt(versionString);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new SettingsImportExportException("Invalid file format version: " + throw new SettingsImportExportException("Invalid file format version: " + versionString);
versionString);
} }
if (version != SettingsExporter.FILE_FORMAT_VERSION) { if (version != SettingsExporter.FILE_FORMAT_VERSION) {
throw new SettingsImportExportException("Unsupported file format version: " + throw new SettingsImportExportException("Unsupported file format version: " + versionString);
versionString);
} }
return version; return version;
} }
private static int validateContentVersion(String versionString) private static int validateContentVersion(String versionString) throws SettingsImportExportException {
throws SettingsImportExportException {
if (versionString == null) { if (versionString == null) {
throw new SettingsImportExportException("Missing content version"); throw new SettingsImportExportException("Missing content version");
} }
@ -811,8 +769,7 @@ public class SettingsImporter {
try { try {
version = Integer.parseInt(versionString); version = Integer.parseInt(versionString);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new SettingsImportExportException("Invalid content version: " + throw new SettingsImportExportException("Invalid content version: " + versionString);
versionString);
} }
if (version < 1) { if (version < 1) {
@ -855,16 +812,13 @@ public class SettingsImporter {
return result; return result;
} }
private static Map<String, ImportedAccount> parseAccounts(XmlPullParser xpp, private static Map<String, ImportedAccount> parseAccounts(XmlPullParser xpp, List<String> accountUuids,
List<String> accountUuids, boolean overview) boolean overview) throws XmlPullParserException, IOException {
throws XmlPullParserException, IOException {
Map<String, ImportedAccount> accounts = null; Map<String, ImportedAccount> accounts = null;
int eventType = xpp.next(); int eventType = xpp.next();
while (!(eventType == XmlPullParser.END_TAG && while (!(eventType == XmlPullParser.END_TAG && SettingsExporter.ACCOUNTS_ELEMENT.equals(xpp.getName()))) {
SettingsExporter.ACCOUNTS_ELEMENT.equals(xpp.getName()))) {
if(eventType == XmlPullParser.START_TAG) { if(eventType == XmlPullParser.START_TAG) {
String element = xpp.getName(); String element = xpp.getName();
if (SettingsExporter.ACCOUNT_ELEMENT.equals(element)) { if (SettingsExporter.ACCOUNT_ELEMENT.equals(element)) {
@ -879,8 +833,7 @@ public class SettingsImporter {
} else if (!accounts.containsKey(account.uuid)) { } else if (!accounts.containsKey(account.uuid)) {
accounts.put(account.uuid, account); accounts.put(account.uuid, account);
} else { } else {
Log.w(K9.LOG_TAG, "Duplicate account entries with UUID " + account.uuid + Log.w(K9.LOG_TAG, "Duplicate account entries with UUID " + account.uuid + ". Ignoring!");
". Ignoring!");
} }
} else { } else {
Log.w(K9.LOG_TAG, "Unexpected start tag: " + xpp.getName()); Log.w(K9.LOG_TAG, "Unexpected start tag: " + xpp.getName());
@ -892,8 +845,7 @@ public class SettingsImporter {
return accounts; return accounts;
} }
private static ImportedAccount parseAccount(XmlPullParser xpp, List<String> accountUuids, private static ImportedAccount parseAccount(XmlPullParser xpp, List<String> accountUuids, boolean overview)
boolean overview)
throws XmlPullParserException, IOException { throws XmlPullParserException, IOException {
String uuid = xpp.getAttributeValue(null, SettingsExporter.UUID_ATTRIBUTE); String uuid = xpp.getAttributeValue(null, SettingsExporter.UUID_ATTRIBUTE);
@ -911,9 +863,7 @@ public class SettingsImporter {
if (overview || accountUuids.contains(uuid)) { if (overview || accountUuids.contains(uuid)) {
int eventType = xpp.next(); int eventType = xpp.next();
while (!(eventType == XmlPullParser.END_TAG && while (!(eventType == XmlPullParser.END_TAG && SettingsExporter.ACCOUNT_ELEMENT.equals(xpp.getName()))) {
SettingsExporter.ACCOUNT_ELEMENT.equals(xpp.getName()))) {
if(eventType == XmlPullParser.START_TAG) { if(eventType == XmlPullParser.START_TAG) {
String element = xpp.getName(); String element = xpp.getName();
if (SettingsExporter.NAME_ELEMENT.equals(element)) { if (SettingsExporter.NAME_ELEMENT.equals(element)) {
@ -1005,9 +955,7 @@ public class SettingsImporter {
List<ImportedIdentity> identities = null; List<ImportedIdentity> identities = null;
int eventType = xpp.next(); int eventType = xpp.next();
while (!(eventType == XmlPullParser.END_TAG && while (!(eventType == XmlPullParser.END_TAG && SettingsExporter.IDENTITIES_ELEMENT.equals(xpp.getName()))) {
SettingsExporter.IDENTITIES_ELEMENT.equals(xpp.getName()))) {
if(eventType == XmlPullParser.START_TAG) { if(eventType == XmlPullParser.START_TAG) {
String element = xpp.getName(); String element = xpp.getName();
if (SettingsExporter.IDENTITY_ELEMENT.equals(element)) { if (SettingsExporter.IDENTITY_ELEMENT.equals(element)) {
@ -1027,13 +975,11 @@ public class SettingsImporter {
return identities; return identities;
} }
private static ImportedIdentity parseIdentity(XmlPullParser xpp) private static ImportedIdentity parseIdentity(XmlPullParser xpp) throws XmlPullParserException, IOException {
throws XmlPullParserException, IOException {
ImportedIdentity identity = new ImportedIdentity(); ImportedIdentity identity = new ImportedIdentity();
int eventType = xpp.next(); int eventType = xpp.next();
while (!(eventType == XmlPullParser.END_TAG && while (!(eventType == XmlPullParser.END_TAG && SettingsExporter.IDENTITY_ELEMENT.equals(xpp.getName()))) {
SettingsExporter.IDENTITY_ELEMENT.equals(xpp.getName()))) {
if(eventType == XmlPullParser.START_TAG) { if(eventType == XmlPullParser.START_TAG) {
String element = xpp.getName(); String element = xpp.getName();
@ -1055,14 +1001,11 @@ public class SettingsImporter {
return identity; return identity;
} }
private static List<ImportedFolder> parseFolders(XmlPullParser xpp) private static List<ImportedFolder> parseFolders(XmlPullParser xpp) throws XmlPullParserException, IOException {
throws XmlPullParserException, IOException {
List<ImportedFolder> folders = null; List<ImportedFolder> folders = null;
int eventType = xpp.next(); int eventType = xpp.next();
while (!(eventType == XmlPullParser.END_TAG && while (!(eventType == XmlPullParser.END_TAG && SettingsExporter.FOLDERS_ELEMENT.equals(xpp.getName()))) {
SettingsExporter.FOLDERS_ELEMENT.equals(xpp.getName()))) {
if(eventType == XmlPullParser.START_TAG) { if(eventType == XmlPullParser.START_TAG) {
String element = xpp.getName(); String element = xpp.getName();
if (SettingsExporter.FOLDER_ELEMENT.equals(element)) { if (SettingsExporter.FOLDER_ELEMENT.equals(element)) {
@ -1082,8 +1025,7 @@ public class SettingsImporter {
return folders; return folders;
} }
private static ImportedFolder parseFolder(XmlPullParser xpp) private static ImportedFolder parseFolder(XmlPullParser xpp) throws XmlPullParserException, IOException {
throws XmlPullParserException, IOException {
ImportedFolder folder = new ImportedFolder(); ImportedFolder folder = new ImportedFolder();
String name = xpp.getAttributeValue(null, SettingsExporter.NAME_ATTRIBUTE); String name = xpp.getAttributeValue(null, SettingsExporter.NAME_ATTRIBUTE);