Monday, April 7, 2008

Apologies

Sorry, I can't get enough of reading my own type (and corrections). I replied to SonOfPethuel's blog.

Friday, April 4, 2008

Create Firefox Multiple-Item Packages - maddon.py

I have a (growing) list of Firefox add-ons that I use all the time, so whenever I am customizing a clean machine, it's a tedious process browsing to each add-on's page and going through the installation procedure repeatedly.

I learned that the Mozilla framework supports Multiple-Item Packages -- multiple add-ons and/or themes grouped together in a single file. I've written a Python script which takes a list of add-ons and themes in any format I could think of and generates a multiple-item package for you -- maddon.py, for "multiple add-on." You can pass to it:

  • local .xpi/jar files
  • directories of .xpi/jar files
  • text files, with each line containing a .xpi/jar file
  • remote URLs
  • websites which will get scraped for .xpi/jar files

I use the text file VicsAddons.txt to generate my personal add-on favorites:
# Download Statusbar
https://addons.mozilla.org/en-US/firefox/addon/26
# Google Browser Sync
http://tools.google.com/firefox/browsersync/install.html
# CustomizeGoogle
https://addons.mozilla.org/en-US/firefox/addon/743
# Better Gmail 2
http://lifehacker.com/software/exclusive-lifehacker-download/better-gmail-2-firefox-extension-for-new-gmail-320618.php
# Better GCal
http://lifehacker.com/software/exclusive-lifehacker-download/enhance-google-calendar-with-the-better-gcal-firefox-extension-260074.php
# Better GReader
http://lifehacker.com/software/exclusive-lifehacker-download/trick-out-google-reader-with-better-greader-262020.php
# Adblock
https://addons.mozilla.org/en-US/firefox/addon/10
# dragdropupload
https://addons.mozilla.org/en-US/firefox/addon/2190
# Firebug
http://getfirebug.com/
# Google Gears
http://dl.google.com/gears/current/gears-osx-opt.xpi
# PicLens
http://www.piclens.com/site/firefox/tutorial_pl_ff.php

Running it produces the following output:
$ maddon.py VicsAddons.txt
Parsing 'VicsAddons.txt'
Parsing 'https://addons.mozilla.org/en-US/firefox/addon/26'
Scanning page...
Downloading 'https://addons.mozilla.org/en-US/firefox/downloads/file/24860/download_statusbar-0.9.6.1-fx.xpi'
Adding 'download_statusbar-0.9.6.1-fx.xpi'
Parsing 'http://tools.google.com/firefox/browsersync/install.html'
Scanning page...
Downloading 'http://dl.google.com/firefox/google-browsersync.xpi'
...

Created 'VicsAddons.xpi' with the following files:
download_statusbar-0.9.6.1-fx.xpi
google-browsersync.xpi
customizegoogle-0.71-fx+sm.xpi
bettergmail2_0.3.4.xpi
bettergcal_0.2.2.xpi
bettergreader_0.2.2.xpi
adblock-0.5.3.043-fx+fl+mz+ns.xpi
dragdropupload-1.5.25-fx.xpi
firebug1.0-current.xpi
firebug-1.1.0b12.xpi
gears-osx-opt.xpi
piclens-mac-release-1.6.2.1659.xpi
install.rdf

I can then drag VicsAddons.xpi to a Firefox window, and all add-ons and themes are installed in one fell swoop (restarting Firefox still required, unfortunately).

Note that since Firebug has both its current and beta versions on the same web page, maddon.py adds them both, which could be problematic. I could reference the exact desired .xpi version, but this loses the benefit of retrieving the latest version when run. Ah, trade-offs.

Here is the help.

usage: maddon.py [options] <file_or_directory> [...]

Create a multiple-item XPI. The <file_or_directory> argument(s) can be any of the following:

