/[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.46 by w, Thu Jan 2 12:14:15 2003 UTC revision 1.50 by w, Sun Jan 12 09:15:06 2003 UTC
# Line 8  use strict; Line 8  use strict;
8  use lib qw(./lib);  use lib qw(./lib);
9  use CGI::Carp qw(fatalsToBrowser);  use CGI::Carp qw(fatalsToBrowser);
10  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};
11    binmode STDOUT; binmode STDIN;
12  require 'wikidata/suikawiki-config.ph';  require 'wikidata/suikawiki-config.ph';
13  use Fcntl;  use Fcntl;
14  ##############################  ##############################
15  my %fmt;        ## formatter objects  our %fmt;       ## formatter objects
16  my %embed_command = (  our %embed_command = (
17          searched        => '^\[\[#searched:([^\]]+)\]\]$',          searched        => '^\[\[#searched:([^\]]+)\]\]$',
18          form    => qr/\[\[\#form(?:\(([A-Za-z0-9-]+)\))?:'((?:[^'\\]|\\.)*)':'((?:[^'\\]|\\.)*)'(?::'((?:[^'\\]|\\.)*)')?\]\]/,          form    => qr/\[\[\#form(?:\(([A-Za-z0-9-]+)\))?:'((?:[^'\\]|\\.)*)':'((?:[^'\\]|\\.)*)'(?::'((?:[^'\\]|\\.)*)')?\]\]/,
19  );  );
20  our ($modifier_dbtype,$url_cgi,%uri,%PathTo,$use_exists);  our ($modifier_dbtype,$url_cgi,%uri,%PathTo,$use_exists);
21  our (%PageName,$kanjicode,$lang,%FixedPage);  our (%PageName,$kanjicode,$lang,%ViewDefinition);
22    
23  ##############################  ##############################
 my $info_LastModified = 'LastModified';  
 my $info_IsFrozen = 'IsFrozen';  
 ##############################  
24  my %form;  my %form;
25  our %database;  our %database;
26  our $database;  our $database = bless {}, 'wiki::dummy';
 my %infobase;  
27  my %interwiki;  my %interwiki;
28  ##############################  ##############################
 my %page_command = (  
     $PageName{RssPage} => 'rss',  
 );  
29  my %command_do = (  my %command_do = (
30      read => \&do_read,      read => \&do_view,
     TEXT_CSS => \&do_output_css,  
     edit => \&do_edit,  
     adminedit => \&do_adminedit,  
31      adminchangepassword => \&do_adminchangepassword,      adminchangepassword => \&do_adminchangepassword,
32      write => \&do_write,      write => \&do_write,
33      searchform => \&do_searchform,      searchform => \&do_searchform,
34      comment => \&do_comment,      comment => \&do_comment,
35      RandomJump  => \&do_random_jump,      RandomJump  => \&do_random_jump,
     rss => \&do_rss,  
     diff => \&do_diff,  
36      wikiform    => \&do_wikiform,      wikiform    => \&do_wikiform,
     map => \&do_map,  
37  );  );
38  my $UA = '';  ## User agent name  my $UA = '';  ## User agent name
39  $| = 1;  $| = 1;
# Line 64  sub main { Line 51  sub main {
51      &close_db;      &close_db;
52  }  }
53    
54  sub do_read {  sub do_view {
55    my $content = $database{$form{mypage}};    my $content = $database{$form{mypage}};
56    #print "content-type:text/plain;charset=euc-jp\n\n".gmtime."Get Lastmodified\n";    my $lm = $database->mtime ($form{mypage});
   my $lm = &get_info($form{mypage}, $info_LastModified);  
57    wiki::referer::add ($form{mypage}, $ENV{HTTP_REFERER});    wiki::referer::add ($form{mypage}, $ENV{HTTP_REFERER});
58    wiki::useragent::add ($ENV{HTTP_USER_AGENT});    wiki::useragent::add ($ENV{HTTP_USER_AGENT});
59    #print gmtime."Search...\n";    &load_formatter ('view');
60    my ($r, $c) = get_search_result ($form{mypage});      my $view = $form{mycmd};
61    my $rl = wiki::referer::list_html ($form{mypage});      if ($view eq 'edit') {
62    my @toc;        $view = 'adminedit' if $form{admin};
63    push @toc, qq(-<a href="#wikipage-see-also">@{[&Resource('SeeAlso',escape=>1)]}</a>) if $c;      } elsif ($view =~ /[^0-9A-Za-z]/) {
64    push @toc, qq(-<a href="#wikipage-referer">@{[&Resource('Referers',escape=>1)]}</a>) if $rl;        $view = 'view'
65      my $cf = 'SuikaWiki/0.9';      }
66      ## Should be support at least:    my ($magic, $content) = &SuikaWiki::Plugin::magic_and_content (undef, $content);
67      ## - 'SuikaWiki/0.9' CRLF    $magic ||= '#?SuikaWiki/0.9';
68      ## - 'H2H/' ("0.9" / "1.0" / "1.1") CRLF    my $o = bless {param => \%form, page => $form{mypage}, toc => [],
69      ## - "/*" WSP* 'W3C-CSS/' ("1.0" / "2.0") "*/" CRLF                   magic => $magic, content => $content,
70      $cf = $1 if $content =~ s#^(?:/\*\s*|[\#<]\?)?([A-Z][A-Za-z0-9-]+/[0-9.]+(?:[^0-9.\x0D\x0A][^\x0D\x0A]*)?)[\x0D\x0A]+##s;                   formatter => $fmt{view}, &_compatible_options ()}, 'SuikaWiki::Plugin';
71      if ($cf =~ m!^(?:\#\?)?SuikaWiki/0.9(?:$|\s)!) {    if (!ref $ViewDefinition{$view} || !&{$ViewDefinition{$view}->{check}} ($o)) {
72      #print gmtime."Header...\n";      print "Status: 406 Unsupported Media Type\n";
73        &print_header ($form{mypage}, -last_modified => $lm, -expires => time + 120,      $view = '-UnsupportedMediaType';
74          -content_format => $cf, -noindex => ($cf =~ /obsoleted="yes"/ ? 1 : 0));    }
75          #print "\n". gmtime."Body...\n";    my $media = $ViewDefinition{$view}->{media};
76        &print_content ($content, content_format => $cf, last_modified => $lm,    if ($ViewDefinition{$view}->{xmedia} && $UA =~ /Gecko/) {
77          -toc => \@toc);      $media = $ViewDefinition{$view}->{xmedia};
78        print &text_to_html (q([[#comment]])) if $cf !~ /obsoleted="yes"/ && !$FixedPage{$form{mypage}};      $o->{media} = $media;
79      }
80        if ($magic =~ m!^\#\?SuikaWiki/0.9!) {
81          &print_header ($form{mypage}, -last_modified => ($magic =~ /interactive="yes"/ ? $lm : time),
82            -expires => ($magic =~ /interactive="yes"/ ? 1 : undef), o => $o,
83            -media => $media, -magic => $magic,  content => $content);
84      } else {      } else {
85        &print_header($form{mypage}, -expires => time + 120, -last_modified => $lm);        &print_header($form{mypage}, -media => $media,
86        print "<pre>@{[&escape($content)]}</pre>";                                     -magic => $magic, -last_modified => $lm, o => $o);
     }  
     if ($c) {  
       print qq{<h2 @{[&id_and_name('wikipage-see-also')]}>@{[&Resource('SeeAlso',escape=>1)]}</h2>};  
       print $r;  
87      }      }
88      if ($rl) {      print $fmt{view}->replace ($ViewDefinition{$view}->{template} => $o);
       print qq(<div @{[&id_and_name('wikipage-referer')]}><h2>@{[&Resource('Referers',escape=>1)]}</h2>\n$rl</div>\n);  
     }  
         #print "\n". gmtime."Footer...\n";  
   &print_footer($form{mypage}, $lm);  
         #print "\n". gmtime."Fin...\n";  
89  }  }
90    
91  sub do_output_css {  sub _do_view_msg (%) {
92    wiki::referer::add ($form{mypage}, $ENV{HTTP_REFERER});    my %option = @_;
93    wiki::useragent::add ($ENV{HTTP_USER_AGENT});    &load_formatter ('view');
94    my $content = $database{$form{mypage}};    my $o = bless {param => \%form, page => $option{-page}, toc => [], condition => \%option,
95    if ($content =~ m#^\s*/\*\s*W3C-CSS#) {                   formatter => $fmt{view}, &_compatible_options ()}, 'SuikaWiki::Plugin';
96      my $lm = gmtime &get_info($form{mypage}, $info_LastModified);    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 {  
97      print "Status: 406 Unsupported Media Type\n";      print "Status: 406 Unsupported Media Type\n";
98      &print_header('WikiPageIsNotCSS', -noindex => 1);      $option{-view} = '-UnsupportedMediaType';
     &print_content($database{WikiPageIsNotCSS});  
     &print_footer('WikiPageIsNotCSS');  
99    }    }
100      my $media = $ViewDefinition{$option{-view}}->{media};
101      if ($ViewDefinition{$option{-view}}->{xmedia} && $UA =~ /Gecko/) {
102        $media = $ViewDefinition{$option{-view}}->{xmedia};
103        $o->{media} = $media;
104      }
105      &print_header($option{-page}, -media => $media, o => $o, -goto => $option{-goto});
106      print $fmt{view}->replace ($ViewDefinition{$option{-view}}->{template} => $o);
107  }  }
108    
109  sub id_and_name ($) {  sub id_and_name ($) {
# Line 134  sub id_and_name ($) { Line 115  sub id_and_name ($) {
115      }      }
116  }  }
117    
 sub do_edit {  
     my ($page) = &unarmor_name(&armor_name($form{mypage}));  
     if (not &is_editable($page)) {  
         &print_header($page, -noindex => 1, -expires => time+60);  
         &print_message(&Resource('Error:ThisPageIsUneditable'));  
     } elsif (&is_frozen($page)) {  
         &print_header($page, -noindex => 1, -expires => time+60);  
         &print_message(&Resource('Error:ThisPageIsUneditable'));  
     } else {  
         &print_header($page, -noindex => 1, -expires => time+60);  
         &print_editform($database{$page}, &get_info($page, $info_LastModified), admin=>0);  
     }  
     wiki::referer::add ($form{mypage}, $ENV{HTTP_REFERER});  
     wiki::useragent::add ($ENV{HTTP_USER_AGENT});  
     my ($r, $c) = get_search_result ($form{mypage});  
     my $rl = wiki::referer::list_html ($form{mypage});  
     if ($c) {  
       print qq{<h2 id="wikipage-see-also">@{[&Resource('SeeAlso',escape=>1)]}</h2>};  
       print $r;  
     }  
     if ($rl) {  
       print qq(<div id="wikipage-referer"><h2>@{[&Resource('Referers',escape=>1)]}</h2>\n$rl</div>\n);  
     }  
     &print_footer($page);  
 }  
   
 sub do_adminedit {  
     my ($page) = &unarmor_name(&armor_name($form{mypage}));  
     &print_header($page, -noindex => 1, -expires => time+60);  
     if (not &is_editable($page)) {  
         &print_message(&Resource('Error:ThisPageIsUneditable'));  
     } else {  
         &print_message(&Resource('Error:PasswordIsNotSpecified'));  
         &print_editform($database{$page}, &get_info($page, $info_LastModified), admin=>1);  
     }  
     &print_footer($page);  
 }  
   
118  sub do_adminchangepassword {  sub do_adminchangepassword {
119      if ($form{mynewpassword} ne $form{mynewpassword2}) {      if ($form{mynewpassword} ne $form{mynewpassword2}) {
120          &print_error(&Resource('Error:PasswordMismatch'));          &_do_view_msg (-view => '-error', -page => $form{mypage},
121                           error_message => &Resource ('Error:PasswordMismatch'));
122            return;
123      }      }
124      my ($validpassword_crypt) = &get_info($PageName{AdminSpecialPage}, 'AdminPassword');      my ($validpassword_crypt) = $database->meta (AdminPassword => $PageName{AdminSpecialPage});
125      if ($validpassword_crypt) {      if ($validpassword_crypt) {
126          if (not &valid_password($form{myoldpassword})) {          if (not &valid_password($form{myoldpassword})) {
127              &print_error(&Resource('Error:PasswordIsIncorrect'));              &_do_view_msg (-view => '-error', -page => $form{mypage},
128                               error_message => &Resource ('Error:PasswordIsIncorrect'));
129                return;
130          }          }
131      }      }
132      my ($sec, $min, $hour, $day, $mon, $year, $weekday) = localtime(time);      my ($sec, $min, $hour, $day, $mon, $year, $weekday) = localtime(time);
# Line 187  sub do_adminchangepassword { Line 134  sub do_adminchangepassword {
134      my $salt1 = $token[(time | $$) % scalar(@token)];      my $salt1 = $token[(time | $$) % scalar(@token)];
135      my $salt2 = $token[($sec + $min*60 + $hour*60*60) % scalar(@token)];      my $salt2 = $token[($sec + $min*60 + $hour*60*60) % scalar(@token)];
136      my $crypted = crypt($form{mynewpassword}, "$salt1$salt2");      my $crypted = crypt($form{mynewpassword}, "$salt1$salt2");
137      &set_info($PageName{AdminSpecialPage}, 'AdminPassword', $crypted);      $database->meta (AdminPassword => $PageName{AdminSpecialPage} => $crypted);
138        
139      &print_header('CompletedSuccessfully', -noindex => 1);      &_do_view_msg (-view => '-wrote', -page => $form{mypage});
     &print_message(&Resource('Error:PasswordIsChanged'));  
     &print_footer('CompletedSuccessfully');  
140  }  }
141    
142  sub valid_password ($) {  sub valid_password ($) {
143      my ($validpassword_crypt) = &get_info($PageName{AdminSpecialPage}, 'AdminPassword');      my ($validpassword_crypt) = $database->meta (AdminPassword => $PageName{AdminSpecialPage});
144      return crypt (shift, $validpassword_crypt) eq $validpassword_crypt ? 1 : 0;      return crypt (shift, $validpassword_crypt) eq $validpassword_crypt ? 1 : 0;
145  }  }
146    
# Line 205  sub do_write { Line 150  sub do_write {
150      }      }
151    
152      if (not &is_editable($form{mypage})) {      if (not &is_editable($form{mypage})) {
153          &print_header($form{mypage}, -noindex => 1);          &_do_view_msg (-view => '-error', -page => $form{mypage},
154          &print_message(&Resource('Error:ThisPageIsUneditable'));                         error_message => &Resource ('Error:ThisPageIsUneditable'));
         &print_footer($form{mypage});  
155          return;          return;
156      }      }
157    
158      if (&conflict($form{mypage}, $form{mymsg})) {      ## Check confliction
159          return;      if ($form{myLastModified} ne $database->mtime ($form{mypage})) {
160          &_do_view_msg (-view => '-conflict', -page => $form{mypage});
161          return;
162      }      }
163    
164      if ($form{mymsg}) {      if ($form{mymsg}) {
# Line 221  sub do_write { Line 167  sub do_write {
167          } else {          } else {
168            $database->STORE ($form{mypage} => $form{mymsg}, -touch => 0);            $database->STORE ($form{mypage} => $form{mymsg}, -touch => 0);
169          }          }
170          &set_info($form{mypage}, $info_IsFrozen, 0 + $form{myfrozen});          $database->meta (IsFrozen => $form{mypage} => 0 + $form{myfrozen});
171          my $fragment = '';          my $fragment = '';
172          $fragment .= qq(;after_edit_cmd=@{[&encode($form{after_edit_cmd})]}) if $form{after_edit_cmd};          $fragment .= qq(;after_edit_cmd=@{[&encode($form{after_edit_cmd})]}) if $form{after_edit_cmd};
173          if ($form{__comment_anchor_index}) {          if ($form{__comment_anchor_index}) {
# Line 229  sub do_write { Line 175  sub do_write {
175          } elsif ($form{__wikiform_anchor_index}) {          } elsif ($form{__wikiform_anchor_index}) {
176              $fragment .= qq(#wikiform-$form{__wikiform_anchor_index});              $fragment .= qq(#wikiform-$form{__wikiform_anchor_index});
177          }          }
178          &print_header('CompletedSuccessfully', -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}||'read').';mypage='.&encode($form{mypage}).qq(;x-param=@{[time.[0..9]->[rand 10]]}$fragment));
         &print_message(&Resource('Error:SavedSuccessfully'));  
         &print_content(&Resource('Error:ContinueReading')." @{[&armor_name($form{mypage})]}");  
         &print_footer('CompletedSuccessfully');  
