/[pub]/suikawiki/script/wiki.cgi
Suika

Diff of /suikawiki/script/wiki.cgi

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.49 by w, Sat Jan 4 03:32:55 2003 UTC revision 1.51 by w, Sun Jan 26 02:30:24 2003 UTC
# Line 1  Line 1 
1  #!/usr/bin/perl  #!/usr/bin/perl
2  # wiki.cgi - This is YukiWiki, yet another Wiki clone.  ## wiki.cgi - This is SuikaWiki, yet another WikiEngine
 #  
 # This program is free software; you can redistribute it and/or  
 # modify it under the same terms as Perl itself.  
3    
4  use strict;  use strict;
5  use lib qw(./lib);  use lib qw(./lib);
6  use CGI::Carp qw(fatalsToBrowser);  use CGI::Carp qw(fatalsToBrowser);
7    binmode STDOUT; binmode STDIN;
8  our $VERSION = do{my @r=(q$Revision$=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};  our $VERSION = do{my @r=(q$Revision$=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
9    require 'wikidata/suikawiki-config.ph'; ## site configuration script
10  require 'wikidata/suikawiki-config.ph';  require Yuki::YukiWikiCache;
11  use Fcntl;  use Fcntl;
 ##############################  
12  our %fmt;       ## formatter objects  our %fmt;       ## formatter objects
13  my %embed_command = (  our %embed_command = (
14          searched        => '^\[\[#searched:([^\]]+)\]\]$',          searched        => '^\[\[#searched:([^\]]+)\]\]$',
15          form    => qr/\[\[\#form(?:\(([A-Za-z0-9-]+)\))?:'((?:[^'\\]|\\.)*)':'((?:[^'\\]|\\.)*)'(?::'((?:[^'\\]|\\.)*)')?\]\]/,          form    => qr/\[\[\#form(?:\(([A-Za-z0-9-]+)\))?:'((?:[^'\\]|\\.)*)':'((?:[^'\\]|\\.)*)'(?::'((?:[^'\\]|\\.)*)')?\]\]/,
16  );  );
17  our ($modifier_dbtype,$url_cgi,%uri,%PathTo,$use_exists);  our ($modifier_dbtype,$url_cgi,%uri,%PathTo);
18  our (%PageName,$kanjicode,$lang,%ViewDefinition);  our (%PageName,$kanjicode,$lang,%ViewDefinition);
19    
 ##############################  
20  my %form;  my %form;
21  our %database;  our %database;
22  our $database = bless {}, 'wiki::dummy';  our $database = bless {}, 'wiki::dummy';
23  my %interwiki;  my %interwiki;
 ##############################  
 my %page_command = (  
     $PageName{RssPage} => 'rss',  
 );  
24  my %command_do = (  my %command_do = (
25      read => \&do_read,      default => \&do_view,
     TEXT_CSS => \&do_output_css,  
     edit => \&do_view,  
26      adminchangepassword => \&do_adminchangepassword,      adminchangepassword => \&do_adminchangepassword,
27      write => \&do_write,      write => \&do_write,
28      searchform => \&do_searchform,      searchform => \&do_searchform,
29      comment => \&do_comment,      comment => \&do_comment,
30      RandomJump  => \&do_random_jump,      RandomJump  => \&do_random_jump,
     rss => \&do_rss,  
     diff => \&do_view,  
31      wikiform    => \&do_wikiform,      wikiform    => \&do_wikiform,
     map => \&do_view,  
32  );  );
33  my $UA = '';  ## User agent name  our $UA = '';  ## User agent name
34  $| = 1;  $| = 1;
 ##############################  
35    
36  sub main {  sub main {
37      $UA = $main::ENV{HTTP_USER_AGENT};      $UA = $main::ENV{HTTP_USER_AGENT};
# Line 54  sub main { Line 40  sub main {
40      if ($command_do{$form{mycmd}}) {      if ($command_do{$form{mycmd}}) {
41          &{$command_do{$form{mycmd}}};          &{$command_do{$form{mycmd}}};
42      } else {      } else {
43          &{$command_do{read}};          &{$command_do{default}};
44      }      }
45      &close_db;      &close_db;
46  }  }
47    
48  sub do_read {  sub do_view {
49    my $content = $database{$form{mypage}};    my $content = $database{$form{mypage}};
50    my $lm = $database->mtime ($form{mypage});    my $lm = $database->mtime ($form{mypage});
51    wiki::referer::add ($form{mypage}, $ENV{HTTP_REFERER});    wiki::referer::add ($form{mypage}, $ENV{HTTP_REFERER});
52    wiki::useragent::add ($ENV{HTTP_USER_AGENT});    wiki::useragent::add ($ENV{HTTP_USER_AGENT});
53    my @toc;    &load_formatter ('view');
54      my ($magic, $content) = &SuikaWiki::Plugin::magic_and_content (undef, $content);      my $view = $form{mycmd};
55      $magic ||= '#?SuikaWiki/0.9';      if ($view eq 'edit') {
56      if ($magic =~ m!^\#\?SuikaWiki/0.9!) {        $view = 'adminedit' if $form{admin};
57        my $expires = time;      } elsif ($view =~ /[^0-9A-Za-z]/) {
58        if ($magic =~ /interactive="yes"/) {        $view = 'default'
59          $lm = $expires;      }
60        if ($view eq 'default' || !$view) {
61          ## BUG: this code is not strict
62          if ($main::ENV{HTTP_COOKIE} =~ /SelectedMode=([0-9A-Za-z]+)/) {
63            $view = $1;
64        } else {        } else {
65          $expires += 120;          $view = 'read';
66        }        }
67        &print_header ($form{mypage}, -last_modified => $lm, -expires => $expires,      }
68          -content_format => $magic, -noindex => ($magic =~ /obsoleted="yes"/ ? 1 : 0));    my ($magic, $content) = &SuikaWiki::Plugin::magic_and_content (undef, $content);
69      $magic ||= '#?SuikaWiki/0.9';
70      my $o = bless {param => \%form, page => $form{mypage}, toc => [],
71                     magic => $magic, content => $content,
72                     formatter => $fmt{view}, &_compatible_options ()}, 'SuikaWiki::Plugin';
73      if (!ref $ViewDefinition{$view} || !&{$ViewDefinition{$view}->{check}} ($o)) {
74        print "Status: 406 Unsupported Media Type\n";
75        $view = '-UnsupportedMediaType';
76      }
77      my $media = $ViewDefinition{$view}->{media};
78      if ($ViewDefinition{$view}->{xmedia} && $UA =~ /Gecko/) {
79        $media = $ViewDefinition{$view}->{xmedia};
80        $o->{media} = $media;
81      } elsif ($UA =~ m#Mozilla/0\..+Windows#) {
82        $kanjicode = 'shift_jis';
83      }
84        if ($magic =~ m!^\#\?SuikaWiki/0.9!) {
85          &print_header ($form{mypage}, -last_modified => ($magic =~ /interactive="yes"/ ? time : $lm),
86            -expires => ($magic =~ /interactive="yes"/ ? 1 : undef), o => $o,
87            -media => $media, -magic => $magic,  content => $content);
88      } else {      } else {
89        &print_header($form{mypage}, -expires => time + 120, -content_format => $magic, -last_modified => $lm);        &print_header($form{mypage}, -media => $media,
90                                       -magic => $magic, -last_modified => $lm, o => $o);
91      }      }
92      &load_formatter ('view');    if ($kanjicode ne 'euc') {
93      print $fmt{view}->replace ($ViewDefinition{read} => bless {param => \%form, page => $form{mypage}, toc => \@toc, formatter => $fmt{view}, &_compatible_options ()}, 'SuikaWiki::Plugin');      my $s = $fmt{view}->replace ($ViewDefinition{$view}->{template} => $o);
94        print &code_convert (\$s => $kanjicode);
95      } else {
96        print $fmt{view}->replace ($ViewDefinition{$view}->{template} => $o);
97      }
98  }  }
99    
100  sub do_output_css {  sub _do_view_msg (%) {
101    wiki::referer::add ($form{mypage}, $ENV{HTTP_REFERER});    my %option = @_;
102    wiki::useragent::add ($ENV{HTTP_USER_AGENT});    &load_formatter ('view');
103    my $content = $database{$form{mypage}};    my $o = bless {param => \%form, page => $option{-page}, toc => [], condition => \%option,
104    if ($content =~ m#^\s*/\*\s*W3C-CSS#) {                   formatter => $fmt{view}, &_compatible_options ()}, 'SuikaWiki::Plugin';
105      my $lm = gmtime $database->mtime ($form{mypage});    unless (&{$ViewDefinition{$option{-view}}->{check}} ($o)) {
     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 {  
106      print "Status: 406 Unsupported Media Type\n";      print "Status: 406 Unsupported Media Type\n";
107      &print_header('WikiPageIsNotCSS', -noindex => 1);      $option{-view} = '-UnsupportedMediaType';
     &load_formatter ('view');  
     print $fmt{view}->replace ($ViewDefinition{read} => bless {param => \%form, page => 'WikiPageIsNotCSS', toc => [], formatter => $fmt{view}, &_compatible_options ()}, 'SuikaWiki::Plugin');  
108    }    }
109      my $media = $ViewDefinition{$option{-view}}->{media};
110      if ($ViewDefinition{$option{-view}}->{xmedia} && $UA =~ /Gecko/) {
111        $media = $ViewDefinition{$option{-view}}->{xmedia};
112        $o->{media} = $media;
113      }
114      &print_header($option{-page}, -media => $media, o => $o, -goto => $option{-goto});
115      print $fmt{view}->replace ($ViewDefinition{$option{-view}}->{template} => $o);
116  }  }
117    
118  sub id_and_name ($) {  sub id_and_name ($) {
# Line 111  sub id_and_name ($) { Line 124  sub id_and_name ($) {
124      }      }
125  }  }
126    
 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');  
 }  
   
127  sub do_adminchangepassword {  sub do_adminchangepassword {
128      if ($form{mynewpassword} ne $form{mynewpassword2}) {      if ($form{mynewpassword} ne $form{mynewpassword2}) {
129          &print_error(&Resource('Error:PasswordMismatch'));          &_do_view_msg (-view => '-error', -page => $form{mypage},
130                           error_message => &Resource ('Error:PasswordMismatch'));
131            return;
132      }      }
133      my ($validpassword_crypt) = $database->meta (AdminPassword => $PageName{AdminSpecialPage});      my ($validpassword_crypt) = $database->meta (AdminPassword => $PageName{AdminSpecialPage});
134      if ($validpassword_crypt) {      if ($validpassword_crypt) {
135          if (not &valid_password($form{myoldpassword})) {          if (not &valid_password($form{myoldpassword})) {
136              &print_error(&Resource('Error:PasswordIsIncorrect'));              &_do_view_msg (-view => '-error', -page => $form{mypage},
137                               error_message => &Resource ('Error:PasswordIsIncorrect'));
138                return;
139          }          }
140      }      }
141      my ($sec, $min, $hour, $day, $mon, $year, $weekday) = localtime(time);      my ($sec, $min, $hour, $day, $mon, $year, $weekday) = localtime(time);
# Line 141  sub do_adminchangepassword { Line 144  sub do_adminchangepassword {
144      my $salt2 = $token[($sec + $min*60 + $hour*60*60) % scalar(@token)];      my $salt2 = $token[($sec + $min*60 + $hour*60*60) % scalar(@token)];
145      my $crypted = crypt($form{mynewpassword}, "$salt1$salt2");      my $crypted = crypt($form{mynewpassword}, "$salt1$salt2");
146      $database->meta (AdminPassword => $PageName{AdminSpecialPage} => $crypted);      $database->meta (AdminPassword => $PageName{AdminSpecialPage} => $crypted);
147        
148      &print_header('CompletedSuccessfully', -noindex => 1);      &_do_view_msg (-view => '-wrote', -page => $form{mypage});
     &print_message(&Resource('Error:PasswordIsChanged'));  
149  }  }
150    
151  sub valid_password ($) {  sub valid_password ($) {
# Line 157  sub do_write { Line 159  sub do_write {
159      }      }
160    
161      if (not &is_editable($form{mypage})) {      if (not &is_editable($form{mypage})) {
162          &print_header($form{mypage}, -noindex => 1);          &_do_view_msg (-view => '-error', -page => $form{mypage},
163          &print_message(&Resource('Error:ThisPageIsUneditable'));                         error_message => &Resource ('Error:ThisPageIsUneditable'));
164          return;          return;
165      }      }
166    
167      ## Check confliction      ## Check confliction
168      if ($form{myLastModified} ne $database->mtime ($form{mypage})) {      if ($form{myLastModified} ne $database->mtime ($form{mypage})) {
169        &print_header($form{mypage}, -noindex => 1);        &_do_view_msg (-view => '-conflict', -page => $form{mypage});
       &load_formatter ('view');  
       print $fmt{view}->replace ($ViewDefinition{-conflict} => bless {param => \%form, page => $form{mypage}, toc => [], formatter => $fmt{view}, &_compatible_options ()}, 'SuikaWiki::Plugin');  
170        return;        return;
171      }      }
172    
# Line 184  sub do_write { Line 184  sub do_write {
184          } elsif ($form{__wikiform_anchor_index}) {          } elsif ($form{__wikiform_anchor_index}) {
185              $fragment .= qq(#wikiform-$form{__wikiform_anchor_index});              $fragment .= qq(#wikiform-$form{__wikiform_anchor_index});
186          }          }
187          &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));          &_do_view_msg (-view => '-wrote', -page => $form{mypage}, -goto => $url_cgi.'?mycmd='.&encode($form{after_edit_cmd}||'default').';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');  
188      } else {      } else {
189          delete $database{$form{mypage}};          delete $database{$form{mypage}};
190          &print_header($form{mypage}, -noindex => 1);          &_do_view_msg (-view => '-deleted', -page => $form{mypage});
         &load_formatter ('view');  
         print $fmt{view}->replace ($ViewDefinition{-deleted} => bless {param => \%form, page => $form{mypage}, formatter => $fmt{view}, &_compatible_options ()}, 'SuikaWiki::Plugin');  
191      }      }
192  }  }
193    
# Line 201  sub _compatible_options () { Line 197  sub _compatible_options () {
197    
198  sub get_search_result ($;%) {  sub get_search_result ($;%) {
199    my $word = lc shift;    my $word = lc shift;
200      my $SearchResult = SuikaWiki::Plugin->cache ('search');
201    my %option = @_;    my %option = @_;
202    my @r;    my @r;
203    foreach my $page (keys %database) {    unless (defined $SearchResult->{$word}) {
204      next if !$option{-match_myself} && ($page eq $word);      for my $page (keys %database) {
205      my $content = lc $database{$page};        next if !$option{-match_myself} && ($page eq $word);
206      if (index (lc $page, $word) > -1) {        my $content = lc $database{$page};
207        my $c = $content =~ s/\Q$word\E//g;        $content =~ s/^[^\x0A\x0D]+[\x0D\x0A]+//s;
208        push @r, [$page, $c+20];        if (index (lc $page, $word) > -1) {
209      } elsif (index ($word, lc $page) > -1) {          my $c = $content =~ s/\Q$word\E//g;
210        my $c = $content =~ s/\Q$word\E//g;          push @r, [$page, $c+20];
211        push @r, [$page, $c+10];        } elsif (index ($word, lc $page) > -1) {
212      } elsif (my $c = $content =~ s/\Q$word\E//g) {          my $c = $content =~ s/\Q$word\E//g;
213        push @r, [$page, $c];          push @r, [$page, $c+10];
214          } elsif (my $c = $content =~ s/\Q$word\E//g) {
215            push @r, [$page, $c];
216          }
217      }      }
218        @r = sort {$b->[1] <=> $a->[1] || $a->[0] cmp $b->[0]} @r;
219        $SearchResult->{$word} = join "\x1E", map {$_->[0]."\x1F".$_->[1]} @r;
220      } else {
221        @r = map {[split /\x1F/, $_, 2]} split /\x1E/, $SearchResult->{$word};
222    }    }
223    #my $em = sub { my $s = shift; $s =~ s#(\Q$word\E)#<em>$1</em>#gi; $s };    #my $em = sub { my $s = shift; $s =~ s#(\Q$word\E)#<em>$1</em>#gi; $s };
224    my $r = join "\n", map {qq(<li>[$_->[1]] <a href ="$url_cgi?@{[&encode($_->[0])]}" class="wiki">@{[&escape($_->[0])]}</a> <span class="wikipage-summary">@{[&escape(&get_subjectline($_->[0]))]}</span></li>)} sort {$b->[1] <=> $a->[1] || $a->[0] cmp $b->[0]} @r;    my $r = join "\n", map {qq(<li>[$_->[1]] <a href ="$url_cgi?@{[&encode($_->[0])]}" class="wiki">@{[&escape($_->[0])]}</a> <span class="wikipage-summary">@{[&escape(&get_subjectline($_->[0]))]}</span></li>)} @r;
225    $r = qq|<ul class="search-result">$r</ul>| if $r;    $r = qq|<ul class="search-result">$r</ul>| if $r;
226    wantarray? ($r, scalar @r): $r;    wantarray? ($r, scalar @r): $r;
227  }  }
# Line 225  sub get_search_result ($;%) { Line 229  sub get_search_result ($;%) {
229  sub do_random_jump {  sub do_random_jump {
230    my @list = keys %database;    my @list = keys %database;
231    my $name = &encode ($list[rand @list]);    my $name = &encode ($list[rand @list]);
232    my $scheme = 'http';    print "Location: $uri{wiki}?$name\n";
   $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";  
233    print "\n";    print "\n";
234  }  }
235    
 sub print_error {  
     my ($msg) = @_;  
     &print_header($PageName{ErrorPage}, -noindex => 1);  
     print qq(<p><strong class="error">$msg</strong></p>);  
     exit(0);  
 }  
   
