Michael Moore’s “Capitalism: A Love Story”

Warning: This blog post is an opinion piece by Greg Slepak (while he searches for an appropriate medium), and has nothing to do with Tao Effect news.

This weekend I saw Michael Moore’s latest film Capitalism: A Love Story. Like most of his films, this one should come with a disclaimer: for the duration of the film you’ll be looking at the world through the eyes of Michael Moore and those who reflect his views. Don’t expect to see or hear any conflicting views or arguments.

For those that hate Moore’s films, there’s plenty in the film to nit-pick about. There’s a scene where he does his best to convince you that all Christian priests hate Capitalism and consider it an evil. Some have argued that he’s misusing the word “capitalism” altogether and should instead say “corporatism”. He also tends to group various corporate entities into a single-group. AIG, Citibank, Goldman Sachs, Bank of America, etc. All of these are placed in the group of “evil rich people bent on screwing over the lower-classes while having cocktail parties on corporate yachts.” In some cases, there is actual truth to that notion, but of course for those looking to put down Michael and nit-pick, he leaves plenty of room in his films to accommodate you.

However, despite the flaws, I enjoy watching Moore’s films precisely because of how rare their kind is.

It has been my general experience in life that many of the people that I encounter are perfectly satisfied to watch the latest action blockbuster out of hollywood, and when a movie like Capitalism rolls out they do two things: they pass up the ticket to see it for another action blockbuster, and then proceed to lambaste his films with a level of ignorance that far exceeds anything that I’ve heard Michael Moore say.

What further amazes me is how successful Moore has been at getting his films to play at major theaters. There are many many other films out there that do a much better job of espousing upon the insanities of our society and yet hardly ever make it into major theaters. Documentaries like Food Inc., Jesus Camp, The Century of Self (video link), Who Killed the Electric Car, and many others only find home to a handful of theaters across the country. These important films have been kicked out of mainstream society, to be replaced by the latest blow-em-up out of Hollywood that has sold out several times over.

That scenario never ceases to amaze me. How such a large amount of people, often the group that stands to benefit most from seeing movies like The Century of Self, who often live quite miserable lives because of their complete ignorance of their surroundings, can constantly, repeatedly purchase tickets to the same exact action script that Hollywood modifies slightly on a bi-monthly basis.

Ironically, it may in fact be because of the overly narrow viewpoint espoused in Capitalism, and its heavy use of emotional content, that he is able to get it distributed so widely. I say that’s better than nothing.

Further, while there are many imperfections in his films, they nevertheless tend to bring up worthy causes and viewpoints into the mainstream for discussion.

I also have to credit Capitalism for making me consider a thought that I hadn’t thought of before, namely,

Why do we allow corporate lobbyists and advisers at all?

It seems to me that just as we supposedly have the separation of church and state, we should institute the separation of the state from all other entities other than, of course, “the people.”

One thing that I’ve been astonished to learn from some of these films (Moore’s and others), is how incredibly entrenched major corporations are in the decision making of our government.

I considered the opposing viewpoint, that perhaps “because they represent the interests of a large amount of people and jobs” they should therefore have a strong say in policy making.

However, this is simply not true. Corporate interests do not include various idealized notions such as the right to a trial by jury, and even more idealized, yet worthy, concepts such as the rights to “life, liberty, and the pursuit of happiness.” Corporate interests are much simpler than that, they just want to “make a lot of money.”

Worse, they have demonstrated unequivocally that the way they’ll go about getting this money will often be by screwing over their workers, and quite often, their customers as well.

So, it seems to me that such entities should have no place whatsoever in any policy making that affects the lives of people outside of their corporation (and in some cases even inside of their corporation). Their advice is usually, simply put: bad. And in the rare instances where it’s not, we certainly did not need them for it. Instead of dictating policy to our representatives, they can call in like the rest of us. Respected scientists, nutritionists, farmers and various other in-field experts make good advisers to the FDA and USDA, not the board members of Kellogg’s and Monsanto.

Government, people often forget, should be owned by the people to serve the interests of the people. When corporations get in the picture, the people are no longer represented, instead the interests of a very small minority is represented, usually at the expense of all the others.

This is what has happened to our government. Although this situation is not anything new, it’s nevertheless messed up and it’s certainly worth changing.

