1// Copyright 2015-present 650 Industries. All rights reserved.
2
3#import <EXApplication/EXProvisioningProfile.h>
4
5@implementation EXProvisioningProfile {
6  NSDictionary *_plist;
7}
8
9+ (nonnull instancetype)mainProvisioningProfile
10{
11  static EXProvisioningProfile *profile;
12  static dispatch_once_t onceToken;
13  dispatch_once(&onceToken, ^{
14    NSDictionary *plist = [self _readProvisioningProfilePlist];
15    profile = [[self alloc] initWithPlist:plist];
16  });
17  return profile;
18}
19
20- (instancetype)initWithPlist:(NSDictionary *)plist
21{
22  if (self = [super init]) {
23    _plist = plist;
24  }
25  return self;
26}
27
28- (nullable NSString *)notificationServiceEnvironment
29{
30  if (!_plist) {
31    return nil;
32  }
33
34  NSDictionary *entitlements = _plist[@"Entitlements"];
35  NSString *apsEnvironment = entitlements[@"aps-environment"];
36  return apsEnvironment;
37}
38
39- (EXAppReleaseType)appReleaseType {
40  NSString *provisioningPath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];
41  if (!provisioningPath) {
42    // provisioning profile does not exist
43#if TARGET_IPHONE_SIMULATOR
44    return EXAppReleaseSimulator;
45#else
46    return EXAppReleaseAppStore;
47#endif
48  }
49
50  NSDictionary *mobileProvision = _plist;
51  if (!mobileProvision) {
52    // failure to read other than it simply not existing
53    return EXAppReleaseTypeUnknown;
54  } else if ([[mobileProvision objectForKey:@"ProvisionsAllDevices"] boolValue]) {
55    // enterprise distribution contains ProvisionsAllDevices - true
56    return EXAppReleaseEnterprise;
57  } else if ([mobileProvision objectForKey:@"ProvisionedDevices"] && [[mobileProvision objectForKey:@"ProvisionedDevices"] count] > 0) {
58    // development contains UDIDs and get-task-allow is true
59    // ad hoc contains UDIDs and get-task-allow is false
60    NSDictionary *entitlements = [mobileProvision objectForKey:@"Entitlements"];
61    if ([[entitlements objectForKey:@"get-task-allow"] boolValue]) {
62      return EXAppReleaseDev;
63    } else {
64      return EXAppReleaseAdHoc;
65    }
66  } else {
67    // app store contains no UDIDs (if the file exists at all?)
68    return EXAppReleaseAppStore;
69  }
70}
71
72/** embedded.mobileprovision plist format:
73
74 AppIDName, // string — TextDetective
75 ApplicationIdentifierPrefix[],  // [ string - 66PK3K3KEV ]
76 CreationData, // date — 2013-01-17T14:18:05Z
77 DeveloperCertificates[], // [ data ]
78 Entitlements {
79 application-identifier // string - 66PK3K3KEV.com.blindsight.textdetective
80 get-task-allow // true or false
81 keychain-access-groups[] // [ string - 66PK3K3KEV.* ]
82 },
83 ExpirationDate, // date — 2014-01-17T14:18:05Z
84 Name, // string — Barrierefreikommunizieren (name assigned to the provisioning profile used)
85 ProvisionedDevices[], // [ string.... ]
86 TeamIdentifier[], // [string — HHBT96X2EX ]
87 TeamName, // string — The Blindsight Corporation
88 TimeToLive, // integer - 365
89 UUID, // string — 79F37E8E-CC8D-4819-8C13-A678479211CE
90 Version, // integer — 1
91 ProvisionsAllDevices // true or false  ***NB: not sure if this is where this is
92
93 */
94+ (NSDictionary *)_readProvisioningProfilePlist
95{
96  NSString *profilePath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];
97  if (!profilePath) {
98    return nil;
99  }
100
101  NSError *error;
102  NSString *profileString = [NSString stringWithContentsOfFile:profilePath encoding:NSASCIIStringEncoding error:&error];
103  if (!profileString) {
104    NSLog(@"Error reading provisioning profile: %@", error.localizedDescription);
105    return nil;
106  }
107
108  NSScanner *scanner = [NSScanner scannerWithString:profileString];
109  BOOL readPrelude = [scanner scanUpToString:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" intoString:nil];
110  if (!readPrelude) {
111    return nil;
112  }
113
114  NSString *plistString;
115  BOOL readPlist = [scanner scanUpToString:@"</plist>" intoString:&plistString];
116  if (!readPlist) {
117    return nil;
118  }
119  plistString = [plistString stringByAppendingString:@"</plist>"];
120
121  NSData *plistData = [plistString dataUsingEncoding:NSUTF8StringEncoding];
122  NSDictionary *plistDictionary = [NSPropertyListSerialization propertyListWithData:plistData
123                                                                            options:NSPropertyListImmutable
124                                                                             format:NULL
125                                                                              error:&error];
126  if (!plistDictionary) {
127    NSLog(@"Error unserializing provisioning profile plist: %@", error.localizedDescription);
128    return nil;
129  }
130
131  return plistDictionary;
132}
133
134@end
135