179      } else {      } else {
180          delete $database{$form{mypage}};          delete $database{$form{mypage}};
181          delete $infobase{$form{mypage}};          &_do_view_msg (-view => '-deleted', -page => $form{mypage});
         &print_header($form{mypage}, -noindex => 1);  
         &print_message(&Resource('Error:PageIsDeletedSuccessfully'));  
         &print_footer($form{mypage});  
182      }      }
183  }  }
184    
185    sub _compatible_options () {
186      (use_anchor_name => ($UA =~ m#Mozilla/[12]\.|Microsoft Internet Explorer# ? 1 : 0));
187    }
188    
189  sub get_search_result ($;%) {  sub get_search_result ($;%) {
190    my $word = lc shift;    my $word = lc shift;
191    my %option = @_;    my %option = @_;
# Line 268  sub get_search_result ($;%) { Line 212  sub get_search_result ($;%) {
212  sub do_random_jump {  sub do_random_jump {
213    my @list = keys %database;    my @list = keys %database;
214    my $name = &encode ($list[rand @list]);    my $name = &encode ($list[rand @list]);
215    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";  
216    print "\n";    print "\n";
217  }  }
218    
 sub print_error {  
     my ($msg) = @_;  
     &print_header($PageName{ErrorPage}, -noindex => 1);  
     print qq(<p><strong class="error">$msg</strong></p>);  
     &print_footer($PageName{ErrorPage});  
     exit(0);  
 }  
   
219  sub print_header ($;%) {  sub print_header ($;%) {
220      my ($page, %option) = @_;      my ($page, %option) = @_;
221      my @head;      my @head;
222      $option{body_class} = &is_frozen($page) ? 'frozen' : 'normal';      $option{o}->{-header}->{class} = &is_frozen($page) ? 'frozen' : '';
223      $option{body_class} .= " wiki-page-obsoleted" if $option{-content_format} =~ /obsoleted="yes"/;      $option{o}->{-header}->{class} .= " wiki-page-obsoleted" if $option{-magic} =~ /obsoleted="yes"/;
224      if ($option{-goto}) {      if ($option{-goto}) {
225        if ($UA =~ m#Opera|MSIE 2\.#) {        if ($UA =~ m#Opera|MSIE 2\.#) {
226            ## WARNING: This code may output unsafe HTML document if            ## WARNING: This code may output unsafe HTML document if
# Line 294  sub print_header ($;%) { Line 228  sub print_header ($;%) {
228            $option{-goto} =~ tr/;/&/ if $UA =~ m#Opera#;            $option{-goto} =~ tr/;/&/ if $UA =~ m#Opera#;
229            print qq{Refresh: 0; url=$option{-goto}\n};            print qq{Refresh: 0; url=$option{-goto}\n};
230            push @head, qq(<meta http-equiv="refresh" content="0; url=$option{-goto}">);            push @head, qq(<meta http-equiv="refresh" content="0; url=$option{-goto}">);
231          } elsif ($UA =~ /Gecko/) {
232              print qq{Refresh: 0; url="$option{-goto}"\n};
233              push @head, qq(<meta http-equiv="refresh" content="0; url=&quot;@{[&escape($option{-goto})]}&quot;" />);
234        } else {        } else {
235            $option{-goto} =~ tr/;/&/ if $UA =~ m#Mozilla/[1-4]\.#;            $option{-goto} =~ tr/;/&/ if $UA =~ m#Mozilla/[1-4]\.#;
236            print qq{Refresh: 0; url="$option{-goto}"\n};            print qq{Refresh: 0; url="$option{-goto}"\n};
# Line 301  sub print_header ($;%) { Line 238  sub print_header ($;%) {
238        }        }
239      }      }
240      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};
241      if ($option{-expires}) {      if ($option{-expires} != -1) {
242        print qq{Expires: @{[scalar gmtime $option{-expires}]}\n};        if (defined $option{-expires}) {  ## TODO: Don't use asctime
243            print qq{Expires: @{[scalar gmtime (time + $option{-expires})]}\n};
244          } elsif ($option{-media}->{expires} != -1) {
245            print qq{Expires: @{[scalar gmtime (time + $option{-media}->{expires})]}\n};
246          }
247      }      }
248      if ($UA =~ m#Mozilla/2#) {      if ($option{-media}->{charset} && $UA =~ m#Mozilla/2#) {
249          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)]}};
250          print qq{Content-Type: $ct\n};          print qq{Content-Type: $ct\n};
251          push @head, qq{<meta http-equiv="content-type" content="$ct">};          $option{o}->{-header}->{meta_ct} = qq{<meta http-equiv="content-type" content="$ct">\n};
252      } elsif ($UA =~ m#Infomosaic#) {      } elsif (!$option{-media}->{charset} || $UA =~ m#Infomosaic#) {
253          print qq{Content-Type: text/html\n};          print qq{Content-Type: $option{-media}->{type}\n};
254      } else {      } else {
255          print qq{Content-Type: text/html; charset=@{[&get_charset_name($kanjicode)]}\n};          my $type = $option{-media}->{type};
256            $type = 'application/xml' if $type eq 'application/rss+xml';
257            print qq{Content-Type: $type; charset=@{[&get_charset_name($kanjicode)]}\n};
258      }      }
259      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" href="@{[&escape($uri{wiki}.'?mycmd=TEXT_CSS;mypage='.&encode($PageName{DefaultStyleForHTML}).';x-lm='.&get_info($PageName{DefaultStyleForHTML}, $info_LastModified))]}");  
     }  
     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";  