236  sub print_header ($;%) {  sub print_header ($;%) {
237      my ($page, %option) = @_;      my ($page, %option) = @_;
238      my @head;      my @head;
239      $option{body_class} = &is_frozen($page) ? 'frozen' : 'normal';      $option{o}->{-header}->{class} = &is_frozen($page) ? 'frozen' : '';
240      $option{body_class} .= " wiki-page-obsoleted" if $option{-content_format} =~ /obsoleted="yes"/;      $option{o}->{-header}->{class} .= " wiki-page-obsoleted" if $option{-magic} =~ /obsoleted="yes"/;
241      if ($option{-goto}) {      if ($option{-goto}) {
242        if ($UA =~ m#Opera|MSIE 2\.#) {        if ($UA =~ m#Opera|MSIE 2\.#) {
243            ## WARNING: This code may output unsafe HTML document if            ## WARNING: This code may output unsafe HTML document if
# Line 250  sub print_header ($;%) { Line 245  sub print_header ($;%) {
245            $option{-goto} =~ tr/;/&/ if $UA =~ m#Opera#;            $option{-goto} =~ tr/;/&/ if $UA =~ m#Opera#;
246            print qq{Refresh: 0; url=$option{-goto}\n};            print qq{Refresh: 0; url=$option{-goto}\n};
247            push @head, qq(<meta http-equiv="refresh" content="0; url=$option{-goto}">);            push @head, qq(<meta http-equiv="refresh" content="0; url=$option{-goto}">);
248          } elsif ($UA =~ /Gecko/) {
249              print qq{Refresh: 0; url="$option{-goto}"\n};
250              push @head, qq(<meta http-equiv="refresh" content="0; url=&quot;@{[&escape($option{-goto})]}&quot;" />);
251        } else {        } else {
252            $option{-goto} =~ tr/;/&/ if $UA =~ m#Mozilla/[1-4]\.#;            $option{-goto} =~ tr/;/&/ if $UA =~ m#Mozilla/[1-4]\.#;
253            print qq{Refresh: 0; url="$option{-goto}"\n};            print qq{Refresh: 0; url="$option{-goto}"\n};
# Line 257  sub print_header ($;%) { Line 255  sub print_header ($;%) {
255        }        }
256      }      }
257      print qq{Last-Modified: @{[scalar gmtime $option{-last_modified}]}\n} if $option{-last_modified};      print qq{Last-Modified: @{[scalar gmtime $option{-last_modified}]}\n} if $option{-last_modified};
258      if ($option{-expires}) {      if ($option{-expires} != -1) {
259        print qq{Expires: @{[scalar gmtime $option{-expires}]}\n};        if (defined $option{-expires}) {  ## TODO: Don't use asctime
260            print qq{Expires: @{[scalar gmtime (time + $option{-expires})]}\n};
261          } elsif ($option{-media}->{expires} != -1) {
262            print qq{Expires: @{[scalar gmtime (time + $option{-media}->{expires})]}\n};
263          }
264      }      }
265      if ($UA =~ m#Mozilla/2#) {      if ($option{-media}->{charset} && $UA =~ m#Mozilla/[12]\.#) {
266          my $ct = qq{text/html; charset=@{[&get_charset_name($kanjicode,compatible=>1)]}};          my $ct = qq{$option{-media}->{type}; charset=@{[&get_charset_name($kanjicode,compatible=>1)]}};
267          print qq{Content-Type: $ct\n};          print qq{Content-Type: $ct\n};
268          push @head, qq{<meta http-equiv="content-type" content="$ct">};          $option{o}->{-header}->{meta_ct} = qq{<meta http-equiv="content-type" content="$ct">\n};
269      } elsif ($UA =~ m#Infomosaic#) {      } elsif (!$option{-media}->{charset} || $UA =~ m#Infomosaic|Mozilla/0\.#) {
270          print qq{Content-Type: text/html\n};          print qq{Content-Type: $option{-media}->{type}\n};
271            $option{o}->{-header}->{meta_ct} = qq{<meta http-equiv="content-type" content="$option{-media}->{type}; charset=@{[&get_charset_name($kanjicode,compatible=>1)]}">\n};
272      } else {      } else {
273          print qq{Content-Type: text/html; charset=@{[&get_charset_name($kanjicode)]}\n};          my $type = $option{-media}->{type};
274            $type = 'application/xml' if $type eq 'application/rss+xml';
275            print qq{Content-Type: $type; charset=@{[&get_charset_name($kanjicode)]}\n};
276      }      }
277      push @head, qq(<title>@{[&escape($page)]}</title>);      print <<"EOD";      ## TODO:
     if ($UA !~ m#Mozilla/[1-4]\.# || $UA =~ m#MSIE (?:[4-9]\.|\d\d)#) {  
       push @head, qq(<link rel="stylesheet" type="text/css").  
                   qq( href="@{[&escape($uri{wiki}.'?mycmd=TEXT_CSS;mypage='.&encode($PageName{DefaultStyleForHTML}).';x-lm='.$database->mtime ($PageName{DefaultStyleForHTML}))]}");  
     }  
     push @head, q(<meta name="ROBOTS" content="NOINDEX">) if $option{-noindex};  
     my ($Links, $links) = &make_navigate_links ($page);  
     #print $Links;      ## Link: fields  
     $links = join "\n", (@head, $links);  
     print <<"EOD";  
