#!/usr/bin/perl -w
=head1 NAME
wmblog -- an example script demonstrating how to use WebMake to generate a web
log.
=head1 SYNOPSIS
wmblog [-D] [-m] < message
=head1 DESCRIPTION
This is a work in progress -- this script is used to generate
L, my web log ;)
I live in my mail reader, so the blog is mail-oriented; when I find something
interesting, I compose a mail to the blog address, or forward the interesting
mail. As a result, this script supports stripping forwarded messages into a
separate page.
=cut
# Where to save the resulting blog items
$BLOGDIR = '/home/jm/taint.org/raw';
# Who can submit items to the blog
# (TODO: add an authentication item to the template ;)
$BLOGGERS = '(jm@jmason.org)';
# Who to send cc's of blogged items to; '' means no cc's.
$CCBLOGGED = 'jm+blogged@jmason.org';
# Where WebMake is installed. This is optional, as for most installs
# WebMake will be in the Perl system lib path.
use lib '/home/jm/ftp/webmake/lib';
$KILLED_HEADERS = qr{
(?:Return-Path|Received|Delivered-To|Message-Id|MIME-Version|
Importance|Sender|Errors-To|Precedence|List-Id|X-Beenthere|
Content-Type|Content-Transfer-Encoding|Reply-To|X-Spam-\S+|
Resent-\S+|Priority|X-\S+)
}x;
# ---------------------------------------------------------------------------
require HTML::WebMake::Main;
sub usage {
die "usage: wmblog [-D] [-m] < message\n";
}
use vars qw{
$opt_h $opt_D $opt_m
};
use Getopt::Std;
getopts ('hDm') or usage();
if (defined $opt_h) { usage(); }
# ---------------------------------------------------------------------------
my $text = '';
my $author = '';
my $subject = '';
# read the mail headers, if present, and find the author from From: header
# get title from Subject: too
if ($opt_m) {
while () {
/^$/ and last;
if (/^From: (.*?)$/) {
if ($1 !~ /${BLOGGERS}/) {
die "access denied: $1\n";
}
$_ = $1;
if (/\((.*)\)/) { $author = $1; }
elsif (/\"?(.*)\"? <.*>/) { $author = $1; }
else { $author = $_; }
}
if (/^Subject: (.*?)\s*$/) {
$subject = $1;
}
}
}
# get the text
$text = join ('', );
close STDIN;
# handle cc'ing
if ($CCBLOGGED =~ /\S/) {
$CCBLOGGED =~ s/'//gs;
open (CC, "|/usr/lib/sendmail -oi -t");
print CC "From: nobody
Subject: blogged item
To: $CCBLOGGED
$text\n";
close CC;
}
# by default, the entire mail message is a blog entry.
# However, if there's BlogStart...BlogEnd block, that's
# the text; the rest of the mail is an attachment.
my $attachedmail = '';
my $linktext = undef;
if ($text =~ s/BlogStart:\s*\n\s*(.*?)\s*\nBlogEnd://s) {
$attachedmail = $text;
$text = $1;
# find the link text. If it's not there, add one.
if ($attachedmail =~ s/^LinkText:\s+(.*?)\s*$//m) {
$linktext = $1;
if (!defined $linktext || $text !~ /\Q$linktext\E/) {
$text .= ' (Link)';
$linktext = 'Link';
}
}
}
# only add an attached-mail file if there *is* an attached mail!
if ($attachedmail =~ /\S/) {
$text =~ s/\b\Q$linktext\E\b/"${linktext}" [mail]/gs;
$text .= "\n\n [mail]: \$(__NAME__.mail)\n\n";
# clean off any spare whitespace, and headers, at the top of the
# attached mail.
$_ = $attachedmail;
s/^From \S+ \S\S\S \S\S\S \d\d [^\n]*$//gm;
s/^---+\s+forwarded message.*$//gim;
s/^---+\s+end of forwarded message.*$//gim;
# trim off unwanted headers
1 while s/(?:^|\n)
${KILLED_HEADERS}
:\s[^\n]*(?:\n\ \ +[^\n]*)*
/\n/gsx;
s/^\s+//gs;
s/\n\n\n+/\n\n/gs;
$attachedmail = $_;
}
# tag it with author metadata from the From: address
if ($author ne '') {
$text .= "$author";
}
if ($subject ne '') {
$text .= "$subject";
}
# now generate a filename to save the content item (and the
# attached mail, if there is one)
my $filename = generate_filename($BLOGDIR);
$text =~ s/__NAME__/${filename}/gs;
$filename = $BLOGDIR.'/'.$filename;
if ($opt_D) {
print "Dump: text = '$text'\n\n\nmail = '$attachedmail'\n\n".
"textfile=$filename.txt\nmailfile=$filename.mail\n";
exit;
}
open (OUT, ">$filename.txt")
or die "Cannot write to $filename.txt\n";
print OUT $text;
close OUT;
if ($attachedmail ne '') {
open (OUT, ">$filename.mail")
or die "Cannot write to $filename.mail\n";
print OUT $attachedmail;
close OUT;
}
# KLUDGE: currently we run this as 'daemon' but the blog index
# is rebuilt as 'jm'. so mail a command to rebuild the blog to
# jm; procmail will catch it and run webmake for us.
system ("echo | mail -s REBUILDBLOG jm");
exit;
# ---------------------------------------------------------------------------
# Generates a filename of the form:
#
# YYYY/MM/DD/HHMMSSa.txt
#
# Where YYYY=year, MM=month, DD=day, HHMMSS=time. 'a' is reserved
# as a counter character to avoid collisions, in case >1 blog item
# arrives in the same second. It's unlikely, but better to be safe.
#
sub generate_filename {
my ($targetdir) = @_;
use POSIX qw(strftime);
use File::Path;
my @time = localtime;
my $dirname = strftime ("%Y/%m/%d", @time);
my $filename = strftime ("%T", @time); $filename =~ s/[^0-9]//g;
my $fulldir = $targetdir.'/'.$dirname;
if (!-d $fulldir) {
mkpath ($fulldir)
or die "Cannot create $fulldir\n";
}
$filename = $dirname.'/'.$filename;
my $counter = 'a';
while (-f $targetdir.'/'.$filename.$counter.'.txt') { $counter++; }
$filename = $filename.$counter;
$filename;
}