A good way to upset the status quo is simply through the spread of information and the systematic removal of ignorance. Michael Moore’s Capitalism: A Love Story, though certainly flawed, helps to serve this purpose by bringing some of these issues to the forefront of America’s consciousness, and for that reason, I recommend you see it.

Espionage 2.5.4 Released!

Espionage 2.5.4 contains minor bug fixes, user interface improvements, and a compatibility fix when using Little Snitch’s Configuration utility:

  • IMPROVED: When adding a folder to Espionage, “passwords do not match” is not displayed until second password is entered.
  • IMPROVED: Wording of documentation on how to re-import (aka restore) backed up or lost encrypted folders.
  • IMPROVED: Switched default keychain choice during install to separate keychain as it has some advantages.
  • FIXED: Issue where Little Snitch Configuration could cause app password prompt to appear repeatedly.
  • FIXED: Removed unnecessary error message to the log related to reodering of folders.
  • FIXED: Rare issue where “Edit Application Associations” button could be disabled when it shouldn’t be.

We decided to change the default keychain to the separate Espionage keychain for several reasons: 1) It can be slightly more secure because it encourages the use of a different password, unique to Espionage. 2) Unlike the the login keychain it will lock itself after 15 minutes of inactivity, or if your machine is put to sleep. This will cause Espionage’s main window to lock as well if Espionage is running. 3) Espionage will keep backups of the separate keychain in its application support folder.

For some, the only disadvantage will be an extra prompt upon login for your master password if you’ve set any folders to autounlock at login. If this is too much of an issue you can always choose the login keychain! 🙂

Enjoy!

Espionage 2.5.3 Released!

Thanks go out to Dirk for emailing us today and letting us know of a security issue whereby a folder’s password could be logged to the system log in a certain error scenario (not cool!). The issue itself is due to a typo in the code that was introduced in 2.5, versions prior to that are not affected.

  • SECURITY: [Important!] Issue introduced in 2.5 where folder password could be logged to system log on an error. (Thanks to Dirk for catching this!)
  • IMPROVED: Background UI when no folders in Espionage.
  • IMPROVED: Better minimum window size.

On the aesthetic side of things we’ve improved Espionage’s background UI for when no folders are protected:

New background UI

If you already have Espionage installed, the easiest and fastest way to update is to choose “Check for Updates” from the Espionage menu.

Otherwise you can download it here:

Espionage 2.5.2 Released!

Espionage 2.5.2 is primarily a bugfix release, but continues to add some polishing touches:

  • NEW: Added an intelligent fail-safe into Espionage to help users whose Finder settings cause the password prompt to appear frequently.
  • NEW: Documentation in troubleshooting section on what to check if the Finder causes the password prompt to appear too frequently.
  • IMPROVED: iSpy installer now places a Readme file alongside ispyd for those who don’t read the installer’s Readme.
  • IMPROVED: Updated Growl to 1.2.
  • IMPROVED: EspionageHelper is now completely 64-bit ready!
  • FIXED: Issue that prevented iSpy installer from running on some rare systems.
  • FIXED: Issue where previous keychain entry wasn’t deleted after moving a folder.
  • FIXED: Issue where moving a folder (as opposed to renaming) could cause erroneous errors.
  • FIXED: Minor issue where application associations could have their names edited.
  • FIXED: Two broken links in the help documentation to the ignore list page.

Enjoy! 🙂

Espionage 2.5 Released! (Update: 2.5.1)

Today we’re finally releasing a brand new Espionage, and we’re marking the occasion by skipping a few version numbers.

