iOS Enterprise App Distribution – Provisioning Profile expired - ios

How I can check in App when expired Provisioning Profile and notify user about date?
Example
I have found here. But this file is not included in a bundle of the project. Maybe there are some options? Thanks

Despite this being a MAC OS X prov checker, it applies all the same to iOS too:
https://github.com/LigeiaRowena/ProvisioningInfo
Personally, that information shouldn't bother your users. You should have a clear record of when they expire, and notify the users via push notifications and/or some form of REST api for expiration dates.
Ideally, the best way to handle this is to periodically (at least once a year) push out an update with nothing more than a new embedded mprov.
Do you specifically need your users to notify you as to when your provisioning profiles are expiring?
But in terms of reading the plist file:
[NSDictionary dictionaryWithContentsOfFile:#"path/to/file.plist"]
This also seems to be a previously answered question at:
Get the EXPIRATION date of a Provisioning Profile at Run-time?
but to reiterate the code:
- (NSString*) getExpiry{
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]];
//There must be a better word to search through this as a structure! Need 'date' sibling to <key>ExpirationDate</key>, or use regex
BOOL sibling = false;
for (NSString* word in profileWords){
if ([word isEqualToString:#"<key>ExpirationDate</key>"]){
NSLog(#"Got to the key, now need the date!");
sibling = true;
}
if (sibling && ([word rangeOfString:#"<date>"].location != NSNotFound)) {
NSLog(#"Found it, you win!");
NSLog(#"Expires: %#",word);
return word;
}
}
}
return #"";
}

Related

Display Unicode String as Emoji

I currently receive emojis in a payload in the following format:
\\U0001F6A3\\U0000200D\\U00002640\\U0000FE0F
which represents "🚣‍♀️"
However, if I try to display this, it only shows the string above (escaped with 1 less ), not the emoji e.g.
NSString *emoji = payload[#"emoji"];
NSLog(#"%#", emoji) then displays as \U0001F6A3\U0000200D\U00002640\U0000FE0F
It's as if the unicode escape it not being recognised. How can I get the string above to show as an emoji?
Please assume that the format the data is received in from the server cannot be changed.
UPDATE
I found another way to do it, but I think the answer by Albert posted below is better. I am only posting this for completeness and reference:
NSArray *emojiArray = [unicodeString componentsSeparatedByString:#"\\U"];
NSString *transformedString = #"";
for (NSInteger i = 0; i < [emojiArray count]; i++) {
NSString *code = emojiArray[i];
if ([code length] == 0) continue;
NSScanner *hexScan = [NSScanner scannerWithString:code];
unsigned int hexNum;
[hexScan scanHexInt:&hexNum];
UTF32Char inputChar = hexNum;
NSString *res = [[NSString alloc] initWithBytes:&inputChar length:4 encoding:NSUTF32LittleEndianStringEncoding];
transformedString = [transformedString stringByAppendingString:res];
}
Remove the excess backslash then convert with a reverse string transform stringByApplyingTransform. The transform must use key "Any-Hex" for emojis.
NSString *payloadString = #"\\U0001F6A3\\U0000200D\\U00002640\\U0000FE0F";
NSString *unescapedPayloadString = [payloadString stringByReplacingOccurrencesOfString:#"\\\\" withString:#"\\"];
NSString *transformedString = [unescapedPayloadString stringByApplyingTransform:#"Any-Hex" reverse:YES];
NSLog(#"%#", transformedString);//logs "🚣‍♀️"
I investigated this, and it seems you may not be receiving what you say you are receiving. If you see \U0001F6A3\U0000200D\U00002640\U0000FE0F in your NSLog, chances are you are actually receiving \\U0001F6A3\\U0000200D\\U00002640\\U0000FE0F at your end instead. I tried using a variable
NSString *toDecode = #"\U0001F6A3\U0000200D\U00002640\U0000FE0F";
self.tv.text = toDecode;
And in textview it is displaying the emoji fine.
So you got to fix that first and then it will display well.

Objective-C how to parse command-line like arguments from a given string?

I'm working with an iOS app using UISearchBar. I would like to add an option for the user to use lightweight search queries that can be entered right in the search bar, like the mail app.
For example, I want to be able to be able to parse "Search Term last:week" and search my data for "Search Term" and create a search filter to show only last 7 days. How can I parse command-line like arguments from iOS String ?
In particular, once I've extracted my tokens and verified that they are valid,
how do I remove them from the search query without affecting the rest of the query?
Here's my original attempt. Are there any ready-made tools I can use for this task?
static NSString* whenKeyword = #"when";
static NSString* lastKeyword = #"last";
-(NSMutableDictionary*)findCommandsInQuery:(NSString*)query
{
//extract keywords from the query, like google mail search. We want to have commands like "cute puppies Last:month"
//remove extra whitespace, prepare to parse
NSString* dirtyString = [query stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSArray* tokens = [dirtyString componentsSeparatedByString:#":"];
//for each token, we want to trim it and remove illegal characters
NSMutableArray* cleanTokens = [[NSMutableArray alloc] initWithCapacity:tokens.count];
NSString* token = nil;
NSString* nextToken = nil;
NSString* cleanToken = nil;
for(int i = 0; i< tokens.count; i ++)
{
//get a token, for example "cute puppies last"
token = tokens[i];
NSArray* words = [token componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if(words.count >0)
{
for(NSString* word in words)
{
cleanToken = [DataSource cleanTrimSearchTerm:word];
if(cleanToken.length > 0)
{
[cleanTokens addObject:cleanToken];
}
}
}else
{
cleanToken = nil;
}
}
//process tokens
NSMutableDictionary* commands = [NSMutableDictionary dictionary];
for(int i = 0; i< cleanTokens.count; i ++)
{
token = cleanTokens[i];
if(i+1 < cleanTokens.count)
{
nextToken = cleanTokens[i+1];
}
[self checkToken:token againstKeyword:whenKeyword withQuantifier:nextToken storeInDictionary:commands];
[self checkToken:token againstKeyword:lastKeyword withQuantifier:nextToken storeInDictionary:commands];
}
DLog(#"found commands: %#",commands);
return commands;
}
Here's a method to respond to commands and create a search query with them
-(void)processCommands:(NSMutableDictionary*)commands
{
NSString* value = commands[lastKeyword];
if(value != nil)
{
DLog(#"%#" ,value);
if([value isEqualToString:#"day"])
{
}else if ([value isEqualToString:#"week"])
{
}else if ([value isEqualToString:#"month"])
{
}else if ([value isEqualToString:#"quarter"])
{
}else if ([value isEqualToString:#"year"])
{
}
}
}
Users usually dislike having to learn query languages. It's a complex user experience. There are many different ways to simplify querying and searching such as using the scope bar of UISearchController or using table view sections to divide the information. But if you are still required to create a query mechanism try to implement your own Abstract Syntax Tree (AST) to avoid spaghetti code

Detect if another application was installed/uninstalled in a jailbroken iDevice

I want to detect when another application was installed/uninstalled and save the time to a database at the moment of execution.
I know this is possible in Android using broadcastreceiver and I want to know if this can be done in iOS using a jailBroken device because I believe this is not possible in a non-jailBroken device.
I hope someone could help me. Thank you.
Recently was having the same problem.
You need to write SpringBoard tweak. In it you observe notification SBInstalledApplicationsDidChangeNotification from local notification center (CFNotificationCenterGetLocalCenter or [NSNotificationCenter defaultCenter]). User info dictionary will contain:
SBInstalledApplicationsRemovedBundleIDs key contains array of bundle IDs of uninstalled applications.
SBInstalledApplicationsModifiedBundleIDs key contains array of bundle IDs of updated applications.
SBInstalledApplicationsAddedBundleIDs key contains array of bundle IDs of installed applications.
Obviously that way you can log every time applications are installed/uninstalled/updated.
You can check if an application is installed by using its bundle id
BOOL isInstalled = [[LSApplicationWorkspace defaultWorkspace] applicationIsInstalled:#"com.app.identifier"];
if (isInstalled) {
// app is installed }
else {
// app is not installed
}
EDIT:
If you want to check if an application got installed you can maybe count the items inside user of com.apple.mobile.installation.plist it holds all the information about installed apps.
You can write the number of apps inside a plist then later check back and compare the results?
// get apps count
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:#"/var/mobile/Library/Caches/com.apple.mobile.installation.plist"];
int numberOfApps = [[dict objectForKey: #"User"] count];
NSLog(#"Count: %i",numberOfApps);
// Save apps count inside a plist
NSString *path = #"/var/mobile/AppsCount.plist";
NSFileManager *fm = [NSFileManager defaultManager];
NSMutableDictionary *data;
if ([fm fileExistsAtPath:path]) {
data = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
}
else {
// If the file doesn’t exist, create an empty dictionary
data = [[NSMutableDictionary alloc] init];
}
[data setObject:[NSNumber numberWithInt:numberOfApps] forKey:#"savedAppsCount"];
[data writeToFile:path atomically:YES];
[data release];
And then to compare old counts with the new apps count:
// get current number of apps
NSString *path = #"/var/mobile/AppsCount.plist";
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:#"/var/mobile/Library/Caches/com.apple.mobile.installation.plist"];
int numberOfApps = [[dict objectForKey: #"User"] count];
// retrieve old app count and compare to new ones
NSMutableDictionary *retrieveCounts = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
int oldAppCount = [[retrieveCounts objectForKey:#"savedAppsCount"] intValue];
if (oldAppCount < numberOfApps) {
NSLog(#"NEW APP GOT INSTALLED");
}
else if (oldAppCount > numberOfApps) {
NSLog(#"AN APP GOT UNINSTALLED");
}
else {
NSLog(#"NOTHING GOT INSTALLED OR UNINSTALLED");
}
[retrieveCounts release];
But that doesn't give you the time, it just checks if a new app got installed
There might be a better way of doing that, but that's what came into my mind.
Hope it helps.

How to pad strings to a fixed width with NSMutableString?

I'm trying to write a string to a text file. That text file will then be read by another program. That second program is expecting the different "fields" in the text file to be a fixed width. Therefore, when I write the text file with my app, I will need to add spaces between my actual data to get everything to line up correctly. How do I get these spaces added?
So far, I've tried writing a function that takes a source string and a target length as input. If the target is longer than the source, it just appends " ". Code for this routine is below:
- (NSString *) makeStringFrom:(NSString *)source withLength:(NSInteger)length
{
// Method to add spaces to the end of a string to get it to a certain length
if ([source length] > length)
{
// String is too long - throw warning and send it back
NSLog(#"Warning - string is already longer than length supplied. Returning source string");
return source;
}
else if ([source length] == length)
{
// String is already correct length, so just send it back
return source;
}
else
{
// String is too short, need to add spaces
NSMutableString *newString = [[NSMutableString alloc] initWithString:source];
NSLog(#"newString initial length = %d",[newString length]);
for (int current = [source length]; current < length; current ++)
{
[newString stringByAppendingString:#" "];
NSLog(#"hit");
}
NSLog(#"target length = %d. newString length = %d",length,[newString length]);
return newString;
}
}
This apparently doesn't work. The length of the string I'm getting back in the return isn't changing any from the length of the supplied string, even when the NSLog(#"hit"); runs multiple times.
There's a stringByPaddingToLength:withString:startingAtIndex: method on NSString that does just this.
You did a silly mistake here
[newString stringByAppendingString:#" "];
This returns a new string, and it doesnot effect the caller object. You need to store it
newString=[newString stringByAppendingString:#" "];
or simply
[newString appendString:#" "];
You want to change:
[newString stringByAppendingString:#" "];
into:
newString = [newString stringByAppendingString:#" "];

Decoding the scanned barcode value to int value

When I scan the barcode and I get some value if it is Equal=2 then I need to display with == and if it is Equal=3 then I need to display with = and if the value is 4 then invalid.
But Scanned Barcode are of integer value -- when decode using NSASCII it is displaying only till value 127 after that it is showing invalid results. Eg: if my Barcode value = 9699 the result value=jem then my added result value=jem= actualstring value=%åasc value id only showing 37
Here is my code:
- (void) readerView:(ZBarReaderView *)view didReadSymbols:(ZBarSymbolSet *)syms fromImage:(UIImage *)img
{
// do something useful with results -- cool thing is that you get access to the image too
for (ZBarSymbol *symbol in syms) {
[resultsBox setText:symbol.data];
if ([resultsBox.text length] == 2) {
addedresult.text = [resultsBox.text stringByAppendingString:#"=="];
} else if ([resultsBox.text length] == 3) {
addedresult.text = [resultsBox.text stringByAppendingString:#"="];
} if ([resultsBox.text length] >= 4) {
addedresult.text = #"Invalid";
}
[Base64 initialize];
NSString *myString = [[NSString alloc]initWithString:addedresult.text];
NSData * data = [Base64 decode:myString];
NSString * actualString = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"%#",actualString);
labeltext.text= actualString;
int asc = [actualString characterAtIndex:0];
label.text = [NSString stringWithFormat:#"%d", asc];
[actualString release];
break;
}
}
Since someone revived this question's comments, i'll revive this entire post.
You shouldn't go through NSData to create an NSString from something you already have, and you're probably losing something along the way. Go directly to NSString using stringWithFormat. Also, ASCII will come back and byte you later, if you have a choice, use UTF8.
NSString *actualStringUTF8 = [NSString stringWithFormat:#"%#",[addedresult.text urlEncodeUsingEncoding:NSUTF8StringEncoding]];
NSString *actualStringASCII = [NSString stringWithFormat:#"%#",[addedresult.text urlEncodeUsingEncoding:NSUTF8StringEncoding]];
NSLog(#"%#",actualStringUTF8);
NSLog(#"%c",[actualStringUTF8 UTF8String]); //This is a const char*
Secondly, I looked into the SDK and it says symbol.data is already an NSString*. Depending on what you want, you may not need to do anything. If you do end up needing to change encoding, make sure you understand why you need to (one good reason is "the rest of the application uses NS****StringEncoding").
Also make sure you compare strings the correct "Objective-C" way:
[actualString isEqualToString: testString];
NOT actualString == testString;

Resources