/[pub]/suikawiki/script/lib/suikawiki.pl
Suika

Contents of /suikawiki/script/lib/suikawiki.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.20 - (show annotations) (download)
Sat Dec 6 02:22:10 2003 UTC (21 years, 7 months ago) by wakaba
Branch: MAIN
Changes since 1.19: +20 -4 lines
File MIME type: text/plain
(magic_and_content, get_data): New. (Moved from SuikaWiki::Plugin

1 use strict;
2 package main;
3 binmode STDOUT; binmode STDIN;
4 our $WIKI;
5 require SuikaWiki::Plugin;
6 our %embed_command = ( # Map, main
7 form => qr/\[\[\#form(?:\(([A-Za-z0-9-]+)\))?:'((?:[^'\\]|\\.)*)':'((?:[^'\\]|\\.)*)'(?::'((?:[^'\\]|\\.)*)')?\]\]/,
8 );
9 our $database = bless {}, 'wiki::dummy';
10 require SuikaWiki::Name::Space;
11 require SuikaWiki::SrcFormat;
12
13 # [to be obsolete]
14 sub do_comment {
15 my ($content) = $main::database{$main::form{mypage}};
16 my $default_name; ## this code is not strict.
17 $default_name = $1 if $content =~ /default-name="([^"]+)"/;
18 my @time = gmtime (time);
19 my $datestr = sprintf '[WEAK[%04d-%02d-%02d %02d:%02d:%02d +00:00]]', $time[5]+1900,$time[4]+1,@time[3,2,1,0];
20 my $namestr = $main::form{myname} || $default_name || &Resource('WikiForm:WikiComment:DefaultName');
21 ($namestr = '', $datestr = '') if $main::form{myname} eq 'nodate';
22 if ($namestr =~ /^(?:>>)?[0-9]/) {
23 $namestr = qq( ''$namestr'': );
24 } elsif (length $namestr) {
25 $namestr = qq( ''[[$namestr]]'': );
26 }
27 my $anchor = &get_new_anchor_index ($content);
28 my $i = 1; my $o = 0;
29 $content =~ s{(\[\[\#r?comment\]\])}{
30 my $embed = $1;
31 if ($i == $main::form{comment_index}) {
32 if ($embed ne '[[#rcomment]]') {
33 $embed = "- [$anchor] $datestr$namestr$main::form{mymsg}\n$embed"; $o = 1;
34 } else {
35 $embed .= "\n- [$anchor] $datestr$namestr$main::form{mymsg}"; $o = 1;
36 }
37 }
38 $i++; $embed;
39 }ge;
40 unless ($o) {
41 $content = "#?SuikaWiki/0.9\n\n" unless $content;
42 $content .= "\n" unless $content =~ /\n$/s;
43 $content .= "- [$anchor] $datestr$namestr$main::form{mymsg}\n";
44 }
45 $main::form{__comment_anchor_index} = $anchor;
46 if ($main::form{mymsg} || $main::form{myname}) {
47 $main::form{mymsg} = $content;
48 $main::form{mytouch} = 'on';
49 &do_write;
50 } else { ## Don't write
51 #$main::form{mycmd} = 'default';
52 #&do_view;
53 die "No comment specified";
54 }
55 }
56
57 # [move to SuikaWiki::Plugin::WikiForm]
58 sub get_new_anchor_index ($) {
59 my $content = shift;
60 my $anchor = 0;
61 $content =~ s/^(?:[-=]+\s*)?\[([0-9]+)\]/$anchor = $1 if $1 > $anchor; $&/mge;
62 $anchor + 1;
63 }
64
65 # [move to SuikaWiki::Plugin::WikiForm]
66 sub do_wikiform {
67 my $content = $main::database{$main::form{mypage}};
68 my $anchor = &get_new_anchor_index ($content);
69 my $write = 0;
70 my $i = 1;
71 $content =~ s{$embed_command{form}}{
72 my ($embed, $wfname, $template, $option) = ($&, $1, $3, $4);
73 if (($wfname && $wfname eq $main::form{wikiform_targetform})
74 || $i == $main::form{wikiform_index}) {
75 $template =~ s/\\([\\'])/$1/g;
76 $option =~ s/\\([\\'])/$1/g;
77 my $param = bless {depth=>10}, 'SuikaWiki::Plugin';
78 $param->{page} = $main::form{mypage};
79 $param->{form_index} = $i;
80 $param->{form_name} = $wfname;
81 $param->{anchor_index} = $anchor;
82 $param->{argv} = \%main::form;
83 $param->{default_name} = $1 if $content =~ /default-name="([^"]+)"/;
84 $param->{default_name} ||= &Resource('WikiForm:WikiComment:DefaultName');
85 SuikaWiki::Plugin->formatter ('form_option')->replace ($option, $param);
86 my $t = 1;
87 for (keys %{$param->{require}||{}}) {
88 (undef $t, last) unless length $param->{argv}->{'wikiform__'.$_};
89 }
90 $t = SuikaWiki::Plugin->formatter ('form_template')->replace ($template, $param) if $t;
91 if (length $t) {
92 if ($param->{output}->{reverse}) {
93 $embed .= "\n" . $t;
94 } else {
95 $embed = $t . "\n" . $embed;
96 }
97 $write = 1;
98 $main::form{__comment_anchor_index} = $anchor
99 if $param->{anchor_index_}; ## $anchor is used!
100 }
101 $main::form{__wikiform_anchor_index} = $i;
102 undef $main::form{wikiform_targetform}; ## Make sure never to match
103 undef $main::form{wikiform_index}; ## with WikiForm in rest of page!
104 }
105 $i++; $embed;
106 }ge;
107 unless ($write) {
108 #$content = "#?SuikaWiki/0.9\n\n" unless $content;
109 #$content .= "\n" unless $content =~ /\n$/s;
110 #
111 }
112 if ($write) {
113 $main::form{mymsg} = $content;
114 $main::form{mytouch} = 'on';
115 &do_write;
116 } else { ## Don't write!
117 #$main::form{mycmd} = 'default';
118 #&do_view;
119 die "No content specified";
120 }
121 }
122
123 # [to be obsolete] ->Message::MIME::Charset
124 sub code_convert {
125 require Jcode;
126 my ($contentref, $code, $srccode) = @_;
127 $code ||= $WIKI->{config}->{charset}->{internal};
128 for ($code, $srccode) {
129 if ($_ eq 'euc-jp') { $_ = 'euc' }
130 elsif ($_ eq 'iso-2022-jp') { $_ = 'jis' }
131 elsif ($_ eq 'utf-8') { $_ = 'utf8' }
132 elsif ($_ eq 'shift_jis') { $_ = 'sjis' }
133 }
134 if ($code eq 'iso-8859-1') {
135 return $$contentref; ## TODO:
136 }
137 $$contentref = Jcode->new ($contentref, $srccode)
138 ## Normalize FULLWIDTH characters and IDEOGRAPHIC SPACE
139 ->tr ("\xA3\xB0-\xA3\xB9\xA3\xC1-\xA3\xDA\xA3\xE1-\xA3\xFA\xA1\xF5\xA1\xA4\xA1\xA5\xA1\xA7\xA1\xA8\xA1\xA9\xA1\xAA\xA1\xAE\xA1\xB0\xA1\xB2\xA1\xBF\xA1\xC3\xA1\xCA\xA1\xCB\xA1\xCE\xA1\xCF\xA1\xD0\xA1\xD1\xA1\xDC\xA1\xF0\xA1\xF3\xA1\xF4\xA1\xF6\xA1\xF7\xA1\xE1\xA1\xE4\xA1\xE3\xA1\xA1\xA2\xAF\xA2\xB0\xA2\xB2\xA2\xB1\xA1\xA1\xC0" => q(0-9A-Za-z&,.:;?!`^_/|()[]{}+$%#*@=>< '"~-))
140 ->tr (qq(\x8E\xDE\x8E\xDF) => qq(\xA1\xAB\xA1\xAC))
141 ->h2z
142 ->$code;
143 return $$contentref;
144 }
145
146 # [to be obsolete] ->Message::Field::Date : Map
147 sub _rfc3339_date ($) {
148 my @time = gmtime (shift);
149 sprintf '%04d-%02d-%02dT%02d:%02d:%02d+00:00', $time[5]+1900,$time[4]+1,@time[3,2,1,0];
150 }
151
152 # [obsolete] ->SuikaWiki::SrcFormat : SuikaWiki09 plugin
153 sub convert_format ($$$;%) {
154 my ($content, $d => $t, %option) = @_;
155 my $f = SuikaWiki::Plugin->format_converter ($d => $t);
156 if (ref $f) {
157 $option{content} = $content;
158 $option{from} = $d;
159 $option{to} = $t;
160 &$f ({}, bless (\%option, 'SuikaWiki::Plugin'));
161 } elsif ($option{-error_no_return}) {
162 return undef;
163 } elsif ($t =~ /HTML|xml/) {
164 if (length $content) {
165 my $NS_XHTML1 = 'http://www.w3.org/1999/xhtml';
166 my $r = Message::Markup::XML::Node->new
167 (type => '#element', namespace_uri => $NS_XHTML1, local_name => 'pre');
168 $r->append_text ($content);
169 return $r;
170 } else {
171 return '';
172 }
173 } else {
174 $content;
175 }
176 }
177
178 package SuikaWiki::Plugin;
179 ## Obsolete
180 sub magic_and_content ($$) {
181 my ($magic, $page) = ('', $_[1]);
182 $magic = $1 if $page =~ s!^((?:\#\?|/\*|<\?)[^\x02\x0A\x0D]+)[\x02\x0A\x0D]+!!s;
183 ($magic, $page);
184 }
185
186 ## Obsolete
187 sub get_data ($$$$;%) {
188 my ($self, $prop, $key, %opt) = @_;
189 ## TODO: common interface to WikiDB
190 ## TODO: error recovering
191 $main::WIKI->{db}->get ($prop => $key);
192 }
193
194 package wiki::transitional::uri_param;
195 require Tie::Hash;
196 our @ISA = 'Tie::Hash';
197
198 sub TIEHASH ($@) {
199 bless {http => $_[1]}, $_[0];
200 }
201
202 sub FETCH ($$) {
203 my ($self, $key) = @_;
204 exists $self->{val}->{$key} ?
205 $self->{val}->{$key}:
206 $self->{http}->parameter ($key);
207 }
208
209 sub STORE ($$$) {
210 my ($self, $key, $val) = @_;
211 $self->{val}->{$key} = $val;
212 }
213
214 sub DELETE ($$) {
215 my ($self, $key) = @_;
216 $self->{val}->{$key} = undef;
217 }
218
219 sub EXISTS ($$) {
220 my ($self, $key) = @_;
221 exists $self->{val}->{$key} ?
222 1:
223 defined $self->{http}->parameter ($key);
224 }
225
226 package main;
227 our $VERSION = do{my @r=(q$Revision: 1.19 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
228 push @{$WIKI->{event}->{setting_initial_variables}}, sub {
229 my $wiki = shift;
230 $wiki->{implementation_version} = 'hcs'.$VERSION;
231
232 ## Error output
233 require SuikaWiki::Output::CGICarp;
234 $SuikaWiki::Output::CGICarp::CUSTOM_REASON_TEXT
235 = 'Internal WikiEngine Error';
236 CGI::Carp::set_message (sub {
237 my $msg = shift;
238 #$msg =~ s/&/&amp;/g;
239 #$msg =~ s/</&lt;/g;
240 my $wiki_name_version = $wiki->{implementation_name} .'/'. $wiki->version;
241 for ($wiki_name_version) { s/&/&amp;/g; s/</&lt;/g;
242 s/([^\x20-\x7E])/sprintf '&#x%02X;',
243 ord $1/g; };
244 print STDOUT <<EOH;
245 <!DOCTYPE html SYSTEM>
246 <title>500 Internal WikiEngine Error</title>
247 <h1>Internal WikiEngine Error</h1>
248 <p>$msg</p>
249 <address>$wiki_name_version</address>
250 EOH
251 });
252
253 $wiki->{var}->{db}->{read_only}->{'#default'} = 1;
254
255 require SuikaWiki::Input::HTTP;
256 $wiki->{input} = SuikaWiki::Input::HTTP->new;
257 $wiki->{input}->{decoder}->{'#default'} = sub {
258 my ($http, $s, $temp_params) = @_;
259 return main::code_convert (\$s, $wiki->{config}->{charset}->{internal},
260 lc (@{$temp_params->{_charset_}||[]}[0])
261 || $wiki->{config}->{charset}->{uri_param});
262 };
263 $wiki->{var}->{client}->{user_agent_name}
264 = $wiki->{input}->meta_variable ('HTTP_USER_AGENT');
265 $wiki->{var}->{client}->{used_for_negotiate} = ['User-Agent'];
266
267 ## TODO: PATH_INFO support
268 my $page = $wiki->{input}->meta_variable ('QUERY_STRING');
269 if ($page && !(index ($page, '=') > -1)) {
270 $page =~ tr/+/ /;
271 $page =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack 'C', hex $1/ge;
272 $page = main::code_convert
273 (\$page, $wiki->{config}->{charset}->{internal},
274 $wiki->{config}->{charset}->{uri_query});
275 } else {
276 $page = $wiki->{input}->parameter ('mypage');
277 }
278
279
280 ## TODO: SuikaWiki 3 WikiName
281 $page =~ tr/\x00-\x20\x7F//d;
282 $page = SuikaWiki::Name::Space::normalize_name ($page);
283 if ($page) {
284 $wiki->{var}->{page} = [split '//', $page];
285 } else {
286 $wiki->{var}->{page} = $wiki->{config}->{page}->{Default};
287 }
288
289 ## Mode
290 my $mode = $wiki->{input}->parameter ('mode')
291 || $wiki->{input}->parameter ('mycmd') ## for compatibility with
292 || 'default'; ## YukiWiki and SuikaWiki 2
293 $mode =~ tr/-/_/;
294 if ($mode eq 'default' || $mode =~ /[^0-9A-Za-z_]/) {
295 ## BUG: this code is not strict
296 my $cookie = $wiki->{input}->meta_variable ('HTTP_COOKIE');
297 if ($cookie =~ /SelectedMode=([0-9A-Za-z_-]+)/) {
298 $mode = $1; $mode =~ tr/-/_/;
299 } else {
300 $mode = 'read';
301 }
302 push @{$wiki->{var}->{client}->{used_for_negotiate}}, 'Cookie';
303 }
304 $wiki->{var}->{mode} = $mode;
305
306 ## Transitional variables
307 tie %main::form, 'wiki::transitional::uri_param', $wiki->{input};
308 $main::UA = $wiki->{var}->{client}->{user_agent_name};
309 $main::form{mypage} = join '//', @{$wiki->{var}->{page}};
310 $main::form{mycmd} = $mode;
311 };
312
313 push @{$WIKI->{event}->{view_in_mode}}, sub {
314 my ($wiki, $opt) = @_;
315 my $arg = {condition => {mode => $opt->{mode} || '-error',
316 output => 'http-cgi',
317 http_method => $opt->{method} || 'GET'}};
318 my $viewobj = $wiki->{view}->instantiate ($opt->{mode} || '-error', $arg);
319 if (ref $viewobj) {
320 $viewobj->main ($arg);
321 } elsif ($opt->{mode} ne '-error') {
322 $wiki->view_in_mode (mode => '-error', method => 'GET');
323 ## TODO: cache control for non-GET
324 } else {
325 die "Some error happens. Additionally, error reporting mode not defined";
326 }
327 };
328
329 ## Initialization of various functions
330 $WIKI->init_variables;
331 $WIKI->init_plugin;
332 $WIKI->init_view;
333 $WIKI->{view}->register_common_modes;
334
335 ## Error handlers
336 use SuikaWiki::DB::Util::Error;
337 my $catcher = catch SuikaWiki::DB::Util::Error with {
338 my $err = shift;
339 my $err_msg = $err->text;
340 $err_msg = caller (3) . '-->' . caller (2) . '-->' . caller (1)
341 . ($err->{-method} ? '->'.$err->{-method} : '')
342 . ': '
343 . (defined $err->{-file} ? $err->{-file} . ': ' : '')
344 . (defined $err->{-prop} ? $err->{-prop} . ': ' : '')
345 . (defined $err->{-key} ? join ('//', @{$err->{-key}}) . ': ' : '')
346 . $err_msg;
347 if ($WIKI->{config}->{path_to}->{db__content__error_log}) {
348 open LOG, '>>', $WIKI->{config}->{path_to}->{db__content__error_log};
349 print LOG scalar (gmtime), " @{[$$]} {$err->{def}->{level}}: ",
350 $err_msg, "\n";
351 close LOG;
352 }
353 if ($err->{def}->{level} eq 'fatal' or $err->{def}->{level} eq 'stop') {
354 require Carp;
355 local $Carp::Verbose = 1;
356 Carp::croak $err_msg;
357 }
358 } catch SuikaWiki::View::Implementation::error with {
359 my $err = shift;
360 exit if $err->{type} eq 'ERROR_REPORTED';
361 $err->throw;
362 };
363
364 $WIKI->{config}->{catch}->{formatter_view}
365 = catch Message::Util::Formatter::error with {
366 my $err = shift;
367 my $wiki = $err->{-option}->{param}->{wiki};
368 SuikaWiki::Plugin->module_package ('Error')
369 ->reporting_formatting_template_error ($err, $wiki);
370 $wiki->view_in_mode (mode => '-error', method => 'GET');
371 throw SuikaWiki::View::Implementation::error
372 type => 'ERROR_REPORTED';
373 };
374
375 $WIKI->{config}->{catch}->{formatter_view_error}
376 = catch Message::Util::Formatter::error with {
377 my $err = shift;
378 my $wiki = $err->{-option}->{param}->{wiki};
379 SuikaWiki::Plugin->module_package ('Error')
380 ->reporting_formatting_template_error ($err, $wiki);
381 $wiki->view_in_mode (mode => '-error-error', method => 'GET');
382 throw SuikaWiki::View::Implementation::error
383 type => 'ERROR_REPORTED';
384 };
385
386 ## Main
387 try {
388 $WIKI->view_in_mode
389 (mode => $WIKI->{var}->{mode},
390 method => $WIKI->{input}->meta_variable ('REQUEST_METHOD'));
391 } $catcher;
392 exit;
393 END {
394 try {
395 $WIKI->exit;
396 } $catcher;
397 };
398
399 =head1 NAME
400
401 lib/suikawiki.pl --- SuikaWiki : WikiEngine driver for HTTP CGI
402
403 =head1 LICENSE
404
405 Copyright 2000-2003 Wakaba <w@suika.fam.cx>, et. al
406
407 This program is free software; you can redistribute it and/or
408 modify it under the same terms as Perl itself.
409
410 =cut
411
412 1; # $Date: 2003/12/01 07:45:11 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24