diff --git a/packages/CMSettingsProvider/src/org/cyanogenmod/cmsettings/CMSettingsProvider.java b/packages/CMSettingsProvider/src/org/cyanogenmod/cmsettings/CMSettingsProvider.java index 5c837bd..ff65aab 100644 --- a/packages/CMSettingsProvider/src/org/cyanogenmod/cmsettings/CMSettingsProvider.java +++ b/packages/CMSettingsProvider/src/org/cyanogenmod/cmsettings/CMSettingsProvider.java @@ -522,9 +522,11 @@ public class CMSettingsProvider extends ContentProvider { // Validate value if inserting int System table final String name = values.getAsString(Settings.NameValueTable.NAME); + final String value = values.getAsString(Settings.NameValueTable.VALUE); if (CMDatabaseHelper.CMTableNames.TABLE_SYSTEM.equals(tableName)) { - final String value = values.getAsString(Settings.NameValueTable.VALUE); validateSystemSettingNameValue(name, value); + } else if (CMDatabaseHelper.CMTableNames.TABLE_SECURE.equals(tableName)) { + validateSecureSettingValue(name, value); } SQLiteDatabase db = dbHelper.getWritableDatabase(); @@ -591,9 +593,11 @@ public class CMSettingsProvider extends ContentProvider { // Validate value if updating System table final String name = values.getAsString(Settings.NameValueTable.NAME); + final String value = values.getAsString(Settings.NameValueTable.VALUE); if (CMDatabaseHelper.CMTableNames.TABLE_SYSTEM.equals(tableName)) { - final String value = values.getAsString(Settings.NameValueTable.VALUE); validateSystemSettingNameValue(name, value); + } else if (CMDatabaseHelper.CMTableNames.TABLE_SECURE.equals(tableName)) { + validateSecureSettingValue(name, value); } int callingUserId = UserHandle.getCallingUserId(); @@ -792,7 +796,7 @@ public class CMSettingsProvider extends ContentProvider { } private void validateSystemSettingNameValue(String name, String value) { - CMSettings.System.Validator validator = CMSettings.System.VALIDATORS.get(name); + CMSettings.Validator validator = CMSettings.System.VALIDATORS.get(name); if (validator == null) { throw new IllegalArgumentException("Invalid setting: " + name); } @@ -803,5 +807,16 @@ public class CMSettingsProvider extends ContentProvider { } } + private void validateSecureSettingValue(String name, String value) { + CMSettings.Validator validator = CMSettings.Secure.VALIDATORS.get(name); + + // Not all secure settings have validators, but if a validator exists, the validate method + // should return true + if (validator != null && !validator.validate(value)) { + throw new IllegalArgumentException("Invalid value: " + value + + " for setting: " + name); + } + } + // TODO Add caching } diff --git a/src/java/cyanogenmod/providers/CMSettings.java b/src/java/cyanogenmod/providers/CMSettings.java index 4b563bc..4b2fb7c 100644 --- a/src/java/cyanogenmod/providers/CMSettings.java +++ b/src/java/cyanogenmod/providers/CMSettings.java @@ -269,6 +269,140 @@ public final class CMSettings { } } + // region Validators + + /** @hide */ + public static interface Validator { + public boolean validate(String value); + } + + private static final Validator sBooleanValidator = + new DiscreteValueValidator(new String[] {"0", "1"}); + + private static final Validator sNonNegativeIntegerValidator = new Validator() { + @Override + public boolean validate(String value) { + try { + return Integer.parseInt(value) >= 0; + } catch (NumberFormatException e) { + return false; + } + } + }; + + private static final Validator sUriValidator = new Validator() { + @Override + public boolean validate(String value) { + try { + Uri.decode(value); + return true; + } catch (IllegalArgumentException e) { + return false; + } + } + }; + + private static final Validator sColorValidator = + new InclusiveIntegerRangeValidator(Integer.MIN_VALUE, Integer.MAX_VALUE); + + private static final Validator sAlwaysTrueValidator = new Validator() { + @Override + public boolean validate(String value) { + return true; + } + }; + + private static final class DiscreteValueValidator implements Validator { + private final String[] mValues; + + public DiscreteValueValidator(String[] values) { + mValues = values; + } + + @Override + public boolean validate(String value) { + return ArrayUtils.contains(mValues, value); + } + } + + private static final class InclusiveIntegerRangeValidator implements Validator { + private final int mMin; + private final int mMax; + + public InclusiveIntegerRangeValidator(int min, int max) { + mMin = min; + mMax = max; + } + + @Override + public boolean validate(String value) { + try { + final int intValue = Integer.parseInt(value); + return intValue >= mMin && intValue <= mMax; + } catch (NumberFormatException e) { + return false; + } + } + } + + private static final class InclusiveFloatRangeValidator implements Validator { + private final float mMin; + private final float mMax; + + public InclusiveFloatRangeValidator(float min, float max) { + mMin = min; + mMax = max; + } + + @Override + public boolean validate(String value) { + try { + final float floatValue = Float.parseFloat(value); + return floatValue >= mMin && floatValue <= mMax; + } catch (NumberFormatException e) { + return false; + } + } + } + + private static final class DelimitedListValidator implements Validator { + private final ArraySet mValidValueSet; + private final String mDelimiter; + private final boolean mAllowEmptyList; + + public DelimitedListValidator(String[] validValues, String delimiter, + boolean allowEmptyList) { + mValidValueSet = new ArraySet(Arrays.asList(validValues)); + mDelimiter = delimiter; + mAllowEmptyList = allowEmptyList; + } + + @Override + public boolean validate(String value) { + ArraySet values = new ArraySet(); + if (!TextUtils.isEmpty(value)) { + final String[] array = TextUtils.split(value, Pattern.quote(mDelimiter)); + for (String item : array) { + if (TextUtils.isEmpty(item)) { + continue; + } + values.add(item); + } + } + if (values.size() > 0) { + values.removeAll(mValidValueSet); + // values.size() will be non-zero if it contains any values not in + // mValidValueSet + return values.size() == 0; + } else if (mAllowEmptyList) { + return true; + } + + return false; + } + } + // endregion Validators + /** * System settings, containing miscellaneous CM system preferences. This table holds simple * name/value pairs. There are convenience functions for accessing individual settings entries. @@ -278,53 +412,12 @@ public final class CMSettings { public static final String SYS_PROP_CM_SETTING_VERSION = "sys.cm_settings_system_version"; - /** @hide */ - public static interface Validator { - public boolean validate(String value); - } - private static final NameValueCache sNameValueCache = new NameValueCache( SYS_PROP_CM_SETTING_VERSION, CONTENT_URI, CALL_METHOD_GET_SYSTEM, CALL_METHOD_PUT_SYSTEM); - private static final Validator sBooleanValidator = - new DiscreteValueValidator(new String[] {"0", "1"}); - - private static final Validator sNonNegativeIntegerValidator = new Validator() { - @Override - public boolean validate(String value) { - try { - return Integer.parseInt(value) >= 0; - } catch (NumberFormatException e) { - return false; - } - } - }; - - private static final Validator sUriValidator = new Validator() { - @Override - public boolean validate(String value) { - try { - Uri.decode(value); - return true; - } catch (IllegalArgumentException e) { - return false; - } - } - }; - - private static final Validator sColorValidator = - new InclusiveIntegerRangeValidator(Integer.MIN_VALUE, Integer.MAX_VALUE); - - private static final Validator sAlwaysTrueValidator = new Validator() { - @Override - public boolean validate(String value) { - return true; - } - }; - // region Methods /** @@ -671,116 +764,6 @@ public final class CMSettings { // endregion - private static final class DiscreteValueValidator implements Validator { - private final String[] mValues; - - public DiscreteValueValidator(String[] values) { - mValues = values; - } - - @Override - public boolean validate(String value) { - return ArrayUtils.contains(mValues, value); - } - } - - private static final class InclusiveIntegerRangeValidator implements Validator { - private final int mMin; - private final int mMax; - - public InclusiveIntegerRangeValidator(int min, int max) { - mMin = min; - mMax = max; - } - - @Override - public boolean validate(String value) { - try { - final int intValue = Integer.parseInt(value); - return intValue >= mMin && intValue <= mMax; - } catch (NumberFormatException e) { - return false; - } - } - } - - private static final class InclusiveFloatRangeValidator implements Validator { - private final float mMin; - private final float mMax; - - public InclusiveFloatRangeValidator(float min, float max) { - mMin = min; - mMax = max; - } - - @Override - public boolean validate(String value) { - try { - final float floatValue = Float.parseFloat(value); - return floatValue >= mMin && floatValue <= mMax; - } catch (NumberFormatException e) { - return false; - } - } - } - - private static final class DelimitedListValidator implements Validator { - private final ArraySet mValidValueSet; - private final String mDelimiter; - private final boolean mAllowEmptyList; - - public DelimitedListValidator(String[] validValues, String delimiter, - boolean allowEmptyList) { - mValidValueSet = new ArraySet(Arrays.asList(validValues)); - mDelimiter = delimiter; - mAllowEmptyList = allowEmptyList; - } - - @Override - public boolean validate(String value) { - ArraySet values = new ArraySet(); - if (!TextUtils.isEmpty(value)) { - final String[] array = TextUtils.split(value, Pattern.quote(mDelimiter)); - for (String item : array) { - if (TextUtils.isEmpty(item)) { - continue; - } - values.add(item); - } - } - if (values.size() > 0) { - values.removeAll(mValidValueSet); - // values.size() will be non-zero if it contains any values not in - // mValidValueSet - return values.size() == 0; - } else if (mAllowEmptyList) { - return true; - } - - return false; - } - } - - /** - * @hide - */ - public static final Validator PROTECTED_COMPONENTS_VALIDATOR = new Validator() { - private final String mDelimiter = "|"; - - @Override - public boolean validate(String value) { - if (!TextUtils.isEmpty(value)) { - final String[] array = TextUtils.split(value, Pattern.quote(mDelimiter)); - for (String item : array) { - if (TextUtils.isEmpty(item)) { - return false; // Empty components not allowed - } - } - } - return true; // Empty list is allowed though. - } - }; - // region System Settings /** @@ -2024,7 +2007,6 @@ public final class CMSettings { NOTIFICATION_LIGHT_PULSE_CUSTOM_ENABLE_VALIDATOR); VALIDATORS.put(NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES, NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES_VALIDATOR); - VALIDATORS.put(Secure.PROTECTED_COMPONENTS, PROTECTED_COMPONENTS_VALIDATOR); }; // endregion } @@ -2047,7 +2029,6 @@ public final class CMSettings { // region Methods - /** * Put a delimited list as a string * @param resolver to access the database with @@ -2668,6 +2649,41 @@ public final class CMSettings { public static boolean isLegacySetting(String key) { return ArrayUtils.contains(LEGACY_SECURE_SETTINGS, key); } + + /** + * @hide + */ + public static final Validator PROTECTED_COMPONENTS_VALIDATOR = new Validator() { + private final String mDelimiter = "|"; + + @Override + public boolean validate(String value) { + if (!TextUtils.isEmpty(value)) { + final String[] array = TextUtils.split(value, Pattern.quote(mDelimiter)); + for (String item : array) { + if (TextUtils.isEmpty(item)) { + return false; // Empty components not allowed + } + } + } + return true; // Empty list is allowed though. + } + }; + + /** + * Mapping of validators for all secure settings. This map is used to validate both valid + * keys as well as validating the values for those keys. + * + * Note: Make sure if you add a new Secure setting you create a Validator for it and add + * it to this map. + * + * @hide + */ + public static final Map VALIDATORS = + new ArrayMap(); + static { + VALIDATORS.put(PROTECTED_COMPONENTS, PROTECTED_COMPONENTS_VALIDATOR); + } } /**