├── BSMobileProvision.podspec ├── LICENSE ├── README.md ├── UIApplication+BSMobileProvision.h └── UIApplication+BSMobileProvision.m /BSMobileProvision.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "BSMobileProvision" 3 | s.version = "0.0.1" 4 | s.summary = "Detecting dev, release, ad hoc, app store, or enterprise builds at runtime." 5 | s.description = "A category for parsing your iOS app's embedded.mobileprovision at runtime. Use it to, among other things, determine at runtime whether your app is being distributed as dev, release, ad hoc, app store, or enterprise." 6 | s.homepage = "https://github.com/appswithus/BSMobileProvision" 7 | s.license = { :type => 'MIT', :file => 'LICENSE' } 8 | s.author = 'The Blindsight Corporation' 9 | s.platform = :ios 10 | s.source = { :git => "https://github.com/appswithus/BSMobileProvision.git", :commit => "d4211e7a0f074be05bd83fa6150745aeb7ba94f1"} 11 | s.source_files = 'UIApplication+BSMobileProvision.{h,m}' 12 | s.requires_arc = false 13 | end 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, The Blindsight Corporation 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **Archived** 2 | ============ 3 | 4 | This project has been archived and is no longer supported by The Blindsight Corporation/Amazon. 5 | 6 | BSMobileProvision 7 | ================= 8 | 9 | A category for parsing your iOS app's embedded.mobileprovision at runtime. Use it to, among other things, determine at runtime whether your app is being distributed as dev, release, ad hoc, app store, or enterprise. 10 | 11 | Usage 12 | ----- 13 | 14 | ```objective-c 15 | #import "UIApplication+BSMobileProvision.h" 16 | 17 | NSString *releaseModeString = @"UNKNOWN"; 18 | UIApplicationReleaseMode releaseMode = [[UIApplication sharedApplication] releaseMode]; 19 | switch (releaseMode) { 20 | case UIApplicationReleaseAdHoc: releaseModeString = @"AdHoc"; break; 21 | case UIApplicationReleaseDev: releaseModeString = @"Dev"; break; 22 | case UIApplicationReleaseAppStore: releaseModeString = @"AppStore"; break; 23 | case UIApplicationReleaseEnterprise: releaseModeString = @"Enterprise"; break; 24 | // case UIApplicationReleaseUnknown: releaseType = @"UNKNOWN"; break; 25 | } 26 | NSLog(@"LAUNCHED WITH RELEASE TYPE: %@",releaseModeString); 27 | ``` 28 | 29 | Notes 30 | ----- 31 | 32 | If you want something less hacky, you should go with something like: 33 | 34 | * [DTFoundation's DTASN1Parser](https://github.com/Cocoanetics/DTFoundation/blob/master/Core/Source/DTASN1Parser.m) 35 | * [TCMobileProvision](https://github.com/tcurdt/TCMobileProvision) (which uses DTASN1Parser) 36 | * [What is a provisioning profile?](http://www.doubleencore.com/2013/02/what-is-a-provisioning-profile-part-1/) 37 | 38 | This was made in part possible due to the following references: 39 | 40 | * [what to look for in the provisioning profile](http://stackoverflow.com/a/3426899/856925) 41 | * [building a property list from data](http://stackoverflow.com/a/1072365/856925) 42 | * [NSScanner tips](http://stackoverflow.com/a/6826076/856925) 43 | * [the importance of not reading it as UTF8](http://stackoverflow.com/q/17285015/793212) 44 | * [.mobileprovision Files Structure and Reading](http://idevblog.info/mobileprovision-files-structure-and-reading/) 45 | 46 | Somewhat related, Jin Budelmann notes that even when an app (such as one released through the app store) does not have an embedded.mobileprovision, the application binary will still be signed, and that that could be another source of information: 47 | 48 | * [How to detect non-jailbroken pirates](http://www.bitcrank.com/blog/?p=37) 49 | -------------------------------------------------------------------------------- /UIApplication+BSMobileProvision.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIApplication+BSMobileProvision.h 3 | // 4 | // Created by kaolin fire on 2013-06-24. 5 | // Copyright (c) 2013 The Blindsight Corporation. All rights reserved. 6 | // Released under the BSD 2-Clause License (see LICENSE) 7 | 8 | #import 9 | 10 | typedef NS_ENUM(NSInteger, UIApplicationReleaseMode) { 11 | UIApplicationReleaseUnknown, 12 | UIApplicationReleaseSim, 13 | UIApplicationReleaseDev, 14 | UIApplicationReleaseAdHoc, 15 | UIApplicationReleaseAppStore, 16 | UIApplicationReleaseEnterprise, 17 | }; 18 | 19 | @interface UIApplication (BSMobileProvision) 20 | 21 | -(UIApplicationReleaseMode) releaseMode; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /UIApplication+BSMobileProvision.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIApplication+BSMobileProvision.m 3 | // 4 | // Created by kaolin fire on 2013-06-24. 5 | // Copyright (c) 2013 The Blindsight Corporation. All rights reserved. 6 | // Released under the BSD 2-Clause License (see LICENSE) 7 | 8 | #import "UIApplication+BSMobileProvision.h" 9 | #import "TargetConditionals.h" 10 | 11 | @implementation UIApplication (BSMobileProvision) 12 | 13 | /** embedded.mobileprovision plist format: 14 | 15 | AppIDName, // string — TextDetective 16 | ApplicationIdentifierPrefix[], // [ string - 66PK3K3KEV ] 17 | CreationData, // date — 2013-01-17T14:18:05Z 18 | DeveloperCertificates[], // [ data ] 19 | Entitlements { 20 | application-identifier // string - 66PK3K3KEV.com.blindsight.textdetective 21 | get-task-allow // true or false 22 | keychain-access-groups[] // [ string - 66PK3K3KEV.* ] 23 | }, 24 | ExpirationDate, // date — 2014-01-17T14:18:05Z 25 | Name, // string — Barrierefreikommunizieren (name assigned to the provisioning profile used) 26 | ProvisionedDevices[], // [ string.... ] 27 | TeamIdentifier[], // [string — HHBT96X2EX ] 28 | TeamName, // string — The Blindsight Corporation 29 | TimeToLive, // integer - 365 30 | UUID, // string — 79F37E8E-CC8D-4819-8C13-A678479211CE 31 | Version, // integer — 1 32 | ProvisionsAllDevices // true or false ***NB: not sure if this is where this is 33 | 34 | */ 35 | 36 | -(NSDictionary*) getMobileProvision { 37 | static NSDictionary* mobileProvision = nil; 38 | if (!mobileProvision) { 39 | NSString *provisioningPath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"]; 40 | if (!provisioningPath) { 41 | mobileProvision = [@{} retain]; 42 | return mobileProvision; 43 | } 44 | // NSISOLatin1 keeps the binary wrapper from being parsed as unicode and dropped as invalid 45 | NSString *binaryString = [NSString stringWithContentsOfFile:provisioningPath encoding:NSISOLatin1StringEncoding error:NULL]; 46 | if (!binaryString) { 47 | return nil; 48 | } 49 | NSScanner *scanner = [NSScanner scannerWithString:binaryString]; 50 | BOOL ok = [scanner scanUpToString:@"" intoString:&plistString]; 54 | if (!ok) { NSLog(@"unable to find end of plist"); return UIApplicationReleaseUnknown; } 55 | plistString = [NSString stringWithFormat:@"%@",plistString]; 56 | // juggle latin1 back to utf-8! 57 | NSData *plistdata_latin1 = [plistString dataUsingEncoding:NSISOLatin1StringEncoding]; 58 | // plistString = [NSString stringWithUTF8String:[plistdata_latin1 bytes]]; 59 | // NSData *plistdata2_latin1 = [plistString dataUsingEncoding:NSISOLatin1StringEncoding]; 60 | NSError *error = nil; 61 | mobileProvision = [NSPropertyListSerialization propertyListWithData:plistdata_latin1 options:NSPropertyListImmutable format:NULL error:&error]; 62 | if (error) { 63 | NSLog(@"error parsing extracted plist — %@",error); 64 | [error release]; 65 | if (mobileProvision) { 66 | [mobileProvision release]; 67 | mobileProvision = nil; 68 | } 69 | return nil; 70 | } 71 | [mobileProvision retain]; 72 | } 73 | return mobileProvision; 74 | } 75 | 76 | -(UIApplicationReleaseMode) releaseMode { 77 | NSDictionary *mobileProvision = [self getMobileProvision]; 78 | if (!mobileProvision) { 79 | // failure to read other than it simply not existing 80 | return UIApplicationReleaseUnknown; 81 | } else if (![mobileProvision count]) { 82 | #if TARGET_IPHONE_SIMULATOR 83 | return UIApplicationReleaseSim; 84 | #else 85 | return UIApplicationReleaseAppStore; 86 | #endif 87 | } else if ([[mobileProvision objectForKey:@"ProvisionsAllDevices"] boolValue]) { 88 | // enterprise distribution contains ProvisionsAllDevices - true 89 | return UIApplicationReleaseEnterprise; 90 | } else if ([mobileProvision objectForKey:@"ProvisionedDevices"] && [[mobileProvision objectForKey:@"ProvisionedDevices"] count] > 0) { 91 | // development contains UDIDs and get-task-allow is true 92 | // ad hoc contains UDIDs and get-task-allow is false 93 | NSDictionary *entitlements = [mobileProvision objectForKey:@"Entitlements"]; 94 | if ([[entitlements objectForKey:@"get-task-allow"] boolValue]) { 95 | return UIApplicationReleaseDev; 96 | } else { 97 | return UIApplicationReleaseAdHoc; 98 | } 99 | } else { 100 | // app store contains no UDIDs (if the file exists at all?) 101 | return UIApplicationReleaseAppStore; 102 | } 103 | } 104 | 105 | @end 106 | --------------------------------------------------------------------------------