Blog

Ice Crystals

Some frost built up on a window in the garage. Lit with a halogen work lamp shining through an old lava lamp. How’s that for a gel?

It’s been cold lately (around -20°F’ish)… so facets are forming all over the place. This isn’t good for the avy season… but nature’s fractals sure make for nice pictures.

» See the rest on Flickr

Captify 1.1.3

December 1, 2009

The image caption plugin I wrote last spring that runs atop jQuery lives again. Made a few fixes, finally got the demonstration online, and zapped the size with Closure (only 2.3kb now!). We're now sitting at 1.1.3. Here's a demo:

Cider chillaxin' in the grass

Put your mouse over the image above.

Docs / Examples | Download

Follow Me on Twitter
RRD tool

rrdtool is a data logging and graphing utility that's great for system monitoring.

Compiling the latest RRDTool

cd ~
wget http://oss.oetiker.ch/rrdtool/pub/rrdtool-1.4.1.tar.gz
tar xzvf rrdtool-1.4.1.tar.gz
cd rrdtool-1.4.1
INSTALL_DIR=/opt/rrdtool-1.4.1
sudo mkdir $INSTALL_DIR
sudo chmod 777 $INSTALL_DIR
./configure --prefix=$INSTALL_DIR && make && make install
cd $INSTALL_DIR
sudo cp -r * /usr
rm -r ~/rrdtool-1.4.1
If you want to bypass the steps above and use a possibly-older version of RRD tool, just run:
sudo apt-get install librrd2-dev rrdtool
(more...)

We played in the snow today

October 30, 2009

For the past day, I've been working on developing a bookmarklet. Part of it involves injecting a sign-in form as an iframe into the page the user is on. Keeping the form snuggled up in a remote iframe is crucial for keeping the credentials the person types far away from the peeking eyes of potentially-malicious code on the page (see "Same-origin policy").

Well this is great. *sigh* Now how do you go about sending legitimate messages back and forth between the two documents?

The Solution
The answer lies with the blend of two techniques: (A) sending the data by setting the fragment identifier for the remote document and then polling for the change, and (B) implementing HTML5's window.postMessage() method.

xcom_send

var xcom_send = function(win, msg, origin){
	if (document.all ? document.documentMode : window.postMessage){
		win.postMessage(msg, origin ? origin : '*');
	}else{
		win.location.hash = '#xcom-' + msg;
	}
};
Argument Notes
win The target window to receive the message.
msg The string to send to win. This will be picked up by the callback setup with xcom_listen.
origin (optional) The domain(s) to allow communication to. Accepts a string, or array of strings. Domains should be in the form of http://the.domain.com (make sure to not include a trailing slash). Important: Don't depend on this for security---this argument will only be acknowledged by modern browers: IE8, Chrome, and FF3 beta 3 so far.

xcom_listen

var xcom_listen = function(win, cb, origin){
	if (document.all ? document.documentMode : win.postMessage){
		var receiveMessage = function(e){
			var safe = origin == null || origin == '*';
			if (!safe){									
				if (origin instanceof Array){
					for (var i = 0; i < origin.length; i++){
						if (origin[i] === e.origin){
							safe = true; 
							break;
						}
					}
				}else{
					safe = e.origin === origin;
				}
			}
			if (safe && cb) cb(e.data);
		};
		if (win.addEventListener) win.addEventListener('message',receiveMessage,false);
		else if(win.attachEvent) win.attachEvent('onmessage',receiveMessage);
		else win.onmessage = receiveMessage;
	}else{
		var l = win.setInterval(function(){
			if (win.location.hash.substring(0,6)=='#xcom-'){
				//window.clearInterval(l);
				var msg = win.location.hash.substring(6);
				win.location.hash = '';
				if (cb) cb(msg);
			}
		}, 250);
	}
};
Argument Notes
win The window to listen for messages from.
cb The callback function to receive any messages from win. The callback will be invoked with the message string as the first and only argument.
origin (optional) The domain(s) to allow communication from. Accepts a string, or array of strings. Domains should be in the form of http://the.domain.com (make sure to not include a trailing slash). Important: Don't depend on this for security---this argument will only be acknowledged by modern browers: IE8, Chrome, and FF3 beta 3 so far.

Usage Example

To listen for messages sent from an iframe in the document, use xcom_listen with a basic callback function:
var frame = document.getElementById('myframe');
xcom_listen(
    frame.contentWindow || frame, 
    function(msg){
        alert('From the iframe: ' + msg);
    }, ['http://mydomain.com', 'http://www.mydomain.com']);
From inside the iframe, use xcom_send and window.top to send a message to be captured by xcom_listen in the parent document (seen above).
xcom_send(window.top, 'I like to talk and be heard!');
No more antisocial cross-domain web apps!