We’ve spent the past month and a half working long hours to bring this update to you, and we hope you like it:

  • NEW: Brand new helper! The heart of Espionage – greatly improved.
  • NEW: Fully featured global status menu! Enable it in the General preferences if it’s disabled.
  • NEW: Stay-Up-To-Date! If update checking is enabled, helper lets you know if you’re out-of-date!
  • NEW: Won’t lock app’s folders if the app quickly relaunches (makes app autoupdate smooth).
  • NEW: Espionage notices if you’ve changed a folder’s settings and prompts you to save them if necessary.
  • NEW: MacJournal application template.
  • NEW: Path Finder compatibility mode for Path Finder users! Enable in Espionage’s preferences.
  • FIXED: Minor issue w/iSpy kext (installer will re-install the updated version)
  • FIXED: Issue where a folder could fail to unlock on Snow Leopard
  • FIXED: Issue that would cause erroneous errors to appear upon renaming of a folder
  • FIXED: Issue that could prevent a folder from being renamed with “Locate Missing Folder…”
  • FIXED: Issue that could cause helper to hang on Snow Leopard.
  • FIXED: Issue that could cause helper to prevent proper shutdown of computer.
  • FIXED: Issue where built-in notifications wouldn’t post if Espionage is moved after running it
  • FIXED: Minor issue with autounlocking non-encrypted folders.
  • FIXED: Rare issue where installer could hang and cause high CPU usage.
  • FIXED: Rare issue where an app might not be watched for quit.
  • FIXED (2.5.1): Issue where application password prompt could appear upon login in 10.6.
  • FIXED (2.5.1): Crash in rare scenario involving quitting Espionage UI during an operation.
  • FIXED (2.5.1): A broken link in the help documentation.
  • FIXED (2.5.1): Bug in the iSpy installer related to version checking.
  • IMPROVED: Folder positions now stick when they’re rearranged in the list.
  • IMPROVED: Behavior if a folder fails to lock.
  • IMPROVED: Behavior if a folder fials to restore.
  • IMPROVED: Finder will now immediately reveal contents of a folder when it’s disabled.
  • IMPROVED: Updated iSpy framework for 64-bit support.
  • IMPROVED: Updating of helper is smoother.
  • IMPROVED: Better handling of applications with disabled associated folders.
  • IMPROVED: Script running architecture.
  • IMPROVED: Built-in notifications now use Core Animation.
  • IMPROVED: Visual feedback in uninstaller during restoration of folders.
  • IMPROVED: Many other improvements and bugfixes too detailed to list.

Overview of Significant Changes

New Helper

If iSpy is Espionage’s nervous system, then Espionage’s helper is surely its brains.

As we slowly make our way towards Espionage’s first birthday, its helper has been relatively unknown for the major role that it plays. Normally the only hint of its existence would be the occasional notification or password prompt, and sometimes, less fortunately, an indirect hint of its presence when Espionage suddenly “stops responding”.

Today this is all changing, as for this release we’ve focused almost exclusively on it. We’ve completely rewritten and redesigned Espionage’s helper. It is much more responsive, more stable, and far more powerful in its capabilities.

You can now do things like encrypt a new folder while interacting with your other locked folders. And the new architecture has finally allowed us to complete a much needed feature…

Global Menu Item

What used to be a sad little menubar item:


Is now a powerful and convenient way of managing your Espionage’d folders:


Path Finder Support!

Path Finder users rejoice! Espionage now has a checkbox for you in its general preferences. Just enable the Path Finder compatibility mode, and Espionage will work seamlessly with your favorite file manager.

Stay-Up-To-Date!

If you’ve enabled update checking (and we hope you have) Espionage’s helper will now quietly check to make sure you’re running the latest version. If it sees that you’re out of date it will post a single notification letting you know.

Support for Application Auto-Updates

In 2.5, you’ll notice a slight delay from the time an application quits to the time Espionage locks its data. This allows applications like Adium to auto-update without skipping a beat. If the application relaunches within 3 seconds, Espionage will not locks its data.

You’ll notice many other tweaks and improvements in this update.

We hope you enjoy it! 🙂

Building a better lock: TESharedObject

While I’m happy to see Grand Central in Snow Leopard, I won’t be using it in any of our applications anytime soon because that means we’d have to turn our backs on all those PPC users out there, and everyone who has yet to upgrade to Snow Leopard. I suspect that this represents a sizable chunk of the OS X using population, at least at the moment.

It would also be nice if we could use Clojure for writing Cocoa apps, but Apple decided to drop the ball on that one.

However, that doesn’t mean we still can’t write good, fast, multithreaded code.

Actors and Shared Data

Right now we’re in the process of rewriting parts of Espionage’s helper program, which is fairly multithreaded and does most of Espionage’s heavy-lifting. Currently we are using mutex locks (in the form of NSLock) to synchronize some of the shared data in the application, and while locks are “OK”, they can start to get messy when you’ve got a lot going on.

That’s why we’re going to convert the helper to use actors (courtesy of Plausible Labs‘ great PLActorKit). But even when you’ve structured your code to use the actor approach, you still have a problem if those actors need to operate on data that’s shared with other actors or other threads. This is where locks could come in, but locks tend to suck.

