X-Git-Url: https://git.deb.at/?p=pkg%2Fblosxom.git;a=blobdiff_plain;f=blosxom.cgi;h=3ebe972c88108cbcb1746d2fc513da371bc63565;hp=78ad2ffcac7160a5cc41a5a1f62fc9c250ad19a3;hb=3ae079e92bfa02656179e5933937c9103f8be48f;hpb=70ac0fad278c1b701df7c3613d27c6b76104dfbd diff --git a/blosxom.cgi b/blosxom.cgi index 78ad2ff..3ebe972 100755 --- a/blosxom.cgi +++ b/blosxom.cgi @@ -1,8 +1,8 @@ #!/usr/bin/perl # Blosxom -# Author: Rael Dornfest -# Version: 2.0.2 +# Author: Rael Dornfest (2003), The Blosxom Development Team (2005-2008) +# Version: 2.1.0 # Home/Docs/Licensing: http://blosxom.sourceforge.net/ # Development/Downloads: http://sourceforge.net/projects/blosxom @@ -79,7 +79,7 @@ $static_entries = 0; # -------------------------------- 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; @@ -88,7 +88,10 @@ use File::stat; use Time::Local; use CGI qw/:standard :netscape/; -$version = "2.0.2"; +$version = "2.1.0"; + +# 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; @@ -141,6 +144,8 @@ my $fh = new FileHandle; # 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 @@ -162,9 +167,6 @@ $static_dir =~ s!/$!!; # 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 @@ -180,39 +182,49 @@ else { # 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 ) = @_; @@ -251,15 +263,19 @@ my @plugin_list = (); my %plugin_hash = (); # If $plugin_list is set, read plugins to use from that file -$plugin_list = "$config_dir/$plugin_list" - if $plugin_list && $plugin_list !~ m!^\s*/!; -if ( $plugin_list and -r $plugin_list and $fh->open("< $plugin_list") ) { - @plugin_list = map { chomp $_; $_ } grep { /\S/ && !/^#/ } <$fh>; - $fh->close; +if ( $plugin_list ) { + if ( -r $plugin_list and $fh->open("< $plugin_list") ) { + @plugin_list = map { chomp $_; $_ } grep { /\S/ && !/^#/ } <$fh>; + $fh->close; + } + else { + warn "unable to read or open plugin_list '$plugin_list': $!"; + $plugin_list = ''; + } } # Otherwise walk @plugin_dirs to get list of plugins to use -elsif (@plugin_dirs) { +if ( ! @plugin_list && @plugin_dirs ) { for my $plugin_dir (@plugin_dirs) { next unless -d $plugin_dir; if ( opendir PLUGINS, $plugin_dir ) { @@ -285,18 +301,21 @@ elsif (@plugin_dirs) { unshift @INC, @plugin_dirs; foreach my $plugin (@plugin_list) { my ( $plugin_name, $off ) = $plugin =~ /^\d*([\w:]+?)(_?)$/; + my $plugin_file = $plugin_list ? $plugin_name : $plugin; my $on_off = $off eq '_' ? -1 : 1; # Allow perl module plugins - if ( $plugin =~ m/::/ && -z $plugin_hash{$plugin} ) { + # The -z test is a hack to allow a zero-length placeholder file in a + # $plugin_path directory to indicate an @INC module should be loaded + if ( $plugin =~ m/::/ && ( $plugin_list || -z $plugin_hash{$plugin} ) ) { # For Blosxom::Plugin::Foo style plugins, we need to use a string require - eval "require $plugin_name"; + eval "require $plugin_file"; } else { # we try first to load from $plugin_dir before attempting from $plugin_path - eval { require "$plugin_dir/$plugin" } - or eval { require $plugin }; + eval { require "$plugin_dir/$plugin_file" } + or eval { require $plugin_file }; } if ($@) { @@ -503,10 +522,10 @@ sub generate { # 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; }; @@ -641,18 +660,31 @@ sub generate { } } - if ( $content_type =~ m{\bxml\b} ) { + if ( $encode_xml_entities && $content_type =~ m{\bxml\b} ) { + # Escape special characters inside the container + + # The following line should be moved more towards to top for + # performance reasons -- Axel Beckert, 2008-07-22 + my $url_escape_re = qr([^-/a-zA-Z0-9:._]); + + $url =~ s($url_escape_re)(sprintf('%%%02X', ord($&)))eg; + $path =~ s($url_escape_re)(sprintf('%%%02X', ord($&)))eg; + $fn =~ s($url_escape_re)(sprintf('%%%02X', ord($&)))eg; # 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; + $url =~ s/($escape_re)/$escape{$1}/g; + $path =~ s/($escape_re)/$escape{$1}/g; + $fn =~ s/($escape_re)/$escape{$1}/g; } $story = &$interpolate($story); @@ -696,16 +728,16 @@ sub nice_date { my ($unixtime) = @_; my $c_time = CORE::localtime($unixtime); - my ( $dw, $mo, $da, $hr, $min, $yr ) + my ( $dw, $mo, $da, $hr, $min, $sec, $yr ) = ( $c_time - =~ /(\w{3}) +(\w{3}) +(\d{1,2}) +(\d{2}):(\d{2}):\d{2} +(\d{4})$/ + =~ /(\w{3}) +(\w{3}) +(\d{1,2}) +(\d{2}):(\d{2}):(\d{2}) +(\d{4})$/ ); $ti = "$hr:$min"; $da = sprintf( "%02d", $da ); my $mo_num = $month2num{$mo}; my $offset - = timegm( 00, $min, $hr, $da, $mo_num - 1, $yr - 1900 ) - $unixtime; + = timegm( $sec, $min, $hr, $da, $mo_num - 1, $yr - 1900 ) - $unixtime; my $utc_offset = sprintf( "%+03d", int( $offset / 3600 ) ) . sprintf( "%02d", ( $offset % 3600 ) / 60 ); @@ -716,34 +748,31 @@ sub nice_date { __DATA__ html content_type text/html; charset=$blog_encoding +html head html head html head -html head -html head -html head $blog_title $path_info_da $path_info_mo $path_info_yr -html head +html head +html head +html head $blog_title $path_info_da $path_info_mo $path_info_yr html head html head -html head
-html head $blog_title
-html head $path_info_da $path_info_mo $path_info_yr -html head
-html head

+html head

+html head

$blog_title

+html head

$path_info_da $path_info_mo $path_info_yr

+html head
-html story

-html story $title
-html story $body
-html story
-html story posted at: $ti | path: $path | permanent link to this entry -html story

+html story
+html story

$title

+html story
$body
+html story

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

+html story
-html date

$dw, $da $mo $yr

+html date

$dw, $da $mo $yr

html foot -html foot

-html foot

-html foot -html foot
+html foot
+html foot powered by blosxom +html foot
html foot html foot @@ -764,7 +793,7 @@ rss story $title rss story $dw, $da $mo $yr $ti:00 $utc_offset rss story $url/$yr/$mo_num/$da#$fn rss story $path -rss story $path/$fn +rss story $url$path/$fn rss story $body rss story @@ -775,15 +804,17 @@ rss foot error content_type text/html +error head error head -error head -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.

- +error head Error: unknown Blosxom flavour "$flavour" +error head +error head

Error: unknown Blosxom flavour "$flavour"

+error head

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.

-error story

$title
-error story $body #

+error story

$title

+error story
$body

#

-error date

$dw, $da $mo $yr

+error date

$dw, $da $mo $yr

error foot error foot