CoreFoundation tutorial

bdrister edited this page Sep 13, 2010 · 3 revisions

Jonathan Head’s quick CoreFoundation tutorial

When creating your first Mac application you invariably reach the point where you realize you need some sort of way to protect all the time and effort you put into developing it. In other words, you need some sort of registration or license system so you can tell who’s paid for your marvelous app.

Enter AquaticPrime – a very elegant system that can do this for you. Fortunately it’s also relatively simple to add to your app, and with the great CoreFoundation implementation, fairly secure as well.

Before explaining how to add this awesomeness to your app, keep the following in mind:

  • This brief tutorial explains how to add the CoreFoundation version of AquaticPrime to your Xcode project to make sure license files are properly validated. It does not go over how to create and send license files to your customers.
  • Work in progress – this tutorial will (hopefully) be added to and improved over time, but it’s not perfect and can’t magically fix your problems. If you run into any problems after adding AquaticPrime to your project, use Xcode to add breakpoints in your code, then step through your program to see where the problem is occuring

All set? Let’s get started then.

First, you’ll want to download AquaticPrime via “Source” > “Download Source” above.

Inside your download you’ll see a folder called “Source” which contains a “CoreFoundation” folder.

Drag and drop the AquaticPrime.c and AquaticPrime.h files into your Xcode project in the Classes folder. Xcode will open a dialog box at this point – make sure to check the box to copy the files into your project.

At this point you can try and build your project, but it will most likely fail with a number of errors. To fix this you’ll need to add the -lcrypto flag to the Other Linker Flags, as seen below. Also, make sure Configuration is set to “All Configurations”.

The next step is to create a method that will check the license file a user enters to make sure it’s valid. The basic structure of what this method should look like is in the main.c file (located in the same CoreFoundation directory as the AquaticPrime.h and AquaticPrime.c files mentioned above), so I won’t include it here.

When using this CoreFoundation version of AquaticPrime with an Objective-C Cocoa application, the important thing to remember is that you may need to do some conversions before using the AquaticPrime methods.

For example, if you have an NSString that contains the file path to the license file that a user enters, you need to convert that NSString to a CFURLRef first before you can use the AquaticPrime method that will verify whether the file is valid or not. Here’s one way to do so:

CFURLRef filePathUrl = CFURLCreateWithString(kCFAllocatorDefault, (CFStringRef)filePath, NULL);

In the code above, the filePath variable can be an NSString that you’ve passed to the check license method you’ve created. Keep in mind, an NSString containing the file path must include “file://” rather than just be the raw path. In other words, it should be “file:///User/Home/Desktop/…” and not “/User/Home/Desktop/…”. If you are using the raw path (one that doesn’t have the “file://” part) then you need to use CFURLCreateWithFileSystemPath. Once you’ve done this conversion, you can then call a method to verify the license file:

APVerifyLicenseFile(filePathUrl);

The above method returns a Boolean (either true or false), so you can use it in a standard if statement to do various things (like return the name and email stored in the license file, etc.).

Once you have that working, you may want to access the data in the license file (to get the name, email, or whatever info that may be included). To do so AquaticPrime has a method that will create a CoreFoundation dictionary of that data. Here’s an example of how to use it:

CFDictionaryRef cfUserLicenseInfo = APCreateDictionaryForLicenseFile(filePathUrl);

So now you have a CoreFoundation dictionary, but how do you convert it to an NSDictionary to more easily access the data? This is easily done like so:

NSDictionary *userLicenseInfo = (NSDictionary *)cfUserLicenseInfo;

Side note: The reason this kind of conversion (from CFDictionaryRef to NSDictionary) is possible is because these two types are toll-free bridged, and all we’re doing here is changing the pointer type to make the compiler happy.

Now you have a NSDictionary of the data included in the license file, and can use it to store info in NSUserDefaults (which is a good approach to saving the “activation” status of your application – don’t just create a flag that stores whether your application has been registerd or not, that’s easily cracked by hackers).

Hopefully this short tutorial helps you incorporate the CoreFoundation version of AquaticPrime into your own application. If time permits, we’ll add more specific information on how to write the method that checks whether a license file is valid or not. Fortunately, the basic structure is well documented in the main.c file mentioned above.