Locks are slow, everyone knows that, but in our experience they can also encourage bad code because you can associate a lock with just about anything, it doesn’t have to be a specific piece of data, it can be a group of actions operating on that data, or data related to it. When you don’t have consistency, things can get out of hand.

So I’ve written a class that aims to solve these two problems with locks.

TESharedObject

When you hold a lock, you prevent any other thread from accessing the data that it’s protecting, regardless of whether that is necessary or not. What if the data that you’re protecting is often only read from? Then despite the fact that it’s perfectly fine for multiple threads to read from a piece of data simultaneously, each reader has to wait in line for the lock to become available. This can really slow things down.

TESharedObject is a replacement for locks that takes this into account. It changes the “lock” paradigm in two ways:

First off, it’s a wrapper around shared data, that is as opposed to a lock, which is just another “thing” that you arbitrarily decide is associated with a piece of data, a decision that you may or may not change your mind about as your code evolves.

The other difference is that unlike a lock, it allows multiple readers to access the data at the same time, provided no one’s writing to it. Databases often take this same approach to improve performance.

Semaphores

TESharedObject implements a basic algorithm using the semaphore primitive. Semaphores aren’t used very often in Cocoa programming, so if you’re unfamiliar with them you’ll be forgiven. Quick overview: a semaphore is an entity that has a count associated with it. You can increase the count by calling, say, “up” on it, or decrease it by calling “down” on it. If you call “down” on it when the count is zero, you block until some other thread increases the count.

So, say we have a database, and we want people to be able to read from it safely simultaneously when no one’s writing to it. By using two semaphores and keeping track of how many people are reading we can accomplish this like so (pseudo-code):

semaphore sRead = 1;
semaphore sAccess = 1;
int readerCount = 0;

reader:
    down(sRead);
    if (++readerCount==1)
        down(sAccess);
    up(sRead);
    access_database();
    down(sRead);
    if (--readerCount == 0)
        up(sAccess);
    up(sRead);

writer:
    down(sAccess);
    access_database();
    up(sAccess);

Here the semaphore sAccess is used as the “lock” on the database, or more accurately, to suspend the next thread that calls “down” on it. Only the first reader will call down on sAccess. A second semaphore sRead is used as a backup to sAccess in the situation that another reader is already suspended on sAccess.

The code for the writer is simple, all writers decrement sAccess‘s count, meaning a single writer is enough to stop everyone.

Building A Better Lock

Now that we have the pseudo-code, we need a design for our lock, and to get the design we need to have some sort of an idea of how we plan on using this lock in practice. I know! It should look something like this:

NSMutableString *sharedData = [NSMutableString stringWithString:@"Poop"];
TESharedObject *superLock = [[TESharedObject alloc] initWithObject:sharedData];

reader:
    NSObject *obj = [superLock borrowForReading]; // like "lock"
    NSLog(@"We've got an object! Take a look: %@", obj);
    [superLock returnObject]; // like "unlock"

writer:
    NSMutableString *aStr = [superLock borrowForWriting];
    [aStr setString:@"Harro!"];
    [superLock returnObject];

There, that looks pretty good. Our superLock is bound to the data it’s protecting. When we want to have a look at the data we call -borrowForReading to “borrow” it, and once we’re finished with it we “return” the data by calling -returnObject. Simple enough, and it works just like using a lock. All we have to do is make sure that we don’t write to the data. If we want to write to it, we call -borrowForWriting instead.

Let’s have a look at what’s inside.

-borrowForReading

- (id)borrowForReading
{
    semaphore_wait(sRead);
    if ( ++readerCount == 1 )
        semaphore_wait(sAccess);
    semaphore_signal(sRead);
    return obj;
}

There’s our pseudo-code! Well, about half of it, I bet you can guess where the other half is. But before we get to that, let’s take a look at -borrowForWriting:

-borrowForWriting

- (id)borrowForWriting
{
    semaphore_wait(sAccess);
    writing = YES;
    return obj;
}

Here the code diverges a bit with the introduction of a new variable writing. We use it so that whether we called -borrowForReading or -borrowForWriting, we only have to call:

-returnObject

