@@ -128,11 +128,9 @@ public void run() {
128128 */
129129 void loadConfigFromStorage (@ Nullable String sdkBehaviorSettings ) {
130130 String sConfig = storageProvider .getServerConfig ();
131- boolean providedSettingsUsed = false ;
132131
133132 if (Utils .isNullOrEmpty (sConfig ) && !Utils .isNullOrEmpty (sdkBehaviorSettings )) {
134133 sConfig = sdkBehaviorSettings ;
135- providedSettingsUsed = true ;
136134 }
137135
138136 L .v ("[ModuleConfiguration] loadConfigFromStorage, [" + sConfig + "]" );
@@ -146,9 +144,7 @@ void loadConfigFromStorage(@Nullable String sdkBehaviorSettings) {
146144 latestRetrievedConfigurationFull = new JSONObject (sConfig );
147145 latestRetrievedConfiguration = latestRetrievedConfigurationFull .getJSONObject (keyRConfig );
148146 L .d ("[ModuleConfiguration] loadStoredConfig, stored config loaded [" + sConfig + "]" );
149- if (providedSettingsUsed ) {
150- saveAndStoreDownloadedConfig (latestRetrievedConfigurationFull );
151- }
147+ saveAndStoreDownloadedConfig (latestRetrievedConfigurationFull );
152148 } catch (JSONException e ) {
153149 L .w ("[ModuleConfiguration] loadStoredConfig, failed to parse, " + e );
154150
@@ -182,8 +178,8 @@ private <T> T extractValue(String key, StringBuilder sb, T currentValue, T defau
182178 return currentValue ;
183179 }
184180
185- private < T > T extractValue (String key , StringBuilder sb , T currentValue , T defaultValue , Class < T > clazz ) {
186- return extractValue (key , sb , currentValue , defaultValue , clazz , null );
181+ private Boolean extractValue (String key , StringBuilder sb , Boolean currentValue , Boolean defaultValue ) {
182+ return extractValue (key , sb , currentValue , defaultValue , Boolean . class , null );
187183 }
188184
189185 //update the config variables according to the current config obj state
@@ -196,25 +192,25 @@ private void updateConfigVariables(@NonNull final CountlyConfig clyConfig) {
196192
197193 StringBuilder sb = new StringBuilder ();
198194
199- currentVNetworking = extractValue (keyRNetworking , sb , currentVNetworking , currentVNetworking , Boolean . class );
200- currentVTracking = extractValue (keyRTracking , sb , currentVTracking , currentVTracking , Boolean . class );
201- currentVSessionTracking = extractValue (keyRSessionTracking , sb , currentVSessionTracking , currentVSessionTracking , Boolean . class );
202- currentVCrashReporting = extractValue (keyRCrashReporting , sb , currentVCrashReporting , currentVCrashReporting , Boolean . class );
203- currentVViewTracking = extractValue (keyRViewTracking , sb , currentVViewTracking , currentVViewTracking , Boolean . class );
204- currentVCustomEventTracking = extractValue (keyRCustomEventTracking , sb , currentVCustomEventTracking , currentVCustomEventTracking , Boolean . class );
205- currentVLocationTracking = extractValue (keyRLocationTracking , sb , currentVLocationTracking , currentVLocationTracking , Boolean . class );
206- currentVContentZone = extractValue (keyREnterContentZone , sb , currentVContentZone , currentVContentZone , Boolean . class );
195+ currentVNetworking = extractValue (keyRNetworking , sb , currentVNetworking , currentVNetworking );
196+ currentVTracking = extractValue (keyRTracking , sb , currentVTracking , currentVTracking );
197+ currentVSessionTracking = extractValue (keyRSessionTracking , sb , currentVSessionTracking , currentVSessionTracking );
198+ currentVCrashReporting = extractValue (keyRCrashReporting , sb , currentVCrashReporting , currentVCrashReporting );
199+ currentVViewTracking = extractValue (keyRViewTracking , sb , currentVViewTracking , currentVViewTracking );
200+ currentVCustomEventTracking = extractValue (keyRCustomEventTracking , sb , currentVCustomEventTracking , currentVCustomEventTracking );
201+ currentVLocationTracking = extractValue (keyRLocationTracking , sb , currentVLocationTracking , currentVLocationTracking );
202+ currentVContentZone = extractValue (keyREnterContentZone , sb , currentVContentZone , currentVContentZone );
207203 serverConfigUpdateInterval = extractValue (keyRServerConfigUpdateInterval , sb , serverConfigUpdateInterval , currentServerConfigUpdateInterval , Integer .class , (Integer value ) -> value > 0 );
208- currentVRefreshContentZone = extractValue (keyRRefreshContentZone , sb , currentVRefreshContentZone , currentVRefreshContentZone , Boolean . class );
209- currentVBackoffMechanism = extractValue (keyRBackoffMechanism , sb , clyConfig .backOffMechanismEnabled , currentVBackoffMechanism , Boolean . class );
204+ currentVRefreshContentZone = extractValue (keyRRefreshContentZone , sb , currentVRefreshContentZone , currentVRefreshContentZone );
205+ currentVBackoffMechanism = extractValue (keyRBackoffMechanism , sb , clyConfig .backOffMechanismEnabled , currentVBackoffMechanism );
210206 currentVBOMAcceptedTimeoutSeconds = extractValue (keyRBOMAcceptedTimeout , sb , currentVBOMAcceptedTimeoutSeconds , currentVBOMAcceptedTimeoutSeconds , Integer .class , (Integer value ) -> value > 0 );
211- currentVBOMRQPercentage = extractValue (keyRBOMRQPercentage , sb , currentVBOMRQPercentage , currentVBOMRQPercentage , Double .class , (Double value ) -> ( value > 0.0 && value < 1.0 ) );
207+ currentVBOMRQPercentage = extractValue (keyRBOMRQPercentage , sb , currentVBOMRQPercentage , currentVBOMRQPercentage , Double .class , (Double value ) -> value > 0.0 && value < 1.0 );
212208 currentVBOMRequestAge = extractValue (keyRBOMRequestAge , sb , currentVBOMRequestAge , currentVBOMRequestAge , Integer .class , (Integer value ) -> value > 0 );
213209 currentVBOMDuration = extractValue (keyRBOMDuration , sb , currentVBOMDuration , currentVBOMDuration , Integer .class , (Integer value ) -> value > 0 );
214210
215211 clyConfig .setMaxRequestQueueSize (extractValue (keyRReqQueueSize , sb , clyConfig .maxRequestQueueSize , clyConfig .maxRequestQueueSize , Integer .class , (Integer value ) -> value > 0 ));
216212 clyConfig .setEventQueueSizeToSend (extractValue (keyREventQueueSize , sb , clyConfig .eventQueueSizeThreshold , Countly .sharedInstance ().EVENT_QUEUE_SIZE_THRESHOLD , Integer .class , (Integer value ) -> value > 0 ));
217- clyConfig .setLoggingEnabled (extractValue (keyRLogging , sb , clyConfig .loggingEnabled , clyConfig .loggingEnabled , Boolean . class ));
213+ clyConfig .setLoggingEnabled (extractValue (keyRLogging , sb , clyConfig .loggingEnabled , clyConfig .loggingEnabled ));
218214 clyConfig .setUpdateSessionTimerDelay (extractValue (keyRSessionUpdateInterval , sb , clyConfig .sessionUpdateTimerDelay , Long .valueOf (Countly .TIMER_DELAY_IN_SECONDS ).intValue (), Integer .class , (Integer value ) -> value > 0 ));
219215 clyConfig .sdkInternalLimits .setMaxKeyLength (extractValue (keyRLimitKeyLength , sb , clyConfig .sdkInternalLimits .maxKeyLength , Countly .maxKeyLengthDefault , Integer .class , (Integer value ) -> value > 0 ));
220216 clyConfig .sdkInternalLimits .setMaxValueSize (extractValue (keyRLimitValueSize , sb , clyConfig .sdkInternalLimits .maxValueSize , Countly .maxValueSizeDefault , Integer .class , (Integer value ) -> value > 0 ));
@@ -223,7 +219,7 @@ private void updateConfigVariables(@NonNull final CountlyConfig clyConfig) {
223219 clyConfig .sdkInternalLimits .setMaxStackTraceLinesPerThread (extractValue (keyRLimitTraceLine , sb , clyConfig .sdkInternalLimits .maxStackTraceLinesPerThread , Countly .maxStackTraceLinesPerThreadDefault , Integer .class , (Integer value ) -> value > 0 ));
224220 clyConfig .sdkInternalLimits .setMaxStackTraceLineLength (extractValue (keyRLimitTraceLength , sb , clyConfig .sdkInternalLimits .maxStackTraceLineLength , Countly .maxStackTraceLineLengthDefault , Integer .class , (Integer value ) -> value > 0 ));
225221 clyConfig .content .setZoneTimerInterval (extractValue (keyRContentZoneInterval , sb , clyConfig .content .zoneTimerInterval , clyConfig .content .zoneTimerInterval , Integer .class , (Integer value ) -> value >= 16 ));
226- clyConfig .setRequiresConsent (extractValue (keyRConsentRequired , sb , clyConfig .shouldRequireConsent , clyConfig .shouldRequireConsent , Boolean . class ));
222+ clyConfig .setRequiresConsent (extractValue (keyRConsentRequired , sb , clyConfig .shouldRequireConsent , clyConfig .shouldRequireConsent ));
227223 clyConfig .setRequestDropAgeHours (extractValue (keyRDropOldRequestTime , sb , clyConfig .dropAgeHours , clyConfig .dropAgeHours , Integer .class , (Integer value ) -> value >= 0 ));
228224
229225 String updatedValues = sb .toString ();
@@ -233,29 +229,113 @@ private void updateConfigVariables(@NonNull final CountlyConfig clyConfig) {
233229 }
234230 }
235231
236- void saveAndStoreDownloadedConfig (@ NonNull JSONObject config ) {
237- L .v ("[ModuleConfiguration] saveAndStoreDownloadedConfig" );
232+ boolean validateServerConfig (@ NonNull JSONObject config ) {
233+ JSONObject newInner = config .optJSONObject (keyRConfig );
234+
235+ L .v ("[ModuleConfiguration] validateServerConfig" );
238236 if (!config .has (keyRVersion )) {
239- L .w ("[ModuleConfiguration] saveAndStoreDownloadedConfig, Retrieved configuration does not has a 'version' field. Config will be ignored." );
240- return ;
237+ L .w ("[ModuleConfiguration] validateServerConfig, Retrieved configuration does not has a 'version' field. Config will be ignored." );
238+ return false ;
239+ } else if (!config .has (keyRTimestamp )) {
240+ L .w ("[ModuleConfiguration] validateServerConfig, Retrieved configuration does not has a 'timestamp' field. Config will be ignored." );
241+ return false ;
242+ } else if (!config .has (keyRConfig )) {
243+ L .w ("[ModuleConfiguration] validateServerConfig, Retrieved configuration does not has a 'configuration' field. Config will be ignored." );
244+ return false ;
245+ } else if (config .length () != 3 ) {
246+ L .w ("[ModuleConfiguration] validateServerConfig, Retrieved configuration does not have the expected number of keys. Config will be ignored." );
247+ return false ;
248+ } else if (newInner == null || newInner .length () == 0 ) {
249+ L .d ("[ModuleConfiguration] validateServerConfig, Config rejected: inner 'c' object is invalid or empty." );
250+ return false ;
241251 }
242252
243- if (!config .has (keyRTimestamp )) {
244- L .w ("[ModuleConfiguration] saveAndStoreDownloadedConfig, Retrieved configuration does not has a 'timestamp' field. Config will be ignored." );
245- return ;
246- }
253+ removeUnsupportedKeys (newInner );
254+ return true ;
255+ }
247256
248- if (!config .has (keyRConfig )) {
249- L .w ("[ModuleConfiguration] saveAndStoreDownloadedConfig, Retrieved configuration does not has a 'configuration' field. Config will be ignored." );
250- return ;
257+ private void removeUnsupportedKeys (@ NonNull JSONObject newInner ) {
258+ Iterator <String > keys = newInner .keys ();
259+ while (keys .hasNext ()) {
260+ String key = keys .next ();
261+ Object value = newInner .opt (key );
262+
263+ boolean isValid = false ;
264+
265+ // --- Boolean keys ---
266+ switch (key ) {
267+ case keyRNetworking :
268+ case keyRTracking :
269+ case keyRSessionTracking :
270+ case keyRCrashReporting :
271+ case keyRViewTracking :
272+ case keyRCustomEventTracking :
273+ case keyRLocationTracking :
274+ case keyREnterContentZone :
275+ case keyRRefreshContentZone :
276+ case keyRBackoffMechanism :
277+ case keyRLogging :
278+ case keyRConsentRequired :
279+ isValid = value instanceof Boolean ;
280+ break ;
281+
282+ // --- Positive Integer keys (> 0) ---
283+ case keyRServerConfigUpdateInterval :
284+ case keyRBOMAcceptedTimeout :
285+ case keyRBOMRequestAge :
286+ case keyRBOMDuration :
287+ case keyRReqQueueSize :
288+ case keyREventQueueSize :
289+ case keyRSessionUpdateInterval :
290+ case keyRLimitKeyLength :
291+ case keyRLimitValueSize :
292+ case keyRLimitSegValues :
293+ case keyRLimitBreadcrumb :
294+ case keyRLimitTraceLine :
295+ case keyRLimitTraceLength :
296+ isValid = value instanceof Integer && ((Integer ) value ) > 0 ;
297+ break ;
298+
299+ // --- Integer >= 0 ---
300+ case keyRDropOldRequestTime :
301+ isValid = value instanceof Integer && ((Integer ) value ) >= 0 ;
302+ break ;
303+
304+ // --- Integer >= 16 ---
305+ case keyRContentZoneInterval :
306+ isValid = value instanceof Integer && ((Integer ) value ) >= 16 ;
307+ break ;
308+
309+ // --- Double between 0.0 and 1.0 ---
310+ case keyRBOMRQPercentage :
311+ isValid = value instanceof Double && ((Double ) value > 0.0 && (Double ) value < 1.0 );
312+ break ;
313+ // --- Unknown keys ---
314+ default :
315+ L .w ("[ModuleConfiguration] removeUnsupportedKeys, Unknown key: [" + key + "], removing it. value: [" + value + "]" );
316+ break ;
317+ }
318+
319+ // --- If not valid or not known, remove it ---
320+ if (!isValid ) {
321+ L .w ("[ModuleConfiguration] removeUnsupportedKeys, Invalid or unknown key: [" + key + "], removing it. value: [" + value + "]" );
322+ keys .remove ();
323+ }
251324 }
325+ }
252326
253- JSONObject newInner = config .optJSONObject (keyRConfig );
254- if (newInner == null || newInner .length () == 0 ) {
255- L .d ("[ModuleConfiguration] Config rejected: inner 'c' object is invalid or empty." );
327+ void saveAndStoreDownloadedConfig (@ NonNull JSONObject config ) {
328+ L .v ("[ModuleConfiguration] saveAndStoreDownloadedConfig" );
329+ boolean validConfig = validateServerConfig (config );
330+ if (!validConfig ) {
331+ L .w ("[ModuleConfiguration] saveAndStoreDownloadedConfig, Retrieved configuration is not valid, ignoring it." );
332+ latestRetrievedConfigurationFull = null ;
333+ latestRetrievedConfiguration = null ;
256334 return ;
257335 }
258336
337+ JSONObject newInner = config .optJSONObject (keyRConfig );
338+ assert newInner != null ;
259339 if (latestRetrievedConfigurationFull == null ) {
260340 latestRetrievedConfigurationFull = new JSONObject ();
261341 latestRetrievedConfiguration = new JSONObject ();
0 commit comments