Singpolyma

Technical Blog

Archive for the "Tech" Category

Wrapping Text to 80 Columns

Posted on

It’s an age-old practise in computing: limiting text files to a maximum of 80 characters per line (sometimes as little as 72 is suggested). Problems have previously been identified with this practise, but the prevelance of full-sized computer terminals has limited people’s exposure to the problem outside of email quoting.

I have been reading Cory Doctorow‘s short stories and novels on my Google Ion (Android-based phone) for a while now using auduaReader, which is so far the best ebook program I’ve found for the platform. Doctorow distributes his books as text files folded to 80 columns. This has never been a problem on my laptop (where it simply means I do not have to call fold before less), but on my phone it is atrocious. The abuse of newlines in places with no real semantics means the reader is unable to reflow the text in a suitable way for the small screen, and as a result every “line” becomes two and a half lines, like so:

This would have originally been
one long line of text. It will
get folded funny.

You can imagine how atrocious that gets when reading a whole book!

All text viewers and editors can wrap and reflow text themselves these days. Lets promise to use newlines to mean “new line” and not “word wrap”.

EDIT: I have written a perl one-liner that easily reflows wiki-style text where double line-breaks are paragraphs and single line breaks can be ignored. This 80% works on Doctorow files, but munges some sections:

perl -0e '$_=<>; s/(?<!\n)\r?\n(?!\r?\n)/ /g; print'

OpenPGP Keys with Photos

Posted on

So, one of the things I decided to do with the transition to my new PGP key was add a small JPEG photo (my common avatar, which is indeed a photo of me) as a UID. This is something OpenPGP keys have supported for some time, it doesn’t add too much to the keysize (as long as you keep the photo small, which I did), it helps people to identify me, and ties the key more firmly to my IRL identity.

I then discovered a problem: some old keyservers, like pgp.mit.edu, *will not* accept keys with photo UIDs. It’s not that they ignore the photo, it’s that they simply refuse the key!

So, with the help of Daniel Kahn Gillmor, I have discovered the strategy for uploading these keys to the old keyservers using the CLI interface to GnuPG (which is what I normally use for my OpenPGP stuff).

cd /tmp/
mkdir -m 0700 testring
gpg --export KEYID | GNUPGHOME=/tmp/testring gpg --import
GNUPGHOME=/tmp/testring gpg --edit-key KEYID

# Select the photo UID by typing it’s number

deluid
save
GNUPGHOME=/tmp/testring gpg --keyserver pgp.mit.edu --send KEYID
rm -rf /tmp/testring

Free Youtube in any Browser

Posted on

Many people have used and loved, Free Youtube (or FYT), my Greasemonkey script that allows people to use Youtube (and other video sharing sites like Google Video, blip.tv, and others) wthout having a Flash player installed. This is useful for the many people who are on hardware or OSs not supported by Adobe, or those who refuse to install the hideous thing on matters of strong principle.

Now, this freedom cane be taken outside of browsers like Firefox and Epiphany that have userscript functionality. Today, right here in this post, I am releasing a version of FYT as a bookmarklet! (Kudos to Christopher Vollick for having the idea.)

Updated to work better with Safari/Quicktime

