This post was written in 2009. It's preserved here for historical purposes — the technical details may no longer be accurate.
🔍
2026 retrospective
Most of the stack here is dead: jQuery’s .live() was removed in 1.9, attachment_fu was superseded by Paperclip and then by Rails’ built-in ActiveStorage (Rails 5.2, 2018). The jQuery plugin registry and RubyForge both shut down years ago.
On VisitaCSA we’re using
defunkt’s facebox to
show places images at
large. Facebox is a great general-purpose lightbox, because it is fast, stable,
is based on jQuery and has got a really clean API.
But we needed more than a simple display lightbox, because we wanted our users
to navigate easily between all images, possibly without modifying facebox at
all. The solution turned out to be pretty simple, thanks also to the
will_paginate plugin we were
already using. It all boils down to having:
A Photo model, instrumented with the has_attachment method
Resource routes for photos (map.resources :photos, :only => :show in
config/routes.rb)
A show controller method in the PhotosController that calls .paginate
with a :per_page argument of 1
An HTML view for the photo resource, that has pagination controls using the
will_paginate helper
Some jQuery code hooks onto the pagination links and makes the browser load
via AJAX the next photo directly into the facebox.
Here is the relevant code, simplified from what’s actually online, because the
photo model is actually polymorphic (using STI) and many different collections
are handled by the photos controller (photos, flyers, etc) for different
models, with different thumbnails :P.
classPhotosController<ApplicationControllerlayoutnilbefore_filter:find_place# The photo gallery core is heredefshowphoto=Photo.find(params[:id])page=params[:page]||@place.photos.index(photo)+1@photos=@place.photos.paginate(:per_page=>1,:page=>page)@photo=@photos.firstenddeffind_place@place=Place.find(params[:place_id])endend
vartheLoadSequenceToRunAfterTheDocumentHasBeenLoaded=function(){// The blinking border
//
(function(t){// (C) 2009 vjt <segmentation-fault@core-dumped.info>
var$=function(_){return(document.getElementById(_));};varee=[$('n'),$('s'),$('w'),$('e')],e,_=true;setInterval(function(){for(vari=ee.length;i&&(e=ee[--i]);_){e.className=e.className?'':'b';}},t*08);/* .oOo.oOo.oOo. ^^^^^ -*** * *** *** *******- **/})((4+8+15+16+23+42)*Math.PI/Math.E+42/*166.81*/);// Google analytics
//
try{varpt=_gat._getTracker("UA-1123581-3");pt._trackPageview();}catch($aMarvellousErrorThatWontBeDisplayedOnTheUserBrowserAtAll){}}// end of theLoadSequenceToRunAfterTheDocumentHasBeenLoaded routine
To me, it looks like a contrived melody, or complicated poetry. It’s evil
engineering, I know. But when I was writing it, I felt exactly the same I did
while writing verses with rhymes. _why’s words
are absolutely pertinent here:
until programmers stop acting like obfuscation is morally hazardous, they’re
not artists, just kids who don’t want their food to touch.”.
You can view the code with syntax highlighting on
github, or with the “View source” function
of your browser while you’re on the segfault
site. :)
This post was written in 2009. It's preserved here for historical purposes — the technical details may no longer be accurate.
🔍
2026 retrospective
The opensource.org site has been redesigned several times since 2009, and the Italian mirror at opensource.antifork.org is long gone. The wget-based mirroring approach described here would no longer produce a usable copy of a modern JavaScript-heavy site.
I currently maintain the italian mirror of
the Open Source Initiative web site, and today I
realized that the script I wrote some months ago wasn’t doing its job well..
because the CSS files weren’t downloaded at all, causing a rather unpleasant
rendering of the site.
To mirror opensource org I’m currently using the plain’ol GNU
Wget -r –mirror and so on. While the
good’ol wget downloads each page prerequisite defined in the HTML source,
it doesn’t support @import CSS rules, and doesn’t download images referenced in
CSS with url() rules.
BTW, nothing that can’t be resolved with some regex-fu: that’s why I’m sharing
the script I’m currently using to mirror the
opensource.org web site, hoping it will generate either a new mirror or some
insights on how to do this job better :).
This post was written in 2009. It's preserved here for historical purposes — the technical details may no longer be accurate.
🔍
2026 retrospective
The permalink_fu plugin has been abandoned for over a decade. Rails dropped the entire plugin system in Rails 4 (2013) — the friendly_id gem became the standard replacement for URL slugs.
Another spin-off from the www.visitacsa.it website:
a permalink_fu
improvement that allows dynamic permalinks. I know it is an
oxymoron, because permalinks should be
.. well .. permanent! And because search
engines index them, they should never
change. But what happens when you publish something, your permalink is
generated with permalink_fu using the title of your post, and after a couple
of days you want to change the title, and the permalink under which the post is
accessible as well?
Following the
specification, your
app should send out a 301 moved permanently HTTP status when accessing the
old permalink and redirect the client to the new Uniform Resource Locator.
That’s quite the same thing what my modification to permalink_fu does:
whenever your post attributes are changed, the former and new permalinks are
saved to the database, and you can enable your controller to generate 302
moved temporarily redirects when needed. In other words, it checks whether the
requested URL is an old permalink, and automagically redirects the client to
the new one.
Everything is done behind the scenes, and the plugin has also got nifty rake
tasks to set up the Redirect model and associated migrations. And you can
change its name, of course! :)
This post was written in 2009. It's preserved here for historical purposes — the technical details may no longer be accurate.
🔍
2026 retrospective
This plugin relied on $.browser (removed in jQuery 1.9) and the Prototype-era trick of hiding a file input under the cursor. Modern browsers support the File API, drag-and-drop uploads, and input.click() works everywhere now – no mouse-chasing needed.
I recently wrote jQuery plug-in, that allows
AJAX file uploads without using a fixed file input button. It achieves its
goals by installing an OnMouseMove handler over the selected elements, and
moving the input button under the mouse cursor.
The quote that inspired this code is: “If Muhammad won’t go to the mountain,
the mountain will come to Muhammad”, the opposite of the more known
proverb
:).
// ~ JavaScript Kung-FU, with an excess chunky bacon dose! ~
// This plugin allows seamless ajax file uploads without having
// a fixed file input button. It achieves this by installing an
// OnMouseMove handler over the interested elements, and moving
// the input button under the cursor. <<If Muhammad won't go to
// the the mountain, the mountain will come to Muhammad.>> :-).
//
// This approach is needed on the majority of browsers, except
// Safari, on which the coder is allowed to trigger a "click"
// event onto an input type=file element. On other browsers,
// you can not, that's why the complicated mousemove approach
// was chosen.
//
// Either way, when the value of the input type=file changes,
// handlers are disabled, and a user-provided callback is then
// called (passed via the "upload" option). Handlers are then
// re-enabled again when the upload succeeds or fails.
//
// IE has additional problems, because, quite unexplicably,
// when submitting a form that causes a page load, the change
// event on the file input is triggered AGAIN, thus triggering
// a new file upload. To circumvent this, you can pass a "linked"
// option, that contains the jQuery selector of the form, and
// whenever an input under this form is hovered, ajax upload
// handlers are temporarily cleared and thus the spurious form
// submission.
//
// The jquery Form plugin is a perfect companion of this one,
// because of its .ajaxSubmit method. Have a look at its home
// page: http://malsup.com/jquery/form/.
//
// Have fun!
// - vjt@openssl.it
//
$.fn.ajaxFormUpload=function(options){varpositioning={top:0,left:0,position:'absolute',cursor:'pointer','z-index':2};varform=$(options.form||'#ajax_upload');form.css(positioning)varinput=form.find('input[type=file]');input.css($.extend(positioning,{width:'10px',opacity:0,'font-size':'0px'}));varhovering_element=null;varelements=$(this);varhandler,event_;if($.browser.safari){event_='click',handler=function(){hovering_element=$(this);input.click();};}else{event_='mousemove',handler=function(event){hovering_element=$(this);form.css({left:event.pageX-10,top:event.pageY-5});};}functionenable(){$(elements).bind(event_,handler);}functiondisable(){$(elements).unbind(event_,handler);}input.change(function(){varelement=hovering_element;if(!element)return;disable();options.upload(element,form);enable();});enable();if(options.linked){$(document).ready(function(){$(options.linked).find('input').mouseover(function(){hovering_element=null;});});}};
When you install the developer beta of Windows
7, after the
usual 3 reboots cycle, you are greeted with the following image:
It is the Siamese fighting fish, a
beautiful tropical fish, but with an interesting characteristic: it is
extremely aggressive. It is popular belief that two males fight each other even
in the wild, but that’s not quite true. This belief descends from the behaviour
of the fish in an aquarium, where the victor continuously attacks the
loser, eventually causing the loser’s death.
Now, think about the software ecosystem as an aquarium. And think about
Microsoft in this aquarium. The latest release of Microsoft OS has an
aggressive fish as its default skin, and it is alone in this aquarium. And
there’s no place for anyone else: they’ll fight whatever adversary, even if it’s
from the same species.
What’s uncertain is .. whether they’ll succeed, or not? :). We’ll see!
This post was written in 2008. It's preserved here for historical purposes — the technical details may no longer be accurate.
🔍
2026 retrospective
Apple removed AU Lab from Xcode/developer tools around 2019, and Soundflower was abandoned by Cycling ‘74 (acquired by Ableton). The modern replacement is BlackHole — a virtual audio driver that does the same job.
The right session shows a document open on an aggregate audio device between soundflower (2ch) and a Creative SBLive with 6 channels: the flower receives sound input from iTunes and routes it to the card channels, using all the 6 speakers.
Effects have been added to improve the audio experience (details here: http://www.rottenbrains.com/?p=232). The right session also uses AUNetSend to stream audio onto the left session, connected to the built-in speakers of the macbook.
Result: stereo audio being played on eight channels. Audio Units are a really powerful instrument, well coded and well working.
[tks nextie for telling me about AUNetSend and AUNetReceive]
Improving: there is no need to use NetSend and NetReceive to play on 8 speakers: an aggregate device composed of Soundflower 2ch, the USB 6ch SBlive and the Built-in output is enough!
Also, note the new bus: it’s required because the AUMatrixReverb effect added to the center channel to improve the audio stereophony actually takes two channels, so it overlaps with the following one (the LFE). But applying the effect to a bus does not exhibit this side effect.
This post was written in 2008. It's preserved here for historical purposes — the technical details may no longer be accurate.
🔍
2026 retrospective
This turned out to be terrifyingly accurate. The “slightly altered personality” is now called your “personal brand” and it’s mandatory for professional survival. Cambridge Analytica proved that user data can shape elections. Instagram and TikTok made the “act of being observed changes behavior” effect orders of magnitude worse. ReadWriteWeb itself shut down in 2012 — link now points to the Wayback Machine.
Exactly the words that run around my mind these days:
When we reach the point where online anonymity has ended, instead of getting
to be who we really are, the fact that we’ve become so aware of the fact that
we’re always being recorded, photographed, tracked, and traced, will have
actually created a slightly altered personality instead. Like reality TV show
contestants, the act of being observed will change our behavior. Our personal
brand image will become our public identity and therefore our identity.
I think these words describe exactly the “facebook effect”.
This post was written in 2008. It's preserved here for historical purposes — the technical details may no longer be accurate.
🔍
2026 retrospective
Apple replaced the MIT Kerberos implementation with Heimdal in OS X 10.7 Lion (2011), removing CCacheServer entirely. On modern macOS, System Integrity Protection (SIP, since 10.11 El Capitan) prevents editing anything under /System/Library/ anyway.
If you’re wondering why the CCacheServer daemon, that caches in memory
Kerberos tickets obtained via kinit(1) is NOT starting .. that’s because of a
strange bug regarding the LimitLoadToSessionType specified in the agent
.plist, located into
/System/Library/LaunchAgents/edu.mit.kerberos.CCacheServer.plist on OSX 10.5
systems.
CCacheServer will then be instantiated when you do a kinit:
$ kinit
Please enter the password for vjt@DOMAIN.LOCAL:
$ klist
Kerberos 5 ticket cache: 'API:Initial default ccache'
Default principal: vjt@DOMAIN.LOCAL
Valid Starting Expires Service Principal
11/12/08 20:59:35 11/13/08 06:59:14 krbtgt/DOMAIN.LOCAL@DOMAIN.LOCAL
renew until 11/19/08 20:59:35
The bug is strange because the LimitLoadToSessionType key actually should
instruct launchd to automatically start up the daemon and run it once for
every logged in
user,
when kinit asks its services. But, if the key is set in the .plist, a
launchctl load on it fails with “nothing found to load”. Weird!