See More

// Copyright 2011 StackMob, Inc // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #import "StackMobClientData.h" #import #import #import "Reachability.h" #include #include #include NSString *bundleVersion = @""; NSString *identifier = @""; NSString *model = @""; NSString *systemVersion = @""; NSString *device_name = @""; NSString *countryCode = @""; NSString *language = @""; NSString *jailBroken = @"NO"; static StackMobClientData * _sharedInstance=nil; @interface StackMobClientData () - (void)startLocationUpdates; - (void)startReachabilityUpdates; - (void)generateClientDataString; @end @implementation StackMobClientData - (id)init { if(self = [super init]) { // Device info. UIDevice *device = [UIDevice currentDevice]; identifier = [device uniqueIdentifier]; model = [device model]; systemVersion = [device systemVersion]; // Locale info. NSLocale *locale = [NSLocale currentLocale]; countryCode = [locale objectForKey:NSLocaleCountryCode]; language = [[NSLocale currentLocale] objectForKey: NSLocaleLanguageCode]; // App info. bundleVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey]; jailBroken = [self isJailBrokenStr]; [self startLocationUpdates]; [self startReachabilityUpdates]; [self generateClientDataString]; } return self; } + (StackMobClientData*) sharedClientData; { if(!_sharedInstance) { _sharedInstance = [[StackMobClientData alloc] init]; } return _sharedInstance; } - (NSString *) platform{ size_t size; sysctlbyname("hw.machine", NULL, &size, NULL, 0); char *machine = malloc(size); sysctlbyname("hw.machine", machine, &size, NULL, 0); NSString *platform = [NSString stringWithCString:machine encoding: NSUTF8StringEncoding]; free(machine); return platform; } - (NSString *) platformString{ NSString *platform = [self platform]; if ([platform isEqualToString:@"iPhone1,1"]) return IPHONE_1G_NAMESTRING; if ([platform isEqualToString:@"iPhone1,2"]) return IPHONE_3G_NAMESTRING; if ([platform hasPrefix:@"iPhone2"]) return IPHONE_3GS_NAMESTRING; if ([platform hasPrefix:@"iPhone3"]) return IPHONE_4_NAMESTRING; if ([platform hasPrefix:@"iPhone4"]) return IPHONE_5_NAMESTRING; if ([platform isEqualToString:@"iPod1,1"]) return IPOD_1G_NAMESTRING; if ([platform isEqualToString:@"iPod2,1"]) return IPOD_2G_NAMESTRING; if ([platform isEqualToString:@"iPod3,1"]) return IPOD_3G_NAMESTRING; if ([platform isEqualToString:@"iPod4,1"]) return IPOD_4G_NAMESTRING; if ([platform isEqualToString:@"iPad1,1"]) return IPAD_1G_NAMESTRING; if ([platform isEqualToString:@"iPad2,1"]) return IPAD_2G_NAMESTRING; if ([platform isEqualToString:@"AppleTV2,1"]) return APPLETV_2G_NAMESTRING; if ([platform hasPrefix:@"iPhone"]) return IPHONE_UNKNOWN_NAMESTRING; if ([platform hasPrefix:@"iPod"]) return IPOD_UNKNOWN_NAMESTRING; if ([platform hasPrefix:@"iPad"]) return IPAD_UNKNOWN_NAMESTRING; if ([platform hasSuffix:@"86"] || [platform isEqual:@"x86_64"]) { if ([[UIScreen mainScreen] bounds].size.width < 768) return IPHONE_SIMULATOR_IPHONE_NAMESTRING; else return IPHONE_SIMULATOR_IPAD_NAMESTRING; } if ([platform isEqualToString:@"iFPGA"]) return IFPGA_NAMESTRING; return IPOD_FAMILY_UNKNOWN_DEVICE; } - (void)dealloc { [_locationManager release]; [_sharedInstance release]; [super dealloc]; } #pragma mark - Properties @synthesize clientDataString = _clientDataString; - (float)longitude { return _location.longitude; } - (float)latitude { return _location.latitude; } #pragma mark - - (void)generateClientDataString { device_name = [self platformString]; NSMutableDictionary* clientDataObject = [[NSMutableDictionary alloc] initWithObjectsAndKeys: identifier, DEVICE_TAG_NAME, model, DEVICE_TYPE_NAME, device_name, DEVICE_NAME, systemVersion, DEVICE_OS_VERSION_NAME, bundleVersion, APP_VERSION_NAME, LIBRARY_VERSION_NUMBER,LIBRARY_VERSION_NAME, countryCode, DEVICE_COUNTRY_CODE, language, DEVICE_LANGUAGE, jailBroken, DEVICE_IS_JAILBORKEN, nil]; if(_locationUpdatesStarted) { [clientDataObject setValue:[NSNumber numberWithFloat:_location.latitude] forKey:LATITUDE]; [clientDataObject setValue:[NSNumber numberWithFloat:_location.longitude] forKey:LONGITUDE]; } NetworkStatus newStatus = [[Reachability reachabilityForInternetConnection] currentReachabilityStatus]; switch (newStatus) { case ReachableViaWWAN: [clientDataObject setValue:@"m" forKey:NETWORK_AVAILABILITY]; // reachable via mobile network break; default: [clientDataObject setValue:@"w" forKey:NETWORK_AVAILABILITY]; // reachable via wifi break; } self.clientDataString = [clientDataObject yajl_JSONString]; } #pragma mark - Location - (void)startLocationUpdates { _locationUpdatesStarted = NO; _location.longitude = 0.0; _location.latitude = 0.0; _locationManager = [[CLLocationManager alloc] init]; _locationManager.delegate = self; _locationManager.desiredAccuracy = kCLLocationAccuracyKilometer; _locationManager.distanceFilter = 500; [_locationManager startUpdatingLocation]; } - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { _locationUpdatesStarted = YES; _location = newLocation.coordinate; [self generateClientDataString]; } #pragma mark - Reachability - (void)startReachabilityUpdates { [Reachability reachabilityWithHostName:@"www.stackmob.com"]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) name:@"kReachabilityChangedNotification" object:nil]; } - (void)reachabilityChanged:(NSNotification *)note { [self generateClientDataString]; } static const char* jailbreak_apps[] = { "/Applications/Cydia.app", "/Applications/limera1n.app", "/Applications/greenpois0n.app", "/Applications/blackra1n.app", "/Applications/blacksn0w.app", "/Applications/redsn0w.app", NULL, }; - (BOOL) isJailBroken { NSBundle *bundle = [NSBundle mainBundle]; NSDictionary *info = [bundle infoDictionary]; // This key-value pair should not be in the pinfo file. If it is, we can be reasonably sure that the app has been compromised. if ([info objectForKey: @"SignerIdentity"] != nil) { return YES; } // Now check for known jailbreak apps. If we encounter one, the device is jailbroken. for (int i = 0; jailbreak_apps[i] != NULL; ++i) { if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithUTF8String:jailbreak_apps[i]]]) { //NSLog(@"isjailbroken: %s", jailbreak_apps[i]); return YES; } } // TODO: Add more checks? This is an arms-race we're bound to lose. return NO; } - (NSString*) isJailBrokenStr { if ([self isJailBroken]) { return @"42"; } return @"0"; } @end