278  Content-Language: $lang  Content-Language: $lang
279  Content-Style-Type: text/css  Content-Style-Type: text/css
280    
 <!-- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"  
 "http://www.w3.org/TR/html4/loose.dtd"> + RUBY -->  
 <html lang="$lang" class="$option{body_class}">  
 <head profile="http://suika.fam.cx/~wakaba/-temp/wiki/wiki?WikiHTMLMetaProfile">  
 $links  
 </head>  
281  EOD  EOD
282      $option{o}->{-header}->{links} = join "\n", (@head);
283  }  }
284    
285  sub get_charset_name ($;%) {  sub get_charset_name ($;%) {
# Line 303  sub get_charset_name ($;%) { Line 294  sub get_charset_name ($;%) {
294      $charset;      $charset;
295  }  }
296    
 sub _navigate_links (@) {  
   my ($page) = @_;  
   my $editable = (&is_editable($page) && !&is_frozen($page)) ? 1 : 0;  
   my $cookedpage = &encode($page);  
   <<EOH;  
     @{[ $editable  
         ? qq(<a title="@{[&Resource('EditThisPageLong',escape=>1)]}" href="$url_cgi?mycmd=edit;mypage=$cookedpage" accesskey="E" class="wiki-cmd">@{[&Resource('EditThisPage',escape=>1)]}</a> | )  
         : qq()  
     ]}  
     <a href="$url_cgi?mycmd=read;mypage=$cookedpage;x-param=@{[time.[0..9]->[rand 10]]}" class="wiki-cmd" title="@{[&Resource('ViewThisPageLong',escape=>1)]}">@{[&Resource('ViewThisPage',escape=>1)]}</a> |  
     <a href="$url_cgi?mycmd=map;mypage=$cookedpage" class="wiki-cmd" title="@{[&Resource('ShowMapOfThisPageLong',escape=>1)]}">@{[&Resource('ShowMapOfThisPage',escape=>1)]}</a> |  
     <a href="$url_cgi?$PageName{CreatePage}" class="wiki" title="@{[&Resource('GoToCreatePageLong',escape=>1)]}">@{[&Resource('GoToCreatePage',escape=>1)]}</a> |  
     <a href="$url_cgi?$PageName{IndexPage}" class="wiki" title="@{[&Resource('GoToIndexPageLong',escape=>1)]}">@{[&Resource('GoToIndexPage',escape=>1)]}</a> |  
     <a href="$url_cgi?$PageName{FrontPage}" class="wiki" title="@{[&Resource('GoToHomePageLong',escape=>1)]}">@{[&Resource('GoToHomePage',escape=>1)]}</a> |  
     <a href="$url_cgi?$PageName{SearchPage}" class="wiki" title="@{[&Resource('GoToSearchPageLong',escape=>1)]}">@{[&Resource('GoToSearchPage',escape=>1)]}</a> |  
     <a href="$url_cgi?mycmd=RandomJump;x-param=@{[time.[0..9]->[rand 10]]}" class="wiki randomlink" title="@{[&Resource('GoSomewhereLong',escape=>1)]}">@{[&Resource('GoSomewhere',escape=>1)]}</a> |  
     <a href="$url_cgi?$PageName{RecentChanges}" class="wiki" title="@{[&Resource('GoToRecentChangesLong',escape=>1)]}">@{[&Resource('GoToRecentChanges',escape=>1)]}</a>  
 EOH  
 }  
   
 sub make_navigate_links ($) {  
     my $page = shift;  
     my @link;  
     push @link, {rel=>'edit', href=>"$url_cgi?mycmd=edit;mypage=@{[&encode($page)]}", class=>"wiki-command", title=>&Resource('EditThisPageLink')} if &is_editable ($page) && !&is_frozen ($page);  
     push @link, {rel=>'edit', href=>"$url_cgi?mycmd=edit;admin=1;mypage=@{[&encode($page)]}", class=>"wiki-command", title=>&Resource('AdminEditThisPageLink')} if &is_editable ($page) || &is_frozen ($page);  
     push @link, {rel=>'view', href=>"$url_cgi?mycmd=read;mypage=@{[&encode($page)]};x-p=@{[time.[0..9]->[rand 10]]}", class=>'wiki-command', title=>&Resource('ViewThisPageLink')};  
     push @link, {rel=>'myself', href=>"$url_cgi?@{[&encode($page)]}", class=>'wiki', title=>&Resource('GoToMyselfLink')};  
     push @link, {rel=>'index', href=>"$url_cgi?$PageName{IndexPage}", class=>'wiki', title=>&Resource('GoToIndexPageLink')};  
     push @link, {rel=>'home', href=>"$url_cgi?$PageName{FrontPage}", class=>'wiki', title=>&Resource('GoToHomePageLink')};  
     push @link, {rel=>'News', href=>"$url_cgi?WikiNews", class=>'wiki', title=>&Resource('GoToWikiNewsLink')};  
     push @link, {rel=>'News', href=>"$url_cgi?$PageName{RecentChanges}", class=>"wiki", title=>&Resource('GoToRecentChangesLink')};  
     push @link, {rel=>'News', href=>"$url_cgi?$PageName{RssPage}", class=>"wiki", title=>&Resource('GoToRssPageLink'), type=>'application/xml'};  
     push @link, {rel=>'search', href=>"$url_cgi?$PageName{SearchPage}", class=>'wiki', title=>&Resource('GoToSearchPageLink')};  
     push @link, {rel=>'help', href=>"$url_cgi?WikiHelp", class=>'wiki', title=>&Resource('GoToWikiHelpLink')};  
     push @link, {rel=>'copyright', href=>"$url_cgi?WikiPageLicense", class=>'wiki', title=>&Resource('GoToWikiPageLicenseLink')};  
     push @link, {rel=>'jump', href=>qq(javascript:var%20WikiName=prompt('Please%20input%20the%20WikiName:','','Jump%20to%20SuikaWiki');if(WikiName)%7B_content.location.href='$url_cgi%3F'+encodeURIComponent(WikiName)%7D), class=>'wiki-cmd', title=>&Resource('JumpToLink')};  
     push @link, {rel=>'jump', href=>qq(javascript:var%20WikiName=prompt('Please%20input%20the%20WikiName:','','Jump%20to%20SuikaWiki');if(WikiName)%7B_content.location.href='$url_cgi%3Fmycmd=edit;mypage='+encodeURIComponent(WikiName)%7D), class=>'wiki-cmd', title=>&Resource('JumpToEditLink')};  
     push @link, {rel=>'lucky', href=>"$url_cgi?mycmd=RandomJump;x-param=@{[time.[0..9]->[rand 10]]}", class=>'wiki randomlink', title=>&Resource('GoSomewhereLink')};  
     push @link, {rel=>'history', href=>$uri{cvs_wikipage}.do{my $s=$page;$s=~s/(.)/sprintf '%02X', ord $1/ges;$s}.'.txt', title=>&Resource('ViewHistoryOfThisPageLink'),hreflang=>'en'} if $uri{cvs_wikipage};  
     push @link, {rel=>'history', href=>"$url_cgi?mycmd=diff;mypage=@{[&encode($page)]}", title=>&Resource('ViewDiffOfThisPageLink'), class=>'wiki-command'} if $wiki::diff::UseDiff;  
     push @link, {rel=>'contents', href=>"$url_cgi?mycmd=map;mypage=@{[&encode($page)]}", title=>&Resource('ShowMapOfThisPageLink'), class=>'wiki-command'};  
     my ($Links, $links) = ('', '');  
     for my $e (@link) {  
         $links .= qq(<link);  
         $Links .= qq(Link: <$e->{href}>);  
         for my $attr (qw/rel rev href title class type hreflang charset/) {  
             $links .= qq( $attr="@{[&escape($e->{$attr})]}") if $e->{$attr};  
         }  
         for my $attr (qw/rel rev title/) {  
             $Links .= qq(; $attr="@{[do{$e->{$attr} =~ s/([\\\"])/\\$1/g; $e->{$attr}}]}") if $e->{$attr};  
         }  
         $links .= qq(>\n);  
         $Links .= qq(\n);  
     }  
     wantarray ? ($Links, $links) : $Links;  
 }  
   
