QuickLogin Plugin For WordPress

August 7th, 2011

This blog runs on WordPress, which has been a great solution for my needs. But as the developer of MarsEdit, you might guess I get the opportunity to see a whole heckuva lot of other systems, and sometimes find myself envious of their advantages, big and small.

One such advantage I noticed is that Squarespace users can log in from any page on their blog, just by pressing the escape key.

By default, WordPress requires that you either memorize the admin page URL, or list an ugly “Login” link i the blog’s template. I never liked the idea of having a login link for a site that only I should ever be logging in to, so for years I have omitted the login link from my site.

This means that when I’m reading comments or something on my site, and am not logged in, I have to do a silly dance before I respond or moderate a comment:

  1. Go to the URL bar in my browser.
  2. Change URL to /wp-admin/
  3. Enter the proper login credentials.
  4. Hit back button to get back where I was.
  5. Reload the page to see the comment form as a logged-in user.

This ends today. My QuickLogin Plugin for WordPress is a drop-in solution that, when activated, gives your WordPress blog the same delicious escape-key behavior that Squarespace offers. Now when I am browsing my own blog and want to log in, I just press the escape key. After I authenticate, I’m automatically returned to the reloaded page I was viewing.

The Case Of The Missing Filetype

August 4th, 2011

Black Ink 1.4.1 is out with just a couple bug fixes, free for registered Black Ink customers. New customers may purchase via the Mac App Store or directly from the Red Sweater Store.

This release fixes an issue where scroll bars in the clue list appear awkwardly under Lion, and also addresses a pretty nasty behavior for customers who have downloaded the new version of Across Lite’s official solving app: opening puzzle files in Black Ink fails completely.

How can the simple act of downloading another app render Black Ink useless for opening files? It has to do with Apple’s file-typing system, and an evidently relatively undefined behavior when two different applications lay claim to the same file extension, but tag it as a different type.

When I released Black Ink 1.0 a few years ago, I adopted Apple’s latest file-typing system, based around Uniform Type Identifiers (UTIs). These identifiers allow developers to provide more meaningful information to the system about what a particular file type is, what file extensions it correlates with, more basic types (like text) that it might be derivative from, etc. Developers who “own” a particular file type give it a UTI

Since Black Ink works primarily as an editor of Across Lite format files, a format that was not invented here at Red Sweater, it would have been appropriate for me to adopt the owning company’s UTI when identifying the files that Black Ink knows how to work with. The problem? Litsoft, the company that created Across Lite, had for years neglected to update their software much, and had never declared a UTI type for the file format.

So I declared my own. I did it politely, using my own domain name in the UTI: com.red-sweater.blackink.acrosslite. I did this purposefully rather than trying to make up something on Litsoft’s behalf, so that I wouldn’t be stepping on their toes when they inevitably defined their own UTI.

In the wake of Lion’s release, that’s what Litsoft finally did. Their latest update to Across Lite declares a definitive UTI type for Across Lite puzzle files, which is fantastic! The problem is, Black Ink 1.4 knows nothing about it. To make matters worse, on some users’ systems, the very act of downloading and trying Across Lite’s changed the system’s idea of what .puz files are.

So users who simply tried out another piece of software were suddenly unable to open puzzle files in Black Ink. Not a good situation.

In Black Ink 1.4.1, the Across Lite UTI for “.puz” files is now listed as an “imported file type” for Black Ink. This means that while Black Ink is not considered the authoritative app for this type (nor should it be), the system should consider it a suitable candidate for opening and working with “.puz” files, whether it thinks they are of Across Lite’s UTI, or mine.

The Power Of Plist

August 3rd, 2011

Most Mac and iOS developers know that when you build an application, you advertise a number of details about the application in the “Info.plist” file, located inside the application bundle. You can examine any application on your Mac and see what kind of information the developer has conveyed about it:

  1. Navigate to a .app file in the Finder, e.g. /Applications/Mail.app
  2. Control-click the app icon and select “Show Package Contents”
  3. Navigate to Contents/Info.plist
  4. Open with a plist editor or your favorite text editor.

