--- suikawiki/script/wiki.cgi 2003/01/04 03:32:55 1.49 +++ suikawiki/script/wiki.cgi 2003/01/12 09:15:06 1.50 @@ -7,13 +7,13 @@ use strict; use lib qw(./lib); use CGI::Carp qw(fatalsToBrowser); -our $VERSION = do{my @r=(q$Revision: 1.49 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r}; - +our $VERSION = do{my @r=(q$Revision: 1.50 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r}; +binmode STDOUT; binmode STDIN; require 'wikidata/suikawiki-config.ph'; use Fcntl; ############################## our %fmt; ## formatter objects -my %embed_command = ( +our %embed_command = ( searched => '^\[\[#searched:([^\]]+)\]\]$', form => qr/\[\[\#form(?:\(([A-Za-z0-9-]+)\))?:'((?:[^'\\]|\\.)*)':'((?:[^'\\]|\\.)*)'(?::'((?:[^'\\]|\\.)*)')?\]\]/, ); @@ -26,22 +26,14 @@ our $database = bless {}, 'wiki::dummy'; my %interwiki; ############################## -my %page_command = ( - $PageName{RssPage} => 'rss', -); my %command_do = ( - read => \&do_read, - TEXT_CSS => \&do_output_css, - edit => \&do_view, + read => \&do_view, adminchangepassword => \&do_adminchangepassword, write => \&do_write, searchform => \&do_searchform, comment => \&do_comment, RandomJump => \&do_random_jump, - rss => \&do_rss, - diff => \&do_view, wikiform => \&do_wikiform, - map => \&do_view, ); my $UA = ''; ## User agent name $| = 1; @@ -59,47 +51,59 @@ &close_db; } -sub do_read { +sub do_view { my $content = $database{$form{mypage}}; my $lm = $database->mtime ($form{mypage}); wiki::referer::add ($form{mypage}, $ENV{HTTP_REFERER}); wiki::useragent::add ($ENV{HTTP_USER_AGENT}); - my @toc; - my ($magic, $content) = &SuikaWiki::Plugin::magic_and_content (undef, $content); - $magic ||= '#?SuikaWiki/0.9'; + &load_formatter ('view'); + my $view = $form{mycmd}; + if ($view eq 'edit') { + $view = 'adminedit' if $form{admin}; + } elsif ($view =~ /[^0-9A-Za-z]/) { + $view = 'view' + } + my ($magic, $content) = &SuikaWiki::Plugin::magic_and_content (undef, $content); + $magic ||= '#?SuikaWiki/0.9'; + my $o = bless {param => \%form, page => $form{mypage}, toc => [], + magic => $magic, content => $content, + formatter => $fmt{view}, &_compatible_options ()}, 'SuikaWiki::Plugin'; + if (!ref $ViewDefinition{$view} || !&{$ViewDefinition{$view}->{check}} ($o)) { + print "Status: 406 Unsupported Media Type\n"; + $view = '-UnsupportedMediaType'; + } + my $media = $ViewDefinition{$view}->{media}; + if ($ViewDefinition{$view}->{xmedia} && $UA =~ /Gecko/) { + $media = $ViewDefinition{$view}->{xmedia}; + $o->{media} = $media; + } if ($magic =~ m!^\#\?SuikaWiki/0.9!) { - my $expires = time; - if ($magic =~ /interactive="yes"/) { - $lm = $expires; - } else { - $expires += 120; - } - &print_header ($form{mypage}, -last_modified => $lm, -expires => $expires, - -content_format => $magic, -noindex => ($magic =~ /obsoleted="yes"/ ? 1 : 0)); + &print_header ($form{mypage}, -last_modified => ($magic =~ /interactive="yes"/ ? $lm : time), + -expires => ($magic =~ /interactive="yes"/ ? 1 : undef), o => $o, + -media => $media, -magic => $magic, content => $content); } else { - &print_header($form{mypage}, -expires => time + 120, -content_format => $magic, -last_modified => $lm); + &print_header($form{mypage}, -media => $media, + -magic => $magic, -last_modified => $lm, o => $o); } - &load_formatter ('view'); - print $fmt{view}->replace ($ViewDefinition{read} => bless {param => \%form, page => $form{mypage}, toc => \@toc, formatter => $fmt{view}, &_compatible_options ()}, 'SuikaWiki::Plugin'); + print $fmt{view}->replace ($ViewDefinition{$view}->{template} => $o); } -sub do_output_css { - wiki::referer::add ($form{mypage}, $ENV{HTTP_REFERER}); - wiki::useragent::add ($ENV{HTTP_USER_AGENT}); - my $content = $database{$form{mypage}}; - if ($content =~ m#^\s*/\*\s*W3C-CSS#) { - my $lm = gmtime $database->mtime ($form{mypage}); - print "Content-Type: text/css; charset=@{[&get_charset_name($kanjicode)]}\n"; - print "Last-Modified: $lm\n"; - print "Expires: @{[scalar gmtime time+3600]}\n"; ## TODO: don't use asctime - print "\n"; - print $content; - } else { +sub _do_view_msg (%) { + my %option = @_; + &load_formatter ('view'); + my $o = bless {param => \%form, page => $option{-page}, toc => [], condition => \%option, + formatter => $fmt{view}, &_compatible_options ()}, 'SuikaWiki::Plugin'; + unless (&{$ViewDefinition{$option{-view}}->{check}} ($o)) { print "Status: 406 Unsupported Media Type\n"; - &print_header('WikiPageIsNotCSS', -noindex => 1); - &load_formatter ('view'); - print $fmt{view}->replace ($ViewDefinition{read} => bless {param => \%form, page => 'WikiPageIsNotCSS', toc => [], formatter => $fmt{view}, &_compatible_options ()}, 'SuikaWiki::Plugin'); + $option{-view} = '-UnsupportedMediaType'; } + my $media = $ViewDefinition{$option{-view}}->{media}; + if ($ViewDefinition{$option{-view}}->{xmedia} && $UA =~ /Gecko/) { + $media = $ViewDefinition{$option{-view}}->{xmedia}; + $o->{media} = $media; + } + &print_header($option{-page}, -media => $media, o => $o, -goto => $option{-goto}); + print $fmt{view}->replace ($ViewDefinition{$option{-view}}->{template} => $o); } sub id_and_name ($) { @@ -111,28 +115,18 @@ } } -sub do_view { - wiki::referer::add ($form{mypage}, $ENV{HTTP_REFERER}); - wiki::useragent::add ($ENV{HTTP_USER_AGENT}); - &print_header($form{mypage}, -noindex => 1, -expires => time+60); - &load_formatter ('view'); - my $view = $form{mycmd}; - if ($view eq 'edit') { - $view = 'adminedit' if $form{admin}; - } elsif ($view =~ /[^0-9A-Za-z]/) { - $view = 'view' - } - print $fmt{view}->replace ($ViewDefinition{$view} => bless {param => \%form, page => $form{mypage}, toc => [], formatter => $fmt{view}, &_compatible_options ()}, 'SuikaWiki::Plugin'); -} - sub do_adminchangepassword { if ($form{mynewpassword} ne $form{mynewpassword2}) { - &print_error(&Resource('Error:PasswordMismatch')); + &_do_view_msg (-view => '-error', -page => $form{mypage}, + error_message => &Resource ('Error:PasswordMismatch')); + return; } my ($validpassword_crypt) = $database->meta (AdminPassword => $PageName{AdminSpecialPage}); if ($validpassword_crypt) { if (not &valid_password($form{myoldpassword})) { - &print_error(&Resource('Error:PasswordIsIncorrect')); + &_do_view_msg (-view => '-error', -page => $form{mypage}, + error_message => &Resource ('Error:PasswordIsIncorrect')); + return; } } my ($sec, $min, $hour, $day, $mon, $year, $weekday) = localtime(time); @@ -141,9 +135,8 @@ my $salt2 = $token[($sec + $min*60 + $hour*60*60) % scalar(@token)]; my $crypted = crypt($form{mynewpassword}, "$salt1$salt2"); $database->meta (AdminPassword => $PageName{AdminSpecialPage} => $crypted); - - &print_header('CompletedSuccessfully', -noindex => 1); - &print_message(&Resource('Error:PasswordIsChanged')); + + &_do_view_msg (-view => '-wrote', -page => $form{mypage}); } sub valid_password ($) { @@ -157,16 +150,14 @@ } if (not &is_editable($form{mypage})) { - &print_header($form{mypage}, -noindex => 1); - &print_message(&Resource('Error:ThisPageIsUneditable')); + &_do_view_msg (-view => '-error', -page => $form{mypage}, + error_message => &Resource ('Error:ThisPageIsUneditable')); return; } ## Check confliction if ($form{myLastModified} ne $database->mtime ($form{mypage})) { - &print_header($form{mypage}, -noindex => 1); - &load_formatter ('view'); - print $fmt{view}->replace ($ViewDefinition{-conflict} => bless {param => \%form, page => $form{mypage}, toc => [], formatter => $fmt{view}, &_compatible_options ()}, 'SuikaWiki::Plugin'); + &_do_view_msg (-view => '-conflict', -page => $form{mypage}); return; } @@ -184,14 +175,10 @@ } elsif ($form{__wikiform_anchor_index}) { $fragment .= qq(#wikiform-$form{__wikiform_anchor_index}); } - &print_header($form{mypage}, -noindex => 1, -goto => $url_cgi.'?mycmd='.&encode($form{after_edit_cmd}||'read').';mypage='.&encode($form{mypage}).qq(;x-param=@{[time.[0..9]->[rand 10]]}$fragment)); - &load_formatter ('view'); - print $fmt{view}->replace ($ViewDefinition{-wrote} => bless {param => \%form, page => $form{mypage}, formatter => $fmt{view}, &_compatible_options ()}, 'SuikaWiki::Plugin'); + &_do_view_msg (-view => '-wrote', -page => $form{mypage}, -goto => $url_cgi.'?mycmd='.&encode($form{after_edit_cmd}||'read').';mypage='.&encode($form{mypage}).qq(;x-param=@{[time.[0..9]->[rand 10]]}$fragment)); } else { delete $database{$form{mypage}}; - &print_header($form{mypage}, -noindex => 1); - &load_formatter ('view'); - print $fmt{view}->replace ($ViewDefinition{-deleted} => bless {param => \%form, page => $form{mypage}, formatter => $fmt{view}, &_compatible_options ()}, 'SuikaWiki::Plugin'); + &_do_view_msg (-view => '-deleted', -page => $form{mypage}); } } @@ -225,24 +212,15 @@ sub do_random_jump { my @list = keys %database; my $name = &encode ($list[rand @list]); - my $scheme = 'http'; - $scheme = lc $1 if $main::ENV{SERVER_PROTOCOL} =~ m#([A-Za-z0-9+.%-]+)#; - print "Location: $scheme://$main::ENV{SERVER_NAME}:$main::ENV{SERVER_PORT}$url_cgi?$name\n"; + print "Location: $uri{wiki}?$name\n"; print "\n"; } -sub print_error { - my ($msg) = @_; - &print_header($PageName{ErrorPage}, -noindex => 1); - print qq(
$msg
); - exit(0); -} - sub print_header ($;%) { my ($page, %option) = @_; my @head; - $option{body_class} = &is_frozen($page) ? 'frozen' : 'normal'; - $option{body_class} .= " wiki-page-obsoleted" if $option{-content_format} =~ /obsoleted="yes"/; + $option{o}->{-header}->{class} = &is_frozen($page) ? 'frozen' : ''; + $option{o}->{-header}->{class} .= " wiki-page-obsoleted" if $option{-magic} =~ /obsoleted="yes"/; if ($option{-goto}) { if ($UA =~ m#Opera|MSIE 2\.#) { ## WARNING: This code may output unsafe HTML document if @@ -250,6 +228,9 @@ $option{-goto} =~ tr/;/&/ if $UA =~ m#Opera#; print qq{Refresh: 0; url=$option{-goto}\n}; push @head, qq(); + } elsif ($UA =~ /Gecko/) { + print qq{Refresh: 0; url="$option{-goto}"\n}; + push @head, qq(); } else { $option{-goto} =~ tr/;/&/ if $UA =~ m#Mozilla/[1-4]\.#; print qq{Refresh: 0; url="$option{-goto}"\n}; @@ -257,38 +238,30 @@ } } print qq{Last-Modified: @{[scalar gmtime $option{-last_modified}]}\n} if $option{-last_modified}; - if ($option{-expires}) { - print qq{Expires: @{[scalar gmtime $option{-expires}]}\n}; + if ($option{-expires} != -1) { + if (defined $option{-expires}) { ## TODO: Don't use asctime + print qq{Expires: @{[scalar gmtime (time + $option{-expires})]}\n}; + } elsif ($option{-media}->{expires} != -1) { + print qq{Expires: @{[scalar gmtime (time + $option{-media}->{expires})]}\n}; + } } - if ($UA =~ m#Mozilla/2#) { - my $ct = qq{text/html; charset=@{[&get_charset_name($kanjicode,compatible=>1)]}}; + if ($option{-media}->{charset} && $UA =~ m#Mozilla/2#) { + my $ct = qq{$option{-media}->{type}; charset=@{[&get_charset_name($kanjicode,compatible=>1)]}}; print qq{Content-Type: $ct\n}; - push @head, qq{}; - } elsif ($UA =~ m#Infomosaic#) { - print qq{Content-Type: text/html\n}; + $option{o}->{-header}->{meta_ct} = qq{\n}; + } elsif (!$option{-media}->{charset} || $UA =~ m#Infomosaic#) { + print qq{Content-Type: $option{-media}->{type}\n}; } else { - print qq{Content-Type: text/html; charset=@{[&get_charset_name($kanjicode)]}\n}; + my $type = $option{-media}->{type}; + $type = 'application/xml' if $type eq 'application/rss+xml'; + print qq{Content-Type: $type; charset=@{[&get_charset_name($kanjicode)]}\n}; } - push @head, qq('.&escape($content).'' : ''; @@ -629,17 +547,17 @@ $fmt{form_option}->replace ($option, $param); $param->{output}->{form} = 1 unless defined $param->{output}->{form}; $definition .= ' %submit;' if $definition !~ /%submit/ && !$param->{output}->{nosubmit} && $param->{output}->{form}; - my $target_page = $param->{output}->{page} || $form{mypage}; + $param->{output}->{page} ||= $form{mypage}; $param->{form_disabled} = 1 if $database->meta (IsFrozen => $form{mypage}); my $target_form = $param->{output}->{id}; my $r = ''; $r = <