Preparing Custom Bookmarks for import into BibleXpress

For content providers & developers only.


Bookmark Links

In version 1.2 and later, BibleXpress can share bookmarks  through e-mail, and the e-mail can include a link to import the bookmarks into a user’s BibleXpress bookmarks if tapped on their iPhone.  BibleXpress can also download bookmarks from a URL.  As content providers & developers, you are encouraged to provide custom content for bookmarks that users can import into their BibleXpress app.


This page serves as support for developers and content providers who wish to work on a Mac OS X 10.5 and later machine with an Intel processor to prepare their own bookmarks for import into BibleXpress, instead of tapping them all together on the iPhone.


The bookmark-importing links utilize the iPhone’s sole inter-application communication protocol: URL’s.   Although you can send the bookmark data directly in the URL, as is detailed lower on the page, the preferred method for content providers is to send users a link that causes BibleXpress to download the bookmarks from a file because it’s simpler, uses less bandwidth, presents a graphical progress bar & cancel button to users as large files download, and does not strain the URL handling system for large bookmarks & reduces caching for Mail and Sarafi.


Preparing your bookmarks is a 3 step process:


1.    Create your bookmarks in accordance with the “Dictionary Representation” section on this page.


2.    Download the free BibleXpress Bookmarker BibleXpressBookmarker.app.zip, run it on your Intel-based Mac running Mac OS X 10.5 or later.  (Using it on a PowerPC-based Mac will cause BibleXpress to crash on the iPhone and perhaps the entire phone.)  Click the “Browse” button and select your dictionary file.  Then click “Save” and give an export filename.  The app will check the format of the bookmarks & let you know if there are errors.  If there are none, it will write the bookmark data file to the path you specified.


3.   After posting the bookmark file from step 2 on the internet, provide your users a link with the following format:


biblexpress://downloadbookmarks?yourURL


where “yourURL” is replaced by the URL of your bookmark file.


Examples of a webpage with the URL and an example property list file are located at:


URL link in webpage:

www.biblexpress.com/testLink.html


Example Property List of Dictionary Representation:

www.biblexpress.com/testPropertyList.plist


Please remember to test importing the bookmarks into BibleXpress before making them available to users.  While BibleXpress is programmed to ignore most formatting errors and abort the import process, it may be possible to create files that create a problem.


Dictionary Representations

I recommend using the “Property List Editor” application (found in /Macintosh HD/Developer/Applications/Utilities/) to generate the dictionary representation of your bookmarks.  You may use either the XML or binary plist formats.


There are three classes of objects that can be in a dictionary representation in the bookmarks: folders, bookmarks, and notemarks.  All of these are represented by a dictionary, and the root dictionary must represent a folder.  You will also need to specify a “Reference” dictionary for each bookmark, and you may include a verse note array for a bookmark.


Each class has a key in the dictionary for it’s class, with the key “Class”, and the possible string values are  “Folder”, “Bookmark” and “Notemark”.  Each class also has a key for “Name”, and its value is a string that is the user-readable name of the folder, bookmark or notemark.


Folders also have a key “Children”, and its value is an array of children, each child is a dictionary representing a folder, bookmark or notemark.


Notemarks also have a key “Text”, and its value is a string that is the text of the notemark.


Bookmarks also have a key “Reference”, and its value is a dictionary that represents a reference.


References may have a “Class” key “Reference”, although it is not required.  References have a “Translation” key, and its value is a string that is how the translation appears in BibleXpress, for instance “NASB” or “NRSV”.  There is a “Book” key, whose value is a string corresponding to the EXACT way the book name is spelled in BibleXpress in the specified translation, for instance “1 Corinthians”, including spaces, capitalization, etc...  There is a “Chapter” key, whose value is a number that is the number of the chapter (in 1-based indexing).  There is a “Verse” key whose value is a number of the value of the first verse that is selected (also in 1-based indexing).  There is an optional “LastVerse” key, whose value is a number for the last verse of the selection, if there is more than one (again, in 1-based indexing).  Chapter, verse, & lastVerse numbers may also be strings.


An example of a reference to John 3:16-18, NASB is as follows in full XML:


<dict>

<key>Class</key>