Drag 5C.com%5C%2Fv%5C%2F%28%5B%5E%5C%26%5D%2B%29%2F%29%3B%0D%0A%09%09%09var%20vimeoid%20%3D%20data.match%28%2Fvimeo%5C.com%5C%2F%5B%5E%5C%3F%5D%2B%5C%3Fclip_id%3D%28%5B%5E%5C%26%5D%2B%29%2F%29%3B%0D%0A%09%09%09var%20blipid%20%3D%20data.match%28%2Fblip%5C.tv%5C%2Fplay%5C%2F.%2B%24%2F%29%3B%0D%0A%09%09%09var%20wpid%20%3D%20data.match%28%2Fv%5C.wordpress%5C.com%5C%2F%28%5B%5E%5C%2F%5C%26%3F%23%5D%2B%29%2F%29%3B%0D%0A%09%09%09var%20flowplayer%20%3D%20data.match%28%2Fflowplayer%2F%29%3B%0D%0A%09%09%09if%28objects%5Bi%5D.parentNode.nodeName%20%3D%3D%20%22OBJECT%22%29%0D%0A%09%09%09%09var%20o%20%3D%20objects%5Bi%5D.parentNode%3B%0D%0A%09%09%09else%0D%0A%09%09%09%09var%20o%20%3D%20objects%5Bi%5D%3B%0D%0A%09%09%09if%28ytid%20%26%26%20ytid%5B1%5D%29%20%7B%0D%0A%09%09%09%09ytid%20%3D%20ytid%5B1%5D%3B%0D%0A%09%09%09%09linkurl%20%3D%20%27http%3A%2F%2Fyoutube.com%2Fwatch%3Fv%3D%27%20%2B%20ytid%3B%0D%0A%09%09%09%7D%20else%20if%28vimeoid%20%26%26%20vimeoid%5B1%5D%29%20%7B%0D%0A%09%09%09%09vimeoid%20%3D%20vimeoid%5B1%5D%3B%0D%0A%09%09%09%09linkurl%20%3D%20%27http%3A%2F%2Fvimeo.com%2F%27%20%2B%20vimeoid%3B%0D%0A%09%09%09%7D%20else%20if%28blipid%29%20%7B%0D%0A%09%09%09%09GM_xmlhttpRequest%28%7B%0D%0A%09%09%09%09%09method%3A%20%27GET%27%2C%0D%0A%09%09%09%09%09url%3A%20objects%5Bi%5D.src%2C%0D%0A%09%09%09%09%09onload%3A%20function%28responseDetails%29%20%7B%0D%0A%09%09%09%09%09%09GM_xmlhttpRequest%28%7B%0D%0A%09%09%09%09%09%09%09method%3A%20%27GET%27%2C%0D%0A%09%09%09%09%09%09%09url%3A%20unescape%28responseDetails.finalUrl.match%28%2Ffile%3D%28%5B%5E%5C%26%5D%2B%29%5C%26%2F%29%5B1%5D%29%2C%0D%0A%09%09%09%09%09%09%09onload%3A%20function%28responseInner%29%20%7B%0D%0A%09%09%09%09%09%09%09%09linkurl%20%3D%20responseInner.responseText.match%28%2F%3Citem%3E%5B%5E%5Cf%5D%2B%3Clink%3E%28.%2B%29%3C%5C%2Flink%3E%2F%29%5B1%5D%3B%0D%0A%09%09%09%09%09%09%09%09embedLink%28o%2C%20linkurl%29%3B%0D%0A%09%09%09%09%09%09%09%09o.parentNode.removeChild%28o%29%3B%0D%0A%09%09%09%09%09%09%09%7D%0D%0A%09%09%09%09%09%09%7D%29%3B%0D%0A%09%09%09%09%09%7D%0D%0A%09%09%09%09%7D%29%3B%0D%0A%09%09%09%7D%20else%20if%28flowplayer%29%20%7B%0D%0A%09%09%09%09var%20config%20%3D%20eval%28%27%28%27%20%2B%20objects%5Bi%5D.getAttribute%28%27flashvars%27%29.match%28%2F%5Econfig%3D%28%5C%7B.%2B%5C%7D%29%24%2F%29%5B1%5D%20%2B%20%27%29%27%29%3B%0D%0A%09%09%09%09var%20div%20%3D%20document.createElement%28%27div%27%29%3B%0D%0A%09%09%09%09div.innerHTML%20%3D%20videoReplaceHTML%28config.playlist%5B1%5D.url%2C%20%27video%2Fmp4%27%29%3B%0D%0A%09%09%09%09o.parentNode.insertBefore%28div%2C%20o%29%3B%0D%0A%09%09%09%09toremove.push%28o%29%3B%0D%0A%09%09%09%7D%20else%20if%28wpid%29%20%7B%0D%0A%09%09%09%09GM_xmlhttpRequest%28%7B%0D%0A%09%09%09%09%09method%3A%20%27GET%27%2C%0D%0A%09%09%09%09%09url%3A%20%27http%3A%2F%2Fv.wordpress.com%2Fwp-content%2Fplugins%2Fvideo%2Fvideo-xml.php%3Fguid%3D%27%20%2B%20wpid%5B1%5D%2C%0D%0A%09%09%09%09%09onload%3A%20function%28responseDetails%29%20%7B%0D%0A%09%09%09%09%09%09var%20videourl%20%3D%20responseDetails.responseText.match%28%2Fmovie_file%3E%28%5B%5E%3C%5D%2B%29%3C%2F%29%5B1%5D%3B%0D%0A%09%09%09%09%09%09o.innerHTML%20%3D%20videoReplaceHTML%28videourl%29%3B%0D%0A%09%09%09%09%09%7D%0D%0A%09%09%09%09%7D%29%3B%0D%0A%09%09%09%7D%20else%20if%28o.getAttribute%28%27flashvars%27%29%29%20%7B%0D%0A%09%09%09%09var%20videourl%20%3D%20o.getAttribute%28%27flashvars%27%29.match%28%2Ffile%3D%28.%2B%29%2F%29%5B1%5D%3B%0D%0A%09%09%09%09if%28videourl%29%20%7B%0D%0A%09%09%09%09%09var%20div%20%3D%20document.createElement%28%27div%27%29%3B%0D%0A%09%09%09%09%09div.innerHTML%20%3D%20videoReplaceHTML%28videourl%29%3B%0D%0A%09%09%09%09%09o.parentNode.insertBefore%28div%2C%20o%29%3B%0D%0A%09%09%09%09%09toremove.push%28o%29%3B%0D%0A%09%09%09%09%7D%0D%0A%09%09%09%7D%0D%0A%09%09%09if%28linkurl%29%20%7B%0D%0A%09%09%09%09embedLink%28o%2C%20linkurl%29%3B%0D%0A%09%09%09%7D%0D%0A%09%09%7D%0D%0A%7D%0D%0Afunction%20init%28%29%20%7B%0D%0A%09if%28lock%29%20return%3B%0D%0A%09lock%20%3D%20true%3B%0D%0A%09%2F%2A%20YOUTUBE%20%2A%2F%0D%0A%09if%28window.location.href.match%28%2Fyoutube.com%5C%2Fwatch%2F%29%29%20%7B%0D%0A%09%09var%20videourl%20%3D%20%27http%3A%2F%2Fyoutube.com%2Fget_video.php%3F%27%3B%0D%0A%09%09unsafeWindow.swfArgs%5B%27vq%27%5D%20%3D%20%272%27%3B%20%2F%2A%20use%20higher%20quality%20%2A%2F%0D%0A%09%09unsafeWindow.swfArgs%5B%27fmt%27%5D%20%3D%20%28unsafeWindow.isHDAvailable%3F%2722%27%3A%2718%27%29%3B%20%2F%2A%20use%20higher%20quality%20%2A%2F%0D%0A%09%09for%28var%20i%20in%20%5B%27fmt%27%2C%27video_id%27%2C%27vq%27%2C%27t%27%5D%29%20%7B%0D%0A%09%09%09i%20%3D%20%5B%27fmt%27%2C%27video_id%27%2C%27vq%27%2C%27t%27%5D%5Bi%5D%3B%0D%0A%09%09%09videourl%20%2B%3D%20%27%26%27%20%2B%20i%20%2B%20%27%3D%27%20%2B%20unsafeWindow.swfArgs%5Bi%5D%3B%0D%0A%09%09%7D%0D%0A%09%09document.getElementById%28%27watch-player-div%27%29.innerHTML%20%3D%20videoReplaceHTML%28videourl%2C%20%27video%2Fmp4%27%29%3B%0D%0A%09%2F%2A%20GOOGLE%20VIDEO%20%2A%2F%0D%0A%09%7D%20else%20if%20%28window.location.href.match%28%2Fvideo.google.com%5C%2Fvideoplay%2F%29%29%20%7B%0D%0A%09%09var%20videourl%20%3D%20unescape%28document.getElementById%28%27VideoPlayback%27%29.src.match%28%2FvideoUrl%3D%28.%2B%29%24%2F%29%5B1%5D%29%3B%0D%0A%09%09document.getElementById%28%27player%27%29.innerHTML%20%3D%20videoReplaceHTML%28videourl%29%3B%0D%0A%09%2F%2A%20VIMEO%20%2A%2F%0D%0A%09%7D%20else%20if%20%28window.location.href.match%28%2Fvimeo.com%5C%2F%5Cd%2B%5C%2F%3F%24%2F%29%29%20%7B%0D%0A%09%09var%20vimeoid%20%3D%20window.location.href.match%28%2Fvimeo.com%5C%2F%28%5Cd%2B%29%5C%2F%3F%24%2F%29%5B1%5D%3B%0D%0A%09%09GM_xmlhttpRequest%28%7B%0D%0A%09%09%09method%3A%20%27GET%27%2C%0D%0A%09%09%09url%3A%20%27http%3A%2F%2Fwww.vimeo.com%2Fmoogaloop%2Fload%2Fclip%3A%27%20%2B%20vimeoid%2C%0D%0A%09%09%09onload%3A%20function%28responseDetails%29%20%7B%0D%0A%09%09%09%09var%20request_signature%20%3D%20responseDetails.responseText.match%28%2Frequest_signature%3E%28%5B%5E%3C%5D%2B%29%3C%2F%29%5B1%5D%3B%0D%0A%09%09%09%09var%20request_signature_expires%20%3D%20responseDetails.responseText.match%28%2Frequest_signature_expires%3E%28%5B%5E%3C%5D%2B%29%3C%2F%29%5B1%5D%3B%0D%0A%09%09%09%09var%20videourl%20%3D%20%27http%3A%2F%2Fwww.vimeo.com%2Fmoogaloop%2Fplay%2Fclip%3A%27%20%2B%20vimeoid%20%2B%20%27%2F%27%20%2B%20request_signature%20%2B%20%27%2F%27%20%2B%20request_signature_expires%20%2B%20%27%2F%3Fq%3Dsd%27%3B%0D%0A%09%09%09%09document.getElementById%28%27vimeo_player_%27%20%2B%20vimeoid%29.innerHTML%20%3D%20videoReplaceHTML%28videourl%29%3B%0D%0A%09%09%09%7D%0D%0A%09%09%7D%29%3B%0D%0A%09%2F%2A%20BLIP.TV%20%2A%2F%0D%0A%09%7D%20else%20if%28window.location.href.match%28%2Fblip%5C.tv%5C%2Ffile%5C%2F%5Cd%2B%5C%2F%3F%24%2F%29%29%20%7B%0D%0A%09%09var%20videourl%20%3D%20%27%27%3B%0D%0A%09%09for%28var%20i%20in%20unsafeWindow.ATOf%5B%27attributes%27%5D%29%20%7B%0D%0A%09%09%09if%28unsafeWindow.ATOf%5B%27attributes%27%5D%5Bi%5D%5B%27attribute%27%5D.match%28%2F%5C.flv%24%2F%29%29%20%7B%0D%0A%09%09%09%09videourl%20%3D%20unsafeWindow.ATOf%5B%27attributes%27%5D%5Bi%5D%5B%27attribute%27%5D%3B%0D%0A%09%09%09%7D%0D%0A%09%09%7D%0D%0A%09%09document.getElementById%28%27video_player%27%29.innerHTML%20%3D%20videoReplaceHTML%28videourl%29%3B%0D%0A%09%7D%20else%20if%28window.location.href.match%28%2Fviddler%5C.com%5C%2F.%2B%5C%2Fvideos%5C%2F%5Cd%2B%2F%29%29%20%7B%0D%0A%09%09var%20videourl%20%3D%20window.location.href.replace%28%2F%5C%2F%3F%24%2F%2C%27.flv%27%29%0D%0A%09%09document.getElementById%28%27flashcontent%27%29.innerHTML%20%3D%20videoReplaceHTML%28videourl%29%3B%0D%0A%09%2F%2A%20ACADEMICEARTH.COM%20%2A%2F%0D%0A%09%7D%20else%20if%28window.location.href.match%28%2Facademicearth.org%5C%2Flectures%5C%2F.%2A%24%2F%29%29%20%7B%0D%0A%09%09var%20videourl%20%3D%20unsafeWindow.flashVars.flvURL%3B%0D%0A%09%09var%20div%20%3D%20document.createElement%28%27div%27%29%3B%0D%0A%09%09div.innerHTML%20%3D%20videoReplaceHTML%28videourl%29%3B%0D%0A%09%09document.getElementById%28%27video-player%27%29.parentNode.insertBefore%28div%2C%20document.getElementById%28%27video-player%27%29%29%3B%0D%0A%09%09document.getElementById%28%27video-player%27%29.parentNode.removeChild%28document.getElementById%28%27video-player%27%29%29%3B%0D%0A%09%2F%2A%20LASTAMPA.IT%20%2A%2F%0D%0A%09%2F%2A%20Code%20by%20Iron%20Bishop%20%2A%2F%0D%0A%09%7D%20else%20if%20%28window.location.href.match%28%2Flastampa%5C.it%5C%2Fmultimedia%2F%29%29%20%7B%0D%0A%09%09var%20videourl%20%3D%20unescape%28document.getElementById%28%27VideoPlayer1%27%29.innerHTML.match%28%2F.%2Ax-mplayer2.%2Aurl%3D%28.%2B%29wmv%2F%29%5B1%5D%29%20%2B%20%22wmv%22%3B%0D%0A%09%09document.getElementById%28%27VideoPlayer1%27%29.innerHTML%20%3D%20videoReplaceHTML%28videourl%29%3B%0D%0A%09%2F%2A%20EMBED%20CODES%20%2A%2F%0D%0A%09%7D%20else%20%7B%0D%0A%09%09unsafeWindow.addEventListener%28%27DOMNodeInserted%27%2C%20init%2C%20false%29%3B%0D%0A%09%09embed_codes%28document.getElementsByTagName%28%27embed%27%29%29%3B%0D%0A%09%09embed_codes%28document.getElementsByTagName%28%27object%27%29%29%3B%0D%0A%09%09for%28var%20i%20in%20toremove%29%20%7B%0D%0A%09%09%09toremove%5Bi%5D.parentNode.removeChild%28toremove%5Bi%5D%29%3B%0D%0A%09%09%7D%0D%0A%09%09toremove%20%3D%20%5B%5D%3B%0D%0A%09%7D%0D%0A%09lock%20%3D%20false%3B%0D%0A%7D%0D%0Ainit%28%29%3B%0D%0AunsafeWindow.addEventListener%28%27load%27%2C%20init%2C%20false%29%3B%0D%0A})();">FYT to your bookmarks bar, or bookmark it in whatever way your browser prefers.

And, for those of you who’s browsers don’t have a working bookmark system, or one that doesn’t support bookmarklets, just save this string somewhere:

Junt cut-n-paste it to your address bar and hit Enter and FYT will process the current page.

rel=first/last for WordPress

Posted on

In line with my last post I have also created a plugin that adds <link> tags to your <head> section on appropriate pages for rel=first and rel=last, attributes that allow browsers and others to easily discover the first and last page in a set of pages.

The plugin also provides utility functions for getting this information so that you can add human-visible <a> tags, if you prefer.

Visit the plugin page

rel=prev/next for WordPress

Posted on

Christopher Vollick pointed out to me yesterday that my site was not supporting rel=next and rel=prev. For those who don’t know, these rel attributes have been with HTML since HTML3, and they allow you to easily use a bookmarklet or extension or whatever you want to go to the next/previous page in a set of pages (like blogs archives). This is a really great thing, and I was a bit suprised WordPress doesn’t support it by default.

This can partly be implemented with a plugin, but unfortunately to fully implement it I needed to create a 3 line patch to core. I have uploaded the tiny plugin and the patch to a gist so you can download them and install/apply to get these great features on your site!