4

I have a .ipa file (iOS app) that I'm letting users install ad-hoc (Over the air on a private server, using an enterprise account).

Challenge is that the apps differentiate a bit from app to app. They have different logos and a different url they use inside the app.

Is it possible to dynamically change a .ipa file I have on my server before people download it?

Further Explanation:

I have to stress, that I can't make an .ipa file for each app. I HAVE to be able to change start screen, logo and set an url variable for a single .ipa file.

I other words, I need to DYNAMICALLY change the .ipa file on the server each time someone wants to download it.

What I would love to have:

I would love to have an example/guide on how to do this on a heroku or amazon server. Nothing fancy. Basically just changing a variable in the info.plist and then codesign it again afterwards.

pnuts
  • 58,317
  • 11
  • 87
  • 139
Holger Sindbaek
  • 2,278
  • 6
  • 41
  • 68
  • 1
    The first thought that comes into my head after reading this question as a fellow Enterprise guy is: why? Are you at liberty to explain your back end situation at all? – Dan Aug 01 '13 at 03:38

3 Answers3

9

As has been stated you can simply unzip and zip again to create your own ipa.

All you further need is to add some resources that don't need code signing.

Your best bet would be to create a new (empty) directory in the ipa. Directories themselves are not signed, but are extracted on the device and can be detected by your code.

In other words: the CodeResources file containing the signatures does not change when adding an empty directory.

A simple test I just did, was to create a folder reference to a folder called "extra", the contents of which are decoded using percent encoding and displayed in a popup:

NSString *path = [[NSBundle mainBundle] pathForResource:@"extra" ofType:@""];
NSDirectoryEnumerator *direnum = [[NSFileManager defaultManager] enumeratorAtPath:path];
NSString *f;
while (f = [direnum nextObject])
{
    NSString *decoded = [f stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:nil message:decoded delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
    [alert show];
}

This can be used to send subliminal messages to your code. Percent encoding allows you to put in any character you like. I tested filename lengths up to 100 chars.

All you further need is some code to dynamically add an empty directory under Payload/yourapp.app/extra/ to the ipa, with the percent encoded message as its filename, e.g. Payload/yourapp.app/extra/http%3A%2F%2Fstackoverflow.com%2F

update: example shell commands to add a directory to an ipa:

$ mkdir -p Payload/myapp.app/extra/http%3A%2F%2Fstackoverflow.com%2F
$ zip -r myapp.ipa Payload/
updating: Payload/ (stored 0%)
updating: Payload/myapp.app/ (stored 0%) 
updating: Payload/myapp.app/extra/ (stored 0%) 
 adding: Payload/myapp.app/extra/http%3A%2F%2Fstackoverflow.com%2F/ (stored 0%) 
$ rm -r Payload/

You will of course need to create a clean copy of the ipa every time, or the urls will pile up under /extra/ inside the ipa.

mvds
  • 45,755
  • 8
  • 102
  • 111
  • That might be a solution. So you're suggesting to simple name the folder the name of the url I want to change? Does it have to be a folder? One thing I'm still quite unclear about, is how to zip/unzip my .ipa on my actual server (Heroku or Amazon S3). – Holger Sindbaek Jul 27 '13 at 15:28
  • Exactly, and yes, it has te be a folder, in order to avoid code signing. I've added a small shell script to the answer, showing how to add a folder to a zip archive. – mvds Jul 28 '13 at 18:17
  • Very nice. This might be a real solution. Can I also replace some of my assets? I have a logo (image) I would like to change. Or would that require me to code-sign it again? How would you run a script like this if the Payload is on a Heroku or Amazon S3 server? – Holger Sindbaek Jul 28 '13 at 19:02
  • I don't know about Heroku or Amazon, it's a different topic and suitable for a separate question. I think replacing/removing/adding assets is impossible without code signing again. You might encode the actual data of an image in directory names, but that would require quite some tedious programming. – mvds Jul 28 '13 at 19:57
  • I have tested it with iOS 7.1 and it is still working. – Torsten B Mar 21 '14 at 09:49
  • I feel I should also note this allows creating "hacked" versions of your apps that are signed as being from you while having the content the bad guy wants, which could be bad. The "right" answer here is resigning on the server along the lines of https://stackoverflow.com/questions/6896029/re-sign-ipa-iphone - it does mean your server will have your code signing private key though, which is also dangerous! – Simon Buchan May 15 '18 at 00:10
  • @SimonBuchan but this is way more fun! – mvds May 15 '18 at 00:16
3

I think you can use Jenkins Build for such type of requirement.Just need to change your resources before build action.And it will generate ipa with new

logo,
Splash,
App_Identifier,
App_DisplayName,
Even Product name you can change.

logo and splash can be replaced by some php script before build action performed.

And For App_Identifier,App_DisplayName,Product Name you can use

Config.xcconfig file

For config.xcconfig look at this link

For Ex. see my Config.xcconfig file Info

appDisplayName=My App
appIdentifier=org.myComp.myApp
productName=katWalk

I take variable in which value is inserted.

For Product name to change Go-> Build Settings->Packaging -> Products

and put that variable name alog with braces followed by dollar($) sign as

enter image description here

To change App_Identifier and app_DisplayName Go -> App-Info.plist file and change the variable names as

enter image description here

Now you need to change that variable values in config.xcconfig file before build and your app will be ready with new logo,Splash,identifier,display name and new product name.

May this will help you

Community
  • 1
  • 1
Prince Kumar Sharma
  • 12,591
  • 4
  • 59
  • 90
  • Sounds like an option. I'm not sure how to do this with Jenkins though. I'm not very familiar with Jenkins. Remember, that this all has to be done automatically online as well. So the user case is that someone goes into mywebsite.com/their_personal_site/iPhone_app and clicks "download". At that moment (or when the personal site is made) the new app should be ready to go. – Holger Sindbaek Jul 27 '13 at 15:31
  • yes i made one something like this using jenkins build and change the following things I mentions above.User uploads his splash and logo and through php or any other script we replaces those files and rebuild with new identifier,product name,logo ,splash and Display name , and archieve an ipa to be downloaded by user. – Prince Kumar Sharma Jul 29 '13 at 04:18
1

Yes, using PHP, Python, Ruby, or any another server side language, you can make a route that handles .ipa and .plist requests. When these come in your server side program can determine which ipa and plist to serve up for that URL.

It may be useful to store all IPAs and their information in a databased, this will allow your script to generate the entirely generate the plist at runtime.

Justin Meiners
  • 10,754
  • 6
  • 50
  • 92
  • Very good answer. I see where you are going. It's not quite a solution though. I've tried to explain a little bit better above. – Holger Sindbaek Jul 18 '13 at 02:42
  • @HolgerEdwardWardlowSindbæk ah I see - no I see no way the server could conditionally compile multiple ios apps. Perhaps the optional features are runtime? – Justin Meiners Jul 18 '13 at 03:08
  • The main features are run-time (it's basically a link that changes from app to app), but I have no idea how to change this link dynamically. Would be awesome if I could set the link dynamically somehow. Can you see any possibility of doing this? – Holger Sindbaek Jul 18 '13 at 03:25