297  sub escape {  sub escape {
298      my $s = shift;      my $s = shift;
299      $s =~ s|\x0D\x0A|\x0A|g;      $s =~ s|\x0D\x0A|\x0A|g;
# Line 383  sub unescape { Line 317  sub unescape {
317  sub convert_format ($$$;%) {  sub convert_format ($$$;%) {
318    my ($content, $d => $t, %option) = @_;    my ($content, $d => $t, %option) = @_;
319    &load_formatter ('format');    &load_formatter ('format');
320    my $f = $fmt{format}->{$d.'_to_'.$t};    my $f = SuikaWiki::Plugin->format_converter ($d => $t);
321    if (ref $f) {    if (ref $f) {
322      $option{content} = $content;      $option{content} = $content;
323        $option{from} = $d;
324        $option{to} = $t;
325      &$f ({}, bless (\%option, 'SuikaWiki::Plugin'));      &$f ({}, bless (\%option, 'SuikaWiki::Plugin'));
326    } elsif ($t =~ /HTML|xml/) {    } elsif ($t =~ /HTML|xml/) {
327      length $content ? '<pre>'.&escape($content).'</pre>' : '';      length $content ? '<pre>'.&escape($content).'</pre>' : '';
# Line 401  sub text_to_html { Line 337  sub text_to_html {
337            
338      ## Load constants      ## Load constants
339      my %const;      my %const;
340      if ($option{content_format} =~ /import="([^"]+)"/) {      if ($option{magic} =~ /import="([^"]+)"/) {
341        for (split /\s*,\s*/, $1) {        for (split /\s*,\s*/, $1) {
342          my $wp = $database{$_};          my $wp = $database{$_};
343          if ($wp =~ m!^\#\?SuikaWikiConst/1.0!) {          if ($wp =~ m!^\#\?SuikaWikiConst/(?:0.9|1.0)!) {
344            wiki::suikawikiconst::to_hash ($wp => \%const);            wiki::suikawikiconst::to_hash ($wp => \%const);
345          }          }
346        }        }
# Line 419  sub text_to_html { Line 355  sub text_to_html {
355          chomp;          chomp;
356          if (/^\*\*\*\*\*([^\x0D\x0A]*)/) {          if (/^\*\*\*\*\*([^\x0D\x0A]*)/) {
357              push @$toc, [5, "i$tocnum" => ($1 || $tocnum)];              push @$toc, [5, "i$tocnum" => ($1 || $tocnum)];
358              push(@result, splice(@saved), qq(<h6 @{[&id_and_name("i$tocnum")]}>) . &inline($1, const => \%const) . '</h6>');              push(@result, splice(@saved), qq(<h6 @{[&id_and_name("i$tocnum")]}>) . &inline($1, %option, const => \%const) . '</h6>');
359              $tocnum++;              $tocnum++;
360          } elsif (/^\*\*\*\*([^\x0D\x0A]*)/) {          } elsif (/^\*\*\*\*([^\x0D\x0A]*)/) {
361              push @$toc, [4, "i$tocnum" => ($1 || $tocnum)];              push @$toc, [4, "i$tocnum" => ($1 || $tocnum)];
362              push(@result, splice(@saved), qq(<h5 @{[&id_and_name("i$tocnum")]}>) . &inline($1, const => \%const) . '</h5>');              push(@result, splice(@saved), qq(<h5 @{[&id_and_name("i$tocnum")]}>) . &inline($1, %option, const => \%const) . '</h5>');
363              $tocnum++;              $tocnum++;
364          } elsif (/^\*\*\*([^\x0D\x0A]*)/) {          } elsif (/^\*\*\*([^\x0D\x0A]*)/) {
365              push @$toc, [3, "i$tocnum" => ($1 || $tocnum)];              push @$toc, [3, "i$tocnum" => ($1 || $tocnum)];
366              push(@result, splice(@saved), qq(<h4 @{[&id_and_name("i$tocnum")]}>) . &inline($1, const => \%const) . '</h4>');              push(@result, splice(@saved), qq(<h4 @{[&id_and_name("i$tocnum")]}>) . &inline($1, %option, const => \%const) . '</h4>');
367              $tocnum++;              $tocnum++;
368          } elsif (/^\*\*([^\x0D\x0A]*)/) {          } elsif (/^\*\*([^\x0D\x0A]*)/) {
369          # if (/^\*\*(.*)/) {          # if (/^\*\*(.*)/) {
370          # Walrus mod (6) end          # Walrus mod (6) end
371              push @$toc, [2, "i$tocnum" => ($1 || $tocnum)];              push @$toc, [2, "i$tocnum" => ($1 || $tocnum)];
372              push(@result, splice(@saved), qq(<h3 @{[&id_and_name("i$tocnum")]}>) . &inline($1, const => \%const) . '</h3>');              push(@result, splice(@saved), qq(<h3 @{[&id_and_name("i$tocnum")]}>) . &inline($1, %option, const => \%const) . '</h3>');
373              $tocnum++;              $tocnum++;
374          } elsif (/^\*([^\x0D\x0A]*)/) {          } elsif (/^\*([^\x0D\x0A]*)/) {
375              push @$toc, [1, "i$tocnum" => ($1 || $tocnum)];              push @$toc, [1, "i$tocnum" => ($1 || $tocnum)];
376              push(@result, splice(@saved), qq(<h2 @{[&id_and_name("i$tocnum")]}>) . &inline($1, const => \%const) . '</h2>');              push(@result, splice(@saved), qq(<h2 @{[&id_and_name("i$tocnum")]}>) . &inline($1, %option, const => \%const) . '</h2>');
377              $tocnum++;              $tocnum++;
378          } elsif (/^(={1,6})(.*)/) {          } elsif (/^(={1,6})(.*)/) {
379              &back_push('ol', length($1), \@saved, \@result);              &back_push('ol', length($1), \@saved, \@result);
380              push(@result, '<li>' . &inline($2, const => \%const) . '</li>');              push(@result, '<li>' . &inline($2, %option, const => \%const) . '</li>');
381          } elsif (/^(-{1,6})(.*)/) {          } elsif (/^(-{1,6})(.*)/) {
382            &back_push('ul', length($1), \@saved, \@result);            &back_push('ul', length($1), \@saved, \@result);
383            my ($pf, $l) = ('', $2);            my ($pf, $l) = ('', $2);
# Line 449  sub text_to_html { Line 385  sub text_to_html {
385              my $num = 0+$1;              my $num = 0+$1;
386              $pf = qq(<a name="anchor-$num" id="anchor-$num" class="anchor">[$num]</a>);              $pf = qq(<a name="anchor-$num" id="anchor-$num" class="anchor">[$num]</a>);
387            }            }
388            push(@result, '<li>' . $pf . &inline ($l, const => \%const) . '</li>');            push(@result, '<li>' . $pf . &inline ($l, %option, const => \%const) . '</li>');
389          } elsif (/^:([^:]+):(.*)/) {          } elsif (/^:([^:]+):(.*)/) {
390              &back_push('dl', 1, \@saved, \@result);              &back_push('dl', 1, \@saved, \@result);
391              push(@result, '<dt>' . &inline($1, const => \%const) . '</dt>', '<dd>' . &inline($2, const => \%const) . '</dd>');              push(@result, '<dt>' . &inline($1, %option, const => \%const) . '</dt>', '<dd>' . &inline($2, %option, const => \%const) . '</dd>');
392          } elsif (/^(?!>>\d)(>{1,5})(.*)/) {          } elsif (/^(?!>>\d)(>{1,5})(.*)/) {
393              &back_push('blockquote', length($1), \@saved, \@result);              &back_push('blockquote', length($1), \@saved, \@result);
394              push @result, "<p>";              push @result, "<p>";
395              push(@result, &inline($2, const => \%const));              push(@result, &inline($2, %option, const => \%const));
396              unshift @saved, "</p>";              unshift @saved, "</p>";
397          } elsif (/^\s*$/) {          } elsif (/^\s*$/) {
398              push(@result, splice(@saved));              push(@result, splice(@saved));
# Line 464  sub text_to_html { Line 400  sub text_to_html {
400              unshift(@saved, "</p>");              unshift(@saved, "</p>");
401          } elsif (/^(\s+.*)$/) {          } elsif (/^(\s+.*)$/) {
402              &back_push('pre', 1, \@saved, \@result);              &back_push('pre', 1, \@saved, \@result);
403              push(@result, &inline($1, const => \%const));              push(@result, &inline($1, %option, const => \%const));
404          } elsif (/^\,(.*?)[\x0D\x0A]*$/) {          } elsif (/^\,(.*?)[\x0D\x0A]*$/) {
405              &back_push('table', 1, \@saved, \@result);              &back_push('table', 1, \@saved, \@result);
406              #######              #######
# Line 480  sub text_to_html { Line 416  sub text_to_html {
416                          $colspan[$i]++;                          $colspan[$i]++;
417                      }                      }
418                      $colspan[$i] = ($colspan[$i] > 1) ? sprintf(' colspan="%d"', $colspan[$i]) : '';                      $colspan[$i] = ($colspan[$i] > 1) ? sprintf(' colspan="%d"', $colspan[$i]) : '';
419                      $value[$i] = sprintf('<td%s%s>%s</td>', $align[$i], $colspan[$i], &inline($value[$i], const => \%const));                      $value[$i] = sprintf('<td%s%s>%s</td>', $align[$i], $colspan[$i], &inline($value[$i], %option, const => \%const));
420                  } else {                  } else {
421                      $value[$i] = '';                      $value[$i] = '';
422                  }                  }
# Line 497  sub text_to_html { Line 433  sub text_to_html {
433          } elsif (/^\[([0-9]+)\](.*)$/ && !$main::_EMBEDED) {          } elsif (/^\[([0-9]+)\](.*)$/ && !$main::_EMBEDED) {
434            my $num = 0+$1;            my $num = 0+$1;
435            push @result, qq(<a name="anchor-$num" id="anchor-$num" class="anchor">[$num]</a>);            push @result, qq(<a name="anchor-$num" id="anchor-$num" class="anchor">[$num]</a>);
436            push @result, &inline ($2, const => \%const);            push @result, &inline ($2, %option, const => \%const);
437          } else {          } else {
438              push(@result, &inline($_, const => \%const));              push(@result, &inline($_, %option, const => \%const));
439          }          }
440      }      }
441      push(@result, splice(@saved));      push(@result, splice(@saved));
# Line 528  sub back_push { Line 464  sub back_push {
464  sub inline ($;%) {  sub inline ($;%) {
465      my ($line, %option) = @_;      my ($line, %option) = @_;
466      $line = &escape($line);      $line = &escape($line);
467      $line =~ s{$embed_command{form}}{&make_custom_form ($1, $2, $3, $4)}ge;      $line =~ s{$embed_command{form}}{&make_custom_form ($1, $2, $3, $4, \%option)}ge;
468      $line =~ s{\[(INS|DEL|SUP|SUB|VAR|CODE|KBD|SAMP|DFN)(?:\(([A-Za-z0-9\x20-]+)\))?\[(.+?)\]\]}{<@{[lc $1]}@{[$2 ? qq( class="$2") : '']}>$3</@{[lc $1]}>}g;      $line =~ s{\[(INS|DEL|SUP|SUB|VAR|CODE|KBD|SAMP|DFN)(?:\(([A-Za-z0-9\x20-]+)\))?\[(.+?)\]\]}{<@{[lc $1]}@{[$2 ? qq( class="$2") : '']}>$3</@{[lc $1]}>}g;
469      $line =~ s:\[(WEAK)\[(.+?)\]\]:<span class="@{[lc $1]}">$2</span>:g;      $line =~ s:\[(WEAK)\[(.+?)\]\]:<span class="@{[lc $1]}">$2</span>:g;
470      $line =~ s:\[ABBR\[([^]]+)\] \[([^]]+)\]\]:<acronym title="$2">$1</acronym>:g;      $line =~ s:\[ABBR\[([^]]+)\] \[([^]]+)\]\]:<acronym title="$2">$1</acronym>:g;
# Line 560  sub inline ($;%) { Line 496  sub inline ($;%) {
496  sub make_wikilink ($%) {  sub make_wikilink ($%) {
497    my ($ename, %option) = @_;    my ($ename, %option) = @_;
498    my $name = &unescape ($ename);    my $name = &unescape ($ename);
499    $option{latest} = $option{latest} ? qq(mycmd=read;x-param=@{[time.[0..9]->[rand 10]]};mypage=) : '';    $option{latest} = $option{latest} ? qq(mycmd=default;x-param=@{[time.[0..9]->[rand 10]]};mypage=) : '';
500    if ($database{$name}) {    if ($database{$name}) {
501      my $subject = &escape (&get_subjectline ($name, delimiter => ''));      my $subject = &escape (&get_subjectline ($name, delimiter => ''));
502      if ($option{anchor}) {      if ($option{anchor}) {
# Line 612  sub make_urilink ($;%) { Line 548  sub make_urilink ($;%) {
548    }    }
549  }  }
550    
551  {my $FormIndex = 0;  {my %FormIndex;
552  sub make_custom_form ($$$$) {  sub make_custom_form ($$$$%) {
553      my ($wfname, $definition, $template, $option) = @_;      my ($wfname, $definition, $template, $foption, $option) = @_;
554      ## $template and $option is currently not used in this procedure.      ## $template is currently not used in this procedure.
555      unless ($main::_EMBEDED) {      #unless ($main::_EMBEDED) {
556          $FormIndex++;          $FormIndex{$option->{page}}++;
557          if (length $definition) {          if (length $definition) {
558              my $param = bless {}, 'SuikaWiki::Plugin';              my $param = bless {depth=>10}, 'SuikaWiki::Plugin';
559              my $lastmodified = $database->mtime ($form{mypage});              my $lastmodified = $database->mtime ($option->{page});
560              &load_formatter (qw/form_input form_option/);              &load_formatter (qw/form_input form_option/);
561              $definition = &unescape ($definition);              $definition = &unescape ($definition);
562              $definition =~ s/\\(.)/$1/g;              $definition =~ s/\\(.)/$1/g;
563              $option = &unescape ($option);              $foption = &unescape ($foption);
564              $option =~ s/\\(.)/$1/g;              $foption =~ s/\\(.)/$1/g;
565              $fmt{form_option}->replace ($option, $param);              $fmt{form_option}->replace ($foption, $param);
566              $param->{output}->{form} = 1 unless defined $param->{output}->{form};              $param->{output}->{form} = 1 unless defined $param->{output}->{form};
567                $param->{output}->{form} = 0 if $main::_EMBEDED;
568              $definition .= ' %submit;' if $definition !~ /%submit/ && !$param->{output}->{nosubmit} && $param->{output}->{form};              $definition .= ' %submit;' if $definition !~ /%submit/ && !$param->{output}->{nosubmit} && $param->{output}->{form};
569              my $target_page = $param->{output}->{page} || $form{mypage};              $param->{output}->{page} ||= $option->{page};
570              $param->{form_disabled} = 1 if $database->meta (IsFrozen => $form{mypage});              $param->{form_disabled} = 1 if $database->meta (IsFrozen => $option->{page});
571              my $target_form = $param->{output}->{id};              my $target_form = $param->{output}->{id};
572              my $r = '';              my $r = '';
573              $r = <<EOH if $param->{output}->{form};              $r = <<EOH if $param->{output}->{form};
574  <form method="post" action="$url_cgi" id="wikiform-$FormIndex" class="wikiform">  <form method="post" action="$url_cgi" id="wikiform-$FormIndex{$option->{page}}" class="wikiform">
575    <input type="hidden" name="mycmd" value="@{[$param->{form_disabled}?'read':'wikiform']}">    <input type="hidden" name="mycmd" value="@{[$param->{form_disabled}?'default':'wikiform']}" />
576    <input type="hidden" name="mypage" value="@{[&escape($target_page)]}">    <input type="hidden" name="mypage" value="@{[&escape($param->{output}->{page})]}" />
577    <input type="hidden" name="myLastModified" value="$lastmodified">    <input type="hidden" name="myLastModified" value="$lastmodified" />
578    <input type="hidden" name="mytouch" value="on">    <input type="hidden" name="mytouch" value="on" />
579    <input type="hidden" name="@{[$target_form? qq(wikiform_targetform" value="@{[&escape($target_form)]}) : qq(wikiform_index" value="$FormIndex)]}">    <input type="hidden" name="@{[$target_form? qq(wikiform_targetform" value="@{[&escape($target_form)]}) : qq(wikiform_index" value="$FormIndex{$option->{page}})]}" />
580  EOH  EOH
581              $r .= qq(<a name="wikiform-$FormIndex"></a>) if $UA =~ m#Mozilla/[12]\.#;              $r .= qq(<a name="wikiform-$FormIndex{$option->{page}}"></a>) if $UA =~ m#Mozilla/[12]\.#;
582              $r .= $fmt{form_input}->replace ($definition, $param);              $r .= $fmt{form_input}->replace ($definition, $param);
583              $r .= "</form>\n" if $param->{output}->{form};              $r .= "</form>\n" if $param->{output}->{form};
584              $r;              $r;
585         } else {  ## No input-interface WikiForm         } else {  ## No input-interface WikiForm
586             qq(<a id="wikiform-$FormIndex" name="wikiform-$FormIndex"><!-- #form --></a>);           qq(<a id="wikiform-$FormIndex{$option->{page}}" name="wikiform-$FormIndex{$option->{page}}"><!-- #form --></a>);
587         }         }
588      } else {      #} else {
589          qq(<ins class="wiki-error">@{[&Resource('Error:WikiForm:EmbedIsNotSupported',escape=>1)]}</ins>);      #    qq(<ins class="wiki-error">@{[&Resource('Error:WikiForm:EmbedIsNotSupported',escape=>1)]}</ins>);
590      }      #}
591  }}  }}
592    
 sub print_message {  
     my ($msg) = @_;  
     print qq(<p><strong>@{[&escape($msg)]}</strong></p>);  
 }  
   
593  sub init_form {  sub init_form {
594      ## TODO: Support multipart/form-data      ## TODO: Support multipart/form-data
595      my $query = '';      my $query = '';
# Line 668  sub init_form { Line 600  sub init_form {
600      if ($main::ENV{REQUEST_METHOD} ne 'POST' && $main::ENV{QUERY_STRING} && $main::ENV{QUERY_STRING} !~ /[&;=]/) {      if ($main::ENV{REQUEST_METHOD} ne 'POST' && $main::ENV{QUERY_STRING} && $main::ENV{QUERY_STRING} !~ /[&;=]/) {
601        my $query = &decode($main::ENV{QUERY_STRING});        my $query = &decode($main::ENV{QUERY_STRING});
602        $query = &code_convert(\$query, $kanjicode);        $query = &code_convert(\$query, $kanjicode);
       if ($page_command{$query}) {  
         $form{mycmd} = $page_command{$query};  
603          $form{mypage} = $query;          $form{mypage} = $query;
604        } else {          $form{mycmd} = 'default';
         $form{mypage} = $query;  
         $form{mycmd} = $database{$form{mypage}} ? 'read' : 'edit';  
       }  
605      } else {      } else {
606        for (split /[;&]/, $query) {        for (split /[;&]/, $query) {
607          if (my ($n, $v) = split /=/, $_, 2) {          if (my ($n, $v) = split /=/, $_, 2) {
# Line 686  sub init_form { Line 613  sub init_form {
613          $form{mypage} = $form{epage};          $form{mypage} = $form{epage};
614          $form{mypage} =~ s/([0-9A-F]{2})/ord hex $1/g;          $form{mypage} =~ s/([0-9A-F]{2})/ord hex $1/g;
615        }        }
       if ($page_command{$form{mypage}} && $form{mycmd} eq 'read') {  
         $form{mypage} = &code_convert(\$form{mypage}, $kanjicode);  
         $form{mycmd} = $page_command{$form{mypage}};  
       }  
616      }      }
617      $form{mypage} ||= 'HomePage';      $form{mypage} ||= $PageName{FrontPage};
618      $form{mypage} =~ tr/\x00-\x1F\x7F//d;      $form{mypage} =~ tr/\x00-\x1F\x7F//d;
619      $form{mycmd} ||= 'read';      $form{mycmd} ||= 'default';
620    
621      # mypreview_edit        -> do_edit, with preview.      # mypreview_edit        -> do_edit, with preview.
622      # mypreview_adminedit   -> do_adminedit, with preview.      # mypreview_adminedit   -> do_adminedit, with preview.
# Line 716  sub init_form { Line 639  sub init_form {
639      $form{myname} = &code_convert(\$form{myname}, $kanjicode);      $form{myname} = &code_convert(\$form{myname}, $kanjicode);
640  }  }
641    
 {my %SubjectLine;  
642  sub get_subjectline {  sub get_subjectline {
643      my ($page, %option) = @_;      my ($page, %option) = @_;
644      unless (defined $SubjectLine{$page}) {      my $SubjectLine = SuikaWiki::Plugin->cache ('headline');
645        unless (defined $SubjectLine->{$page}) {
646        if (not &is_editable($page)) {        if (not &is_editable($page)) {
647          $SubjectLine{$page} = "";          $SubjectLine->{$page} = "";
648        } else {        } else {
649          $SubjectLine{$page} = $database{$page};          $SubjectLine->{$page} = do {
650          $SubjectLine{$page} =~ s!^\#\?[^\x0A\x0D]+[\x0A\x0D]*!!s;            my $s=$database{$page};
651          $SubjectLine{$page} =~ s/\x0D?\x0A.*//s;            $s =~ s!^\#\?[^\x0A\x0D]+[\x0A\x0D]*!!s;
652              $s =~ s/\x0D?\x0A.*//s;
653            $s};
654        }        }
655      }      }
656      if (length $SubjectLine{$page}) {      if (length $SubjectLine->{$page}) {
657        $option{delimiter} = defined $option{delimiter} ? $option{delimiter} : &Resource('Title-Summary Delimiter');        $option{delimiter} = defined $option{delimiter} ? $option{delimiter} : &Resource('Title-Summary Delimiter');
658        $option{delimiter}.$SubjectLine{$page}.$option{tail};        $option{delimiter}.$SubjectLine->{$page}.$option{tail};
659      } else {      } else {
660        '';        '';
661      }      }
662  }}  }
663    
664  sub open_db {  sub open_db {
665      if ($modifier_dbtype eq 'dbmopen') {      if ($modifier_dbtype eq 'dbmopen') {
666          dbmopen(%database, $PathTo{WikiDataBase}, 0666) or &print_error("(dbmopen) $PathTo{WikiDataBase}");          dbmopen(%database, $PathTo{WikiDataBase}, 0666) or die "(dbmopen) $PathTo{WikiDataBase}";
667      } elsif ($modifier_dbtype eq 'AnyDBM_File') {      } elsif ($modifier_dbtype eq 'AnyDBM_File') {
668          eval q{use AnyDBM_File};          eval q{use AnyDBM_File};
669          tie(%database, "AnyDBM_File", $PathTo{WikiDataBase}, O_RDWR|O_CREAT, 0666) or &print_error("(tie AnyDBM_File) $PathTo{WikiDataBase}");          tie(%database, "AnyDBM_File", $PathTo{WikiDataBase}, O_RDWR|O_CREAT, 0666) or die ("(tie AnyDBM_File) $PathTo{WikiDataBase}");
670      } elsif ($modifier_dbtype eq 'Yuki::YukiWikiDB') {      } elsif ($modifier_dbtype eq 'Yuki::YukiWikiDB') {
671          eval q{use Yuki::YukiWikiDB};          eval q{use Yuki::YukiWikiDB};
672          tie(%database, "Yuki::YukiWikiDB", $PathTo{WikiDataBase}) or &print_error("(tie Yuki::YukiWikiDB) $PathTo{WikiDataBase}");          tie(%database, "Yuki::YukiWikiDB", $PathTo{WikiDataBase}) or die ("(tie Yuki::YukiWikiDB) $PathTo{WikiDataBase}");
673      } else {    ## Yuki::YukiWikiDB || Yuki::YukiWikiDBMeta      } else {    ## Yuki::YukiWikiDB || Yuki::YukiWikiDBMeta
674          eval qq{use $modifier_dbtype};          eval qq{use $modifier_dbtype};
675          $database = tie(%database, $modifier_dbtype => $PathTo{WikiDataBase}, -lock => 2, -backup => $wiki::diff::UseDiff) or &print_error("(tie $modifier_dbtype) $PathTo{WikiDataBase}");          $database = tie(%database, $modifier_dbtype => $PathTo{WikiDataBase}, -lock => 2, -backup => $wiki::diff::UseDiff) or die ("(tie $modifier_dbtype) $PathTo{WikiDataBase}");
676      }      }
677  }  }
678    
# Line 769  sub editform (@) { Line 694  sub editform (@) {
694    my $magic = '';    my $magic = '';
695    $magic = $1 if $option{content} =~ m/^([^\x0A\x0D]+)/s;    $magic = $1 if $option{content} =~ m/^([^\x0A\x0D]+)/s;
696        
697    my $selected = 'read';    my $selected = 'default';
698    if ($form{after_edit_cmd}) {    if ($form{after_edit_cmd}) {
699      $selected = $form{after_edit_cmd};      $selected = $form{after_edit_cmd};
700    } elsif ($magic =~ /Const|Config|CSS/) {    } elsif ($magic =~ /Const|Config|CSS/) {
# Line 777  sub editform (@) { Line 702  sub editform (@) {
702    }    }
703    my $afteredit = <<EOH;    my $afteredit = <<EOH;
704  <select name="after_edit_cmd">  <select name="after_edit_cmd">
705    <option value="default" label="@{[&Resource('Edit:SaveAndDefault',escape=>1)]}"@{[$selected eq 'default' ? ' selected="selected"':'']}>@{[&Resource('Edit:SaveAndDefault',escape=>1)]}</option>
706  <option value="read" label="@{[&Resource('Edit:SaveAndView',escape=>1)]}"@{[$selected eq 'read' ? ' selected="selected"':'']}>@{[&Resource('Edit:SaveAndView',escape=>1)]}</option>  <option value="read" label="@{[&Resource('Edit:SaveAndView',escape=>1)]}"@{[$selected eq 'read' ? ' selected="selected"':'']}>@{[&Resource('Edit:SaveAndView',escape=>1)]}</option>
707  <option value="edit" label="@{[&Resource('Edit:SaveAndEdit',escape=>1)]}"@{[$selected eq 'edit' ? ' selected="selected"':'']}>@{[&Resource('Edit:SaveAndEdit',escape=>1)]}</option>  <option value="edit" label="@{[&Resource('Edit:SaveAndEdit',escape=>1)]}"@{[$selected eq 'edit' ? ' selected="selected"':'']}>@{[&Resource('Edit:SaveAndEdit',escape=>1)]}</option>
708  </select>  </select>
709  EOH  EOH
710    $f .= <<"EOD";    $f .= <<"EOD";
711  <form action="$uri{wiki}" method="post">  <form action="$uri{wiki}" method="post">
712      @{[ $option{conflict} ? '' : qq(<label><input type="submit" name="mypreview_write" value="@{[&Resource('Edit:Save',escape=>1)]}"><kbd>S</kbd></label>) ]}      @{[ $option{conflict} ? '' : qq(<label><input type="submit" name="mypreview_write" value="@{[&Resource('Edit:Save',escape=>1)]}" /><kbd>S</kbd></label>) ]}
713      @{[ $option{admin} ? qq(<label>@{[&Resource('Edit:Password=',escape=>1)]}<input type="password" name="mypassword" value="" size="10"></label>) : "" ]} [@{[&get_new_anchor_index($option{content})]}]<br>      @{[ $option{admin} ? qq(<label>@{[&Resource('Edit:Password=',escape=>1)]}<input type="password" name="mypassword" value="" size="10" /></label>) : "" ]} [@{[&get_new_anchor_index($option{content})]}]<br />
714      <input type="hidden" name="myLastModified" value="$option{last_modified}">      <input type="hidden" name="myLastModified" value="$option{last_modified}" />
715      <input type="hidden" name="mypage" value="@{[&escape($form{mypage})]}">      <input type="hidden" name="mypage" value="@{[&escape($form{mypage})]}" />
716      <textarea cols="@{[&Resource('Edit:Form:Cols')+0||80]}" rows="@{[&Resource('Edit:Form:Rows')+0||20]}" name="mymsg" tabindex="1">@{[&escape($option{content})]}</textarea><br>      <textarea cols="@{[&Resource('Edit:Form:Cols')+0||80]}" rows="@{[&Resource('Edit:Form:Rows')+0||20]}" name="mymsg" tabindex="1">@{[&escape($option{content})]}</textarea><br />
717  @{[  @{[
718      $option{admin} ?      $option{admin} ?
719      qq(      qq(
720      <label><input type="radio" name="myfrozen" value="1" @{[$frozen ? qq(checked="checked") : ""]}>@{[&Resource('Edit:Freeze',escape=>1)]}</label>      <label><input type="radio" name="myfrozen" value="1" @{[$frozen ? qq(checked="checked") : ""]} />@{[&Resource('Edit:Freeze',escape=>1)]}</label>
721      <label><input type="radio" name="myfrozen" value="0" @{[$frozen ? "" : qq(checked="checked")]}>@{[&Resource('Edit:DontFreeze',escape=>1)]}</label><br>)      <label><input type="radio" name="myfrozen" value="0" @{[$frozen ? "" : qq(checked="checked")]} />@{[&Resource('Edit:DontFreeze',escape=>1)]}</label><br />)
722      : ""      : ""
723  ]}  ]}
724  @{[  @{[
725      $option{conflict} ? "" :      $option{conflict} ? "" :
726      qq(      qq(
727          <label><input type="checkbox" name="mytouch" value="on" checked="checked">@{[&Resource('Edit:UpdateTimeStamp',escape=>1)]}</label><br>          <label><input type="checkbox" name="mytouch" value="on" checked="checked" />@{[&Resource('Edit:UpdateTimeStamp',escape=>1)]}</label><br />
728          <label><input type="submit" name="mypreview_write" value="@{[&Resource('Edit:Save',escape=>1)]}" accesskey="S"><kbd>S</kbd></label>          <label><input type="submit" name="mypreview_write" value="@{[&Resource('Edit:Save',escape=>1)]}" accesskey="S" /><kbd>S</kbd></label>
729         $afteredit         $afteredit
730      )      )
731  ]}  ]}
# Line 810  EOD Line 736  EOD
736    
737  sub is_editable {  sub is_editable {
738      my ($page) = @_;      my ($page) = @_;
739      $page =~ /[\x00-\x1F\x7F]/ ? 0 : 1;      $page =~ /[\x00-\x20\x7F]/ ? 0 : 1;
740  }  }
741    
742  sub decode {  sub decode {
# Line 822  sub decode { Line 748  sub decode {
748    
749  sub encode {  sub encode {
750    my $s = shift;    my $s = shift;
751    $s =~ s/([^0-9A-Za-z_-])/sprintf '%%%02X', ord $1/g;    $s =~ s/([^0-9A-Za-z_-])/sprintf '%%%02X', ord $1/ge;
752    $s;    $s;
753  }  }
754    
# Line 858  sub frozen_reject { Line 784  sub frozen_reject {
784          # You are admin.          # You are admin.
785          return 0;          return 0;
786      } else {      } else {
787          &print_error(&Resource('Error:PasswordIsIncorrect'));          &_do_view_msg (-view => '-error', -page => $form{mypage},
788          return 1;                         error_message => &Resource ('Error:PasswordIsIncorrect'));
789            exit;
790      }      }
791  }  }
792    
# Line 900  sub do_comment { Line 827  sub do_comment {
827          $form{mymsg} = $content;          $form{mymsg} = $content;
828          $form{mytouch} = 'on';          $form{mytouch} = 'on';
829          &do_write;          &do_write;
830      } else {      } else {    ## Don't write
831          $form{mycmd} = 'read';          $form{mycmd} = 'default';
832          &do_read;          &do_view;
833      }      }
834  }  }
835    
# Line 921  sub embedded_to_html { Line 848  sub embedded_to_html {
848          my $lastmodified = $database->mtime ($form{mypage});          my $lastmodified = $database->mtime ($form{mypage});
849          return <<"EOD";          return <<"EOD";
850  <form action="$url_cgi" method="post" id="x-comment-@{[++$CommentIndex]}" class="comment"><p>  <form action="$url_cgi" method="post" id="x-comment-@{[++$CommentIndex]}" class="comment"><p>
851      <input type="hidden" name="mycmd" value="comment">      <input type="hidden" name="mycmd" value="comment" />
852      <input type="hidden" name="mypage" value="$form{mypage}">      <input type="hidden" name="mypage" value="$form{mypage}" />
853      <input type="hidden" name="myLastModified" value="$lastmodified">      <input type="hidden" name="myLastModified" value="$lastmodified" />
854      <input type="hidden" name="mytouch" value="on">      <input type="hidden" name="mytouch" value="on" />
855      <input type="hidden" name="comment_index" value="$CommentIndex">      <input type="hidden" name="comment_index" value="$CommentIndex" />
856      @{[&Resource('WikiForm:WikiComment:Name=',escape=>1)]}      @{[&Resource('WikiForm:WikiComment:Name=',escape=>1)]}
857      <input type="text" name="myname" value="" size="10" class="comment-name">      <input type="text" name="myname" value="" size="10" class="comment-name" />
858      <input type="text" name="mymsg" value="" size="60" class="comment-msg">      <input type="text" name="mymsg" value="" size="60" class="comment-msg" />
859      <input type="submit" value="@{[&Resource('WikiForm:Add',escape=>1)]}" title="@{[&Resource('WikiForm:AddLong',escape=>1)]}" class="comment-submit">      <input type="submit" value="@{[&Resource('WikiForm:Add',escape=>1)]}" title="@{[&Resource('WikiForm:AddLong',escape=>1)]}" class="comment-submit" />
860  </p></form>  </p></form>
861  EOD  EOD
862       } else {       } else {
863          return <<"EOD";          return <<"EOD";
864  <del><form action="$url_cgi" method="get">  <del><form action="$url_cgi" method="get">
865      <input type="hidden" name="mycmd" value="read">      <input type="hidden" name="mycmd" value="default" />
866      <input type="hidden" name="mypage" value="$form{mypage}">      <input type="hidden" name="mypage" value="$form{mypage}" />
867      @{[&Resource('WikiForm:WikiComment:Name=',escape=>1)]}      @{[&Resource('WikiForm:WikiComment:Name=',escape=>1)]}
868      <input type="text" name="myname" value="" size="10" disabled="disabled">      <input type="text" name="myname" value="" size="10" disabled="disabled" />
869      <input type="text" name="mymsg" value="" size="60" disabled="disabled">      <input type="text" name="mymsg" value="" size="60" disabled="disabled" />
870  </form></del>  </form></del>
871  EOD  EOD
872      }      }
# Line 948  EOD Line 875  EOD
875    } elsif ($embedded =~ /^\[\[\#embed:(.+)\]\]$/) {    } elsif ($embedded =~ /^\[\[\#embed:(.+)\]\]$/) {
876      my ($name, $r) = ($1, '');      my ($name, $r) = ($1, '');
877      if ($main::_EMBEDED != 1) {      if ($main::_EMBEDED != 1) {
878        my ($content, $cf) = ($database{$name}, 'SuikaWiki/0.9');        my ($cf, $content) = SuikaWiki::Plugin->magic_and_conten ($database{$name});
879        $cf = $1 if $content =~ s!^(?:[\#<]\?|/\*\s*)?([A-Z][A-Za-z0-9-]+/[0-9.]+(?:[^0-9.][^\x0D\x0A]*)?)[\x0D\x0A]+!!s;        $cf ||= '#?SuikaWiki/0.9';
880        if ($cf =~ m!^(?:\#\?)?SuikaWiki/0.9(?:$|\s)!) {        if ($cf =~ m!^#\?SuikaWiki/0.9(?:$|\s)!) {
881          $main::_EMBEDED = 1;          $main::_EMBEDED = 1;
882          $r = &text_to_html ($content, content_format => $cf);          $r = &text_to_html ($content, magic => $cf, page => $name);
883          $main::_EMBEDED = 0;          $main::_EMBEDED = 0;
884        } elsif (length $content) {        } elsif (length $content) {
885          $r = "<pre>@{[&escape ($content)]}</pre>";          $r = "<pre>@{[&escape ($content)]}</pre>";
886        } else {        } else {
887          $r = &text_to_html ("[INS[\n[[$name]]: @{[&Resource('Embed:PageNotFound')]}\n]INS]\n", content_format => 'SuikaWiki/0.9');          $r = &text_to_html ("[INS[\n[[$name]]: @{[&Resource('Embed:PageNotFound')]}\n]INS]\n", magic => '#?SuikaWiki/0.9');
888        }        }
889      } else {    ## nested #EMBED      } else {    ## nested #EMBED
890        $r = &text_to_html ("[INS[\n[[$name]]: @{[&Resource('Embed:Nested',escape=>1)]}\n]INS]\n", content_format => 'SuikaWiki/0.9');        $r = &text_to_html ("[INS[\n[[$name]]: @{[&Resource('Embed:Nested',escape=>1)]}\n]INS]\n", magic => '#?SuikaWiki/0.9');
891      }      }
892      return qq(<blockquote title="@{[&escape($name)]}" class="wiki-embed">$r<div class="cite-note">¡Ø<cite><a href="$url_cgi?@{[&encode($name)]}" class="wiki">@{[&escape($name)]}</a></cite>¡Ù</div></blockquote>);      return qq(<blockquote title="@{[&escape($name)]}" class="wiki-embed">$r<div class="cite-note">¡Ø<cite><a href="$url_cgi?@{[&encode($name)]}" class="wiki">@{[&escape($name)]}</a></cite>¡Ù</div></blockquote>);
893    } elsif ($embedded =~ /^\[\[\#randomlink:(.+)\]\]$/) {    } elsif ($embedded =~ /^\[\[\#randomlink:(.+)\]\]$/) {
# Line 994  sub do_wikiform { Line 921  sub do_wikiform {
921              || $i == $form{wikiform_index}) {              || $i == $form{wikiform_index}) {
922              $template =~ s/\\(.)/$1/g;              $template =~ s/\\(.)/$1/g;
923              $option =~ s/\\(.)/$1/g;              $option =~ s/\\(.)/$1/g;
924              my $param = bless {}, 'SuikaWiki::Plugin';              my $param = bless {depth=>10}, 'SuikaWiki::Plugin';
925              $param->{page} = $form{mypage};              $param->{page} = $form{mypage};
926              $param->{form_index} = $i;              $param->{form_index} = $i;
927              $param->{form_name} = $wfname;              $param->{form_name} = $wfname;
# Line 1004  sub do_wikiform { Line 931  sub do_wikiform {
931              $param->{default_name} ||= &Resource('WikiForm:WikiComment:DefaultName');              $param->{default_name} ||= &Resource('WikiForm:WikiComment:DefaultName');
932              $fmt{form_option}->replace ($option, $param);              $fmt{form_option}->replace ($option, $param);
933              my $t = 1;              my $t = 1;
934              for (@{$param->{require}||[]}) {              for (keys %{$param->{require}||{}}) {
935                  (undef $t, last) unless length $param->{argv}->{'wikiform__'.$_};                  (undef $t, last) unless length $param->{argv}->{'wikiform__'.$_};
936              }              }
937              $t = $fmt{form_template}->replace ($template, $param) if $t;              $t = $fmt{form_template}->replace ($template, $param) if $t;
# Line 1019  sub do_wikiform { Line 946  sub do_wikiform {
946                    if $param->{anchor_index_};  ## $anchor is used!                    if $param->{anchor_index_};  ## $anchor is used!
947              }              }
948              $form{__wikiform_anchor_index} = $i;              $form{__wikiform_anchor_index} = $i;
949              undef $form{wikiform_targetform};  ## make sure never to match              undef $form{wikiform_targetform};  ## Make sure never to match
950              undef $form{wikiform_index};       ## with WikiForm in rest of page              undef $form{wikiform_index};       ## with WikiForm in rest of page!
951          }          }
952          $i++; $embed;          $i++; $embed;
953      }ge;      }ge;
# Line 1033  sub do_wikiform { Line 960  sub do_wikiform {
960          $form{mymsg} = $content;          $form{mymsg} = $content;
961          $form{mytouch} = 'on';          $form{mytouch} = 'on';
962          &do_write;          &do_write;
963      } else {      } else {    ## Don't write!
964          $form{mycmd} = 'read';          $form{mycmd} = 'default';
965          &do_read;          &do_view;
966      }      }
967  }  }
968    
# Line 1050  sub code_convert { Line 977  sub code_convert {
977      return $$contentref;      return $$contentref;
978  }  }
979    
 sub do_rss {  
     eval q{use Yuki::RSS};  
     my $rss = new Yuki::RSS(  
         version => '1.0',  
         encoding => &get_charset_name ($kanjicode),  
     );  
     my $scheme = 'http';  
     $scheme = lc $1 if $main::ENV{SERVER_PROTOCOL} =~ m#([A-Za-z0-9+.%-]+)#;  
     my $myuri = "$scheme://$main::ENV{SERVER_NAME}:$main::ENV{SERVER_PORT}$url_cgi";  
     $rss->stylesheet (  
       href      => $myuri . "?mycmd=TEXT_CSS;mypage=WikiStyle:RSS",  
       type      => 'text/css',  
     );  
     $rss->channel(  
         title   => &Resource ('RSS:WikiTitle'),  
         link    => $myuri,  
         description     => &Resource ('RSS:WikiDescription'),  
         'dc:language'   => $lang,  
     );  
     my $recentchanges = $database{RecentChanges};  
     my $count = 0;  
     foreach (split(/\n/, $recentchanges)) {  
         last if ($count >= 15);  
         if (/\[\[([^]]+)\]\]/) {  
           my $title = $1;  
           $rss->add_item (  
             title       => &escape($title),  
             link        => $myuri . '?' . &encode($title),  
             description => &escape(&get_subjectline($title,delimiter=>'')),  
             'dc:date'   => $database->mtime ($title),  
           );  
           $count++;  
         }  
     }  
     # print RSS information (as XML).  
     print <<"EOD"  
 Content-type: application/xml; charset=@{[&get_charset_name ($kanjicode)]}  
   
 @{[$rss->as_string]}  
 EOD  
 }  
   
