URL-shortening scripts fixed (I think)

It’s been over a year since I posted these scripts for getting

Oddly, it wasn’t until today that someone—@ptujec in this tweet, to be exact—pointed out that the shortening scripts don’t work when the URL contains certain characters. Even more odd, I never ran into this problem myself, even though I use these scripts (or variants of these scripts—see below) almost daily. Still, I had to find the problem and correct it.

At first, I thought the problem was AppleScript misinterpreting an ampersand (&) in the original URL. Nope. Then I thought it was insufficient quoting in the argument passed to curl. Nope, although the argument should be quoted for safety. The problem, which would have been avoided if I had paid more attention to the Metamark API, was that the special characters in the original URL weren’t being escaped before sending it to Metamark for shortening.

So I wrote a quick Python script for URL-escaping, which I called escapeurl:

    1:  #!/usr/bin/python
    3:  from urllib import quote
    4:  from sys import argv
    6:  if argv[1]:
    7:    print quote(argv[1],'/:')

It replaces every character in the URL other than

with a code that looks like %nn, where nn is the hex code for the character. The original URL is the first argument to the command; the escaped version of the URL is printed to STDOUT.

With this utility made executable and saved in my ~/bin directory, I rewrote the AppleScripts. surl now looks like this:

 1:  tell application "Safari"
 2:   set longURL to URL of front document
 3:  end tell
 5:  set safeURL to do shell script "~/bin/escapeurl " & "'" & longURL & "'"
 6:  set cmd to "curl 'http://metamark.net/api/rest/simple?long_url=" & safeURL & "'"
 8:  set shortURL to do shell script cmd
 9:  set the clipboard to shortURL as text
11:  tell application "Play Sound"
12:   play "HD:System:Library:Sounds:Glass.aiff"
13:  end tell
15:  open location "x-launchbar:hide" -- delete this line if you're using Quicksilver instead of LaunchBar.

The significant addition is Line 5, which escapes the original URL by calling the little Python script. Similarly, scurl looks like this:

     1:  set longURL to the clipboard
     2:  set safeURL to do shell script "~/bin/escapeurl " & "'" & longURL & "'"
     3:  set cmd to "curl 'http://metamark.net/api/rest/simple?long_url=" & safeURL & "'"
     5:  set shortURL to do shell script cmd
     6:  set the clipboard to shortURL as text
     8:  tell application "Play Sound"
     9:    play "HD:System:Library:Sounds:Glass.aiff"
    10:  end tell
    12:  open location "x-launchbar:hide" -- delete this line if you're using Quicksilver instead of LaunchBar.

Actually, I don’t use the standalone versions of these scripts as much as I use versions embedded in TextExpander snippets1. Here’s what the surl script looks like as a TextExpander snippet:

TextExpander AppleScript snippets work by replacing the abbreviation—I use ;surl for this one, with the leading semicolon—with the output of the script. There’s no need to put the shortened URL onto the clipboard, so that line from the standalone script has been deleted. Because the creation of the shortened URL is obvious when the abbreviation is replaced by the output of the script, the clause that plays a sound has also been deleted. So has the LaunchBar-specific line at the end, because this version of the script isn’t run via LaunchBar.

Similarly, the TextExpander version of the scurl script looks like this:

and has an abbreviation of ;scurl.

I think these changes will allow surl and scurl to handle any URL you throw at them. Thanks to @ptujec for bringing this bug to my attention.


  1. Back when I wrote this post, I was using TypeIt4Me, but I switched to TextExpander shortly thereafter because TypeIt4Me gave funny results on my G4 iBook