260  Content-Language: $lang  Content-Language: $lang
261  Content-Style-Type: text/css  Content-Style-Type: text/css
262    
 <!-- <!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>  
 <body class="$option{body_class}">  
 EOD  
     &print_navigate_links ($page);  
     print <<EOD;  
 <h1 class="header">@{[&escape($page)]}</h1>  
263  EOD  EOD
264      $option{o}->{-header}->{links} = join "\n", (@head);
265  }  }
266    
267  sub get_charset_name ($;%) {  sub get_charset_name ($;%) {
# Line 351  sub get_charset_name ($;%) { Line 276  sub get_charset_name ($;%) {
276      $charset;      $charset;
277  }  }
278    
 sub print_navigate_links (@) {  
   my ($page) = @_;  
   my $editable = (&is_editable($page) && !&is_frozen($page)) ? 1 : 0;  
   my $cookedpage = &encode($page);  
   print <<EOH;  
 <div class="tools">  
     @{[ $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>  
 </div>  
 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=adminedit;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;  
 }  
   
 sub print_footer {  
     my ($page, $lm) = @_;  
     my $epage = &encode ($page);  
   my $cvslog1 = q$Revision$;  
   my $cvslog2 = q$Date$;  
   print_navigate_links ($page);  
   print <<"EOD";  
 @{[ $lm ? qq(<div id="wikipage-last-modified">@{[&Resource('LastModified=',escape=>1)]}@{[&_rfc3339_date ($lm)]}</div>) : '' ]}  
 <div class="footer">  
 <a href="http://www.hyuki.com/yukiwiki/" title="YukiWiki 2.0.beta1.2002-05-29 &copy; 2000-2002 by Hiroshi Yuki">@{[&Resource('About:Name:YukiWiki',escape=>1)]}</a> <a href="http://digit.que.ne.jp/work/" title="WalWiki 2.0.beta1.wal.1 &copy; 2000-2002 by Makio Tsukamoto">@{[&Resource('About:Name:WalWiki',escape=>1)]}</a>  
 <a href="/gate/cvs/wakaba/wiki/" title="@{[&Resource('About:SuikaWiki:JumpToCVS',escape=>1)]} ($cvslog2)">@{[&Resource('About:Name:SuikaWiki',escape=>1)]} $cvslog1</a>  
 </div>  
 </body>  
 </html>  
 EOD  
 }  
   
279  sub escape {  sub escape {
280      my $s = shift;      my $s = shift;
281      $s =~ s|\r\n|\n|g;      $s =~ s|\x0D\x0A|\x0A|g;
282      $s =~ s|&|&amp;|g;      $s =~ s|&|&amp;|g;
283      $s =~ s|<|&lt;|g;      $s =~ s|<|&lt;|g;
284      $s =~ s|>|&gt;|g;      $s =~ s|>|&gt;|g;
# Line 447  sub unescape { Line 296  sub unescape {
296      return $s;      return $s;
297  }  }
298    
299  sub print_content ($;$) {  sub convert_format ($$$;%) {
300      my ($rawcontent, %option) = @_;    my ($content, $d => $t, %option) = @_;
301      print &text_to_html($rawcontent, toc=>1, %option);    &load_formatter ('format');
302      my $f = SuikaWiki::Plugin->format_converter ($d => $t);
303      if (ref $f) {
304        $option{content} = $content;
305        $option{from} = $d;
306        $option{to} = $t;
307        &$f ({}, bless (\%option, 'SuikaWiki::Plugin'));
308      } elsif ($t =~ /HTML|xml/) {
309        length $content ? '<pre>'.&escape($content).'</pre>' : '';
310      } else {
311        $content;
312      }
313  }  }
314    
315  sub text_to_html {  sub text_to_html {
316      my ($txt, %option) = @_;      my ($txt, %option) = @_;
317      my @toc;      my $toc = $option{-toc} || (ref $option{toc} ? $option{toc} : []);
     my @toc2 = @{$option{-toc}||[]};  
318      my $tocnum = 0;      my $tocnum = 0;
319            
320      ## Load constants      ## Load constants
# Line 477  sub text_to_html { Line 336  sub text_to_html {
336      foreach (@txt) {      foreach (@txt) {
337          chomp;          chomp;
338          if (/^\*\*\*\*\*([^\x0D\x0A]*)/) {          if (/^\*\*\*\*\*([^\x0D\x0A]*)/) {
339              push(@toc, qq(----- <a href="#i$tocnum">@{[&escape($1)||$tocnum]}</a>\n));              push @$toc, [5, "i$tocnum" => ($1 || $tocnum)];
340              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, const => \%const) . '</h6>');
341              $tocnum++;              $tocnum++;
342          } elsif (/^\*\*\*\*([^\x0D\x0A]*)/) {          } elsif (/^\*\*\*\*([^\x0D\x0A]*)/) {
343              push(@toc, qq(---- <a href="#i$tocnum">@{[&escape($1)||$tocnum]}</a>\n));              push @$toc, [4, "i$tocnum" => ($1 || $tocnum)];
344              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, const => \%const) . '</h5>');
345              $tocnum++;              $tocnum++;
346          } elsif (/^\*\*\*([^\x0D\x0A]*)/) {          } elsif (/^\*\*\*([^\x0D\x0A]*)/) {
347              push(@toc, qq(--- <a href="#i$tocnum">@{[&escape($1)||$tocnum]}</a>\n));              push @$toc, [3, "i$tocnum" => ($1 || $tocnum)];
348              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, const => \%const) . '</h4>');
349              $tocnum++;              $tocnum++;
350          } elsif (/^\*\*([^\x0D\x0A]*)/) {          } elsif (/^\*\*([^\x0D\x0A]*)/) {
351          # if (/^\*\*(.*)/) {          # if (/^\*\*(.*)/) {
352          # Walrus mod (6) end          # Walrus mod (6) end
353              push(@toc, qq(-- <a href="#i$tocnum">@{[&escape($1)||$tocnum]}</a>\n));              push @$toc, [2, "i$tocnum" => ($1 || $tocnum)];
354              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, const => \%const) . '</h3>');
355              $tocnum++;              $tocnum++;
356          } elsif (/^\*([^\x0D\x0A]*)/) {          } elsif (/^\*([^\x0D\x0A]*)/) {
357              push(@toc, qq(- <a href="#i$tocnum">@{[&escape($1)||$tocnum]}</a>\n));              push @$toc, [1, "i$tocnum" => ($1 || $tocnum)];
358              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, const => \%const) . '</h2>');
359              $tocnum++;              $tocnum++;
360          } elsif (/^(={1,6})(.*)/) {          } elsif (/^(={1,6})(.*)/) {
# Line 563  sub text_to_html { Line 422  sub text_to_html {
422      }      }
423      push(@result, splice(@saved));      push(@result, splice(@saved));
424            
425      my $toc = '';      my $r = join("\n", @result);
426      if ($option{toc}) {      $r =~ s#<p>\x0D?\x0A</p>##g;
427          # Convert @toc (table of contents) to HTML.      $r =~ s#[\x0D\x0A]+</#</#g;
428          # This part is taken from Makio Tsukamoto's WalWiki.      $r =~ s#<pre>\x0D?\x0A#<pre>#g;
429          my (@tocsaved, @tocresult);      $r;
         foreach (@toc,@toc2) {  
             if (/^(-{1,6})(.*)$/) {  
                 &back_push('ul', length($1), \@tocsaved, \@tocresult);  
                 push(@tocresult, '<li>' . $2 . '</li>');  
             }  
         }  
         push(@tocresult, splice(@tocsaved));  
         $toc = join("\n", @tocresult);  
         $toc = $toc ? qq(<div id="wikipage-toc">$toc</div>) : '';  
     }  
     $toc .= join("\n", @result);  
     $toc =~ s#<p>\n</p>##g;  
     $toc =~ s#[\x0D\x0A]+</#</#g;  
     $toc =~ s#<pre>\n#<pre>#g;  
     $toc;  
