use strict; package main; binmode STDOUT; binmode STDIN; our $WIKI; require SuikaWiki::Plugin; our %embed_command = ( # Map, main form => qr/\[\[\#form(?:\(([A-Za-z0-9-]+)\))?:'((?:[^'\\]|\\.)*)':'((?:[^'\\]|\\.)*)'(?::'((?:[^'\\]|\\.)*)')?\]\]/, ); our $database = bless {}, 'wiki::dummy'; require SuikaWiki::Name::Space; require SuikaWiki::SrcFormat; # [to be obsolete] sub do_comment { my ($content) = $main::database{$main::form{mypage}}; my $default_name; ## this code is not strict. $default_name = $1 if $content =~ /default-name="([^"]+)"/; my @time = gmtime (time); my $datestr = sprintf '[WEAK[%04d-%02d-%02d %02d:%02d:%02d +00:00]]', $time[5]+1900,$time[4]+1,@time[3,2,1,0]; my $namestr = $main::form{myname} || $default_name || &Resource('WikiForm:WikiComment:DefaultName'); ($namestr = '', $datestr = '') if $main::form{myname} eq 'nodate'; if ($namestr =~ /^(?:>>)?[0-9]/) { $namestr = qq( ''$namestr'': ); } elsif (length $namestr) { $namestr = qq( ''[[$namestr]]'': ); } my $anchor = &get_new_anchor_index ($content); my $i = 1; my $o = 0; $content =~ s{(\[\[\#r?comment\]\])}{ my $embed = $1; if ($i == $main::form{comment_index}) { if ($embed ne '[[#rcomment]]') { $embed = "- [$anchor] $datestr$namestr$main::form{mymsg}\n$embed"; $o = 1; } else { $embed .= "\n- [$anchor] $datestr$namestr$main::form{mymsg}"; $o = 1; } } $i++; $embed; }ge; unless ($o) { $content = "#?SuikaWiki/0.9\n\n" unless $content; $content .= "\n" unless $content =~ /\n$/s; $content .= "- [$anchor] $datestr$namestr$main::form{mymsg}\n"; } $main::form{__comment_anchor_index} = $anchor; if ($main::form{mymsg} || $main::form{myname}) { $main::form{mymsg} = $content; $main::form{mytouch} = 'on'; &do_write; } else { ## Don't write #$main::form{mycmd} = 'default'; #&do_view; die "No comment specified"; } } # [move to SuikaWiki::Plugin::WikiForm] sub get_new_anchor_index ($) { my $content = shift; my $anchor = 0; $content =~ s/^(?:[-=]+\s*)?\[([0-9]+)\]/$anchor = $1 if $1 > $anchor; $&/mge; $anchor + 1; } # [move to SuikaWiki::Plugin::WikiForm] sub do_wikiform { my $content = $main::database{$main::form{mypage}}; my $anchor = &get_new_anchor_index ($content); my $write = 0; my $i = 1; $content =~ s{$embed_command{form}}{ my ($embed, $wfname, $template, $option) = ($&, $1, $3, $4); if (($wfname && $wfname eq $main::form{wikiform_targetform}) || $i == $main::form{wikiform_index}) { $template =~ s/\\([\\'])/$1/g; $option =~ s/\\([\\'])/$1/g; my $param = bless {depth=>10}, 'SuikaWiki::Plugin'; $param->{page} = $main::form{mypage}; $param->{form_index} = $i; $param->{form_name} = $wfname; $param->{anchor_index} = $anchor; $param->{argv} = \%main::form; $param->{default_name} = $1 if $content =~ /default-name="([^"]+)"/; $param->{default_name} ||= &Resource('WikiForm:WikiComment:DefaultName'); SuikaWiki::Plugin->formatter ('form_option')->replace ($option, $param); my $t = 1; for (keys %{$param->{require}||{}}) { (undef $t, last) unless length $param->{argv}->{'wikiform__'.$_}; } $t = SuikaWiki::Plugin->formatter ('form_template')->replace ($template, $param) if $t; if (length $t) { if ($param->{output}->{reverse}) { $embed .= "\n" . $t; } else { $embed = $t . "\n" . $embed; } $write = 1; $main::form{__comment_anchor_index} = $anchor if $param->{anchor_index_}; ## $anchor is used! } $main::form{__wikiform_anchor_index} = $i; undef $main::form{wikiform_targetform}; ## Make sure never to match undef $main::form{wikiform_index}; ## with WikiForm in rest of page! } $i++; $embed; }ge; unless ($write) { #$content = "#?SuikaWiki/0.9\n\n" unless $content; #$content .= "\n" unless $content =~ /\n$/s; # } if ($write) { $main::form{mymsg} = $content; $main::form{mytouch} = 'on'; &do_write; } else { ## Don't write! #$main::form{mycmd} = 'default'; #&do_view; die "No content specified"; } } # [to be obsolete] ->Message::MIME::Charset sub code_convert { require Jcode; my ($contentref, $code, $srccode) = @_; $code ||= $WIKI->{config}->{charset}->{internal}; for ($code, $srccode) { if ($_ eq 'euc-jp') { $_ = 'euc' } elsif ($_ eq 'iso-2022-jp') { $_ = 'jis' } elsif ($_ eq 'utf-8') { $_ = 'utf8' } elsif ($_ eq 'shift_jis') { $_ = 'sjis' } } if ($code eq 'iso-8859-1') { return $$contentref; ## TODO: } $$contentref = Jcode->new ($contentref, $srccode) ## Normalize FULLWIDTH characters and IDEOGRAPHIC SPACE ->tr ("\xA3\xB0-\xA3\xB9\xA3\xC1-\xA3\xDA\xA3\xE1-\xA3\xFA\xA1\xF5\xA1\xA4\xA1\xA5\xA1\xA7\xA1\xA8\xA1\xA9\xA1\xAA\xA1\xAE\xA1\xB0\xA1\xB2\xA1\xBF\xA1\xC3\xA1\xCA\xA1\xCB\xA1\xCE\xA1\xCF\xA1\xD0\xA1\xD1\xA1\xDC\xA1\xF0\xA1\xF3\xA1\xF4\xA1\xF6\xA1\xF7\xA1\xE1\xA1\xE4\xA1\xE3\xA1\xA1\xA2\xAF\xA2\xB0\xA2\xB2\xA2\xB1\xA1\xA1\xC0" => q(0-9A-Za-z&,.:;?!`^_/|()[]{}+$%#*@=>< '"~-)) ->tr (qq(\x8E\xDE\x8E\xDF) => qq(\xA1\xAB\xA1\xAC)) ->h2z ->$code; return $$contentref; } # [to be obsolete] ->Message::Field::Date : Map sub _rfc3339_date ($) { my @time = gmtime (shift); sprintf '%04d-%02d-%02dT%02d:%02d:%02d+00:00', $time[5]+1900,$time[4]+1,@time[3,2,1,0]; } # [obsolete] ->SuikaWiki::SrcFormat : SuikaWiki09 plugin sub convert_format ($$$;%) { my ($content, $d => $t, %option) = @_; my $f = SuikaWiki::Plugin->format_converter ($d => $t); if (ref $f) { $option{content} = $content; $option{from} = $d; $option{to} = $t; &$f ({}, bless (\%option, 'SuikaWiki::Plugin')); } elsif ($option{-error_no_return}) { return undef; } elsif ($t =~ /HTML|xml/) { if (length $content) { my $NS_XHTML1 = 'http://www.w3.org/1999/xhtml'; my $r = Message::Markup::XML::Node->new (type => '#element', namespace_uri => $NS_XHTML1, local_name => 'pre'); $r->append_text ($content); return $r; } else { return ''; } } else { $content; } } package SuikaWiki::Plugin; ## Obsolete sub magic_and_content ($$) { my ($magic, $page) = ('', $_[1]); $magic = $1 if $page =~ s!^((?:\#\?|/\*|<\?)[^\x02\x0A\x0D]+)[\x02\x0A\x0D]+!!s; ($magic, $page); } ## Obsolete sub get_data ($$$$;%) { my ($self, $prop, $key, %opt) = @_; ## TODO: common interface to WikiDB ## TODO: error recovering $main::WIKI->{db}->get ($prop => $key); } package wiki::transitional::uri_param; require Tie::Hash; our @ISA = 'Tie::Hash'; sub TIEHASH ($@) { bless {http => $_[1]}, $_[0]; } sub FETCH ($$) { my ($self, $key) = @_; exists $self->{val}->{$key} ? $self->{val}->{$key}: $self->{http}->parameter ($key); } sub STORE ($$$) { my ($self, $key, $val) = @_; $self->{val}->{$key} = $val; } sub DELETE ($$) { my ($self, $key) = @_; $self->{val}->{$key} = undef; } sub EXISTS ($$) { my ($self, $key) = @_; exists $self->{val}->{$key} ? 1: defined $self->{http}->parameter ($key); } package main; our $VERSION = do{my @r=(q$Revision: 1.20 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r}; push @{$WIKI->{event}->{setting_initial_variables}}, sub { my $wiki = shift; $wiki->{implementation_version} = 'hcs'.$VERSION; ## Error output require SuikaWiki::Output::CGICarp; $SuikaWiki::Output::CGICarp::CUSTOM_REASON_TEXT = 'Internal WikiEngine Error'; CGI::Carp::set_message (sub { my $msg = shift; #$msg =~ s/&/&/g; #$msg =~ s/{implementation_name} .'/'. $wiki->version; for ($wiki_name_version) { s/&/&/g; s/ 500 Internal WikiEngine Error

Internal WikiEngine Error

$msg

$wiki_name_version
EOH }); $wiki->{var}->{db}->{read_only}->{'#default'} = 1; require SuikaWiki::Input::HTTP; $wiki->{input} = SuikaWiki::Input::HTTP->new; $wiki->{input}->{decoder}->{'#default'} = sub { my ($http, $s, $temp_params) = @_; return main::code_convert (\$s, $wiki->{config}->{charset}->{internal}, lc (@{$temp_params->{_charset_}||[]}[0]) || $wiki->{config}->{charset}->{uri_param}); }; $wiki->{var}->{client}->{user_agent_name} = $wiki->{input}->meta_variable ('HTTP_USER_AGENT'); $wiki->{var}->{client}->{used_for_negotiate} = ['User-Agent']; ## TODO: PATH_INFO support my $page = $wiki->{input}->meta_variable ('QUERY_STRING'); if ($page && !(index ($page, '=') > -1)) { $page =~ tr/+/ /; $page =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack 'C', hex $1/ge; $page = main::code_convert (\$page, $wiki->{config}->{charset}->{internal}, $wiki->{config}->{charset}->{uri_query}); } else { $page = $wiki->{input}->parameter ('mypage'); } ## TODO: SuikaWiki 3 WikiName $page =~ tr/\x00-\x20\x7F//d; $page = SuikaWiki::Name::Space::normalize_name ($page); if ($page) { $wiki->{var}->{page} = [split '//', $page]; } else { $wiki->{var}->{page} = $wiki->{config}->{page}->{Default}; } ## Mode my $mode = $wiki->{input}->parameter ('mode') || $wiki->{input}->parameter ('mycmd') ## for compatibility with || 'default'; ## YukiWiki and SuikaWiki 2 $mode =~ tr/-/_/; if ($mode eq 'default' || $mode =~ /[^0-9A-Za-z_]/) { ## BUG: this code is not strict my $cookie = $wiki->{input}->meta_variable ('HTTP_COOKIE'); if ($cookie =~ /SelectedMode=([0-9A-Za-z_-]+)/) { $mode = $1; $mode =~ tr/-/_/; } else { $mode = 'read'; } push @{$wiki->{var}->{client}->{used_for_negotiate}}, 'Cookie'; } $wiki->{var}->{mode} = $mode; ## Transitional variables tie %main::form, 'wiki::transitional::uri_param', $wiki->{input}; $main::UA = $wiki->{var}->{client}->{user_agent_name}; $main::form{mypage} = join '//', @{$wiki->{var}->{page}}; $main::form{mycmd} = $mode; }; push @{$WIKI->{event}->{view_in_mode}}, sub { my ($wiki, $opt) = @_; my $arg = {condition => {mode => $opt->{mode} || '-error', output => 'http-cgi', http_method => $opt->{method} || 'GET'}}; my $viewobj = $wiki->{view}->instantiate ($opt->{mode} || '-error', $arg); if (ref $viewobj) { $viewobj->main ($arg); } elsif ($opt->{mode} ne '-error') { $wiki->view_in_mode (mode => '-error', method => 'GET'); ## TODO: cache control for non-GET } else { die "Some error happens. Additionally, error reporting mode not defined"; } }; ## Initialization of various functions $WIKI->init_variables; $WIKI->init_plugin; $WIKI->init_view; $WIKI->{view}->register_common_modes; ## Error handlers use SuikaWiki::DB::Util::Error; my $catcher = catch SuikaWiki::DB::Util::Error with { my $err = shift; my $err_msg = $err->text; $err_msg = caller (3) . '-->' . caller (2) . '-->' . caller (1) . ($err->{-method} ? '->'.$err->{-method} : '') . ': ' . (defined $err->{-file} ? $err->{-file} . ': ' : '') . (defined $err->{-prop} ? $err->{-prop} . ': ' : '') . (defined $err->{-key} ? join ('//', @{$err->{-key}}) . ': ' : '') . $err_msg; if ($WIKI->{config}->{path_to}->{db__content__error_log}) { open LOG, '>>', $WIKI->{config}->{path_to}->{db__content__error_log}; print LOG scalar (gmtime), " @{[$$]} {$err->{def}->{level}}: ", $err_msg, "\n"; close LOG; } if ($err->{def}->{level} eq 'fatal' or $err->{def}->{level} eq 'stop') { require Carp; local $Carp::Verbose = 1; Carp::croak $err_msg; } } catch SuikaWiki::View::Implementation::error with { my $err = shift; exit if $err->{type} eq 'ERROR_REPORTED'; $err->throw; }; $WIKI->{config}->{catch}->{formatter_view} = catch Message::Util::Formatter::error with { my $err = shift; my $wiki = $err->{-option}->{param}->{wiki}; SuikaWiki::Plugin->module_package ('Error') ->reporting_formatting_template_error ($err, $wiki); $wiki->view_in_mode (mode => '-error', method => 'GET'); throw SuikaWiki::View::Implementation::error type => 'ERROR_REPORTED'; }; $WIKI->{config}->{catch}->{formatter_view_error} = catch Message::Util::Formatter::error with { my $err = shift; my $wiki = $err->{-option}->{param}->{wiki}; SuikaWiki::Plugin->module_package ('Error') ->reporting_formatting_template_error ($err, $wiki); $wiki->view_in_mode (mode => '-error-error', method => 'GET'); throw SuikaWiki::View::Implementation::error type => 'ERROR_REPORTED'; }; ## Main try { $WIKI->view_in_mode (mode => $WIKI->{var}->{mode}, method => $WIKI->{input}->meta_variable ('REQUEST_METHOD')); } $catcher; exit; END { try { $WIKI->exit; } $catcher; }; =head1 NAME lib/suikawiki.pl --- SuikaWiki : WikiEngine driver for HTTP CGI =head1 LICENSE Copyright 2000-2003 Wakaba , et. al This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; # $Date: 2003/12/06 02:22:10 $