Brad Dominy

Selected Work

The following are projects I have written and designed, most of which are based on Cocoa for MacOSX. I have also written AppleScripts and used other languages like Python, PHP, Perl, C, and Java.

Office Location

Apple had a means of marking a person's office location in their LDAP schema by specifying a map image and then their coordinates. A utility called Directory in Leopard would show the map with the point marked with a pin, but it has since disappeared in Snow Leopard, probably because it was a little bit buggy. The whole setup seemed oriented towards smaller organizations running Open Directory, because it had a built in limitation of 500 entries and was quite slow when looking at our LDAP server. Still, it is a cool idea, so I decided to bring it to Address Book as a plug-in for our company employees.

All names and personal info in the above images have been changed to protect the innocent

The plugin works by first telling Address Book what kind of information it responds to and whether it is valid for that card. In this case, we let Office Location run if the user is looking at a Chapman employee's work address. For everything else, it is grayed out. When the user chooses the Show office location... from the popup menu, a new window is created and we fetch information from our LDAP server. This included some contact information, picture, which map to show, and their coordinates. Since we are running as a part of Address Book, it was important to not bog down the main thread, so this all happens in a background thread as a part of the new NSOperationQueue protocol.

When the fetch is done, it creates a PDF view with the office map and then an overlay with the image of the pin at the right location. This allows for easy zooming and centering without having to continually redraw the map. The window is a part of Address Book, so when the user quits out, the map window goes away as well.

Google Onebox Employee Search

Our internal website uses a Google mini for searching. One of the features of the box is the ability to create onebox modules to return specialized results. The technology is based upon XSLT and XML, so the first part was to create a php script that took in a search string and then did a LDAP lookup matching against name, email, phone, and other fields. Any matches are returned as an XML set.

All names and personal info in the above images have been changed to protect the innocent

The second part uses XSLT to transform those results into HTML. We didn't want to clutter up the page with too many results, so I also wrote some javascript code that would hide and show additional results if more than three results were returned. If only one result is returned, we present a full set of information and the employee's image.


Our VOIP system works with Cisco IP phones to illuminate a Message Waiting Indicator (MWI) light on the phones whenever a user has a new voicemail. It also allows for the delivery of those voicemails as wav attachments in emails. The only problem was that the system did not know when voicemails had been read and the Message Waiting Indicator (MWI) remained on all the time. This proved to be a distraction for people as they never could trust whether the light meant they really had new voicemail or not.

LightSwitch is a mail bundle which listens for the changing of the message read flag on delivered voicemails and then toggles the MWI light on or off to match. It is deceptively simple. First, mail bundles are not officially allowed by Apple and using them is an at your own risk proposition. However, gaining access to the guts of the Mail app was necessary in order to tie into the system. Second, our VOIP system let you toggle the MWI but only with a telnet session. Finally, the requirements were that it work in the background with zero setup, so it was a pretty tall order.

LightSwitch uses the account information for the voicemail IMAP account to lookup from LDAP a user's phone extension. It uses a technique called "swizzling" to replace a method with one of it's own in the objective-c runtime. This lets you listen in to the signals Mail normally sends internally, including the one when a message read flag is updated. Whenever a voicemail message is read, LightSwitch checks to see how many unread messages there are and if there are none, it starts a telnet session to our VOIP system to turn the MWI light off for that user's extension. It can also turn the light on if you mark a voicemail as unread. It all happens within a couple of seconds so user's are no longer worried about the system getting out of sync.

It installs by just being dropped into a user's Library/Mail/Bundles folder and by updating Mail's preferences to allow for bundles. Lately, Apple has been adding a couple of extra layers of protection to make sure that mail bundles are compatible, so while they are still not officially sanctioned, it looks like they are going to tolerate them for the foreseeable future.


Having up to date contact information for employees is essential for any large company. Apple has focused on Microsoft's Active Directory and their own Open Directory as a solution for this, but, in our case, these were not options. We also wanted to have more control over how the information was presented with custom labels and to show relationships between employees like having an attorney's secretary listed on their card. To bridge this gap, I created ABSync - essentially a one way sync client.

The first challenge was to clean up our LDAP server and bring it into compliance with Apple's LDAP schema. Our employee list had been designed to be accessed via a browser on our intranet. This meant a lot of the information was spread out in different databases with different owners, and the data was accessed directly thru cgis. We had a LDAP server as a part of our email server, but it had never been utilized for much more than holding email addresses. Once we loaded the Apple LDAP schema, we were able to begin populating it with data from all those different sources, including phone numbers, addresses, map information, photos, dates, and relationships.

All names and personal info in the above images have been changed to protect the innocent

The second challenge was to bring that information into Address Book. In our environment, we needed a way to let people sync this information when they are working on our internal network. It had to be relatively quick and work in the background and be pretty much bullet proof as losing contact information to an attorney is a serious offense. Sync Services is a framework that lets you build a sync client and handles a lot of the heavy lifting normally associated with syncing data. You register for various types of sync data, including contact information, and when the client connects, the sync server tells the client what kind of sync to perform and handles passing whatever data has changed since the last sync.

ABSync is a command line application that acts as a one way Sync Services client since the source of our data is read only. ABSync talks to our LDAP server to determine what changes have been made on the server and then generates the appropriate sync changes. I had to run the sync as part of a cycle where any changes made to an employees card was first accepted, and then in a follow up sync returned to the state on the LDAP server. It is not exactly what the Sync Services engineers had in mind, but it actually works pretty well.

The result is an Address Book with an "Office List" group that always contains a list of our active employees. If you make any changes to the data we control (i.e. modifies or deletes of the group, group membership, or information on an employee's card) it is automatically reverted. Any additional information you add like notes is not affected.

About me

Brad Dominy


By Language

By Frameworks