430  }  }
431    
432  sub back_push {  sub back_push {
# Line 634  sub inline ($;%) { Line 478  sub inline ($;%) {
478  sub make_wikilink ($%) {  sub make_wikilink ($%) {
479    my ($ename, %option) = @_;    my ($ename, %option) = @_;
480    my $name = &unescape ($ename);    my $name = &unescape ($ename);
481      $option{latest} = $option{latest} ? qq(mycmd=read;x-param=@{[time.[0..9]->[rand 10]]};mypage=) : '';
482    if ($database{$name}) {    if ($database{$name}) {
483      my $subject = &escape (&get_subjectline ($name, delimiter => ''));      my $subject = &escape (&get_subjectline ($name, delimiter => ''));
484      if ($option{anchor}) {      if ($option{anchor}) {
485        return qq(<a title="$subject" href="$url_cgi?@{[&encode($name)]}#anchor-$option{anchor}" class="wiki">$ename&gt;&gt;$option{anchor}</a>);        return qq(<a title="$subject" href="$uri{wiki}?$option{latest}@{[&encode($name)]}#anchor-$option{anchor}" class="wiki">$ename&gt;&gt;$option{anchor}</a>);
486      } else {      } else {
487        return qq(<a title="$subject" href="$url_cgi?@{[&encode($name)]}" class="wiki">$ename</a>);        return qq(<a title="$subject" href="$uri{wiki}?$option{latest}@{[&encode($name)]}" class="wiki">$ename</a>);
488      }      }
489    } else {    } else {
490      return qq(<a title="@{[&Resource('JumpAndEditWikiPage',escape=>1)]}" href="$url_cgi?@{[&escape($name)]}" class="wiki not-exist">$ename<span class="mark">@{[&Resource('JumpAndEditWikiPageMark',escape=>1)]}</span></a>);      return qq(<a title="@{[&Resource('JumpAndEditWikiPage',escape=>1)]}" href="$uri{wiki}?$option{latest}@{[&escape($name)]}" class="wiki not-exist">$ename<span class="mark">@{[&Resource('JumpAndEditWikiPageMark',escape=>1)]}</span></a>);
491    }    }
492  }  }
493    
# Line 693  sub make_custom_form ($$$$) { Line 538  sub make_custom_form ($$$$) {
538          $FormIndex++;          $FormIndex++;
539          if (length $definition) {          if (length $definition) {
540              my $param = bless {}, 'SuikaWiki::Plugin';              my $param = bless {}, 'SuikaWiki::Plugin';
541              my $lastmodified = &get_info($form{mypage}, $info_LastModified);              my $lastmodified = $database->mtime ($form{mypage});
542              &load_formatter (qw/form_input form_option/);              &load_formatter (qw/form_input form_option/);
543              $definition = &unescape ($definition);              $definition = &unescape ($definition);
544              $definition =~ s/\\(.)/$1/g;              $definition =~ s/\\(.)/$1/g;
# Line 702  sub make_custom_form ($$$$) { Line 547  sub make_custom_form ($$$$) {
547              $fmt{form_option}->replace ($option, $param);              $fmt{form_option}->replace ($option, $param);
548              $param->{output}->{form} = 1 unless defined $param->{output}->{form};              $param->{output}->{form} = 1 unless defined $param->{output}->{form};
549              $definition .= ' %submit;' if $definition !~ /%submit/ && !$param->{output}->{nosubmit} && $param->{output}->{form};              $definition .= ' %submit;' if $definition !~ /%submit/ && !$param->{output}->{nosubmit} && $param->{output}->{form};
550              my $target_page = $param->{output}->{page} || $form{mypage};              $param->{output}->{page} ||= $form{mypage};
551              $param->{form_disabled} = 1 if $FixedPage{$target_page};              $param->{form_disabled} = 1 if $database->meta (IsFrozen => $form{mypage});
552              my $target_form = $param->{output}->{id};              my $target_form = $param->{output}->{id};
553              my $r = '';              my $r = '';
554              $r = <<EOH if $param->{output}->{form};              $r = <<EOH if $param->{output}->{form};
555  <form method="post" action="$url_cgi" id="wikiform-$FormIndex" class="wikiform">  <form method="post" action="$url_cgi" id="wikiform-$FormIndex" class="wikiform">
556    <input type="hidden" name="mycmd" value="@{[$param->{form_disabled}?'read':'wikiform']}">    <input type="hidden" name="mycmd" value="@{[$param->{form_disabled}?'read':'wikiform']}" />
557    <input type="hidden" name="mypage" value="@{[&escape($target_page)]}">    <input type="hidden" name="mypage" value="@{[&escape($param->{output}->{page})]}" />
558    <input type="hidden" name="myLastModified" value="$lastmodified">    <input type="hidden" name="myLastModified" value="$lastmodified" />
559    <input type="hidden" name="mytouch" value="on">    <input type="hidden" name="mytouch" value="on" />
560    <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)]}" />
561  EOH  EOH
562              $r .= qq(<a name="wikiform-$FormIndex"></a>) if $UA =~ m#Mozilla/[12]\.#;              $r .= qq(<a name="wikiform-$FormIndex"></a>) if $UA =~ m#Mozilla/[12]\.#;
563              $r .= $fmt{form_input}->replace ($definition, $param);              $r .= $fmt{form_input}->replace ($definition, $param);
# Line 726  EOH Line 571  EOH
571      }      }
572  }}  }}
573    
 sub print_message {  
     my ($msg) = @_;  
     print qq(<p><strong>@{[&escape($msg)]}</strong></p>);  
 }  
   