These files advertise a number of interesting attributes including the application’s official version and copyright strings. They also include important clues to the system about what kinds of files the application knows how to read and write, and what its minimum system requirements are.

Minimum System Requirements

Declaring the right Info.plist values not only allows a developer to control which operating systems a product should run on, but which of the application’s architectures should be considered for a particular operating system. For example, Black Ink uses a number of keyed values describing its requirements:

	<key>LSArchitecturePriority</key>
	<array>
		<string>x86_64</string>
		<string>i386</string>
		<string>ppc</string>
	</array>
	<key>LSMinimumSystemVersion</key>
	<string>10.4.0</string>
	<key>LSMinimumSystemVersionByArchitecture</key>
	<dict>
		<key>i386</key>
		<string>10.4.0</string>
		<key>x86_64</key>
		<string>10.6.0</string>
		<key>ppc</key>
		<string>10.4.0</string>
	</dict>

Notice the fidelity of some of these options. Black Ink is an application that is compiled with binary code for three separate architectures embedded into it: 64-bit Intel, 32-bit Intel, and 32-bit PowerPC. In order to give the user the best possible experience after they double-click the application icon, the system consults the Info.plist values to determine which binary is most appropriate to load on the current system.

The options for Black Ink start by indicating that all things being equal, it prefers to run as 64-bit Intel, but will settle for 32-bit Intel or PowerPC in a pinch. Next, it conveys that it should not be run on any operating system earlier than Mac OS X 10.4. Finally, it adds an additional restriction by architecture, stating that in the case of 64-bit Intel, the system should consider Mac OS X 10.6 the minimum required OS.

Why so picky? For example, Mac OS X 10.5 will run on computers that are new enough to support 64-bit Intel code, but the 10.5 operating environment itself doesn’t contain enough compatible libraries to make it very useful to a full-featured Cocoa application. So we need to convince the 10.5 system to ignore our 64-bit Intel code. And this is how it’s done.

Embedding Info.plist

This is all well and good for applications, but what about other code that may be run on a variety of hardware and operating systems? In particular, command-line tools do not come in the same bundled-folder format that applications do. Fortunately, Apple thought of this when they implemented support in their developer tools for embedding the contents of an Info.plist directly into the binary itself. You just have to pass the Info.plist path to Apple’s linker tool when it’s constructing your binary file. (Thanks to Paul Kim for reminding me of this functionality). What this means in practice is adding arguments like this to your Xcode target’s “Other Linker Flags” build setting:

-sectcreate __TEXT __info_plist $(INFOPLIST_FILE)

This instructs the linker to crete a new text segment named “__info_plist” in the resulting binary, and to fill it with the contents of the referenced Info.plist file. To make sure the INFOPLIST_FILE expands correctly, just make sure you set it in the separate build setting for identifying the Info.plist (the one you’d normally use in an app, and that is just ignored by default for a command-line tool target).

I brushed up on all this information because I wanted to help ensure that some recent work I did to create a standalone MultiMarkdown tool would be backward compatible with older systems. This required adding an embedded plist much as I’m describing here.

(Note: I have gotten some feedback to the effect that the __info_plist segment’s minimum system version requirements may not actually be consulted properly on Mac OS X 10.5. This would be a bummer, and in fact sort of reject the whole point of embedding the Info.plist in this case. I’m going to see if I can confirm whether it doesn’t in fact work.)

You could technically embed all kinds of stuff in the binary, with different section names. But the contract in this case is that when Mac OS X is determining information about an executable, it will consult the bundle’s Info.plist file, if it happens to be an executable in a bundle, or the binary’s __info_plist segment, if it happens to have one.

Another common reason for needing to embed Info.plist information into a standalone binary is if you are using Apple’s code signing mechanism to sign an individual binary tool. Code signing uses information from the Info.plist of a product, and in the case of standalone binaries, the only product-cohesive place to put this is in the binary itself.

