| 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__ |