6. Scripting the iPhone Configuration Utility

This chapter looks at automating the creation of config profiles via scripting. You’ll learn about scripting the iPhone Configuration Utility (iPCU) application itself, and how to bypass the iPCU entirely.

True, the iPCU isn’t hard to use. But if you want to create highly customized profiles, change profiles without manually doing so in the iPCU, or integrate profile creation and maintenance as a part of other workflows, you’ll want to use scripting.

This chapter is going to revolve around AppleScript because I know it really well, it does the job, and the syntax is somewhat self-documenting. However, you could accomplish the same goal in Python, Ruby, Perl, shell, C#, or almost any other language.

Learning AppleScript Basics

The AppleScript Language

AppleScript is a vaguely English-like programming/scripting language that allows you to manipulate applications to do things much faster than you could do them manually, and in exactly the same every time. I say “vaguely English-like,” because while AppleScript is almost English, it tends to not be English in amusing ways. For example, to display the URL of the current tab in Safari, AppleScript says:

tell application "Safari"
    set theURL to URL of current tab of window 1
end tell

That’s somewhat in English, but it’s probably not how you’d ask another human being for that information. So it’s “vaguely” English-like. AppleScript is also a dynamic language. Because it manipulates applications, it relies on each application to implement AppleScript within itself. As each application does different things—and there are no hard rules to much of AppleScript—you get some interesting differences. For example, to do the exact same thing in Google Chrome that we did in Safari, the AppleScript is:

tell application "Google Chrome"
    set theURL to URL of active tab of window 1
end tell

Why is it “active” instead of “current” or vice-versa? You’ll have to ask the developers of each application. Let’s just say that these application-specific “dialects” make AppleScript “interesting.”


Note