574  sub init_form {  sub init_form {
575      ## TODO: Support multipart/form-data      ## TODO: Support multipart/form-data
576      my $query = '';      my $query = '';
# Line 741  sub init_form { Line 581  sub init_form {
581      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} !~ /[&;=]/) {
582        my $query = &decode($main::ENV{QUERY_STRING});        my $query = &decode($main::ENV{QUERY_STRING});
583        $query = &code_convert(\$query, $kanjicode);        $query = &code_convert(\$query, $kanjicode);
       if ($page_command{$query}) {  
         $form{mycmd} = $page_command{$query};  
         $form{mypage} = $query;  
       } else {  
584          $form{mypage} = $query;          $form{mypage} = $query;
585          $form{mycmd} = $database{$form{mypage}} ? 'read' : 'edit';          $form{mycmd} = $database{$form{mypage}} ? 'read' : 'edit';
       }  
586      } else {      } else {
587        for (split /[;&]/, $query) {        for (split /[;&]/, $query) {
588          if (my ($n, $v) = split /=/, $_, 2) {          if (my ($n, $v) = split /=/, $_, 2) {
# Line 759  sub init_form { Line 594  sub init_form {
594          $form{mypage} = $form{epage};          $form{mypage} = $form{epage};
595          $form{mypage} =~ s/([0-9A-F]{2})/ord hex $1/g;          $form{mypage} =~ s/([0-9A-F]{2})/ord hex $1/g;
596        }        }
       if ($page_command{$form{mypage}} && $form{mycmd} eq 'read') {  
         $form{mypage} = &code_convert(\$form{mypage}, $kanjicode);  
         $form{mycmd} = $page_command{$form{mypage}};  
       }  
597      }      }
598      $form{mypage} ||= 'HomePage';      $form{mypage} ||= $PageName{FrontPage};
599        $form{mypage} =~ tr/\x00-\x1F\x7F//d;
600      $form{mycmd} ||= 'read';      $form{mycmd} ||= 'read';
601    
602      # mypreview_edit        -> do_edit, with preview.      # mypreview_edit        -> do_edit, with preview.
# Line 810  sub get_subjectline { Line 642  sub get_subjectline {
642    
643  sub open_db {  sub open_db {
644      if ($modifier_dbtype eq 'dbmopen') {      if ($modifier_dbtype eq 'dbmopen') {
645          dbmopen(%database, $PathTo{WikiDataBase}, 0666) or &print_error("(dbmopen) $PathTo{WikiDataBase}");          dbmopen(%database, $PathTo{WikiDataBase}, 0666) or die "(dbmopen) $PathTo{WikiDataBase}";
         dbmopen(%infobase, $PathTo{WikiInfoBase}, 0666) or &print_error("(dbmopen) $PathTo{WikiInfoBase}");  
646      } elsif ($modifier_dbtype eq 'AnyDBM_File') {      } elsif ($modifier_dbtype eq 'AnyDBM_File') {
647          eval q{use AnyDBM_File};          eval q{use AnyDBM_File};
648          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}");
649          tie(%infobase, "AnyDBM_File", $PathTo{WikiInfoBase}, O_RDWR|O_CREAT, 0666) or &print_error("(tie AnyDBM_File) $PathTo{WikiInfoBase}");      } elsif ($modifier_dbtype eq 'Yuki::YukiWikiDB') {
     } elsif ($modifier_dbtype eq 'YukiWikiDB') {  
650          eval q{use Yuki::YukiWikiDB};          eval q{use Yuki::YukiWikiDB};
651          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}");
652          tie(%infobase, "Yuki::YukiWikiDB", $PathTo{WikiInfoBase}) or &print_error("(tie Yuki::YukiWikiDB) $PathTo{WikiInfoBase}");      } else {    ## Yuki::YukiWikiDB || Yuki::YukiWikiDBMeta
     } else {  
653          eval qq{use $modifier_dbtype};          eval qq{use $modifier_dbtype};
654          $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}");
         tie(%infobase, $modifier_dbtype => $PathTo{WikiInfoBase}, -lock => 2) or &print_error("(tie $modifier_dbtype) $PathTo{WikiInfoBase}");  
655      }      }
656  }  }
657    
658  sub close_db {  sub close_db {
659      if ($modifier_dbtype eq 'dbmopen') {      if ($modifier_dbtype eq 'dbmopen') {
660          dbmclose(%database);          dbmclose(%database);
         dbmclose(%infobase);  
661      } else {      } else {
662          untie(%database);          untie(%database);
         untie(%infobase);  
663      }      }
664  }  }
665    
666  sub print_editform {  sub editform (@) {
667      my ($mymsg, $lastmodified, %mode) = @_;    my %option = @_;
668      my $frozen = &is_frozen($form{mypage});    my $frozen = &is_frozen ($option{page});
669      $option{content} = $database{$option{page}} unless defined $option{content};
670      if ($form{mypreview}) {    $option{content} = $database{NewPageTemplate} unless length $option{content};
671          if ($form{mymsg}) {    $option{last_modified} = $database->mtime ($option{page}) unless defined $option{last_modified};
672              unless ($mode{conflict}) {    my $f = '';
673                  print qq(<h3>@{[&Resource('Preview:Title',escape=>1)]}</h3>\n);    my $magic = '';
674                  print qq(<p>@{[&Resource('Preview:Notice',escape=>1)]}</p>\n);    $magic = $1 if $option{content} =~ m/^([^\x0A\x0D]+)/s;
675                  print qq(<div class="preview">\n);    
676                  &print_content($form{mymsg});    my $selected = 'read';
677                  print qq(</div>\n);    if ($form{after_edit_cmd}) {
678              }      $selected = $form{after_edit_cmd};
679          } else {    } elsif ($magic =~ /Const|Config|CSS/) {
680              print @{[&Resource('Preview:Empty',escape=>1)]};      $selected = 'edit';
681          }    }
682          $mymsg = &escape($form{mymsg});    my $afteredit = <<EOH;
     } else {  
         $mymsg = &escape($mymsg || $database{NewPageTemplate});  
     }  
     my $magic = '';  
     $magic = $1 if $mymsg =~ m/^([^\x0A\x0D]+)/s;  
   
     my $edit = $mode{admin} ? 'adminedit' : 'edit';  
     my $selected = 'read';  
     if ($form{after_edit_cmd}) {  
         $selected = $form{after_edit_cmd};  
     } elsif ($magic =~ /Const|Config|CSS/) {  
         $selected = 'edit';  
     }  
     my $afteredit = <<EOH;  
683  <select name="after_edit_cmd">  <select name="after_edit_cmd">
684  <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>
685  <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>
686  </select>  </select>
687  EOH  EOH
688      $f .= <<"EOD";
689      print <<"EOD";  <form action="$uri{wiki}" method="post">
690  <form action="$url_cgi" method="post">      @{[ $option{conflict} ? '' : qq(<label><input type="submit" name="mypreview_write" value="@{[&Resource('Edit:Save',escape=>1)]}" /><kbd>S</kbd></label>) ]}
691  <h2>@{[&Resource('Edit:Title',escape=>1)]}</h2>      @{[ $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 />
692      @{[ $mode{conflict} ? '' : qq(<input type="submit" name="mypreview_write" value="@{[&Resource('Edit:Save',escape=>1)]}"><kbd>S</kbd>) ]}      <input type="hidden" name="myLastModified" value="$option{last_modified}" />
693      @{[ $mode{admin} ? qq(<label>@{[&Resource('Edit:Password=',escape=>1)]}<input type="password" name="mypassword" value="" size="10"></label>) : "" ]} [@{[do {my $n = 0;      <input type="hidden" name="mypage" value="@{[&escape($form{mypage})]}" />
694                 $mymsg =~ s/(?:-+\s)?\[([0-9]+)\]/$n = $1 if $1 > $n; $&/mge;      <textarea cols="@{[&Resource('Edit:Form:Cols')+0||80]}" rows="@{[&Resource('Edit:Form:Rows')+0||20]}" name="mymsg" tabindex="1">@{[&escape($option{content})]}</textarea><br />
                ++$n}]}]<br>  
     <input type="hidden" name="myLastModified" value="$lastmodified">  
     <input type="hidden" name="mypage" value="@{[&escape($form{mypage})]}">  
     <textarea cols="@{[&Resource('Edit:Form:Cols')+0||80]}" rows="@{[&Resource('Edit:Form:Rows')+0||20]}" name="mymsg" tabindex="1">$mymsg</textarea><br>  
695  @{[  @{[
696      $mode{admin} ?      $option{admin} ?
697      qq(      qq(
698      <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>
699      <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 />)
700      : ""      : ""
701  ]}  ]}
702  @{[  @{[
703      $mode{conflict} ? "" :      $option{conflict} ? "" :
704      qq(      qq(
705          <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 />
706          <input type="submit" name="mypreview_$edit" value="@{[&Resource('Edit:Preview',escape=>1)]}">          <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>  
707         $afteredit         $afteredit
708      )      )
709  ]}  ]}
710  </form>  </form>
711  EOD  EOD
712      unless ($mode{conflict}) {      $f;
         ## Show help text  
         my $help = $database{WikiEditHelp};  
         $help =~ s!^\#\?([A-Z][A-Za-z0-9-]+/[0-9.]+(?:[^0-9.\x0D\x0A][^\x0D\x0A]*)?)[\x0D\x0A]+!!s;  
         print &text_to_html ($help, toc => 0);  
     }  
713  }  }
714    
715  sub is_editable {  sub is_editable {
716      my ($page) = @_;      my ($page) = @_;
717      if ($FixedPage{$page} || $page =~ /\s/ || $page =~ /^\#/) {      $page =~ /[\x00-\x20\x7F]/ ? 0 : 1;
         return 0;  
     } else {  
         return 1;  
     }  
 }  
   
 # armor_name:  
 #   WikiName -> WikiName  
 #   not_wiki_name -> [[not_wiki_name]]  
 sub armor_name { qq([[$_[0]]]) }  
   
 # unarmor_name:  
 #   [[bracket_name]] -> bracket_name  
 #   WikiName -> WikiName  
 sub unarmor_name {  
     my ($name) = @_;  
     if ($name =~ /^\[\[(\S+?)\]\]$/) {  
         return $1;  
     } else {  
         return $name;  
     }  
718  }  }
719    
720  sub decode {  sub decode {
# Line 944  sub decode { Line 725  sub decode {
725  }  }
726    
727  sub encode {  sub encode {
728      my ($s) = @_;    my $s = shift;
729      my $encoded = '';    $s =~ s/([^0-9A-Za-z_-])/sprintf '%%%02X', ord $1/ge;
730      foreach my $ch (split(//, $s)) {    $s;
         if ($ch =~ /[A-Za-z0-9_]/) {  
             $encoded .= $ch;  
         } else {  
             $encoded .= '%' . sprintf("%02X", ord($ch));  
         }  
     }  
     return $encoded;  
 }  
   
 sub conflict {  
     my ($page, $rawmsg) = @_;  
     if ($form{myLastModified} eq &get_info($page, $info_LastModified)) {  
         return 0;  
     }  
     &print_header($page, -noindex => 1);  
     &print_content(&Resource('Error:Conflict'));  
     &print_editform($rawmsg, $form{myLastModified}, frozen=>0, conflict=>1);  
     &print_footer($page);  
     return 1;  
731  }  }
732    
733  sub get_now {  sub get_now {
# Line 990  sub init_InterWikiName { Line 752  sub init_InterWikiName {
752    $interwiki{'[[]]'} = 1;       ## dummy    $interwiki{'[[]]'} = 1;       ## dummy
753  }  }
754    
   
 sub get_info {  
     my ($page, $key) = @_;  
     my %info = map { split(/=/, $_, 2) } split(/\n/, $infobase{$page});  
     return $info{$key};  
 }  
   
 sub set_info {  
     my ($page, $key, $value) = @_;  
     my %info = map { split(/=/, $_, 2) } split(/\n/, $infobase{$page});  
     $info{$key} = $value;  
     my $s = '';  
     for (keys %info) {  
         $s .= "$_=$info{$_}\n";  
     }  
     $infobase{$page} = $s;  
 }  
   
755  sub frozen_reject {  sub frozen_reject {
756      my ($isfrozen) = &get_info($form{mypage}, $info_IsFrozen);      my ($isfrozen) = $database->meta (IsFrozen => $form{mypage});
757      my ($willbefrozen) = $form{myfrozen};      my ($willbefrozen) = $form{myfrozen};
758      if (not $isfrozen and not $willbefrozen) {      if (not $isfrozen and not $willbefrozen) {
759          # You need no check.          # You need no check.
# Line 1018  sub frozen_reject { Line 762  sub frozen_reject {
762          # You are admin.          # You are admin.
763          return 0;          return 0;
764      } else {      } else {
765          &print_error(&Resource('Error:PasswordIsIncorrect'));          &_do_view_msg (-view => '-error', -page => $form{mypage},
766          return 1;                         error_message => &Resource ('Error:PasswordIsIncorrect'));
767            exit;
768      }      }
769  }  }
770    
771  sub is_frozen {  sub is_frozen ($) { $database->meta (IsFrozen => $_[0]) ? 1 : 0 }
     my ($page) = @_;  
     if (&get_info($page, $info_IsFrozen)) {  
         return 1;  
     } else {  
         return 0;  
     }  
 }  
772    
773  sub do_comment {  sub do_comment {
774      my ($content) = $database{$form{mypage}};      my ($content) = $database{$form{mypage}};
775      my $default_name;   ## this code does not strict.      my $default_name;   ## this code is not strict.
776      $default_name = $1 if $content =~ /default-name="([^"]+)"/;      $default_name = $1 if $content =~ /default-name="([^"]+)"/;
777      my $datestr = '[WEAK['.&get_now.']]';      my $datestr = '[WEAK['.&get_now.']]';
778      my $namestr = $form{myname} || $default_name || &Resource('WikiForm:WikiComment:DefaultName');      my $namestr = $form{myname} || $default_name || &Resource('WikiForm:WikiComment:DefaultName');
# Line 1085  sub embedded_to_html { Line 823  sub embedded_to_html {
823      my ($embedded) = @_;      my ($embedded) = @_;
824      if ($embedded eq '[[#comment]]' or $embedded eq '[[#rcomment]]') {      if ($embedded eq '[[#comment]]' or $embedded eq '[[#rcomment]]') {
825        unless ($main::_EMBEDED) {        unless ($main::_EMBEDED) {
826          my $lastmodified = &get_info($form{mypage}, $info_LastModified);          my $lastmodified = $database->mtime ($form{mypage});
827          return <<"EOD";          return <<"EOD";
828  <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>
829      <input type="hidden" name="mycmd" value="comment">      <input type="hidden" name="mycmd" value="comment" />
830      <input type="hidden" name="mypage" value="$form{mypage}">      <input type="hidden" name="mypage" value="$form{mypage}" />
831      <input type="hidden" name="myLastModified" value="$lastmodified">      <input type="hidden" name="myLastModified" value="$lastmodified" />
832      <input type="hidden" name="mytouch" value="on">      <input type="hidden" name="mytouch" value="on" />
833      <input type="hidden" name="comment_index" value="$CommentIndex">      <input type="hidden" name="comment_index" value="$CommentIndex" />
834      @{[&Resource('WikiForm:WikiComment:Name=',escape=>1)]}      @{[&Resource('WikiForm:WikiComment:Name=',escape=>1)]}
835      <input type="text" name="myname" value="" size="10" class="comment-name">      <input type="text" name="myname" value="" size="10" class="comment-name" />
836      <input type="text" name="mymsg" value="" size="60" class="comment-msg">      <input type="text" name="mymsg" value="" size="60" class="comment-msg" />
837      <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" />
838  </p></form>  </p></form>
839  EOD  EOD
840       } else {       } else {
841          return <<"EOD";          return <<"EOD";
842  <del><form action="$url_cgi" method="get">  <del><form action="$url_cgi" method="get">
843      <input type="hidden" name="mycmd" value="read">      <input type="hidden" name="mycmd" value="read" />
844      <input type="hidden" name="mypage" value="$form{mypage}">      <input type="hidden" name="mypage" value="$form{mypage}" />
845      @{[&Resource('WikiForm:WikiComment:Name=',escape=>1)]}      @{[&Resource('WikiForm:WikiComment:Name=',escape=>1)]}
846      <input type="text" name="myname" value="" size="10" disabled="disabled">      <input type="text" name="myname" value="" size="10" disabled="disabled" />
847      <input type="text" name="mymsg" value="" size="60" disabled="disabled">      <input type="text" name="mymsg" value="" size="60" disabled="disabled" />
848  </form></del>  </form></del>
849  EOD  EOD
850      }      }
# Line 1209  sub do_wikiform { Line 947  sub do_wikiform {
947  sub code_convert {  sub code_convert {
948    require Jcode;    require Jcode;
949      my ($contentref, $code) = (shift, shift || $kanjicode);      my ($contentref, $code) = (shift, shift || $kanjicode);
950      $code = 'jis' if $code =~ /iso/;      if    ($code =~ /euc/) { $code = 'euc' }
951      $code = 'euc' if $code =~ /euc/;      elsif ($code =~ /iso/) { $code = 'jis' }
952      $code = 'sjis' if $code =~ /shift/;      elsif ($code =~ /shi/) { $code = 'sjis' }
953      $code = 'utf8' if $code =~ /utf/;      elsif ($code =~ /utf/) { $code = 'utf8' }
954      $$contentref = Jcode->new ($contentref)->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\xA2\xAF\xA2\xB0\xA2\xB2\xA2\xB1\xA1\xE4\xA1\xE3\xA1\xC0\xA1\xA1" => q(0-9A-Za-z&,.:;?!`^_/|()[]{}+$%#*@='"~-><\ ))->$code;      $$contentref = Jcode->new ($contentref)->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\xA2\xAF\xA2\xB0\xA2\xB2\xA2\xB1\xA1\xE4\xA1\xE3\xA1\xC0\xA1\xA1" => q(0-9A-Za-z&,.:;?!`^_/|()[]{}+$%#*@='"~-><\ ))->$code;
955      return $$contentref;      return $$contentref;
956  }  }
957    
 sub do_diff {  
     my $title = $form{mypage};  
     &print_header($title, -noindex => 1);  
     print qq(<h2>@{[&Resource('Diff:Title',escape=>1)]}</h2>);  
     print qq(<p>@{[&Resource('Diff:Notice',escape=>1)]}</p>);  
     print qq(<pre class="diff">);  
     for (split(/\n/, &escape ($database->traverse_diff ($form{mypage})))) {  
         if (/^\+(.*)/) {  
             print qq(<ins class="added">$1</ins>\n);  
         } elsif (/^\-(.*)/) {  
             print qq(<del class="deleted">$1</del>\n);  
         } elsif (/^\=(.*)/) {  
             print qq(<span class="same">$1</span>\n);  
         } else {  
             print qq|??? $_\n|;  
         }  
     }  
     print qq(</pre>);  
     &print_footer($title);  
 }  
   
 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'   => &get_info ($title, $info_LastModified),  
           );  
           $count++;  
         }  
     }  
     # print RSS information (as XML).  
     print <<"EOD"  
 Content-type: application/xml; charset=@{[&get_charset_name ($kanjicode)]}  
   
 @{[$rss->as_string]}  
 EOD  
 }  
   
