1
# See bottom of file for license and copyright information
4
---+!! package Foswiki::Engine
6
The engine class is a singleton that implements details about Foswiki's
7
execution mode. This is the base class and implements basic behavior.
9
Each engine should inherits from this and overload methods necessary
10
to achieve correct behavior.
14
package Foswiki::Engine;
23
---++ ClassMethod new() -> $engine
25
Constructs an engine object.
31
my $class = ref($proto) || $proto;
33
return bless $this, $class;
38
---++ ObjectMethod run()
40
Start point to Runtime Engines.
46
my $req = $this->prepare;
48
my $res = Foswiki::UI::handleRequest($req);
49
$this->finalize( $res, $req );
55
---++ ObjectMethod prepare() -> $req
57
Initialize a Foswiki::Request object by calling many preparation methods
58
and returns it, or a status code in case of error.
66
$req = Foswiki::Request->new();
67
$this->prepareConnection($req);
68
$this->prepareQueryParameters($req);
69
$this->prepareHeaders($req);
70
$this->prepareCookies($req);
71
$this->preparePath($req);
72
$this->prepareBody($req);
73
$this->prepareBodyParameters($req);
74
$this->prepareUploads($req);
76
catch Foswiki::EngineException with {
78
my $res = $e->{response};
79
unless ( defined $res ) {
80
$res = new Foswiki::Response();
81
$res->header( -type => 'text/html', -status => $e->{status} );
82
my $html = CGI::start_html( $e->{status} . ' Bad Request' );
83
$html .= CGI::h1('Bad Request');
84
$html .= CGI::p( $e->{reason} );
85
$html .= CGI::end_html();
88
$this->finalizeError($res);
93
my $res = Foswiki::Response->new();
94
$res->header( -type => 'text/plain' );
97
# output the full message and stacktrace to the browser
98
$res->print( $e->stringify() );
101
my $mess = $e->stringify();
104
# tell the browser where to look for more help
106
'Foswiki detected an internal error - please check your Foswiki logs and webserver logs for more information.'
108
$mess =~ s/ at .*$//s;
110
# cut out pathnames from public announcement
111
$mess =~ s#/[\w./]+#path#g;
115
$this->finalizeError($res);
116
return 500; # Internal server error
123
---++ ObjectMethod prepareConnection( $req )
125
Abstract method, must be defined by inherited classes.
126
* =$req= - Foswiki::Request object to populate
128
Should fill remoteAddr, method and secure fields of =$req= object.
132
sub prepareConnection { }
136
---++ ObjectMethod prepareQueryParameters( $req, $queryString )
138
Should fill $req's query parameters field.
140
This method populates $req as it should if given $queryString parameter.
141
Subclasses may redefine this method and call SUPER with query string obtained.
145
sub prepareQueryParameters {
146
my ( $this, $req, $queryString ) = @_;
147
my @pairs = split /[&;]/, $queryString;
148
my ( $param, $value, %params, @plist );
149
foreach my $pair (@pairs) {
150
( $param, $value ) = split('=', $pair, 2);
152
if ( defined $value ) {
154
$value =~ s/%([0-9A-F]{2})/chr(hex($1))/gei;
156
if ( defined $param ) {
158
$param =~ s/%([0-9A-F]{2})/chr(hex($1))/gei;
159
push @{ $params{$param} }, $value;
163
foreach my $param (@plist) {
164
$req->queryParam( $param, $params{$param} );
170
---++ ObjectMethod prepareHeaders( $req )
172
Abstract method, must be defined by inherited classes.
173
* =$req= - Foswiki::Request object to populate
175
Should fill $req's headers and remoteUser fields.
179
sub prepareHeaders { }
183
---++ ObjectMethod preparePath( $req )
185
Abstract method, must be defined by inherited classes.
186
* =$req= - Foswiki::Request object to populate
188
Should fill $req's uri and pathInfo fields.
196
---++ ObjectMethod prepareCookies( $req )
198
* =$req= - Foswiki::Request object to populate
200
Should fill $req's cookie field. This method take cookie data from
201
previously populated headers field and initializes from it. Maybe
202
doesn't need to overload in children classes.
207
my ( $this, $req ) = @_;
208
eval { require CGI::Cookie };
209
throw Error::Simple($@) if $@;
210
$req->cookies( scalar CGI::Cookie->parse( $req->header('Cookie') ) )
211
if $req->header('Cookie');
216
---++ ObjectMethod prepareBody( $req )
218
Abstract method, must be defined by inherited classes.
219
* =$req= - Foswiki::Request object to populate
221
Should perform any initialization tasks related to body processing.
229
---++ ObjectMethod prepareBodyParameters( $req )
231
Abstract method, must be defined by inherited classes.
232
* =$req= - Foswiki::Request object to populate
234
Should fill $req's body parameters.
238
sub prepareBodyParameters { }
242
---++ ObjectMethod prepareUploads( $req )
244
Abstract method, must be defined by inherited classes.
245
* =$req= - Foswiki::Request object to populate
247
Should fill $req's uploads field. Its a hashref whose keys are
248
parameter names and values Foswiki::Request::Upload objects.
252
sub prepareUploads { }
256
---++ ObjectMethod finalize($res, $req)
258
Finalizes the request by calling many methods to send response to client and
259
take any appropriate finalize actions, such as delete temporary files.
260
* =$res= is the Foswiki::Response object
261
* =$req= it the Foswiki::Request object.
266
my ( $this, $res, $req ) = @_;
267
$this->finalizeUploads($res, $req);
268
$this->finalizeHeaders( $res, $req );
269
$this->finalizeBody($res);
274
---++ ObjectMethod finalizeUploads( $res, $req )
276
Abstract method, must be defined by inherited classes.
277
* =$res= - Foswiki::Response object to get data from
278
* =$req= - Foswiki::Request object to get data from
280
Should delete any temp files created in preparation phase.
284
sub finalizeUploads { }
288
---++ ObjectMethod finalizeError( $res )
290
Called if some engine especific error happens.
292
* =$res= - Foswiki::Response object to get data from
297
my ( $this, $res ) = @_;
298
$this->finalizeHeaders($res);
299
$this->finalizeBody($res);
304
---++ ObjectMethod finalizeHeaders( $res, $req )
306
Base method, must be redefined by inherited classes. For convenience
307
this method deals with HEAD requests related stuff. Children classes
309
* =$res= - Foswiki::Response object to get data from
310
* =$req= - Foswiki::Request object to get data from
312
Should call finalizeCookies and then send $res' headers to client.
316
sub finalizeHeaders {
317
my ( $this, $res, $req ) = @_;
318
$this->finalizeCookies($res);
319
if ( $req && $req->method() && uc($req->method()) eq 'HEAD' ) {
321
$res->deleteHeader('Content-Length');
327
---++ ObjectMethod finalizeCookies( $res )
329
* =$res= - Foswiki::Response object to both get data from and populate
331
Should populate $res' headers field with cookies, if any.
335
sub finalizeCookies {
336
my ( $this, $res ) = @_;
338
# SMELL: Review comment below, from CGI:
339
# if the user indicates an expiration time, then we need
340
# both an Expires and a Date header (so that the browser is
342
$res->pushHeader( 'Set-Cookie',
343
Scalar::Util::blessed $_
344
&& $_->isa('CGI::Cookie') ? $_->as_string : $_ )
345
foreach $res->cookies;
350
---++ ObjectMethod finalizeBody( $res )
352
* =$res= - Foswiki::Response object to get data from
354
Should send $res' body to client. This method calls =write()=
355
as needed, sou engines should redefine that method insted of this one.
360
my ( $this, $res ) = @_;
361
my $body = $res->body;
363
$this->prepareWrite($res);
364
if ( Scalar::Util::blessed($body) && $body->can('read')
365
or ref $body eq 'GLOB' )
367
while ( !eof $body ) {
368
read $body, my $buffer, 4096;
369
last unless $this->write($buffer);
380
---++ ObjectMethod prepareWrite( $res )
382
Abstract method, must be defined by inherited classes.
383
* =$res= - Foswiki::Response object to get data from
385
Shold perform any task needed before writing.
386
That's ok if none needed ;-)
394
---++ ObjectMethod write( $buffer )
396
Abstract method, must be defined by inherited classes.
397
* =$buffer= - chunk of data to be sent
399
Should send $buffer to client.
404
ASSERT('Pure virtual method - should never be called');
409
# Module of Foswiki - The Free and Open Source Wiki, http://foswiki.org/
411
# Copyright (C) 2008-2009 Foswiki Contributors. Foswiki Contributors
412
# are listed in the AUTHORS file in the root of this distribution.
413
# NOTE: Please extend that file, not this notice.
415
# Additional copyrights apply to some or all of the code in this
418
# Copyright (C) 1999-2007 Peter Thoeny, peter@thoeny.org
419
# and TWiki Contributors. All Rights Reserved. TWiki Contributors
420
# are listed in the AUTHORS file in the root of this distribution.
422
# This module is based/inspired on Catalyst framework. Refer to
424
# http://search.cpan.org/~mramberg/Catalyst-Runtime-5.7010/lib/Catalyst.pm
426
# for credits and liscence details.
428
# This program is free software; you can redistribute it and/or
429
# modify it under the terms of the GNU General Public License
430
# as published by the Free Software Foundation; either version 2
431
# of the License, or (at your option) any later version. For
432
# more details read LICENSE in the root of this distribution.
434
# This program is distributed in the hope that it will be useful,
435
# but WITHOUT ANY WARRANTY; without even the implied warranty of
436
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
438
# As per the GPL, removal of this notice is prohibited.