Photos, stylesheets, and fixups

This commit is contained in:
Neale Pickett 2008-10-27 15:57:45 -06:00
parent 5b75fb6604
commit 237e5c0cd8
104 changed files with 2226 additions and 0 deletions

226
default.css Normal file
View File

@ -0,0 +1,226 @@
/*
* Global
*/
html {
color:#061208;
background:#bfb8a6;
}
body {
background:#e1d8c9;
border: solid black 1px;
font-family: serif;
color: #000;
margin: 1em auto;
padding: 2px;
min-width: 20em;
max-width: 50em;
}
h1, h2, h3, h4, h5, h6 {
font-family: "MgOpen Moderna", sans-serif;
color: #c17f6f;
}
a {
color: #2A70E0;
text-decoration: none;
}
a:visited {
color: #469;
}
a:hover {
color: #bb3;
}
pre {
background: silver;
}
.notice {
background: yellow;
}
.figure {
float: right;
text-align: center;
background-color: #eeeeee;
border: solid gray 2px;
padding: 4px;
margin: 5px 15px;
}
.left {
float: left;
}
/*
* Header elements
*/
h1#head {
background:#5c5f80;
border: 1px solid black;
text-align: left;
padding: 0em 0px 1em 10px;
margin: 0em;
font: normal 2em "URW Gothic L" sans-serif;
letter-spacing: 0.33em;
}
#head a {
color: #ffe;
}
#head img {
float: right;
border: 2px solid black;
margin: 0px 30px 5px 0px;
}
/*
* Navigation menu
*
* IE6 doesn't understand CSS selectors. So we use the > selector to
* specify stuff IE6 shouldn't see. This has the effect of permanently
* hiding the pop-up menus.
*/
#nav {
position: absolute;
top: 4em;
text-align: left;
padding: 0em 1em;
margin: 0px auto;
}
#nav li {
display: inline;
}
#nav li a {
background: #bdcde4;
color: #5c5f80;
padding: 1px 10px;
}
#nav li a:hover {
color: yellow;
}
#nav li ul {
background:#bdcde4;
display: none;
}
#nav > li ul li {
display: list-item;
padding: 0px;
}
#nav > li:hover {
position: relative;
}
#nav > li:hover ul {
color: white;
text-align: left;
display: block;
position: absolute;
top: 1.2em;
left: 0px;
margin: 0px 0px;
padding: 5px 5px;
min-width: 10em;
list-style-type: square;
}
#nav > li ul li {
display: list-item;
margin-left: 1em;
}
#nav ul.this {
color: #555;
}
/*
* Main body
*/
#body {
margin: 10px;
}
address {
background:#5c5f80;
color: #bdcde4;
border: 1px solid black;
margin: 0;
clear: both;
padding: 0.5em;
font-size: 80%;
}
address a {
color: #ffe;
}
/*
* IkiWiki crap
*/
.actions {
font-size: 80%;
margin: 0;
padding: 1px 5px;
text-align: right;
}
.actions ul {
margin: 0;
}
.actions li {
display: inline;
padding: 2px;
margin: 0;
}
.inlinepage {
border: solid black 1px;
margin: 1em 2em;
background: #eee;
padding: 0em 1em;
}
.inlinepage .header a {
font-size: 150%;
}
/* Orange feed button. */
.feedbutton {
background: #f60;
color: white;
border: outset black 1px;
padding: 0px 0.5em 0px 0.5em;
font: bold 8pt sans-serif;
}
.feedbutton:hover {
background: #f90;
}
.pagedate {
color: #666;
font-size: 75%;
}
table.img {
float: right;
background-color: #eef;
border: solid #ccd;
border-width: 1px 1px 0px 1px;
}
table.img caption {
font-size: 80%;
caption-side: bottom;
text-align: center;
background-color: #eef;
border: solid #ccd;
border-width: 0px 1px 1px 1px;
}

63
doc/Bohnendämmerung.mdwn Normal file
View File

@ -0,0 +1,63 @@
Two rules. One Bean. Five Hundred ways to Win.
================================================
The ultimate German game
By [Cheapass Games](http://cheapass.com/)
Rule 1: Do not think about the bean.
Rule 2: Do not bisect the bean.
You can win with the longest road, the shortest road, or the most medium
road; the most balanced herd; the fastest hay wain (fair days only); the
most gregarious senator, the most accurate clock, or the closest ratio
of tadpoles to frogs (inverted) during any rainy period. You can win by
controlling the most of two commodities, but not of three. Victory goes
to the fastest ship (laden), the fastest ship (unladen), or the two
ships (one of each color) with the highest combined speed. You can win
by digging the deepest mine; raising the fluffiest herd; or by finishing
first in last race, last in first race, or first and last in the most
races overall. You can win with the largest rank of followers at the
end of the Insurrection Phase, the friendliest chef, or the least
talkative ghost. If you are the first player to reach the top of the
building with both your blimbers, or if your climbers are the only ones
left on the building, you win. The holder of the "Eternal Darkness"
token at the end of any round (unliss that player is Grandmother) wins.
Control of Nlort, Quimper, and Nice for one month (excluding Cunnery
Phase and not including Midnight Madness); joint monopolies in Space
Gas, Brie, and Garbage; or the tallest pile of pigs are also conditions
of victory. (Pigs in excess of total brake strength are deducted from
tallest pile, obviously.) You can win by creating the table with the
most legs; the most central city; the most non-central city; the planet
with the highest gravity; or by collecting the largest variety of
grains. Swimming is good for you. Each day spent in prison without
escaping: deduct 16 Points. Failure to say "Hail to the King" when a
King is played: Deduct 4 Points. Highest annual fluctuation each round
in relative value of all (controlled) local currencies combined as
measured by the particular net present value equation given in the last
line of the top card of the discard pile, not counting Banking cards
(unless the King is on or within one space of your most populous
territory): score as value. You can win by accumulating the most rice;
taking the most tourists on the same bus; removing the last stone from
the "wheel of eternity" board; retiring more than three vampires during
the Carnival; taking the longest turn; earning the most points; or by
taking the most moves back. The player with the closest pre-game guess
to sum of car numbers in second and third place in all races combined
(without going over) earns 21 points. If a player has paid to "Ride the
Pony" at least once before the Investment Phase of the third banking
day, that player wins once for each card he has collected from each
deck. Woodsman's Festival Bonus: the player with the most unused
Sovereigns (i.e., unspent for at least three turns, track with counters)
earns 5 Points for each merchant at the fair selling soup, wine, goats,
or decorative hats, and a triple bonus if any of these items contain
elements from that player's most recent Market Visit (please do not
combine bonuses for multiple entries in the same section, and ignore
foyers and vestibules when calculating square feet). You can with with
the cleanest monkey, the smallest enzyme, the most absurd victory
conditions, or the most chutzpah. If there is a tie for most
simultaneous victories, the game gose to the player with the longest
hair. If there is a tie for longest hair, the game goes to the player
with the most cards in hand. If there is a tie for most cards in hand,
the game goes to the player with the moistest feet. If there is a tie
for moistest feet, you may wish to score again: you probably missed
something.

17
doc/dingo.mdwn Normal file
View File

@ -0,0 +1,17 @@
[[!meta title="The Dink (merf!)"]]
Aliases: Dingo, (The) Dink, El Pinto Grande, Mr. Merf
Battle cry: merf!
[[!img img_5058.jpg size="500x500"]]
The Dink is (we think) a cross between a Chihuahua and a Norwich Terrier. (A Chihuahua/Norwich Terrier mix, for all you Google searchers out there). He is mellow for a small dog, but can get nervous like a Chihuahua when he goes for rides in the car (we don't drive much and he's not used to it). He doesn't have any problem with the bike trailer, though:
[[!img img_5087.jpg size="500x500"]]
His paperwork at the shelter said he was 4 months old in April, which would mean he was born in December of 2003. But that's awfully close to Christmas, so the person surrendering him may have put down how long they had him, which would mean he was actually born in October, 2003.
When we got him he already knew "sit" and was mostly house-trained. He's very friendly toward people and other dogs. During his only encounter with a cat (so far) he was curious but not overly interested.
[[!img img_5108.jpg size="500x500"]]

BIN
doc/dingo/img_5058.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 KiB

BIN
doc/dingo/img_5087.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

BIN
doc/dingo/img_5108.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 KiB

16
doc/drwiii-invaders.txt Normal file
View File

@ -0,0 +1,16 @@
:< := 8< 8= #< #= ~ |
|
:< := 8< 8= #< ~ |
|
:< := 8< 8= |
<|
:< := 8< 8= #< #= |
* |
:< := 8< 8= #= ~ |
|
:< := 8< |
~ |
:< |
~ |
|
|

BIN
logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

7
papers.mdwn Normal file
View File

