Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the EXPIRATION date of a Provisioning Profile at Run-time?

I have an app that I routinely pass out to testers via the ad-hoc distribution method. Some of these testers are 'on the ball' and know enough about provisioning profiles and the quarterly expirations and can (if I forget) give me a nudge to rebuild a new version for them to test.

However some of the users always seem to get to the point where it stops running and then bitch and moan about it - despite them probably dismissing the iOS level reminder.

My question is can I programatically get hold of the expiry date at runtime and do my own 'in-app' alerts or system notifications to remind them to pull down the newer version?

like image 603
iOSProgrammingIsFun Avatar asked Sep 23 '13 14:09

iOSProgrammingIsFun


2 Answers

Swift version:

// Returns `nil` if it fails
private func getProvisioningProfileExpirationDateAsString() -> String? {
    guard
        let profilePath = Bundle.main.path(forResource: "embedded", ofType: "mobileprovision"),
        let profileData = try? Data(contentsOf: URL(fileURLWithPath: profilePath)),
        // Note: We use `NSString` instead of `String`, because it makes it easier working with regex, ranges, substring etc.
        let profileNSString = NSString(data: profileData, encoding: String.Encoding.ascii.rawValue)
        else {
        print("WARNING: Could not find or read `embedded.mobileprovision`. If running on Simulator, there are no provisioning profiles.")
        return nil
    }


    // NOTE: We have the `[\\W]*?` check to make sure that variations in number of tabs or new lines in the future does not influence the result.
    guard let regex = try? NSRegularExpression(pattern: "<key>ExpirationDate</key>[\\W]*?<date>(.*?)</date>", options: []) else {
        print("Warning: Could not create regex.")
        return nil
    }

    let regExMatches = regex.matches(in: profileNSString as String, options: [], range: NSRange(location: 0, length: profileNSString.length))

    // NOTE: range `0` corresponds to the full regex match, so to get the first capture group, we use range `1`
    guard let rangeOfCapturedGroupForDate = regExMatches.first?.range(at: 1) else {
        print("Warning: Could not find regex match or capture group.")
        return nil
    }

    let dateAsString = profileNSString.substring(with: rangeOfCapturedGroupForDate)
    return dateAsString
}
like image 56
Nikolay Suvandzhiev Avatar answered Oct 03 '22 13:10

Nikolay Suvandzhiev


In iOS 13, it doesn't work. The description of NSData changes from

{0x30822755 06092a86 4886f70d 010702a0 ... 889bfcbe ed768bac }

to

{length = ..., bytes = 0x30822755 06092a86 4886f70d 010702a0 ... 889bfcbe ed768bac }

Try this code:

NSData *data = ....;
NSUInteger dataLength = [data length];
NSMutableString *string =[NSMutableString stringWithCapacity:dataLength*2];

const unsigned char *dataBytes = [data bytes];
for (NSInteger idx = 0; idx < dataLength; ++idx)
{
    [string appendFormat:@"%02x", dataBytes[idx]];
}
like image 20
Ttnka Avatar answered Oct 03 '22 14:10

Ttnka