- (void)returnObject
{
    if ( writing )
    {
        writing = NO;
        semaphore_signal(sAccess);
    }
    else
    {
        semaphore_wait(sRead);
        if ( --readerCount == 0 )
            semaphore_signal(sAccess);
        semaphore_signal(sRead);
    }
}

And that’s it. We’re almost done now, if you’ve made it here, thanks for sticking with me. I only have two more things to show you, and I think it’ll be worth it.

TESharedMap

Another aspect of shared data that we’ve neglected to address is the notion of “globality”. Yes, I did just make that word up, but it has important consequences! When you’re dealing with shared data, you’re often dealing with global variables, and dammit, now you’ve gotta find a place to put them!

A lot of people just put them at the top. They make long laundry lists of static declarations at the top of some file, and for each piece of shared data two declarations are required: the data, and the lock for the data. This can get kinda ugly, and ugly code is often harder to read and maintain. Our TESharedObject suffers from this same problem, it’d be nice if we could just focus on the data and not have to deal with the lock that’s associated with it.

We can get close to this with TESharedMap. TESharedMap acts as a “summoner”, we tell it: “Give us our object!” And it does. We don’t need to worry about keeping track of the associated TESharedObject, TESharedMap handles that for us. Put something into the map and it magically becomes thread-safe, so long as you remember to retrieve it only through the map.

Here’s its interface:

@interface TESharedMap : NSObject {
    TESharedObject *sharedMap;
}

+ (TESharedMap *)map;

- (id)borrowObjectForKey:(NSString *)key forReadingOnly:(BOOL)readonly;
- (void)returnObjectForKey:(NSString *)key;
- (void)setObject:(id)obj forKey:(NSString *)key;
- (void)removeObjectForKey:(NSString *)key;

@end

Benchmarks

What are the performance benefits of using TESharedObject and TESharedMap instead of NSLock and the like? For this I’ve written 3 programs, they each do the same thing, the only difference is that each uses a different synchronization primitive that we’ve discussed (TESharedObject, TESharedMap, and NSLock).

Here’s the TESharedMap version:

#import <Foundation/Foundation.h>
#import "TESharedObject.h"
#import "Common.h"
#import "Config.h"

static int reader = 0;
static int writer = 0;
static int msgIdx = 0;
static int tCount = NUM_READERS + NUM_WRITERS;

static NSString *msgs[] = {
    @"Hello World!", @"how are you?", @"random message!", @"hope we have enough of these...",
    @"I'm sure we will", @"there so many!", @"How many messages does it take", @"to screw in a lightbulb?"
};

#define newMsgIdx (msgIdx++%(sizeof(msgs)/sizeof(msgs[0])))

@interface Actor : NSObject
- (void)readerMain;
- (void)writerMain;
@end

@implementation Actor
- (void)readerMain
{
    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    int i=READ_TIMES, readerID = ++reader;

    while ( --i > 0 )
    {
        fprintf(stderr, "Reader %d getting message...\n", readerID);
        NSString *message = [[TESharedMap map] borrowObjectForKey:OBJ_KEY forReadingOnly:YES];
        fprintf(stderr, "Reader %d got message: %s\n", readerID, [message UTF8String]);
        usleep(READ_SLEEP);
        [[TESharedMap map] returnObjectForKey:OBJ_KEY];
    }

    fprintf(stderr, "Reader %d done!\n", readerID);
    if ( --tCount == 0 )
    {
        printf("good-bye\n");
        exit(0);
    }
    [pool release];
}
- (void)writerMain
{
    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    int i=WRITE_TIMES, writerID = ++writer;

    while ( --i > 0 )
    {
        fprintf(stderr, "Writer %d getting message...\n", writerID);
        NSMutableString *message = [[TESharedMap map] borrowObjectForKey:OBJ_KEY forReadingOnly:WRITE_MEANS_READ];
        [message setString:msgs[newMsgIdx]];
        fprintf(stderr, "Writer %d set message to: %s\n", writerID, [message UTF8String]);
        usleep(WRITE_SLEEP);
        [[TESharedMap map] returnObjectForKey:OBJ_KEY];
    }

    fprintf(stderr, "Writer %d done!\n", writerID);
    if ( --tCount == 0 )
    {
        printf("good-bye\n");
        exit(0);
    }
    [pool release];
}
@end

