blib/lib/POE/Component/XUL.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 187 | 474 | 39.4 |
branch | 25 | 134 | 18.6 |
condition | 13 | 104 | 12.5 |
subroutine | 39 | 72 | 54.1 |
pod | 4 | 37 | 10.8 |
total | 268 | 821 | 32.6 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | package # Hide from CPAN indexer | ||||||
2 | POE::Component::XUL; | ||||||
3 | # $Id: XUL.pm 1566 2010-11-03 03:13:32Z fil $ | ||||||
4 | # Copyright Philip Gwyn 2007-2010. All rights reserved. | ||||||
5 | |||||||
6 | 14 | 14 | 234317 | use strict; | |||
14 | 16 | ||||||
14 | 328 | ||||||
7 | 14 | 14 | 48 | use warnings; | |||
14 | 13 | ||||||
14 | 334 | ||||||
8 | |||||||
9 | 14 | 14 | 56 | use File::Path; | |||
14 | 12 | ||||||
14 | 692 | ||||||
10 | 14 | 14 | 45 | use File::Spec; | |||
14 | 16 | ||||||
14 | 208 | ||||||
11 | 14 | 14 | 41 | use File::Basename; | |||
14 | 15 | ||||||
14 | 844 | ||||||
12 | 14 | 14 | 6209 | use HTTP::Date; | |||
14 | 39110 | ||||||
14 | 712 | ||||||
13 | 14 | 14 | 5610 | use HTTP::Status; | |||
14 | 40676 | ||||||
14 | 2863 | ||||||
14 | 14 | 14 | 6187 | use HTML::Entities qw( encode_entities_numeric ); | |||
14 | 57520 | ||||||
14 | 844 | ||||||
15 | 14 | 14 | 7269 | use I18N::AcceptLanguage; | |||
14 | 11423 | ||||||
14 | 366 | ||||||
16 | 14 | 14 | 4920 | use IO::File; | |||
14 | 73280 | ||||||
14 | 1380 | ||||||
17 | 14 | 14 | 5942 | use MIME::Types; | |||
14 | 70109 | ||||||
14 | 554 | ||||||
18 | 14 | 14 | 5271 | use POE; | |||
14 | 276120 | ||||||
14 | 78 | ||||||
19 | 14 | 14 | 456094 | use POE::Component::Server::HTTP; | |||
14 | 604170 | ||||||
14 | 750 | ||||||
20 | 14 | 14 | 100 | use POE::Session; | |||
14 | 20 | ||||||
14 | 70 | ||||||
21 | 14 | 14 | 6925 | use POE::XUL::Controler; | |||
14 | 74 | ||||||
14 | 403 | ||||||
22 | 14 | 14 | 5974 | use POE::XUL::Node; | |||
14 | 23 | ||||||
14 | 46 | ||||||
23 | 14 | 14 | 5000 | use POE::XUL::Request; | |||
14 | 27 | ||||||
14 | 363 | ||||||
24 | 14 | 14 | 68 | use POE::XUL::Logging; | |||
14 | 10 | ||||||
14 | 771 | ||||||
25 | 14 | 14 | 59 | use POSIX qw(:errno_h); | |||
14 | 19 | ||||||
14 | 98 | ||||||
26 | 14 | 14 | 5243 | use Scalar::Util qw( reftype blessed ); | |||
14 | 13 | ||||||
14 | 574 | ||||||
27 | 14 | 14 | 49 | use Socket qw( unpack_sockaddr_in ); | |||
14 | 16 | ||||||
14 | 470 | ||||||
28 | |||||||
29 | 14 | 14 | 48 | use Carp; | |||
14 | 12 | ||||||
14 | 686 | ||||||
30 | |||||||
31 | our $VERSION = '0.0601'; | ||||||
32 | |||||||
33 | 14 | 14 | 48 | use constant DEBUG => 0; | |||
14 | 13 | ||||||
14 | 637 | ||||||
34 | |||||||
35 | 14 | 14 | 49 | use vars qw( $HAVE_DEVEL_SIZE $HAVE_DATA_DUMPER $SINGLETON ); | |||
14 | 13 | ||||||
14 | 977 | ||||||
36 | BEGIN { | ||||||
37 | 14 | 14 | 22 | $HAVE_DEVEL_SIZE = 0; | |||
38 | 14 | 14 | 671 | eval "use " . # Hide from CPANTS kwalitee | |||
14 | 5953 | ||||||
14 | 5634 | ||||||
14 | 432 | ||||||
39 | "Devel::Size;"; | ||||||
40 | 14 | 50 | 56 | $HAVE_DEVEL_SIZE = 1 unless $@; | |||
41 | |||||||
42 | 14 | 18 | $HAVE_DATA_DUMPER = 0; | ||||
43 | 14 | 14 | 590 | eval "use Data::Dumper;"; | |||
14 | 83 | ||||||
14 | 15 | ||||||
14 | 451 | ||||||
44 | 14 | 50 | 51839 | $HAVE_DATA_DUMPER = 1 unless $@; | |||
45 | } | ||||||
46 | |||||||
47 | ############################################################### | ||||||
48 | sub spawn | ||||||
49 | { | ||||||
50 | 2 | 2 | 1 | 1374 | my ($package, $args) = @_; | ||
51 | |||||||
52 | 2 | 2 | my $self = $package; | ||||
53 | 2 | 50 | 14 | unless( blessed $self ) { | |||
54 | 2 | 10 | $self = $package->new( $args ); | ||||
55 | } | ||||||
56 | |||||||
57 | POE::Session->create( | ||||||
58 | 2 | 50 | 4 | options => { %{ $self->{opts}||{} } }, | |||
2 | 20 | ||||||
59 | object_states => [ | ||||||
60 | $self => [ qw( _start shutdown | ||||||
61 | static xul httpd_error xul_file | ||||||
62 | poe_size poe_kernel poe_test | ||||||
63 | session_count session_timeout session_exists | ||||||
64 | sig_HUP sig_DIE | ||||||
65 | ) ], | ||||||
66 | ], | ||||||
67 | ); | ||||||
68 | } | ||||||
69 | |||||||
70 | ############################################################### | ||||||
71 | sub new | ||||||
72 | { | ||||||
73 | 6 | 6 | 0 | 1613 | my( $package, $args ) = @_; | ||
74 | |||||||
75 | 6 | 12 | $args->{port} = $args->{port}; | ||||
76 | 6 | 50 | 23 | $args->{port} = 8077 unless defined $args->{port}; # PORT | |||
77 | 6 | 50 | 16 | $args->{root} = $args->{root} || '/usr/local/poe-xul/xul'; # ROOT | |||
78 | 6 | 100 | 27 | $args->{alias} ||= 'component-poe-xul'; | |||
79 | 6 | 50 | 20 | $args->{apps} = {} if (!defined $args->{apps}); | |||
80 | 6 | 50 | 18 | $args->{opts} = {} if (!defined $args->{opts}); | |||
81 | 6 | 50 | 27 | $args->{timeout} ||= 60*30; # 30 minutes | |||
82 | |||||||
83 | 6 | 50 | 20 | unless (ref($args->{apps}) eq 'HASH') { | |||
84 | 0 | 0 | croak "apps parameter must be a HASH ref"; | ||||
85 | } | ||||||
86 | 6 | 50 | 18 | unless (ref($args->{opts}) eq 'HASH') { | |||
87 | 0 | 0 | croak "opts parameter must be a HASH ref"; | ||||
88 | } | ||||||
89 | |||||||
90 | 6 | 31 | my $self = bless { %$args }, $package; | ||||
91 | 6 | 46 | $self->build_controler( $self->{timeout}, $self->{apps} ); | ||||
92 | |||||||
93 | 6 | 19 | $self->__parse_apps(); | ||||
94 | 6 | 10 | $self->{sessions} = {}; | ||||
95 | |||||||
96 | 6 | 33 | 107 | $self->{static_root} ||= File::Spec->catfile( $self->{root}, 'xul' ); | |||
97 | 6 | 33 | 50 | $self->{log_root} ||= File::Spec->catfile( $self->{root}, 'log' ); | |||
98 | |||||||
99 | 6 | 29 | $self->build_logging( $args->{logging} ); | ||||
100 | |||||||
101 | 6 | 14 | $self->{languages} = [ qw( en fr ) ]; # XXX | ||||
102 | 6 | 10 | $self->{default_language} = 'fr'; # XXX | ||||
103 | |||||||
104 | 6 | 14 | return $SINGLETON = $self; | ||||
105 | } | ||||||
106 | |||||||
107 | sub __parse_apps | ||||||
108 | { | ||||||
109 | 6 | 6 | 9 | my( $self ) = @_; | |||
110 | |||||||
111 | 6 | 10 | my $controler = $self->{controler}; | ||||
112 | 6 | 50 | 24 | $self->{app_names} ||= {}; | |||
113 | |||||||
114 | 6 | 9 | foreach my $app ( keys %{ $self->{apps} } ) { | ||||
6 | 20 | ||||||
115 | 0 | 0 | my $A = $self->{apps}{$app}; | ||||
116 | 0 | 0 | my $r = ref $A; | ||||
117 | # Make sure we have a package or a coderef | ||||||
118 | 0 | 0 | my $ok = 0; | ||||
119 | 0 | 0 | 0 | 0 | if( $r and 'HASH' eq $r ) { | ||
120 | $self->{app_names}{$app} = { | ||||||
121 | en => $A->{en}, | ||||||
122 | fr => $A->{fr}, | ||||||
123 | 0 | 0 | }; | ||||
124 | 0 | 0 | 0 | if( $A->{package} ) { | |||
125 | 0 | 0 | $A = $A->{package}; | ||||
126 | 0 | 0 | undef $r; | ||||
127 | } | ||||||
128 | else { | ||||||
129 | 0 | 0 | $A = $A->{code}; | ||||
130 | 0 | 0 | $r = 'CODE'; | ||||
131 | } | ||||||
132 | } | ||||||
133 | 0 | 0 | 0 | 0 | if( not $r and $controler->package_ctor( $A ) ) { | ||
0 | |||||||
134 | 0 | 0 | $ok = 1; | ||||
135 | } | ||||||
136 | elsif( $r eq 'CODE') { | ||||||
137 | 0 | 0 | $ok = 1; | ||||
138 | } | ||||||
139 | 0 | 0 | 0 | unless( $ok ) { | |||
140 | 0 | 0 | croak "apps parameter $app must be a code reference or name of a package that defines ->spawn, not $r ($A)"; | ||||
141 | } | ||||||
142 | 0 | 0 | $self->{apps}{$app} = $A; | ||||
143 | } | ||||||
144 | } | ||||||
145 | |||||||
146 | |||||||
147 | ############################################################### | ||||||
148 | sub build_controler | ||||||
149 | { | ||||||
150 | 6 | 6 | 0 | 6 | my( $self, $timeout, $apps ) = @_; | ||
151 | |||||||
152 | 6 | 41 | $self->{controler} = POE::XUL::Controler->new( $timeout, $apps ); | ||||
153 | } | ||||||
154 | |||||||
155 | ############################################################### | ||||||
156 | sub build_http_server | ||||||
157 | { | ||||||
158 | 0 | 0 | 0 | 0 | my( $self, $addr, $port ) = @_; | ||
159 | 0 | 0 | $self->{mimetypes} = MIME::Types->new(); | ||||
160 | |||||||
161 | 0 | 0 | my $alias = $self->{alias}; | ||||
162 | |||||||
163 | $self->{aliases} = POE::Component::Server::HTTP->new( | ||||||
164 | Port => $self->{port}, | ||||||
165 | 0 | 0 | MapOrder => 'bottom-first', | ||||
166 | # PreHandler => { '/' => _mk_handler( $self, 'pre_connection' ) }, | ||||||
167 | PostHandler => { | ||||||
168 | '/' => _mk_handler( $self, 'post_connection' ) | ||||||
169 | }, | ||||||
170 | ContentHandler => { | ||||||
171 | '/xul' => _mk_call( $alias, 'xul' ), | ||||||
172 | '/xul/file/' => _mk_call( $alias, 'xul_file' ), | ||||||
173 | '/__poe_size' => _mk_call( $alias, 'poe_size' ), | ||||||
174 | '/__poe_kernel' => _mk_call( $alias, 'poe_kernel' ), | ||||||
175 | '/__poe_text ' => _mk_call( $alias, 'poe_text' ), | ||||||
176 | '/' => _mk_call( $alias, 'static' ), | ||||||
177 | }, | ||||||
178 | ErrorHandler => { | ||||||
179 | '/' => _mk_call( $alias, 'httpd_error' ), | ||||||
180 | }, | ||||||
181 | |||||||
182 | Headers => { 'X-POE-XUL' => $VERSION }, | ||||||
183 | ); | ||||||
184 | } | ||||||
185 | |||||||
186 | ## We build these closures outside of build_http_server, because otherwise | ||||||
187 | ## they would capture a reference to $self | ||||||
188 | sub _mk_handler | ||||||
189 | { | ||||||
190 | 0 | 0 | 0 | my( $self, $call ) = @_; | |||
191 | 0 | 0 | 0 | 0 | return [ sub { RC_OK } ] unless $self; | ||
0 | 0 | ||||||
192 | 0 | 0 | 0 | return [ sub { $self->$call(@_) } ] | |||
0 | 0 | ||||||
193 | } | ||||||
194 | |||||||
195 | sub _mk_call | ||||||
196 | { | ||||||
197 | 0 | 0 | 0 | my( $alias, $handler ) = @_; | |||
198 | 0 | 0 | 0 | return sub { return $poe_kernel->call( $alias, $handler, @_ ) }; | |||
0 | 0 | ||||||
199 | } | ||||||
200 | |||||||
201 | |||||||
202 | ############################################################### | ||||||
203 | # Introspection used for load balancer | ||||||
204 | sub port | ||||||
205 | { | ||||||
206 | 0 | 0 | 1 | 0 | my( $self ) = @_; | ||
207 | |||||||
208 | 0 | 0 | my $sid = $self->{aliases}{tcp}; | ||||
209 | 0 | 0 | my $tcp = $poe_kernel->alias_resolve( $sid ); | ||||
210 | 0 | 0 | 0 | die "$$: Server::TCP has disapeared! tcp=$sid" unless $tcp; | |||
211 | 0 | 0 | my $wheel = $tcp->get_heap->{listener}; | ||||
212 | 0 | 0 | 0 | die "Server::TCP no longer has the listener wheel in 'listener'" | |||
213 | unless $wheel; | ||||||
214 | 0 | 0 | my $sockname = $wheel->getsockname; | ||||
215 | 0 | 0 | my($peer_port, $peer_addr) = unpack_sockaddr_in( $sockname ); | ||||
216 | 0 | 0 | return $peer_port; | ||||
217 | # use Data::Denter; | ||||||
218 | # die Denter $sockname; | ||||||
219 | } | ||||||
220 | |||||||
221 | sub alias | ||||||
222 | { | ||||||
223 | 0 | 0 | 1 | 0 | my( $self ) = @_; | ||
224 | 0 | 0 | return $self->{alias}; | ||||
225 | } | ||||||
226 | |||||||
227 | ############################################################################ | ||||||
228 | # POE methods | ||||||
229 | |||||||
230 | ############################################################### | ||||||
231 | sub _start | ||||||
232 | { | ||||||
233 | 2 | 2 | 796 | my ($self, $kernel, $session) = @_[OBJECT, KERNEL, SESSION]; | |||
234 | |||||||
235 | 2 | 8 | $kernel->alias_set( $self->{alias} ); | ||||
236 | 2 | 51 | $kernel->sig( shutdown => 'shutdown' ); | ||||
237 | 2 | 39 | $kernel->sig( HUP => 'sig_HUP' ); | ||||
238 | 2 | 53 | $kernel->sig( DIE => 'sig_DIE' ); | ||||
239 | |||||||
240 | # TODO: listen host | ||||||
241 | 2 | 29 | $self->build_http_server( '0.0.0.0', $self->{port} ); | ||||
242 | 2 | 24808 | $self->log_setup; | ||||
243 | } | ||||||
244 | |||||||
245 | # NB : no longer used | ||||||
246 | sub _stop | ||||||
247 | { | ||||||
248 | 0 | 0 | 0 | xwarn "XUL stop"; | |||
249 | } | ||||||
250 | |||||||
251 | ############################################################### | ||||||
252 | # Sane shutdown | ||||||
253 | sub shutdown | ||||||
254 | { | ||||||
255 | 2 | 2 | 1 | 5267 | my( $self ) = @_; | ||
256 | # xwarn "$$ XUL shutdown"; | ||||||
257 | 2 | 8 | $self->{shutdown} = 1; | ||||
258 | 2 | 8 | $poe_kernel->post( $self->{aliases}{httpd}, 'shutdown' ); | ||||
259 | 2 | 50 | $poe_kernel->alias_remove( delete $self->{alias} ); | ||||
260 | 2 | 46 | $poe_kernel->sig( 'HUP' ); | ||||
261 | } | ||||||
262 | |||||||
263 | ############################################################### | ||||||
264 | # POE Exception handling | ||||||
265 | sub sig_DIE | ||||||
266 | { | ||||||
267 | 0 | 0 | 0 | 0 | my( $self, $kernel, $sig, $ex ) = @_[ OBJECT, KERNEL, ARG0, ARG1 ]; | ||
268 | 0 | 0 | xwarn "============================\nERROR: $sig $ex\n"; | ||||
269 | 0 | 0 | xwarn "Exception in $ex->{event}: $ex->{error_str}\n"; | ||||
270 | } | ||||||
271 | |||||||
272 | |||||||
273 | |||||||
274 | |||||||
275 | ############################################################### | ||||||
276 | sub session_timeout | ||||||
277 | { | ||||||
278 | 0 | 0 | 0 | 0 | my ($self, $kernel, $SID) = @_[OBJECT, KERNEL, ARG0]; | ||
279 | 0 | 0 | my $controler = $self->{controler}; | ||||
280 | 0 | 0 | DEBUG and | ||||
281 | xwarn "Session timeout for $SID"; | ||||||
282 | 0 | 0 | 0 | 0 | if( defined $SID and $controler->exists( $SID ) ) { | ||
283 | 0 | 0 | DEBUG and | ||||
284 | xdebug "Timeout SID=$SID"; | ||||||
285 | 0 | 0 | $kernel->call( $SID, 'timeout', $SID ); # TODO unit test | ||||
286 | # unregister will send the 'shutdown' event | ||||||
287 | 0 | 0 | $controler->unregister( $SID ); | ||||
288 | } | ||||||
289 | } | ||||||
290 | |||||||
291 | ############################################################### | ||||||
292 | # Get the number of active sessions. | ||||||
293 | # Used by IGDAIP::App to see when a backend should exit | ||||||
294 | sub session_count | ||||||
295 | { | ||||||
296 | 0 | 0 | 0 | 0 | my ($self, $kernel) = @_[ OBJECT, KERNEL ]; | ||
297 | 0 | 0 | return $self->{controler}->count; | ||||
298 | } | ||||||
299 | |||||||
300 | ############################################################### | ||||||
301 | # Verify if a session exists | ||||||
302 | sub session_exists | ||||||
303 | { | ||||||
304 | 0 | 0 | 0 | 0 | my ($self, $kernel, $SID ) = @_[ OBJECT, KERNEL, ARG0 ]; | ||
305 | 0 | 0 | return $self->{controler}->exists( $SID ); | ||||
306 | } | ||||||
307 | |||||||
308 | |||||||
309 | |||||||
310 | |||||||
311 | |||||||
312 | ############################################################################ | ||||||
313 | # XUL request handling | ||||||
314 | |||||||
315 | ############################################################### | ||||||
316 | # Get the arguments out of a request | ||||||
317 | sub parse_args | ||||||
318 | { | ||||||
319 | 0 | 0 | 0 | 0 | my( $self, $req ) = @_; | ||
320 | |||||||
321 | 0 | 0 | return POE::XUL::Request->new( $req ); | ||||
322 | } | ||||||
323 | |||||||
324 | ############################################################### | ||||||
325 | # Report an error in the request parsing | ||||||
326 | sub parse_error | ||||||
327 | { | ||||||
328 | 0 | 0 | 0 | 0 | my( $self, $rc ) = @_; | ||
329 | |||||||
330 | 0 | 0 | $self->error_standard( $rc, "argument parsing" ); | ||||
331 | } | ||||||
332 | |||||||
333 | ############################################################### | ||||||
334 | # A request under /xul for an application | ||||||
335 | sub xul | ||||||
336 | { | ||||||
337 | 0 | 0 | 0 | 0 | my( $self, $kernel, $req, $resp ) = @_[ OBJECT, KERNEL, ARG0..$#_ ]; | ||
338 | |||||||
339 | 0 | 0 | DEBUG and | ||||
340 | warn "$$: xul"; | ||||||
341 | 0 | 0 | 0 | if( $self->{shutdown} ) { | |||
342 | 0 | 0 | xwarn "XUL request, but we are shutdown\n"; | ||||
343 | 0 | 0 | return; | ||||
344 | } | ||||||
345 | |||||||
346 | 0 | 0 | local $self->{request} = $req; | ||||
347 | 0 | 0 | local $self->{response} = $resp; | ||||
348 | |||||||
349 | 0 | 0 | DEBUG and xwarn "XUL request"; | ||||
350 | |||||||
351 | 0 | 0 | my $controler = $self->{controler}; | ||||
352 | |||||||
353 | 0 | 0 | my $uri = $req->uri->path; | ||||
354 | 0 | 0 | 0 | if( $uri ne '/xul' ) { | |||
355 | 0 | 0 | return $self->error_standard( RC_BAD_REQUEST, "parsing uri", | ||||
356 | "$uri isn't a valid path\n" ); | ||||||
357 | } | ||||||
358 | |||||||
359 | 0 | 0 | my $ret = $self->parse_args( $req ); | ||||
360 | 0 | 0 | 0 | unless( ref $ret ) { | |||
361 | 0 | 0 | return $self->parse_error( $ret ); | ||||
362 | } | ||||||
363 | |||||||
364 | 0 | 0 | $req->{start} = time; | ||||
365 | |||||||
366 | 0 | 0 | 0 | my $SID = $req->param( 'SID' ) || ''; | |||
367 | 0 | 0 | 0 | my $event = $req->param( 'event' ) || 'boot'; | |||
368 | 0 | 0 | 0 | my $app = $req->param( 'app' ) || ''; | |||
369 | 0 | 0 | DEBUG and xdebug "Request for app=$app SID=$SID event=$event"; | ||||
370 | |||||||
371 | 0 | 0 | 0 | 0 | unless( $app and $event ) { | ||
372 | 0 | 0 | $req->pre_log; | ||||
373 | 0 | 0 | xlog "app=$app SID=$SID event=$event is an empty request"; | ||||
374 | 0 | 0 | return $self->error( RC_BAD_REQUEST, 'Empty request' ); | ||||
375 | } | ||||||
376 | |||||||
377 | 0 | 0 | my $rc; | ||||
378 | 0 | 0 | eval { | ||||
379 | 0 | 0 | local $self->{logging}->{app} = $app; | ||||
380 | 0 | 0 | $req->pre_log; | ||||
381 | 0 | 0 | 0 | if( $event eq 'boot' ) { | |||
0 | |||||||
382 | 0 | 0 | my $fail = $controler->boot( $req, $resp ); | ||||
383 | 0 | 0 | 0 | if( $fail ) { | |||
384 | # boot failed | ||||||
385 | 0 | 0 | $rc = $self->error_boot_fail( $fail ); | ||||
386 | } | ||||||
387 | } | ||||||
388 | ## TODO: move the rest of this into Controler->something | ||||||
389 | elsif( ! $controler->exists( $SID ) ) { | ||||||
390 | 0 | 0 | $rc = $self->error_unknown_session( $SID ); | ||||
391 | } | ||||||
392 | else { | ||||||
393 | 0 | 0 | $controler->keepalive( $SID ); | ||||
394 | 0 | 0 | 0 | if( $event eq 'connect' ) { | |||
0 | |||||||
0 | |||||||
395 | 0 | 0 | $controler->connect( $SID, $req, $resp ); | ||||
396 | } | ||||||
397 | elsif( $event eq 'disconnect' ) { | ||||||
398 | 0 | 0 | $controler->disconnect( $SID, $req, $resp ); | ||||
399 | } | ||||||
400 | elsif( $event eq 'close' ) { | ||||||
401 | 0 | 0 | $controler->close( $SID, $req, $resp ); | ||||
402 | } | ||||||
403 | else { | ||||||
404 | # everything else is a DOM event | ||||||
405 | 0 | 0 | $controler->request( $SID, $event, $req, $resp ); | ||||
406 | } | ||||||
407 | } | ||||||
408 | 0 | 0 | 0 | $rc ||= RC_WAIT; | |||
409 | }; | ||||||
410 | |||||||
411 | 0 | 0 | 0 | unless( defined $rc ) { | |||
412 | 0 | 0 | warn "Error: $@"; | ||||
413 | 0 | 0 | $rc = $self->error_standard( RC_INTERNAL_SERVER_ERROR, $event, $@ ); | ||||
414 | } | ||||||
415 | |||||||
416 | 0 | 0 | return $rc; | ||||
417 | } | ||||||
418 | |||||||
419 | ############################################################### | ||||||
420 | ## Request for a file that starts with /xul/ | ||||||
421 | sub xul_file | ||||||
422 | { | ||||||
423 | 0 | 0 | 0 | 0 | my( $self, $kernel, $req, $resp ) = @_[ OBJECT, KERNEL, ARG0..$#_ ]; | ||
424 | |||||||
425 | # DEBUG and | ||||||
426 | 0 | 0 | warn "$$: xul_file"; | ||||
427 | 0 | 0 | my $uri = $req->uri->path; | ||||
428 | 0 | 0 | 0 | unless( $uri =~ m(^/xul/file(/(.*))?) ) { | |||
429 | 0 | 0 | return $self->error_standard( RC_BAD_REQUEST, "parsing uri", | ||||
430 | "$uri isn't a valid path\n" ); | ||||||
431 | } | ||||||
432 | 0 | 0 | 0 | my $filename = $2||''; | |||
433 | 0 | 0 | $req->uri->path( '/xul' ); | ||||
434 | 0 | 0 | my $ret = $self->parse_args( $req ); | ||||
435 | 0 | 0 | 0 | unless( ref $ret ) { | |||
436 | 0 | 0 | return $self->parse_error( $ret ); | ||||
437 | } | ||||||
438 | |||||||
439 | 0 | 0 | $req->param( filename => $filename ); | ||||
440 | 0 | 0 | return shift->xul( @_ ); | ||||
441 | } | ||||||
442 | |||||||
443 | |||||||
444 | |||||||
445 | ############################################################################ | ||||||
446 | # Static file handling | ||||||
447 | |||||||
448 | ############################################################### | ||||||
449 | sub static | ||||||
450 | { | ||||||
451 | 0 | 0 | 0 | 0 | my( $self, $kernel, $req, $resp ) = @_[ OBJECT, KERNEL, ARG0..$#_ ]; | ||
452 | |||||||
453 | 0 | 0 | DEBUG and | ||||
454 | xwarn "POE::Component::XUL->static"; | ||||||
455 | 0 | 0 | 0 | if( $self->{shutdown} ) { | |||
456 | 0 | 0 | xwarn "Static request, but we are shutdown\n"; | ||||
457 | 0 | 0 | return; | ||||
458 | } | ||||||
459 | |||||||
460 | 0 | 0 | local $self->{request} = $req; | ||||
461 | 0 | 0 | local $self->{response} = $resp; | ||||
462 | |||||||
463 | 0 | 0 | my $ret; | ||||
464 | 0 | 0 | eval { | ||||
465 | 0 | 0 | my $method = $req->method; | ||||
466 | # Verify HTTP method | ||||||
467 | 0 | 0 | 0 | 0 | unless( $method eq 'GET' or $method eq 'HEAD' ) { | ||
468 | 0 | 0 | $ret = $self->error_standard( RC_METHOD_NOT_ALLOWED, $method ); | ||||
469 | 0 | 0 | return; | ||||
470 | } | ||||||
471 | |||||||
472 | # Send the file | ||||||
473 | 0 | 0 | my $uri = $req->uri->path; | ||||
474 | 0 | 0 | DEBUG and | ||||
475 | xdebug "Static request: $uri"; | ||||||
476 | |||||||
477 | 0 | 0 | my $file = $self->uri_to_file( $uri ); | ||||
478 | 0 | 0 | 0 | if( -d $file ) { | |||
0 | |||||||
479 | 0 | 0 | $ret = $self->static_file( $uri, 'index.html' ); | ||||
480 | } | ||||||
481 | elsif( -f "$file.build" ) { | ||||||
482 | 0 | 0 | $ret = $self->build_file( $uri, $file ); | ||||
483 | } | ||||||
484 | else { | ||||||
485 | 0 | 0 | $ret = $self->static_file( $uri ); | ||||
486 | } | ||||||
487 | 0 | 0 | DEBUG and xwarn "$$: ret=$ret"; | ||||
488 | }; | ||||||
489 | |||||||
490 | 0 | 0 | 0 | if( $ret ) { | |||
491 | 0 | 0 | $resp->code( $ret ); | ||||
492 | # $response->continue; | ||||||
493 | 0 | 0 | return $ret; | ||||
494 | } | ||||||
495 | 0 | 0 | $self->error_standard( RC_INTERNAL_SERVER_ERROR, "serving static file", $@ ); | ||||
496 | } | ||||||
497 | |||||||
498 | #################################################################### | ||||||
499 | sub uri_to_file | ||||||
500 | { | ||||||
501 | 0 | 0 | 0 | 0 | my( $self, @path ) = @_; | ||
502 | |||||||
503 | 0 | 0 | my $path = File::Spec->catfile( grep {defined} @path ); | ||||
0 | 0 | ||||||
504 | 0 | 0 | $path =~ s(/\./)(/)g; | ||||
505 | 0 | 0 | $path =~ s(/\.\./)(/)g; | ||||
506 | |||||||
507 | 0 | 0 | 0 | unless( $path =~ s(^/)($self->{static_root}/) ) { | |||
508 | 0 | 0 | $path = File::Spec->catfile( $self->{static_root}, $path ); | ||||
509 | } | ||||||
510 | 0 | 0 | $path =~ s(//)(/)g; | ||||
511 | 0 | 0 | return $path; | ||||
512 | } | ||||||
513 | |||||||
514 | #################################################################### | ||||||
515 | sub static_file | ||||||
516 | { | ||||||
517 | 1 | 1 | 0 | 3 | my( $self, $uri, $file ) = @_; | ||
518 | |||||||
519 | 1 | 3 | my $req = $self->{request}; | ||||
520 | 1 | 2 | my $resp = $self->{response}; | ||||
521 | |||||||
522 | 1 | 1 | my $fullfile = $file; | ||||
523 | 1 | 50 | 3 | if( $uri ) { | |||
524 | 0 | 0 | $fullfile = $self->uri_to_file( $uri, $file ); | ||||
525 | } | ||||||
526 | 1 | 2 | DEBUG and xdebug "Static file: $fullfile"; | ||||
527 | |||||||
528 | |||||||
529 | # warn "REQUEST=", $req->as_string; | ||||||
530 | # Does the file exist? | ||||||
531 | 1 | 50 | 11 | return $self->error_not_found( $fullfile ) unless -f $fullfile; | |||
532 | |||||||
533 | 1 | 3 | my $lastmod = (stat _)[9]; | ||||
534 | 1 | 2 | my $size = (stat _)[7]; | ||||
535 | |||||||
536 | # open the file | ||||||
537 | 1 | 4 | my $in = IO::File->new( $fullfile ); | ||||
538 | 1 | 50 | 39 | unless( $in ) { | |||
539 | 0 | 0 | return $self->error( RC_FORBIDDEN, "$uri: $!" ); | ||||
540 | } | ||||||
541 | |||||||
542 | # Make sure it's not too huge | ||||||
543 | 1 | 50 | 3 | if( $size > 1024 * 1024 ) { | |||
544 | 0 | 0 | return $self->error_standard( RC_REQUEST_ENTITY_TOO_LARGE, | ||||
545 | "looking at the file", | ||||||
546 | "$size is much to large" ); | ||||||
547 | } | ||||||
548 | |||||||
549 | # set up content-type | ||||||
550 | 1 | 7 | my $ct = $self->guess_ct( $fullfile ); | ||||
551 | 1 | 1 | DEBUG and xdebug "content_type=$ct\n"; | ||||
552 | 1 | 22 | $self->{response}->content_type( $ct ); | ||||
553 | |||||||
554 | # add useful headers | ||||||
555 | 1 | 50 | 33 | 64 | if( $lastmod and not $ct =~ m(^application/vnd\.mozilla\.xul\+xml$) ) { | ||
556 | 1 | 2 | DEBUG and xdebug "Last-modified=", time2str( $lastmod ); | ||||
557 | 1 | 5 | $self->{response}->header( 'Last-Modified' => | ||||
558 | time2str( $lastmod ) | ||||||
559 | ); | ||||||
560 | } | ||||||
561 | |||||||
562 | # bail if HEAD request | ||||||
563 | 1 | 50 | 84 | if ( $req->method eq 'HEAD' ) { | |||
564 | 0 | 0 | DEBUG and | ||||
565 | xdebug "HEAD size=$size"; | ||||||
566 | 0 | 0 | $resp->content_length( $size ); | ||||
567 | 0 | 0 | return RC_OK; | ||||
568 | } | ||||||
569 | |||||||
570 | # RFC1945 says HEAD should ingore if-modified-since | ||||||
571 | |||||||
572 | # 304 check | ||||||
573 | 1 | 15 | my $since = $req->header( 'If-Modified-Since' ); | ||||
574 | 1 | 50 | 25 | if( $since ) { | |||
575 | 0 | 0 | DEBUG and xdebug "If-mod-since=$since"; | ||||
576 | 0 | 0 | $since = str2time( $since ); | ||||
577 | |||||||
578 | 0 | 0 | 0 | 0 | if ( $lastmod && $since && $since >= $lastmod ) { | ||
0 | |||||||
579 | 0 | 0 | DEBUG and xdebug "NOT MODIFIED SINCE (size=$size)"; | ||||
580 | 0 | 0 | $resp->header( 'Last-Modified' => '' ); | ||||
581 | 0 | 0 | return RC_NOT_MODIFIED; | ||||
582 | } | ||||||
583 | } | ||||||
584 | # warn "RESPONSE=", $self->{response}->as_string; | ||||||
585 | |||||||
586 | # Read and set the content | ||||||
587 | 1 | 10 | my $c = join '', <$in>; | ||||
588 | 1 | 8 | undef( $in ); | ||||
589 | |||||||
590 | 1 | 50 | 33 | 7 | if( ($uri eq '/' or $uri =~ m(^/index.html?)) and | ||
33 | |||||||
591 | $c =~ /\[APP-LIST\]/ ) { | ||||||
592 | 0 | 0 | my $alist = $self->app_list; | ||||
593 | 0 | 0 | $c =~ s/\[APP-LIST\]/$alist/g; | ||||
594 | } | ||||||
595 | |||||||
596 | 1 | 5 | $self->{response}->content( $c ); | ||||
597 | 1 | 23 | $self->{response}->content_length( length $c ); | ||||
598 | 1 | 36 | return RC_OK; | ||||
599 | } | ||||||
600 | |||||||
601 | #################################################################### | ||||||
602 | sub app_list | ||||||
603 | { | ||||||
604 | 0 | 0 | 0 | 0 | my( $self ) = @_; | ||
605 | 0 | 0 | my @html = < | ||||
606 | |||||||
617 | |
||||||
618 | HTML | ||||||
619 | 0 | 0 | my $lang = $self->language_guess; | ||||
620 | |||||||
621 | 0 | 0 | 0 | my $text = $lang eq 'fr' ? "Avec menus" : "Keep menus"; | |||
622 | 0 | 0 | my $count = keys %{ $self->{apps} }; | ||||
0 | 0 | ||||||
623 | 0 | 0 | foreach my $app ( sort keys %{ $self->{apps} } ) { | ||||
0 | 0 | ||||||
624 | 0 | 0 | 0 | 0 | next if $app eq 'IGDAIP' and 1 != $count; | ||
625 | 0 | 0 | 0 | my $name = $self->{app_names}{$app}{$lang} || $app; | |||
626 | 0 | 0 | push @html, < | ||||
627 | |
||||||
628 | ($text) | ||||||
629 | HTML | ||||||
630 | } | ||||||
631 | |||||||
632 | 0 | 0 | push @html, ""; | ||||
633 | 0 | 0 | return join "\n", @html; | ||||
634 | } | ||||||
635 | |||||||
636 | sub language_guess | ||||||
637 | { | ||||||
638 | 0 | 0 | 0 | 0 | my( $self ) = @_; | ||
639 | 0 | 0 | 0 | return $self->{default_language} unless $self->{request}; | |||
640 | 0 | 0 | my $accept = $self->{request}->header( 'Accept-Language' ); | ||||
641 | $self->{acceptor} ||= I18N::AcceptLanguage->new( | ||||||
642 | defaultLanguage => $self->{default_language}, | ||||||
643 | 0 | 0 | 0 | strict => 0 | |||
644 | ); | ||||||
645 | 0 | 0 | return $self->{acceptor}->accepts( $accept, $self->{languages} ); | ||||
646 | } | ||||||
647 | |||||||
648 | #################################################################### | ||||||
649 | # Build a file out of smaller files | ||||||
650 | # This removes the need for complex Makefiles to build up a single | ||||||
651 | # javascript / CSS / XBL file. | ||||||
652 | # | ||||||
653 | # The Build files is the filename + .build extention | ||||||
654 | # A Cache file is the filename + .cache extention | ||||||
655 | sub build_file | ||||||
656 | { | ||||||
657 | 1 | 1 | 0 | 29460 | my( $self, $uri, $fullfile ) = @_; | ||
658 | |||||||
659 | 1 | 3 | my $bfile = "$fullfile.build"; | ||||
660 | 1 | 27 | my $bage = (stat $bfile)[9]; | ||||
661 | 1 | 3 | my $cfile = "$fullfile.cache"; | ||||
662 | 1 | 19 | my $cage = (stat $cfile)[9]; | ||||
663 | |||||||
664 | 1 | 50 | 33 | 6 | unless( $cage and $cage > $bage ) { # cache file isn't newer then build file | ||
665 | # so we have to create the cache file | ||||||
666 | 1 | 3 | local $self->{loop_check} = {}; | ||||
667 | 1 | 4 | $self->create_cache_file( $cfile, $bfile ); | ||||
668 | } | ||||||
669 | |||||||
670 | 1 | 53 | return $self->static_file( '', $cfile ); | ||||
671 | } | ||||||
672 | |||||||
673 | ############################################################ | ||||||
674 | # Recursively create the file in $cfile from $bfile | ||||||
675 | sub create_cache_file | ||||||
676 | { | ||||||
677 | 8 | 8 | 0 | 579 | my( $self, $cfile, $bfile ) = @_; | ||
678 | 8 | 7 | my $out = $cfile; | ||||
679 | 8 | 100 | 35 | $out = IO::File->new( "> $cfile" ) unless ref $cfile; | |||
680 | |||||||
681 | 8 | 459 | my $dir = dirname $bfile; | ||||
682 | |||||||
683 | 8 | 50 | 23 | if( $self->{loop_check}{ $bfile } ) { | |||
684 | 0 | 0 | die "Recursion detected: $bfile included more then once"; | ||||
685 | } | ||||||
686 | 8 | 17 | local $self->{loop_check}{ $bfile } = 1; | ||||
687 | |||||||
688 | 8 | 50 | 31 | my $in = IO::File->new( $bfile ) or die "Unable to read $bfile: $!\n"; | |||
689 | 8 | 511 | while( my $line = <$in> ) { | ||||
690 | 16 | 100 | 140 | if( $line =~ /^\s*\@include "(.+)"\s*$/) { | |||
691 | 6 | 155 | my $file = File::Spec->rel2abs( $1, $dir ); | ||||
692 | 6 | 14 | $self->create_cache_file( $out, $file ); | ||||
693 | } | ||||||
694 | else { | ||||||
695 | 10 | 25 | $out->print( $line ); | ||||
696 | } | ||||||
697 | } | ||||||
698 | } | ||||||
699 | |||||||
700 | ############################################################ | ||||||
701 | sub guess_ct | ||||||
702 | { | ||||||
703 | 3 | 3 | 0 | 1824 | my($self, $file)=@_; | ||
704 | 3 | 9 | $file =~ s/\.cache$//; | ||||
705 | 3 | 11 | my $ct = $self->{mimetypes}->mimeTypeOf( $file ); | ||||
706 | 3 | 100 | 151 | $ct ||= 'application/octet-stream'; | |||
707 | 3 | 50 | 13 | $ct .= '; charset=iso-8859-1' if $ct eq 'text/html'; | |||
708 | |||||||
709 | 3 | 32 | return $ct; | ||||
710 | } | ||||||
711 | |||||||
712 | ############################################################ | ||||||
713 | # URI that would restart an application | ||||||
714 | sub uri_restart | ||||||
715 | { | ||||||
716 | 0 | 0 | 0 | 0 | my( $self ) = @_; | ||
717 | 0 | 0 | my $req = $self->{request}; | ||||
718 | 0 | 0 | my $uri = $req->uri; | ||||
719 | |||||||
720 | # We need to know what the browser thinks we are called | ||||||
721 | 0 | 0 | my $host = $req->header( 'X-Forwarded-Host' ); | ||||
722 | 0 | 0 | 0 | if( $host ) { | |||
723 | 0 | 0 | xwarn "Restart on $host"; | ||||
724 | 0 | 0 | $host =~ s/,.+$//; | ||||
725 | 0 | 0 | $uri->host( $host ); | ||||
726 | 0 | 0 | 0 | 0 | $uri->port( undef ) if defined $uri->port and 0==$uri->port; | ||
727 | } | ||||||
728 | 0 | 0 | my $referer = $req->header( 'Referer' ); | ||||
729 | 0 | 0 | 0 | 0 | if( $referer and $referer =~ /https/ ) { | ||
730 | 0 | 0 | $uri->scheme( 'https' ); | ||||
731 | } | ||||||
732 | 0 | 0 | $uri->path( '/start.xul' ); | ||||
733 | 0 | 0 | my $app = $req->param( 'app' ); | ||||
734 | 0 | 0 | $uri->query_keywords( $app ); | ||||
735 | 0 | 0 | return $uri; | ||||
736 | } | ||||||
737 | |||||||
738 | ############################################################################ | ||||||
739 | # Error handling | ||||||
740 | |||||||
741 | ############################################################ | ||||||
742 | sub error | ||||||
743 | { | ||||||
744 | 0 | 0 | 0 | 0 | my($self, $code, $text, $ct)=@_; | ||
745 | |||||||
746 | 0 | 0 | 0 | $ct ||= 'text/plain'; | |||
747 | |||||||
748 | # This could get annoying fast. It also shows 404s | ||||||
749 | 0 | 0 | 0 | warn "$code $text\n"unless $ENV{AUTOMATED_TESTING}; | |||
750 | 0 | 0 | 0 | 0 | xlog "$code $text\n" | ||
751 | if $ct eq 'text/plain' and (DEBUG or $code != RC_NOT_FOUND); | ||||||
752 | |||||||
753 | 0 | 0 | 0 | if( $self->{response} ) { | |||
754 | 0 | 0 | $self->{response}->code( $code ); | ||||
755 | 0 | 0 | $self->{response}->content_type( $ct ); | ||||
756 | 0 | 0 | 0 | if( $ct eq 'text/html' ) { | |||
757 | 0 | 0 | $text = encode_entities_numeric( $text, "\x80-\xff" ); | ||||
758 | } | ||||||
759 | |||||||
760 | 0 | 0 | $self->{response}->content( $text ); | ||||
761 | 0 | 0 | $self->{response}->content_length( length $text ); | ||||
762 | } | ||||||
763 | else { | ||||||
764 | 0 | 0 | xcarp "Response was already sent!"; | ||||
765 | } | ||||||
766 | 0 | 0 | return $code; | ||||
767 | } | ||||||
768 | |||||||
769 | ############################################################ | ||||||
770 | sub error_standard | ||||||
771 | { | ||||||
772 | 0 | 0 | 0 | 0 | my( $self, $code, $when, $what ) = @_; | ||
773 | |||||||
774 | # Thank you HTTP::Status | ||||||
775 | 0 | 0 | my $message = status_message( $code ); | ||||
776 | 0 | 0 | 0 | $message ||= 'unknown'; | |||
777 | |||||||
778 | 0 | 0 | 0 | $what ||= ''; | |||
779 | |||||||
780 | 0 | 0 | return $self->error( $code, "Error while $when: $message ($code)\n$what" ); | ||||
781 | } | ||||||
782 | |||||||
783 | ############################################################ | ||||||
784 | sub error_not_found | ||||||
785 | { | ||||||
786 | 0 | 0 | 0 | 0 | my( $self, $file ) = @_; | ||
787 | 0 | 0 | my $msg = "Unknown file '$file'"; | ||||
788 | 0 | 0 | xwarn "$msg\n"; | ||||
789 | |||||||
790 | 0 | 0 | return $self->error( RC_NOT_FOUND, <<" HTML", 'text/html'); | ||||
791 | |||||||
792 | |
||||||
793 | |||||||
794 | Le fichier que vous cherchez ne semble pas exister. |
||||||
795 | $msg |
||||||
796 | |||||||
797 | |||||||
798 | HTML | ||||||
799 | } | ||||||
800 | |||||||
801 | ############################################################### | ||||||
802 | ## TODO : as XUL | ||||||
803 | sub error_unknown_session | ||||||
804 | { | ||||||
805 | 0 | 0 | 0 | 0 | my( $self, $SID ) = @_; | ||
806 | |||||||
807 | 0 | 0 | xwarn "Unknown session $SID"; | ||||
808 | |||||||
809 | 0 | 0 | my $url = $self->uri_restart; | ||||
810 | |||||||
811 | 0 | 0 | return $self->error( RC_GONE, <<" HTML", 'text/html'); | ||||
812 | |||||||
813 | |
||||||
814 | |||||||
815 | Program inexistante |
||||||
816 | Votre session ($SID) n'existe pas. Elle est surement expirée. |
||||||
817 | |||||||
818 | |||||||
819 | |||||||
820 | HTML | ||||||
821 | } | ||||||
822 | |||||||
823 | ############################################################### | ||||||
824 | ## TODO : as XUL | ||||||
825 | sub error_boot_fail | ||||||
826 | { | ||||||
827 | 0 | 0 | 0 | 0 | my( $self, $fail ) = @_; | ||
828 | |||||||
829 | 0 | 0 | return $self->error( RC_NOT_FOUND, <<" HTML", 'text/html'); | ||||
830 | |||||||
831 | |
||||||
832 | |||||||
833 | Écheque au démarrage |
||||||
834 | $fail |
||||||
835 | |||||||
836 | |||||||
837 | HTML | ||||||
838 | } | ||||||
839 | |||||||
840 | |||||||
841 | |||||||
842 | |||||||
843 | ############################################################ | ||||||
844 | sub httpd_error | ||||||
845 | { | ||||||
846 | 0 | 0 | 0 | 0 | my( $self, $request, $response) = @_[ OBJECT, ARG0..$#_ ]; | ||
847 | |||||||
848 | 0 | 0 | my $op=$request->header('Operation'); | ||||
849 | 0 | 0 | my $errnum=$request->header('Errnum'); | ||||
850 | 0 | 0 | my $errstr=$request->header('Error'); | ||||
851 | |||||||
852 | 0 | 0 | DEBUG and | ||||
853 | xdebug "HTTPD ERROR op=$op errstr=$errstr errnum=$errnum\n"; | ||||||
854 | |||||||
855 | 0 | 0 | 0 | 0 | if($op eq 'read' and ($errnum==0 or $errnum = ECONNRESET)) { | ||
0 | |||||||
856 | # remote closed | ||||||
857 | 0 | 0 | 0 | 0 | if( $self->{controler} and $request ) { | ||
858 | 0 | 0 | DEBUG and | ||||
859 | xdebug "$$ REMOTE CLOSED req=$request"; | ||||||
860 | 0 | 0 | $self->{controler}->cancel( $request ); | ||||
861 | } | ||||||
862 | # PostHandler will deal with resuming the listening socket | ||||||
863 | } | ||||||
864 | else { | ||||||
865 | 0 | 0 | xwarn "Error during $op: [$errnum] $errstr"; | ||||
866 | } | ||||||
867 | |||||||
868 | 0 | 0 | return RC_OK; | ||||
869 | |||||||
870 | } | ||||||
871 | |||||||
872 | ############################################################################ | ||||||
873 | # Peeking | ||||||
874 | |||||||
875 | ############################################################### | ||||||
876 | sub poe_size | ||||||
877 | { | ||||||
878 | 0 | 0 | 0 | 0 | my( $self, $kernel, $req, $resp ) = @_[ OBJECT, KERNEL, ARG0, ARG1 ]; | ||
879 | |||||||
880 | 0 | 0 | my $content = -1; | ||||
881 | 0 | 0 | if( DEBUG and $HAVE_DEVEL_SIZE ) { | ||||
882 | $content = Devel::Size::total_size( $kernel ); | ||||||
883 | } | ||||||
884 | 0 | 0 | $resp->code( RC_OK ); | ||||
885 | 0 | 0 | $resp->content_type( 'text/plain' ); | ||||
886 | 0 | 0 | $resp->content_length( length $content ); | ||||
887 | 0 | 0 | $resp->content( $content ); | ||||
888 | 0 | 0 | return RC_OK; | ||||
889 | } | ||||||
890 | |||||||
891 | sub poe_kernel | ||||||
892 | { | ||||||
893 | 0 | 0 | 0 | 0 | my( $self, $kernel, $req, $resp ) = @_[ OBJECT, KERNEL, ARG0, ARG1 ]; | ||
894 | |||||||
895 | 0 | 0 | my $content = ''; | ||||
896 | 0 | 0 | if( DEBUG and $HAVE_DATA_DUMPER ) { | ||||
897 | local $Data::Dumper::Indent = 1; | ||||||
898 | $content = Data::Dumper::Dumper( $kernel ); | ||||||
899 | } | ||||||
900 | 0 | 0 | $resp->code( RC_OK ); | ||||
901 | 0 | 0 | $resp->content_type( 'text/plain' ); | ||||
902 | 0 | 0 | $resp->content_length( length $content ); | ||||
903 | 0 | 0 | $resp->content( $content ); | ||||
904 | 0 | 0 | return RC_OK; | ||||
905 | } | ||||||
906 | |||||||
907 | sub poe_test | ||||||
908 | { | ||||||
909 | 0 | 0 | 0 | 0 | my( $self, $kernel, $req, $resp ) = @_[ OBJECT, KERNEL, ARG0, ARG1 ]; | ||
910 | |||||||
911 | 0 | 0 | local $self->{request} = $req; | ||||
912 | 0 | 0 | local $self->{response} = $resp; | ||||
913 | |||||||
914 | 0 | 0 | $self->parse_args( $req ); | ||||
915 | |||||||
916 | 0 | 0 | my $uri_restart = $self->uri_restart; | ||||
917 | 0 | 0 | my $content = < | ||||
918 | uri_restart: $uri_restart | ||||||
919 | TEXT | ||||||
920 | 0 | 0 | xwarn "content=$content"; | ||||
921 | 0 | 0 | $resp->code( RC_OK ); | ||||
922 | 0 | 0 | $resp->content_type( 'text/plain' ); | ||||
923 | 0 | 0 | $resp->content_length( length $content ); | ||||
924 | 0 | 0 | $resp->content( $content ); | ||||
925 | 0 | 0 | return RC_OK; | ||||
926 | } | ||||||
927 | |||||||
928 | |||||||
929 | |||||||
930 | |||||||
931 | |||||||
932 | |||||||
933 | ############################################################################ | ||||||
934 | # Log handling | ||||||
935 | |||||||
936 | ############################################################ | ||||||
937 | sub build_logging | ||||||
938 | { | ||||||
939 | 6 | 6 | 0 | 9 | my( $self, $args_log ) = @_; | ||
940 | |||||||
941 | 6 | 38 | $self->{logging} = POE::XUL::Logging->new( $args_log, $self->{log_root} ); | ||||
942 | } | ||||||
943 | |||||||
944 | ############################################################ | ||||||
945 | sub log_setup | ||||||
946 | { | ||||||
947 | 5 | 5 | 0 | 1491 | my( $self ) = @_; | ||
948 | 5 | 22 | $self->{logging}->setup; | ||||
949 | } | ||||||
950 | |||||||
951 | ############################################################ | ||||||
952 | sub sig_HUP | ||||||
953 | { | ||||||
954 | 0 | 0 | 0 | my( $self ) = @_; | |||
955 | 0 | xwarn "SIGHUP"; | |||||
956 | 0 | $poe_kernel->sig_handled(); | |||||
957 | |||||||
958 | 0 | $self->log_setup; | |||||
959 | } | ||||||
960 | |||||||
961 | |||||||
962 | ############################################################ | ||||||
963 | sub post_connection | ||||||
964 | { | ||||||
965 | 0 | 0 | 0 | my( $self, $req, $resp ) = @_; | |||
966 | 0 | 0 | my $app = eval { $req->param( 'app' ) } || $self->{logging}->{app}; | ||||
967 | 0 | local $self->{logging}->{app} = $app; | |||||
968 | |||||||
969 | 0 | my $conn = $req->connection; | |||||
970 | 0 | my @log; | |||||
971 | 0 | 0 | push @log, ($conn ? $conn->remote_ip : '0.0.0.0'); | ||||
972 | 0 | 0 | 0 | if( $log[-1] eq '127.0.0.1' and $req->header( 'X-Forwarded-For' ) ) { | |||
973 | 0 | $log[-1] = $req->header( 'X-Forwarded-For' ); | |||||
974 | } | ||||||
975 | # push @log, ($self->{preforked} ? $$ : '-'); | ||||||
976 | 0 | push @log, $$, '-'; | |||||
977 | |||||||
978 | |||||||
979 | |||||||
980 | 0 | my $path = $req->uri->path; | |||||
981 | 0 | my $query = $req->uri->query; | |||||
982 | 0 | 0 | 0 | $path .= "?$query" if $query and $req->method eq 'GET'; | |||
983 | |||||||
984 | 0 | push @log, "[". POSIX::strftime("%d/%m/%Y:%H:%M:%S %z", localtime)."]", | |||||
985 | join ' ', $req->method, $path; | ||||||
986 | 0 | $log[-1] = qq("$log[-1]"); | |||||
987 | 0 | 0 | push @log, ($resp->code||'000'), ($resp->content_length||0); | ||||
0 | |||||||
988 | |||||||
989 | 0 | xlog( { message => join( ' ', @log )."\n", | |||||
990 | type => 'REQ' | ||||||
991 | } ); | ||||||
992 | # use Devel::Cycle; | ||||||
993 | # find_cycle( $poe_kernel ); | ||||||
994 | 0 | return RC_OK; | |||||
995 | } | ||||||
996 | |||||||
997 | |||||||
998 | |||||||
999 | |||||||
1000 | 1; | ||||||
1001 | |||||||
1002 | __END__ |