.(xpi|jar) file - added directly to bundle
URL, .webloc file
- if ends with '.(xpi|jar)', will be downloaded and add to bundle;
otherwise, the web page is scanned for links ending with '.(xpi|jar)'
directory - scanned for files satisfying any of the above requirements
text file - each line is scanned as if it were given as a parameter. Lines beginning
with '"', '#', '!', or ':' are considered comments

Friday, March 28, 2008

Find Duplicate Files - dups.py

I have a lot of images imported at different times and from different sources, and I wanted a quick way to find duplicates. Not finding a satisfactory (read: free) solution (though I admittedly didn't do a very exhaustive search), I took this opportunity to learn Python and came up with dups.py. Note that the file displays within a frame, so you might have to view frame source to get to the actual code.

Without arguments, dups.py checks the current directory, recursively:
$ dups.py
Duplicates found:
./Data/2004/05_4/015_12A.jpg
./Data/2004/2004.09.29 Grandma/015_12A.jpg
Duplicates found:
./Data/2002/19/uvs021219-008.jpg
./Data/2006/01_2/uvs040430-006.jpg
...
This has been tested on the Mac OS X and cygwin, and should also work with Python for Windows.

There are lots of nerdy options, like filtering by file size and following symbolic links. Try dups.py -h to see them all:
usage: dups.py [options] [<file_or_directory> ...]

Find duplicate files in the given path(s). Defaults to searching files recursively,
except for hidden files (beginning with "."), empty files, and symbolic links.

Options:
--version show program's version number and exit
-h, --help show this help message and exit
-v, --verbose verbose

Exclusion Options:
-f, --flat do not scan directories recursively
-g n, --greater-than=n
only scan files of size greater than n bytes
-l n, --less-than=n
only scan files of size less than n bytes

Inclusion Options:
-L, --follow-links follow symbolic links (warning: beware of infinite
loops)
-H, --hidden-files include hidden files
-z, --zero-files include empty files

Miscellaneous:
-D, --delete delete subsequent duplicates (files are scanned in
argument-list order)
-c, --create-rel-links
replace subsequent duplicates with relative links
(non-Windows only)
-C, --create-abs-links
same as "-c", but links are absolute
-s, --special-hidden
changes meaning of "hidden files" (-H) depending on
platform: cygwin - uses Windows file attributes
(warning: slow); win32 - files with names starting
with "." considered hidden

P.S. I hacked together a way to detect Windows hidden files from cygwin but it's ugly and slow.

4/6/08 update: I added the ability to delete duplicates (-D), and create relative (-c) or absolute (-C) symbolic links.

Saturday, March 1, 2008

Hacking Lite - Evading Coffee Shop Banners

This is mostly a note to myself and not intended to express approval of the behavior described ;-)

Occasionally I like to bring my laptop to a nearby coffee shop to get some work done without all of the distractions of my apartment. My favorite place has been a Tanner's Coffee Company within walking distance of my place. It's a little noisy sometimes, and the food isn't the freshest, but the drinks are decent and I seem to get a lot done whenever I'm there.

Their wireless offering injects an ad banner at the top of every page. This alone would not be prohibitively annoying since adblock successfully strips the ads, leaving only the banner, but what does tend to dampen the customer experience is that it breaks some sites, Google Reader in particular. Because of this, I started to do a little tinkering...

I figured they didn't inject all internet traffic, since I'm able to ssh without problems. Maybe they detect requests to servers at port 80? I toyed with the idea of using a local proxy server, blah blah blah...

Turns out, they actually filter on the user agent field within HTTP requests! This means that if you're using Firefox or Safari (or, I imagine, Internet Explorer), the banner will be injected; Opera, however, is ad-free. This also means that simply changing the user agent field that your browser declares in its HTTP requests sets you (ad) free as well.

In Firefox there are a number of ways to do this: install a Firefox extension, or simply add a string value to about:config named:

general.useragent.override

with a value like

Opera/9.26 (Macintosh; Intel Mac OS X; U; en)