int main(int argc, char const *argv[])
{
    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    NSMutableString *message = [[NSMutableString alloc] initWithString:msgs[newMsgIdx]];
    [[TESharedMap map] setObject:message forKey:OBJ_KEY];

    for (int i=0; i<NUM_READERS; ++i)
        [NSThread detachNewThreadSelector:@selector(readerMain) toTarget:[Actor new] withObject:nil];
    for (int i=0; i<NUM_WRITERS; ++i)
        [NSThread detachNewThreadSelector:@selector(writerMain) toTarget:[Actor new] withObject:nil];

    // wait for threads to terminate...
    while (tCount)
        sleep(1);

    printf("good-bye\n");
    [pool release];
    return 0;
}

The program launches a certain number of readers and writers, and they each access an NSMutableString a certain number of times. To simulate computation, each reader and writer sleeps for a certain amount of time upon accessing the string. The number of readers and writers, as well as other parameters, can be adjusted by modifying the “Config.h” file:

// play with these parameters
#define NUM_READERS 4
#define NUM_WRITERS 4
#define READ_TIMES 4000
#define WRITE_TIMES 4000
#define READ_SLEEP 1000
#define WRITE_SLEEP 1000

I ran 4 benchmarks using the *NIX ‘time’ command comparing the 3 synchronization primitives against each other by adjusting the number of readers and writers and keeping the other parameters constant.

Dramatic Results

TESharedObject results

First we see that the extra layer that TESharedMap adds on top of TESharedObject is pretty much negligible in terms of performance.

The results for 0r/4w is the worst-case scenario for TESharedObject (no readers), and as expected it performs pretty much exactly like the typical lock.

The results for 4r/0w is the best-case scenario, when there are only readers accessing the data. This is the real payoff, almost no penalty for accessing shared data! You can’t get this with mutex locks.

The other two results show what happens when you have both readers and writers, in which case TESharedObject quickly overtakes the mutex lock, but what’s most interesting is that as you add more readers, TESharedObject takes a fairly negligible hit while the lock’s performance is significantly degraded. Why?

The reason becomes pretty obvious if you actually run these tests yourself. What happens is that the readers dominate the lock. This happens because in this program, the data is besieged by a constant and unrelenting stream of readers and writers who lust after the data until they’ve had their fill. In this situation, the more readers you add, the less likely it becomes that a writer will be able to get a hold of it, so what happens is that there’s suddenly a stampede of readers with virtually unfettered access to the data which they quickly gobble up, and then after most or all of the readers have had their fill the writers get their turn.

So while TESharedObject can provide a significant performance boost, if your lock is highly contested by readers they can shut out any writers. In most of the situations that I’ve seen locks used, this doesn’t happen. But if you are using a TESharedObject in a maelstrom like this, you’ll probably want to subclass it and modify the -borrowForReading method so that it sleeps if the readerCount is too high, which will make it a bit slower, but it will still be at least as fast as a lock, and you’ll have better looking code.

I think that’s it for now. All the code in this post, including the code for TESharedObject and TESharedMap, is provided under an BSD-style license and can be downloaded by clicking the icon below:

TESharedObject

Enjoy! 😉

– Greg (twitter: @taoeffect)

Ooops! Help form was broken! [Updated]

Update: Our host has fixed the problem, the support form is back online.

We just noticed that the php installation on our host appears to be a little bit broken in the ‘mail’ department, and because of this we may not have received some support emails.

If you have not received a response from us after waiting 24 hours, please resend your support question directly to our support email address: .

We’ve contacted our hosting provider and are currently waiting for a response from them. Until we’ve fixed this problem our support form will be down. We’ll update this post once it’s fixed, and please accept our apologies for any inconvenience this may have caused.

Espionage 2.1 Released! (Updated for 2.1.1)

After over a month in development, Espionage 2.1 is ready.

Espionage 2.1 is a significant update, and one of the major changes is full support for Snow Leopard. Espionage 2.1 itself can be thought of as a “Snow Leopard” kind-of update in that on the surface it may appear to be very similar to 2.0.8, but beneath its familiar exterior is a fully revamped interior.

This is a significant update that everyone using Espionage is strongly encouraged to update to, as it contains many significant bug fixes, including a fix for a rare kernel panic that could occur in previous versions of iSpy. Also, because 2.1 updates iSpy the iSpy installer will run again. You will not need to restart or logout though, unless after performing the update Espionage cannot establish communication with its helper.

