I needed to keep my bookmarks in sync between my main computer,
beria (a TiBook running Safari) and my on-the-go one,
loungelizard (a Toshiba Portege R100 running Firebird). The usage pattern is that most of my serious browsing is done on my Mac, but I do ocasionally use the Portege for surfing, mainly to look stuff up. Therefore a two-way sync wasn't necessary, but it would have been nice to have the same set of keywords and the bookmark toolbar on both computers.
If I was going to be launching a web browser, chances were that I at least had web access, therefore doing this sync-ing over HTTP seemed like the best idea. I was already running Apache on
beria, so I decided to write a CGI script that exported my bookmarks. I could then fetch it using the Windows build of
wget and stick it in the right place (
Safari uses XML for its bookmarks file, more specifically the Apple
.plist format. This is somewhat annoying to parse, since it uses
<array/dict/string> pairs to specify values, and so if I'm looking for a value, I need to find its key first, and then get the next tag in the hierarchy. There appeared to be an XSLT that did this conversion, but I couldn't get it to work with the Perl XSLT library that I had found on CPAN. After some messing around with XML::Smart, I went for the lowest level method and parsed it all using XML::DOM.
The net result is this Perl script that exports to HTML. Since I have a lot of bookmarks, I added caching, so that if Safari's bookmarks file hasn't been touched since the last execution, it uses the last generated converted file. Since Safari doesn't have built-in support for keywords, I had previously hacked in that functionality using a method very similar to this article (though done using Perl of course). Therefore my bookmarks exporting script also loads my keywords script, and outputs those keywords to the generated Firebird bookmark file.
Fetching on the Windows side was done by replacing my Firebird shortcut with one that invoked a Perl script (thank you ActiveState) which first pinged
beria, and if that suceeded initiated the
wget command (the pinging had to be done first since
wget had a tendency to zero out the destination file even if the HTTP connection couldn't be established). I would have used a DOS shell script (for better portability), but I couldn't find a way to do the same ping test first. Note that
start and not the Firebird .exe directly since
start seems to return immediately, letting the Perl process exit (simply using
fork instead didn't seem to work, perhaps because I couldn't figure out how to detach the forked process's stdin/out/err).