Coming Soon: Strip Sync

2010-01-29 19:00:00 -0500

Updated: 6/6/2012 This blog post is out of date, and the software referenced in it, Strip Sync, has been discontinued in favor of Strip for Windows and Strip for OS X.

Strip IconWe’ve been getting a ton of mail lately about Strip, mostly along the lines of, “when will the desktop client be ready?” We’ve made a ton of progress over the last few weeks, and we really appreciate the various letters of encouragement and everyone’s enthusiasm.

Strip Sync

We are calling the initial desktop client Strip Sync. It provides some really critical functionality for the Strip platform going forward, and it will be offered for free here on our website. It runs on Mac OS X 10.5 and later, and most modern versions of Windows (although “modern” feels like a weird term, given the leap into the future that seems to be taking place at the moment). It’s really two separate, native applications that provide the same excellent and much-needed features:

  • Import from CSV – with files from Palm Strip Exporter or any other resource.
  • Synchronization with the iPhone – you’ll be able to bring over your old Palm data.
  • Independent back-up – for many people, the iTunes backup just isn’t enough.

At some point soon Strip Sync will also provide handy export and printing capabilities, but we’re really eager to get these much-asked-for features out there already, so export and print may not be introduced in the initial version. We’ll see soon.

We’re about ready to start looking for beta testers, we’ll post a notice here on the blog soon and send out a message to the mailing list. If you’d like to be added to our mailing list, send us an email, or just fill out the form over on the Strip product page.

Once Strip Sync is out the door we’re going to use it as the basis of the full-featured desktop version of Strip, which will allow you to enter and edit your data from the desktop, as opposed to having to slowly tap away with your thumbs on the iPhone.

What About Android?

We’ve been getting a lot of queries asking for a version of Strip for Android, but this one really jumps out:


Years ago, around the turn of the century, I used to work as an
engineer at Palm Digital Media (eBook division of Palm); all of the
devs and admins in our group worshipped your Strip app.

I have recently acquired an Android device (Nexus One). Please release
a version for Android.

Thanks for making one of the most useful applications ever,

We’d really love to do this, I mean, really, love. Right now our hands are a bit full with those two aforementioned native desktop applications! Once we have the desktop component firmly in place, we can begin to explore other platforms like Android, but for now it’s going to have to wait. We do expect to see an explosion of Android devices over the next year or so, and it would be a fantastic addition to the Strip platform.

If you’ve just got to have Strip on your platform of choice, please let us know, we’re listening.

Co-working Open House in Brooklyn 1/29

2010-01-25 19:00:00 -0500

My co-working space, The Change You Want To See, in North-side Williamsburg, is hosting our monthly open house event this Friday, the 29th of January. Anybody is welcome to drop in our space during normal hours, but our open-house event is a great time to meet other local professionals and free-lancers. People tend to be very focused during the day, and then at 5pm we do our happy hour (“beer o’clock”).

So, if you’re thinking of checking out co-working, or you just want to chew my ear off about one of our products, you’ll be most welcome. Do check the link and add your name if you plan on coming.

Tempo API Mailing List

2010-01-14 19:00:00 -0500

Our time-tracking service Tempo has an API available (an Application Programming Interface) that allows our customers to integrate their own software with Tempo directly. In the interests of fostering discussion, sharing tips, and providing another vector for making announcements directly to consumers of the API, I’ve created a mailing list on Zed Shaw’s new service Librelist.

To sign up, simply send any old email to:

You will receive a confirmation message, and once you are all confirmed, you should be good to go. If you are running code that integrates with our service, or are building something now, I encourage you to join the list and to share with us any difficulties you experience, that we might share knowledge that so often gets trapped in our “support” email box.

That said, if you want to address an issue privately, you’re always welcome to get in touch with us directly.

MTA NYC Transit Opens Data

2010-01-13 19:00:00 -0500

As a New Yorker and a firm believer in mass transit and open data policies, I am happy to see the big news that came with yesterday’s unveiling of the new MTA website:

The agency’s new policy does away with time-consuming data-sharing procedures and burdensome licensing requirements. As of today, schedule, route and fare information are available directly from the MTA website in a standard format, and the data will be updated whenever service changes. Similar set-ups have allowed developers to create scores of transit applications for cell phones and web browsers in other cities, giving riders convenient access to up-to-date information.

Amen! Visit the new developer access page to sign up for accessing to the MTA’s data. Looking forward to seeing what evolves, as I’m sure that apps like Across Air and Exit Strategy are only the beginning. I’ve come to use Exit Strategy a lot, more often for the built-in Subway map than for the nearest door to the NQRW stairway. Maybe I’m a touch old-skool, but I prefer a well-designed map to the augmented reality thing. Get off my lawn! City Transit apparently provides you with a lot of similar getting-around features, plus service advisories, which is handy.

I’m guessing the developers at iTrans really love dynamic programming, because the shortest-path problem is not an easy one, but they’re not content to leave it up to Google, as their app provides this offline, running its calculations on your phone. I need to give that a shot. This particular app is nice because it provides you further info outside the Subway, like PATH and NJTransit (although how accurate that data can be is questionable, as there has been no sign of opening up coming from either NJTransit or the Port Authority).

Cocoa: SQLCipher Manager Available

2010-01-05 19:00:00 -0500

We’ve posted a new project to Github: SQLCipher Manager.

