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

Contents of /suikawiki/script/wiki.cgi

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.36 - (hide annotations) (download)
Tue Dec 10 07:27:38 2002 UTC (23 years, 11 months ago) by wakaba
Branch: MAIN
Changes since 1.35: +80 -37 lines
*** empty log message ***

1 wakaba 1.9 #!/usr/bin/perl
2     #
3 wakaba 1.16 # wiki.cgi - This is YukiWiki, yet another Wiki clone.
4 wakaba 1.9 #
5 wakaba 1.16 # Copyright (C) 2000-2002 by Hiroshi Yuki.
6 wakaba 1.9 # <[email protected]>
7     # http://www.hyuki.com/yukiwiki/
8     #
9 wakaba 1.16 # This program is free software; you can redistribute it and/or
10     # modify it under the same terms as Perl itself.
11 wakaba 1.9 #
12 wakaba 1.16 # walwiki.cgi based on yukiwiki.cgi - Yet another WikiWikiWeb clone.
13    
14     # Walrus add (debug) start
15     my $walrus_log;
16     my $walrus_debugging = 0;
17     # Walrus add (debug) end
18    
19     # Libraries.
20     use strict;
21     use lib qw(./WalWiki/lib);
22     use CGI qw(:standard);
23     use CGI::Carp qw(fatalsToBrowser);
24     use Yuki::RSS;
25     use Yuki::DiffText qw(difftext);
26     use Yuki::YukiWikiDB;
27     use AnyDBM_File;
28     require 'jcode.pl';
29 wakaba 1.32 require Jcode;
30 wakaba 1.16 use Fcntl;
31     my $version = '2.0.beta1.2002-05-29';
32 wakaba 1.17 my $walversion;
33 wakaba 1.9 ##############################
34 wakaba 1.16 #
35     # You MUST modify following '$modifier_...' variables.
36     #
37     my $modifier_mail = '[email protected]'; # Your mail address, like '[email protected]'.
38     my $modifier_url = 'http://suika.fam.cx/~wakaba/'; # Your web page, like 'http://digit.que.ne.jp/work/'.
39     my $modifier_name = '��'; # Your name, like 'Makio Tsukamoto'.
40     # my $modifier_dbtype = 'AnyDBM_File'; # Fast, not available on some server, page size limited.
41     # my $modifier_dbtype = 'dbmopen'; # Fast, not available on some server, page size limited.
42     my $modifier_dbtype = 'YukiWikiDB'; # Slow, available on all environment.
43     # my $modifier_sendmail = '/usr/sbin/sendmail -t -n'; # Your sendmail.
44     my $modifier_sendmail = ''; # If you don't need mail notification.
45 wakaba 1.17 my $modifier_dir_data = './wikidata'; # Your data directory.
46 wakaba 1.27 my $modifier_rss_title = "SuikaWiki $walversion";
47 wakaba 1.16 my $modifier_rss_link = 'http://suika.fam.cx/~wakaba/-temp/wiki2/wiki'; # Blank is not allowed.
48 wakaba 1.27 my $modifier_rss_description = 'This is SuikaWiki';
49 wakaba 1.9 ##############################
50 wakaba 1.16 #
51     # You MAY modify following variables.
52     #
53 wakaba 1.35 $SuikaWiki::Plugin::plugin_directory = q(./SuikaWiki/Plugin/);
54 wakaba 1.16 my $file_touch = "$modifier_dir_data/touched.txt";
55     my $file_resource = "$modifier_dir_data/resource.txt";
56     my $file_FrontPage = "$modifier_dir_data/frontpage.txt";
57     my $file_conflict = "$modifier_dir_data/conflict.txt";
58     my $file_format = "$modifier_dir_data/format.txt";
59 wakaba 1.28 my $url_cgi = '/~wakaba/-temp/wiki/wiki'; ## MUST be started from '/'
60 wakaba 1.25 my $url_stylesheet = $url_cgi.'?mycmd=TEXT_CSS;mypage=WikiHTMLStyle';
61 wakaba 1.16 my $icontag = '<img src="/icons/folder" alt="*" width="40" height="40" />';
62     my $maxrecent = 50;
63 wakaba 1.9 my $cols = 80;
64     my $rows = 20;
65     ##############################
66 wakaba 1.16 #
67     # You MAY, but do NOT NEED modify following variables.
68     #
69     my $dataname = "$modifier_dir_data/wiki";
70     my $infoname = "$modifier_dir_data/info";
71     my $diffname = "$modifier_dir_data/diff";
72     my $editchar = '?';
73     my $subject_delimiter = ' - ';
74     my $use_autoimg = 1; # automatically convert image URL into <img> tag.
75     my $use_exists = 0; # If you can use 'exists' method for your DB.
76     ##############################
77     my $InterWikiName = 'InterWikiName';
78     my $RecentChanges = 'RecentChanges';
79     my $AdminChangePassword = 'AdminChangePassword';
80     my $CompletedSuccessfully = 'CompletedSuccessfully';
81 wakaba 1.18 my $FrontPage = 'HomePage';
82 wakaba 1.16 my $IndexPage = 'IndexPage';
83     my $SearchPage = 'SearchPage';
84     my $CreatePage = 'CreatePage';
85     my $ErrorPage = 'ErrorPage';
86     my $RssPage = 'RssPage';
87 wakaba 1.26 my $NAME_OF_WikiPageLicense = 'WikiPageLicense';
88 wakaba 1.16 my $AdminSpecialPage = 'Admin Special Page'; # must include spaces.
89     ##############################
90     my $bracket_name = '\[\[(\S+?)\]\]';
91     my $embedded_name = '\[\[(#\S+?)\]\]';
92 wakaba 1.31 my %fmt; ## formatter objects
93 wakaba 1.16 ##############################
94     my $embed_comment = '[[#comment]]';
95     my $embed_rcomment = '[[#rcomment]]';
96 wakaba 1.25 my $embed_comment_Name_Prompt = '̾��:';
97     my $DEFAULT_embed_comment_name = '̵̾������';
98 wakaba 1.16 my $embed_interwiki = '^\[\[#(box|text|password):(\S+)\]\]$'; # Walrus add (5)
99 wakaba 1.22 my %embed_command = (
100     searched => '^\[\[#searched:([^\]]+)\]\]$',
101 wakaba 1.34 form => qw/\[\[\#form(?:\(([A-Za-z0-9-]+)\))?:'((?:[^'\\]|\\.)*)':'((?:[^'\\]|\\.)*)'(?::'((?:[^'\\]|\\.)*)')?\]\]/,
102 wakaba 1.22 );
103 wakaba 1.16 ##############################
104     my $info_LastModified = 'LastModified';
105     my $info_IsFrozen = 'IsFrozen';
106     my $info_AdminPassword = 'AdminPassword';
107     ##############################
108     my $kanjicode = 'euc';
109     my $charset = 'EUC-JP';
110     my $lang = 'ja';
111     my %fixedpage = (
112     $IndexPage => 1,
113     $CreatePage => 1,
114     $ErrorPage => 1,
115     $RssPage => 1,
116     $RecentChanges => 1,
117     $SearchPage => 1,
118     $AdminChangePassword => 1,
119     $CompletedSuccessfully => 1,
120 wakaba 1.18 #$FrontPage => 1,
121 wakaba 1.32 WikiUserAgentList => 1,
122 wakaba 1.35 WikiPluginInfo => 1,
123 wakaba 1.16 );
124     my %form;
125     my %database;
126     my %infobase;
127     my %diffbase;
128     my %resource;
129     my %interwiki;
130     ##############################
131     my %page_command = (
132     $IndexPage => 'index',
133     $SearchPage => 'searchform',
134     $CreatePage => 'create',
135     $RssPage => 'rss',
136     $AdminChangePassword => 'adminchangepasswordform',
137 wakaba 1.18 #$FrontPage => 'FrontPage',
138 wakaba 1.35 WikiPluginInfo => 'x_WikiPluginInfo',
139 wakaba 1.16 );
140     my %command_do = (
141     read => \&do_read,
142 wakaba 1.25 TEXT_CSS => \&do_output_css,
143 wakaba 1.16 edit => \&do_edit,
144     adminedit => \&do_adminedit,
145     adminchangepasswordform => \&do_adminchangepasswordform,
146     adminchangepassword => \&do_adminchangepassword,
147     write => \&do_write,
148     index => \&do_index,
149     searchform => \&do_searchform,
150     search => \&do_search,
151     create => \&do_create,
152     createresult => \&do_createresult,
153     FrontPage => \&do_FrontPage,
154     comment => \&do_comment,
155 wakaba 1.28 RandomJump => \&do_random_jump,
156 wakaba 1.16 rss => \&do_rss,
157     diff => \&do_diff,
158     interwikibox => \&do_interwiki_box, # Walrus add (5)
159 wakaba 1.33 wikiform => \&do_wikiform,
160 wakaba 1.35 x_WikiPluginInfo => \&do_wikiplugininfo,
161 wakaba 1.16 );
162     ##############################
163     my $walversion = '2.0.beta1.wal.1'; # Walrus add (1)
164 wakaba 1.9 ##############################
165 wakaba 1.16 # &test_convert;
166 wakaba 1.33 my $UA = ''; ## User agent name
167 wakaba 1.16 ##############################
168 wakaba 1.9
169     sub main {
170 wakaba 1.32 $UA = $main::ENV{HTTP_USER_AGENT};
171 wakaba 1.16 &init_resource;
172     &open_db;
173     &init_form;
174     &init_InterWikiName;
175     if ($command_do{$form{mycmd}}) {
176     &{$command_do{$form{mycmd}}};
177 wakaba 1.9 } else {
178 wakaba 1.16 &do_FrontPage;
179 wakaba 1.9 }
180 wakaba 1.16 &close_db;
181 wakaba 1.9 }
182    
183     sub do_read {
184 wakaba 1.26 my $content = $database{$form{mypage}};
185 wakaba 1.27 my $lm = &get_info($form{mypage}, $info_LastModified);
186     wiki::referer::add ($form{mypage}, $ENV{HTTP_REFERER});
187 wakaba 1.32 wiki::useragent::add ($ENV{HTTP_USER_AGENT});
188 wakaba 1.29 my ($r, $c) = get_search_result ($form{mypage});
189     my $rl = wiki::referer::list_html ($form{mypage});
190     my @toc;
191     push @toc, qq(-<a href="#wikipage-see-also">See Also</a>) if $c;
192     push @toc, qq(-<a href="#wikipage-referer">���ȸ�</a>) if $rl;
193 wakaba 1.26 my $cf = 'SuikaWiki/0.9';
194 wakaba 1.27 ## Should be support at least:
195     ## - 'SuikaWiki/0.9' CRLF
196     ## - 'H2H/' ("0.9" / "1.0" / "1.1") CRLF
197     ## - "/*" WSP* 'W3C-CSS/' ("1.0" / "2.0") "*/" CRLF
198 wakaba 1.32 $cf = $1 if $content =~ s#^(?:/\*\s*|[\#<]\?)?([A-Z][A-Za-z0-9-]+/[0-9.]+(?:[^0-9.\x0D\x0A][^\x0D\x0A]*)?)[\x0D\x0A]+##s;
199 wakaba 1.28 if ($cf =~ m!^(?:\#\?)?SuikaWiki/0.9(?:$|\s)!) {
200 wakaba 1.29 &print_header ($form{mypage}, -last_modified => $lm,
201     -content_format => $cf, -noindex => $cf =~ /obsoleted="yes"/);
202     &print_content ($content, content_format => $cf, last_modified => $lm,
203     -toc => \@toc);
204 wakaba 1.32 print &text_to_html (q([[#comment]])) if $cf !~ /obsoleted="yes"/ && !$fixedpage{$form{mypage}};
205 wakaba 1.26 } else {
206 wakaba 1.29 &print_header($form{mypage}, -last_modified => $lm);
207 wakaba 1.26 print "<pre>@{[&escape($content)]}</pre>";
208     }
209 wakaba 1.22 if ($c) {
210 wakaba 1.32 print qq{<h2 @{[&id_and_name('wikipage-see-also')]}>See also</h2>};
211 wakaba 1.22 print $r;
212     }
213 wakaba 1.29 if ($rl) {
214 wakaba 1.32 print qq(<div @{[&id_and_name('wikipage-referer')]}><h2>���ȸ�</h2>\n$rl</div>\n);
215 wakaba 1.27 }
216     &print_footer($form{mypage}, $lm);
217 wakaba 1.9 }
218    
219 wakaba 1.25 sub do_output_css {
220     my $content = $database{$form{mypage}};
221     if ($content =~ m#^\s*/\*\s*W3C-CSS#) {
222 wakaba 1.29 my $lm = &get_info($form{mypage}, $info_LastModified);
223 wakaba 1.36 print scalar make_navigate_links ($form{mypage});
224 wakaba 1.25 print "Content-Type: text/css; charset=$charset\n";
225 wakaba 1.29 print "Last-Modified: $lm\n";
226 wakaba 1.25 print "\n";
227     print $content;
228     } else {
229     print "Status: 406 Unsupported Media Type\n";
230 wakaba 1.29 &print_header('WikiPageIsNotCSS', -noindex => 1);
231 wakaba 1.25 &print_content($database{WikiPageIsNotCSS});
232     &print_footer('WikiPageIsNotCSS');
233     }
234     }
235    
236 wakaba 1.32 sub id_and_name ($) {
237     my $name = shift;
238 wakaba 1.36 if ($UA =~ m#Mozilla/[12]\.|Microsoft Internet Explorer#) {
239 wakaba 1.32 qq{id="$name"><a name="$name"></a};
240     } else {
241     qq{id="$name"};
242     }
243     }
244    
245 wakaba 1.9 sub do_edit {
246 wakaba 1.16 my ($page) = &unarmor_name(&armor_name($form{mypage}));
247 wakaba 1.29 &print_header($page, -noindex => 1);
248 wakaba 1.16 if (not &is_editable($page)) {
249     &print_message($resource{cantchange});
250     } elsif (&is_frozen($page)) {
251     &print_message($resource{cantchange});
252     } else {
253     &print_editform($database{$page}, &get_info($page, $info_LastModified), admin=>0);
254 wakaba 1.9 }
255 wakaba 1.30 wiki::referer::add ($form{mypage}, $ENV{HTTP_REFERER});
256 wakaba 1.32 wiki::useragent::add ($ENV{HTTP_USER_AGENT});
257 wakaba 1.30 my ($r, $c) = get_search_result ($form{mypage});
258     my $rl = wiki::referer::list_html ($form{mypage});
259     if ($c) {
260     print q{<h2 id="wikipage-see-also">See also</h2>};
261     print $r;
262     }
263     if ($rl) {
264     print qq(<div id="wikipage-referer"><h2>���ȸ�</h2>\n$rl</div>\n);
265     }
266 wakaba 1.16 &print_footer($page);
267 wakaba 1.9 }
268    
269 wakaba 1.16 sub do_adminedit {
270     my ($page) = &unarmor_name(&armor_name($form{mypage}));
271 wakaba 1.29 &print_header($page, -noindex => 1);
272 wakaba 1.16 if (not &is_editable($page)) {
273     &print_message($resource{cantchange});
274 wakaba 1.9 } else {
275 wakaba 1.16 &print_message($resource{passwordneeded});
276     &print_editform($database{$page}, &get_info($page, $info_LastModified), admin=>1);
277 wakaba 1.9 }
278 wakaba 1.16 &print_footer($page);
279 wakaba 1.9 }
280    
281 wakaba 1.16 sub do_adminchangepasswordform {
282 wakaba 1.29 &print_header($AdminChangePassword, -noindex => 1);
283 wakaba 1.16 &print_passwordform;
284     &print_footer($AdminChangePassword);
285     }
286 wakaba 1.9
287 wakaba 1.16 sub do_adminchangepassword {
288     if ($form{mynewpassword} ne $form{mynewpassword2}) {
289     &print_error($resource{passwordmismatcherror});
290     }
291     my ($validpassword_crypt) = &get_info($AdminSpecialPage, $info_AdminPassword);
292     if ($validpassword_crypt) {
293     if (not &valid_password($form{myoldpassword})) {
294     &send_mail_to_admin(<<"EOD", "AdminChangePassword");
295     myoldpassword=$form{myoldpassword}
296     mynewpassword=$form{mynewpassword}
297     mynewpassword2=$form{mynewpassword2}
298 wakaba 1.9 EOD
299 wakaba 1.16 &print_error($resource{passworderror});
300 wakaba 1.9 }
301 wakaba 1.16 }
302     my ($sec, $min, $hour, $day, $mon, $year, $weekday) = localtime(time);
303     my (@token) = ('0'..'9', 'A'..'Z', 'a'..'z');
304     my $salt1 = $token[(time | $$) % scalar(@token)];
305     my $salt2 = $token[($sec + $min*60 + $hour*60*60) % scalar(@token)];
306     my $crypted = crypt($form{mynewpassword}, "$salt1$salt2");
307     &set_info($AdminSpecialPage, $info_AdminPassword, $crypted);
308    
309 wakaba 1.29 &print_header($CompletedSuccessfully, -noindex => 1);
310 wakaba 1.16 &print_message($resource{passwordchanged});
311     &print_footer($CompletedSuccessfully);
312     }
313    
314     sub do_index {
315     &print_header($IndexPage);
316     print qq(<ul>);
317     foreach my $page (sort keys %database) {
318     if (&is_editable($page)) {
319 wakaba 1.24 print qq(<li><a href="$url_cgi?@{[&encode($page)]}">@{[&escape($page)]}</a>@{[&escape(&get_subjectline($page))]}</li>);
320 wakaba 1.16 # print qq(<li>@{[&get_info($page, $info_IsFrozen)]}</li>);
321     # print qq(<li>@{[0 + &is_frozen($page)]}</li>);
322 wakaba 1.9 }
323     }
324 wakaba 1.16 print qq(</ul>);
325     &print_footer($IndexPage);
326 wakaba 1.9 }
327    
328 wakaba 1.16 sub do_write {
329     if (&frozen_reject()) {
330     return;
331 wakaba 1.9 }
332    
333     if (not &is_editable($form{mypage})) {
334 wakaba 1.29 &print_header($form{mypage}, -noindex => 1);
335 wakaba 1.16 &print_message($resource{cantchange});
336     &print_footer($form{mypage});
337 wakaba 1.9 return;
338     }
339    
340 wakaba 1.16 if (&conflict($form{mypage}, $form{mymsg})) {
341 wakaba 1.9 return;
342     }
343    
344 wakaba 1.16 # Making diff
345 wakaba 1.9 {
346 wakaba 1.16 &open_diff;
347     my @msg1 = split(/\n/, $database{$form{mypage}});
348 wakaba 1.9 my @msg2 = split(/\n/, $form{mymsg});
349 wakaba 1.16 $diffbase{$form{mypage}} = &difftext(\@msg1, \@msg2);
350     &close_diff;
351 wakaba 1.9 }
352    
353     if ($form{mymsg}) {
354 wakaba 1.16 $database{$form{mypage}} = $form{mymsg};
355     &send_mail_to_admin($form{mypage}, "Modify");
356     if ($form{mytouch}) {
357     &set_info($form{mypage}, $info_LastModified, '' . localtime);
358     &update_recent_changes;
359     }
360     &set_info($form{mypage}, $info_IsFrozen, 0 + $form{myfrozen});
361 wakaba 1.36 my $fragment = '';
362     $fragment .= qq(;after_edit_cmd=@{[&encode($form{after_edit_cmd})]}) if $form{after_edit_cmd};
363 wakaba 1.33 if ($form{__comment_anchor_index}) {
364 wakaba 1.36 $fragment .= qq(#anchor-$form{__comment_anchor_index});
365 wakaba 1.33 } elsif ($form{__wikiform_anchor_index}) {
366 wakaba 1.36 $fragment .= qq(#wikiform-$form{__wikiform_anchor_index});
367 wakaba 1.33 }
368 wakaba 1.36 &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));
369 wakaba 1.16 &print_message($resource{saved});
370     &print_content("$resource{continuereading} @{[&armor_name($form{mypage})]}");
371     &print_footer($CompletedSuccessfully);
372     } else {
373     &send_mail_to_admin($form{mypage}, "Delete");
374     delete $database{$form{mypage}};
375     delete $infobase{$form{mypage}};
376     if ($form{mytouch}) {
377     &update_recent_changes;
378     }
379 wakaba 1.29 &print_header($form{mypage}, -noindex => 1);
380 wakaba 1.16 &print_message($resource{deleted});
381     &print_footer($form{mypage});
382 wakaba 1.9 }
383     }
384    
385 wakaba 1.16 sub do_searchform {
386     &print_header($SearchPage);
387     &print_searchform("");
388     &print_footer($SearchPage);
389 wakaba 1.9 }
390    
391 wakaba 1.16 sub do_search {
392 wakaba 1.22 my $word = $form{mymsg};
393 wakaba 1.16 &print_header($SearchPage);
394 wakaba 1.22 &print_searchform(&escape($word));
395 wakaba 1.30 print scalar get_search_result ($word, -output_not_found => 1, -match_myself => 1);
396 wakaba 1.16 &print_footer($SearchPage);
397 wakaba 1.9 }
398    
399 wakaba 1.22 sub get_search_result ($;%) {
400 wakaba 1.32 my $word = lc shift;
401 wakaba 1.22 my %option = @_;
402 wakaba 1.30 my @r;
403     foreach my $page (keys %database) {
404     next if $page eq $RecentChanges || ($page eq $word && !$option{-match_myself});
405 wakaba 1.28 my $content = $database{$page};
406 wakaba 1.30 my $cf = 'SuikaWiki/0.9';
407     $cf = $1 if $content =~ s/^\#\?([^\x0A\x0D]+)//s;
408     next if $cf =~ /obsoleted="yes"/;
409 wakaba 1.32 if (index (lc $page, $word) > -1) {
410     my $c = $content =~ s/\Q$word\E//gi;
411 wakaba 1.30 push @r, [$page, $c+20];
412 wakaba 1.32 } elsif (index ($word, lc $page) > -1) {
413     my $c = $content =~ s/\Q$word\E//gi;
414 wakaba 1.30 push @r, [$page, $c+10];
415 wakaba 1.32 } elsif (my $c = $content =~ s/\Q$word\E//gi) {
416 wakaba 1.30 push @r, [$page, $c];
417 wakaba 1.22 }
418     }
419 wakaba 1.32 my $em = sub { my $s = shift; $s =~ s#(\Q$word\E)#<em>$1</em>#gi; $s };
420 wakaba 1.30 my $r = join "\n", map {qq(<li>[$_->[1]] <a href ="$url_cgi?@{[&encode($_->[0])]}" class="wiki">@{[&$em(&escape($_->[0]))]}</a> <span class="wikipage-summary">@{[&$em(&escape(&get_subjectline($_->[0])))]}</span></li>)} sort {$b->[1] <=> $a->[1] || $a->[0] cmp $b->[0]} @r;
421     $r = qq|<ul class="search-result">$r</ul>| if $r;
422     get_message ($resource{notfound}) if @r == 0 && $option{-output_not_found};
423     wantarray? ($r, scalar @r): $r;
424 wakaba 1.22 }
425    
426 wakaba 1.16 sub do_create {
427     &print_header($CreatePage);
428     print <<"EOD";
429     <form action="$url_cgi" method="post">
430     <input type="hidden" name="mycmd" value="edit">
431     <strong>$resource{newpagename}</strong><br>
432     <input type="text" name="mypage" value="" size="20">
433     <input type="submit" value="$resource{createbutton}"><br>
434     </form>
435     EOD
436     &print_footer($CreatePage);
437 wakaba 1.9 }
438    
439 wakaba 1.28 sub do_random_jump {
440     my @list = keys %database;
441     my $name = &encode ($list[rand @list]);
442 wakaba 1.29 my ($scheme) = 'http';
443     $scheme = $1 if $main::ENV{SERVER_PROTOCOL} =~ m#([A-Za-z0-9+.%-]+)#;
444     print "Location: $scheme://$main::ENV{SERVER_NAME}:$main::ENV{SERVER_PORT}$url_cgi?$name\n";
445 wakaba 1.28 print "\n";
446     }
447    
448 wakaba 1.16 sub do_FrontPage {
449     open(FILE, $file_FrontPage) or &print_error("($file_FrontPage)");
450     my $content = join('', <FILE>);
451     &code_convert(\$content, $kanjicode);
452     close(FILE);
453     &print_header($FrontPage);
454     &print_content($content);
455     &print_footer($FrontPage);
456 wakaba 1.9 }
457    
458     sub print_error {
459     my ($msg) = @_;
460 wakaba 1.29 &print_header($ErrorPage, -noindex => 1);
461 wakaba 1.16 print qq(<p><strong class="error">$msg</strong></p>);
462     &print_footer($ErrorPage);
463 wakaba 1.9 exit(0);
464     }
465    
466 wakaba 1.27 sub print_header ($;%) {
467     my ($page, %option) = @_;
468 wakaba 1.16 my $bodyclass = "normal";
469     if (&is_frozen($page) and $form{mycmd} =~ /^(read|write)$/) {
470     $bodyclass = "frozen";
471 wakaba 1.22 }
472 wakaba 1.29 $bodyclass .= " wiki-page-obsoleted" if $option{-content_format} =~ /obsoleted="yes"/;
473 wakaba 1.32 if ($option{-goto}) {
474 wakaba 1.36 if ($UA =~ m#Opera|MSIE 2\.#) {
475     $option{-goto} =~ tr/;/&/ if $UA =~ m#Opera#;
476 wakaba 1.33 print qq{Refresh: 0; url=$option{-goto}\n};
477     $option{-goto} = qq(<meta http-equiv="refresh" content="0; url=$option{-goto}">);
478 wakaba 1.32 } else {
479 wakaba 1.36 $option{-goto} =~ tr/;/&/ if $UA =~ m#Mozilla/[1-4]\.#;
480 wakaba 1.33 print qq{Refresh: 0; url="$option{-goto}"\n};
481     $option{-goto} = qq(<meta http-equiv="refresh" content="0; url=&quot;@{[&escape($option{-goto})]}&quot;">);
482 wakaba 1.32 }
483     }
484 wakaba 1.27 print qq{Last-Modified: $option{-last_modified}\n} if $option{-last_modified};
485 wakaba 1.32 my $meta_ct = '';
486     if ($UA =~ m#Mozilla/2#) {
487     $meta_ct = qq{text/html; charset=@{[&x_charset($charset)]}};
488     print qq{Content-Type: $meta_ct\n};
489     $meta_ct = qq{<meta http-equiv="content-type" content="$meta_ct">};
490 wakaba 1.36 } elsif ($UA =~ m#Infomosaic#) {
491     print qq{Content-Type: text/html\n};
492 wakaba 1.32 } else {
493     print qq{Content-Type: text/html; charset=$charset\n};
494     }
495 wakaba 1.16 my $cookedpage = &encode($page);
496 wakaba 1.24 my $escapedpage = &escape($page);
497 wakaba 1.36 my ($Links, $links) = &make_navigate_links ($page);
498     print $Links;
499 wakaba 1.9 print <<"EOD";
500 wakaba 1.18 Content-Language: $lang
501     Content-Style-Type: text/css
502 wakaba 1.9
503 wakaba 1.28 <!--
504 wakaba 1.16 <!DOCTYPE html
505     PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
506 wakaba 1.28 "http://www.w3.org/TR/html4/loose.dtd"> + RUBY -->
507 wakaba 1.16 <html lang="$lang">
508 wakaba 1.36 <head profile="http://suika.fam.cx/~wakaba/-temp/wiki/wiki?WikiHTMLMetaProfile">
509 wakaba 1.33 $meta_ct$option{-goto}
510 wakaba 1.29 <title>$escapedpage</title>
511 wakaba 1.36 @{[($UA !~ m#Mozilla/[1-4]\.# || $UA =~ m#MSIE (?:[4-9]\.|\d\d)#) ? qq(<link rel="stylesheet" type="text/css" href="@{[&escape($url_stylesheet)]}">) : '']}
512 wakaba 1.29 @{[$option{-noindex} ? q(<meta name="ROBOTS" content="NOINDEX">) : '']}
513 wakaba 1.36 $links
514 wakaba 1.9 </head>
515 wakaba 1.16 <body class="$bodyclass">
516 wakaba 1.22 EOD
517     &print_navigate_links ($page);
518     print <<EOD;
519 wakaba 1.29 <h1 class="header">@{[&escape($page)]}</h1>
520 wakaba 1.22 EOD
521     }
522    
523 wakaba 1.32 sub x_charset ($) {
524     my $charset = lc shift;
525     if ($charset eq 'euc-jp') {
526     $charset = 'x-euc-jp';
527     } elsif ($charset eq 'shift_jis') {
528     $charset = 'x-sjis';
529     }
530     $charset;
531     }
532    
533 wakaba 1.22 sub print_navigate_links (@) {
534     my ($page) = @_;
535     my $editable = 0;
536     my $admineditable = 0;
537     if (&is_frozen($page) and $form{mycmd} =~ /^(read|write)$/) {
538     $editable = 0;
539 wakaba 1.29 #$admineditable = 1;
540 wakaba 1.22 } elsif (&is_editable($page) and $form{mycmd} =~ /^(read|write)$/) {
541 wakaba 1.29 #$admineditable = 1;
542 wakaba 1.22 $editable = 1;
543     } else {
544     $editable = 0;
545     }
546     my $cookedpage = &encode($page);
547     print <<EOH;
548 wakaba 1.16 <div class="tools">
549     @{[ $admineditable
550     ? qq(<a title="$resource{admineditthispage}" href="$url_cgi?mycmd=adminedit;mypage=$cookedpage">$resource{admineditbutton}</a> | )
551     : qq()
552     ]}
553     @{[ $editable
554 wakaba 1.29 ? #qq(<a title="$resource{editthispage}" href="$url_cgi?mycmd=edit;mypage=$cookedpage" accesskey="E">$resource{editbutton} <kbd>E</kbd></a> | )
555     qq(<a title="$resource{editthispage}" href="$url_cgi?mycmd=edit;mypage=$cookedpage" accesskey="E">�Խ�</a> | )
556 wakaba 1.16 : qq()
557     ]}
558 wakaba 1.32 <a href="$url_cgi?mycmd=read;mypage=$cookedpage;x-param=@{[time.[0..9]->[rand 10]]}">ɽ��</a> |
559 wakaba 1.16 @{[ $admineditable
560     ? qq(<a href="$url_cgi?mycmd=diff;mypage=$cookedpage">$resource{diffbutton}</a> | )
561     : qq()
562     ]}
563 wakaba 1.29 <a href="$url_cgi?$CreatePage" class="wiki">����</a> |
564     <a href="$url_cgi?$IndexPage" class="wiki">$resource{indexbutton}</a> |
565     <a href="$url_cgi?$FrontPage" class="wiki">����</a> |
566     <a href="$url_cgi?$SearchPage" class="wiki">$resource{searchbutton}</a> |
567     <a href="$url_cgi?mycmd=RandomJump;x-param=@{[time.[0..9]->[rand 10]]}" class="wiki randomlink">�ɤ���</a> |
568     <a href="$url_cgi?$RecentChanges" class="wiki">�ǿ�</a>
569