# --------------------------------
use vars
- qw! $version $blog_title $blog_description $blog_language $blog_encoding $datadir $url %template $template $depth $num_entries $file_extension $default_flavour $static_or_dynamic $config_dir $plugin_list $plugin_path $plugin_dir $plugin_state_dir @plugins %plugins $static_dir $static_password @static_flavours $static_entries $path_info $path_info_yr $path_info_mo $path_info_da $path_info_mo_num $flavour $static_or_dynamic %month2num @num2month $interpolate $entries $output $header $show_future_entries %files %indexes %others !;
+ qw! $version $blog_title $blog_description $blog_language $blog_encoding $datadir $url %template $template $depth $num_entries $file_extension $default_flavour $static_or_dynamic $config_dir $plugin_list $plugin_path $plugin_dir $plugin_state_dir @plugins %plugins $static_dir $static_password @static_flavours $static_entries $path_info_full $path_info $path_info_yr $path_info_mo $path_info_da $path_info_mo_num $flavour $static_or_dynamic %month2num @num2month $interpolate $entries $output $header $show_future_entries %files %indexes %others $encode_xml_entities !;
use strict;
use FileHandle;
$version = "2.0.2";
+# Should I encode entities for xml content-types? (plugins can turn this off if they do it themselves)
+$encode_xml_entities = 1;
+
# Load configuration from $ENV{BLOSXOM_CONFIG_DIR}/blosxom.conf, if it exists
my $blosxom_config;
if ( $ENV{BLOSXOM_CONFIG_FILE} && -r $ENV{BLOSXOM_CONFIG_FILE} ) {
# Use the stated preferred URL or figure it out automatically
$url ||= url( -path_info => 1 );
+# Unescape %XX hex codes (from URI::Escape::uri_unescape)
+$url =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
$url =~ s/^included:/http:/ if $ENV{SERVER_PROTOCOL} eq 'INCLUDED';
# NOTE: Since v3.12, it looks as if CGI.pm misbehaves for SSIs and
# Fix depth to take into account datadir's path
$depth += ( $datadir =~ tr[/][] ) - 1 if $depth;
-# Global variable to be used in head/foot.{flavour} templates
-$path_info = '';
-
if ( !$ENV{GATEWAY_INTERFACE}
and param('-password')
and $static_password
# Path Info Magic
# Take a gander at HTTP's PATH_INFO for optional blog name, archive yr/mo/day
my @path_info = split m{/}, path_info() || param('path');
+$path_info_full = join '/', @path_info; # Equivalent to $ENV{PATH_INFO}
shift @path_info;
-while ( $path_info[0]
- and $path_info[0] =~ /^[a-zA-Z].*$/
- and $path_info[0] !~ /(.*)\.(.*)/ )
-{
- $path_info .= '/' . shift @path_info;
-}
-
# Flavour specified by ?flav={flav} or index.{flav}
$flavour = '';
+if (! ($flavour = param('flav'))) {
+ if ( $path_info[$#path_info] =~ /(.+)\.(.+)$/ ) {
+ $flavour = $2;
+ pop @path_info if $1 eq 'index';
+ }
+}
+$flavour ||= $default_flavour;
-if ( $path_info[$#path_info] =~ /(.+)\.(.+)$/ ) {
- $flavour = $2;
- $path_info .= "/$1.$2" if $1 ne 'index';
- pop @path_info;
+# Global variable to be used in head/foot.{flavour} templates
+$path_info = '';
+# Add all @path_info elements to $path_info till we come to one that could be a year
+while ( $path_info[0] && $path_info[0] !~ /^(19|20)\d{2}$/) {
+ $path_info .= '/' . shift @path_info;
}
-else {
- $flavour = param('flav') || $default_flavour;
+
+# Pull date elements out of path
+if ($path_info[0] && $path_info[0] =~ /^(19|20)\d{2}$/) {
+ $path_info_yr = shift @path_info;
+ if ($path_info[0] &&
+ ($path_info[0] =~ /^(0\d|1[012])$/ ||
+ exists $month2num{ ucfirst lc $path_info_mo })) {
+ $path_info_mo = shift @path_info;
+ # Map path_info_mo to numeric $path_info_mo_num
+ $path_info_mo_num = $path_info_mo =~ /^\d{2}$/
+ ? $path_info_mo
+ : $month2num{ ucfirst lc $path_info_mo };
+ if ($path_info[0] && $path_info[0] =~ /^[0123]\d$/) {
+ $path_info_da = shift @path_info;
+ }
+ }
}
+# Add remaining path elements to $path_info
+$path_info .= '/' . join('/', @path_info);
+
# Strip spurious slashes
$path_info =~ s!(^/*)|(/*$)!!g;
-# Date fiddling
-( $path_info_yr, $path_info_mo, $path_info_da ) = @path_info;
-$path_info_mo_num
- = $path_info_mo
- ? ( $path_info_mo =~ /\d{2}/
- ? $path_info_mo
- : ( $month2num{ ucfirst( lc $path_info_mo ) } || undef ) )
- : undef;
-
# Define standard template subroutine, plugin-overridable at Plugins: Template
$template = sub {
my ( $path, $chunk, $flavour ) = @_;
# Define default interpolation subroutine
$interpolate = sub {
-
package blosxom;
my $template = shift;
- $template =~ s/(\$\w+(?:::\w+)*)/"defined $1 ? $1 : ''"/gee;
+ # Interpolate scalars, namespaced scalars, and hash/hashref scalars
+ $template =~ s/(\$\w+(?:::\w+)*(?:(?:->)?{(['"]?)[-\w]+\2})?)/"defined $1 ? $1 : ''"/gee;
return $template;
};
}
}
- if ( $content_type =~ m{\bxml\b} ) {
+ if ( $encode_xml_entities && $content_type =~ m{\bxml\b} ) {
# Escape <, >, and &, and to produce valid RSS
my %escape = (
__DATA__
html content_type text/html; charset=$blog_encoding
+html head <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
html head <html>
html head <head>
-html head <meta http-equiv="content-type" content="text/html;charset=$blog_encoding" />
-html head <link rel="alternate" 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 <meta http-equiv="content-type" content="text/html;charset=$blog_encoding" >
+html head <link rel="alternate" type="application/rss+xml" title="RSS" href="$url/index.rss" >
+html head <title>$blog_title $path_info_da $path_info_mo $path_info_yr</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 head <div align="center">
+html head <h1>$blog_title</h1>
+html head <p>$path_info_da $path_info_mo $path_info_yr</p>
+html head </div>
-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 story <div>
+html story <h3><a name="$fn">$title</a></h3>
+html story <div>$body</div>
+html story <p>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>
+html story </div>
-html date <h3>$dw, $da $mo $yr</h3>
+html date <h2>$dw, $da $mo $yr</h2>
html foot
-html foot <p />
-html foot <center>
-html foot <a href="http://blosxom.sourceforge.net/"><img src="http://blosxom.sourceforge.net/images/pb_blosxom.gif" border="0" /></a>
-html foot </center>
+html foot <div align="center">
+html foot <a href="http://blosxom.sourceforge.net/"><img src="http://blosxom.sourceforge.net/images/pb_blosxom.gif" alt="powered by blosxom" border="0" width="90" height="33" ></a>
+html foot </div>
html foot </body>
html foot </html>
error content_type text/html
+error head <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
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></p>
-
+error head <head><title>Error: unknown Blosxom flavour "$flavour"</title></head>
+error head <body>
+error head <h1><font color="red">Error: unknown Blosxom flavour "$flavour"</font></h1>
+error head <p>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.</p>
-error story <p><b>$title</b><br />
-error story $body <a href="$url/$yr/$mo_num/$da#fn.$default_flavour">#</a></p>
+error story <h3>$title</h3>
+error story <div>$body</div> <p><a href="$url/$yr/$mo_num/$da#fn.$default_flavour">#</a></p>
-error date <h3>$dw, $da $mo $yr</h3>
+error date <h2>$dw, $da $mo $yr</h2>
error foot </body>
error foot </html>