Welcome to the make+m4 template system
|
@ -0,0 +1,49 @@
|
|||
DESTDIR = /srv/www/woozle.org
|
||||
|
||||
TEMPLATE = template.html.m4
|
||||
MDWNTOHTML = ./mdwntohtml $(TEMPLATE)
|
||||
|
||||
# HTML to be generated
|
||||
HTML =
|
||||
|
||||
# Things to copy
|
||||
COPY =
|
||||
|
||||
# Directories in which %.mdwn generates %.html
|
||||
PLAIN =
|
||||
|
||||
# Other targets for "make all"
|
||||
TARGETS = html copy images
|
||||
|
||||
all: default
|
||||
|
||||
-include *.mk */*.mk
|
||||
|
||||
$(DESTDIR)/%.html: %.mdwn $(TEMPLATE)
|
||||
@mkdir -p $(dir $@)
|
||||
$(MDWNTOHTML) < $< > $@
|
||||
|
||||
$(DESTDIR)/%: %
|
||||
@mkdir -p $(dir $@)
|
||||
cp $< $@
|
||||
|
||||
$(DESTDIR)/%-sm.jpg: %.jpg
|
||||
jpegtopnm $< | pnmscale -xysize 400 400 | pnmtojpeg > $@
|
||||
|
||||
$(DESTDIR)/tmp:
|
||||
mkdir -p $@
|
||||
|
||||
$(DESTDIR)/footer.xml: $(TEMPLATE)
|
||||
awk '(/FOOT/) { a += 1; next; } (a == 1) { print; }' $< > $@
|
||||
|
||||
default: $(TARGETS)
|
||||
|
||||
MDWN = $(wildcard $(addsuffix /*.mdwn, $(PLAIN)))
|
||||
HTML += $(patsubst %.mdwn, %.html, $(MDWN))
|
||||
|
||||
html: $(addprefix $(DESTDIR)/, $(HTML))
|
||||
copy: $(addprefix $(DESTDIR)/, $(COPY))
|
||||
images: $(addprefix $(DESTDIR)/, $(IMAGES))
|
||||
|
||||
clean:
|
||||
rm -rf $(wildcard $(DESTDIR)/*)
|
|
@ -0,0 +1,18 @@
|
|||
Title: Home
|
||||
|
||||
<form class="login"
|
||||
action="https://woozle.org/mail/index.php"
|
||||
method="post">
|
||||
Username
|
||||
<input type="text" name="user" size="15" />
|
||||
Password
|
||||
<input type="password" name="password" size="15" />
|
||||
<input type="submit" value="Read Email" />
|
||||
</form>
|
||||
|
||||
|
||||
Nov 9: Web site changes
|
||||
=======================
|
||||
|
||||
I'm twiddling with the web site. Webmail should be fine but other things may
|
||||
be up and down throughout the day.
|
|
@ -0,0 +1,106 @@
|
|||
#! /usr/bin/python
|
||||
|
||||
import cgitb; cgitb.enable()
|
||||
import cgi
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
import re
|
||||
import smtplib
|
||||
|
||||
f = cgi.FieldStorage()
|
||||
|
||||
l = f.getfirst('l')
|
||||
if not l:
|
||||
l = os.environ.get('PATH_INFO', '/')[1:]
|
||||
|
||||
desc_re = re.compile(r'List-Id: "?([^<]*)"? <')
|
||||
def getdesc(d):
|
||||
fn = '%s/control/customheaders' % d
|
||||
try:
|
||||
hdrs = file(fn).read()
|
||||
except IOError:
|
||||
return '(none)'
|
||||
ret = desc_re.search(hdrs)
|
||||
if ret:
|
||||
return ret.group(1)
|
||||
else:
|
||||
return '(none)'
|
||||
|
||||
listdir = '/var/spool/mlmmj/%s' % l
|
||||
if l and os.path.isdir(os.path.join(listdir, 'control')):
|
||||
title = '%s membership' % l
|
||||
a = f.getfirst('a')
|
||||
addr = f.getfirst('addr')
|
||||
|
||||
if ((a == 'subscribe') or (a == 'unsubscribe')) and addr:
|
||||
server = smtplib.SMTP('localhost')
|
||||
faddr = addr
|
||||
taddr = '%s-%s@woozle.org' % (l, a)
|
||||
try:
|
||||
server.sendmail(faddr,
|
||||
[taddr],
|
||||
'From: %s\nTo: %s\n\n' % (faddr, taddr))
|
||||
content = '<p>I have sent a confirmation message to <tt>%s</tt>. ' % addr
|
||||
content += 'It should be in your mailbox shortly.</p>'
|
||||
except Exception, err:
|
||||
content = "<p>Uh oh. That didn't work.</p>"
|
||||
content += "<pre>%s</pre>" % cgi.escape(str(err))
|
||||
else:
|
||||
desc = getdesc(listdir)
|
||||
content = '<h2>%s@woozle.org' % l
|
||||
if desc:
|
||||
content += ": %s" % cgi.escape(desc)
|
||||
content += '</h2>'
|
||||
content += '<p>To subscribe to or unsubscribe from the %s list,' % l
|
||||
content += ' just enter your email address in this handy dandy form!</p>'
|
||||
content += '<form method="post" action="/lists.cgi">'
|
||||
content += ' <input type="hidden" name="l" value="%s" />' % l
|
||||
content += ' Email address: <input name="addr" />'
|
||||
content += ' <input type="submit" name="a" value="subscribe" />'
|
||||
content += ' <input type="submit" name="a" value="unsubscribe" />'
|
||||
content += '</form>'
|
||||
if os.path.exists(os.path.join(listdir, 'control', 'archive')):
|
||||
content += " <p><a href='http://woozle.org/list-archives/%s/threads.html'>Message archive</a></p>" % l
|
||||
else:
|
||||
title = 'Email lists'
|
||||
|
||||
content = '<h2>Public email lists on this host</h2>'
|
||||
content += '<table>'
|
||||
content += ' <thead>'
|
||||
content += ' <tr>'
|
||||
content += ' <th>list</th>'
|
||||
content += ' <th>description</th>'
|
||||
content += ' <th>actions</th>'
|
||||
content += ' </tr>'
|
||||
content += ' </thead>'
|
||||
content += ' <tbody>'
|
||||
|
||||
for d in glob.glob('/var/spool/mlmmj/*'):
|
||||
if os.path.islink(d):
|
||||
continue
|
||||
if os.path.exists('%s/control/private' % d):
|
||||
continue
|
||||
|
||||
l = os.path.basename(d)
|
||||
content += '<tr><td><a href="/lists/%s">%s</a></td>' % (l, l)
|
||||
content += '<td>%s</td>' % getdesc(d)
|
||||
content += '<td><form action="lists">'
|
||||
content += ' <input name="addr" />'
|
||||
content += ' <input type="hidden" name="l" value="%s" /><br />' % l
|
||||
content += ' <input type="submit" name="a" value="subscribe" />'
|
||||
content += ' <input type="submit" name="a" value="unsubscribe" />'
|
||||
content += '</form>'
|
||||
if os.path.exists('%s/control/archive' % d):
|
||||
content += '<a href="http://woozle.org/list-archives/%s/threads.html">view archive</a>' % l
|
||||
content += '</td></tr>\n'
|
||||
|
||||
content += ' </tbody>'
|
||||
content += '</table>'
|
||||
|
||||
print 'Content-type: text/html'
|
||||
print
|
||||
sys.stdout.flush()
|
||||
p = os.popen('m4 -DTITLE="%s" template.html.m4 -' % title, 'w')
|
||||
p.write(content)
|
||||
p.close()
|
|
@ -0,0 +1,15 @@
|
|||
#! /bin/sh -e
|
||||
|
||||
while IFS=: read field value; do
|
||||
case "$field" in
|
||||
"")
|
||||
break
|
||||
;;
|
||||
Title)
|
||||
# echo strips leading and trailing whitespace
|
||||
title=$(echo $value)
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
m4 -Dimage='<a href="$1.jpg"><img src="$1-sm.jpg"></a>' | markdown | m4 -DTITLE="$title" $1 -
|
|
@ -0,0 +1,11 @@
|
|||
#! /bin/sh
|
||||
|
||||
echo 'Title: People'
|
||||
echo
|
||||
|
||||
ls /home/*/public_html/index.html | while read fn; do
|
||||
a=${fn#/home/}
|
||||
u=${a%/public_html/index.html}
|
||||
|
||||
echo "* [$u](/~$u)"
|
||||
done
|
|
@ -0,0 +1,83 @@
|
|||
html {
|
||||
font-family: sans-serif;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
body {
|
||||
max-width: 700px;
|
||||
margin: auto;
|
||||
color: #636;
|
||||
background: #fff;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
body h1:first-child {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
color: #ccc;
|
||||
margin: 0;
|
||||
}
|
||||
body h1:first-child:before {
|
||||
font-size: 300%;
|
||||
font-weight: normal;
|
||||
content: "Woozle";
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
nav {
|
||||
font-size: 80%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
nav ul {
|
||||
background-color: #eee;
|
||||
margin: 0;
|
||||
padding: 0 1em;
|
||||
}
|
||||
nav li {
|
||||
font-weight: bold;
|
||||
display: inline;
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #e8b;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 150%;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
|
||||
.login {
|
||||
margin: 0 1em;
|
||||
color: #e8b;
|
||||
background: #fbfbfb;
|
||||
border: 1px solid #eee;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.login input {
|
||||
border: 1px solid #ddd;
|
||||
color: #bbb;
|
||||
background: #fff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
img
|
||||
{
|
||||
border: 1px #e8b solid;
|
||||
}
|
||||
img.left {
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: #eee;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>TITLE</title>
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="stylesheet" href="/style.css" type="text/css" />
|
||||
<link rel="icon" type="image/png" href="/icon.png" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>TITLE</h1>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="/">Home</a></li>
|
||||
<li><a href="/lists">Email lists</a></li>
|
||||
<li><a href="/wishlists">Wish lists</a></li>
|
||||
<li><a href="/people">People</a><li>
|
||||
</ul>
|
||||
</nav>
|
||||
define(image, <a href="$1.jpg"><img src="$1-sm.jpg"></a>)
|
||||
divert(1)
|
||||
</body>
|
||||
</html>
|
||||
divert(0)
|
|
@ -0,0 +1,52 @@
|
|||
#! /usr/bin/python
|
||||
|
||||
import cgitb; cgitb.enable()
|
||||
import cgi
|
||||
import glob
|
||||
import os
|
||||
import sys
|
||||
import markdown
|
||||
|
||||
BASE = '/var/lib/wishlists'
|
||||
|
||||
f = cgi.FieldStorage()
|
||||
|
||||
title = 'Wishlists'
|
||||
content = []
|
||||
|
||||
u = f.getfirst('u')
|
||||
p = f.getfirst('p')
|
||||
|
||||
if u:
|
||||
if p:
|
||||
if p.lower() not in ('dingo', 'jada'):
|
||||
content.append("<p>I'm sorry but that is not the right answer.</p>")
|
||||
else:
|
||||
txt = f.getfirst('txt')
|
||||
open(os.path.join(BASE, u), 'w').write(txt)
|
||||
content.append('<p>Okay, thanks!</p>')
|
||||
content.append('<p><a href="wishlist.cgi">Back to wishlists</a></p>')
|
||||
else:
|
||||
title = "%s's Wishlist" % cgi.escape(u)
|
||||
txt = open(os.path.join(BASE, u)).read()
|
||||
content.append('<form action="wishlist.cgi" method="post">')
|
||||
content.append('<input type="hidden" name="u" value="%s">' % u)
|
||||
content.append('<textarea name="txt" rows="15" cols="60">%s</textarea>' % cgi.escape(txt))
|
||||
content.append('<br>')
|
||||
content.append('What is the name of Amy and Neale\'s dog?')
|
||||
content.append('<input name="p">')
|
||||
content.append('<input type="submit" value="update">')
|
||||
content.append('</form>')
|
||||
else:
|
||||
for fn in sorted(glob.glob(os.path.join(BASE, '*'))):
|
||||
u = os.path.basename(fn)
|
||||
content.append("<h1>%s</h1>" % cgi.escape(u))
|
||||
content.append(markdown.markdown(open(fn).read()))
|
||||
content.append('<p><a href="wishlist.cgi?u=%s">edit</a></p>' % u)
|
||||
|
||||
print 'Content-type: text/html'
|
||||
print
|
||||
sys.stdout.flush()
|
||||
p = os.popen('m4 -DTITLE="%s" template.html.m4 -' % title, 'w')
|
||||
p.write('\n'.join(content))
|
||||
p.close()
|
|
@ -0,0 +1,6 @@
|
|||
PLAIN += .
|
||||
COPY += icon.png style.css lists.cgi wishlist.cgi $(TEMPLATE)
|
||||
HTML += people.html
|
||||
|
||||
$(DESTDIR)/people.html: people.sh
|
||||
sh $< | $(MDWNTOHTML) > $@
|
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 1.3 MiB |
After Width: | Height: | Size: 1.3 MiB |
After Width: | Height: | Size: 368 KiB |
After Width: | Height: | Size: 254 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 256 KiB |
After Width: | Height: | Size: 341 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 8.4 KiB |
After Width: | Height: | Size: 2.0 MiB |
After Width: | Height: | Size: 497 KiB |
After Width: | Height: | Size: 1.8 MiB |
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 1.0 MiB |
After Width: | Height: | Size: 2.2 MiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 1.4 MiB |
After Width: | Height: | Size: 861 KiB |
After Width: | Height: | Size: 772 KiB |
After Width: | Height: | Size: 1.6 MiB |
After Width: | Height: | Size: 1.7 MiB |
After Width: | Height: | Size: 1.8 MiB |
After Width: | Height: | Size: 893 KiB |
After Width: | Height: | Size: 2.2 MiB |
After Width: | Height: | Size: 1.8 MiB |
After Width: | Height: | Size: 774 KiB |
After Width: | Height: | Size: 1.3 MiB |
After Width: | Height: | Size: 1.3 MiB |
After Width: | Height: | Size: 1.0 MiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 1.0 MiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 889 KiB |
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 1.2 MiB |
|
@ -0,0 +1,131 @@
|
|||
Title: 2009 Christmas Letter
|
||||
|
||||
image(img_4403))
|
||||
|
||||
We had lots of help decorating the Christmas tree this year, when we took these photos. From left to right: Dingo, Samantha, Neale, Claire, Fitri, Jada, Ginnie, and Amy. For those confused about the sudden explosion in family members: we got to share our Thanksgiving with Samantha and Claire, Amy's cousins; and Fitri is our exchange student from Indonesia.
|
||||
|
||||
Here are some photo highlights from 2009!
|
||||
|
||||
image(img_3543)
|
||||
|
||||
We did a lot of home projects this year, starting with the installation of a new woodstove and roof, and also rebuilt our deck. Neale built the hearth for the woodstove, and for a little while Ginnie got to play on it:
|
||||
|
||||
image(img_3550)
|
||||
|
||||
image(img_4178)
|
||||
|
||||
Kellie and Bill Robinson-Smith came to visit for the February birthdays, and we took them to the Jemez ruins up the road:
|
||||
|
||||
image(dscn1714)
|
||||
|
||||
|
||||
Ginnie graduated from the bike trailer for longer rides to a kid-back style bike that attaches to our bikes.
|
||||
|
||||
image(img_3531)
|
||||
|
||||
Ginnie also tried out soccer. She had fun for about three weeks, but four-year-olds don't really get the idea of having to share the ball, even with teammates. She did enjoy socializing though! And the dandelions on the field, too.
|
||||
|
||||
image(img_3561)
|
||||
|
||||
In May we got to see Ginnie's ballet recital. The kids in her class were "gumdrops" from Candyland.
|
||||
|
||||
image(img_3683)
|
||||
|
||||
Two weeks later we headed to the Pacific Northwest and got out to the beach near Astoria, and also got some good visiting in with family. We got to join in on the annual Robinson family get-together at the Great Wolf Lodge near Olympia, where Ginnie proved to be a bit of a dare-devil on waterslides.
|
||||
|
||||
Ginnie and Liz, taking a breather from the slides:
|
||||
|
||||
image(DSC08025)
|
||||
|
||||
The whole Robinson family at dinner:
|
||||
|
||||
image(DSC07998_edited-1)
|
||||
|
||||
Ginnie, Amy's dad Jim and Julie Vandling:
|
||||
|
||||
image(img_3823)
|
||||
|
||||
In Astoria:
|
||||
|
||||
image(fam)
|
||||
|
||||
image(img_3782)
|
||||
|
||||
Neale's sister April, her husband Dave and their daughter Ariana came to visit us for the 4th of July. The girls had a ball together, as usual, eating popsicles and getting their faces painted at the local 4th of July celebration.
|
||||
|
||||
image(IMG_2513)
|
||||
|
||||
image(IMG_2610-1)
|
||||
|
||||
image(IMG_2608-1)
|
||||
|
||||
And then came the Hailstorm from Hell. On July 6th (I know this because of all of our insurance forms) the entire town of Los Alamos put most autobody businesses, window retailers and roofers in the black for the year. Our car sustained some amazing dents, although no broken windows luckily. The brand-new roof on our house was totaled, however.
|
||||
|
||||
image(img_3941)
|
||||
|
||||
Ginnie and Amy spent a lot of the summer at the neighborhood pool, where Ginnie started swimming on her own this year. Here she is, waiting for her swim teacher at the Deep End:
|
||||
|
||||
image(Image106)
|
||||
|
||||
Neale got more and more experienced handling the bees. After they were delivered in the spring, the entire colony absconded from the hive (that's a fancy name for "The queen decided the hive was not to her liking, and took the entire colony with her"). Luckily, some friends of ours set us up with a nucleus, complete with comb, baby bees and honey.
|
||||
|
||||
image(img_4047)
|
||||
|
||||
In July we were asked to take in an exchange student for the year, and after some consideration decided that it would be a great experience. Three weeks later, Fitri from Indonesia arrived. She has adjusted very nicely, is involved in the Key Club and International Club at the high school, plans to run track in the spring, and amazingly took a Japanese class at the local college (imagine learning a new language from an English-speaking teacher, when English isn't your first language!). Fitri has taught us a lot about her culture, and impressed us with her ability to adapt and learn.
|
||||
|
||||
We took Fitri and Ginnie to the Dixon Apple Farm in the fall:
|
||||
|
||||
image(img_4085)
|
||||
|
||||
We finished rebuilding the deck in September. Next year, a railing!
|
||||
|
||||
image(img_4062)
|
||||
|
||||
Ginnie and Fitri on Halloween:
|
||||
|
||||
image(img_4185)
|
||||
|
||||
Amy and Ginnie have also been exploring trails around Los Alamos with friends. The kids have a ball together on their hikes, checking out the canyons and ladders and bridges.
|
||||
|
||||
Ginnie in some early snow on Pajarito Mountain:
|
||||
|
||||
image(100_1565)
|
||||
|
||||
At Tsankawi, which is a separate part of the Bandelier ruins:
|
||||
|
||||
image(100_1572)
|
||||
|
||||
The kids at Tsankawi. We got some good ladder-climbing in and had fun finding ancient arrowheads and pottery, which are still scattered around on top of the mesa there:
|
||||
|
||||
image(100_1577)
|
||||
|
||||
We also got Fitri out to Bandelier. Here she is on one of the series of 4 or 5 ladders going up to the Alcove House:
|
||||
|
||||
image(img_4276)
|
||||
|
||||
Amy's sister Kristen and her boyfriend Alex came to visit us for Thanksgiving. We took them down to Alamogordo to visit our cousins, Samantha and Claire, and took the whole gang to Carlsbad Caverns.
|
||||
|
||||
image(img_4324)
|
||||
|
||||
Fitri seems to be getting a little tired here...
|
||||
|
||||
image(img_4336)
|
||||
|
||||
Kristen and Ginnie got to bond on the hike down into the caverns:
|
||||
|
||||
image(img_4337)
|
||||
|
||||
Then we took everyone back to Los Alamos, where we had some great helpers putting together our Thanksgiving dinner. It was nice to visit with Kristen and Alex, and Neale's parents Christy and Steve joined us for Thanksgiving too. The girls also helped us decorate our tree, and the tree got its topper put on a total of three times.
|
||||
|
||||
image(img_4346)
|
||||
image(img_4355)
|
||||
image(img_4362)
|
||||
image(img_4398)
|
||||
image(img_4399)
|
||||
image(img_4404)
|
||||
|
||||
As you can see, our house has been full of busy but happy changes, and we were thrilled to welcome so many visitors this year. Have a very Merry Christmas and Happy New Year!
|
||||
|
||||
Love,
|
||||
|
||||
The Picketts (Neale, Amy, Gwendolyn-Ginnie, Fitri, and the dogs (Jada and the Dink)
|
|
@ -0,0 +1,5 @@
|
|||
PLAIN += $(wildcard xmas/*)
|
||||
|
||||
XMAS_IMAGES = $(wildcard xmas/*/*.jpg)
|
||||
XMAS_IMAGES_SC = $(patsubst %.jpg, %-sm.jpg, $(XMAS_IMAGES))
|
||||
IMAGES += $(XMAS_IMAGES) $(XMAS_IMAGES_SC)
|