Examining Binary Info.plists

After you’ve performed the magic above, you’ll probably be keen to inspect your command-line tool’s Info.plist to see if it worked. To do this, you can use the otool command from the Finder. If you run otool with the “-l” option to show all load commands, it will include the load command that identifies the __info_plist segment. Use grep to narrow it down to the part you’re interested in:

otool -l ./yourTool | grep info_plist -B1 -A10

Any results at will confirm that there is Info.plist information in the binary, but how does it look? The “-s” option to otool lets you examine the contents of a specific segment in a binary, but it dumps it out as hex code. Fortunately, another system-bundled tool called “xxd” is capable of easily converting between hex-dump and text formats. As it turns out, some of Apple’s bundled developer tools (at least on my Mac) contain these embedded __info_plist sections, so if you don’t have a command line tool of your own to try this on, you can peek at what the “atos” tool has to say for itself:

otool -X -s __TEXT __info_plist /usr/bin/atos | xxd -r

In Summary

Info.plist values are important for conveying information about your product, from the crudest, most obvious stuff like version number, to the most nuanced details such as which architectures are supported. Knowing how to specify an application or tool’s requirements as precisely as possible will ensure that the product performs optimally on whatever supported system your user happens to be using. I’ve barely scratched the surface here with a few common deployment keys that control execution behavior on Mac OS X. Be sure to skim Apple’s Information Property List Key Reference to see if there are other useful bits of information you can share for your application or for your command-line tool.

Windowless Skyscraper

August 3rd, 2011

One of the thrills of software development is how much power is placed into the hands, literally, of a single engineer. Software takes work, and lots of it. But thanks to frameworks of reusable code, individuals are consistently able to “outbuild” the work of our predecessors, while exerting the same or less effort.

Consider the work that went into the first word processors and web browsers, whose work can now be mimicked by a Mac developer who knows how to embed NSTextView or or WebView. Imagine the time that early game developers invested in rudimentary sprite drawing, animation, and collision, which is now achieved easily in iOS games with open source packages such as cocos2d.

Still, building truly great software continues to elude most developers. It’s easy to assume that a large amount of time invested in a project, combined with an impressive outcome, is the key to a successful product. But it’s not so simple.

The ninety-ninety rule is often cited when describing the challenge of finessing a product after most of the hard work has seemingly been done:

“The first 90 percent of the code accounts for the first 90 percent of the development time. The remaining 10 percent of the code accounts for the other 90 percent of the development time.” — Tom Cargill

I agree with this perspective, and I cite it often when discussing software with others. The rule as stated is in terms of “code” but is also applicable to all the visual design, user experience, marketing, and positioning of a product. I think the rule is also recursive: whatever is missing can always be split up such that an “easy” 90% of the job can be done, leaving an elusive 10% of finesse work.

Many developers mistakenly assume that after they’ve put a ton of work into a project, and it achieves some impressive feat, that their work is done. When you focus on the enormity of work completed thus far, it’s tempting to pat yourself on the back and call it a day.

But customers don’t care about the hard work that went into the 90%. They only notice the flaws or omissions in the 10%. Imagine if Michelangelo’s statue of David was perfect in every detail, except that where David’s face should be, a clump of ragged, unfinished marble lay crudely in its place. Instead of marveling at the exquisite details of David’s feet, torso, and arms, viewers would reject it as unfinished and clumsy.

An important takeaway for software developers is that the missing 10%, or the missing one-tenth of 10%, may be something that will take a great deal of work to get right, but it may be something you simply overlooked the importance of.

You might build an impressive skyscraper projecting 40 stories into the sky. The architecture, interior design, plumbing, and electrical work may all be superior to that of your peers. But if some blindness in your product vision prevents you from adding windows, the product will never sell. It doesn’t matter how much time or effort went into this masterpiece: nobody will live in a windowless skyscraper.