PPOTDevice.m 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. //
  2. // PPOTDevice.m
  3. // Copyright © 2009 PayPal, Inc. All rights reserved.
  4. //
  5. #import "PPOTDevice.h"
  6. #include <sys/types.h>
  7. #include <sys/sysctl.h>
  8. #include <sys/param.h>
  9. #include <sys/mount.h>
  10. #include <sys/socket.h>
  11. #include <netinet/in.h>
  12. #include <arpa/inet.h>
  13. #include <net/if.h>
  14. #include <ifaddrs.h>
  15. #import "PPOTSimpleKeychain.h"
  16. #import "PPOTString.h"
  17. #define kKeychainDeviceIdentifier @"PayPal_MPL_DeviceGUID"
  18. #define kPPOTOTDeviceFallbackCountryISOCode @"US"
  19. #define kPPOTOTDeviceFallbackCountryDialingCode @"1"
  20. @implementation PPOTDevice
  21. + (NSString *)hardwarePlatform {
  22. size_t size;
  23. sysctlbyname("hw.machine", NULL, &size, NULL, 0);
  24. char *machine = malloc(size);
  25. sysctlbyname("hw.machine", machine, &size, NULL, 0);
  26. NSString *platform = [NSString stringWithUTF8String:machine];
  27. free(machine);
  28. return platform;
  29. }
  30. + (NSString *)deviceName {
  31. NSString *model = [[UIDevice currentDevice] model];
  32. NSString *deviceName = [NSString stringWithFormat:@"%@ (%@)", model, [PPOTDevice hardwarePlatform]];
  33. return deviceName;
  34. }
  35. + (NSString *)complicatedDeviceLocale {
  36. // Start with the device's current language:
  37. NSString *deviceLocale = [NSLocale preferredLanguages][0];
  38. // Treat dialect, if present, as region (except for Chinese, where it's a bit more than just a dialect):
  39. // For example, "en-GB" ("British English", as of iOS 7) -> "en_GB"; and "en-GB_HK" -> "en_GB".
  40. if (![deviceLocale hasPrefix:@"zh"]) {
  41. if ([deviceLocale rangeOfString:@"-"].location != NSNotFound) {
  42. NSUInteger underscoreLocation = [deviceLocale rangeOfString:@"_"].location;
  43. if (underscoreLocation != NSNotFound) {
  44. deviceLocale = [deviceLocale substringToIndex:underscoreLocation];
  45. }
  46. deviceLocale = [deviceLocale stringByReplacingOccurrencesOfString:@"-" withString:@"_"];
  47. }
  48. }
  49. // If no region is specified, then use the device's current locale (if the language matches):
  50. if ([deviceLocale rangeOfString:@"_"].location == NSNotFound) {
  51. NSString *deviceLanguage = [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode];
  52. NSString *deviceRegion = [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode];
  53. if (!deviceRegion) {
  54. // NSLocaleCountryCode can return nil if device's Region is set to English, Esperanto, etc.
  55. deviceRegion = @"";
  56. }
  57. NSString *calculatedDeviceLocale;
  58. if ([deviceRegion length]) {
  59. calculatedDeviceLocale = [NSString stringWithFormat:@"%@_%@", deviceLanguage, deviceRegion];
  60. } else {
  61. calculatedDeviceLocale = deviceLanguage;
  62. }
  63. if ([deviceLanguage hasPrefix:deviceLocale]) {
  64. deviceLocale = calculatedDeviceLocale;
  65. }
  66. else if ([deviceRegion length]) {
  67. // For language-matching here, treat missing device dialect as wildcard; e.g, "zh" matches either "zh-Hans" or "zh-Hant":
  68. NSUInteger targetHyphenLocation = [deviceLocale rangeOfString:@"-"].location;
  69. if (targetHyphenLocation != NSNotFound) {
  70. NSString *targetLanguage = [deviceLocale substringToIndex:targetHyphenLocation];
  71. if ([deviceLanguage hasPrefix:targetLanguage]) {
  72. deviceLocale = [NSString stringWithFormat:@"%@_%@", deviceLocale, deviceRegion];
  73. } else if ([deviceLocale caseInsensitiveCompare:@"zh-Hant"] == NSOrderedSame &&
  74. ([deviceRegion isEqualToString:@"HK"] || [deviceRegion isEqualToString:@"TW"])) {
  75. // Very special case: target language is zh-Hant, and device region is either xx_HK or xx_TW,
  76. // for *any* "xx" (because device region could be en_HK or en_TW):
  77. deviceLocale = [NSString stringWithFormat:@"%@_%@", deviceLocale, deviceRegion];
  78. }
  79. }
  80. }
  81. }
  82. return deviceLocale;
  83. }
  84. + (NSString *)appropriateIdentifier {
  85. // see if we already have one
  86. NSString *appropriateId = [[NSString alloc] initWithData:[PPOTSimpleKeychain dataForKey:kKeychainDeviceIdentifier]
  87. encoding:NSUTF8StringEncoding];
  88. // if not generate a new one and save
  89. if (!appropriateId.length) {
  90. appropriateId = [[NSUUID UUID] UUIDString];
  91. [PPOTSimpleKeychain setData:[appropriateId dataUsingEncoding:NSUTF8StringEncoding] forKey:kKeychainDeviceIdentifier];
  92. }
  93. return appropriateId;
  94. }
  95. + (void)clearIdentifier {
  96. [PPOTSimpleKeychain setData:nil forKey:kKeychainDeviceIdentifier];
  97. }
  98. @end