958  sub _rfc3339_date ($) {  sub _rfc3339_date ($) {
959    my @time = gmtime (shift);    my @time = gmtime (shift);
960    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];
961  }  }
962    
963  sub is_exist_page {  sub is_exist_page { $use_exists ? exists ($database{$_[0]}) : $database{$_[0]} }
     my ($name) = @_;  
     if ($use_exists) {  
         return exists($database{$name});  
     } else {  
         return $database{$name};  
     }  
 }  
   
964  sub __get_database ($) { $database{ $_[0] } }  sub __get_database ($) { $database{ $_[0] } }
 sub __set_database ($$) { $database{ $_[0] } = $_[1] }  
   
 sub do_map {  
     my $page = $form{mypage};  
     &print_header ($page);  
     wiki::referer::add ($form{mypage}, $ENV{HTTP_REFERER});  
     wiki::useragent::add ($ENV{HTTP_USER_AGENT});  
     my ($r, $c) = get_search_result ($form{mypage});  
     my $rl = wiki::referer::list_html ($form{mypage});  
     print "<h2>@{[&Resource('Map:Title',escape=>1)]}</h2>\n<p>@{[&Resource('Map:Description',escape=>1)]}</p>\n";  
     my %option = (level => 0+&Resource('Map:Depth'), weight_list => {}, not_exist => {},  
       map_from_here => &Resource('Map:FromHere'),  
       map_from_here_description => &Resource('Map:FromHereLong'));  
     &wiki::map::make_list ($page, %option);  
     print &wiki::map::list_to_html ($page, $option{weight_list}, %option);  
     if ($c) {  
       print qq{<h2 id="wikipage-see-also">@{[&Resource('SeeAlso',escape=>1)]}</h2>};  
       print $r;  
     }  
     if ($rl) {  
       print qq(<div id="wikipage-referer"><h2>@{[&Resource('Referers',escape=>1)]}</h2>\n$rl</div>\n);  
     }  
     &print_footer ($page);  
 }  