@ -0,0 +1,7 @@
[[!meta title="Papers"]]
These are papers I have written. Most of them were written to explain a
concept to someone on woozle. Hopefully other people will find them
useful, too.
[[!map pages="papers/*" show="title"]]

51
papers/DNS.mdwn Normal file
View File

@ -0,0 +1,51 @@
[[!meta title="How DNS Works"]]
When you request a URL like `http://goob.woozle.org/~neale/foo.html`,
the first thing your browser does is send out a DNS query on
"goob.woozle.org". Specifically, it asks for A records or CNAMEs. A
records contain the name->IP mapping, and CNAMEs are like aliases.
CNAMEs are a little out of vogue these days, so I'll focus on A records.
Your browser sends the query to your recursive DNS resolver (the
nameserver in /etc/resolv.conf). The resolver then pulls out the last
part of the hostname (the .org), and looks for the server that can
answer for the .org Top Level Domain (TLD). It does this by asking some
big central nameservers that are listed by IP in its configuration. One
of those big central nameservers will come back and say something like,
".org is served by 1.2.3.4". Then your recursive resolver goes off to
1.2.3.4 and asks it about "woozle.org". 1.2.3.4 will come back with
another IP, in this case 216.39.146.229. Finally, the resolver connects
to 216.39.146.229 and asks it about "goob.woozle.org". 216.39.146.229
will come back with an answer of 216.39.146.229 (since 216.39.146.229 is
what's listed as goob.woozle.org's IP address).
The reason the .org domain said to go to 216.39.146.229 is because
that's what I listed as the primary authoritative name server for the
"woozle.org" domain with my host registrar (pacificroot.com). A lot of
people use networksolutions.com as their host registrar. So on
216.39.146.229, I have an authoritative name server (nsd) that knows
about the woozle.org domain. Some other authoritative name servers are
tinydns and BIND (the Buggy Internet Name Daemon).
Your recursive resolver has now obtained the mapping from
"goob.woozle.org" to 216.39.146.229, so it returns that IP address to
your web browser. If you're running a caching resolver, then the next
time it's asked it won't bother querying the Internet again, it will
just tell you the same thing it told you last time. That can make things
a whole lot faster.
Then your browser makes a TCP connection to 216.39.146.229, on port 80
(the HTTP port). When it connects, it sends something like this:
<pre>
GET /~neale/foo.html
Host: goob.woozle.org
</pre>
That's helpful, because I have a whole lot of hostnames all going to
216.39.146.229. The web server looks at the host header and pulls up
the appropriate page for that domain. My web server, thttpd, has an
easy go of this: it just goes into a directory called "goob.woozle.org".
Apache and other servers take a little more configuration, but in
practice aren't much more difficult to run. This concept of many names
pointing to the same IP address is called "virtual hosting".

299
papers/digimatrix.mdwn Normal file
View File

