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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.24 - (show annotations) (download)
Sun Feb 1 12:25:26 2004 UTC (21 years, 5 months ago) by wakaba
Branch: MAIN
Changes since 1.23: +103 -58 lines
File MIME type: text/plain
(main::_rfc3339_date, SuikaWiki::Plugin::get_data): Removed

1 =head1 NAME
2
3 suikawiki.pl - SuikaWiki Driver as HTTP CGI Script (SWHCS)
4
5 =head1 DESCRIPTION
6
7 This script is a WikiDriver for SuikaWiki, working as HTTP CGI script.
8 With this script, SuikaWiki WikiEngine can be controled via remote WWW
9 user agents.
10
11 This file is part of SuikaWiki.
12
13 =cut
14
15 package wiki::driver::http;
16 use strict;
17 our $VERSION = do{my @r=(q$Revision: 1.23 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
18
19 ## These lines should be removed after utf8 support
20 BEGIN {
21 $Message::Util::Formatter::Base::Token = qr/[\w._+\x80-\xFF-]+/;
22 require Message::Util::Formatter::Base;
23 }
24
25 ## -- Constructing a new instance of the WikiEngine --
26
27 require SuikaWiki::Implementation;
28 our $WIKI = SuikaWiki::Implementation->new;
29
30 ## -- Registering Version of the WikiDriver --
31
32 $WIKI->{driver_name} = 'SWHCS';
33 $WIKI->{driver_version} = $VERSION;
34 $WIKI->{driver_uri_reference}
35 = q<http://suika.fam.cx/~wakaba/-temp/wiki/wiki?SWHCS>;
36
37 ## -- Preparing Dying Message as HTTP Response --
38
39 require SuikaWiki::Output::CGICarp;
40 $SuikaWiki::Output::CGICarp::CUSTOM_REASON_TEXT = 'Internal WikiEngine Error';
41 CGI::Carp::set_message (sub {
42 my $msg = shift; ## Already escaped
43 my $wiki_name_version = sprintf '%s/%s %s/%s',
44 $WIKI->{driver_name}, $WIKI->{driver_version},
45 $WIKI->{engine_name}, $WIKI->{engine_version};
46 my $trace = Carp::longmess ();
47 for ($trace, $wiki_name_version) {
48 s/&/&amp;/g; s/</&lt;/g; s/([^\x20-\x7E])/sprintf '&#x%02X;', ord $1/ge;
49 };
50 print <<" EOH";
51 <!DOCTYPE html SYSTEM>
52 <title lang="en">500 Internal WikiEngine Error</title>
53 <h1 lang="en">Internal WikiEngine Error</h1>
54 <p>$msg</p>
55 <p>$trace</p>
56 <address>$wiki_name_version</address>
57 EOH
58 });
59
60 ## -- Loading Configuration File --
61
62 require 'wikidata/suikawiki-config.ph';
63 config ($WIKI);
64
65 ## -- Loading Modules --
66
67 use SuikaWiki::DB::Util::Error;
68 require SuikaWiki::Name::Space;
69
70 ## -- Transitional Functions --
71
72 # [to be obsolete] ->Message::MIME::Charset
73 sub main::code_convert {
74 my ($contentref, $code, $srccode) = @_;
75 return $$contentref if $$contentref !~ /[^\x21-\x7E]/;
76 require Jcode;
77 $code ||= $WIKI->{config}->{charset}->{internal};
78 for ($code, $srccode) {
79 s/[^0-9A-Za-z_.+-]+//g;
80 if ($_ eq 'euc-jp') { $_ = 'euc' }
81 elsif ($_ eq 'iso-2022-jp') { $_ = 'jis' }
82 elsif ($_ eq 'utf-8') { $_ = 'utf8' }
83 elsif ($_ eq 'shift_jis') { $_ = 'sjis' }
84 }
85 if ($code eq 'iso-8859-1') {
86 return $$contentref; ## TODO:
87 }
88 $$contentref = Jcode->new ($contentref, $srccode)
89 ## Normalize FULLWIDTH characters and IDEOGRAPHIC SPACE
90 ->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&,.:;?!`^_/|()[]{}+$%#*@=>< '"~-))
91 # ->tr (qq(\x8E\xDE\x8E\xDF) => qq(\xA1\xAB\xA1\xAC))
92 ->h2z (1)
93 ->$code;
94 return $$contentref;
95 }
96
97 ## -- Initializing WikiPlugin --
98
99 $WIKI->init_plugin; ## WikiPlugin manager
100
101 ## -- Initializing WikiView --
102
103 $WIKI->init_view; ## WikiView manager
104 $WIKI->{view}->register_common_modes;
105
106 ## WikiView manager error handler
107 push @{$WIKI->{event}->{view_error}}, sub {
108 my ($wiki, $event) = @_;
109 SuikaWiki::Plugin->module_package ('Error')
110 ->report_error_simple
111 ($wiki, WikiView => $event->{error}->text,
112 -trace => 1)
113 if $event->{error}->{-def}->{level} eq 'fatal'
114 or $wiki->{config}->{debug}->{view};
115 unless ($event->{error}->{-def}->{level} eq 'fatal'
116 or $event->{error}->{-def}->{level} eq 'stop') {
117 $event->{cancel} = 1;
118 }
119 };
120
121 ## "view_in_mode" method definition
122 push @{$WIKI->{event}->{view_in_mode}}, sub {
123 my ($wiki, $opt) = @_;
124 my $arg = {condition => {mode => $opt->{mode} || '-error',
125 output => 'http-cgi',
126 http_method => $opt->{method} || 'GET'}};
127 my $viewobj = $wiki->{view}->instantiate ($opt->{mode} || '-error', $arg);
128 if (ref $viewobj) {
129 $viewobj->main ($arg);
130 } elsif ($opt->{mode} ne '-error') {
131 report SuikaWiki::View::Implementation::error
132 -type => 'WARN_VIEW_NOT_DEFINED', condition => $arg->{condition},
133 -object => $wiki->{view}, method => 'view_in_mode';
134 $wiki->view_in_mode (mode => '-error', method => 'GET');
135 ## TODO: cache control for non-GET
136 } else {
137 die "Some error occured. Additionally, error reporting mode not defined";
138 }
139 };
140
141 ## WikiView formatting template error handler
142 $WIKI->{config}->{catch}->{formatter_view}
143 = catch Message::Util::Formatter::error with {
144 my $err = shift;
145 my $wiki = $err->{option}->{param}->{wiki};
146 SuikaWiki::Plugin->module_package ('Error')
147 ->reporting_formatting_template_error ($err, $wiki,
148 trace => 1);
149 $wiki->view_in_mode (mode => '-error', method => 'GET');
150 throw SuikaWiki::View::Implementation::error
151 -type => 'ERROR_REPORTED';
152 };
153
154 ## WikiView formatting template error handler (occured in "-error" mode)
155 $WIKI->{config}->{catch}->{formatter_view_error}
156 = catch Message::Util::Formatter::error with {
157 my $err = shift;
158 my $wiki = $err->{option}->{param}->{wiki};
159 SuikaWiki::Plugin->module_package ('Error')
160 ->reporting_formatting_template_error ($err, $wiki,
161 trace => 1);
162 $wiki->view_in_mode (mode => '-error-error', method => 'GET');
163 throw SuikaWiki::View::Implementation::error
164 -type => 'ERROR_REPORTED';
165 };
166
167 ## -- Preparing for WikiDatabase Error Reports --
168 {
169 my $error_report = sub {
170 my ($wiki, $err) = @_;
171 my $report = ($err->{-def}->{level} eq 'fatal' or
172 $err->{-def}->{level} eq 'stop' or
173 $wiki->{config}->{debug}->{db}) ? 1 : 0;
174 if ($report and $wiki->{config}->{path_to}->{db__content__error_log}) {
175 my $err_msg = caller (1).($err->{method}? '->'.$err->{method}: '').': '
176 .(defined $err->{file}? $err->{file} . ': ' : '')
177 .(defined $err->{prop}? $err->{prop} . ': ' : '')
178 .(defined $err->{key}? join ('//', @{$err->{key}}).': ':'')
179 . $err->text;
180 open LOG, '>>', $wiki->{config}->{path_to}->{db__content__error_log};
181 print LOG scalar (gmtime), " @{[$$]} {$err->{-def}->{level}}: ",
182 $err_msg, "\n";
183 close LOG;
184 }
185 SuikaWiki::Plugin->module_package ('WikiDB')
186 ->reporting_error ($err, $wiki) if $report;
187 if ($err->{-def}->{level} eq 'fatal'
188 # or $err->{-def}->{level} eq 'stop' ## for debug
189 ) {
190 $wiki->view_in_mode (mode => '-wdb--fatal-error');
191 throw SuikaWiki::DB::Util::Error -type => 'ERROR_REPORTED';
192 }
193 };
194 unshift @{$WIKI->{event}->{database_loaded}}, sub {
195 my $wiki = shift;
196 unshift @{$wiki->{db}->{event}->{error}}, sub {
197 my ($db, $event) = @_;
198 $error_report->($wiki, $event->{error});
199 if ($event->{error}->{-type} eq 'INFO_DB_PROP_OPENED') {
200 unshift @{$db->{prop}->{$event->{error}->{prop}}->{-db}
201 ->{event}->{error}}, sub {
202 my ($db, $event) = @_;
203 $error_report->($wiki, $event->{error});
204 };
205 }
206 }; # database error
207 }; # database_loaded
208 }
209
210 ## -- Preparing for Misc. Error Reports --
211
212 if ($WIKI->{config}->{debug}->{general}) {
213 $main::SIG{__WARN__} = sub {
214 push @{$WIKI->{var}->{error}||=[]}, {
215 description => Message::Markup::XML::Node->new
216 (type => '#text',
217 value => $_[0]),
218 };
219 };
220 }
221
222 ## -- (Declaring for) Initializing $wiki->{var} --
223
224 push @{$WIKI->{event}->{setting_initial_variables}}, sub {
225 my $wiki = shift;
226 ## Database access mode
227 $wiki->{var}->{db}->{read_only}->{'#default'} = 1;
228
229 ## Input parameter
230 require SuikaWiki::Input::HTTP;
231 $wiki->{input} = SuikaWiki::Input::HTTP->new (wiki => $wiki);
232 $wiki->{input}->{decoder}->{'#default'} = sub {
233 my ($http, $s, $temp_params) = @_;
234 return main::code_convert (\$s, $wiki->{config}->{charset}->{internal},
235 lc (@{$temp_params->{_charset_}||[]}[0])
236 || $wiki->{config}->{charset}->{uri_param});
237 };
238
239 ## User agent negotiation
240 $wiki->{var}->{client}->{user_agent_name}
241 = $wiki->{input}->meta_variable ('HTTP_USER_AGENT');
242 $wiki->{var}->{client}->{used_for_negotiate} = ['User-Agent'];
243 my $dg = SuikaWiki::Plugin->module_package ('Downgrade');
244 $dg->set_downgrade_flags ($wiki) if $dg;
245
246 ## TODO: PATH_INFO support
247
248 ## URI query parameter
249 my $page = $wiki->{input}->meta_variable ('QUERY_STRING');
250 if ($page and not (index ($page, '=') > -1)) {
251 $page =~ tr/+/ /;
252 $page =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack 'C', hex $1/ge;
253 $page = main::code_convert
254 (\$page, $wiki->{config}->{charset}->{internal},
255 $wiki->{config}->{charset}->{uri_query});
256 } else {
257 $page = $wiki->{input}->parameter ('mypage');
258 }
259
260 ## TODO: SuikaWiki 3 WikiName
261 $page =~ tr/\x00-\x20\x7F//d;
262 $page = SuikaWiki::Name::Space::normalize_name ($page);
263 if ($page) {
264 $wiki->{var}->{page} = [split '//', $page];
265 } else {
266 $wiki->{var}->{page} = $wiki->{config}->{page}->{Default};
267 }
268
269 ## Mode
270 my $mode = $wiki->{input}->parameter ('mode')
271 || $wiki->{input}->parameter ('mycmd') ## for compatibility with
272 || 'default'; ## YukiWiki and SuikaWiki 2
273 $mode =~ tr/-/_/;
274 if ($mode eq 'default' or $mode =~ /[^0-9A-Za-z_]/) {
275 my $cookie = $wiki->{input}->meta_variable ('HTTP_COOKIE');
276 ## BUG: this code is not strict
277 if ($cookie =~ /SelectedMode=([0-9A-Za-z_-]+)/) {
278 $mode = $1; $mode =~ tr/-/_/;
279 } else {
280 $mode = 'read';
281 }
282 push @{$wiki->{var}->{client}->{used_for_negotiate}}, 'Cookie';
283 }
284 $wiki->{var}->{mode} = $mode;
285 };
286
287
288 #### ---- Per-Session ----
289
290 ## -- Initializing $wiki->{var} (Actual) --
291
292 $WIKI->init_variables; ## Per-session variables
293
294 ## -- Instantiating WikiView --
295
296 try {
297 $WIKI->view_in_mode
298 (mode => $WIKI->{var}->{mode},
299 method => $WIKI->{input}->meta_variable ('REQUEST_METHOD'));
300 } catch SuikaWiki::DB::Util::Error with {
301 my $err = shift;
302 unless ($err->{-type} eq 'ERROR_REPORTED') {
303 $WIKI->view_in_mode (mode => '-wdb--fatal-error');
304 }
305 } catch SuikaWiki::View::Implementation::error with {
306 my $err = shift;
307 $err->throw unless $err->{-type} eq 'ERROR_REPORTED';
308 } finally {
309 $WIKI->close_input;
310 $WIKI->close_db;
311 };
312 exit;
313
314
315
316 ## -- Terminating WikiEngine --
317
318 END {
319 $WIKI->exit;
320 }
321
322 =head1 SYNOPSIS
323
324 In your C<suikawiki.cgi>, write as:
325
326 #!/usr/bin/perl
327 BEGIN { $0 = ''.$0 }
328 use strict;
329 use lib qw(lib);
330 use CGI::Carp qw(fatalsToBrowser);
331 require 'suikawiki.pl';
332
333 =head1 SEE ALSO
334
335 <http://suika.fam.cx/~wakaba/-temp/wiki/wiki?SuikaWiki>,
336 <http://suika.fam.cx/~wakaba/-temp/wiki/wiki?SWHCS>,
337 C<wiki.cgi>, C<wikidata/suikawiki-config.ph>,
338 C<SuikaWiki::Implementation>
339
340 =head1 LICENSE
341
342 Copyright 2000-2004 Wakaba <w@suika.fam.cx>, et. al. All rights reserved.
343
344 This program is free software; you can redistribute it and/or
345 modify it under the same terms as Perl itself.
346
347 =cut
348
349 1; # $Date: 2004/01/16 08:01:05 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24