# Blosxom
# Author: Rael Dornfest <rael@oreilly.com>
-# Version: 2.0
-# Home/Docs/Licensing: http://www.raelity.org/apps/blosxom/
+# Version: 2.0.1
+# Home/Docs/Licensing: http://www.blosxom.com/
+# Development/Downloads: http://sourceforge.net/projects/blosxom
package blosxom;
@num2month = sort { $month2num{$a} <=> $month2num{$b} } keys %month2num;
# Use the stated preferred URL or figure it out automatically
-$url ||= url();
-$url =~ s/^included:/http:/; # Fix for Server Side Includes (SSI)
+$url ||= url(-path_info => 1);
+$url =~ s/^included:/http:/ if $ENV{SERVER_PROTOCOL} eq 'INCLUDED';
+
+# NOTE: Since v3.12, it looks as if CGI.pm misbehaves for SSIs and
+# always appends path_info to the url. To fix this, we always
+# request an url with path_info, and always remove it from the end of the
+# string.
+my $pi_len = length $ENV{PATH_INFO};
+my $might_be_pi = substr($url, -$pi_len);
+substr($url, -length $ENV{PATH_INFO}) = '' if $might_be_pi eq $ENV{PATH_INFO};
+
$url =~ s!/$!!;
# Drop ending any / from dir settings
return join '', <$fh> if $fh->open("< $datadir/$path/$chunk.$flavour");
} while ($path =~ s/(\/*[^\/]*)$// and $1);
- return join '', ($template{$flavour}{$chunk} || $template{error}{$chunk} || '');
+ # Check for definedness, since flavour can be the empty string
+ if (defined $template{$flavour}{$chunk}) {
+ return $template{$flavour}{$chunk};
+ } elsif (defined $template{error}{$chunk}) {
+ return $template{error}{$chunk}
+ } else {
+ return '';
+ }
};
# Bring in the templates
%template = ();
while (<DATA>) {
- last if /^(__END__)?$/;
- my($ct, $comp, $txt) = /^(\S+)\s(\S+)\s(.*)$/;
+ last if /^(__END__)$/;
+ my($ct, $comp, $txt) = /^(\S+)\s(\S+)(?:\s(.*))?$/ or next;
$txt =~ s/\\n/\n/mg;
- $template{$ct}{$comp} = $txt;
+ $template{$ct}{$comp} .= $txt . "\n";
}
# Plugins: Start
my $tmp; foreach my $plugin ( @plugins ) { $plugins{$plugin} > 0 and $plugin->can('entries') and defined($tmp = $plugin->entries()) and $entries = $tmp and last; }
my ($files, $indexes, $others) = &$entries();
-%files = %$files; %indexes = %$indexes; %others = ref $others ? %$others : ();
-
-# Plugins: Filter
-foreach my $plugin ( @plugins ) { $plugins{$plugin} > 0 and $plugin->can('filter') and $entries = $plugin->filter(\%files, \%others) }
+%indexes = %$indexes;
# Static
if (!$ENV{GATEWAY_INTERFACE} and param('-password') and $static_password and param('-password') eq $static_password) {
foreach ( ('', split /\//, $path) ) {
$p .= "/$_";
$p =~ s!^/!!;
- $path_info = $p;
$done{$p}++ and next;
(-d "$static_dir/$p" or $p =~ /\.$file_extension$/) or mkdir "$static_dir/$p", 0755;
foreach $flavour ( @static_flavours ) {
param('-quiet') or print "$fn.$flavour\n";
my $fh_w = new FileHandle "> $static_dir/$fn.$flavour" or die "Couldn't open $static_dir/$p for writing: $!";
$output = '';
- print $fh_w
- $indexes{$path} == 1
- ? &generate('static', $p, '', $flavour, $content_type)
- : &generate('static', '', $p, $flavour, $content_type);
+ if ($indexes{$path} == 1) {
+ # category
+ $path_info = $p;
+ # individual story
+ $path_info =~ s!\.$file_extension$!\.$flavour!;
+ print $fh_w &generate('static', $path_info, '', $flavour, $content_type);
+ } else {
+ # date
+ local ($path_info_yr,$path_info_mo,$path_info_da, $path_info) =
+ split /\//, $p, 4;
+ unless (defined $path_info) {$path_info = ""};
+ print $fh_w &generate('static', '', $p, $flavour, $content_type);
+ }
$fh_w->close;
}
}
sub generate {
my($static_or_dynamic, $currentdir, $date, $flavour, $content_type) = @_;
+ %files = %$files; %others = ref $others ? %$others : ();
+
+ # Plugins: Filter
+ foreach my $plugin ( @plugins ) { $plugins{$plugin} > 0 and $plugin->can('filter') and $entries = $plugin->filter(\%files, \%others) }
+
my %f = %files;
# Plugins: Skip
($path,$fn) = $path_file =~ m!^$datadir/(?:(.*)/)?(.*)\.$file_extension!;
# Only stories in the right hierarchy
- $path =~ /^$currentdir/ or $path_file eq "$datadir/$currentdir" or next;
+ $path =~ /^$currentdir(?=$|/)/ or $path_file eq "$datadir/$currentdir" or next;
# Prepend a slash for use in templates only if a path exists
$path &&= "/$path";
# Default HTML and RSS template bits
__DATA__
html content_type text/html
-html head <html><head><link rel="alternate" type="type="application/rss+xml" title="RSS" href="$url/index.rss" /><title>$blog_title $path_info_da $path_info_mo $path_info_yr</title></head><body><center><font size="+3">$blog_title</font><br />$path_info_da $path_info_mo $path_info_yr</center><p />
-html story <p><a name="$fn"><b>$title</b></a><br />$body<br /><br />posted at: $ti | path: <a href="$url$path">$path</a> | <a href="$url/$yr/$mo_num/$da#$fn">permanent link to this entry</a></p>\n
-html date <h3>$dw, $da $mo $yr</h3>\n
-html foot <p /><center><a href="http://www.blosxom.com/"><img src="http://www.blosxom.com/images/pb_blosxom.gif" border="0" /></a></body></html>
+
+html head <html>
+html head <head>
+html head <link rel="alternate" type="type="application/rss+xml" title="RSS" href="$url/index.rss" />
+html head <title>$blog_title $path_info_da $path_info_mo $path_info_yr
+html head </title>
+html head </head>
+html head <body>
+html head <center>
+html head <font size="+3">$blog_title</font><br />
+html head $path_info_da $path_info_mo $path_info_yr
+html head </center>
+html head <p />
+
+html story <p>
+html story <a name="$fn"><b>$title</b></a><br />
+html story $body<br />
+html story <br />
+html story posted at: $ti | path: <a href="$url$path">$path </a> | <a href="$url/$yr/$mo_num/$da#$fn">permanent link to this entry</a>
+html story </p>
+
+html date <h3>$dw, $da $mo $yr</h3>
+
+html foot
+html foot <p />
+html foot <center>
+html foot <a href="http://www.blosxom.com/"><img src="http://www.blosxom.com/images/pb_blosxom.gif" border="0" /></a>
+html foot </center>
+html foot </body>
+html foot </html>
+
rss content_type text/xml
-rss head <?xml version="1.0"?>\n<!-- name="generator" content="blosxom/$version" -->\n<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN" "http://my.netscape.com/publish/formats/rss-0.91.dtd">\n\n<rss version="0.91">\n <channel>\n <title>$blog_title $path_info_da $path_info_mo $path_info_yr</title>\n <link>$url</link>\n <description>$blog_description</description>\n <language>$blog_language</language>\n
-rss story <item>\n <title>$title</title>\n <link>$url/$yr/$mo_num/$da#$fn</link>\n <description>$body</description>\n </item>\n
-rss date \n
-rss foot </channel>\n</rss>
+
+rss head <?xml version="1.0"?>
+rss head <!-- name="generator" content="blosxom/$version" -->
+rss head <!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN" "http://my.netscape.com/publish/formats/rss-0.91.dtd">
+rss head
+rss head <rss version="0.91">
+rss head <channel>
+rss head <title>$blog_title $path_info_da $path_info_mo $path_info_yr</title>
+rss head <link>$url</link>
+rss head <description>$blog_description</description>
+rss head <language>$blog_language</language>
+
+rss story <item>
+rss story <title>$title</title>
+rss story <link>$url/$yr/$mo_num/$da#$fn</link>
+rss story <description>$body</description>
+rss story </item>
+
+rss date
+
+rss foot </channel>
+rss foot </rss>
+
error content_type text/html
-error head <html><body><p><font color="red">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.</font>\n\n
-error story <p><b>$title</b><br />$body <a href="$url/$yr/$mo_num/$da#fn.$default_flavour">#</a></p>\n
-error date <h3>$dw, $da $mo $yr</h3>\n
-error foot </body></html>
+
+error head <html>
+error head <body>
+error head <p><font color="red">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.</font>
+
+
+error story <p><b>$title</b><br />
+error story $body <a href="$url/$yr/$mo_num/$da#fn.$default_flavour">#</a></p>
+
+error date <h3>$dw, $da $mo $yr</h3>
+
+error foot </body>
+error foot </html>
__END__