files
Spec for Bookdog's Successor
In order to more easily implement some of the features that users have been requesting and provide an application which is befitting Mac OS 10.5 and 10.6, early this year I decided to succeed Bookdog with a new application. Although Bookdog will continue to be updated as needed to maintain system compatibility, new capabilities and features are being designed into the new application only. I've been working on it for several months, and things are now coalescing to the point where it's time to publish a specification for public review, stating the differences between the new application and Bookdog. This page and the links on it are that specification.
Crossgrade Path for Bookdog Users
Our server is now set up to offer recent Bookdog licensees free crossgrade licenses within the new application with two clicks, and pro-rated discounts will be offered to longer-term Bookdog users. The new application automatically imports application preferences, document preferences and item preferences (unordered folders, false alarms, etc.) from Bookdog.
System Requirements
The new application requires Mac OS X 10.5 (Leopard) or later. Supported web browsers are:
- Camino
- Firefox 3.0 or later
- OmniWeb 5.0 or later
- Opera 9.5 or later
- Safari
- Shiira 2.0 or later
Supported web services are:
- del.icio.us
- Google Bookmarks
The old Firefox 2 and Netscape Navigator browsers are no longer supported. Users of these old browsers can easily use Bookdog to migrate their bookmarks to a supported browser or service, all of which are free, so there is no reason not to use them.
Name and Icon
There seem to be two kinds of Bookdog users: Those that love the icon, and those that hate it. An app should not be judged by its icon, and the fuzzy fur poses an unnecessary technical and artistic challenge. Therefore, the new application will have a new name, and a simple icon that may be beautiful, but will not evoke strong emotions either way.
Documents
The concepts of bookmarks documents and migration documents used by Bookdog can be confusing to users, and has limited what we can do. Therefore, the new application has one unified document called a bookmarks book, presented in a tabbed document window.
Three background tools and schedules replaced by on-demand Librarian.
Inside Bookdog is a companion Bookwatchdog which "watches" bookmarks for cues that ordering should be done. Migrations, can be scheduled using either Automator workflows saved as iCal plug-ins, or as launchd jobs scheduled by the Bookdog Migration Scheduler. With the new bookmarks book, these operations can now be performed by the same tool, called the Librarian, and the new application can use launchd in Mac OS X 10.5 to launch it only when a task needs to be done. After Librarian is done with this task, it terminates itself. Having one tool to do both ordering and migrating allows a wider mix of tasks and triggers, frees users from having to see Bookwatchdog in their Login Items, and frees me from having to write and maintain lots of code that is necessary to add it, remove it, launch it, check it, and quit it when necessary.
RSS Live Bookmark Feeds
Live Bookmark RSS feeds from Firefox or OmniWeb bookmarks are handled in a way that makes them useful when migrated or copied among Firefox, OmniWeb and Safari, and, by extension, the iPhone's RSS reader. The last-updated list of articles, which are typically yesterday's news, which were shown in Bookdog, are not shown, and similarly these articles are not migrated or copied to other browsers as bookmarks. If the other browser supports storing the current list of articles in its bookmarks, as do Firefox and OmniWeb, they are migrated or copied as articles. Instead of being shown as folders, the RSS feed:// url is shown, and also it is copied to the destination during a migration, move or copy/paste operation.
Inspector Window
In Inspector Window, junk has been removed and the layout improved.
The Bookmarks Book : A true "Document"
Document Structure in Bookdog
Bookdog does not have its own permanent storage place for your bookmarks [1]. When you click in Bookdog's File menu Open, Save or Revert, Bookdog operates on the actual files used by the browser or server [1], as though they were its own documents, although it implements some interlocks to avoid data loss in the event of conflicts. It calls these bookmarks documents.
To make this work, the special properties added by Bookdog, such as which folders you want ordered, etc., are stored separately in your Bookdog's document preferences, and, behind the scenes, item preferences. Bookdog associates these preferences with the bookmarks document when needed. Bookdog also has migration documents, which are real, albeit lightweight documents owned by Bookdog. Migration documents simply configure migrations between two bookmarks documents.
Evaluation of Bookdog's Document Structure
Bookdog's bookmarks documents are wysiwyg to an extreme; what you see is EXACTLY what you GOT. Users have grasped this easily; the only problem is that some would like it to be even more extreme, in that they are surprised they need to Save this document before the browser or service sees it. However the structure has some other, more serious drawbacks.
- The document preferences and item preferences are not a natural part of the Macintosh paradigm and therefore require a rather odd-looking list of documents in most of Bookdog's Preference tabs, and some stunts under the hood to make them work.
- Modelling simple migrations or synchronization tasks as stand-alone migration documents is handy to provide Applescriptability and thus scheduling capability to these tasks. However, people expect a Macintosh document file to have some substantial content.
- In order for Bookdog to be able to open standalone documents for advanced users, it must tell the system that it can potentially handle a wide range of document types, including .plist, .html and Opera bookmarks documents which have no .extension. In fact, it can handle only the tiny subclasses of these which are bookmarks. This has caused confusion when users without a plist editor installed click on, for example, a non-bookmarks .plist file and are told that Bookdog cannot open it.
- It does not easily lend itself to support an all-browsers bookmarks menulet such as is provided by URL Manager Pro.
- Standalone or backup files, not identified with a particular browser or service, have to be identified with a sequence number so that their document preferences can be tracked.
- Making File > Open and File > Save access data from other than a single file required writing lots of extra code to override Cocoa's standard behavior. Extra code means more maintenance and difficulty in adding new features.
Introducing a Single Document Type: The Bookmarks Book
The new application addresses these drawbacks with single unified bookmarks book which is now a real document, owned by the new application. So, obviously, this document now contains its own document preferences. Further, it also contains copies of your bookmarks (the Content), so that the item preferences are also contained naturally. Users of URL Manager Pro are now beginning to feel at home. It goes further, though. To use such a document for managing bookmarks in browsers and services, like Bookdog did, we import and export or sync bookmarks in and out, using new Sync In and Sync Out commands. A bookmarks book is configured to remember a list of Sync In and Sync Out browsers and services with which the synchronizations occur, and for each synchronization, and adjustments or translations required to match the browser/service feature sets. The On Open preference tab has added to it a setting to Perform Sync In whenever this document is opened and the On Save tab a similar Perform Sync Out whenever this document is saved. These boxes are checked on by default. Note that, because there may be more than one browser/service in the Sync-in and Sync-out instructions, the new bookmarks book has the capability to synchronize or migrate between browsers and services, so indeed the old migration document is no longer needed.
Usage Case 1: The typical Single-Web-Browser Users
Users that use only a single web browser such as Safari will work with only one bookmarks book. The Sync In will read from Safari only and the Sync Out will write to Safari only. If further the Open/Save preferences are configured to Sync In just after opening and Sync Out just before closing a document, this bookmarks book will behave in the same way that, for example, the Safari ◇ Bookdog document does. A wizard will silently this bookmarks book based on imported Bookdog preferences when Bookdog users first run the new application.
Usage Case 2: The typical Multiple-Web-Browser or URL Manager Pro refugee
Users of multiple web browsers and/or services who wish to have the same bookmarks in all of them, such as refugees from URL Manager Pro, will also work with one bookmarks book, but it will be set to Sync In from and Sync Out to their desired set of web browsers and/or services. For Bookdog users, it will no longer be necessary to chain three migrations together (A↔B, B↔C, C↔A) in order to synchronize three browsers A, B and C; nor will it be necessary to delete an item in all three different browser/services in order to get rid of it. For URL Manager Pro users who like the menulet (technically called a "status item" by Apple), this feature is planned to be added in a subsequent release.
Document File Location
By default, the user's first/only bookmarks book will be stored out of sight, in the user's Application Support folder, but more advanced users may create additional bookmarks books for special purposes.
Jerry Krinock
Bookmarks Book's Document Window
In order to accomodate the additional document functions which have been rolled in to the bookmarks book from Preferences and Migrations, the document window in the new application is tabbed. The tabs are
- Content. Shows the bookmarks and folders in hierarchical or flat view, with search fields; basically the Bookdog document window as it is now.
- General Preferences. Same as Bookdog's Preferences > General, but laid out to only the attributes of the (one) subject bookmarks book document, so there is no table. In addition, four checkboxes will be used to specify whether or not the document has a Bookmarks Bar, Bookmarks Menu, Unfiled Bookmarks, and/or Shared Bookmarks collection. The first two collections are to mirror the collections featured by most web browsers, Unfiled Bookmarks is a feature of Firefox 3 and Shared Bookmarks is a feature of OmniWeb. It is hoped that these four collections, or variations of them, will be sufficient to mirror the collections of any browser or web service for the foreseeable future!
- View Preferences. Same as Bookdog's Preferences > View, but laid out to only the attributes of the (one) subject bookmarks book document, so there is no table.
- Order. Same as Bookdog's Preferences > Sorting Order, laid out to only the attributes of the (one) subject bookmarks book document, so there is no table.
- Sync In/Out. See detailed description.
- Automation. Subsumes Bookdog's Open ("do upon launch") preference pane, the Bookwatchdog preference pane and the scheduling of Migration actions which must be done in Bookdog using Automator or the Bookdog Migration Scheduler. In this tab, the user configures a list of background jobs which are done while the new application is not running. Each job must have one or more triggers which may be configured configured to execute a sequence of commands.
The following triggers are available in a popup menu in the Type column:- When I launch New Application.
- When I 'Save' this Document.
- Bookmarks Changed in Browser. When this is chosen, it is followed in the Detail column by another popup. The items in the second popup are a selection of installed browsers.
- Scheduled Time of Day. When this is chosen, it is followed in the Detail column by another popup which has a time-and-minute selector, NSCalenderSelector or whatever they call it.
- When I Log In to my Mac Account.
Note: "Change in Safari Bookmarks" triggers 3 minutes after the actual change. Change in Other Browsers bookmarks triggers when the browser quits.
The available commands are:- Sync In. Followed in the Detail column with several choices:
- Yield to browser.
- Ask user if OK to quit browser
- Quit browser.
- Kill browser.
- Sort
- Find Duplicates
- Verify
- Sync Out. Followed in the Detail column with three choices:
- Yield to browser.
- Ask user if OK to quit browser
- Quit browser.
- Kill browser.
The Yield/Ask/Quit/Kill browser details handle the conflict which sometimes occurs if a browser is running. The problem is that, of the desktop web browsers, only Safari can handle either a Sync In and Sync Out while it is running. Other browsers can handle a Sync In only, except for Firefox 3 which can handle neither Sync In nor Sync Out. So, if a Sync In or Sync Out command in a job would be something that a running browser cannot handle, the new application (or Background Worker) needs to know what to do. The default is to Yield to the browser and abort the job; it doesn't get done. The second choice is to ask the user in a dialog. Of course, this option is not available for jobs started by unattended triggers. The third choice is to send the browser(s) Quit message(s). But web browsers frequently display stupid dialogs when you ask them to quit, for example: There is a window open. Are you sure you want to quit? If a user has scheduled a job to run overnight, there will be no one to answer this dialog. Therefore, the final option, useful in the overnight-job situation, is to Kill the browser, with no questions asked.
For example, to orderize Safari bookmarks whenever they are changed, the trigger would be Change detected in Safari, and the commands would be:- Sync In (which is configured in Sync In/Out to sync in from Safari only).
- Orderize all items.
- Sync Out (which is configured in Sync In/Out to sync our from Safari only)
- Sync In (which is configured in Sync In/Out to sync in from Safari, Camino and Firefox).
- Sync Out (which is configured in Sync In/Out to sync out to Safari, Camino and Firefox).
Note that, due to the unification of functions which were separate in Bookdog, many possible previously-impossible automatic jobs, such as the above example of synchronizing when a browser is quit, are now possible.
Before executing any command, New Application determines if it is necessary. Generally, if the bookmarks involved have not changed in any way that could affect the result since the last time the command was executed, command execution is not necessary and is skipped. The details of this determination are kind of complicated.
More to come.
Skipping Command Execution
Sometimes the commands in a job do not need to be performed. As an extreme example, if you don't use your Mac for an entire day, you don't have any new or changed bookmarks, and therefore there is no need for any of the commands in a job to execute.
Timestamps Used
Browfiles (the things that New Application remembers about external stores) store the following NSDate attributes:
lastInternalized
lastExternalized
Browfiles also compute dynamically, but do not store, a lastTouched NSDate value.
Bookmarks Books store the following NSDate attributes:
lastUnordered
lastOrdered
lastUnfoundDupes (dupes can go away too, if bookmarks deleted, so we don't say 'lastMadeDupes')
lastFoundDupes
lastUnverified
lastVerified
lastTouched
Comparison to see if needDo
With the above timestamps available, the following comparisons are used before executing a command, to calculate a boolean needDo.
Sync In. This command is executed as sub-command(s) called Internalize. Each extore in the Sync In list creates one Internalize command. For each Internalize, needDo if lastTouched > lastInternalized for the extore's browfile.
Orderize. needDo if lastUnordered > lastOrdered for the bmxBk.
Find Duplicates. needDo if lastUnfoundDupes > lastFoundDupes for the bmxBk.
Verify. needDo always.
Sync Out. This command is executed as sub-command(s) called Externalize. Each extore in the Sync Out list creates one Externalize command. For each Externalize, needDo if lastTouched for the bmxBk > lastExternalized for the extore's browfile. A file conflict occurs if the browfile's lastTouched > lastInternalized.
Execution
Finally, of course, the command is executed only if needDo.
Sync In and Sync Out
The Need for Adjustments
Not all browsers and services allow bookmarks to be stored in the same way. In Bookdog, each bookmarks document is wysiwyg (what you see is what you get) with respect to the browser or service. For example, Camino does not allow loose bookmarks at its root level. It only allows folders. Therefore, if a user drags, migrates, moves or copies some loose bookmarks into the root level of a Camino document in Bookdog, knowing that these are Camino bookmarks, Bookdog retargets them during the drop to the Bookmarks Menu of the Camino document, and the user is immediately aware of the issue.
This wysiwyg behavior, while nice, is not be available in the bookmarks book, because it is an independent document, not restricted by the requirements of any particular browser or service. The moves or other adjustments necessary to satisfy the destination browser or service will be made during Sync Out, and will not be shown to the user until the user launches the browser or service and sees the result.
Sync In and Sync Out Process Details
Sync In is a two-step process internally. First, the data is read in from the external browser or service to an external managed object context. Second, it is internalized from there into the bookmark book's document managed object context, making any adjustments that are required or specified.
Sync Out is a three-step process internally. The first step is externalize items from the bookmark book's document managed object context into the external managed object context, again using the old migrate routine to make whatever adjustments are necessary. The next step is to actually write out the data. For browser/services with atomic stores, this means to simply overwrite the old file. For browser/services with nonatomic stores such as Firefox 3 or any online service, this means to compare/insert/update/delete items on the server or in the database to match the items in the external managed object context. The third step, required for browsers or services which assigns external identifiers to new which are unpredictable, is to retrieve from the browser or service the external identifiers it assigned to any new items, and backfill those into the bookmarks book.
Some of the adjustments are optional. For example, when syncing in from a browser that does not support tags, some may want tags to be added to items based on their folder lineage. The bookmarks book window will have a tab for configuring these options. These options are generally those that are in the Translating tab of Bookdog's Preferences window.
Merging
Since Bookdog has no sense that the bookmark to "Apple" which it saw in your Safari bookmarks last week is the same bookmark to "Apple" that it sees in your Safari bookmarks today (unless you had given this bookmark special, extended properties), the only thing it compares is the URL, and it has only two choices when resolving a conflict: Either keep this one, or keep that one. When MERGE is selected as an option in Bookdogs Migration document, the user therefore gets a further option to Select which browser's items to favor when consolidating folders and avoiding duplicate bookmarks. It was a necessary design exercise for me to consider all possible use cases, but I would bet that the number of users who ever actually read the documentation or thought hard enough to actually understand what that option really does is probably about six or seven.
Several features of the new application allow this horrendous option to be removed:
- knows the unique identifier of every bookmark.
- reads the bookmarks it is about to overwrite before overwriting them.
- handles bookmarks asymmetrically, in its own context instead of wysiwyg-ing other applications.
- can merge the properties of individual items instead of just deleting one and keeping the other.
Avoiding Unnecessary Processing
New application
Browser Service Profiles
To perform a Sync In or Sync Out operations, the new application needs to identify the path, file format, and protocols required to access the external store, which is the source of data for a Sync In command or the destination of data for a Sync Out command. Physically, the external store is a file or directory, on a local drive or, for web services, on a remote server. The information about the external store is stored in a data object called a browser service profile. The attributes in this object are:
- External Store Format (exformat). This tells the application or worker what file format or API to use. Examples: Safari, Firefox, Delicious.
- Profile name. This is for browser names that have user profiles. Currently only Firefox uses this attribute.
- Store media. This identifies where to get the data. Possible values are: relative to user's home folder, relative to other user's home folder (possibly on other Mac), relative to remote server, relative to startup volume root.
- Other Mac Account This is required for other Mac account sources or destinations; bookmarks owned by desktop browsers on other accounts or networked accounts.
- Other Mac Volume This is optional, for other Mac account sources or destinations. It is used when bookmarks were accessed by mounting the root level of a networked hard drive.
- Standalone path. This is required for standalone sources or destinations. These are "loose" bookmarks files. Although they were created using the file format of a particular browser and thus have a browser or service name, are not known to that browser.
Jerry Krinock
Bookmarks Book's Sync In/Out Tab
This document describes the Sync In/Out tab of a bookmark book's window. This tab is divided into two parts.
- Sync In. Here we have ripped out half of Bookdog's old Migration document. This tab contains a list. The user lists, in order, the sources (browsers, services or standalone files) from which items will be matched or copied during a Sync In operation. (Users of only one browser/service will have only that single source and thus only one item in their list.)
When a Sync In is performed, for each item encountered in the source, the new application looks in the existing Content of the bookmarks book. If a corresponding item is found (it must have been copied during a previous Sync In), the properties of the two items are compared and, if any differences are found, the existing Content item's properties are changed to match the current properties of the source item. Note that an item's parent folder is a property, so this may also move items which were moved in the source. Corresponding items are matched by a unique identifier supplied by the source. If no match is found for a source item, the item is simply copied from the source. Mercifully, all browsers and services now supported, as well as those being contemplated for support in the future, now attach such unique identifiers to each of their items.
For each source, there are also four option checkboxes:
- Don't Create Duplicates. When match/copying in items from the second or later source, bookmarks will not be copied if they link to the same website or resource as an already-copied bookmark from a previous source. Note that this option does not stop duplicates which exist within the same source from being match/copied in.
- Create Tags From Folders. When match/copying in items, create tags for each user-created "soft" folder in the lineage of each bookmark. This option will only be enabled for sources which do not support tags. For example, if a bookmark is in a folder named "Fruit" which is itself in a folder named "Trees" which is in the source's Bookmarks Bar, when this bookmark is synced in to the new application it will have two tags, "Fruit" and "Trees". (The Bookmarks Bar is not a user-created "soft" folder.)
- Set Shared. When copy/matching in items, set the shared attribute to YES if this option is on and NO if it is off. This option is only enabled for sources which do not have a "private"/"shared" attribute such as Safari, Firefox and any other desktop web browser. Most web services such as del.icio.us and ma.gnolia.com do have such an attribute, so that attribute value is copied directly and therefore this option is enabled for those sources.
- Delete Unmatched. After copy/matching is complete, delete all items in the Content which were not matched by an item in the source. Not often used, this option allows the user to clone a bookmarks book Content from a "golden" source.
- Sync Out. Here we have ripped out the other half of Bookdog's old Migration document. This tab contains a similar list. The user lists, in order, the destinations (browsers, services or standalone files) from which items will be matched or copied during a Sync Out operation. (Users of only one browser/service will have only that single destination and thus only one item in their list.)
When a Sync Out is performed, any items in any destination which are not matched by items in the bookmarks book Content are always deleted, and the properties of remaining items are changed if necessary to match the properties of corresponding items in the Content. (For some browser/services, for technical reasons, this is done by deleting all items in the destination and then copying in all items from the Content. For others, this is done by copy/matching in items and then deleting the unmatched items. The user does not see this because, either way, the result is the same.)
There is one option, Create Folders From Tags which may cause additional copies of items to appear in the destination. This option may be set to one of three possible values
- 1. For each item with one or more tags, place the item in a folder which has the same name as one of the tags. Create this folder if necessary. The tag used is arbitrarily selected. That's not a very good situation, but the alternative is to order tags which is not done by any of the browser/services that support tags. But this is the way Bookdog does it now. This needs more thought.
- 1+. For each item with one or more tags, place the item in a folder which has the same name as one of the tags. Create this folder if necessary. For items with more than one tag, create copies of the item and do the same with each additional tag.
- 0. Do not create any folders from tags. This is the only value enabled for destinations which themselves support tags, since it would be undesirable to create such folders when you've got real tags.
Librarian replaces Bookwatchdog
Automatic Operations done by Bookdog
There are two operations that users have requested Bookdog be able to do automatically, ordering the bookmarks of one browser and migrating between browsers. These features are avalailable, sort of, in current versions of Bookdog.
How Bookdog does it, and how it Got There
Automatically Ordering. When I first wrote SafariSorter, and later the first versions of Bookdog, ordering of Safari bookmarks could be scheduled as a cron job. This was rather crude, but basically I was in a hurry and this is the only thing I knew. Later versions of Bookdog learned how to orderize when bookmarks were modified (Safari only), when browsers were quit, or at login. The capability to orderize on a schedule was dropped, since this would have complicated things too much and the three new options were way better. The actual ordering is done by Bookwatchdog, a background agent, specifically a Login Item, which is always running (if the user has scheduled any such ordering jobs).
Automatically migrating. Following Apple recommendations, I made the migration documents and the migrate command in Bookdog AppleScriptable, created a couple of Automator actions, and published instructions for scheduling Automator workflows containing bookmarks-migrating actions as iCal events. Well, although I've tried hard to believe in Automator, after working with users on it for a year, I decided that there must be a better way and found that AppleScripts could be scheduled as launchd tasks. So, I hacked together a quick AppleScript named Bookdog Migration Scheduler and also put a BookdogMigrationPerformer AppleScript in the Bookdog package. The Bookdog Migration Scheduler opens a migration document in Bookdog, asks the user to configure it, and then stores it into a special folder in the user's Library > Application Support. It then further schedules BookdogMigrationPerformer to run as a launchd task at a certain time every day. When BookdogMigrationPerformer runs, it runs the migrations in the special folder and voila, we have a daily migration that does not require Automator and does not appear in iCal, which is really annoying. (Well, maybe it's not too annoying because, just between you and me, I can't imagine anyone in a sales-type job that seriously needs to keep track of appointments and deadlines using something as lame as iCal.) Note now that, however it is scheduled, migrating is done by the Bookdog main application in the foreground. That's not necessary. Users who are most happy with the process schedule it for 4:00 AM or so.
A single tool to perform both ordering and synchronizing
First of all, in accordance with more modern usage, we're going to call copy/matching bookmarks items between and among browsers synchronizing and drop the term migrating. And, both operations will be done in the background by a tool named[AppName] Librarian tool. Unlike Bookwatchdog, the [AppName] Librarian will not be a Login Item and thus will not be visible to the user.
Triggers: Does [AppName] Librarian need to be always running?
The launchd tool, which is running all the time in Mac OS X, can schedule tasks to run on day/time triggers. It can also now watch directories, like the older kqueue used by Bookwatchdog. I believe this capability is new in Leopard's launchd. Anyhow, it's new to me! And it makes it possible to do all automatic operations without a constantly-running background agent, with all the headaches that entails. Instead, we can have a [AppName] Librarian, launched by launchd when necessary, and it can terminate itself whenever its task is complete. Here is how we implement the various triggers.
- Day/Time. The launchd tool is easily configured for this trigger.
- Login. The launchd tool is easily configured for this trigger.
- Change in [some browser's] Bookmarks. We use the new WatchPaths trigger in launchd to watch the bookmarks file or directory. ALSO, Experiments have shown that all web browsers, except Safari, reliably write a certain file or change the contents of a certain directory whenever they are quit. For some browsers, this is the bookmarks file. For others, it is a preferences file or some other file. Thus, if we tell launchd to launch our [AppName] Librarian whenever this certain path has been altered, and then our [AppName] Librarian waits a few seconds to see if the browser is running, and if it is not, then our [AppName] Librarian knows that the browser has just been quit. However, fortunately Safari is the only browser which allows us to change its bookmarks file while it is running. Therefore, to simplify the user interface compared to Bookdog, the same trigger is for Safari as for other browsers.
- [AppName] launched. [AppName] stores in its Preferences a list of documents (paths and aliases) which have a job with an appLaunched trigger. When it launches, unless it was launched by either Librarian or the user opening a document, it iterates through this list, opening the indicated documents and, for each, performing the job which has the appLaunched trigger.
Order via Email+Mail
Our applications feature built-in stores which allow you to purchase a standard License instantly using a credit card, e-check or Paypal funds, via either Google Checkout or Paypal. The application will visit our server to get your License Key instantly as soon as your purchase is complete. It's very cool when it works.
If for some reason this does not work for you, we'll take your order via email and you can pay by mailing us a personal or company check, or money order. Please allow up to 24 hours for processing.
