Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use none-deprecated archive functions when possible #394

Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion RadarSDK.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,6 @@
children = (
9679F4A027CD8D0600800797 /* CLLocation+Radar.h */,
9679F4A227CD8DE200800797 /* CLLocation+Radar.m */,
53CCD782275E579800F79CC8 /* RadarLogBuffer.m */,
);
name = Util;
sourceTree = "<group>";
Expand Down Expand Up @@ -497,6 +496,7 @@
96A5A11527ADA02E007B960B /* RadarLog.h */,
96A5A11427ADA02E007B960B /* RadarLog.m */,
96A5A11627ADA02E007B960B /* RadarLogBuffer.h */,
53CCD782275E579800F79CC8 /* RadarLogBuffer.m */,
DD236D66230A0D6700EB88F9 /* RadarLogger.h */,
DD236D67230A0D6700EB88F9 /* RadarLogger.m */,
9683FD6127B36C26009EBB6B /* RadarMeta.h */,
Expand Down
2 changes: 1 addition & 1 deletion RadarSDK/RadarLog.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
/**
Represents a debug log.
*/
@interface RadarLog : NSObject <NSCoding>
@interface RadarLog : NSObject <NSSecureCoding>

/**
The levels for debug logs.
Expand Down
4 changes: 4 additions & 0 deletions RadarSDK/RadarLog.m
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,8 @@ - (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:_createdAt forKey:@"createdAt"];
}

+ (BOOL)supportsSecureCoding {
return YES;
}

@end
17 changes: 15 additions & 2 deletions RadarSDK/RadarLogBuffer.m
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,13 @@ - (void)persistLogs {
for (NSString *file in files) {
NSString *filePath = [self.logFileDir stringByAppendingPathComponent:file];
NSData *fileData = [self.fileHandler readFileAtPath:filePath];
RadarLog *log = [NSKeyedUnarchiver unarchiveObjectWithData:fileData];
RadarLog *log;
if (@available(iOS 11.0, *)) {
log = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObjects:[NSString class], [RadarLog class], [NSDate class], nil] fromData:fileData error:nil];
} else {
log = [NSKeyedUnarchiver unarchiveObjectWithData:fileData];
}

if (log && log.message) {
[logs addObject:log];
}
Expand All @@ -122,7 +128,14 @@ - (void)persistLogs {

- (void)writeToFileStorage:(NSArray <RadarLog *> *)logs {
for (RadarLog *log in logs) {
NSData *logData = [NSKeyedArchiver archivedDataWithRootObject:log];

NSData *logData;
if (@available(iOS 11.0, *)) {
logData = [NSKeyedArchiver archivedDataWithRootObject:log requiringSecureCoding:YES error:nil];
} else {
logData = [NSKeyedArchiver archivedDataWithRootObject:log];
}

NSTimeInterval unixTimestamp = [log.createdAt timeIntervalSince1970];
// logs may be created in the same millisecond, so we append a counter to the end of the timestamp to "tiebreak"
NSString *unixTimestampString = [NSString stringWithFormat:@"%lld_%04d", (long long)unixTimestamp, fileCounter++];
Expand Down
2 changes: 1 addition & 1 deletion RadarSDK/RadarReplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#import "Radar.h"

@interface RadarReplay : NSObject <NSCoding>
@interface RadarReplay : NSObject <NSSecureCoding>

@property (nonnull, copy, nonatomic, readonly) NSDictionary *replayParams;

Expand Down
4 changes: 4 additions & 0 deletions RadarSDK/RadarReplay.m
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,8 @@ - (NSUInteger)hash {
return [self.replayParams hash];
}

+ (BOOL)supportsSecureCoding {
return YES;
}

@end
27 changes: 23 additions & 4 deletions RadarSDK/RadarReplayBuffer.m
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,17 @@ - (void)writeNewReplayToBuffer:(NSMutableDictionary *)replayParams {
[prunedBuffer addObject:mutableReplayBuffer[i]];
}
}
replaysData = [NSKeyedArchiver archivedDataWithRootObject:prunedBuffer];
if (@available(iOS 11.0, *)) {
replaysData = [NSKeyedArchiver archivedDataWithRootObject:prunedBuffer requiringSecureCoding:true error:nil];
} else {
replaysData = [NSKeyedArchiver archivedDataWithRootObject:prunedBuffer];
}
} else {
replaysData = [NSKeyedArchiver archivedDataWithRootObject:mutableReplayBuffer];
if (@available(iOS 11.0, *)) {
replaysData = [NSKeyedArchiver archivedDataWithRootObject:mutableReplayBuffer requiringSecureCoding:true error:nil];
} else {
replaysData = [NSKeyedArchiver archivedDataWithRootObject:mutableReplayBuffer];
}
}

[[NSUserDefaults standardUserDefaults] setObject:replaysData forKey:@"radar-replays"];
Expand Down Expand Up @@ -150,14 +158,25 @@ - (void)removeReplaysFromBuffer:(NSArray<RadarReplay *> *)replays {
[mutableReplayBuffer removeObjectsInArray:replays];

// persist the updated buffer
NSData *replaysData = [NSKeyedArchiver archivedDataWithRootObject:mutableReplayBuffer];
NSData *replaysData;
if (@available(iOS 11.0, *)) {
replaysData = [NSKeyedArchiver archivedDataWithRootObject:mutableReplayBuffer requiringSecureCoding:true error:nil];
} else {
replaysData = [NSKeyedArchiver archivedDataWithRootObject:mutableReplayBuffer];
}
[[NSUserDefaults standardUserDefaults] setObject:replaysData forKey:@"radar-replays"];
}

- (void)loadReplaysFromPersistentStore {
NSData *replaysData = [[NSUserDefaults standardUserDefaults] objectForKey:@"radar-replays"];
if (replaysData) {
NSArray *replays = [NSKeyedUnarchiver unarchiveObjectWithData:replaysData];
NSArray *replays;
if (@available(iOS 11.0, *)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little confused about iOS 11 version gate since NSSecureCoding is available from iOS 6

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the archivedDataWithRootObject: requireingSecureCoding: function is only introduced in iOS 11.0. the function that we were using (without the second param) is the one raising security alerts.

NSSet *allowedClasses = [NSSet setWithObjects:[NSArray class], [RadarReplay class], [NSDictionary class], [NSString class], [NSNumber class], nil];
replays = [NSKeyedUnarchiver unarchivedObjectOfClasses:allowedClasses fromData:replaysData error:nil];
} else {
replays = [NSKeyedUnarchiver unarchiveObjectWithData:replaysData];
}
[[RadarLogger sharedInstance] logWithLevel:RadarLogLevelDebug message:[NSString stringWithFormat:@"Loaded replays | length = %lu", (unsigned long)[replays count]]];
mutableReplayBuffer = [NSMutableArray arrayWithArray:replays];
}
Expand Down
21 changes: 19 additions & 2 deletions RadarSDKTests/RadarSDKTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#import "RadarTestUtils.h"
#import "RadarTripOptions.h"
#import "RadarFileStorage.h"

#import "RadarReplayBuffer.h"

@interface RadarSDKTests : XCTestCase

Expand All @@ -30,6 +30,7 @@ @interface RadarSDKTests : XCTestCase
@property (nonatomic, strong) RadarFileStorage *fileSystem;
@property (nonatomic, strong) NSString *testFilePath;
@property (nonatomic, strong) RadarLogBuffer *logBuffer;
@property (nonatomic, strong) RadarReplayBuffer *replayBuffer;
@end

@implementation RadarSDKTests
Expand Down Expand Up @@ -299,7 +300,7 @@ - (void)setUp {
self.testFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"testfile"];
[[RadarLogBuffer sharedInstance]clearBuffer];
[[RadarLogBuffer sharedInstance]setPersistentLogFeatureFlag:YES];

[[RadarReplayBuffer sharedInstance]clearBuffer];
}

- (void)tearDown {
Expand Down Expand Up @@ -1489,6 +1490,22 @@ - (void)test_RadarLogBuffer_purge {
[[RadarLogBuffer sharedInstance]clearBuffer];
}

- (void)test_RadarReplayBuffer_writeAndRead {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you for adding this test

RadarSdkConfiguration *sdkConfiguration = [RadarSettings sdkConfiguration];
sdkConfiguration.usePersistence = true;
[RadarSettings setSdkConfiguration:sdkConfiguration];

CLLocation *location = [[CLLocation alloc] initWithLatitude:0.1 longitude:0.1];
NSMutableDictionary * params = [RadarTestUtils createTrackParamWithLocation:location stopped:YES foreground:YES source:RadarLocationSourceGeofenceEnter replayed:YES beacons:[NSArray arrayWithObject:[RadarBeacon alloc]] verified:YES attestationString:@"attestationString" keyId:@"keyID" attestationError:@"attestationError" encrypted:YES expectedCountryCode:@"CountryCode" expectedStateCode:@"StateCode"];

[[RadarReplayBuffer sharedInstance] writeNewReplayToBuffer:params];
[[RadarReplayBuffer sharedInstance] setValue:NULL forKey:@"mutableReplayBuffer"];
[[RadarReplayBuffer sharedInstance] loadReplaysFromPersistentStore];
NSMutableArray<RadarReplay *> *mutableReplayBuffer = [[RadarReplayBuffer sharedInstance] valueForKey:@"mutableReplayBuffer"];
XCTAssertEqual(mutableReplayBuffer.count, 1);
XCTAssertEqualObjects(mutableReplayBuffer.firstObject.replayParams, params);
}

- (void)test_RadarSdkConfiguration {
RadarSdkConfiguration *sdkConfiguration = [[RadarSdkConfiguration alloc] initWithDict:@{
@"logLevel": @"warning",
Expand Down
22 changes: 22 additions & 0 deletions RadarSDKTests/RadarTestUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,34 @@

#import <Foundation/Foundation.h>

#import "CLLocation+Radar.h"
#import "RadarLocationManager.h"
#import "RadarSettings.h"
#import "RadarState.h"
#import "RadarUtils.h"
#import "RadarTripOptions.h"
#import "RadarVerificationManager.h"

NS_ASSUME_NONNULL_BEGIN

@interface RadarTestUtils : NSObject

+ (NSDictionary *)jsonDictionaryFromResource:(NSString *)resource;

+ (NSMutableDictionary *)createTrackParamWithLocation:(CLLocation *_Nonnull)location
stopped:(BOOL)stopped
foreground:(BOOL)foreground
source:(RadarLocationSource)source
replayed:(BOOL)replayed
beacons:(NSArray<RadarBeacon *> *_Nullable)beacons
verified:(BOOL)verified
attestationString:(NSString *_Nullable)attestationString
keyId:(NSString *_Nullable)keyId
attestationError:(NSString *_Nullable)attestationError
encrypted:(BOOL)encrypted
expectedCountryCode:(NSString * _Nullable)expectedCountryCode
expectedStateCode:(NSString * _Nullable)expectedStateCode;

@end

NS_ASSUME_NONNULL_END
177 changes: 177 additions & 0 deletions RadarSDKTests/RadarTestutils.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,181 @@ + (NSDictionary *)jsonDictionaryFromResource:(NSString *)resource {
return jsonDict;
}

+ (NSMutableDictionary *)createTrackParamWithLocation:(CLLocation *_Nonnull)location
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess using the default values returned by radarState and radarSettings is perfectly fine in this case, but can we just put a comment noting that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added function docstring in the header file for this behaviour

stopped:(BOOL)stopped
foreground:(BOOL)foreground
source:(RadarLocationSource)source
replayed:(BOOL)replayed
beacons:(NSArray<RadarBeacon *> *_Nullable)beacons
verified:(BOOL)verified
attestationString:(NSString *_Nullable)attestationString
keyId:(NSString *_Nullable)keyId
attestationError:(NSString *_Nullable)attestationError
encrypted:(BOOL)encrypted
expectedCountryCode:(NSString * _Nullable)expectedCountryCode
expectedStateCode:(NSString * _Nullable)expectedStateCode{
NSMutableDictionary *params = [NSMutableDictionary new];
BOOL anonymous = [RadarSettings anonymousTrackingEnabled];
params[@"anonymous"] = @(anonymous);
if (anonymous) {
params[@"deviceId"] = @"anonymous";
params[@"geofenceIds"] = [RadarState geofenceIds];
params[@"placeId"] = [RadarState placeId];
params[@"regionIds"] = [RadarState regionIds];
params[@"beaconIds"] = [RadarState beaconIds];
} else {
params[@"id"] = [RadarSettings _id];
params[@"installId"] = [RadarSettings installId];
params[@"userId"] = [RadarSettings userId];
params[@"deviceId"] = [RadarUtils deviceId];
params[@"description"] = [RadarSettings __description];
params[@"metadata"] = [RadarSettings metadata];
NSString *sessionId = [RadarSettings sessionId];
if (sessionId) {
params[@"sessionId"] = sessionId;
}
}
params[@"latitude"] = @(location.coordinate.latitude);
params[@"longitude"] = @(location.coordinate.longitude);
CLLocationAccuracy accuracy = location.horizontalAccuracy;
if (accuracy <= 0) {
accuracy = 1;
}
params[@"accuracy"] = @(accuracy);
params[@"altitude"] = @(location.altitude);
params[@"verticalAccuracy"] = @(location.verticalAccuracy);
params[@"speed"] = @(location.speed);
params[@"speedAccuracy"] = @(location.speedAccuracy);
params[@"course"] = @(location.course);
if (@available(iOS 13.4, *)) {
params[@"courseAccuracy"] = @(location.courseAccuracy);
}
if (location.floor) {
params[@"floorLevel"] = @(location.floor.level);
}
long nowMs = (long)([NSDate date].timeIntervalSince1970 * 1000);
if (!foreground) {
long timeInMs = (long)(location.timestamp.timeIntervalSince1970 * 1000);
params[@"updatedAtMsDiff"] = @(nowMs - timeInMs);
}
params[@"foreground"] = @(foreground);
params[@"stopped"] = @(stopped);
params[@"replayed"] = @(replayed);
params[@"deviceType"] = [RadarUtils deviceType];
params[@"deviceMake"] = [RadarUtils deviceMake];
params[@"sdkVersion"] = [RadarUtils sdkVersion];
params[@"deviceModel"] = [RadarUtils deviceModel];
params[@"deviceOS"] = [RadarUtils deviceOS];
params[@"country"] = [RadarUtils country];
params[@"timeZoneOffset"] = [RadarUtils timeZoneOffset];
params[@"source"] = [Radar stringForLocationSource:source];
if ([RadarSettings xPlatform]) {
params[@"xPlatformType"] = [RadarSettings xPlatformSDKType];
params[@"xPlatformSDKVersion"] = [RadarSettings xPlatformSDKVersion];
} else {
params[@"xPlatformType"] = @"Native";
}
NSMutableArray<NSString *> *fraudFailureReasons = [NSMutableArray new];
if (@available(iOS 15.0, *)) {
CLLocationSourceInformation *sourceInformation = location.sourceInformation;
if (sourceInformation) {
if (sourceInformation.isSimulatedBySoftware) {
params[@"mocked"] = @(YES);
[fraudFailureReasons addObject:@"fraud_mocked_from_mock_provider"];
}
if (sourceInformation.isProducedByAccessory) {
[fraudFailureReasons addObject:@"fraud_mocked_produced_by_accessory"];
}
}
}

RadarTripOptions *tripOptions = Radar.getTripOptions;

if (tripOptions) {
NSMutableDictionary *tripParams = [NSMutableDictionary new];
tripParams[@"version"] = @("2");
[tripParams setValue:tripOptions.externalId forKey:@"externalId"];
[tripParams setValue:tripOptions.metadata forKey:@"metadata"];
[tripParams setValue:tripOptions.destinationGeofenceTag forKey:@"destinationGeofenceTag"];
[tripParams setValue:tripOptions.destinationGeofenceExternalId forKey:@"destinationGeofenceExternalId"];
[tripParams setValue:[Radar stringForMode:tripOptions.mode] forKey:@"mode"];
params[@"tripOptions"] = tripParams;
}

RadarTrackingOptions *options = [Radar getTrackingOptions];
if (options.syncGeofences) {
params[@"nearbyGeofences"] = @(YES);
}
if (beacons) {
params[@"beacons"] = [RadarBeacon arrayForBeacons:beacons];
}
NSString *locationAuthorization = [RadarUtils locationAuthorization];
if (locationAuthorization) {
params[@"locationAuthorization"] = locationAuthorization;
}
NSString *locationAccuracyAuthorization = [RadarUtils locationAccuracyAuthorization];
if (locationAccuracyAuthorization) {
params[@"locationAccuracyAuthorization"] = locationAccuracyAuthorization;
}
params[@"notificationAuthorization"] = [RadarState notificationPermissionGranted] ? @"true" : @"false";

params[@"trackingOptions"] = [options dictionaryValue];

BOOL usingRemoteTrackingOptions = RadarSettings.tracking && RadarSettings.remoteTrackingOptions;
params[@"usingRemoteTrackingOptions"] = @(usingRemoteTrackingOptions);

params[@"verified"] = @(verified);
if (verified) {
params[@"attestationString"] = attestationString;
params[@"keyId"] = keyId;
params[@"attestationError"] = attestationError;
params[@"encrypted"] = @(encrypted);
BOOL jailbroken = [[RadarVerificationManager sharedInstance] isJailbroken];
params[@"compromised"] = @(jailbroken);
if (jailbroken) {
[fraudFailureReasons addObject:@"fraud_compromised_jailbroken"];
}
if (expectedCountryCode) {
params[@"expectedCountryCode"] = expectedCountryCode;
}
if (expectedStateCode) {
params[@"expectedStateCode"] = expectedStateCode;
}
}
params[@"appId"] = [[NSBundle mainBundle] bundleIdentifier];
RadarSdkConfiguration *sdkConfiguration = [RadarSettings sdkConfiguration];
if (sdkConfiguration.useLocationMetadata) {
NSMutableDictionary *locationMetadata = [NSMutableDictionary new];
locationMetadata[@"motionActivityData"] = [RadarState lastMotionActivityData];
locationMetadata[@"heading"] = [RadarState lastHeadingData];
locationMetadata[@"speed"] = @(location.speed);
locationMetadata[@"speedAccuracy"] = @(location.speedAccuracy);
locationMetadata[@"course"] = @(location.course);

if (@available(iOS 13.4, *)) {
locationMetadata[@"courseAccuracy"] = @(location.courseAccuracy);
}

locationMetadata[@"battery"] = @([[UIDevice currentDevice] batteryLevel]);
locationMetadata[@"altitude"] = @(location.altitude);

if (@available(iOS 15, *)) {
locationMetadata[@"ellipsoidalAltitude"] = @(location.ellipsoidalAltitude);
locationMetadata[@"isProducedByAccessory"] = @([location.sourceInformation isProducedByAccessory]);
locationMetadata[@"isSimulatedBySoftware"] = @([location.sourceInformation isSimulatedBySoftware]);
}
locationMetadata[@"floor"] = @([location.floor level]);

params[@"locationMetadata"] = locationMetadata;
}

params[@"fraudFailureReasons"] = fraudFailureReasons;

// added after API call fail
params[@"replayed"] = @(YES);
params[@"updatedAtMs"] = @(nowMs);

return params;
}

@end
Loading