2013-04-26 11 views
25

Vorrei rilevare se un determinato profilo di provisioning è un profilo di sviluppo o un profilo di distribuzione (ad hoc o app store). Ho bisogno di farlo solo programmaticamente.Come rilevare che un profilo di provisioning è destinato allo sviluppo o alla distribuzione, a livello di programmazione

Ho già capito come rilevare ad hoc rispetto all'appstore. E sono specificamente interessato a sviluppo e distribuzione.

Ho esaminato i plists interni a ciascun tipo di profilo e non riesco a trovare una differenza distinguibile (tramite security cms -D -i #{@profilePath}). Ho anche esaminato l'API openssl e sto usando questo per la manipolazione di alcuni certificati.

Questo è per un sistema di build automatizzato xcode personalizzato. Come parte della convalida pre-compilazione, devo assicurarmi che il profilo specificato non sia destinato allo sviluppo.

È possibile? In tal caso, come posso differenziare a livello di codice tra i due?

Grazie in anticipo per qualsiasi idea!

+0

Questa è una domanda interessante, +1. –

+0

Ovviamente gli utenti di 'testflightapp.com' lo fanno per i file .ipa, ma non so nemmeno come differenziare adhoc/appstore quello che stai facendo. Penso che gli strumenti da riga di comando di XCode dovrebbero includere uno "strumento per il rilascio di profili di fornitura" e questo dovrebbe essere fatto per noi. È solo una ricca fonte di confusione dell'utente. Grazie Apple. –

+0

Hi Warren P, fyi tutto quello che sto facendo per rilevare un profilo adhoc rispetto ad appstore sta verificando la presenza della chiave 'ProvisionedDevices' nel plist del profilo, poiché i profili appstore non hanno alcun dispositivo predisposto. Potrebbe non essere infallibile, ma per il sistema che sto lavorando al suo interno serve lo scopo. Spero che questo sia utile. –

risposta

18

Questo è stato qualcosa che ho affrontato in uno dei miei sistemi di compilazione per lo stesso scopo ... facciamo un viaggio indietro nel tempo fino al primo giorno del "Programma per sviluppatori iPhone". Se fossi in giro per la comunità in quel momento, potresti ricordare che la toolchain era ... dovremmo dire meno amichevole ... di quanto lo sia oggi.

Quando si desidera creare per l'AppStore o per le build AdHoc è necessario creare questo file entitlements.plist, quindi incollare un blob di XML nel corpo di quel file. Quindi hai eseguito la build e in quel momento si è verificata quella che sembrava essere la magia e la pura presenza di quel file ha reso la costruzione funzionante, ti ha permesso di costruire manualmente il tuo IPA e continuare il lavoro come al solito. Ora che siamo un po 'più vecchi e, si spera, un po' più saggi che in quei primi giorni dell'SDK, siamo arrivati ​​a riconoscere che il blob XML magico non era in realtà così magico - il "get-task-allow" key è un'impostazione per indicare se il binario dovrebbe consentire ad altri processi (come forse un debugger) di collegarsi al binario. Quando si firmano app utilizzando un profilo di provisioning di sviluppo, questa chiave sarà impostata su "true" (e quindi permetterà a LLDB di collegarsi e interagire con la propria app) ... e naturalmente quando si firmano app utilizzando un profilo di provisioning di distribuzione, questa chiave verrà impostata a 'falso'.

Apple ha fornito alcuni aggiornamenti in Tech Note TN2250 sulla lettura del XML (e per estensione dei diritti) di Profili di fornitura:

sicurezza CMS -D -i /path/to/the.app/embedded. mobileprovision

Ciò restituirà l'XML nel profilo Provisioning - da lì si può analizzare la coppia di valori chiave per 'get-task-consentire' e l'uso che il valore per determinare se il profilo di provisioning è sviluppo o la distribuzione .

Sono assolutamente d'accordo che sarebbe bello avere uno strumento che ce lo dirà direttamente, quindi non dobbiamo annusare il profilo per trovare indizi, ma allo stesso tempo, almeno, abbiamo un alto livello di affidabilità, anche se in modo indiretto per fare quella distinzione prima di scappare e creare una build che non possiamo usare.

Buona fortuna e fammi sapere se hai bisogno di ulteriori chiarimenti o hai altre domande.

+0

Ottima risposta, esattamente quello che stavo cercando, grazie per la spiegazione dettagliata! –

+0

Siete i benvenuti! La chiave ProvisionedDevices è ancora una buona misura di convalida secondaria; Non lo uso nel mio sistema, ma sicuramente lo potresti ancora fare. –

9

Sulla base dell'ottima risposta di Bryan Musial, ho scritto un codice che consente di controllare "get-task-allow" direttamente dall'applicazione in fase di esecuzione.Nel mio caso sto usando questo booleana per accedere solo in applicazioni di debug:

+ (BOOL)isDevelopmentApp 
{ 
    // Special case of simulator 
    if (isSimulator) 
    { 
     return YES; 
    } 

    // There is no provisioning profile in AppStore Apps 
    NSString *profilePath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"]; 

    // Check provisioning profile existence 
    if (profilePath) 
    { 
     // Get hex representation 
     NSData *profileData = [NSData dataWithContentsOfFile:profilePath]; 
     NSString *profileString = [NSString stringWithFormat:@"%@", profileData]; 

     // Remove brackets at beginning and end 
     profileString = [profileString stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:@""]; 
     profileString = [profileString stringByReplacingCharactersInRange:NSMakeRange(profileString.length - 1, 1) withString:@""]; 

     // Remove spaces 
     profileString = [profileString stringByReplacingOccurrencesOfString:@" " withString:@""]; 

     // Convert hex values to readable characters 
     NSMutableString *profileText = [NSMutableString new]; 
     for (int i = 0; i < profileString.length; i += 2) 
     { 
      NSString *hexChar = [profileString substringWithRange:NSMakeRange(i, 2)]; 
      int value = 0; 
      sscanf([hexChar cStringUsingEncoding:NSASCIIStringEncoding], "%x", &value); 
      [profileText appendFormat:@"%c", (char)value]; 
     } 

     // Remove whitespaces and new lines characters 
     NSArray *profileWords = [profileText componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 
     NSString *profileClearText = [profileWords componentsJoinedByString:@""]; 

     // Look for debug value 
     NSRange debugRange = [profileClearText rangeOfString:@"<key>get-task-allow</key><true/>"]; 
     if (debugRange.location != NSNotFound) 
     { 
      return YES; 
     } 
    } 

    // Return NO by default to avoid security leaks 
    return NO; 
} 
+0

Grazie per il commento sulle build di App Store senza profilo di provisioning. Mi ha aiutato a eseguire il debug di un misterioso incidente! – phatmann

20

Ho costruire una versione più concisa ed efficace del codice di Toom:

io sostengo frammenti di codice come questo in una sostanza, si potrebbe trovare un più versione aggiornata qui: https://gist.github.com/steipete/7668246

static BOOL PSPDFIsDevelopmentBuild(void) { 
#if TARGET_IPHONE_SIMULATOR 
return YES; 
#else 
static BOOL isDevelopment = NO; 
static dispatch_once_t onceToken; 
dispatch_once(&onceToken, ^{ 
    // There is no provisioning profile in AppStore Apps. 
    NSData *data = [NSData dataWithContentsOfFile:[NSBundle.mainBundle pathForResource:@"embedded" ofType:@"mobileprovision"]]; 
    if (data) { 
     const char *bytes = [data bytes]; 
     NSMutableString *profile = [[NSMutableString alloc] initWithCapacity:data.length]; 
     for (NSUInteger i = 0; i < data.length; i++) { 
      [profile appendFormat:@"%c", bytes[i]]; 
     } 
     // Look for debug value, if detected we're a development build. 
     NSString *cleared = [[profile componentsSeparatedByCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet] componentsJoinedByString:@""]; 
     isDevelopment = [cleared rangeOfString:@"<key>get-task-allow</key><true/>"].length > 0; 
    } 
}); 
return isDevelopment; 
#endif 
} 
1

Ecco una versione per Swift 3, sulla base di @ steipete di risposta:

static func isDevelopmentProvisioningProfile() -> Bool { 
#if IOS_SIMULATOR 
    return true 
#else 
    // there will be no provisioning profile in AppStore Apps 
    guard let fileName = Bundle.main.path(forResource: "embedded", ofType: "mobileprovision") else { 
     return false 
    } 

    let fileURL = URL(fileURLWithPath: fileName) 
    // the documentation says this file is in UTF-8, but that failed 
    // on my machine. ASCII encoding worked ¯\_(ツ)_/¯ 
    guard let data = try? String(contentsOf: fileURL, encoding: .ascii) else { 
     return false 
    } 

    let cleared: String = data.components(separatedBy: .whitespacesAndNewlines).joined() 
    return cleared.contains("<key>get-task-allow</key><true/>") 
#endif 
} 
Problemi correlati