#!/usr/bin/perl -w # Blosxom # Author: Rael Dornfest # Version: 0+5i # Home/Docs/Licensing: http://www.raelity.org/apps/blosxom/ # --- Configurable variables ----- # What's this blog's title? my $blog_title = "Hal Goes Abroad"; # What's this blog's description (for outgoing RSS feed)? my $blog_description = "Hal goes to New Zealand (for the America's Cup) and beyoond."; # What's this blog's primary language (for outgoing RSS feed)? my $blog_language = "en"; # Where are this blog's entries kept? my $datadir = "/home/eisen/blog"; # Should I stick only to the datadir for items or travel down the # directory hierarchy looking for items? If so, to what depth? # 0 = infinite depth (aka grab everything), 1 = datadir only, n = n levels down my $depth = 0; # How many entries should I show on the home page? my $num_entries = 5; # -------------------------------- use strict; use FileHandle; use File::Find; use File::stat; use Time::localtime; use CGI qw/:standard :netscape/; my $datadir_current = $datadir; # Fix depth to take into account datadir's path $depth and $depth += ($datadir =~ tr[/][]) - 1; # Take a gander at HTTP's PATH_INFO for optional blog name, archive yr/mo/day my $url = url(); $url =~ s/^included:/http:/; # Fix for Server Side Includes (SSI) my @pi = split m{/}, path_info(); shift @pi; my $pi_bl = ''; while ($pi[0] =~ /^[a-zA-Z]\w*$/) { $pi_bl .= '/' . shift @pi; } my $flavour = param('flav') || 'html'; # An icky bit of backward-compatibility with Blosxom < 0+5i #path_info() =~ m!/xml/?$! and $flavour = 'rss'; # Check the existence and readability of a specified sub-blog $pi_bl and -d "$datadir_current/$pi_bl" and -r "$datadir_current/$pi_bl" and $datadir_current .= "/$pi_bl", $url .= "/$pi_bl", $blog_title .= ": $pi_bl"; # Date fiddling my($pi_yr,$pi_mo,$pi_da) = @pi; my %month2num = (nil=>'00', Jan=>'01', Feb=>'02', Mar=>'03', Apr=>'04', May=>'05', Jun=>'06', Jul=>'07', Aug=>'08', Sep=>'09', Oct=>'10', Nov=>'11', Dec=>'12'); my @num2month = sort { $month2num{$a} <=> $month2num{$b} } keys %month2num; my $pi_mo_num = $pi_mo ? ( $pi_mo =~ /\d{2}/ ? $pi_mo : ($month2num{ucfirst(lc $pi_mo)} || undef) ) : undef; my $fh = new FileHandle; # Bring in the templates my %template = (); while () { last if /^(__END__)?$/; my($ct, $comp, $txt) = /^(\S+)\s(\S+)\s(.*)$/; $txt =~ s/\\n/\n/mg; $template{$ct}{$comp} = $txt; } chomp(my $content_type = $fh->open("< $datadir_current/content_type.$flavour") || $fh->open("< $datadir/content_type.$flavour") ? <$fh> : ($template{$flavour}{'content_type'} || 'text/plain')); # Header print header($content_type); my $head = join '', ($fh->open("< $datadir_current/head.$flavour") || $fh->open("< $datadir/head.$flavour") ? <$fh> : ($template{$flavour}{'head'} || $template{'error'}{'head'})); $head =~ s/(\$\w+)/$1 . "||''"/gee; print $head; # Send in the blogs my $curdate = ''; my %files; find({ wanted => sub { my $curr_depth = $File::Find::dir =~ tr[/][]; return if $depth and $curr_depth > $depth; $_ =~ /\.txt$/ and $files{$File::Find::name} = stat($_)->mtime; }, follow_fast => 1 }, $datadir_current); foreach ( sort { $files{$b} <=> $files{$a} } keys %files ) { last if $num_entries-- <= 0 && !$pi_yr; my($fn) = ($_ =~ /^$datadir_current\/?(.*)\.txt$/); my($path) = ($fn =~ /^(.*)\//); # Date fiddling for by-{year,month,day} archive views my $mtime = ctime(stat("$datadir_current/$fn.txt")->mtime); my($dw,$mo,$da,$ti,$yr) = ( $mtime =~ /(\w{3}) +(\w{3}) +(\d{1,2}) +(\d{2}:\d{2}):\d{2} +(\d{4})$/ ); $da = sprintf("%02d", $da); my $mo_num = $month2num{$mo}; next if $pi_yr && $yr != $pi_yr; last if $pi_yr && $yr < $pi_yr; next if $pi_mo_num && $mo ne $num2month[$pi_mo_num]; next if $pi_da && $da != $pi_da; last if $pi_da && $da < $pi_da; $content_type eq 'text/html' && $curdate ne "$dw, $da $mo $yr" && print span({-class=>'blosxomDate'}, $curdate = "$dw, $da $mo $yr"); # Entry if (-T "$datadir_current/$fn.txt" && $fh->open("< $datadir_current/$fn.txt")) { chomp(my $title = <$fh>); chomp(my $body = join '', <$fh>); if ($content_type eq 'text/xml') { # Escape <, >, and &, and to produce valid RSS my %escape = ('<'=>'<', '>'=>'>', '&'=>'&', '"'=>'"'); my $escape_re = join '|' => keys %escape; $title =~ s/($escape_re)/$escape{$1}/g; $body =~ s/($escape_re)/$escape{$1}/g; } $fh->close; my $story = join '', ($fh->open("< $datadir_current/story.$flavour") || $fh->open("< $datadir/story.$flavour") ? <$fh> : ($template{$flavour}{'story'} || $template{'error'}{'story'})); $story =~ s/(\$\w+)/$1 . "||''"/gee; print $story; $fh->close; } } # Foot my $foot = join '', ($fh->open("< $datadir_current/foot.$flavour") || $fh->open("< $datadir/foot.$flavour") ? <$fh> : ($template{$flavour}{'foot'} || $template{'error'}{'foot'})); $foot =~ s/(\$\w+)/$1 . "||''"/gee; print $foot; # Default HTML and RSS template bits __DATA__ html content_type text/html html head $blog_title $pi_da $pi_mo $pi_yr
$blog_title
$pi_da $pi_mo $pi_yr

html story

$title
$body

posted at: $ti | path: /$path | permanent link to this entry

\n html foot

rss content_type text/xml rss head \n\n\n\n\n \n $blog_title $pi_da $pi_mo $pi_yr\n $url\n $blog_description\n $blog_language\n rss story \n $title\n $url/$yr/$mo_num/$da#$fn\n $body\n \n rss foot \n error head Error: I'm afraid this is the first I've heard of a "$flavour" flavoured Blosxom. Try dropping the "/+$flavour" bit from the end of the URL.\n\n html content_type text/html