as described here. It's probably a good idea to stick with a realistic user agent string as opposed to something arbitrary, since websites like Gmail may switch to less functional versions if they don't recognize your browser.

A quick way to determine your browser's user agent is javascript:document.write(navigator.userAgent).

The service responsible for the ads at this particular Tanner's (I think they're all independently owned) seems to be a company named AnchorFree. Chances are, this technique could work for ad-injection schemes used by other wi-fi spots.

Done and done. Back to high-quality coffee shop web surfing!

5/1/08 update: Okay, I'm dumb. A much easier way to do this is to add the filter

*.anchorfree.*

in AdBlock Plus. This solves the problem much more elegantly and doesn't run into issues with sites not supporting your supposed user agent.

Tuesday, February 5, 2008

Navigate Gmail Using Your Apple Remote

When I first got my Mac, I was really impressed with Front Row and how easy it was to manage all of my media with an interface as sparse and simple as the Apple Remote. Yet, there was one thing that left me wanting -- "If only I could use it to check my email," I thought wistfully. "I'd never leave my couch!"

Finally, my ambition for laziness can now satisfied! Though lacks the shiny polish of Front Row, an application called iRed Lite allows mere mortals to customize the behavior of the Apple Remote. I've written what's called a "layer" in the iRed Lite parlance, which is basically a set of actions tailored for a specific application.

If this is something you're interested in trying out, a couple of caveats about my solution:

  • It assumes you are running Firefox.
  • It assumes you are always logged into Gmail (by checking "Remember me on this computer" at login).
  • So far it seems that iRed Lite cannot save an entire layer at once; each action must be saved as a separate script. I've created an archive called iRedLite_Gmail.zip consisting of actions which I map in the following manner:

Open - browse to Gmaildouble-click play
Open conversation (o)play
Back to conversation list (u)left
Star conversation (s)hold play
Previous conversation (k)up
Next conversation (j)down
Previous message (p)right
Scroll downdouble-click down
Scroll updouble-click up
Increase text size (cmd-=)double-click right
Decrease text size (cmd--)double-click left

Of course you can easily remap them any way you wish. Beware that iRed Lite tends to crash here and there, though -- save early, save often.

To recap, first download and install iRed Lite. Then download and unzip iRedLite_Gmail.zip, create a new layer and import the actions defined in each file in the archive.

3/15/08 update: Thanks everyone for your comments! To summarize:

  • My actions have been grouped into one file here.
  • You need to enable keyboard shortcuts in your Gmail Settings for this to work.
  • This doesn't play well with Firefox Beta 3; I'll do what I can to tinker with this:
    • You'll need to change the "increase font size" shortcut to send "cmd-+" instead of "cmd-=".
    • "Open Gmail" doesn't work.

I will work on a Google Reader version at some point. I will incorporate everyone's suggestions and post updates here.

Sunday, August 12, 2007

From Your Side

Here are the lyrics to a song I wrote back in my less heathenistic days. I have an entry on my to-do list to record this some day but I haven't been very motivated to get it done.

From Your Side

There was a day
I thought I knew just what I wanted
But my heart had gotten in the way
There was no use
I was sullen as a stone
I didn't have a thing to say
I wish that you could carve my heart
So that I could have another start
But we all have our demons
And I know you have your reasons
I just wish I could see the other side
What does it really matter
You tell me there's an answer
But I can't help thinking that there must be more
I know it's not about me
But sometimes it's not so easy
I know the picture's bigger from your side
From your side
There is a way
And though I know which way to go
It doesn't wash the pain away
So now today
There is something I've got to do
I'm going to give it all away
I wish that I could see your eyes
'Cause then I think I'd realize
When the hunger is so strong
And I know I can't go on
You're always there to tell me it's all right
Could it be that I'm too late
But you're so willing to wait
There are better things than this world, in the next
I know it's not about me
But sometimes it's not so easy
I know the picture's bigger from your side
From your side
From your side