line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package XAO::Web; |
2
|
22
|
|
|
22
|
|
199180
|
use warnings; |
|
22
|
|
|
|
|
53
|
|
|
22
|
|
|
|
|
757
|
|
3
|
22
|
|
|
22
|
|
136
|
use strict; |
|
22
|
|
|
|
|
60
|
|
|
22
|
|
|
|
|
413
|
|
4
|
22
|
|
|
22
|
|
117
|
use Encode; |
|
22
|
|
|
|
|
46
|
|
|
22
|
|
|
|
|
1648
|
|
5
|
22
|
|
|
22
|
|
160
|
use Error qw(:try); |
|
22
|
|
|
|
|
49
|
|
|
22
|
|
|
|
|
128
|
|
6
|
22
|
|
|
22
|
|
3117
|
use XAO::Utils; |
|
22
|
|
|
|
|
47
|
|
|
22
|
|
|
|
|
1295
|
|
7
|
22
|
|
|
22
|
|
2896
|
use XAO::Projects; |
|
22
|
|
|
|
|
7044
|
|
|
22
|
|
|
|
|
960
|
|
8
|
22
|
|
|
22
|
|
2541
|
use XAO::Objects; |
|
22
|
|
|
|
|
18855
|
|
|
22
|
|
|
|
|
712
|
|
9
|
22
|
|
|
22
|
|
10533
|
use XAO::SimpleHash; |
|
22
|
|
|
|
|
45255
|
|
|
22
|
|
|
|
|
810
|
|
10
|
22
|
|
|
22
|
|
8846
|
use XAO::PageSupport; |
|
22
|
|
|
|
|
115
|
|
|
22
|
|
|
|
|
706
|
|
11
|
22
|
|
|
22
|
|
9021
|
use XAO::Templates; |
|
22
|
|
|
|
|
64
|
|
|
22
|
|
|
|
|
740
|
|
12
|
22
|
|
|
22
|
|
216
|
use XAO::Errors qw(XAO::Web); |
|
22
|
|
|
|
|
53
|
|
|
22
|
|
|
|
|
141
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
############################################################################### |
15
|
|
|
|
|
|
|
# XAO::Web version number. Hand changed with every release! |
16
|
|
|
|
|
|
|
# |
17
|
22
|
|
|
22
|
|
7677
|
use vars qw($VERSION); |
|
22
|
|
|
|
|
46
|
|
|
22
|
|
|
|
|
88201
|
|
18
|
|
|
|
|
|
|
$VERSION='1.90'; |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
############################################################################### |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=head1 NAME |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
XAO::Web - XAO Web Developer, dynamic content building suite |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
=head1 SYNOPSIS |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
use XAO::Web; |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
my $web=XAO::Web->new(sitename => 'test'); |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
$web->execute(cgi => $cgi, |
33
|
|
|
|
|
|
|
path => '/index.html'); |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
my $config=$web->config; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
$config->clipboard->put(foo => 'bar'); |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
=head1 DESCRIPTION |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
Please read L for general overview and setup |
42
|
|
|
|
|
|
|
instructions, and please read L for an overview |
43
|
|
|
|
|
|
|
of the templating system. Check also misc/samplesite for code examples |
44
|
|
|
|
|
|
|
and a generic site setup. |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
XAO::Web module provides a frameworks for loading site configuration and |
47
|
|
|
|
|
|
|
executing objects and templates in the site context. It is used in |
48
|
|
|
|
|
|
|
scripts and in Apache web server handler to generate actual web pages |
49
|
|
|
|
|
|
|
content. |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
Normally a developer does not need to use XAO::Web directly. |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=head1 SITE INITIALIZATION |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
When XAO::Web creates a new site (for mod_perl that happens only once |
56
|
|
|
|
|
|
|
during each instance on Apache lifetime) it first loads new 'Config' |
57
|
|
|
|
|
|
|
object using XAO::Objects' new() method and site name it knows. If site |
58
|
|
|
|
|
|
|
overrides Config - it loads site specific Config, if not - the systme |
59
|
|
|
|
|
|
|
one. |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
After the object is created XAO::Web embeds two standard additional |
62
|
|
|
|
|
|
|
configuration objects into it: |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=over |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=item hash |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
Hash object is primarily used to keep site configuration parameters. It |
69
|
|
|
|
|
|
|
is just a XAO::SimpleHash object and most of its methods get embedded - |
70
|
|
|
|
|
|
|
get, put, getref, delete, defined, exists, keys, values, contains. |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=item web |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
Web configuration embeds methods that allow cookie, clipboard and |
75
|
|
|
|
|
|
|
cgi manipulations -- add_cookie, cgi, clipboard, cookies, header, |
76
|
|
|
|
|
|
|
header_args. |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=back |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
After that XAO::Web calls init() method on the Config object which |
81
|
|
|
|
|
|
|
is supposed to finish configuration set up and usually stuffs some |
82
|
|
|
|
|
|
|
parameters into 'hash', then connects to a database and embeds database |
83
|
|
|
|
|
|
|
configuration object into the Config object as well. Refer to |
84
|
|
|
|
|
|
|
L for an example of site specific Config object and |
85
|
|
|
|
|
|
|
init() method. |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
When object initialization is completed the Config object is placed into |
88
|
|
|
|
|
|
|
XAO::Projects registry and is retrieved from there on next access to the |
89
|
|
|
|
|
|
|
same site in case of mod_perl. |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
B that means that if you are embedding a site specific version |
92
|
|
|
|
|
|
|
of an object during initialisation you need to pass 'sitename' into |
93
|
|
|
|
|
|
|
XAO::Objects' new() method. |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=head1 METHODS |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
Methods of XAO::Web objects include: |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
=over |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=cut |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
############################################################################### |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
sub analyze ($$;$$); |
106
|
|
|
|
|
|
|
sub clipboard ($); |
107
|
|
|
|
|
|
|
sub config ($); |
108
|
|
|
|
|
|
|
sub execute ($%); |
109
|
|
|
|
|
|
|
sub new ($%); |
110
|
|
|
|
|
|
|
sub set_current ($); |
111
|
|
|
|
|
|
|
sub sitename ($); |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
############################################################################### |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=item analyze ($;$$) |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
Checks how to display the given path (scalar or split up array |
118
|
|
|
|
|
|
|
reference). Always returns valid results or throws an error if that |
119
|
|
|
|
|
|
|
can't be accomplished. |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
Returns hash reference: |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
prefix => longest matching prefix (directory in case of template found) |
124
|
|
|
|
|
|
|
path => path to the page after the prefix |
125
|
|
|
|
|
|
|
fullpath => full path from original query |
126
|
|
|
|
|
|
|
objname => object name that will serve this path |
127
|
|
|
|
|
|
|
objargs => object args hash (may be empty) |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
Optional second argument can be used to enforce a specific site name. |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
Optional third argument must be used to allow returning records of types |
132
|
|
|
|
|
|
|
other than 'xaoweb'. This is used by Apache::XAO to get 'maptodir' and |
133
|
|
|
|
|
|
|
'external' mappings. Default is to look for xaoweb only records. |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=cut |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
sub analyze ($$;$$) { |
138
|
84
|
|
|
84
|
1
|
187
|
my ($self,$patharr,$sitename,$allow_other_types)=@_; |
139
|
|
|
|
|
|
|
|
140
|
84
|
50
|
|
|
|
184
|
$patharr=[ split(/\/+/,$patharr) ] unless ref $patharr; |
141
|
|
|
|
|
|
|
|
142
|
84
|
|
66
|
|
|
570
|
shift @$patharr while @$patharr && !length($patharr->[0]); |
143
|
84
|
|
|
|
|
190
|
unshift(@$patharr,''); |
144
|
84
|
|
|
|
|
243
|
my $path=join('/',@$patharr); |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
# Looking for the object matching the path. |
147
|
|
|
|
|
|
|
# |
148
|
84
|
|
|
|
|
167
|
my $siteconfig=$self->config; |
149
|
84
|
|
|
|
|
1652
|
my $table=$siteconfig->get('path_mapping_table'); |
150
|
84
|
50
|
|
|
|
3683
|
if($table) { |
151
|
84
|
|
|
|
|
235
|
for(my $i=@$patharr; $i>=0; $i--) { |
152
|
248
|
100
|
|
|
|
504
|
my $dir=$i ? join('/',@{$patharr}[0..$i-1]) : ''; |
|
167
|
|
|
|
|
379
|
|
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
my $od=$table->{$dir} || |
155
|
|
|
|
|
|
|
$table->{'/'.$dir} || |
156
|
|
|
|
|
|
|
$table->{$dir.'/'} || |
157
|
248
|
|
33
|
|
|
1431
|
$table->{'/'.$dir.'/'}; |
158
|
248
|
100
|
|
|
|
658
|
next unless defined $od; |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
## |
161
|
|
|
|
|
|
|
# If $od is an empty string or an empty array reference -- |
162
|
|
|
|
|
|
|
# this means that we need to fall back to default handler |
163
|
|
|
|
|
|
|
# for that path. |
164
|
|
|
|
|
|
|
# |
165
|
|
|
|
|
|
|
# The same happens for 'default' type in a hash reference. |
166
|
|
|
|
|
|
|
# |
167
|
3
|
|
|
|
|
11
|
my $rhash; |
168
|
3
|
50
|
|
|
|
22
|
if(ref($od) eq 'HASH') { |
|
|
0
|
|
|
|
|
|
169
|
3
|
|
50
|
|
|
17
|
my $type=$od->{'type'} || 'xaoweb'; |
170
|
3
|
50
|
0
|
|
|
13
|
if($type eq 'default') { |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
171
|
0
|
|
|
|
|
0
|
last; |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
elsif($type eq 'xaoweb') { |
174
|
3
|
50
|
|
|
|
13
|
if(!$od->{'objname'}) { |
175
|
0
|
|
|
|
|
0
|
throw XAO::E::Web "analyze - no objname/objargs for '$dir'"; |
176
|
|
|
|
|
|
|
} |
177
|
3
|
|
|
|
|
17
|
$rhash=merge_refs($od); |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
elsif($allow_other_types) { |
180
|
0
|
|
|
|
|
0
|
$rhash=merge_refs($od); |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
elsif($od->{'xaoweb'} && ref($od->{'xaoweb'}) eq 'HASH') { |
183
|
0
|
|
|
|
|
0
|
$rhash=merge_refs($od->{'xaoweb'}); |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
else { |
186
|
0
|
|
|
|
|
0
|
next; |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
elsif(ref($od) eq 'ARRAY') { |
190
|
0
|
0
|
|
|
|
0
|
last unless @$od; |
191
|
0
|
|
|
|
|
0
|
my %args; |
192
|
0
|
0
|
|
|
|
0
|
if(scalar(@{$od})%2 == 1) { |
|
0
|
|
|
|
|
0
|
|
193
|
0
|
|
|
|
|
0
|
%args=@{$od}[1..$#{$od}]; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
else { |
196
|
0
|
|
|
|
|
0
|
throw XAO::E::Web "analyze - odd number of arguments in the mapping table, dir=$dir, objname=$od->[0]"; |
197
|
|
|
|
|
|
|
} |
198
|
0
|
|
|
|
|
0
|
$rhash={ |
199
|
|
|
|
|
|
|
type => 'xaoweb', |
200
|
|
|
|
|
|
|
objname => $od->[0], |
201
|
|
|
|
|
|
|
objargs => \%args, |
202
|
|
|
|
|
|
|
}; |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
else { |
205
|
0
|
0
|
|
|
|
0
|
last unless length($od); |
206
|
0
|
|
|
|
|
0
|
$rhash={ |
207
|
|
|
|
|
|
|
type => 'xaoweb', |
208
|
|
|
|
|
|
|
objname => $od, |
209
|
|
|
|
|
|
|
objargs => { }, |
210
|
|
|
|
|
|
|
}; |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
3
|
|
|
|
|
61
|
$rhash->{'path'}=join('/',@{$patharr}[$i..$#$patharr]); |
|
3
|
|
|
|
|
11
|
|
214
|
3
|
|
|
|
|
8
|
$rhash->{'patharr'}=$patharr; |
215
|
3
|
|
|
|
|
12
|
$rhash->{'prefix'}=$dir; |
216
|
3
|
|
|
|
|
11
|
$rhash->{'fullpath'}=$path; |
217
|
|
|
|
|
|
|
|
218
|
3
|
|
|
|
|
13
|
return $rhash; |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
} |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
## |
223
|
|
|
|
|
|
|
# Now looking for exactly matching template and returning Page |
224
|
|
|
|
|
|
|
# object if found. |
225
|
|
|
|
|
|
|
# |
226
|
81
|
|
|
|
|
256
|
my $filename=XAO::Templates::filename($path,$sitename); |
227
|
81
|
100
|
|
|
|
267
|
if($filename) { |
228
|
|
|
|
|
|
|
return { |
229
|
|
|
|
|
|
|
type => 'xaoweb', |
230
|
|
|
|
|
|
|
subtype => 'file', |
231
|
|
|
|
|
|
|
objname => 'Page', |
232
|
|
|
|
|
|
|
objargs => { }, |
233
|
|
|
|
|
|
|
path => $path, |
234
|
|
|
|
|
|
|
patharr => $patharr, |
235
|
|
|
|
|
|
|
fullpath => $path, |
236
|
80
|
|
|
|
|
234
|
prefix => join('/',@{$patharr}[0..($#$patharr-1)]), |
|
80
|
|
|
|
|
772
|
|
237
|
|
|
|
|
|
|
filename => $filename, |
238
|
|
|
|
|
|
|
}; |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
## |
242
|
|
|
|
|
|
|
# Nothing was found, returning Default object |
243
|
|
|
|
|
|
|
# |
244
|
|
|
|
|
|
|
return { |
245
|
1
|
|
|
|
|
9
|
type => 'xaoweb', |
246
|
|
|
|
|
|
|
subtype => 'notfound', |
247
|
|
|
|
|
|
|
objname => 'Default', |
248
|
|
|
|
|
|
|
path => $path, |
249
|
|
|
|
|
|
|
patharr => $patharr, |
250
|
|
|
|
|
|
|
fullpath => $path, |
251
|
|
|
|
|
|
|
prefix => '' |
252
|
|
|
|
|
|
|
}; |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
############################################################################### |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
=item clipboard () |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
Returns site clipboard object. |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
=cut |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
sub clipboard ($) { |
264
|
0
|
|
|
0
|
1
|
0
|
my $self=shift; |
265
|
0
|
|
|
|
|
0
|
return $self->config->clipboard; |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
############################################################################### |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=item config () |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
Returns site configuration object reference. |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=cut |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
sub config ($) { |
277
|
630
|
|
|
630
|
1
|
977
|
my $self=shift; |
278
|
630
|
|
33
|
|
|
6007
|
return $self->{'siteconfig'} || |
279
|
|
|
|
|
|
|
throw XAO::E::Web "config - no configuration object"; |
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
############################################################################### |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=item execute (%) |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
Executes given `path' using given `cgi' environment. Prints results to |
287
|
|
|
|
|
|
|
standard output and uses CGI object methods to send header. |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
B Execute() changes global projects context and is not re-entry safe |
290
|
|
|
|
|
|
|
currently! Meaning that if you create a XAO::Web object in any method |
291
|
|
|
|
|
|
|
called inside of execute() loop and then call execute() on that newly |
292
|
|
|
|
|
|
|
created XAO::Web object the system will fail and no useful results will |
293
|
|
|
|
|
|
|
be produced. |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
=cut |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
sub execute ($%) { |
298
|
11
|
|
|
11
|
1
|
32
|
my $self=shift; |
299
|
11
|
|
|
|
|
44
|
my $args=get_args(\@_); |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
# Setting dprint/eprint to Apache or PSGI methods if needed |
302
|
|
|
|
|
|
|
# |
303
|
11
|
|
|
|
|
166
|
my $old_logprint_handler; |
304
|
11
|
50
|
|
|
|
51
|
if($args->{'apache'}) { |
|
|
50
|
|
|
|
|
|
305
|
|
|
|
|
|
|
$old_logprint_handler=XAO::Utils::set_logprint_handler(sub { |
306
|
0
|
|
|
0
|
|
0
|
$args->{'apache'}->server->warn($_[0]); |
307
|
0
|
|
|
|
|
0
|
}); |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
elsif($args->{'psgi'}) { |
310
|
|
|
|
|
|
|
$old_logprint_handler=XAO::Utils::set_logprint_handler(sub { |
311
|
0
|
|
|
0
|
|
0
|
$args->{'psgi'}->{'psgi.errors'}->print($_[0]."\n"); |
312
|
0
|
|
|
|
|
0
|
}); |
313
|
|
|
|
|
|
|
} |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
# Setting the current project context to our site. |
316
|
|
|
|
|
|
|
# |
317
|
11
|
|
|
|
|
31
|
$self->set_current(); |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
# We check if the site has a mapping for '/internal-error' in |
320
|
|
|
|
|
|
|
# path_mapping_table. If it has we wrap process() into the try block |
321
|
|
|
|
|
|
|
# and execute /internal-error if we get an error. |
322
|
|
|
|
|
|
|
# |
323
|
11
|
|
|
|
|
30
|
my $pagetext; |
324
|
|
|
|
|
|
|
try { |
325
|
11
|
|
|
11
|
|
366
|
$pagetext=$self->process($args); |
326
|
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
otherwise { |
328
|
0
|
|
|
0
|
|
0
|
my $e=shift; |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
# Under mod_perl we get apache's internal exceptions for genuine apache |
331
|
|
|
|
|
|
|
# problems (timeouts, etc). These are not re-throwable apparently, |
332
|
|
|
|
|
|
|
# so we wrap them into Error::Simple. |
333
|
|
|
|
|
|
|
# |
334
|
0
|
0
|
|
|
|
0
|
if($e->isa('APR::Error')) { |
335
|
0
|
|
|
|
|
0
|
$e=Error::Simple->new("$e"); |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
$self->config->header_args( |
339
|
0
|
|
|
|
|
0
|
-Status => '500 Internal Error', |
340
|
|
|
|
|
|
|
-expires => 'now', |
341
|
|
|
|
|
|
|
-cache_control => 'no-cache', |
342
|
|
|
|
|
|
|
); |
343
|
|
|
|
|
|
|
|
344
|
0
|
|
0
|
|
|
0
|
my $edata=$self->clipboard->get('/internal_error') || { }; |
345
|
|
|
|
|
|
|
|
346
|
0
|
|
0
|
|
|
0
|
my $path=$edata->{'display_path'} || '/internal-error/index.html'; |
347
|
0
|
|
|
|
|
0
|
my $pd=$self->analyze($path); |
348
|
|
|
|
|
|
|
|
349
|
0
|
0
|
0
|
|
|
0
|
if($pd && $pd->{'type'} eq 'xaoweb' && $pd->{'objname'} ne 'Default') { |
|
|
|
0
|
|
|
|
|
350
|
0
|
|
|
|
|
0
|
eprint "$e"; |
351
|
|
|
|
|
|
|
|
352
|
0
|
|
0
|
|
|
0
|
$edata->{'message'}||="$e"; |
353
|
0
|
|
0
|
|
|
0
|
$edata->{'code'}||='UNKNOWN'; |
354
|
0
|
|
0
|
|
|
0
|
$edata->{'path'}||=$args->{'path'}; |
355
|
0
|
|
0
|
|
|
0
|
$edata->{'pagedesc'}||=$self->clipboard->get('pagedesc'); |
356
|
|
|
|
|
|
|
|
357
|
0
|
|
|
|
|
0
|
$self->clipboard->put(internal_error => $edata); |
358
|
|
|
|
|
|
|
|
359
|
0
|
|
|
|
|
0
|
$pagetext=$self->process($args,{ |
360
|
|
|
|
|
|
|
path => $path, |
361
|
|
|
|
|
|
|
template => undef, |
362
|
|
|
|
|
|
|
pagedesc => $pd, |
363
|
|
|
|
|
|
|
}); |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
else { |
366
|
0
|
0
|
|
|
|
0
|
XAO::Utils::set_logprint_handler($old_logprint_handler) if $old_logprint_handler; |
367
|
0
|
|
|
|
|
0
|
throw $e; |
368
|
|
|
|
|
|
|
} |
369
|
11
|
|
|
|
|
155
|
}; |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
# We need to call "header" for CGI to do its magic on it. We |
372
|
|
|
|
|
|
|
# typically will get an empty string in mod_perl environment, and the |
373
|
|
|
|
|
|
|
# header will be sent to Apache by CGI. |
374
|
|
|
|
|
|
|
# |
375
|
11
|
|
|
|
|
271
|
my $header=$self->config->header; |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
# If we get the header then it was not printed before and we are |
378
|
|
|
|
|
|
|
# expected to print out the page. This is almost always true except |
379
|
|
|
|
|
|
|
# when page includes something like Redirect object. |
380
|
|
|
|
|
|
|
# |
381
|
11
|
|
|
|
|
12845
|
my $result; |
382
|
11
|
50
|
|
|
|
31
|
if(defined $header) { |
383
|
11
|
50
|
|
|
|
57
|
if(my $env=$args->{'psgi'}) { |
|
|
50
|
|
|
|
|
|
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
# Can't use $header, need an array that includes header_args |
386
|
|
|
|
|
|
|
# and cookies. |
387
|
|
|
|
|
|
|
# |
388
|
|
|
|
|
|
|
$result=[ |
389
|
0
|
|
|
|
|
0
|
$args->{'cgi'}->psgi_header({ $self->config->header_array() }), |
390
|
|
|
|
|
|
|
[ $pagetext ], |
391
|
|
|
|
|
|
|
]; |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
elsif(my $r=$args->{'apache'}) { |
394
|
0
|
|
|
|
|
0
|
my $h=$self->config->header_args; |
395
|
|
|
|
|
|
|
|
396
|
0
|
0
|
0
|
|
|
0
|
if($mod_perl::VERSION && $mod_perl::VERSION >= 1.99) { |
397
|
|
|
|
|
|
|
# This is accomplished by CGI when config->header is |
398
|
|
|
|
|
|
|
# called above, and it does not work properly anyway |
399
|
|
|
|
|
|
|
# |
400
|
|
|
|
|
|
|
### while(my ($n,$v)=each %$h) { |
401
|
|
|
|
|
|
|
### dprint "n='$n' v='$v'"; |
402
|
|
|
|
|
|
|
### $r->headers_out->set($n => $v); |
403
|
|
|
|
|
|
|
### $r->err_headers_out->set($n => $v); |
404
|
|
|
|
|
|
|
### } |
405
|
0
|
0
|
|
|
|
0
|
$r->content_type('text/html') unless $r->content_type; |
406
|
|
|
|
|
|
|
} |
407
|
|
|
|
|
|
|
else { |
408
|
0
|
|
|
|
|
0
|
while(my ($n,$v)=each %$h) { |
409
|
0
|
|
|
|
|
0
|
$r->header_out($n => $v); |
410
|
0
|
|
|
|
|
0
|
$r->err_header_out($n => $v); |
411
|
|
|
|
|
|
|
} |
412
|
0
|
|
|
|
|
0
|
$r->send_http_header; |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
|
415
|
0
|
0
|
|
|
|
0
|
$r->print($pagetext) unless $r->header_only; |
416
|
|
|
|
|
|
|
} |
417
|
|
|
|
|
|
|
else { |
418
|
11
|
|
|
|
|
424
|
print $header, |
419
|
|
|
|
|
|
|
$pagetext; |
420
|
|
|
|
|
|
|
} |
421
|
|
|
|
|
|
|
} |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
# Cleaning up site configuration |
424
|
|
|
|
|
|
|
# |
425
|
11
|
|
|
|
|
50
|
$self->config->cleanup(mode => 'after'); |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
# Restoring the default dprint/eprint handling |
428
|
|
|
|
|
|
|
# |
429
|
11
|
50
|
|
|
|
38
|
XAO::Utils::set_logprint_handler($old_logprint_handler) if $old_logprint_handler; |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
# Only really needed for PSGI |
432
|
|
|
|
|
|
|
# |
433
|
11
|
|
|
|
|
39
|
return $result; |
434
|
|
|
|
|
|
|
} |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
############################################################################### |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
=item expand (%) |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
Expands given `path' using given `cgi' or 'apache' environment. Returns |
441
|
|
|
|
|
|
|
just the text of the page in scalar context and page content plus header |
442
|
|
|
|
|
|
|
content in array context. |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
This is normally used in scripts to execute only a particular template |
445
|
|
|
|
|
|
|
and to get results of execution. BUT this code is also used as part of |
446
|
|
|
|
|
|
|
the normal execute(). |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
`Objargs' argument may refer to a hash of additional parameters to be |
449
|
|
|
|
|
|
|
passed to the template being executed. |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
Example: |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
my $report=$web->expand( |
454
|
|
|
|
|
|
|
cgi => XAO::Objects->new(objname => 'CGI'), |
455
|
|
|
|
|
|
|
path => '/bits/stat-report', |
456
|
|
|
|
|
|
|
objargs => { |
457
|
|
|
|
|
|
|
CUSTOMER_ID => '123X234Z', |
458
|
|
|
|
|
|
|
MIN_TIME => time - 86400 * 7, |
459
|
|
|
|
|
|
|
}, |
460
|
|
|
|
|
|
|
); |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
See also lower level process() method. |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
=cut |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
sub expand ($%) { |
467
|
71
|
|
|
71
|
1
|
677
|
my $self=shift; |
468
|
71
|
|
|
|
|
206
|
my $args=get_args(\@_); |
469
|
|
|
|
|
|
|
|
470
|
71
|
|
|
|
|
886
|
$self->set_current; |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
# Processing the page and getting its text. Setting dprint and |
473
|
|
|
|
|
|
|
# eprint to use Apache logging if there is a reference to Apache |
474
|
|
|
|
|
|
|
# request given to us. |
475
|
|
|
|
|
|
|
# |
476
|
71
|
|
|
|
|
506
|
my $pagetext=$self->process($args); |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
# In scalar context (normal cases) we return only the resulting page |
479
|
|
|
|
|
|
|
# text. In array context (compatibility) we return header as well. |
480
|
|
|
|
|
|
|
# |
481
|
71
|
50
|
|
|
|
155
|
if(wantarray) { |
482
|
0
|
|
|
|
|
0
|
eprint "Calling ".ref($self)."::expand in ARRAY context is obsolete"; |
483
|
0
|
|
|
|
|
0
|
my $header=$self->config->header; |
484
|
0
|
|
|
|
|
0
|
$self->config->cleanup(mode => 'after'); |
485
|
0
|
|
|
|
|
0
|
return ($pagetext,$header); |
486
|
|
|
|
|
|
|
} |
487
|
|
|
|
|
|
|
else { |
488
|
71
|
|
|
|
|
155
|
$self->config->cleanup(mode => 'after'); |
489
|
71
|
|
|
|
|
598
|
return $pagetext; |
490
|
|
|
|
|
|
|
} |
491
|
|
|
|
|
|
|
} |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
############################################################################### |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
sub _expand_list ($$) { |
496
|
161
|
|
|
161
|
|
5031
|
my ($self,$autolist)=@_; |
497
|
|
|
|
|
|
|
|
498
|
161
|
|
|
|
|
255
|
my $content=''; |
499
|
|
|
|
|
|
|
|
500
|
161
|
100
|
|
|
|
376
|
if(!$autolist) { |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
501
|
138
|
|
|
|
|
468
|
return ''; |
502
|
|
|
|
|
|
|
} |
503
|
|
|
|
|
|
|
elsif(ref($autolist) eq 'ARRAY') { |
504
|
23
|
|
|
|
|
74
|
my $clipboard=$self->config->clipboard; |
505
|
|
|
|
|
|
|
|
506
|
23
|
|
|
|
|
66
|
for(my $i=0; $i<@$autolist; $i+=2) { |
507
|
28
|
|
|
|
|
182
|
my ($objname,$objargs)=@{$autolist}[$i,$i+1]; |
|
28
|
|
|
|
|
76
|
|
508
|
28
|
|
|
|
|
104
|
my $obj=XAO::Objects->new(objname => $objname); |
509
|
28
|
|
|
|
|
2101
|
$content.=$obj->expand($objargs); |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
# Not processing any more if there was a final output. |
512
|
|
|
|
|
|
|
# |
513
|
28
|
100
|
|
|
|
78
|
last if $clipboard->get('_no_more_output'); |
514
|
|
|
|
|
|
|
} |
515
|
|
|
|
|
|
|
} |
516
|
|
|
|
|
|
|
elsif(ref($autolist) eq 'HASH') { |
517
|
0
|
|
|
|
|
0
|
eprint "Using HASH auto-list is deprecated, use an ordered array"; |
518
|
0
|
|
|
|
|
0
|
foreach my $objname (keys %{$autolist}) { |
|
0
|
|
|
|
|
0
|
|
519
|
0
|
|
|
|
|
0
|
my $obj=XAO::Objects->new(objname => $objname); |
520
|
0
|
|
|
|
|
0
|
$content.=$obj->expand($autolist->{$objname}); |
521
|
|
|
|
|
|
|
} |
522
|
|
|
|
|
|
|
} |
523
|
|
|
|
|
|
|
else { |
524
|
0
|
|
|
|
|
0
|
throw XAO::E::Web "process - don't know how to handle ($autolist)," . |
525
|
|
|
|
|
|
|
" must be a hash or an array reference"; |
526
|
|
|
|
|
|
|
} |
527
|
|
|
|
|
|
|
|
528
|
23
|
|
|
|
|
701
|
return $content; |
529
|
|
|
|
|
|
|
} |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
############################################################################### |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
=item process (%) |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
Takes the same arguments as the expand() method returning expanded page |
536
|
|
|
|
|
|
|
text. Does not clean the site context and should not be called directly |
537
|
|
|
|
|
|
|
-- for normal situations either expand() or execute() methods should be |
538
|
|
|
|
|
|
|
called. |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
=cut |
541
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
sub process ($%) { |
543
|
82
|
|
|
82
|
1
|
147
|
my $self=shift; |
544
|
82
|
|
|
|
|
203
|
my $args=get_args(\@_); |
545
|
|
|
|
|
|
|
|
546
|
82
|
|
|
|
|
763
|
my $siteconfig=$self->config; |
547
|
82
|
|
|
|
|
1940
|
my $clipboard=$siteconfig->clipboard; |
548
|
82
|
|
|
|
|
184
|
my $sitename=$self->sitename; |
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
# Making sure path starts from a slash |
551
|
|
|
|
|
|
|
# |
552
|
82
|
|
33
|
|
|
209
|
my $path=$args->{'path'} || throw XAO::E::Web "process - no 'path' given"; |
553
|
82
|
|
|
|
|
226
|
$path='/' . $path; |
554
|
82
|
|
|
|
|
403
|
$path=~s/\/{2,}/\//g; |
555
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
# Resetting page text stack in case it was terminated abnormally |
557
|
|
|
|
|
|
|
# before and we're in the same process/memory. |
558
|
|
|
|
|
|
|
# |
559
|
82
|
|
|
|
|
295
|
XAO::PageSupport::reset(); |
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
# Analyzing the path. We have to do that up here because the object |
562
|
|
|
|
|
|
|
# might specify that we should not touch CGI. |
563
|
|
|
|
|
|
|
# |
564
|
82
|
|
|
|
|
140
|
my $pd=$args->{'pagedesc'}; |
565
|
82
|
50
|
|
|
|
186
|
if(!$pd) { |
566
|
82
|
|
|
|
|
226
|
my @path=split(/\//,$path); |
567
|
82
|
50
|
|
|
|
186
|
push(@path,"") unless @path; |
568
|
82
|
50
|
|
|
|
215
|
push(@path,"index.html") if $path =~ /\/$/; |
569
|
82
|
|
|
|
|
218
|
$pd=$self->analyze(\@path); |
570
|
|
|
|
|
|
|
} |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
# Figuring out current active URL. It might be the same as base_url |
573
|
|
|
|
|
|
|
# and in most cases it is, but it just as well might be different. |
574
|
|
|
|
|
|
|
# |
575
|
|
|
|
|
|
|
# The URL should be full path to the start point - |
576
|
|
|
|
|
|
|
# http://host.com in case of rewrite and something like |
577
|
|
|
|
|
|
|
# http://host.com/cgi-bin/xao-apache.pl/sitename in case of plain |
578
|
|
|
|
|
|
|
# CGI usage. |
579
|
|
|
|
|
|
|
# |
580
|
82
|
|
|
|
|
155
|
my $active_url; |
581
|
82
|
|
|
|
|
146
|
my $apache=$args->{'apache'}; |
582
|
82
|
|
|
|
|
134
|
my $cgi=$args->{'cgi'}; |
583
|
82
|
100
|
|
|
|
176
|
if(!$cgi) { |
584
|
7
|
50
|
|
|
|
15
|
!$args->{'psgi'} || |
585
|
|
|
|
|
|
|
throw XAO::E::Web "- need to have a CGI with PSGI"; |
586
|
7
|
|
|
|
|
34
|
$cgi=XAO::Objects->new(objname => 'CGI', no_cgi => $pd->{'no_cgi'}); |
587
|
|
|
|
|
|
|
} |
588
|
82
|
50
|
|
|
|
196
|
if($apache) { |
589
|
0
|
|
|
|
|
0
|
$active_url="http://" . $apache->hostname; |
590
|
|
|
|
|
|
|
} |
591
|
|
|
|
|
|
|
else { |
592
|
82
|
50
|
33
|
|
|
310
|
if(defined($CGI::VERSION) && $CGI::VERSION>=2.80) { |
593
|
82
|
|
|
|
|
553
|
$active_url=$cgi->url(-base => 1, -full => 0); |
594
|
82
|
|
100
|
|
|
31505
|
my $pinfo=$cgi->path_info || ''; |
595
|
82
|
|
100
|
|
|
1264
|
my $uri=$cgi->request_uri || ''; |
596
|
82
|
|
|
|
|
755
|
$uri=~s/^(.*?)\?.*$/$1/; |
597
|
82
|
100
|
33
|
|
|
783
|
if($pinfo =~ /^\/\Q$sitename\E(\/.+)?\Q$uri\E/) { |
|
|
50
|
|
|
|
|
|
598
|
|
|
|
|
|
|
# mod_rewrite |
599
|
|
|
|
|
|
|
} |
600
|
|
|
|
|
|
|
elsif($pinfo && $uri =~ /^(.*)\Q$pinfo\E$/) { |
601
|
|
|
|
|
|
|
# cgi |
602
|
0
|
|
|
|
|
0
|
$active_url.=$1; |
603
|
|
|
|
|
|
|
} |
604
|
|
|
|
|
|
|
# dprint ">2.8 $active_url"; |
605
|
|
|
|
|
|
|
} |
606
|
|
|
|
|
|
|
else { |
607
|
0
|
|
|
|
|
0
|
$active_url=$cgi->url(-full => 1, -path_info => 0); |
608
|
0
|
0
|
|
|
|
0
|
$active_url=$1 if $active_url=~/^(.*)(\Q$path\E)$/; |
609
|
|
|
|
|
|
|
# dprint "<2.8 $active_url"; |
610
|
|
|
|
|
|
|
} |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
# Trying to understand if rewrite module was used or not. If not |
613
|
|
|
|
|
|
|
# - adding sitename to the end of guessed URL. |
614
|
|
|
|
|
|
|
# |
615
|
82
|
50
|
33
|
|
|
398
|
if($active_url =~ /cgi-bin/ || $active_url =~ /xao-[\w-]+\.pl/) { |
616
|
0
|
|
|
|
|
0
|
$active_url.="/$sitename"; |
617
|
|
|
|
|
|
|
} |
618
|
|
|
|
|
|
|
} |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
# Eating extra slashes |
621
|
|
|
|
|
|
|
# |
622
|
82
|
|
|
|
|
204
|
chop($active_url) while $active_url =~ /\/$/; |
623
|
82
|
|
|
|
|
213
|
$active_url=~s/(?
|
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
# Figuring out secure URL |
626
|
|
|
|
|
|
|
# |
627
|
82
|
|
|
|
|
138
|
my $active_is_secure; |
628
|
|
|
|
|
|
|
my $active_url_secure; |
629
|
82
|
100
|
|
|
|
264
|
if($active_url =~ /^http:(\/\/.*)$/) { |
|
|
50
|
|
|
|
|
|
630
|
48
|
|
|
|
|
141
|
$active_url_secure='https:' . $1; |
631
|
48
|
|
|
|
|
76
|
$active_is_secure=0; |
632
|
|
|
|
|
|
|
} |
633
|
|
|
|
|
|
|
elsif($active_url =~ /^https:(\/\/.*)$/) { |
634
|
34
|
|
|
|
|
59
|
$active_url_secure=$active_url; |
635
|
34
|
|
|
|
|
83
|
$active_url='http:' . $1; |
636
|
34
|
|
|
|
|
49
|
$active_is_secure=1; |
637
|
|
|
|
|
|
|
} |
638
|
|
|
|
|
|
|
else { |
639
|
0
|
|
|
|
|
0
|
dprint "Wrong active URL ($active_url)"; |
640
|
0
|
|
|
|
|
0
|
$active_url_secure=$active_url; |
641
|
|
|
|
|
|
|
} |
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
# Storing active URLs |
644
|
|
|
|
|
|
|
# |
645
|
82
|
|
|
|
|
273
|
$clipboard->put(active_url => $active_url); |
646
|
82
|
|
|
|
|
1834
|
$clipboard->put(active_url_secure => $active_url_secure); |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
# Checking if we have base_url, assuming active_url if not. |
649
|
|
|
|
|
|
|
# Ensuring that URL does not end with '/'. |
650
|
|
|
|
|
|
|
# |
651
|
82
|
50
|
|
|
|
3182
|
if($siteconfig->defined('base_url')) { |
652
|
82
|
|
|
|
|
2904
|
my $url=$siteconfig->get('base_url'); |
653
|
82
|
50
|
|
|
|
3484
|
$url=~/^http:/i || |
654
|
|
|
|
|
|
|
throw XAO::E::Web "- bad base_url ($url) for sitename=$sitename"; |
655
|
82
|
|
|
|
|
154
|
my $nu=$url; |
656
|
82
|
|
|
|
|
196
|
chop($nu) while $nu =~ /\/$/; |
657
|
82
|
50
|
|
|
|
164
|
$siteconfig->put(base_url => $nu) if $nu ne $url; |
658
|
|
|
|
|
|
|
|
659
|
82
|
|
|
|
|
1398
|
$url=$siteconfig->get('base_url_secure'); |
660
|
82
|
50
|
|
|
|
3269
|
if(!$url) { |
661
|
0
|
|
|
|
|
0
|
$url=$siteconfig->get('base_url'); |
662
|
0
|
|
|
|
|
0
|
$url=~s/^http:/https:/i; |
663
|
|
|
|
|
|
|
} |
664
|
82
|
|
|
|
|
130
|
$nu=$url; |
665
|
82
|
|
|
|
|
186
|
chop($nu) while $nu =~ /\/$/; |
666
|
82
|
|
|
|
|
1439
|
$siteconfig->put(base_url_secure => $nu); |
667
|
|
|
|
|
|
|
} |
668
|
|
|
|
|
|
|
else { |
669
|
0
|
|
|
|
|
0
|
$siteconfig->put(base_url => $active_url); |
670
|
0
|
|
|
|
|
0
|
$siteconfig->put(base_url_secure => $active_url_secure); |
671
|
0
|
|
|
|
|
0
|
dprint "No base_url for sitename '$sitename'; assuming base_url=$active_url, base_url_secure=$active_url_secure"; |
672
|
|
|
|
|
|
|
} |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
# Checking if we're running under mod_perl |
675
|
|
|
|
|
|
|
# |
676
|
82
|
50
|
33
|
|
|
1950
|
my $mod_perl=($apache || $ENV{'MOD_PERL'}) ? 1 : 0; |
677
|
82
|
|
|
|
|
240
|
$clipboard->put(mod_perl => $mod_perl); |
678
|
82
|
|
|
|
|
1390
|
$clipboard->put(mod_perl_request => $apache); |
679
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
# Checking if a charset is known for the site. If it is, setting |
681
|
|
|
|
|
|
|
# it up for CGI-params decoding and for output. |
682
|
|
|
|
|
|
|
# |
683
|
82
|
|
|
|
|
2547
|
my $charset=$siteconfig->get('charset'); |
684
|
82
|
50
|
|
|
|
3190
|
if($charset) { |
685
|
82
|
50
|
|
|
|
222
|
if($cgi->can('set_param_charset')) { |
686
|
82
|
|
|
|
|
185
|
$cgi->set_param_charset($charset); |
687
|
|
|
|
|
|
|
} |
688
|
|
|
|
|
|
|
else { |
689
|
0
|
|
|
|
|
0
|
eprint "CGI object we have does not support set_param_charset"; |
690
|
|
|
|
|
|
|
} |
691
|
82
|
|
|
|
|
1480
|
$siteconfig->header_args( |
692
|
|
|
|
|
|
|
-Charset => $charset, |
693
|
|
|
|
|
|
|
); |
694
|
|
|
|
|
|
|
} |
695
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
# Putting CGI object into site configuration. The special case is |
697
|
|
|
|
|
|
|
# 'no_cgi' in the path_mapping_table which means that the object is |
698
|
|
|
|
|
|
|
# going to handle CGI arguments itself. It can be useful if it needs |
699
|
|
|
|
|
|
|
# raw query string. |
700
|
|
|
|
|
|
|
# |
701
|
82
|
|
|
|
|
289
|
$siteconfig->embedded('web')->enable_special_access; |
702
|
82
|
|
|
|
|
1637
|
$siteconfig->cgi($cgi); |
703
|
82
|
|
|
|
|
180
|
$siteconfig->embedded('web')->disable_special_access; |
704
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
# Traditionally URLs that do not end with .foo are considered |
706
|
|
|
|
|
|
|
# directories and get an internal redirect to path/index.html |
707
|
|
|
|
|
|
|
# Sometimes it is desirable to be able to pass down any URLs without |
708
|
|
|
|
|
|
|
# a forced redirect -- this is controlled by 'urlstyle' parameter |
709
|
|
|
|
|
|
|
# set to 'raw'. |
710
|
|
|
|
|
|
|
# |
711
|
82
|
|
100
|
|
|
327
|
my $urlstyle=$pd->{'urlstyle'} || 'files'; |
712
|
82
|
100
|
|
|
|
186
|
if($urlstyle eq 'files') { |
|
|
50
|
|
|
|
|
|
713
|
81
|
100
|
|
|
|
374
|
if($pd->{'patharr'}->[-1] !~ /\.\w+$/) { |
714
|
2
|
|
|
|
|
16
|
my $pd=$self->analyze([ @{$pd->{'patharr'}},'index.html' ]); |
|
2
|
|
|
|
|
18
|
|
715
|
|
|
|
|
|
|
#use Data::Dumper; dprint "pd=",Dumper($pd); |
716
|
2
|
100
|
|
|
|
21
|
if($pd->{'objname'} ne 'Default') { |
717
|
1
|
50
|
|
|
|
26
|
my $newpath=$siteconfig->get($active_is_secure ? 'base_url_secure' : 'base_url') . $path . '/'; |
718
|
1
|
|
|
|
|
50
|
dprint "Redirecting $path to $newpath"; |
719
|
1
|
|
|
|
|
22
|
$siteconfig->header_args( |
720
|
|
|
|
|
|
|
-Location => $newpath, |
721
|
|
|
|
|
|
|
-Status => 301, |
722
|
|
|
|
|
|
|
); |
723
|
1
|
|
|
|
|
13
|
return "Directory index redirection\n"; |
724
|
|
|
|
|
|
|
} |
725
|
|
|
|
|
|
|
} |
726
|
|
|
|
|
|
|
} |
727
|
|
|
|
|
|
|
elsif($urlstyle eq 'raw') { |
728
|
|
|
|
|
|
|
# nothing |
729
|
|
|
|
|
|
|
} |
730
|
|
|
|
|
|
|
else { |
731
|
0
|
|
|
|
|
0
|
eprint "Unknown urlstyle '$urlstyle' for $path"; |
732
|
|
|
|
|
|
|
} |
733
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
# Separator for the error_log :) |
735
|
|
|
|
|
|
|
# |
736
|
81
|
50
|
33
|
|
|
230
|
if(XAO::Utils::get_debug() && !$args->{'quieter'}) { |
737
|
0
|
|
|
|
|
0
|
my @d=localtime; |
738
|
0
|
|
|
|
|
0
|
my $date=sprintf("%02u:%02u:%02u %u/%02u/%04u",$d[2],$d[1],$d[0],$d[4]+1,$d[3],$d[5]+1900); |
739
|
0
|
|
|
|
|
0
|
undef(@d); |
740
|
0
|
|
|
|
|
0
|
dprint "============ date=$date, mod_perl=$mod_perl, " . |
741
|
|
|
|
|
|
|
"path='$path', translated='$pd->{path}'"; |
742
|
|
|
|
|
|
|
} |
743
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
# Putting path decription into the site clipboard |
745
|
|
|
|
|
|
|
# |
746
|
81
|
|
|
|
|
448
|
$clipboard->put(pagedesc => $pd); |
747
|
|
|
|
|
|
|
|
748
|
|
|
|
|
|
|
# Setting expiration time in the page header to immediate |
749
|
|
|
|
|
|
|
# expiration. If that's not what the page wants -- it can override |
750
|
|
|
|
|
|
|
# these. |
751
|
|
|
|
|
|
|
# |
752
|
81
|
|
|
|
|
2868
|
$siteconfig->header_args( |
753
|
|
|
|
|
|
|
-expires => 'now', |
754
|
|
|
|
|
|
|
-cache_control => 'no-cache', |
755
|
|
|
|
|
|
|
); |
756
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
# Do we need to run any objects before executing? A good place to |
758
|
|
|
|
|
|
|
# turn on debug mode if required using Debug object. |
759
|
|
|
|
|
|
|
# |
760
|
81
|
|
|
|
|
1591
|
my $pageheader=$self->_expand_list($siteconfig->get('auto_before')); |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
# If the header issued a final output (commonly a redirect), then |
763
|
|
|
|
|
|
|
# nothing else needs to be done. |
764
|
|
|
|
|
|
|
# |
765
|
81
|
|
|
|
|
148
|
my $pagebody=''; |
766
|
81
|
|
|
|
|
131
|
my $pagefooter=''; |
767
|
81
|
100
|
|
|
|
162
|
if(!$clipboard->get('_no_more_output')) { |
768
|
|
|
|
|
|
|
|
769
|
|
|
|
|
|
|
# Preparing object arguments out of standard ones, object specific |
770
|
|
|
|
|
|
|
# once from template paths and supplied hash (in that order of |
771
|
|
|
|
|
|
|
# preference). |
772
|
|
|
|
|
|
|
# |
773
|
|
|
|
|
|
|
my $objargs={ |
774
|
|
|
|
|
|
|
path => $pd->{'path'}, |
775
|
|
|
|
|
|
|
fullpath => $pd->{'fullpath'}, |
776
|
80
|
|
|
|
|
2201
|
prefix => $pd->{'prefix'}, |
777
|
|
|
|
|
|
|
}; |
778
|
|
|
|
|
|
|
|
779
|
80
|
|
|
|
|
311
|
$objargs=merge_refs($objargs,$pd->{'objargs'},$args->{'objargs'}); |
780
|
|
|
|
|
|
|
|
781
|
|
|
|
|
|
|
# Loading page displaying object and executing it. |
782
|
|
|
|
|
|
|
# |
783
|
80
|
|
|
|
|
1766
|
my $obj=XAO::Objects->new(objname => 'Web::' . $pd->{'objname'}); |
784
|
80
|
|
|
|
|
5710
|
$pagebody=$obj->expand($objargs); |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
# Do we need to run any objects after executing? A good place to |
787
|
|
|
|
|
|
|
# dump benchmark statistics for example. |
788
|
|
|
|
|
|
|
# |
789
|
80
|
|
|
|
|
1649
|
$pagefooter=$self->_expand_list($siteconfig->get('auto_after')); |
790
|
|
|
|
|
|
|
} |
791
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
# Done! Somewhat convoluted way of joining strings is here because |
793
|
|
|
|
|
|
|
# the page header would be a unicode character string (even if |
794
|
|
|
|
|
|
|
# it is really an empty string) and that would contaminate the |
795
|
|
|
|
|
|
|
# concatenation and convert the resulting page text into a character |
796
|
|
|
|
|
|
|
# string. That is not desirable if the output is a binary document. |
797
|
|
|
|
|
|
|
# |
798
|
|
|
|
|
|
|
my $pagetext=join('',map { |
799
|
81
|
100
|
50
|
|
|
216
|
Encode::is_utf8($_) ? Encode::encode($charset || 'utf8',$_) : $_; |
|
243
|
|
|
|
|
982
|
|
800
|
|
|
|
|
|
|
} ($pageheader,$pagebody,$pagefooter)); |
801
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
### dprint "---length(pageheader)=".length($pageheader).", utf8=".Encode::is_utf8($pageheader); |
803
|
|
|
|
|
|
|
### dprint "---length(pagebody)= ".length($pagebody).", utf8=".Encode::is_utf8($pagebody); |
804
|
|
|
|
|
|
|
### dprint "---length(pagefooter)=".length($pagefooter).", utf8=".Encode::is_utf8($pagefooter); |
805
|
|
|
|
|
|
|
### dprint "---length(pagetext)= ".length($pagetext).", utf8=".Encode::is_utf8($pagetext); |
806
|
|
|
|
|
|
|
|
807
|
81
|
|
|
|
|
1675
|
$siteconfig->header_args( |
808
|
|
|
|
|
|
|
-content_length => length($pagetext), |
809
|
|
|
|
|
|
|
); |
810
|
|
|
|
|
|
|
|
811
|
81
|
|
|
|
|
288
|
return $pagetext; |
812
|
|
|
|
|
|
|
} |
813
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
############################################################################### |
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
=item new (%) |
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
Creates or loads a context for the named site. The only required |
819
|
|
|
|
|
|
|
argument is 'sitename' which provides the name of the site. |
820
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
=cut |
822
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
sub new ($%) { |
824
|
38
|
|
|
38
|
1
|
394
|
my $proto=shift; |
825
|
38
|
|
|
|
|
921
|
my $args=get_args(\@_); |
826
|
|
|
|
|
|
|
|
827
|
|
|
|
|
|
|
## |
828
|
|
|
|
|
|
|
# Getting site name |
829
|
|
|
|
|
|
|
# |
830
|
38
|
|
33
|
|
|
2065
|
my $sitename=$args->{'sitename'} || |
831
|
|
|
|
|
|
|
throw XAO::E::Web "new - required parameter missing (sitename)"; |
832
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
## |
834
|
|
|
|
|
|
|
# Loading or creating site configuration object. |
835
|
|
|
|
|
|
|
# |
836
|
38
|
|
|
|
|
599
|
my $siteconfig=XAO::Projects::get_project($sitename); |
837
|
38
|
50
|
|
|
|
543
|
if(!$siteconfig) { |
838
|
|
|
|
|
|
|
## |
839
|
|
|
|
|
|
|
# Creating configuration. |
840
|
|
|
|
|
|
|
# |
841
|
38
|
|
|
|
|
789
|
$siteconfig=XAO::Objects->new( |
842
|
|
|
|
|
|
|
sitename => $sitename, |
843
|
|
|
|
|
|
|
objname => 'Config', |
844
|
|
|
|
|
|
|
); |
845
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
## |
847
|
|
|
|
|
|
|
# Always embedding at least web config and a hash |
848
|
|
|
|
|
|
|
# |
849
|
38
|
|
|
|
|
157659
|
$siteconfig->embed(web => new XAO::Objects objname => 'Web::Config'); |
850
|
38
|
|
|
|
|
10929
|
$siteconfig->embed(hash => new XAO::SimpleHash); |
851
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
## |
853
|
|
|
|
|
|
|
# Running initialization, this is where parameters are inserted and |
854
|
|
|
|
|
|
|
# normally FS::Config gets embedded. |
855
|
|
|
|
|
|
|
# |
856
|
38
|
|
33
|
|
|
13322
|
$siteconfig->init($args->{'init_args'} || ()); |
857
|
|
|
|
|
|
|
|
858
|
|
|
|
|
|
|
## |
859
|
|
|
|
|
|
|
# Creating an entry in in-memory projects repository |
860
|
|
|
|
|
|
|
# |
861
|
38
|
|
|
|
|
13558
|
XAO::Projects::create_project( |
862
|
|
|
|
|
|
|
name => $sitename, |
863
|
|
|
|
|
|
|
object => $siteconfig, |
864
|
|
|
|
|
|
|
); |
865
|
|
|
|
|
|
|
} |
866
|
|
|
|
|
|
|
|
867
|
|
|
|
|
|
|
# CGI in args is not supported any more, needs to be passed in execute |
868
|
|
|
|
|
|
|
# |
869
|
38
|
50
|
|
|
|
2229
|
$args->{'cgi'} && |
870
|
|
|
|
|
|
|
throw XAO::E::Web "- 'cgi' argument to 'new' is not supported, pass it to 'execute'"; |
871
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
# This helps Mailer to be called outside of web context. |
873
|
|
|
|
|
|
|
# TODO: Probably need some better initialization strategy, this does |
874
|
|
|
|
|
|
|
# not feel as the Right Thing |
875
|
|
|
|
|
|
|
# |
876
|
38
|
|
|
|
|
1089
|
my $url=$siteconfig->get('base_url'); |
877
|
38
|
50
|
|
|
|
3775
|
if($url) { |
878
|
38
|
50
|
|
|
|
440
|
$url=~/^http:/i || |
879
|
|
|
|
|
|
|
throw XAO::E::Web "new - bad base_url ($url) for sitename=$sitename"; |
880
|
38
|
|
|
|
|
153
|
my $nu=$url; |
881
|
38
|
|
|
|
|
584
|
chop($nu) while $nu =~ /\/$/; |
882
|
38
|
50
|
|
|
|
185
|
$siteconfig->put(base_url => $nu) if $nu ne $url; |
883
|
|
|
|
|
|
|
|
884
|
38
|
|
|
|
|
999
|
$url=$siteconfig->get('base_url_secure'); |
885
|
38
|
50
|
|
|
|
1462
|
if(!$url) { |
886
|
38
|
|
|
|
|
844
|
$url=$siteconfig->get('base_url'); |
887
|
38
|
|
|
|
|
1999
|
$url=~s/^http:/https:/i; |
888
|
|
|
|
|
|
|
} |
889
|
38
|
|
|
|
|
134
|
$nu=$url; |
890
|
38
|
|
|
|
|
179
|
chop($nu) while $nu =~ /\/$/; |
891
|
38
|
|
|
|
|
876
|
$siteconfig->put(base_url_secure => $nu); |
892
|
|
|
|
|
|
|
} |
893
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
# Done |
895
|
|
|
|
|
|
|
# |
896
|
|
|
|
|
|
|
bless { |
897
|
38
|
|
33
|
|
|
2024
|
sitename => $sitename, |
898
|
|
|
|
|
|
|
siteconfig => $siteconfig, |
899
|
|
|
|
|
|
|
}, ref($proto) || $proto; |
900
|
|
|
|
|
|
|
} |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
############################################################################### |
903
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
sub check_uri_access ($$) { |
905
|
0
|
|
|
0
|
0
|
0
|
my ($self,$uri)=@_; |
906
|
|
|
|
|
|
|
|
907
|
|
|
|
|
|
|
# By convention we disallow access to /bits/ and /CVS/ for security |
908
|
|
|
|
|
|
|
# reasons. If needed the site can override these or add other |
909
|
|
|
|
|
|
|
# regex'es into path_deny_table |
910
|
|
|
|
|
|
|
# |
911
|
0
|
|
|
|
|
0
|
my $pdtc=$self->config->get('path_deny_table_compiled'); |
912
|
0
|
0
|
|
|
|
0
|
if(!$pdtc) { |
913
|
0
|
|
0
|
|
|
0
|
my $pdt=merge_refs({ |
914
|
|
|
|
|
|
|
'/bits/' => 1, |
915
|
|
|
|
|
|
|
'/CVS/' => 1, |
916
|
|
|
|
|
|
|
},$self->config->get('path_deny_table') || { }); |
917
|
0
|
|
|
|
|
0
|
$pdtc=[ map { qr/$_/ } grep { $pdt->{$_} } keys %$pdt ]; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
918
|
0
|
|
|
|
|
0
|
$self->config->put('path_deny_table_compiled' => $pdtc); |
919
|
|
|
|
|
|
|
} |
920
|
|
|
|
|
|
|
|
921
|
0
|
|
|
|
|
0
|
return ! grep { $uri =~ $_ } @$pdtc; |
|
0
|
|
|
|
|
0
|
|
922
|
|
|
|
|
|
|
} |
923
|
|
|
|
|
|
|
|
924
|
|
|
|
|
|
|
############################################################################### |
925
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
=item set_current () |
927
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
Sets the current site as the current project in the sense of XAO::Projects. |
929
|
|
|
|
|
|
|
|
930
|
|
|
|
|
|
|
=cut |
931
|
|
|
|
|
|
|
|
932
|
|
|
|
|
|
|
sub set_current ($) { |
933
|
120
|
|
|
120
|
1
|
215
|
my $self=shift; |
934
|
|
|
|
|
|
|
|
935
|
120
|
|
|
|
|
319
|
XAO::Projects::set_current_project($self->sitename); |
936
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
# Cleaning up the configuration. Useful even if it was just created |
938
|
|
|
|
|
|
|
# as it will unlock tables in the database for instance. |
939
|
|
|
|
|
|
|
# We call it here because cleanup code may rely on the project being |
940
|
|
|
|
|
|
|
# active. |
941
|
|
|
|
|
|
|
# |
942
|
120
|
|
|
|
|
1558
|
$self->config->cleanup(mode => 'before'); |
943
|
|
|
|
|
|
|
} |
944
|
|
|
|
|
|
|
|
945
|
|
|
|
|
|
|
############################################################################### |
946
|
|
|
|
|
|
|
|
947
|
|
|
|
|
|
|
=item sitename () |
948
|
|
|
|
|
|
|
|
949
|
|
|
|
|
|
|
Returns site name. |
950
|
|
|
|
|
|
|
|
951
|
|
|
|
|
|
|
=cut |
952
|
|
|
|
|
|
|
|
953
|
|
|
|
|
|
|
sub sitename ($) { |
954
|
202
|
|
|
202
|
1
|
331
|
my $self=shift; |
955
|
202
|
50
|
|
|
|
873
|
$self->{'sitename'} || throw XAO::E::Web "sitename - no site name"; |
956
|
|
|
|
|
|
|
} |
957
|
|
|
|
|
|
|
|
958
|
|
|
|
|
|
|
############################################################################### |
959
|
|
|
|
|
|
|
1; |
960
|
|
|
|
|
|
|
__END__ |