<string>Reference</string>

<key>Translation</key>

<string>NASB</string>

<key>Book</key>

<string>John</string>

<key>Chapter</key>

<string>3</string>

<key>Verse</key>

<string>16</string>

<key>LastVerse</key>

<string>18</string>

</dict>


Bookmarks may have an optional “Notes” key, whose value is an array of strings, each string of which corresponds to a verse referenced by that bookmark.  So if the reference is to verses 16-18, you need to include an array with 3 item.  If you include verse notes, the user will be asked if they should be imported, and if the user permits, the notes will be appended to their verse notes during import.  If you are going to include verse notes, your root folder dictionary should have a key “IncludesVerseNotes” and the value should be a String that says “YES” or “NO”.  If you do not include this key, but include notes, they will be ignored.



Creating URL Encoded Bookmarks

If, for some strange reason, you want to send the bookmarks encoded in the e-mail in the same format that BibleXpress sends them between applications, you first need to follow these steps:


1    Create the dictionary representation of your bookmarks.

2    Get an NSPropertyListSerialization in binary format.

3    Compress this binary plist data using libz.dylib

4    Prepend the uncompressed length of the plist data into sizeof(int) bytes on the front of the compressed data.

5    Encode the data in base 64 (e-mails aren’t guaranteed to handle more than 7 bits of each byte correctly.)

6    Place the base-64 encoded data into BibleXpress’s bookmark URL scheme:


BibleXpress URL Schema

The BibleXpress URL schema includes, among other things, the ability to import bookmarks.  An example bookmark URL is shown here:


biblexpress://bookmarks?customData


Copy this letter-for-letter, but replace “customData” by the base-64 encoded bookmark data.


You can embed this in an html link in the following way:

<a href=“biblexpress://bookmarks?customData”>Click here to import these Bookmarks.</a>  If the user taps on this link from  a webpage or in an e-mail on their iPhone with BibleXpress 1.2 or later installed, BibleXpress will launch automatically and ask the user how they wish to import the bookmarks.


Base 64 Encoding

BibleXpress bookmark data is “base 64” encoded so that it may be sent through e-mails without fear of corruption.  It is simple to create a base-64 encoding, and for Cocoa developers, the same code I use to create the base-64 encode on the device and decode is available for free download here: NSData_Base64Encoding.zip.  This code is an extension to NSData, and provides a method that takes an NSData instance and creates an NSString that is a base-64 encoding of the data.  It is important that this string replace the “customData” in the URL example above, and that it not be modified in anyway.


Getting Binary Data

The NSData object above should contain a binary xml representation of the bookmarks that is compressed.  With an NSDictionary, you can create a binary property list with the following code:


NSString *error;

NSData *pListData = [NSPropertyListSerialization dataFromPropertyList:bookmarkDictionaryRepresentation format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error];

if(nil != error)

{

NSLog(@"serialization error: %@", error);

[error release];

}


where “bookmarkDictionaryRepresentation” is the instance name of your NSDictionary which is a “dictionary representation” of the bookmarks.


Once you have this data, you must use libz to compress it, and the first sizeof(int) bytes of data should be prepended to the data.  Here is code to do that:


int unCompSize = [pListData length];

unsigned long compSize = compressBound(unCompSize);

unsigned char *compData = (unsigned char *)malloc(compSize + sizeof(int));

memcpy(compData, &unCompSize, sizeof(int));

compress2(compData + sizeof(int), &compSize, [pListData bytes], unCompSize, Z_BEST_COMPRESSION);


NSData *compressedData = [NSData dataWithBytesNoCopy:compData length:compSize + sizeof(int)];


NSString *base64Bookmarks = [compressedData stringWithBase64Encoding];

[compressedData release];

free(compData);


The compressedData instance is the data you want to then convert using [compressedData stringWithBase64Encoding];

Note that because I have used a memcpy to write the uncompressed size to the data object, this only works on Intel byte order machines.


Conclusion

I hope that many of you will be able to provide custom solutions for BibleXpress users, a community that is growing very rapidly.  Most folks are asking for “daily reading,” that’d be a good place to start.


If you would me to post a link to your website’s bookmark-importing link, contact me at support@biblexpress.com.