For more information about AppleScript, see Apple Training Series: AppleScript 1-2-3 by Sal Soghoian and Bill Cheeseman, published by Peachpit Press. The Internet also has many good resources such as Apple’s AppleScript Users’ email list (http://lists.apple.com/mailman/listinfo/applescript-users), and MacScripter (www.macscripter.net/).


The Dictionary

In AppleScript, you use the dictionary to see what scripting functionality an application supports. Everything that can be scripted has a dictionary. Even the base Mac OS X has one, called, amusingly, “Standard Additions.” (I’ll ignore the grammatical silliness of that. But it is some mighty silliness.) The Finder, Microsoft Word, and all AppleScript-able applications have a dictionary, including the iPCU. Some dictionaries are fantastic. (For all the ragging they get, the core Adobe CS suite applications have phenomenal dictionaries.) Others are less so. (We’ll not name names here. No sense in further embarrassing the wicked.) The iPCU’s dictionary isn’t the best I’ve ever seen, but it provides the necessary capabilities.

Scripting the iPhone Configuration Utility

I’m not going to go through every possible way to script the iPCU because this book would become infinitely long (and I’m not getting paid by the word. Alas!) However, let’s look at a few settings to give you a feel for what’s possible, and also to show you how to make a script flexible and fast, so you can customize .mobileconfig files with very little effort.

One thing to be clear about: you can only script configuration file setup with AppleScript. You can’t script application installs, and so on. Now, let’s look at a basic setup with email, CalDAV, and some restrictions.

The first thing you need to do in the script is make sure that it is targeting the iPCU; otherwise, you’ll have some serious issues. To do that, you use a tell block:

tell application "iPhone Configuration Utility"
end tell

You put all your code between those two lines, and your script will work much better. Remember that some basic items—such as the name—have to be in every profile, even though they are of no functional use. So, when you create the initial profile, you set those properties at the same time:

tell application "iPhone Configuration Utility"
    set theProfile to make new configuration profile with properties {displayed name:"scripted profile", profile identifier: "com.bynkii.scriptedprofile", organization:"Mr. Wonderful", account description:"I made it in a SCRIPT"}
end tell

Part of this script is pretty obvious. It’s telling the iPCU to create a new profile called “theProfile.” It has a list of properties such as the displayed name, the identifier, the organization, and the account description. AppleScript properties are created as an AppleScript record—that is, a comma-delimited list of elements that have an identifier and a value. So, in this case, an identifier is displayed name, and its value is "scripted profile". Since “scripted profile” is text, you enclose it in quotes to identify it as such. A colon separates the identifier and its value, and the whole thing is enclosed in curly braces. So, a generic record of text values would be:

{identifer1:"one",identifier2:"two",identifier3:"three"}

and so on. All AppleScript properties are records.

However, in the properties of this newly-created profile (Figure 6.1), you’ll see some things you didn’t create, like the id, removable, and the removal password.

Figure 6.1. iPCU creates some values automatically.

Image

Those values are needed, but in the case of the ID, you can’t create it, at least not via the iPCU. That’s okay because the iPCU does it for you. In the case of the removal and the removal password values, you didn’t specify them, so the iPCU set them to default values, “always” and “missing value” (a.k.a. “nothing”), respectively. That’s one of the advantages of scripting an application: the script can do a lot of the scutwork so you don’t have to.

Now that you have a base config, you can add some payloads; but first, a word about elements. An AppleScript element is a part of a class that can have its own properties. In this case, the main class is “configuration profile.” The configuration profile has its own properties, such as the id, organization, and so on. The payloads are classes that are also elements.

Why not make them properties, since they’re a part of the configuration profile? Because then you’d have a properties record that was insanely long and really hard to change or adjust. As you’ll soon see, by implementing the payloads as elements of a configuration profile, you can make things more modular, and easier to deal with.

One neat thing about AppleScript and the “tell” concept is that it’s not just for applications. You can use it for classes, too. So now that we created a configuration profile, we’re going to “tell” it about the payloads it’s getting. The first payload will be a restrictions payload. To add that, add the following code below the initial line that creates the configuration profile:

tell theProfile
    make new restrictions payload with properties {allow adding game center friends:false, allow multiplayer gaming:false, explicit content allowed:false, YouTube allowed:false}
end tell

This bit’s pretty clear, right? The only real difference with these properties is that the values are all boolean values, and are either true or false. Since they’re not text values, they don’t need the quotes. Luckily, we don’t care about the id because the iPCU takes care of this for you when you save the profile to a .mobileconfig file.

Next, create an email profile by adding in the appropriate “make new email payload” section:

make new email payload with properties {account description: "scripted email account", account name:"John C. Welch", account protocol:IMAP, email address:"[email protected]", incoming server hostname:"imap.bynkii.com", incoming server port:143, incoming server username:"john", incoming server uses password authentication:true, incoming server uses SSL:false, outgoing server hostname:"smtp.bynkii.com", outgoing server port:587, outgoing server username:"john", outgoing server uses password authentication:true, outgoing server uses SSL:false, use incoming password when sending mail:true}

No need to memorize this stuff, other than specific values such as the incoming server username’s value. It’s all in the iPCU dictionary. Now, for your CalDAV payload:

make new CalDAV payload with properties {account description: "scripted CalDAV account", hostname:"calendar.bynkii.com", port:80, principal URL:"http://calendar.bynkii.com/caldav", use SSL:false, user name:"john"}

Finally, you’ll need to tell the iPCU where to save the profile and with what filename:

export theProfile to "/Users/jwelch/Desktop/test.mobileconfig"

So, when we put the whole script together, we get:

tell application "iPhone Configuration Utility"
    set theProfile to make new configuration profile with properties {displayed name:"scripted profile", profile identifier: "com.bynkii.scriptedprofile", organization:"Mr. Wonderful", account description:"I made it in a SCRIPT"}
    --set theEmailUsername to "john"
    tell theProfile
        make new restrictions payload with properties {allow adding game center friends:false, allow multiplayer gaming:false, explicit content allowed:false, YouTube allowed:false}
        make new email payload with properties {account description:"scripted email account", account name:"John C. Welch", account protocol:IMAP, email address:"john@ bynkii.com", incoming server hostname:"imap.bynkii.com", incoming server port:143, incoming server username:"john", incoming server uses password authentication:true, incoming server uses SSL:false, outgoing server hostname:"smtp.bynkii.com", outgoing server port:587, outgoing server username:"john", outgoing server uses password authentication:true, outgoing server uses SSL:false, use incoming password when sending mail:true}
        make new CalDAV payload with properties {account description:"scripted CalDAV account", hostname:"calendar. bynkii.com", port:80, principal URL:"http://calendar. bynkii.com/caldav", use SSL:false, user name:"john"}
    end tell
    export theProfile to "/Users/jwelch/Desktop/test.mobileconfig"
end tell

Pretty nice, and the results are a properly configured .mobileconfig file. That’s all well and good; but now, when you need to generate a new profile, you have to open the script and change the name. So what have you saved in terms of time and effort? Not much.

However, don’t despair, for you can fix this with ease. What you need to do is add a way to change just the user names without manually editing the script. To do that, you’ll add some code so that the script asks for the new name and then sets it. For simplicity’s sake, I’m going to assume all user names are the same for every account that the profile is configuring. To get this information, you’re going to use a command from the aforementioned “Standard Additions”: display dialog. Display dialog is a way to ask someone to enter a bit of text, and then use that text elsewhere. Display dialog returns a record, called the dialog reply, that includes three items:

• button returned: the name of the button clicked in the dialog

• gave up: the dialog time out (You can set a time out value if you wish. We won’t.)

• text returned: the text the human types. This is what we care about.

So, here’s the code:

set theUserName to text returned of (display dialog "please enter the user name" default answer "Bob")

Normally, you would set the display dialog line to something that would become the dialog reply, and then you’d pull the text returned from that. To save space and typing, we’ll just do it all on one line. We tell Standard Additions to set theUserName to the text returned from the display dialog command (the only “applications” you don’t need a tell block for are scripting additions, such as Standard Additions). The display dialog command is in parentheses because we want it to execute first, followed by the rest of the line.

We’ll put this line outside the iPCU tell block for two reasons: First, the line has nothing to do with the iPCU. This is just good AppleScript practice. Second, it’s safer, although technically speaking, we don’t have to because Scripting Additions is omnipresent in AppleScript. Still, remember the little Chrome/Safari example earlier in this chapter? Well, sometimes application vendors are not as careful with names as they should be. Sticking a command from one dictionary into another is a way to get some really odd errors that will make you crazy. In the interest of avoiding the crazy-making, we shan’t be so silly.

You can then change the individual payloads. Wherever an option for a user name was present, change that value from the string it had, (“john” in this example) to theUsername. So you go from this:

username:"john"

to this:

username:theUserName

Anytime this script is run, it asks for a user name, and that name becomes the user name for every payload that needs one. If you need multiple user names, you’d use multiple display dialog lines and save the results to different variable names.

So, the script now looks like this:

set theUserName to text returned of (display dialog "please enter the user name" default answer "Bob")
tell application "iPhone Configuration Utility"
    set theProfile to make new configuration profile with properties {displayed name:"scripted profile", profile identifier:"com. bynkii.scriptedprofile", organization:"Mr. Wonderful", account description:"I made it in a SCRIPT"}
    tell theProfile
        make new restrictions payload with properties {allow adding game center friends:false, allow multiplayer gaming:false, explicit content allowed:false, YouTube allowed:false}
        make new email payload with properties {account description:"scripted email account", account name:"John C. Welch", account protocol:IMAP, email address:"john@ bynkii.com", incoming server hostname:"imap.bynkii.com", incoming server port:143, incoming server username: theUserName, incoming server uses password authentication: true, incoming server uses SSL:false, outgoing server hostname:"smtp.bynkii.com", outgoing server port:587, outgoing server username:theUserName, outgoing server uses password authentication:true, outgoing server uses SSL:false, use incoming password when sending mail:true}
        make new CalDAV payload with properties {account description:"scripted CalDAV account", hostname:"calendar.bynkii.com", port:80, principal URL:"http://calendar.bynkii.com/caldav", use SSL:false, user name:theUserName}
    end tell
    export theProfile to "/Users/jwelch/Desktop/test.mobileconfig"
end tell

For one at a time needs, this script is great. But if you wanted to be really slick, you could create a modified version that could, say, read a bunch of names from a file and then create multiple config profile files in one fell swoop. That’s just the ticket when you have a lot of people who need devices set up. For this task, we’ll make two assumptions to save space: all user names are the same, and the name in your email address is your user name.

First, add some new lines to the beginning of the script:

set theSourceFile to choose file
set theFileReference to open for access theSourceFile without write permission
set theNames to read theFileReference
close access theFileReference
set theNameList to every paragraph of theNames

These lines do several things. First, they ask you to pick a file that you want to use as a source for user names and email addresses. In this case, I created a text file with one name per line. When you choose this file, the file and path to that file are put into a variable called “theSourceFile”.

Next, you want to open theSourceFile to read the data. That’s what the “open for access” line does. Because you don’t need or want to change any data in the file, you disallow write access. This line creates a file reference number that is put into “theFileReference”.

Then, the script reads the data out of the file that theFileReference points to, and shoves it into theNames. This is a bunch of text with the names and the line-ending characters as its content.

To be neat, close access to theFileReference. You don’t need it anymore, so closing it is the correct thing to do.

Since we want to make that text in theNames into something easier to use, turn it into a list by getting every paragraph in theNames, and putting that into theNameList. A list is like a record, only it has no identifiers, just values separated by commas. When you ask for every anything in AppleScript, the answer is always a list. In this case, you want every paragraph, which is text separated by returns. Doing so creates a list with each name as its own entry.

So, you now have a list of names.

Now, modify the tell block for the iPCU. Just after the tell application "iPhone Configuration Utility" line, add some new lines:

repeat with x in theNameList
    set theName to contents of x
    set theUserName to theName
    set theEmailAddress to theName & "@bynkii.com"
    set theFileName to theName & ".mobileconfig"
    set theExportPath to "/Users/jwelch/Desktop/mobileconfigs/" & theFileName

A repeat loop is just that. It goes round and round doing things over and over until you tell it to stop. The repeat with x in theNameList line tells AppleScript that you want to go through every item in theNameList and every time you go through, shove the next item in the list into x. You then set theName to the contents of x because what is in x can be inconsistent. Sometimes it’s the contents of the list item, or sometimes it’s something not so useful such as item 1 of theNameList. By using the contents of x, you always know that you’re getting the name, and not a description of the place in the list where that name is.

Then use theName to create a few variables:

• theUserName (which you’ve seen before)

• theEmailAddress, created by concatenating theName and “@bynkii.com” into one text string (& is the concatenation operator in AppleScript)

• theFileName, by concatenating theName and “.mobileconfig”

• The path for the exported file, by concatenating the path to the destination folder, /Users/jwelch/Desktop/mobileconfigs/ and theFileName

Next, we go through our payload sections and make some substitutions. Wherever a user name is needed, that value is set to theUserName. Wherever an email address is needed, that value is set to theEmailAddress.

We also change our export line to read:

export theProfile to theExportPath

so that we create a separate .mobileconfig file for each name in the list, with the name as part of the filename. Finally, between the “export” line, and the “end tell” line, add an “end repeat” line to close the repeat statement correctly. The script now looks like this:

set theSourceFile to choose file
set theFileReference to open for access theSourceFile without write permission
set theNames to read theFileReference
close access theFileReference
set theNameList to every paragraph of theNames
tell application "iPhone Configuration Utility"
    repeat with x in theNameList
        set theName to contents of x
        set theUserName to theName
        set theEmailAddress to theName & "@bynkii.com"
        set theFileName to theName & ".mobileconfig"
        set theExportPath to "/Users/jwelch/Desktop/mobileconfigs/" & theFileName
        set theProfile to make new configuration profile with properties {displayed name:"scripted profile", profile identifier:"com.bynkii.scriptedprofile", organization:"Mr. Wonderful", account description:"I made it in a SCRIPT"}
        tell theProfile
            make new restrictions payload with properties {allow adding game center friends:false, allow multiplayer gaming:false, explicit content allowed:false, YouTube allowed:false}
            make new email payload with properties {account description:"scripted email account", account name:"John C. Welch", account protocol:IMAP, email address:theEmailAddress, incoming server hostname: "imap.bynkii.com", incoming server port:143, incoming server username:theUserName, incoming server uses password authentication:true, incoming server uses SSL:false, outgoing server hostname:"smtp.bynkii. com", outgoing server port:587, outgoing server username:theUserName, outgoing server uses password authentication:true, outgoing server uses SSL:false, use incoming password when sending mail:true}
            make new CalDAV payload with properties {account description:"scripted CalDAV account", hostname: "calendar.bynkii.com", port:80, principal URL:"http:// calendar.bynkii.com/caldav", use SSL:false, user name: theUserName}
        end tell
        export theProfile to theExportPath
    end repeat
end tell

You added a total of 12 lines of code, and changed 2 or 3 others, but created a script that can create 1 to 1000 individual config profiles, and the only change in effort is creating a list of names. The only other manual task is pointing the script at that name file.

That is why you write scripts; rather than creating all these config files by hand, you can create a bunch of profiles at the same time with a script, and you create them at machine speed, not human speed. Totally sweet.

Wrapping Up

To be honest, you don’t need the iPCU to script .mobileconfig files. They’re just text files with predictable sections and a predictable layout. You don’t even need the iPCU to create the UUID numbers, you can do that using uuidgen.

However, you’re going to do a lot more work creating the script without iPCU because now you will have to replicate the entire XML file structure by hand; and if that structure changes, who gets to change the script to account for that? You do! You’re also not going to gain much of a speed improvement. Even with the iPCU’s processing overhead, it’s going to create profiles automatically far faster than you ever will manually.

But, if you don’t want to use AppleScript, or C# on Windows, you’re kind of stuck doing it the hard way. If you can do that kind of scripting, however, you probably don’t need me to tell you how to do it. Spending some time with the iPCU and analyzing several .mobileconfig files will tell you all you need to know.

Whew, that was a lot. And if you’ve never seen AppleScript, this chapter felt even deeper. I’ll warn you, though. Once you get a taste for automating your work, you’ll quickly start automating more of your work. Wait! I’m not warning you, I’m encouraging you to do this. Life is too short to spend it doing repetitive scutwork on a computer. Automate, automate, automate!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.7.26