@ -0,0 +1,299 @@
[[!meta title="Debian on Digimatrix"]]
<p class="notice">
Caution: this is what I was running in 2004. Nowadays we just use
MythTV. Some of this stuff (like the X configuration) still applies,
though, which is why I'm leaving the page up.
</p>
Introduction
------------
We have a Digimatrix hooked up to our high-definition television. We
use it for a number of things:
* Watching DVDs
* Playing music from OGG and MP3 files
* Recording and playing back television shows
* Storing pictures and movies from our digital camera
* Hosting our pictures and movies, along with those of our friends,
on a web server
* Playing Super Nintendo video games
* Occasional desktop tasks
MythTV and Freevo vs. KDE
-------------------------
This sounds like a MythTV box, right? I tried MythTV, and Freevo, and
while I was impressed with how pretty they were, I just couldn't get
them working quite right.
[MythTV](http://www.mythtv.org/) gave a blank screen trying to watch or
record TV, with no useful error messages, and try as I might I just
couldn't figure out what the problem was. After spending three days on
it I gave up.
[Freevo](http://freevo.sourceforge.net/) had its own problems; I don't
remember exactly what they were now. I do remember feeling like Freevo
was held together with bailing wire and chewing gum, while MythTV had a
much more polished and easy-to-use feel to it.
Neither of them worked well out of the box with the Digimatrix remote
control.
In the end, I decided it'd be easier for everybody if we just used KDE.
It lets me bind actions to the key sequences the remote control sends
out, and for most TV-type activities the remote does enough to move
around in [Xine](http://xinehq.de/) and
[Konqueror](http://www.konqueror.org/). The
[x2x](http://x2x.dottedmag.net/) program allows us to use our laptops to
control things over the wireless network, when the remote doesn't
suffice. The Unix `at` utility and a little shell script lets us
schedule TV recordings with more ease than a VCR.
Best of all, there's no meta-information filed away in some obscure
database layout. Everything is a file somewhere and can be manipulated
with Konqueror or the shell.
This turns out to be a very workable setup.
h2. Installing the base system
I had to install the testing (etch) installation CD for it to have a
driver for the SiS 900 10/100 network card. Installation went smoothly
enough. Everything is detected at boot time except:
* LED Panel and front panel buttons (including volume)
* Infrared reciever
* 802.11b card ([Ralink rt2400 chipset](http://rt2x00.serialmonkey.com/)).
While I've gotten the rt2400 drivers to work, the card won't seem to
associate with my WAP until some other device does it first. This is
so inconvenient that I've run a long CAT-5 cable under the house so I
can use the 10/100 ethernet port.
I installed the following additional packages to help me administer the
machine:
<pre>
# aptitude install less zile screen ssh strace sudo ntp ntpdate
</pre>
Web server
--------------
Waldorf needed to run a web server to host photo albums.
<pre>
# aptitude install mathopd stunnel4 php4-cgi rssh
# aptitude install netpbm jhead exiftran libjpeg-mmx-progs libjpeg-progs
</pre>
I won't detail my web server configuration here, since that's unique to me.
X
----
<pre>
# aptitude install x-window-system
</pre>
To my surprise this brought in x.org. I run an HDTV over DVI, so to get
full screen, I had to change the configuration as follows:
<pre>
Section "Device"
Identifier "Generic Video Card"
Driver "sis"
Option "ForceCRT1Type" "DVI-D"
EndSection
Section "Monitor"
Identifier "Generic Monitor"
Option "DPMS"
HorizSync 30-65
VertRefresh 30-60
ModeLine "720p" 74.160 1280 1352 1392 1648 697 725 730 750
EndSection
</pre>
I also had to add "720p" to the `Modes` of the `Display` subsection of
`Screen`.
You may notice I only have 697 pixels vertically. That's because my TV
puts about 23 lines in the "overscan", preventing me from seeing my KDE
toolbar. I haven't yet found a way to recenter the screen, this just
chops off the bottom. As a hack, I put empty KDE toolbars on the top,
left, and right borders. This keeps windows inside the viewable area.
h2. KDE
I like KDE. I've tried MythTV and Freevo and found it's just easier to
run KDE and occasionally use a mouse and keyboard. The only thing we
don't get is a snazzy interface to recording TV shows, but we don't tend
to want to do that very often. I may work on a web interface to XML-TV
listings later on.
<pre>
# aptitude install kde kdm
</pre>
I don't know if this is typical or not, but Debian's KDE went on without
asking me a single question. Kudos to the packagers.
h2. Sound
<pre>
# aptitude install alsa-base alsa-utils
</pre>
We use the Digimatrix's S/PDIF output (isn't it lame that it comes out
the front?). I know from a previous installation that if you just use
the defaults, you need to reboot between playing 2-channel audio and
using Xine's pass-through option to play a 7.1-channel DVD. I'm sure it
has something to do with the sound card resetting something or other.
The solution seems to be having ALSA multiplex audio, and while I don't
get why this works, work it does.
I put the following into `/etc/asound.conf`:
<pre>
pcm.asus-hw {
type hw
card 0
}
pcm.!default {
type plug
slave.pcm "asus"
}
pcm.asus {
type dmix
ipc_key 1234
slave {
pcm "hw:0,0"
period_time 0
period_size 1024
buffer_size 4096
rate 48000
}
}
ctl.asus-hw {
type hw
card 0
}
</pre>
h2. A decent desktop
At this point I was able to browse the web and play music using KDE's
"JuK":http://developer.kde.org/~wheeler/juk.html, so I took a break to
dance around the living room with my 1-year-old daughter as ABBA sang to
us.
h2. Playing DVDs
I like kaffeine, mostly because it's part of KDE and I'm a purist. It
can play all sorts of movies and even has a nice startup screen that
allows you to type in numbers for various actions (play from playlist,
play DVD, etc.).
<pre>
# aptitude install kaffeine
</pre>
### DVD's Content Scrambling System ###
For some reason the DVD guys thought putting an encryption scheme on the
DVD was going to slow down piracy. I don't see any evidence of that
happening, but because of stupid laws in the US, you have to install
illegal software (as in, illegal to own) in order to watch the DVDs
you've bought or rented. To become a criminal, just run the following
commands:
<pre>
# wget http://www.dtek.chalmers.se/groups/dvd/deb/libdvdcss2_1.2.5-1_i386.deb
# dpkg -i libdvdcss2_1.2.5-1_i386.deb
</pre>
The version and/or URL may have changed since I wrote this. Apologies
in advance.
### DVD drive speed ###
Linux does not use DMA on IDE devices when it boots up, you have to turn
that on yourself. I'm not sure what the reason is for this, probably
compatibility with some ancient thing that blows up if you attempt DMA.
In any case, turning on DMA will allows your DVD drive to keep up with
the data on the DVD.
<pre>
# aptitude install hdparm
</pre>
To turn on DMA, I put the following at the end of `/etc/hdparm.conf`.
While I was at it, I turned ot DMA for the hard drive too.
<pre>
/dev/dvd {
dma = on
}
/dev/hda {
dma = on
}
</pre>
### Try a DVD ###
At this point I was able to watch DVDs, so I did. I watched the first
DVD of the first season of Buffy, which turned out to be a terrible idea
since it's pretty dark and not very high quality. I played around with
the gamma settings in the KDE configuration tool, and set my gamma at
1.25. Then I adjusted the brightness, contrast, and saturation of
Kaffeine, and got what I think is a pretty nice-looking configuration.
h2. The remote control
What good is a home theater system if you have to get up off your butt
to press buttons? This is America, man! I want to be able to eat
cheez-doodles and watch porn all night without having my feet hit the
floor, ever.
### The keyboard thingy ###
My Digimatrix came with this IR receiver thingy that goes in between the
keyboard and the keyboard port on the Digimatrix. It synthesizes
keypresses in response to your remote. Pretty slick! This is good
enough for most things, and for a long time I just bound remote
keystrokes to do certain things in KDE applications, and to certain
actions in Xine.
### lirc ###
lirc is the Linux Infra-Red Control system. It provides a standard
interface to various IR recievers and remote controls, and supplies
events to whatever wants to listen to it. KDE has a module to listen to
it, so I figured I'd give it a go.
<pre>
# aptitude install kdelirc
</pre>
Unfortunately, lirc 0.7 (the version in debian testing and unstable)
does not compile on Linux 2.6.12 and newer, so I had to install from
source code.

110
papers/html-tutorial.html Normal file
View File

@ -0,0 +1,110 @@
[[!meta title="The 3-minute HTML tutorial"]]
<p>As computer formats go, HTML is really easy and logical. It's all just
text that you can edit with any basic text editor, like gedit nder
Gnome, or notepad in Windows. Let's start out with an example. Say you
have a sentence, and you want one word in it to be bold. That sentence
would look like this:</p>
<pre>Guess which word is &lt;b&gt;bold&lt;/b&gt;?</pre>
<p>As should be obvious, the bold word in that sentence is "word". Just
kidding, it's the word "bold", in between <code>&lt;b&gt;</code> and <code>&lt;/b&gt;</code> tags.
The sentence will show up like so:</p>
<blockquote>Guess which word is <b>bold</b>?</blockquote>
<p>You now know HTML, the rest is just learning the names of the tags.</p>
<hr />
<p>Seriously! Here's a slightly larger example:</p>
<pre>&lt;title&gt;My first web page&lt;/title&gt;
&lt;h1&gt;Welcome&lt;/h1&gt;
&lt;p&gt;
Welcome to my &lt;b&gt;first ever&lt;/b&gt; web page!
It features:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A title!&lt;/li&gt;
&lt;li&gt;A header!&lt;/li&gt;
&lt;li&gt;A paragraph!&lt;/li&gt;
&lt;li&gt;An unordered list!&lt;/li&gt;
&lt;/ul&gt;
</pre>
<p>So what you end up with in the end is something like this:</p>
<blockquote>
<div style="background: #ddd; border: solid black 3px;">
<div style="background: #00A; color: white; width: 100%;">
My first web page - WoozWeb Browser
</div>
<h1 style="text-align: left;">Welcome</h1>
<p>
Welcome to my <b>first ever</b> web page!
It features:
</p>
<ul>
<li>A title!</li>
<li>A header!</li>
<li>A paragraph!</li>
<li>An unordered list!</li>
</ul>
</div>
</blockquote>
<p>The part inside the <code>&lt;title&gt;</code> and the <code>&lt;/title&gt;</code> is the title of your
page; that's what goes in the window frame at the very top of your web
browser window, above the menus and everything else.</p>
<p>The stuff in between <code>&lt;h1&gt;</code> and <code>&lt;/h1&gt;</code> is a "level-1 header". That
means that it's the biggest header you can get. There are also h2, h3,
h4, h5, and h6 headers, with h6 being the smallest.</p>
<p>The stuff inside <code>&lt;p&gt;</code> and <code>&lt;/p&gt;</code> is a paragraph. Since HTML treats
spaces the same as line breaks, you need to use paragraph tags around
each paragraph. Inside the example paragraph is our old friend bold.</p>
<p>Then, there's <code>&lt;ul&gt;</code> and <code>&lt;/ul&gt;</code>, an "unordered list" (as opposed to an
ordered list, which would have a number by each item). Inside the list
are four "list items", enclosed in <code>&lt;li&gt;</code> and <code>&lt;/li&gt;</code>.</p>
<hr/>
<p>Now check this action out:</p>
<pre>&lt;p&gt;
This is an
&lt;img src="http://www.woozle.org/images/star.png"
alt="star"&gt;&lt;/img&gt; image, and
&lt;a href="http://woozle.org/"&gt;this&lt;/a&gt; is a link.
&lt;/p&gt;
</pre>
<p>Which will show up like this:</p>
<blockquote>
<p>This is an <img src="http://www.woozle.org/images/star.png" alt="star"> image, and <a href="http://woozle.org/">this</a> is a link.
</blockquote>
<p>The example above has an image tag, with two "attributes", "src" and
"alt". The "src" attribute in an <code>&lt;img&gt;</code> tag gives the
URL to a picture, and the "alt" attribute is the text that's displayed
to people who can't see images (blind users, folks without graphics
capabilities, or if there's a problem on your web server). The "alt"
attribue is required, but you can set it to <code>""</code> if there's
nothing appropriate for alternate text.</p>
<p>Lastly, the infamous link, enclosed inside of <code>&lt;a&gt;</code>
and <code>&lt;/a&gt;</code>. The "href" attribute gives the URL that
the browser will go to if you click the link.</p>
<hr/>
<p>That's it for basic HTML, and it should be enough to get you started
writing your own pages. So go write something! The best way to learn
it is to try stuff out and see what it does. For more neat HTML tags,
check out <a href="http://www.cs.tut.fi/~jkorpela/HTML3.2/">HTML 3.2 by
Examples</a>, which is what I used to learn HTML.</p>

View File

@ -0,0 +1,170 @@
[[!meta title="&ldquo;Reply-To&rdquo; Munging Still Considered Harmful. Really."]]
An Earnest Plea to People Still Having This Debate
--------------------------------------------------
A long time ago, Chip Rosenthal wrote a fine document entitled
['Reply-To' Munging Considered
Harmful](http://www.unicom.com/pw/reply-to-harmful.html). It details the
problems caused by `Reply-To` munging. Chip's essay basically points
out that:
* Munging only helps people with broken mail clients.
* Munging can catch people by surprise, since in every other email
they've gotten with multiple recipients, when they hit "reply" it goes
only to the sender.
* Munging totally breaks things for people who want replies to go to a
different address than the one they sent the mail from.
In 2000 (or maybe earlier), Simon Hill wrote a response called [Reply-To
Munging Considered
Useful](http://www.metasystema.net/essays/reply-to.mhtml), which is
frequently offered as a rebuttal to Chip's document in online debates.
Simon's response boils down to the following:
* Munging encourages list discussion.
* RFC 822 seems to indicate it's okay.
* Munging makes things easier on broken mail clients.
People still using these two documents to debate the issue are wasting
everybody's time. The issue was definitively settled in 2001, and Chip
won.
The IETF settles things
-----------------------
The IETF (Internet Engineering Task Force) writes the standards
documents for the Internet. Such a document, called an RFC (Request For
Comments), attempts to unambiguously lay out in English the way things
are supposed to take place. They are deliberated intensely, sometimes
for years, and every paragraph is scrutinized by scores of experts.
Still, problems do crop up with RFCs over time, be they from
ambiguities, new technologies, or flat out mistakes. If problems are
big enough or numerous enough, the IETF will issue a new RFC to correct
the deficiencies of an older one. This new document is said to
_obsolete_ the old one.
Both Chip's and Simon's documents refer to RFC 822, "Standard For The
Format Of ARPA Internet Text Messages", issued way back in 1982, before
most of us even knew what a computer network was. Indeed, RFC 822
doesn't say anything about whether or not mailing lists can or should
set the `Reply-To` header field. Chip interpreted it one way, and Simon
another.
In April of 2001, the IETF issued af new document, [RFC
2822](http://www.ietf.org/rfc/rfc2822.txt), which obsoletes RFC 822. In
this new RFC, the author addresses the `Reply-To` header field in a few
places, but the most relevant to this discussion is the following in
section 3.6.2 "Originator fields":
> When the "Reply-To:" field is present, it indicates the mailbox(es) to
> which the author of the message suggests that replies be sent.
Your list software is not "the author of the message", so it must not
set or in any way meddle with the `Reply-To` header field. That field
exists for the author and the author alone. If your list munges it, you
are violating the standard.
These standards are not written flippantly, they are carefully crafted
in such a way as to ensure everything on the Internet works as smoothly
as possible. So do the Internet a favor and leave `Reply-To` alone.
How to specify where to post list messages
------------------------------------------
[RFC 2369](http://www.ietf.org/rfc/rfc2369.txt) specifies, in section
3.4, the `List-Post` header field:
> The List-Post field describes the method for posting to the list.
> This is typically the address of the list, but MAY be a moderator, or
> potentially some other form of submission. For the special case of a
> list that does not allow posting (e.g., an announcements list), the
> List-Post field may contain the special value "NO".
Modern mail list software sets this header field, or provides some
mechanism for the administrator to set it.
Mail clients are beginning to act on it too. The KMail program Simon
references uses the presence of this header field to make the "reply"
action send to the list and the list only, and provides a "reply to
author" action that will always send to the message's author whether
it's a list or not. "Reply to author" honors the `Reply-To` field.
This is exactly the convenient behavior Simon claims to want in his
essay, and it can all be done using standard behavior.
Getting two copies of the same email
------------------------------------
Some people complain that they'll get two copies of the same email.
Since they're on the list, their first copy is the one sent to them by
the list. When the responder hit "reply all", it also put their email
address in the recipient list, so they get a second copy directly.
Fortunately, there's already a technical solution to this. Since all
mail clients put a unique `Message-ID` header field on their email, a
mail reader has only to compare the `Message-ID` of a message to
previously-recieved messages. If it's the same, then the second message
is a duplicate and can be safely ignored.
If your mail reader doesn't do this, that's too bad, but it's not an
excuse to violate Internet standards and surprise people with
inconsistent behavior, just to prevent you from having to delete a few
emails. Anyone who gets any spam at all knows how to delete email.
It's What People Want
---------------------
I can't tell you how many `Reply-To` munging lists I've been on where
someone (or multiple people) send private messages to the list by
accident. "But I hit reply, not reply to all!" I've even been bitten
by this, right after a message to the list chiding people for sending
private messages to the list!
People want their mail client to be consistent. When they hit "reply"
they want it to go to the person who wrote the message. When they hit
"reply to all", they want it to also go to everyone who received it.
Most people understand this by now, since it's how their mail reader has
worked for every email they've ever gotten. Your list shouldn't be any
different.
Sure, mistakes are going to happen, maybe on your list, maybe with an
email with multiple recipients. It's not your job as a list owner to
make sure people can't make mistakes with their software. If the job
belongs to anybody other the user, it'd be the author of the mail
client. Your job is to make sure your mail list follows Internet
standards, and as a result works consistently for the user.
Summary
-------
Some people want to munge `Reply-To` header fields. They believe it
makes reply-to-list easier, and it encourages more list traffic. It
really does neither, and not only is it a poor idea but it's forbidden
by Internet standards.
The IETF has spoken, and if you violate their standard and munge your
`Reply-To` header fields you're just creating problems for everybody.
-----
References
----------
* ['Reply-To' Munging Considered
Harmful](http://www.unicom.com/pw/reply-to-harmful.html)
* [Reply-To Munging Considered
Useful](http://www.metasystema.net/essays/reply-to.mhtml)
* [RFC 822](http://www.ietf.org/rfc/rfc822.txt): _STANDARD FOR THE FORMAT
OF ARPA INTERNET TEXT MESSAGES_
* [RFC 2822](http://www.ietf.org/rfc/rfc2822.txt): _Internet Message
Format_
* [RFC 2369](http://www.ietf.org/rfc/rfc2369.txt): _The Use of URLs as
Meta-Syntax for Core Mail List Commands and their Transport through
Message Header Fields_

132
papers/sockets.mdwn Normal file
View File

@ -0,0 +1,132 @@
[[!meta title="Introduction To TCP Sockets"]]
Client Sockets
--------------
Sockets are sort of like PBX phone systems, where the IP address is
the phone number, and the port is the extension. Every paired
(connected) socket has a source IP/port and a destination IP/port.
When you want to hook up to a listening server, first you have to
request a socket from the kernel. You use the socket() call. In
Python, that'd be:
<pre>
import socket
s = socket.socket(socket.PF_INET, socket.SOCK_STREAM)
</pre>
That tells Python that you want a socket in the Internet class (as
opposed to, say Appletalk), and that it should be a streaming
socket (TCP, as opposed to a datagram socket, which would be UDP).
The next thing you can do is tell the kernel what IP/port you'd like to
use as the source port (think of this as the number that will show
up on caller ID when you make your connection). You can do this
with the bind() call, like this:
<pre>
s.bind(("192.168.4.216", 9234))
</pre>
This tells the kernel to use the IP/port of 192.168.4.216 and 9234. When
you make an outbound connection, it will come from that IP and that
port. You can use 0 for the IP and 0 for the port, in which case
the kernel picks one for you. Or you can skip the bind call
entirely, which is the same as binding to `('', 0)`.
So you've got a socket and it's bound to something, now all you
have to do is connect it (make your phone call). In Python:
<pre>
s.connect(("192.168.4.12", 80))
</pre>
That'll hook you up to port 80 (the HTTP port) of 192.168.4.12.
From then on you can use s just like it was a file, with read and
write replaced with send and recv (I think you can actually use
read and write on sockets, but traditionally send and recv are used):
<pre>
s.send("GET / HTTP/1.0\n\n")
print s.recv(8192)
</pre>
When you're done, just close it:
<pre>
s.close()
</pre>
Server Sockets
--------------
Since a server operates on a IP/port combination too, you still do the
socket and bind calls (and you can skip the bind if you want any random
port, but I've never heard of a server that doesn't care what port it's
listening to). Then the next thing you have to do for a server, instead
of connecting, is listen. In Python:
<pre>
s.listen()
</pre>
That tells the kernel to start listening for incoming connections
to the IP/Port you got with bind.
Once you get a connection set up in the kernel, you have to ask the
kernel for that connection. That conenction will be a different file
descriptor than the one you had listening, so that you can have multiple
connections plugged in to the same ip/port and keep them all distinct.
The call you make to the kernel is "accept" and by default it will block
(that is, the kernel won't return control to your program) until there's
a new socket established. So you'll see loops like this:
<pre>
while 1:
c = s.accept()
cli_sock, cli_addr = c
cli_sock.send("Hello, person from %s" % cli_addr)
</pre>
So there, you are accepting from s, it puts the new socket in c. Python
does a little trick here, in that it actually returns a tuple (like a
list) with the first value the actual socket, and the second value the
address (ip/port) of the incoming connection. So you don't have to ask
again to find out who just connected to you, get get it with the accept
call. The C library does this in a slightly different way, but you
still get the same information. And at that point, you can start
treating the client socket just like you would any other connected
socket.
Forking for fun and profit
--------------------------
The code above is the serializing (FIFO) model, but you'd need to
fork to handle multiple requests simultaneously. In practice,
hardly anything serializes requests, what's more common is
something like this:
<pre>
while 1:
c = s.accept()
if os.fork():
c.close()
else:
do_client_stuff(c)
c.close()
exit(0)
</pre>
If you're just learning sockets, do a serialized socket first. It'll be
easier to understand what's going on that way. But forks are easy too.
You call fork() and then you get a new process that starts with the same
everything (all the variables are the same and it starts running right
after the fork() call). After the fork, both are running as if the fork
has just completed, but the parent's fork returned the PID of the new
process, and the child's fork returned 0.

7
poems.mdwn Normal file
View File

@ -0,0 +1,7 @@
[[!meta title="Poems"]]
If wishes were horses
And poets were kings
I guess I'd still have my day job.
[[!map pages="poems/*" show="title"]]

25
poems/bagel-girl.mdwn Normal file
View File

@ -0,0 +1,25 @@
[[!meta title="Ode to the Bagel Girl"]]
We stand waiting for the 253 to Redmond
The fog sits lightly on our tongues
Cigarette smoke blending in
I walk to catch a glimpse of the bagel girl
(who works the second shift,
from noon to eight on weekdays).
Oh bagel girl, make me a cappucino.
Brew the espresso dark and heavy
Froth the milk thick and heady.
Tell me you love me, bagel girl.
Ride away with me
Into a cream cheese sunset.
----
I wrote this on the bus home. There was a young girl with a beautiful
face sitting at the front of the bus, and I kept looking at her before I
started to write. I was laughing so hard as I wrote this, that she
started to get pretty self-conscious.

11
poems/double-dactyl.mdwn Normal file
View File

@ -0,0 +1,11 @@
[[!meta title="Double Dactyls"]]
Hoobimus Goobimus,
Emad El-Haraty
“Please call me Fishmael”
said to #tron.
But for the myriad
nicks in the channel list,
characteristically,
they were all gone.

21
poems/ducks.mdwn Normal file
View File

@ -0,0 +1,21 @@
[[!meta title="Ducks"]]
If ducks ran the country, I'm sure you'll agree
Things sure would be different for you and for me!
For starters, we'd live near a pond or a lake
On your birthday, you'd have to eat fish, and not cake.
At lunchtime we'd all go eat grass under trees.
For snacks we'd have quackers, without any cheese.
We'd waddle around from point A to point B,
and when going in groups, we would all form a V.
We wouldn't wear raincoats in winter or fall,
But then, I suppose we'd wear nothing at all.
Every person on earth would be covered with down
And I bet that would make it much harder to drown.
If ducks ran the country, it sure would be strange.
And everything we find familiar would change.
I don't think I'd like it. No, not in the least.
But it still would be better than if it were geese.

8
poems/goldfish.mdwn Normal file
View File

@ -0,0 +1,8 @@
[[!meta title="My Goldfish Wish"]]
I wish a goldfish were my pet!
I'd make sure he was warm and wet.
I'd keep him in the kitchen sink,
And wash him when he starts to stink.

10
poems/lake.mdwn Normal file
View File

@ -0,0 +1,10 @@
[[!meta title="Poem For A Moonlit Lake With City Lights Reflecting"]]
It,
is getting,
dark.
----
Written while leaving dance class at Madrona Park; August 10, 9:07pm

31
poems/mice.mdwn Normal file
View File

@ -0,0 +1,31 @@
[[!meta title="Ode to Mice"]]
Leave them mice alone
Let them wander through your home
Eat little holes into your walls
Let them scamper up and down the halls
Leave them mice alone
Let them grow up on their own
Give them places for mousey beds
Protect their little mousey heads
And sometimes late at night
When you and your boyfriend had a fight
Those little mouseys, they just might
Not give a damn
But when you curl up in bed by yourself
And you're hoping that somebody else
Can feel your anguish, up there on the shelf
They'll be eating SPAM
So leave them mice alone
Leave them lots of styrofoam
And sweaters, and pink insulation stuff
Make sure that they have enough
Leave them mice alone
Don't call the Orkin man on the phone
Those little mouseys
They are your friends

26
poems/optimized.mdwn Normal file
View File

@ -0,0 +1,26 @@
[[!meta title="Optimized"]]
This poem made for Wooz-Web 8
So please download today.
On my computer, it looks great!
On yours, it might turn gray.
It uses ActivePoetry
(By WoozleSoft, v4.3)
And fonts from [here](#), and [here](#), and [here](#);
Without those fonts, it sucks, I fear.
You'll need a 3-D graphics chip
To see the verses do a flip;
A hundred gigabytes of RAM
(unless you want your mouse to jam)
Get MarcoMuddy SlickWave Bash
If you don't want the rhymes to crash
And please be sure to maximize
So that the meter can resize.
I'm sorry if you cannot see
This interactive poetry
But I just cannot take the time
To make my poems sound good on every browser!

44
poems/poopy.mdwn Normal file
View File

@ -0,0 +1,44 @@
[[!meta title="The Poopy Song"]]
![G|:ccGG cc2c|ddAA d3c|BBBB BB2A|GGAB c3G:|](poopy-music.png)
I had a baby Ginnie
She liked to poop a lot
And when it came out of her butt
The temperature was hot
She liked to poop her diapers
The smell was never strong
And when she pooped them really good
Her dad would sing a song
### chorus ###
Poopy Poopy Poopy
Poopy all day long
Poopy Poopy Poopy
This is the Poopy song
(repeat)
This little baby pooper
She liked to bounce and dance
And when you least expected it
Shed up and poop her pants
Shed poopy in the morning
Shed poopy in the night
If she went long between her poops
You knew things werent right
[chorus]
Her poop was many colors
Like yellow, brown, and green
Sometimes she made so much of it
It made you want to scream
She always pooped for pleasure
She never pooped for spite
If poop were good and evil, then
Shed poop for what was right
[chorus]

21
poems/sap.mdwn Normal file
View File

@ -0,0 +1,21 @@
[[!meta title="Sap"]]
I love you dear, so very much
That I get sappy when we touch
Or even when I think of you
Your eyes so red, your hair so blue
I see your face, it warms my heart
It makes my colon leap, then fart
There aren't enough words to express how much I am in love with you
Even breaking meter won't do
The fleshy folds around your teeth
Are red like blood, beyond belief
They make me want to osculate
And doing so is super-great
In short, my love, you fill my gap
With sticky, drippy, sugary sap
I hope you're with me for all time
And that is why I wrote these lines

31
poems/snark.mdwn Normal file
View File

@ -0,0 +1,31 @@
[[!meta title="Snark Hair"]]
Has anyone ever turned into a snark?
In the sun? In the rain? When it's light? When it's dark?
I'm asking because in the past couple days
Snark features have turned up in frightening ways.
On Monday the snark hair began to appear
I felt just a tuft of it under my ear.
On Tuesday, my daugter declared with shagrin
It grew to envelop my cheeks and my chin.
On Wednesday I noted with mounting alarm
that snark hair was starting to grow on my arm.
On Thursday I woke up and got quite distressed:
the thick, furry snark hair had covered my chest!
This morning, I came in to work and found out
my nose was beginning to look like a snout.
My hands looked like snark claws; my feet did as well,
I carried a pungent, distinct snark-like smell.
It looks as though snarkdom may be in the works.
I'm still undecided about all the perks:
My hearing and sniffing's improved, and that's cool,
But everything's suddenly slimed with snark drool.
So if you're aware of a cure for this ill,
be it some kind of tonic, or potion, or pill,
please tell me! Or else when I go to the park,
kids won't call me "Mister", they'll just shout "Hey, Snark!"

6
poems/winders.mdwn Normal file
View File

@ -0,0 +1,6 @@
[[!meta title="Winders"]]
If I should ever find myself
A-washin' dirty winders,
I think that I'd confine myself
To washin' ol' Max Enders'.

19
poems/woozle-irc.mdwn Normal file
View File

@ -0,0 +1,19 @@
[[!meta title="32 lines about 16 lusers"]]
ian is a manager, he also rides a motorbike
hbunny's a boss-man too, and he pumps iron day and night
Meeko is a quasi-furry, lives in Georgia with the fam
Seattle City pays owreee to try and stick it to the man
toast lives on a sailboat with husband, daughters, and some pets
brains take pictures of them all and posts them on the Internets
pinky's in New Jersey, works at linode keeping servers up
crispy's got a dozen kids and writes code for some small start-up
alien's a British guy, his wife is French and they ride bikes
Fub's from Denmark, lives in London, wife and son are Chinese tykes
ameigh is a mommy and she studies speech impediments
nate's a mystery to me, I don't know how he pays his rents
ronin is a Star Wars fan, and coding's something he enjoys
heidi's pinky's wife, she has a business selling bedroom toys
kirk hacks Linux Kernels, and his paycheck comes from Cray Research
nwc's a mystery, he mostly hangs around and lurks
And me, I just sit around writing poems.

3
print.css Normal file
View File

@ -0,0 +1,3 @@
#head, #nav, .actions {
display: none;
}

31
smileys.mdwn Normal file
View File

@ -0,0 +1,31 @@
This page is used to control what smileys are supported by the wiki.
Just write the text of a smiley to display it.
* \\:) [[smileys/smile.png]]
* \\:-) [[smileys/smile.png]]
* \\:D [[smileys/smile-big.png]]
* \\:-D [[smileys/smile-big.png]]
* \\;) [[smileys/wink.png]]
* \\;-) [[smileys/wink.png]]
* \\:\ [[smileys/thinking.png]]
* \\:-\ [[smileys/thinking.png]]
* \\:/ [[smileys/thinking.png]]
* \\:-/ [[smileys/thinking.png]]
* \\:| [[smileys/neutral.png]]
* \\:-| [[smileys/neutral.png]]
* \\:( [[smileys/sad.png]]
* \\:-( [[smileys/sad.png]]
* \\:-? [[smileys/tongue.png]]
* \\:-P [[smileys/tongue.png]]
* \\:o [[smileys/shock.png]]
----
To change the supported smileys, just edit the lists on this page.
Note that the format is important; each list item should start with the
text that is turned into the smiley, escaped so that users can see what
produces it, followed by a [[ikiwiki/WikiLink]] to the image to display.
/!\ Bear in mind that the link to the image needs to be written in a way that
will work if it's copied to other pages on the wiki. So be sure to include the
smileys directory in the path to the file.

31
src.mdwn Normal file
View File

@ -0,0 +1,31 @@
[[!meta title="Software"]]
I write software for a living. I like doing it so much that sometimes I
even write software just for fun. Here are some of the better hacks I've
created over the years.
[Firebot](firebot) is an IRC automaton (bot) that works as an InfoBot,
LinkBot (links multiple channels, even across servers), command bot
(displays the output of programs), web bot (fetches and parses web
pages, returning the results), and more. Everything runs in an
asynchronous select() loop with a very easy-to-use high-level interface.
[Photobob](photobob) is a web-based photo album. There's nothing to
differentiate this from the myriad other web-based photo albums out
there, except that this one doesn't need a database and doesn't write
any meta-information. You just point it at a directory full of
images/movies and it serves 'em up.
[eguile](eguile) is a text preprocessor using guile scheme.
[escm](escm) is the same thing for gauche. You could use these to build
a web site with a common theme. I used to use them, but now I use a
very simple m4 template.
The [Universal Boardgame Kit](ubk/) is a kit you can build for under $5
to use with a number of boardgames. A few boards are included. I
designed the pieces and most of the boards, and hand-coded them all in
PostScript. That makes me feel manly.
I also have some little [Python](python/), [PostScript](ps-hacks), and
[other](misc) hacks, which do clever things.

65
src/eguile.mdwn Normal file
View File

@ -0,0 +1,65 @@
[[!meta title="Eguile : a scheme preprocessor"]]
If you've ever wished your text preprocessor could do symbolic
derivation, eguile is the tool for you!
eguile is a preprocessor which lets you include Scheme code in your
source files--any source files, not just HTML. With the bundled
ntp-style.scm, you can give web pages a consistent interface with easy
navigation bars, just like this page. Further functionality is limited
only by your imagination and programming ability.
eguile looks like PHP, but with Scheme instead of Perl. If you're the
sort of person that would enjoy something like this, you probably don't
need any further description.
## Downloading it
[eguile.scm](scheme/eguile.scm).
## Reference
Easy squeezy:
<dl>
<dt>&lt;?scm scheme-code ?&gt;</dt>
<dd>Evaluates scheme-code, discarding value of the last expression</dd>
<dt>&lt;?scm:d scheme-code ?&gt;</dt>
<dd>Evaluates scheme-code, displaying the value of the last expression</dd>
</dl>
For example:
<?scm (define (square x) (* x x)) ?>
2 squared is <?scm:d (square 2) ?>
renders as:
2 squared is 4
## Inspiration
I modeled eguile after ht2html by Barry Warsaw (a far cooler cat than
I). ht2html is a slick package, but it didn't feel enough like
programming to me and seemed more complicated than it needed to be. escm
seemed like a better solution, but felt a little too kludgy, and I
needed to learn Scheme better anyway. So I stole the layout from ht2html
and the syntax from escm.
## License
eguile is distributed under the GNU Public License version 2.0 or
later. Please refer to the file COPYING for more information.
## Help me help you!
I don't honestly expect anyone to use eguile, so I'm not going to put
much into it beyond this page and what improvements I personally
need. If you do end up using it, please let me know! I'd be more than
happy to help you through any rough spots, and to consider any
suggestions. If nothing else, I can link to your pages as another
example of eguile in use :)

54
src/escm.mdwn Normal file
View File

@ -0,0 +1,54 @@
[[!meta title="escm: a scheme preprocessor"]]
This is my port of [eguile](http://woozle.org/~neale/src/eguile) to
gauche scheme. It uses regular expressions and as a result is faster
and easier to read. It's so tiny, in fact, that I don't feel compelled
to write much about it.
eguile looks like PHP, but with Scheme instead of Perl. If you're the
sort of person that would enjoy something like this, you probably don't
need any further description.
I use eguile along with a couple handy procedures and some makefiles to
generate my entire web space, and a few non-profit web sites I maintain.
I'd be happy to share the site-building stuff with anybody who asks, but
I'm not going to package it up until someone's interested.
Downloading it
--------------
You can download a [tarball of the latest version in git](http://woozle.org/~neale/gitweb.cgi?p=escm;a=snapshot), or check it out yourself:
git clone http://woozle.org/~neale/repos/escm
Reference
---------
Easy squeezy:
<dl>
<dt>&lt;?scm scheme-code ?&gt;</dt>
<dd>Evaluates scheme-code, discarding value of the last expression</dd>
<dt>&lt;?scm:d scheme-code ?&gt;</dt>
<dd>Evaluates scheme-code, displaying the value of the last expression</dd>
</dl>
For example:
<?scm (define (square x) (* x x)) ?>
2 squared is <?scm:d (square 2) ?>
renders as:
2 squared is 4
Related stuff
------------------------
* [escm 1.1](http://practical-scheme.net/vault/escm.html) by Shiro
Kawai, author of gauche, was my inspiration.
* [eguile](http://woozle.org/~neale/src/eguile) is Guile-only

167
src/firebot.mdwn Normal file
View File

@ -0,0 +1,167 @@
[[!meta title="Firebot"]]
FireBot is a winner!
Firebot is an IRC bot combining the functionality of a Linkbot, an
Infobot, and a Clickolinko, which is this cool thing Emad El-Haraty and
I came up with to make short URLs out of stuff posted into the channel,
for people with text browsers that wrap URLs.
Note that, in addition to interacting with FireBot within a channel, you
can also communicate directly with FireBot via `/msg` commands. Just in
case you need a little one-on-one action and don't want spew your
playtime around some channel with other folks watching. That can be *so*
distracting. Some commands still require you to preface them with
FireBot's name. Example:
/msg firebot firebot: literal ...
Downloading
-----------
You can download a [tarball snapshot of the latest release](http://woozle.org/~neale/gitweb.cgi?p=firebot;a=snapshot;h=HEAD), or use cogito:
git clone http://woozle.org/~neale/repos/firebot
LinkBot Features
----------------
Firebot can link channels across networks. It is present in all
channels and the same functions can be accessed on either side.
Everything said on one channel is relayed to the others.
It is possible to link multiple channels on multiple servers, including
multiple channels on a single server.
ClickLinko (UrlBot)
-------------------
Whenever FireBot sees a URL in the channel, he makes a note of it and
creates a shorter URL out of it.
InfoBot
-------
As an InfoBot, FireBot listens in the channel for anything of the form
"x is y", and then stores that little tidbit. Later, when someone asks
a question about x ("what is x?", "who is x?", "wtf is x?"), FireBot
answers with the factoid he gathered.
<dl>
<dt>firebot, _x_</dt>
<dd>look up a factoid for _x_</dd>
<dt>firebot, _x_ is _y_</dt>
<dd>store _y_ as a factiod about _x_</dd>
<dt>firebot, _x_ is also _y_</dt>
<dd>store _y_ as another factoid about _x_</dd>
<dt>firebot, append _x_ &lt;= _y_</dt>
<dd>store _y_ as another factoid about _x_. You'd use this for things where _x_ has the word "is" in it, or other things that you can't store with the preceding commands.</dd>
<dt>no, firebot, _x_ is _y_</dt>
<dd>store _y_ as the only factoid about _x_, even if _x_ already has factoids</dd>
<dt>firebot, literal _x_</dt>
<dd>display all factoids about _x_</dd>
<dt>firebot, lock _x_</dt>
<dd>do not learn any more factoids about _x_</dd>
<dt>firebot, unlock _x_</dt>
<dd>resume learning factoids about _x_</dd>
<dt>firebot, forget _x_</dt>
<dd>forget all factoids about _x_</dd>
<dt>firebot, forget _x_ from _y_</dt>
<dd>forget a single entry (<em>x</em>) that is listed in _y_; _x_ can be a single word, it does not need to be the whole entry</dd>
<dt>firebot, shut up</td>
<dd>make the bot only respond to factoids when addressed specifically</dd>
<dt>firebot, be chatty</td>
<dd>make the bot respond to factoids even when not addressed</dd>
</dl>
In addition, the following tricks can be used within factiods:
* Any factoid beginning with `\\` (a backslash) is displayed directly.
That is, instead of saying "<firebot> x is y", FireBot just says
"<firebot> y".
* Any factoid beginning with <code>:</code> (a colon) is
displayed an action. That is, instead of saying "<firebot> x is y",
FireBot says "* firebot y"
* You may put `%(sender)s` in the factoid to print the name of the
person who asked about the factoid (when sent to a user in a private
message, it's the recipient of the message)
Utilities
---------
<dl>
<dt>firebot, later tell _whom_ _what_</dt>
<dd>The next time _whom_ says something in the channel, deliver the message _what_ publically.</dd>
<dt>firebot, in _time_ say _what_</dt>
<dd>after _time_ (eg. "15 seconds", "2 hours", "5 days"), announce _what_ in the channel</dd>
<dt>seen _whom_</dt>
<dd>Report the last thing said in the channel by _whom_, and how long ago it was said.</dd>
<dt>dict _word_</dt>
<dd>look _word_ up in the dictionary</dd>
<dt>quote _symbol_</dt>
<dd>get a stock quote for _symbol_</dd>
<dt>pollen _zip_</dt>
<dd>report pollen forecast for US zip code _zip_</dd>
<dt>cdecl explain _jibberish_</dt>
<dd>explain the C declaration _jibberish_ (eg. "cdecl explain struct bar *(*foo)[](int)")</dd>
<dt>cdecl declare _english_</dt>
<dd>give the C declaration for _english_ (eg. "cdecl declare foo as pointer to array of function (int) returning pointer to struct bar")</dd>
<dt>how many _x_ in _y_ _z_</dt>
<dd>determine the number of _x_ items that are contained in _y_ amount of _z_ items (eg. how many miles in 1 light year)</dd>
<dt>how much is _amt_ _source_ in _dest_</dt>
<dd>do a currency conversion from _source_ to _dest_. Both must be three-letter currency codes. (eg. "how much is 100 USD in EUR")</dd>
<dt>calc _expr_</dt>
<dd>calculate _expr_ (eg. "calc 2 * 5")</dd>
</dl>
Toys
----
<dl>
<dt>8ball, _question_</dt>
<dd>consult the magic 8-ball regarding _question_</dd>
<dt>_nickname_++</dt>
<dd>add a whuffie point for _nickname_</dd>
<dt>_nickname_--</dt>
<dd>remove a whuffie point for _nickname_</dd>
<dt>whuffie for _nickname_</dt>
<dd>check the whuffie for _nickname_</dd>
</dl>

62
src/ipqueue.mdwn Normal file
View File

@ -0,0 +1,62 @@
[[!meta title="Python ipqueue"]]
This is the Netfilter userspace IPQueue module for Python. It allows you
to do all your Linux IPQueue stuff from the comfort of Python. This only
works with Linux.
Put in simpler terms, this is a way to hook a Python script into your
kernel's networking stack. This could be the fundamental building block
of a firewall. You can use it to snoop on traffic, modify or discard
certain packets, make routing decisions, masquerade stuff, whatever--and
you get it all with garbage collection :)
Download
--------
* [Latest version](ipqueue.tar.gz)
* [Netfilter QUEUE bindings](nfqueue-0.1.tar.bz2) Mike Auty &lt;mike.auty&#64;gmail&#46;com&gt;
</ul>
License
-------
GPL, of course.
Screen Shots
------------
Here's an example program which transparently proxies all traffic it
gets to port 25 of 10.1.1.2. This is just an example, a real-world
transparent proxy would be much more sophisticated.
<pre>
#! /usr/bin/env python
import ipqueue
import iputils
rewrite = 1
q = ipqueue.IPQ(ipqueue.IPQ_COPY_PACKET)
while 1:
p = q.read()
tcp = iputils.TCP(p[ipqueue.PAYLOAD])
print "Got %s -> %s on hook %d" % (iputils.ntoa(tcp.saddr),
iputils.ntoa(tcp.daddr),
p[ipqueue.HOOK])
if rewrite and p[ipqueue.HOOK] == 0:
tcp.daddr = iputils.aton("10.1.1.2")
tcp.th_dport = 25
q.set_verdict(p[0], ipqueue.NF_ACCEPT, tcp.to_str())
else:
q.set_verdict(p[0], ipqueue.NF_ACCEPT)
</pre>
Help me out
-----------
If you're using this in a project, let me know and I'll link to it. If
you find any bugs, or want any features, please let me know about that
too. If you've got a hankering to write better documentation, that would
also be welcome :)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1
src/ipqueue/ipqueue.tar.gz Symbolic link
View File

@ -0,0 +1 @@
ipqueue-1.4.1.tar.gz

Binary file not shown.

59
src/photobob.mdwn Normal file
View File

@ -0,0 +1,59 @@
[[!meta title="Photobob"]]
I don't have a lot to say about photobob. It's the 7th or so photo
album package I've written, and probably the best. You just put
pictures and movies in a directory, and away you go. This works
really well with [an automated digicam photo sucking
thing](/~neale/blog/2006-10-18.The_automatic_camera_suck_script/).
Like all web applications I write, photobob does not use tables for
layout, and will change layout depending on your browser's width. It
uses CSS but still looks passable in non-CSS browsers. There is no
database back-end because it doesn't need one. It's just files in
directories.
Motivation
----------
I want my photo albums to survive longer than the software that serves
them up. My grandparents have shoeboxes full of photos, categorized by
date and event. This is nice because it doesn't require any additional
tools to determine the categorization.
All the web-based photo albums I've run across require some way to store
metadata. In one extreme example (PHP Gallery), all the images are
stored in one flat directory. Should the metadata ever become corrupted
or disappear, or should you decide to switch programs, you're left with
a huge mess and your categorization work is lost.
Photobob uses the file system as its categorization. You put photos in
directories, and attach comments to the photos themselves (using the
JFIF comment field). This makes it easy to press CDs or DVDs of your
photo albums and still preserve the categorization and narration you've
done. Should you decide to quit using Photobob, your photos will still
be tucked away in their directories, with no droppings from the album
software.
Photobob also takes advantage of a special property of JPEG files: size
reductions by powers of two (½, ¼, 1/8, etc.) are a very inexpensive
operation when done at decoding time. Additionally, many digital
cameras write small "thumbnail" images in the JFIF headers. Photobob
takes advantage of both of these properties to serve up scaled images
quickly and without needing to write anything to the hard drive.
Getting it
----------
It's not really packaged up for distribution, but that's only because I
doubt anyone will want it. If you're interested in trying it out on
your site, email me and I'll be glad to help you set it up.
You can check out the [woozle albums](http://woozle.org/albums)
for a live demo.
To get your own copy, run
git clone http://woozle.org/~neale/repos/photobob
Or you can do a [download the latest commit as a tarball](http://woozle.org/~neale/gitweb.cgi?p=photobob;a=snapshot;h=HEAD).

89
src/pysieved.mdwn Normal file
View File

@ -0,0 +1,89 @@
[[!meta title="pysieved: Python Managesieve Server"]]
This is a GPL managesieve server. It uses a plug-in architecture to
support different authentication, homedir lookup, and storage
back-ends.
I wrote this so I could use avelsieve (SquirrelMail) with Postfix
and Dovecot. It should work with other managesieve clients too.
Please share with me your successes and failures.
Plugin architecture
-------------------
The server ships with the following plug-ins:
Authentication:
* Dovecot
* PAM
* SASL
* MySQL
Homedir lookup & session initiation:
* Dovecot
* /etc/passwd
* MySQL
* simple virtual hosting (eg. /var/lib/virtual/username)
Storage:
* Dovecot
Additional back-ends are easy to write, just copy one of the existing
back-ends and start hacking. No modifications are needed to any
existing code, so you don't have to worry about things like the
managesieve protocol or forking.
Download
--------
[Version 1.0](http://woozle.org/~neale/gitweb.cgi?p=pysieved;a=commit;h=1.0)
was released on May 10, 2008 after release candidate 3 had been out for
6 weeks with no bug reports.
You can get the latest version [as
a tarball](http://woozle.org/~neale/gitweb.cgi?p=pysieved;a=snapshot;h=HEAD),
or with git:
git clone http://woozle.org/~neale/repos/pysieved
A [web view of revisions](http://woozle.org/~neale/gitweb.cgi?p=pysieved) is
also available for those without git.
Installation
------------
Put all the files somewhere. I put mine in /usr/local/lib/pysieved.
Copy pysieved.ini into /usr/local/etc/, and edit to taste. It's
commented.
To run from inetd, add the following line to /etc/inetd.conf:
sieve stream tcp nowait root /usr/bin/python python /usr/local/lib/pysieved/pysieved.py --inetd
To run as a daemon, just run
python pysieved.py
Mail list / IRC channel
-----------------------
If you use pysieved, please join the pysieved mail list by emailing
[pysieved-subscribe@woozle.org](mailto:pysieved-subscribe@woozle.org) or
visiting the [subscription page](http://woozle.org/lists/pysieved).
To talk about pysieved on IRC, join us in
[#pysieved on irc.oftc.net](irc://irc.oftc.net/pysieved).
--------
Neale Pickett <neale@woozle.org>

111
src/xss.mdwn Normal file
View File

@ -0,0 +1,111 @@
[[!meta title="xss"]]
[xss](http://woozle.org/~neale/src/xss) is a suite of X screensaver
utilities. You can use shell scripts to glue the tools together to
build your own screen saver and/or locker. You can use any
`xscreensaver` hack instead of the built-in `magic` hack, or you can use
`xlock` if you prefer.
The programs
------------
`xss` uses the decades-old MIT-SCREEN-SAVER extension to launch a
program when the X server turns on the built-in screen saver. Unlike
`xautolock`, `xss` blocks until the X server says it's time to do
something.
`xsswin` makes a full-screen black window and runs some other program,
passing along the window ID in the environment (`$XSS_WINDOW`) and
possibly as an argument (`XSS_WINDOW` in argv is replaced with the ID).
`xkeygrab` grabs the keyboard and mouse, and echoes all typed lines to
stdout.
`xcursorpos` prints out the x and y coordinates of the cursor.
`xbell` sounds the X server's bell.
`magic` is a reimplementation of the "magic" screen saver from After
Dark. It might look weird at 8bpp.
Examples
--------
Tell the X server to launch the screen saver after 90 seconds idle:
$ xset s 90
Run like `xautolock`:
$ xss xlock -mode qix &
Just run a screen saver, don't lock
$ xss -w /usr/lib/xscreensaver/deco -window-id XSS_WINDOW &
Launch a program called "screenlock" when you're idle:
$ xss screenlock &
An simple "screenlock" script:
#! /bin/sh
xsswin magic XSS_WINDOW & pid=$!
xkeygrab | (while read l; do [ "$l" != "secret" ] && break; done)
kill $pid
A more complex "screenlock" script which locks the screen awaiting a
pass phrase with the right md5 checksum. After 4 seconds of being
locked, it pauses mpd (iff it was playing). When the screen is
unlocked, mpd is resumed (iff it was playing beforehand). The script
won't lock if the cursor's at the top of the screen.
#! /bin/sh
xcursorpos | (read x y; [ $y -lt 20 ]) && exit 0
mpc | fgrep -q '[playing]' && playing=1
xsswin magic XSS_WINDOW 2>/dev/null & xsswin=$!
(sleep 4; [ $playing ] && kill -0 $xsswin 2>/dev/null && mpc --no-status pause) &
xkeygrab | (
while read l; do
md5s=$(echo -n $l | md5sum | cut -d\ -f1)
if [ $md5s = 'a37c87558d98e9fe0484e09070268be1' ]; then
break
fi
xbell
done
)
kill $xsswin
[ $playing ] && mpc --no-status play
Download
--------
You can [browse the source](http://woozle.org/~neale/gitweb.cgi?p=xss),
download a [tarball of the latest
commit](http://woozle.org/~neale/gitweb.cgi?p=xss;a=snapshot), or clone the
git repository:
git clone http://woozle.org/~neale/repos/xss/
History
-------
AIX apparently had something also called `xss` which did almost exactly
what mine does, but with command-line options. `magic` is similar to
the `qix` hack from xscreensaver and xlock. I'm not aware of anything
else like the rest of the programs, which is why I wrote them.
I lifted some code from `beforelight` from the X11 distribution, and
from `slock` from [suckless.org](http://suckless.org/). Both have a
BSD/X11-like license.
------
Neale Pickett <neale@woozle.org>

14
toys.mdwn Normal file
View File

@ -0,0 +1,14 @@
[[!meta title="Toys"]]
Some various junk I've done. Maybe you'll find it amusing. Maybe
you'll just wonder why I spend so much time on this garbage.
* This [A Mind Forever Voyaging Decoder](amfv-decoder.cgi) is the sort
of thing where you'll only know what it is if you have a need for it.
* Play [a fun game](fungame)!
* Or you could play [robotfindskitten](robotfindskitten.cgi), which is
also fun!
* If you need to write someone a letter but really don't want to, try my
[smalltalk generator](smalltalk.cgi).
* Maybe you'd rather see a [magic trick](omg-magic)?
* How about some [Internet Reiki](reiki)?

20
toys/crunt.php Normal file
View File

@ -0,0 +1,20 @@
<html>
<head>
<title>crunt</title>
</head>
<body>
<?php
$crunts = rand() % 500;
$baby = $crunts * 0.75;
for ($i = 1; $i < $crunts; $i += 1) {
if (($i < $baby)
&& (rand() % 10 > 7)) {
print "<strong>CRUNT</strong> ";
} else {
print "crunt ";
}
}
print "<strong>CRUNT!</strong>";
?>
</body>
</html>

31
toys/fungame.mdwn Normal file
View File

@ -0,0 +1,31 @@
[[!meta title="Fun Game"]]
<a name="part1"></a>
Let's play a fun game.
You think of a number between 1 and 100, and I'll try to guess
it.
When you've thought of your number, click [here](#part2).
<br style="margin-top: 200%;" />
<a name="part2"></a>
Is your number 7?
* [Yes](#part3)
* [No](#part2)
<br style="margin-top: 200%;" />
<a name="part3"></a>
Yay, I win!
Would you like to play again?
* [Yes](#part1)
* [No](#part1)
<br style="margin-top: 100%;" />

72
toys/omg-magic.html Normal file
View File

@ -0,0 +1,72 @@
[[!meta title="OMG Magic!"]]
<p>
This is a clever magic trick. This paragraph should be filled with
suspenseful leadup to waste your time and get you TOTALLY PUMPED for
this AWESOME MAGIC TRICK that was created by some famous and/or
mystical person and now it's coming <b>directly to you</b> on the
Internets! Can you believe it!
</p>
<p>
Pick a card. Stare at it long enough to memorize what card you've
picked, try to burn it into you mind. Don't worry, take your time,
I'll wait.
</p>
<div style="text-align: center;">
<img alt="card" src="12.png" />
<img alt="card" src="13.png" />
<img alt="card" src="7.png" />
<img alt="card" src="10.png" />
<img alt="card" src="6.png" />
</div>
<p>
When you've memorized your card, you may <a href="#part2">proceed to
the next page</a>.
</p>
<br style="margin-top: 200%;" />
<a name="part2"></a>
<h1>OMG Magic!</h1>
<p>
Do you remember your card? I'm going to yak at you for a little while
to make you spend some time doing something other than focusing on
those cards. This is called <em>redirection</em> and it's a
fundamental part of most magic tricks. The fact that it works even in
a web page says more about humanity than you in particular, so don't
feel bad.
</p>
<p>
Ready to have you mind blown? <a href="#part3">Let's go!</a>
</p>
<br style="margin-top: 200%;" />
<a name="part3"></a>
<h1>OMG Magic!</h1>
<p>
I have removed your card from the hand!
</p>
<div style="text-align: center;">
<img alt="card" src="15.png" />
<img alt="card" src="8.png" />
<img alt="card" src="9.png" />
<img alt="card" src="14.png" />
</div>
<h3>
Did it work?
</h3>
<h2>
OMG Magic!
</h2>
<br style="margin-top: 100%;" />

BIN
toys/omg-magic/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 B

BIN
toys/omg-magic/10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
toys/omg-magic/11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
toys/omg-magic/12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
toys/omg-magic/13.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
toys/omg-magic/14.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
toys/omg-magic/15.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
toys/omg-magic/16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
toys/omg-magic/17.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 B

BIN
toys/omg-magic/18.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 B

BIN
toys/omg-magic/19.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 630 B

BIN
toys/omg-magic/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

BIN
toys/omg-magic/20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

BIN
toys/omg-magic/21.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 B

BIN
toys/omg-magic/22.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 608 B

BIN
toys/omg-magic/23.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

BIN
toys/omg-magic/24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 B

BIN
toys/omg-magic/25.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

BIN
toys/omg-magic/26.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

BIN
toys/omg-magic/27.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

BIN
toys/omg-magic/28.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 B

BIN
toys/omg-magic/29.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

BIN
toys/omg-magic/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

BIN
toys/omg-magic/30.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 B

BIN
toys/omg-magic/31.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

BIN
toys/omg-magic/32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

BIN
toys/omg-magic/33.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 B

BIN
toys/omg-magic/34.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 B

BIN
toys/omg-magic/35.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

BIN
toys/omg-magic/36.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

BIN
toys/omg-magic/37.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

BIN
toys/omg-magic/38.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 B

BIN
toys/omg-magic/39.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

BIN
toys/omg-magic/4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

BIN
toys/omg-magic/40.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

BIN
toys/omg-magic/41.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

BIN
toys/omg-magic/42.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 B

BIN
toys/omg-magic/43.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 B

BIN
toys/omg-magic/44.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 435 B

BIN
toys/omg-magic/45.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 505 B

BIN
toys/omg-magic/46.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

BIN
toys/omg-magic/47.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

BIN
toys/omg-magic/48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 B

BIN
toys/omg-magic/49.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 B

BIN
toys/omg-magic/5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
toys/omg-magic/50.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

BIN
toys/omg-magic/51.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

BIN
toys/omg-magic/52.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

BIN
toys/omg-magic/53.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
toys/omg-magic/54.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
toys/omg-magic/6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Some files were not shown because too many files have changed in this diff Show More