X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=rt%2Flib%2FRT%2FInterface%2FWeb%2FHandler.pm;h=ad1068bac1a10718571f0aaee2691d7d70ca21cb;hb=9ce482da3960ee43decee41fba53b78c12c3e52c;hp=a1784c2cc596817f6f0a71579899ac3cee3f606e;hpb=7588a4ac90a9b07c08a3107cd1107d773be1c991;p=freeside.git diff --git a/rt/lib/RT/Interface/Web/Handler.pm b/rt/lib/RT/Interface/Web/Handler.pm index a1784c2cc..ad1068bac 100644 --- a/rt/lib/RT/Interface/Web/Handler.pm +++ b/rt/lib/RT/Interface/Web/Handler.pm @@ -2,7 +2,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2016 Best Practical Solutions, LLC # # # (Except where explicitly superseded by other copyright notices) @@ -54,7 +54,6 @@ use CGI qw/-private_tempfiles/; use MIME::Entity; use Text::Wrapper; use CGI::Cookie; -use Time::ParseDate; use Time::HiRes; use HTML::Scrubber; use RT::Interface::Web; @@ -62,6 +61,9 @@ use RT::Interface::Web::Request; use File::Path qw( rmtree ); use File::Glob qw( bsd_glob ); use File::Spec::Unix; +use HTTP::Message::PSGI; +use HTTP::Request; +use HTTP::Response; sub DefaultHandlerArgs { ( comp_root => [ @@ -104,7 +106,6 @@ sub InitSessionDir { } -use UNIVERSAL::require; sub NewHandler { my $class = shift; $class->require or die $!; @@ -114,7 +115,7 @@ sub NewHandler { @_ ); - $handler->interp->set_escape( h => \&RT::Interface::Web::EscapeUTF8 ); + $handler->interp->set_escape( h => \&RT::Interface::Web::EscapeHTML ); $handler->interp->set_escape( u => \&RT::Interface::Web::EscapeURI ); $handler->interp->set_escape( j => \&RT::Interface::Web::EscapeJS ); return($handler); @@ -154,7 +155,7 @@ and is not recommended to change. =item Clean up state of RT::Action::SendEmail using 'CleanSlate' method -=item Flush tmp GnuPG key preferences +=item Flush tmp crypt key preferences =back @@ -181,10 +182,9 @@ sub CleanupRequest { require RT::Action::SendEmail; RT::Action::SendEmail->CleanSlate; - if (RT->Config->Get('GnuPG')->{'Enable'}) { - require RT::Crypt::GnuPG; - RT::Crypt::GnuPG::UseKeyForEncryption(); - RT::Crypt::GnuPG::UseKeyForSigning( undef ); + if (RT->Config->Get('Crypt')->{'Enable'}) { + RT::Crypt->UseKeyForEncryption(); + RT::Crypt->UseKeyForSigning( undef ); } %RT::Ticket::MERGE_CACHE = ( effective => {}, merged => {} ); @@ -248,10 +248,10 @@ MODPERL use RT::Interface::Web::Handler; use CGI::Emulate::PSGI; +use Plack::Builder; use Plack::Request; use Plack::Response; use Plack::Util; -use Encode qw(encode_utf8); sub PSGIApp { my $self = shift; @@ -263,7 +263,7 @@ sub PSGIApp { $self->InitSessionDir; - return sub { + my $mason = sub { my $env = shift; { @@ -271,14 +271,21 @@ sub PSGIApp { return $self->_psgi_response_cb( $res->finalize ) if $res; } - RT::ConnectToDatabase() unless RT->InstallMode; + unless (RT->InstallMode) { + unless (eval { RT::ConnectToDatabase() }) { + my $res = Plack::Response->new(503); + $res->content_type("text/plain"); + $res->body("Database inaccessible; contact the RT administrator (".RT->Config->Get("OwnerEmail").")"); + return $self->_psgi_response_cb( $res->finalize, sub { $self->CleanupRequest } ); + } + } my $req = Plack::Request->new($env); # CGI.pm normalizes .. out of paths so when you requested # /NoAuth/../Ticket/Display.html we saw Ticket/Display.html # PSGI doesn't normalize .. so we have to deal ourselves. - if ( $req->path_info =~ m{/\.} ) { + if ( $req->path_info =~ m{(^|/)\.\.?(/|$)} ) { $RT::Logger->crit("Invalid request for ".$req->path_info." aborting"); my $res = Plack::Response->new(400); return $self->_psgi_response_cb($res->finalize,sub { $self->CleanupRequest }); @@ -308,7 +315,59 @@ sub PSGIApp { sub { $self->CleanupRequest() }); -}; + }; + + my $app = $self->StaticWrap($mason); + for my $plugin (RT->Config->Get("Plugins")) { + my $wrap = $plugin->can("PSGIWrap") + or next; + $app = $wrap->($plugin, $app); + } + return $app; +} + +sub StaticWrap { + my $self = shift; + my $app = shift; + my $builder = Plack::Builder->new; + + my $headers = RT::Interface::Web::GetStaticHeaders(Time => 'forever'); + + for my $static ( RT->Config->Get('StaticRoots') ) { + if ( ref $static && ref $static eq 'HASH' ) { + $builder->add_middleware( + '+RT::Interface::Web::Middleware::StaticHeaders', + path => $static->{'path'}, + headers => $headers, + ); + $builder->add_middleware( + 'Plack::Middleware::Static', + pass_through => 1, + %$static + ); + } + else { + $RT::Logger->error( + "Invalid config StaticRoots: item can only be a hashref" ); + } + } + + my $path = sub { s!^/static/!! }; + $builder->add_middleware( + '+RT::Interface::Web::Middleware::StaticHeaders', + path => $path, + headers => $headers, + ); + for my $root (RT::Interface::Web->StaticRoots) { + $builder->add_middleware( + 'Plack::Middleware::Static', + path => $path, + root => $root, + pass_through => 1, + ); + } + return $builder->to_app($app); +} sub _psgi_response_cb { my $self = shift; @@ -328,11 +387,26 @@ sub _psgi_response_cb { $cleanup->(); return ''; } - return utf8::is_utf8($_[0]) ? encode_utf8($_[0]) : $_[0]; + # XXX: Ideally, responses should flag if they need + # to be encoded, rather than relying on the UTF-8 + # flag + return Encode::encode("UTF-8",$_[0]) if utf8::is_utf8($_[0]); return $_[0]; }; }); - } +} + +sub GetStatic { + my $class = shift; + my $path = shift; + my $static = $class->StaticWrap( + # Anything the static wrap doesn't handle gets 404'd. + sub { [404, [], []] } + ); + my $response = HTTP::Response->from_psgi( + $static->( HTTP::Request->new(GET => $path)->to_psgi ) + ); + return $response; } 1;