One other note is that we’ve had the chance to finally investigate the Logitech Control Center issue, and it turns out that Espionage is compatible with it, but only with the latest version of LCC (as of this writing, 2.7). Espionage 2.1 will detect if you have an older version installed and will refuse to run until you update to the latest version. Click here for more information.

Here is the full list of significant changes:

  • NEW: Snow Leopard Support
  • NEW: Autodetection of encryption settings upon adding an already encrypted folder
  • NEW: Xcode template to protect Xcode snapshots
  • FIXED: Panic in iSpy that could happen in certain situations.
  • FIXED: Crash that could happen after 1.x -> 2.x upgrade
  • FIXED: Fixed a bug resulting in 1.x -> 2.x upgraded folders being listed as not encrypted
  • FIXED: Issue where folder could get stuck with bad ACLs
  • FIXED: Irrelevant error messages to console in relation to ACLs
  • FIXED: Corrected iChat template
  • FIXED: Minor bug associated with ExpanDrive integration while restoring a folder while it’s unlocked
  • FIXED: Minor bug where dependencies for one association could be used for another in app templates
  • FIXED: Minor UI glitch when updating Espionage’s helper
  • CHANGED: Updated code signing certificate, you will be prompted to re-authorize Espionage to access keychain
  • IMPROVED: Modified warning for detection of Logitech Control Center to suggest update to latest version if necessary
  • IMPROVED: Updated all components of iSpy, now Snow Leopard compatible, fixed several memory leaks
  • IMPROVED: Significantly improved documentation on backing up folders (including documentation on Time Machine and other tools)
  • IMPROVED: When searching for a process, match only processes with same exact name, as opposed to names that contain it
  • IMPROVED: Espionage now detects upon launch folders that weren’t properly locked and syncs up to the situation
  • IMPROVED: Behavior on waiting for associations to quit when helper is stopped
  • IMPROVED: Changed default backup interval to 1 hour
  • IMPROVED: Protective ACLs are removed from folder while it’s disabled to allow folder sync with apps like ChronoSync
  • IMPROVED: Improved wording of password cover
  • IMPROVED: Improved a notification associated with disabling a folder
  • IMPROVED: Added check to detect when multiple, conflicting disk images could already exist for a folder being added
  • IMPROVED: Added check to detect when an already encrypted folder being added to Espionage was renamed
  • IMPROVED: Updated BWToolkit to 1.2.2

Overview of Significant Changes

Auto-detection of encryption settings

In previous versions of Espionage, adding an already encrypted folder to Espionage (for example, a folder you retrieved from backups), you needed to know two pieces of information: how the folder was encrypted originally, and what password was used to encrypt it.

Now you only need to know only one piece of information, and that’s the password that was used to encrypt the folder. Espionage will automatically detect the folder’s encryption for you:

Auto-detection of encryption settings

Snow Leopard support and updated iSpy

Espionage 2.1 is now ready to be used on Snow Leopard, so those of you who have pre-release versions of it installed can now use your favorite encryption tool on it! 🙂

iSpy has also been updated, it is now much more robust, and a few small memory leaks have been plugged. A small number of users experienced kernel panics with the previous version, this is now fixed in 2.1.

Improved backup documentation!

We received some emails saying that our backup documentation could use some work, and hopefully with 2.1 we’ve addressed your concerns. It now includes documentation on how to restore or backup using Espionage’s backups, Time Machine, or using a third-party software/service. Check it out!

Espionage 2.1.1 Release Notes

2.1.1 fixes a couple of rare and minor issues with 2.1:

  • FIXED: Rare issue with trial error dialogue
  • FIXED: Rare issue that could lead to a failure to encrypt a folder
  • FIXED: Spelling of “Unlocking” (thanks Andreas)

Cloak contest over!

Thank you to everyone who submitted icons for the Cloak icon contest!

The contest is over, and my apologies for being two days late to the announcement.

The bad news is that we weren’t able to pick a winner, meaning Cloak will continue to use the same icon for the time being. The good news though is that I’m throwing the entire concept of having a contest out the window. If you think you can improve upon Cloak’s icon, by all means go for it and post your creation in the comments below. You may want to read some of the comments posted to the contest before doing so though.