I spend 12 hours straight in Aptana (an Eclipse-based IDE for web development) some days. Aptana’s great… but it’s pretty vanilla-looking straight out of the box (which gets old).

This evening, a friend taunted me with Coda screenshots, and I decided enough is enough—it’s time to give code highlighting in Aptana a facelift. Well, here it is: a custom color scheme just for Aptana! I call it “Autumna.”

How it looks

HTML, JavaScript, and PHP all at once

CSS

PHP

Download & Install

  1. Download and extract autumna-1.1.zip.
  2. In Aptana, go to: Window > Preferences.
    • In the search box in the upper left of the dialog that comes up, type in “colors”. This’ll hide almost all the fields you’re not interested in.
    • For each language listed under Aptana > Editors, there will be a “Colors” node. When you click on each, you’ll see an “Import…” button that will allow you to install the color scheme for the language.

Follow Me on Twitter

An Epic Meetup

October 12, 2009

Last week was pretty good. Naah, epic actually. One of my great friends Pasquale D’Silva from Australia (now in Vancouver) finally hopped on a plane and came to visit for a week in Cody, WY.

We got to marvel at tumbleweeds (apparently mystical to Aussies), take a giant roadtrip through Yellowstone and into Jackson,wrestle with bears, walk through heaps of snow, fine-tune my Aussie accent, delve into a pitch-black cave, laugh at cowboy hats, bake little creatures in the oven1, pillage McDonald’s like Vikings, geek out, and all sorts of other awesome.

Spelunking

Day 3: Pasquale about to follow Brandon into a shimmy over a decent-sized drop in Spirit Mountain cave. Unfortunately we weren’t able to find “The Descent” creatures down there…

Also, I finally got to witness how the illustrating fiend can draw any creature (real or imaginative) in thirty seconds flat… even on the back of the car.

Dirty bear...

At Old Faithful: A remedy for the hiding bears…

The only disappointment of the trip was not getting to see a real bear—the January-like wintery conditions probably didn’t help. Anyways, it’s sure going to be hard to say “snow” without pronouncing it as “snaaaar” now…

Twas a totally awesome time! Now to make it up to Vancouver sometime!

Video: Some random highlights... Especially random at 00:45!

  1. @PETA: clay creatures []

Reviving Bitalizer

September 30, 2009

For the past couple months, I’ve been assuming that I forever lost one of my favorite data visualization projects when my server exploded.

Bitalizer

What was it?

A nifty, visual way to visualize the 1’s and 0’s that make up digital files. It was a brainchild from a dull lecture on Mesoamerican Culture.

It lives again

Yesterday, about 10 levels deep into my “heap” folder, I found it. For those who’re wondering: my “heap” folder is what I throw everything into when my three monitors get filled with icons. Old “heap” folders get thrown in, too. The folders hold what’d you find behind your bedroom dresser after three years—in a digital sense.

http://thirdroute.com/projects/bitalizer/

It’s Alive

September 29, 2009

Someone has got to have a voodoo doll out there for my blogs.

  • The very first one got killed after I forgot to renew the domain (brianreavis.com) and then GoDaddy, being the awesome company that they are, stole it out from under me.
  • The second blog died after an experimental server setup exploded (basically).
  • This one is here to stay.
When authorizing SSL keys, you typically concatenate it to the authorized_keys file. Like this:
cat publickey.pub >> ~/.ssh/authorized_keys
But this simple method doesn't work when you're trying to load keys automatically .The keys might already exist, and if you keep concatenating the file, authorized_keys will get miles long with duplicates. So, here's a basic bash script to authorize a key if it doesn't already exist in the index:
#!/bin/bash
keypub="/root/github.pub"
keyprivate="/root/github"
while read line; do 
	keydata=$line
done < $keypub
keydata="${keydata#"${keydata%%[![:space:]]*}"}"
keydata="${keydata%"${keydata##*[![:space:]]}"}"
keyfound=`fgrep "${keydata}" ~/.ssh/authorized_keys`
if [[ -n "${keyfound}" ]]; then
	echo "${keydata}"
	echo "SSH key already loaded into ~/.ssh/authorized_keys"
	exit 1
else
	keypubname=`basename $keypub`
	keyprivatename=`basename $keyprivate`
	sudo cp -f "$keyprivate" "/root/.ssh/${keyprivatename}"
	sudo cp -f "$keypub" "/root/.ssh/${keypubname}"
	sudo cat "/root/.ssh/${keypubname}" >> "/root/.ssh/authorized_keys"
	echo "${keydata}"
	echo "Key successfully loaded into ~/.ssh/authorized_keys"
	exit 0
fi
Update these values to point to the public/private keys:
keypub="/root/github.pub"
keyprivate="/root/github"
Bash is beautiful for automation, isn't it?
Older Posts »