980  sub _rfc3339_date ($) {  sub _rfc3339_date ($) {
981    my @time = gmtime (shift);    my @time = gmtime (shift);
982    sprintf '%04d-%02d-%02dT%02d:%02d:%02d+00:00', $time[5]+1900,$time[4]+1,@time[3,2,1,0];    sprintf '%04d-%02d-%02dT%02d:%02d:%02d+00:00', $time[5]+1900,$time[4]+1,@time[3,2,1,0];
983  }  }
984    
 sub is_exist_page { $use_exists ? exists ($database{$_[0]}) : $database{$_[0]} }  
 sub __get_database ($) { $database{ $_[0] } }  
   
985  my %_Resource;  my %_Resource;
986  sub Resource ($;%) {  sub Resource ($;%) {
987    my ($s, %o) = @_;    my ($s, %o) = @_;
# Line 1195  sub add ($) { Line 1077  sub add ($) {
1077    return unless $UseLog;    return unless $UseLog;
1078    $s =~ s/([\x00-\x08\x0A-\x1F\x25\x7F-\xFF])/sprintf '%%%02X', unpack 'C', $1/ge;    $s =~ s/([\x00-\x08\x0A-\x1F\x25\x7F-\xFF])/sprintf '%%%02X', unpack 'C', $1/ge;
1079    my %ua;    my %ua;
1080    for (split /\n/, &main::__get_database($main::PageName{UserAgentList})) {    for (split /\n/, $main::database{$main::PageName{UserAgentList}}) {
1081      if (/^-\[(\d+)\] (.+)$/) {      if (/^-\[(\d+)\] (.+)$/) {
1082        my ($t, $n) = ($1, $2);        my ($t, $n) = ($1, $2);
1083        $n =~ tr/\x0A\x0D//d;        $n =~ tr/\x0A\x0D//d;
# Line 1217  sub to_hash ($;$) { Line 1099  sub to_hash ($;$) {
1099    my $h = shift || {};    my $h = shift || {};
1100    my $val;    my $val;
1101    for my $line (split /\n/, $page) {    for my $line (split /\n/, $page) {
1102        next if $line =~ /^#/;
1103      $line =~ tr/\x0A\x0D//d;      $line =~ tr/\x0A\x0D//d;
1104      if ($val && $line =~ s/^\s+//) {      if ($val && $line =~ s/^\s+//) {
1105        $h->{$val} .= length $h->{$val} ? "\n" . $line : $line;        $h->{$val} .= length $h->{$val} ? "\n" . $line : $line;
# Line 1233  sub meta (@) {undef} Line 1116  sub meta (@) {undef}
1116  sub Yuki::YukiWikiDB2::meta (@) {undef}  sub Yuki::YukiWikiDB2::meta (@) {undef}
1117    
1118  package SuikaWiki::Plugin;  package SuikaWiki::Plugin;
1119    our $plugin_directory;    our ($plugin_directory, %List, %Index, %Cache);
1120    our %List;    push @main::INC, $plugin_directory.'/../..';
   our %Index;  
1121    
1122  sub escape ($$) { main::escape ($_[1]) }  sub escape ($$) { main::escape ($_[1]) }
1123  sub unescape ($$) { main::unescape ($_[1]) }  sub unescape ($$) { main::unescape ($_[1]) }
# Line 1245  sub __get_datetime ($) { main::get_now ( Line 1127  sub __get_datetime ($) { main::get_now (
1127  sub resource ($$;%) { shift; &main::Resource (@_) }  sub resource ($$;%) { shift; &main::Resource (@_) }
1128  sub uri ($$) { $main::uri{$_[1]} }  sub uri ($$) { $main::uri{$_[1]} }
1129  sub new_index ($$) { ++$Index{$_[1]} }  sub new_index ($$) { ++$Index{$_[1]} }
1130    sub user_agent_names ($) { $main::UA }
1131  sub magic_and_content ($$) {  sub magic_and_content ($$) {
1132    my $page = $_[1];    my ($magic, $page) = ('', $_[1]);
1133    $page =~ s!^((?:\#\?|/\*|<\?)[^\x02\x0A\x0D]+)[\x02\x0A\x0D]+!!s;    $magic = $1 if $page =~ s!^((?:\#\?|/\*|<\?)[^\x02\x0A\x0D]+)[\x02\x0A\x0D]+!!s;
1134    ($1, $page);    ($magic, $page);
1135  }  }
1136  sub formatter ($$) {  sub formatter ($$) {
1137    &main::load_formatter ($_[1]);    &main::load_formatter ($_[1]);
1138    $main::fmt{$_[1]};    $main::fmt{$_[1]};
1139  }  }
1140    sub format_converter ($$$) {
1141      &main::load_formatter ('format');
1142      $main::fmt{format}->{($_[1]=~/([A-Za-z0-9]\S+)/?$1:'SuikaWiki/0.9').'_to_'.$_[2]}
1143      || $main::fmt{format}->{($_[1]=~/([A-Za-z0-9](?:(?!\/)\S)+)/?$1:'SuikaWiki').'_to_'.$_[2]};
1144    }
1145    sub cache ($$) {
1146      my $name = $_[1];
1147      unless (ref $Cache{$name}) {
1148        my %cache;
1149        tie (%cache, 'Yuki::YukiWikiCache', -file => $main::PathTo{CachePrefix}.$name);
1150        $Cache{$name} = \%cache;
1151      }
1152      $Cache{$name};
1153    }
1154    
1155  sub regist ($@) {  sub regist ($@) {
1156      my $pack = shift;      my $pack = shift;
# Line 1280  package wiki::conneg; Line 1177  package wiki::conneg;
1177  sub get_accept_lang (;$) {  sub get_accept_lang (;$) {
1178    my $alang = shift || $main::ENV{HTTP_ACCEPT_LANGUAGE};    my $alang = shift || $main::ENV{HTTP_ACCEPT_LANGUAGE};
1179    my %alang = (ja => 0.0002, en => 0.0001);    my %alang = (ja => 0.0002, en => 0.0001);
1180      if ($UA =~ m#Mozilla/0\.#) {
1181        $alang{ja} = 0.00001;
1182      }
1183    my $i = 0.1;    my $i = 0.1;
1184    for (split /\s*,\s*/, $alang) {    for (split /\s*,\s*/, $alang) {
1185      tr/\x09\x0A\x0D\x20//d;      tr/\x09\x0A\x0D\x20//d;
# Line 1322  exit 0; Line 1222  exit 0;
1222  __END__  __END__
1223  =head1 NAME  =head1 NAME
1224    
1225  wiki.cgi --- SuikaWiki: Yet yet another Wiki engine  wiki.cgi --- SuikaWiki: Yet yet another WikiEngine
1226    
1227  =head1 SEE ALSO  =head1 SEE ALSO
1228    

Legend:
Removed from v.1.49  
changed lines
  Added in v.1.51

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24