« September 2009 | Main | November 2009 »

October 24, 2009

Tangent City

I blame Dave for wasting most of my day... He sent out a message saying that the URL of his site had changed. As part of that the URLs for his RSS feeds changed. I'm currently using Google Reader and wanted to update the feed URLs. I'm on a Mac and use Safari for my browsing needs. By default in Safari when you click on a link that is a feed it opens in Safari's RSS reader, not what I wanted. Off to investigate other options.

A quick Google search led me to a menu bar Google Reader tool that can also act as Safari's RSS reader. More than I wanted but a great option if I wanted to stay more on top of my RSS feeds. Not something I need to be doing.

At this point I'm vague on how I went down the path but I thought I'd create my own application to do what I wanted with an RSS feed. I really wanted to duplicate the "Add to Google" button behavior so I tracked down the documentation and then wrote a short Perl script to take an arbitrary URI and use that feature. For those interested the script is:

#!/usr/bin/perl -T

use strict;
use URI::Escape;

# verify that a URI exists to add
if (scalar(@ARGV) < 1)
{
    die "No URI passed.";
}

# untaint the path as exec is used
$ENV{"PATH"} = "";

# uri_escape_utf8() used in this context effectively untaints the data
# but given how it operates it doesn't satify Perl's untaint
# requirements. Since the PROGRAM LIST version of exec is used, a
# fairly liberal regexp can be used to untaint the uri.
my $uri = uri_escape_utf8($ARGV[0]);
if ($uri =~ /^([A-Za-z0-9\-_.!~*'()\%]*)$/)
{
    $uri = $1;
}
else
{
    die "URI is not safe : $uri\n";
}

exec("/usr/bin/open", "-a", "/Applications/Safari.app", "http://fusion.google.com/add?source=atgs&feedurl=$uri") || die "Unable to exec /usr/bin/open : $!\n";

It was only after writing the script that I realized one can't have a script act as an application on a Mac. Turns out there are two great options for packaging a script as an application. The first is DropScript and the other more fully feature one is Platypus. Turns out neither one worked for me. Despite twiddling all the knobs that I could with each program, my script never got passed the URI of the feed when I clicked on it in Safari.

Back to searching some more and I ran across a very light weight application called reader-helper that did most of what I wanted. As noted though there is a little bug in the program that causes Google Reader to freak out a little when clicking on a link. A quick scan of the program's source let me see that it would be easy to change the code to use the other URL for adding the feed and fix the Google Reader issue. Along the way I also fixed some missing URI reserved characters that should be encoded when passing a URI as a query parameter. The patch ended up being:

Index: GoogleReader.m
===================================================================
--- GoogleReader.m      (revision 8)
+++ GoogleReader.m      (working copy)
@@ -13,8 +13,8 @@

 +(void)subscribeToFeed:(NSString *)feedURL
 {
-       NSString *apiStr = @"http://www.google.com/reader/preview/*/feed/";
-       CFStringRef feedStr = CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)feedURL, NULL, (CFStringRef)@";/?:@&=+$,", kCFStringEncodingUTF8);
+       NSString *apiStr = @"http://fusion.google.com/add?source=atgs&feedurl=";
+       CFStringRef feedStr = CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)feedURL, NULL, (CFStringRef)@":/?#[]@!$&’()*+,;=", kCFStringEncodingUTF8);
        NSString *cmdStr = [apiStr stringByAppendingString:[NSString stringWithFormat:@"%@", feedStr]];
        NSLog(cmdStr);
        [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:cmdStr]];

My next problem was recompiling the source to incorporate my change. Thankfully all I had to do was wait for the newest XCode to download. Once I installed XCode creating a new binary was a snap. A ran into one last little issue in that Reader Helper doesn't exit after being launched. I had to manually kill the executable before my new binary was recognized.

While this wasn't how I thought I was going to spent my day it felt really good to just hack around on a little problem that was bugging me. It feels even better to have found a solution.

Tags: code hack mac

Tell Your Story, Ask a Sincere Question, Interpret Generously

Below is an excerpt talking about devolving online discourse from Diana Larsen, chair of the Agile Alliance board of directors, which was included in the Agile Alliance October Newsletter. Sound advice for any discussion, not just technical ones:
“Tell Your Story” encourages posters to share their perspective on a topic and avoid assuming they can know or can represent the perspective or thinking of others. For millennia, humans have learned through sharing stories. We’re wired that way. Telling my own story keeps me anchored in real events, emotions, intentions, and outcomes without second guessing the emotions or intentions of others. Listening to stories of other people’s experience helps me learn a fresh way of perceiving the world. Telling someone else’s story brings me too close to the slippery slope of judgment and labeling, and, like a bug in a venus-fly-trap, I slide into the Fundamental Attribution Error, interpreting other’s unfortunate behaviors and actions as arising from character flaws, while viewing my own actions through the lens of the unavoidable situational constraints and drama of my story.

“Ask a Sincere Question” supports a mode of inquiry and curiosity. I pose sincere questions when I show a willingness to admit I don’t know, “I’ve never tried pair programming, how do you start?” or seek to extend my knowledge “What’s on your task board? How does it work for your team?” So, what’s an insincere question? It’s when a statement masquerades as a question (Don’t you agree that...?) or the question disparages another (How did you get to be such an idiot?) or manipulates the respondent (Are you still beating your wife?).

“Interpret Generously” gives me an opportunity to rethink an initial reaction before I respond. I get to ask myself, “what else would have to be true for this puzzling position/behavior to make sense?” and “why would a reasonable person behave this way?” Once I can imagine a generous interpretation and a positive intent, whether close to actual facts or not, my reaction changes. I become more ready to ask a sincere question about the other person’s story and to learn what lies behind the mystery of why we have differing perspectives.

Tags: discussions online quote