965    
966  my %_Resource;  my %_Resource;
967  sub Resource ($;%) {  sub Resource ($;%) {
# Line 1349  sub add ($$) { Line 992  sub add ($$) {
992    $list{ $uri }++;    $list{ $uri }++;
993    set ($page, \%list);    set ($page, \%list);
994  }  }
995  sub get ($) {  sub get ($) { split /"/, $main::database->meta (Referer => $_[0]) }
   my $page = shift;  
   split /"/, main::get_info ($page, 'Referer');  
 }  
996  sub set ($%) {  sub set ($%) {
997    my $page = shift;    my $page = shift;
998    my $list = shift;    my $list = shift;
999    main::set_info ($page, Referer => join '"', %$list);    $main::database->meta (Referer => $page => join '"', %$list);
1000  }  }
1001    
1002  sub get_dont_record () {  sub get_dont_record () {
1003    map {s/\$/\\\$/g; s/\@/\\\@/g; $_}    map {s/\$/\\\$/g; s/\@/\\\@/g; $_}
1004    grep !/^#/,    grep !/^#/,
1005    split /[\x0D\x0A]+/, &main::__get_database ('RefererDontRecord');    split /[\x0D\x0A]+/, $main::database{RefererDontRecord};
1006  }  }
1007  sub get_site_name () {  sub get_site_name () {
1008    my @lines = grep /[^#]/, split /[\x0D\x0A]+/, &main::__get_database('RefererSiteName');    my @lines = grep /[^#]/, split /[\x0D\x0A]+/, $main::database{RefererSiteName};
1009    my @item;    my @item;
1010    for (@lines) {    for (@lines) {
1011      next if /^#/;      next if /^#/;
# Line 1450  sub to_hash ($;$) { Line 1090  sub to_hash ($;$) {
1090    $h;    $h;
1091  }  }
1092    
1093    package wiki::dummy;
1094    sub mtime (@) {undef}
1095    sub meta (@) {undef}
1096    sub Yuki::YukiWikiDB2::meta (@) {undef}
1097    
1098  package SuikaWiki::Plugin;  package SuikaWiki::Plugin;
1099    our $plugin_directory;  # defined in top of this file.    our $plugin_directory;
1100    our %List;    our %List;
1101      our %Index;
1102      push @main::INC, $plugin_directory.'/../..';
1103    
1104  sub escape ($$) { main::escape ($_[1]) }  sub escape ($$) { main::escape ($_[1]) }
1105  sub unescape ($$) { main::unescape ($_[1]) }  sub unescape ($$) { main::unescape ($_[1]) }
# Line 1461  sub decode ($$) { main::decode ($_[1]) } Line 1108  sub decode ($$) { main::decode ($_[1]) }
1108  sub __get_datetime ($) { main::get_now () }  sub __get_datetime ($) { main::get_now () }
1109  sub resource ($$;%) { shift; &main::Resource (@_) }  sub resource ($$;%) { shift; &main::Resource (@_) }
1110  sub uri ($$) { $main::uri{$_[1]} }  sub uri ($$) { $main::uri{$_[1]} }
1111    sub new_index ($$) { ++$Index{$_[1]} }
1112    sub user_agent_names ($) { $main::UA }
1113    sub magic_and_content ($$) {
1114      my ($magic, $page) = ('', $_[1]);
1115      $magic = $1 if $page =~ s!^((?:\#\?|/\*|<\?)[^\x02\x0A\x0D]+)[\x02\x0A\x0D]+!!s;
1116      ($magic, $page);
1117    }
1118    sub formatter ($$) {
1119      &main::load_formatter ($_[1]);
1120      $main::fmt{$_[1]};
1121    }
1122    sub format_converter ($$$) {
1123      &main::load_formatter ('format');
1124      $main::fmt{format}->{($_[1]=~/([A-Za-z0-9]\S+)/?$1:'SuikaWiki/0.9').'_to_'.$_[2]}
1125      || $main::fmt{format}->{($_[1]=~/([A-Za-z0-9](?:(?!\/)\S)+)/?$1:'SuikaWiki').'_to_'.$_[2]};
1126    }
1127    
1128  sub regist ($@) {  sub regist ($@) {
1129      my $pack = shift;      my $pack = shift;
# Line 1510  sub get ($;\%) { Line 1173  sub get ($;\%) {
1173    for my $lang (sort {$option->{accept_language}->{$b} <=> $option->{accept_language}->{$a}} grep {$option->{accept_language}->{$_}!=0} keys %{$option->{accept_language}}) {    for my $lang (sort {$option->{accept_language}->{$b} <=> $option->{accept_language}->{$a}} grep {$option->{accept_language}->{$_}!=0} keys %{$option->{accept_language}}) {
1174      while (length $lang) {      while (length $lang) {
1175        unless ($option->{accept_language}->{defined $option->{accept_language}->{$lang} ? $lang : '*'} == 0) {        unless ($option->{accept_language}->{defined $option->{accept_language}->{$lang} ? $lang : '*'} == 0) {
1176          $option->{resource}->{$lang} ||= &wiki::suikawikiconst::to_hash (&main::__get_database('WikiResource:'.$lang));          $option->{resource}->{$lang} ||= &wiki::suikawikiconst::to_hash ($main::database{'WikiResource:'.$lang});
1177          $v = $option->{resource}->{$lang}->{$resname};          $v = $option->{resource}->{$lang}->{$resname};
1178          last if defined $v;          last if defined $v;
1179        }        }
# Line 1521  sub get ($;\%) { Line 1184  sub get ($;\%) {
1184    defined $v ? $v : $resname;    defined $v ? $v : $resname;
1185  }  }
1186    
 package wiki::map;  
   
 sub make_list ($;%) {  
   my ($page, %option) = @_;  
   $option{level} ||= 3;  
   my %weight;  
   my $content = &main::__get_database ($page);  
   $content =~ s{^\#\?([^\x0A\x0D]+)}{  
     if ($1 =~ /import="([^"]+)"/) {  
       for (split /\s*,\s*/, $1) {  
         $weight{$_} += 2;  
       }  
     }  
     $&;  
   }ges;  
   ## Bug: this code does not support content type.  
   $content =~ s{\[\[((?!\#)[^]]+)\](?:>>\d+)?\]}{  
     $weight{$1}++; $&;  
   }ge;  
   delete $weight{$page};        ## Delete myself  
   for my $page (keys %weight) {  
     my $w = ($content =~ s/\Q$page\E/$&/g);  
     $weight{$page} += $w + $weight{$page}; ## Weight of [[name]] is x2.  
     ($weight{$page} *= 0.1, $option{not_exist}->{$page} = 1) unless &main::is_exist_page ($page);  
   }  
   $option{weight_list}->{$page} = \%weight;  
   if (--$option{level}) {  
     for my $page (keys %weight) {  
       &make_list ($page, %option) unless $option{weight_list}->{$page};  
     }  
   }  
   $option{weight_list};  
 }  
   
 sub list_to_html ($$;%) {  
   my ($Page, $wlist, %option) = @_;  
   my $r = '';  
   $option{outputed}->{$Page} = 1;  
   for my $page (sort {$wlist->{$Page}->{$b} <=> $wlist->{$Page}->{$a}} keys %{$wlist->{$Page}}) {  
     $r .= qq(<li><span class="weight">[@{[0+$wlist->{$Page}->{$page}]}]</span> <a href="$main::url_cgi?@{[&main::encode($page)]}" class="wiki@{[$option{not_exist}->{$page}?' not-exist':'']}">@{[&main::escape ($page).($option{not_exist}->{$page}?qq(<span class="mark">@{[&main::Resource('JumpAndEditWikiPageMark',escape=>1)]}</span>):'')]}</a> <a href="$main::url_cgi?mycmd=map;mypage=@{[&main::encode($page)]}" class="wiki-cmd map-from-here" title="@{[&main::escape($option{map_from_here_description})]}">@{[&main::escape($option{map_from_here})]}</a> <span class="summary">@{[&main::escape(&main::get_subjectline($page))]}</span>);  
     unless ($option{outputed}->{$page}) {  
       $r .= &list_to_html ($page, $wlist, %option);  
     }  
     $r .= "</li>\n";  
   }  
   $r ? qq(<ul class="map">$r</ul>) : '';  
 }  
   
1187  package main;  package main;
1188  &main;  &main;
1189  exit 0;  exit 0;
# Line 1579  __END__ Line 1194  __END__
1194    
1195  wiki.cgi --- SuikaWiki: Yet yet another Wiki engine  wiki.cgi --- SuikaWiki: Yet yet another Wiki engine
1196    
1197    =head1 SEE ALSO
1198    
1199    <IW:SuikaWiki:SuikaWiki>
1200    
1201  =head1 AUTHORS  =head1 AUTHORS
1202    
1203  Hiroshi Yuki <hyuki@hyuki.com> <http://www.hyuki.com/yukiwiki/>  Hiroshi Yuki <hyuki@hyuki.com> <http://www.hyuki.com/yukiwiki/>

Legend:
Removed from v.1.46  
changed lines
  Added in v.1.50

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24