I just set up
SSLTLS on my web site. Everything can be had via https://wingolog.org/, and things appear to work. However the process of transitioning even a simple web site to SSL is so clownshoes bad that it's amazing anyone ever does it. So here's an incomplete list of things that can go wrong when you set up TLS on a web site.
OK so you decide to pay for a certificate, assuming that will be better, and because who knows what's going on with StartSSL. You've heard of RapidSSL so you go to rapidssl.com. WTF their price is 49 dollars for a stupid certificate? Your domain name was only 10 dollars, and domain name resolution is an actual ongoing service, unlike certificate issuance that just happens one time. You can't believe it so you click through to the prices to see, and you get this:
OK so I'm using Epiphany on Debian and I think that uses the system root CA list which is different from what Chrome or Firefox do but Jesus this is shaking my faith in the internet if I can't connect to an SSL certificate provider over SSL.
You remember hearing something on Twitter about cheaper certs, and oh ho ho, it's rapidsslonline.com, not just RapidSSL. WTF. OK. It turns out Geotrust and RapidSSL and Verisign are all owned by Symantec anyway. So you go and you pay. Paying is the first thing you have to do on rapidsslonline, before anything else happens. Welp, cross your fingers and take out your credit card, cause SSLanta Clause is coming to town.
Recall, distantly, that SSL has private keys and public keys. To create an SSL certificate you have to generate a key on your local machine, which is your private key. That key shouldn't leave your control -- that's why the DigitalOcean page is so bogus. The certification authority (CA) then needs to receive your public key and then return it signed. You don't know how to do this, because who does? So you Google and copy and paste command line snippets from a website. Whoops!
Hey neat it didn't delete your home directory, cool. Let's assume that your local machine isn't rooted and that your server isn't rooted and that your hosting provider isn't rooted, because that would invalidate everything. Oh what so the NSA and the five eyes have an ongoing program to root servers? Um, well, water under the bridge I guess. Let's make a key. You google "generate ssl key" and this is the first result.
# openssl genrsa -des3 -out foo.key 1024
Whoops, you just made a 1024-bit key! I don't know if those are even accepted by CAs any more. Happily if you leave off the 1024, it defaults to 2048 bits, which I guess is good.
Also you just made a key with a password on it (that's the -des3 part). This is eminently pointless. In order to use your key, your web server will need the decrypted key, which means it will need the password to the key. Adding a password does nothing for you. If you lost your private key but you did have it password-protected, you're still toast: the available encryption cyphers are meant to be fast, not hard to break. Any serious attacker will crack it directly. And if they have access to your private key in the first place, encrypted or not, you're probably toast already.
OK. So let's say you make your key, and make what's called the "
CRTCSR", to ask for the cert.
# openssl req -new -key foo.key -out foo.csr
Now you're presented with a bunch of pointless-looking questions like your country code and your "organization". Seems pointless, right? Well now I have to live with this confidence-inspiring dialog, because I left off the organization:
Don't mess up, kids! But wait there's more. You send in your CSR, finally figure out how to receive mail for email@example.com because that's what "verification" means (not, god forbid, control of the actual web site), and you get back a certificate. Now the fun starts!
How are you actually going to serve SSL? The truly paranoid use an out-of-process SSL terminator. Seems legit except if you do that you lose any kind of indication about what IP is connecting to your HTTP server. You can use a more HTTP-oriented terminator like bud but then you have to mess with X-Forwarded-For headers and you only get them on the first request of a connection. You could just enable mod_ssl on your Apache, but that code is terrifying, and do you really want to be running Apache anyway?
In my case I ended up switching over to nginx, which has a startlingly underspecified configuration language, but for which the Debian defaults are actually not bad. So you uncomment that part of the configuration, cross your fingers, Google a bit to remind yourself how systemd works, and restart the web server. Haich Tee Tee Pee Ess ahoy! But did you remember to disable the NULL authentication method? How can you test it? What about the NULL encryption method? These are actual things that are configured into OpenSSL, and specified by standards. (What is the use of a secure communications standard that does not provide any guarantee worth speaking of?) So you google, copy and paste some inscrutable incantation into your config, turn them off. Great, now you are a dilettante tweaking your encryption parameters, I hope you feel like a fool because I sure do.
Except things are still broken if you allow RC4! So you better make sure you disable RC4, which incidentally is exactly the opposite of the advice that people were giving out three years ago.
OK, so you took your certificate that you got from the CA and your private key and mashed them into place and it seems the web browser works. Thing is though, the key that signs your certificate is possibly not in the actual root set of signing keys that browsers use to verify the key validity. If you put just your key on the web site without the "intermediate CA", then things probably work but browsers will make an additional request to get the intermediate CA's key, slowing down everything. So you have to concatenate the text files with your key and the one with the intermediate CA's key. They look the same, just a bunch of numbers, but don't get them in the wrong order because apparently the internet says that won't work!
But don't put in too many keys either! In this image we have a cert for jsbin.com with one intermediate CA:
And here is the same but with an a different root that signed the GeoTrust Global CA certificate. Apparently there was a time in which the GeoTrust cert hadn't been added to all of the root sets yet, and it might not hurt to include them all:
Thing is, the first one shows up "green" in Chrome (yay), but the second one shows problems ("outdated security settings" etc etc etc). Why? Because the link from Equifax to Geotrust uses a SHA-1 signature, and apparently that's not a good idea any more. Good times? (Poor Remy last night was doing some basic science on the internet to bring you these results.)
Or is Chrome denying you the green because it was RapidSSL that signed your certificate with SHA-1 and not SHA-256? It won't tell you! So you Google and apply snakeoil and beg your CA to reissue your cert, hopefully they don't charge for that, and eventually all is well. Chrome gives you the green.
Or not! Because if you left on SSLv3 support you're still broken! Also, TLSv1.0, which is actually greater than SSLv3 for no good reason, also has problems; and then TLS1.1 also has problems, so you better stick with just TLSv1.2. Except, except, older Android phones don't support TLSv1.2, and neither does the Googlebot, so you don't get the rankings boost you were going for in the first place. So you upgrade your phone because that's a thing you want to do with your evenings, and send snarky tweets into the ether about scumbag google wanting to promote HTTPS but not supporting the latest TLS version.
So finally, finally, you have a web site that offers HTTPS and HTTP access. You're good right? Except no! (Catching on to the pattern?) Because what happens is that people just type in web addresses to their URL bars like "google.com" and leave off the HTTP, because why type those stupid things. So you arrange for http://www.wobsite.com to redirect https://www.wobsite.com for users that have visited the HTTPS site. Except no! Because any network attacker can simply strip the redirection from the HTTP site.
The "solution" for this is called HTTP Strict Transport Security, or HSTS. Once a visitor visits your HTTPS site, the server sends a response that tells the browser never to fetch HTTP from this site. Except that doesn't work the first time you go to a web site! So if you're Google, you friggin add your name to a static list in the browser. EXCEPT EVEN THEN watch out for the Delorean.
And what if instead they go to wobsite.com instead of the www.wobsite.com that you configured? Well, better enable HSTS for the whole site, but to do anything useful with such a web request you'll need a wildcard certificate to handle the multiple URLs, and those run like 150 bucks a year, for a one-bit change. Or, just get more single-domain certs and tack them onto your cert, using the precision tool cat, but don't do too many, because if you do you will overflow the initial congestion window of the TCP connection and you'll have to wait for an ACK on your certificate before you can actually exchange keys. Don't know what that means? Better look it up and be an expert, or your wobsite's going to be slow!
If your security goals are more modest, as they probably are, then you could get burned the other way: you could enable HSTS, something could go wrong with your site (an expired certificate perhaps), and then people couldn't access your site at all, even if they have no security needs, because HTTP is turned off.
Now you start to add secure features to your web app, safe with the idea you have SSL. But better not forget to mark your cookies as secure, otherwise they could be leaked in the clear, and better not forget that your website might also be served over HTTP. And better check up on when your cert expires, and better have a plan for embedded browsers that don't have useful feedback to the user about certificate status, and what about your CA's audit trail, and better stay on top of the new developments in security! Did you read it? Did you read it? Did you read it?
It's a wonder anything works. Indeed I wonder if anything does.
Greetings, dear readers!
Welcome to my little corner of the internet. This is my place to share and write about things that are important to me. I'm delighted that you stopped by.
Unlike a number of other personal sites on the tubes, I have comments enabled on most of these blog posts. It's gratifying to me to hear when people enjoy an article. I also really appreciate it when people bring new information or links or things I hadn't thought of.
Of course, this isn't like some professional peer-reviewed journal; it's above all a place for me to write about my wanderings and explorations. Most of the things I find on my way have already been found by others, but they are no less new to me. As Goethe said, quoted in the introduction to The Joy of Cooking: "That which thy forbears have bequeathed to thee, earn it anew if thou wouldst possess it."
In that spirit I would enjoin my more knowledgeable correspondents to offer their insights with the joy of earning-anew, and particularly to recognize and banish the spectre of that moldy, soul-killing "well-actually" response that is present on so many other parts of the internet.
I've had a good experience with comments on this site, and I'm a bit lazy, so I take an optimistic approach to moderation. By default, comments are posted immediately. Every so often -- more often after a recent post, less often in between -- I unpublish comments that I don't feel contribute to the piece, or which I don't like for whatever reason. It's somewhat arbitrary, but hey, welcome to my corner of the internet.
This has the disadvantage that some unwanted comments end up published, then they go away. If you notice this happening to someone else's post, it's best to just ignore it, and in particular to not "go meta" and ask in the comments why a previous comment isn't there any more. If it happens to you, I'd ask you to re-read this post and refrain from unwelcome comments in the future. If you think I made an error -- it can happen -- let me know privately.
Finally, and it really shouldn't have to be said, but racism, sexism, homophobia, transphobia, and ableism are not welcome here. If you see such a comment that I should delete and have missed, let me know privately. However even among well-meaning people, and that includes me, there are ways of behaving that reinforce subtle bias. Please do point out such instances in articles or comments, either publicly or privately. Working on ableist language is a particular challenge of mine.
You can contact me via comments (anonymous or not), via email (firstname.lastname@example.org), twitter (@andywingo), or IRC (wingo on freenode). Thanks for reading, and happy hacking :)
Time passes! And it takes us along with it: now a lazy float, now the running rapids, now an eerie calm.
And now, for me, a rising white noise of waterfall. In a month my partner and I move to Geneva. It's exciting and terrifying and anxiety-producing, but the nice thing about time is that I know it will carry me over the stress of, you know, learning French and such things.
I have loved my time in Barcelona, since moving here in 2005. The city has been pretty good to me. While I am indeed ready to go and try new things, I won't be leaving it without regret.
As a practical matter, I'll be (quite happily) staying on with Igalia, in their compilers group. Practically speaking, my move doesn't change much, work-wise; I've always met with customers over the net or on-site, never in Barcelona itself.
There are loads of practicalities to sort out, but if you have any knowledge about the town, I'm all digital ears. Also, if you happen to need some responsible caretakers for your alpine villa, do let me know. It doesn't even have to have a hot tub. I'm not particular. Just sayin'.
This piece is even more navel-gazing than most, so if that's not your bag, surf on, dear surfer, surf on.
Tomorrow ten years ago I wrote:
summertime... and the living is easy.
Ten years! There are few things that I have done consistently for ten years, but typing at this end of the intertube appears to be one of them.
Although there is some juice to squeeze out of the history of this thing, I don't think it's interesting enough. So instead in the rest of this essay I'll just say whatever comes to my mind.
As you might have gathered, I don't like defining myself. I prefer to let what I do give you enough material so that you can conclude what you want. But in the absence of auto-definition, over time I feel that you are defining me.
Let me be concrete. You are mostly technical people, probably computer programmers. You respect what I write to some degree, and that is very gratifying. But let's say I start writing more about politics and social justice. For me it was much easier to write something political five or ten years ago than it is now. Now, I have to think about my readers, and say something that is both well-reasoned and not offensive, because I have the kind of audience for whom technically correct is the best kind of correct.
I don't know what I think about this. Politically I self-identify as an anarchist. (It's both more and less crazy than it sounds.) Politics are more important than what I do in code, but I'm more hesitant to write about such things, because it's not always the case that I can express it adequately. This may be an advantage to us all, but it is stifling as well.
I told you it was going to be navel-gazing ;-)
Here I am, dropping the second-person plural like it's nothing. Au contraire! I do enjoy writing for an audience. Thank you all for reading: those who started with me at Advogato, those more recent subscribers, and those that just click through occasionally.
Thanks especially to people on Planet GNOME for putting up with me over these last few years. The things I do now are only tangentially related to GNOME, but it has been a great help to my writing to know that there were thousands of people reading. If you ever find it too off-topic, file a bug asking the PGO maintainers to restrict the feed to a particular tag or three.
Thanks also to my commenters. I have learned lots from yall. I especially appreciate the pleasant tone that you have. I apologize for not responding to all of the many good points that you make; sometimes the answer is too long, sometimes I have no excuse. In any case, I put my effort into the articles more than the comment threads. At least that way we mostly avoid back-and-forths; there are better media for that.
For the record, although I don't currently moderate comments, I do delete offensive or spammy comments whenever they appear. This has worked well for me.
I've done OK with this electrorag. If you write a blog, and aspire to such modest success, I have only this advice: write about interesting things. Write conversationally, and succinctly if possible. Write socially, addressing a community of readers. That's all!
on macro, on micro
This is just as good a time as any to note that I opened a Twitter account recently. It goes completely against my instincts. My blog is self-hosted. I wrote the software that runs the blog. I wrote the compiler that compiles the software that runs the blog, and the compiler is self-hosted!
I feel I have to justify myself here. In the end it is pretty simple: I need fresh chatter, without having an inbox. I feel like my news sources are an echo chamber, and I need to break out of it somehow. Twitter seems appropriate for grabbing links and zeitgeist. RSS seems too much like an inbox. I'll end up trying to self-host and do the identi.ca dance at some point, but for now, Twitter it is. If following is your game, @andywingo is my name.
I still have no idea what to type at that ridiculous 140-character box. When it comes to blogging, I don't know how to do micro :)
I have no idea what the future holds. Maybe it's a bunch of nerdy compiler articles. Maybe it's cat pictures. We'll see. Thanks for accompanying me this far!
summertime... and the living is easy.
or, from the department of self-inflicted injuries
Recently I saw a bunch of errors in my server logs. People were asking for pages on my web site, but only if they were newer than Thu, 08 Ma 2012 22:44:59 GMT. "Ma"? What kind of a month is that? The internets have so many crazy things.
On further investigation, it seemed this was just a case of garbage in, garbage out; my intertube was busted. I was the one returning a Last-Modified with that date. It was invalid, but client software sent it back with the conditional request.
Thinking more on this, though, and on the well-known last-modified hack in which that field can be used as an unblockable cookie, I think I have to share some blame with the clients again.
So, clients using at least Apple-PubSub/65.28, BottomFeeder/4.1, NetNewsWire, SimplePie, Vienna, and Windows-RSS-Platform/2.0 should ask the people that implement their RSS software to only pass a Last-Modified date if it's really a valid date. Implementors of the NetVibes and worio.com bots should also take a look at their HTTP stacks. I don't guess that there's much that you can do with an etag though, for better or for worse.
Just a brief meta-note: I've added per-tag feeds to tekuti, based on a patch kindly provided by Brian Gough, and unkindly neglected by me these last four months.
Anyway, you can now access http://wingolog.org/feed/atom?with=guile&without=web&with=scheme and other such URLs. Should be good for planets.
Let me know if there are any problems. Thanks!
Hey tubes! Long time no type, in this direction at least.
It seems that most of my writing energy these past few months has been directed towards Guile. For example, right now I should be writing documentation for new hacks, but instead I am typing at another part of the ether.
It's good and bad, this thing. The good thing is the hack-cadence in Guile is high. The bad thing is that not many learn about it, because, well, code doesn't blog about itself, does it?
Except in this case, perhaps. The tin can jiggling the electrons at the other end of this blogline has been my hack, of late. What you are reading is words about Scheme web servers, served by a Scheme web server.
That's right, I ported Tekuti to Guile 2.0. Delicious dogfood, yum!
In the process, I decided that mod-lisp, which I had been using, was stupid. There is already a simple, standard way of serving HTTP requests over a socket, and it is HTTP. So I wrote pieces of a web server, and put them in Guile. I'll probably write more about that later, so no more words about that for now, except to request that folks with spiders, bots, odd rss grabbers and such send me bug reports if things aren't legit.
ciao slicehost, ciao linode
If you're still on slicehost, I heartily recommend that you switch. (Heartily! Strange word. Like gravy and meatballs or something.) Linode feels faster to me, it's half the price, and otherwise the quality is about the same or perhaps a little better. And from what I hear, the linode offerings continue to improve, while slicehost hasn't changed for the 2+ years that I was with them.
Anyway, rap at yall soon, and keep your parentheses warm in this at-times cold Northern winter. Peace!
Images courtesy of the excellent Hyperbole and a Half.
Well, it's been a little while since I wrote about tekuti, my Scheme-powered, git-backed blog software. Time for an update.
I added a global tag cloud, in addition to the abridged cloud on the main page. Clicking on a tag takes you to a time-ordered list of posts having that tag, with a cloud of related tags. The post list could use some improvement, mostly because my titles are nonsensical.
I also implemented full-text search, which uses git grep under the hood. Amusing.
Also amusing is the "related posts" list, which shows up individual post pages. It's calculated as the set of posts which share the most tags with the post in question. The indexes that are automatically rebuilt when the master ref changes makes this a relatively cheap set to compute.
Also also: some artificial intelligence anti spam foo. Ha!
This stuff is actually fun to hack on, and is self-contained -- I'm almost spending more time writing about the features than I did implementing them.
I fleshed out tekuti's web page today, giving reasonably detailed install, deployment, and hacking instructions. It even includes a description on how to migrate from wordpress. I'd appreciate any comments that folks might have, probably better on this post than via email.
Stop the madness: uninstall PHP from your servers. We can do better than that!
In a couple hours I'll go up to the polideportivo and help lay out 500 square meters of mat. It's seminar weekend, kiddos! The incoming instructors are top-notch, Yamada sensei out of New York and Shibata sensei out of Hombu dojo in Tokyo. As a bonus we'll have Peter Bernath, Harvey Konigsberg, and about 50 or so other people coming from abroad. Good times!
And, and, para colmo, tomorrow I test for black belt. Yay!
A lot of people ask what happens once you get your black belt. Its traditional meaning is that you are a serious student, and have an understanding of the basics of a martial art. It does not connote finality in any way; it's more like a milestone, or something like that.
One can see this in the first-degree tests, like mine tomorrow. They're usually fun to watch, but unnecessarily forced, lacking in grace. The difference between first- and second-degree tests is phenomenal, though -- it seems that in the few years after shodan, practitioners gain a sense of confidence and fluidity that they lacked before. That I lack now, I mean. So it's an important rite, for me, but one that points towards the future rather than the past.
The album "Less Talk, More Rock" by Propagandhi is a near-masterpiece. While I do like their other albums, "Less Talk, More Rock" has an infectious youthful brilliance that makes me twitch every time I hear it. I must have listened to Resisting Tyrannical Government 50 times and it is still a transformative experience. Rock on!
Since last week's missive, I've been able to relax a bit, hack-wise, fixing errors as I see them. Most errors have been related to the fact that displaying a blog entry first parses it as valid XML, throwing an exception if the input is invalid. Luckily wordpress is pretty good at ensuring that its text is valid XML, but it's not complete -- it allows bare ampersands, both in the text and in URLs, and sometimes lets angle-brackets pass through unfiltered. So I've had to fix up a few old posts.
Among the more curious things I have had to write for this blagware is a UTF-8 encoder, in order to parse character references like ’ and such, given that Guile only does byte strings, currently.
Shockingly, to me, I do get spam, on the order of about one or two comments per day. No one else uses this software. It seems that there are a couple bots out there that actually parse forms, looking for textareas, then manage to divine which fields require what syntax. Currently my field names are the same as wordpress', so I will vary them until my obscurity provides the necessary "security".
But in the meantime, since my persistent store is Git and not a database, I can easily revert any change, be it changes to posts or to comments or whatever. I fleshed out the admin interface sufficiently so that you can actually create and edit posts there, and gave it an interface for seeing recent changes and possibly reverting them. Of course, reversion is also a change which can be reverted, ad infinitum, so there is no need for scary warnings in the UI when deleting comments, because no change is irreversible. Neat.
A little while ago I got a mail from my good friend Leif, on whose laurels or electrons I have been resting, freeloading wingolog.org on his colocated server. Perhaps this was an acceptable arrangement when I was teaching in Namibia, earning five dollars a day, but now that I earn my keep programming for the man it is a less tenable position.
In any case, the mail went like this: "Wingo, find a new hosting arrangement." Or something to that effect. So I bought a slice and started to migrate my wingolog.org services there.
It is at this point in the story that I experienced a bit of revulsion at the thought of migrating my blog product, powered by Wordpress, to the new server. Wordpress is (1) plagued with security vulnerabilities, and (2) written in PHP, neither of which I was excited to have on my fresh clean slice.
Hence, the bad idea: what if I wrote my own weblog software, so that I wouldn't have to install PHP?
Then, the idea whose worth I have not yet fully evaluated: what if I wrote said weblog software in Scheme?
Then, constraints result in awesomeness: I considered how I could use a database from my usual Scheme implementation, Guile. There are no standard database bindings for Guile, nothing like Perl's DBI or Python's DB-API, and the only binding that I knew of, for PostGres, was bitrotten. (Incidentally the PG binding has been updated within the last couple weeks.) But then I thought, why not use git's object database as a persistent store?
tekuti is born
So in this way I turned a terrible idea into a great one: write weblog software, written in Scheme for fun, and using Git as the persistent storage layer. Three weeks later, if you are reading this, Tekuti has the basics working great.
If you visit my web site, it's probably not very impressive. Some things aren't even implemented yet, for example the tags/ tree, and archives aren't yet exposed to the user. But under the hood there is much new excellence, and quite a bit of old excellence. By way of explaining what I mean, first a bit of background about the architecture.
Tekuti is implemented as a long-running Guile process sitting behind Apache. Tekuti listens on a TCP port, and Apache connects to the port for every request that it receives, sending headers and post data, and receiving headers and body to send to the client. This protocol is implemented by the misnamed mod_lisp, which actually has nothing to do with Lisp, but is just used as a way to use Apache as your frontend while processing requests with some kind of long-running process. FastCGI is similar, but with a more complicated protocol.
Like I mentioned, Git's object database is used as a persistent store. Tekuti is configured to look at a particular directory for a "bare" git repository. The format of the store is rather simple: each post is in a tree. There is a blob for post metadata, and a blob for the raw post content. There is a comment tree under each post tree, and each comment is one blob, somewhat like an rfc 822 mail message.
Clearly, however, this format is not appropriate for all access requirements of weblog software. For example, a request to the main page would involve scanning all of the metadata blobs, parsing post timestamps out of all of them, then taking the latest N timestamps, and showing those posts. This process might work fine if you have 10 posts, but with 200 it is a bit more problematic.
Hence, Tekuti keeps an index of the persistent store. The index is extensible. It currently stores a pre-parsed and time-ordered copy of post metadata, and a mapping between tags and posts for making a tag cloud or for navigating by tag. In that way showing the last N posts is a simple matter of looking at the index, then pulling specific post contents out of the database with git show (and subsequent post-processing).
The names of the post trees are made in such a way that going to 2008/01/19/hackings directly translates into a tree name, so that lookup of individual posts is O(1).
I should mention that the entirety of Tekuti, modulo a couple of local procedures, is written in the functional style. Once allocated, data is never mutated.
Oddly enough, this immutable style of programming promotes the mutability of the program itself. If you run tekuti with the --repl argument, it spawns the main listening and processing loop in a thread, leaving the main thread to run a read-eval-print loop. If you redefine a function in the REPL, it is picked up immediately by the processing thread. My current deployment strategy is to run it within a screen session, so my REPL is always available to me. I just have to SSH into my server, run screen -r, and I can diagnose any problems or change any code that I want to, without restarting the Guile process.
I used similar facilities while developing the software, via Guile's Emacs integration code, known as GDS. If you run Tekuti with --gds, it will spawn a thread to connect to a locally running Emacs. At that point, you can redefine code in the running Tekuti process from within Emacs. It's an incredible reduction in the standard edit-compile-run cycle, effectively removing the "compile" step.
it's all functional programming
Git actively supports the functional programming style: if you have a reference to a tree, that tree will never change out from below you. The only kind of imperative modification that Git supports, besides the interning of new objects into the database, is updating the value of "refs", which conveniently has a compare-and-swap operator, git-update-ref. So not only is git's object database excellent for functional programming, it supports concurrency natively. Indeed, the algorithms that one must use to update a ref are exactly those used in lock-free datastructures. Neat stuff!
So, to summarize: the core of Tekuti is a tail-recursive loop, a là erlang, in which after every iteration we do a goto to the new code of the function. At the beginning of the iteration, we get the value of the "master" ref, and if it's different from the one Tekuti saw last, we do a reindexing operation (on only those parts of the tree that changed). Then we read the data from the mod_lisp socket, dispatch the request, and then -- oh, something I didn't discuss --
All this without harming a single angle-bracket. No <a href="">, no <p>; all of the data is represented as s-expressions (instead of x[ml]-expressions). Hence we have the entire power of the SXML toolkit at hand: pre-post-order, functional tree-fold input parsing, and you never have to think about that stray ampersand in your text, because strings and XML are distinct data types.
the bad, the ugly
Instructions on getting the source code, and importing your old Wordpress blog posts, are available at http://wingolog.org/software/tekuti/. It's two thousand lines of scheme. The user-level side of things is OK, although it lacks pingback support, and the archives and tag browsing stuff isn't quite finished yet.
On the side of the admin, the one who writes the weblog posts, things are, um, spare. I committed this post directly to the git repository. There's some scaffolding for an admin interface which as yet fails to be awesome. In addition, I'm not sure how well things work when you're starting from an empty repository; probably best to import from wordpress first.
You'll want the latest Guile 1.8, ideally with threading support so you can do things like --repl and --gds. Then you'll want the latest guile-lib, preferably from the development repository.
things I learned
So, as I was hacking this thing, I allowed myself the liberty to investigate the meta-level, practices and code that could help me to hack better. I now use paredit-mode when hacking Scheme code in Emacs, which is a revolution. I now miss it when I hack C. I figured out how to link Emacs and a running Guile application via GDS, which is both crazy futuristic and also crazy 20 years old. (It's pretty much like SLIME for you common lispers.) I learned how to use mod_lisp and Guile's sockets, and lots of ickiness surrounding HTTP: status codes, decoding post data, implementing basic authentication (and base64 decoding!), encoding of URLs, Last-Modified and If-Modified-Since, etc.
Guile's built-in exception handing is a bit ad-hoc, so I learned SRFI-34 and SRFI-35 to try to systematize things a bit more. Mixed results. The same conclusion probably applies to learning the intricacies of `format', including its iteration constructs. PCL good book.
I investigated writing this all in R6RS scheme, but the best-looking compiler, ikarus, is not available for my development machine, which runs PPC. Also, R6's support for dynamic programming still isn't there. I'd like to look at it again at some point, perhaps with an eye towards porting; I think that for me, Tekuti will be the litmus test for R6's validity as a programming language. We'll see.
what's with the name
Ote ku ti kutya mOshiwambo, "tekuti" otashi ti "ote ku ti".
Te estoy contando que en oshiwambo, "tekuti" quiere decir "te estoy contando".
I'm telling you that in Oshiwambo, "tekuti" means "I'm telling you".