I’ve got to make this brief because I have a ton of work to do, but we’ve recently split out a few chunks of re-usable code from our iPhone application Strip in order to facilitate sharing that code across multiple projects, both for the iPhone and for Mac OS X development. Most of that stuff will be staying internal, and wouldn’t be of much use to others anyway, but we decided to make SQLCipher Manager available as open source software under the same MIT-style license as SQLCipher itself.

The project on Github is an XCode project that builds a static library. You can use cross-project references to utilize this code from other XCode projects and to link against the static lib (required by Apple for us iPhone developers). There’s a great reference on doing this over at Mobile Orchard, so I’ll refrain fro going into the process here.

In short, it provides a singleton that handles your database connection to SQLCipher, keying, re-keying, notifying your app when the database has been created or opened, etc. This sounds like a no-brainer, but you end up re-using this code quite a bit, so it only made sense to define it and a delegate protocol:

@protocol SQLCipherManagerDelegate <NSObject>
- (void)didOpenDatabase;
- (void)didCreateDatabase;
- (void)didEncounterRekeyError;
- (void)didEncounterDatabaseError:(NSString *)error;

This means you’d do something like this in your app delegate, to initialize the manager for your application, and handle schema events:

- (void)applicationDidFinishLaunching:(UIApplication *)application {
NSLog(@"Setting up sqlcipher manager, and ourself as delegate...");
// setup the db manager register as the delegate
SQLCipherManager *dm = [SQLCipherManager sharedManager];
[dm setDelegate:self];
// set the databasePath property (required), use default iphone app documents directory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *saveDirectory = [paths objectAtIndex:0];
NSString *databasePath = [saveDirectory stringByAppendingPathComponent:CONFIG_DBNAME];
NSLog(@"setting db path to %@", databasePath);
[dm setDatabasePath:databasePath];

[self launchLoginView];

# pragma mark -
# pragma mark SQLCipherManagerDelegate

- (void)didOpenDatabase {
NSLog(@"Database opened");
SQLCipherManager *dm = [SQLCipherManager sharedManager];
NSUInteger schemaVersion = [dm getSchemaVersion];
if (schemaVersion != CONFIG_SCHEMAVERSION) {
NSLog(@"handing off to schema manager, found old version %d", schemaVersion);
StripSchemaManager *schemaManager = [[StripSchemaManager alloc] initWithSQLCipherManager:dm];
[schemaManager migrate:CONFIG_SCHEMAVERSION];
[schemaManager release];

- (void)didCreateDatabase {
NSLog(@"Database created, migrating");
SQLCipherManager *dm = [SQLCipherManager sharedManager];
StripSchemaManager *schemaManager = [[StripSchemaManager alloc] initWithSQLCipherManager:dm];
[schemaManager migrate:CONFIG_SCHEMAVERSION];

- (void)didEncounterDatabaseError:(NSString *)error {
NSLog(@"Database error! %@", error);
SQLCipherManager *dm = [SQLCipherManager sharedManager];
[dm closeDatabase];
abort(); // ouch, yo, but it leaves us a crash log for later

- (void)didEncounterRekeyError {
[self lockApplication];
[self presentError:[NSError errorUsingDatabase:@"An error occured rekeying the database. Please login again using your original password" reason:@""]];

Your login view controller (or whatever you are passing control to as the application sets up) would actually do the opening, or creating, of the database. Ours looks something like this:

- (IBAction)submit {
SQLCipherManager *dm = [SQLCipherManager sharedManager];
BOOL databaseExists = [dm databaseExists];

// just bail if the submitted password is invalid
if (![dm passwordIsValid:passwordField.text]) {
errorLabel.text = @"Invalid password";
self.passwordConfirm = nil;
passwordField.text = nil;

// if this is the first time through, require confirmation
if(databaseExists == NO && !self.passwordConfirm) {
self.passwordConfirm = passwordField.text;
passwordField.text = nil;
passwordField.placeholder = @"Confirm your password";
[passwordField becomeFirstResponder];

loadingImage.hidden = NO;
CFRunLoopRunInMode (kCFRunLoopDefaultMode, 0, true);

// seed OpenSSL RAND (removed)

SecureAppDelegate *appDelegate = (SecureAppDelegate *) [[UIApplication sharedApplication] delegate];
if (databaseExists) { // what mode are we in?
// attempt login, we only have passwordField present on screen
if ([dm openDatabaseWithPassword:passwordField.text]) {
[passwordField resignFirstResponder];
[appDelegate launchAppView]; // push new view controller, etc... wait we have no navigation controller...
} else {
errorLabel.text = @"Incorrect password";
[passwordField becomeFirstResponder];
} else {
if ([self passwordIsConfirmed]) {
[passwordField resignFirstResponder];
[dm createDatabaseWithPassword:passwordField.text];
[appDelegate launchAppView]; // here again we need to get our navigation controller going
} else {
errorLabel.text = @"Passwords didn't match";
[passwordField becomeFirstResponder];
passwordField.placeholder = @"Access password";
self.passwordConfirm = nil; // wipe fields
passwordField.text = nil;
loadingImage.hidden = YES;

Those are the basics of using SQLCipher in a Cocoa Touch application, and the approach is easily ported to Mac OS X. Can’t go into the various details right now, hopefully it’s explanatory enough. Questions should be posed on the SQLCipher-Users mailing list. Bugs and enhancement requests should be filed using the Issues tracker on the Github project.

Zetetic is the creator of the encrypted iPhone data vault and password manager Strip and the open source encryption-enhanced database engine SQLCipher.