diff options
-rw-r--r-- | Bugzilla.pm | 9 | ||||
-rw-r--r-- | Bugzilla/CGI.pm | 10 | ||||
-rw-r--r-- | Bugzilla/Quantum/CGI.pm | 153 | ||||
-rw-r--r-- | Bugzilla/Quantum/Legacy.pm | 58 | ||||
-rw-r--r-- | Bugzilla/Quantum/Plugin/Glue.pm | 52 |
5 files changed, 93 insertions, 189 deletions
diff --git a/Bugzilla.pm b/Bugzilla.pm index ff588028c..b68586c8d 100644 --- a/Bugzilla.pm +++ b/Bugzilla.pm @@ -235,14 +235,7 @@ sub extensions { } sub cgi { - my ( undef, $cgi ) = @_; - - if ( defined $cgi ) { - return request_cache->{cgi} = $cgi; - } - else { - return request_cache->{cgi} ||= Bugzilla::CGI->new; - } + return request_cache->{cgi} ||= Bugzilla::CGI->new; } sub input_params { diff --git a/Bugzilla/CGI.pm b/Bugzilla/CGI.pm index 1a191daaa..78037292a 100644 --- a/Bugzilla/CGI.pm +++ b/Bugzilla/CGI.pm @@ -560,8 +560,16 @@ sub header { $headers{'-link'} .= ', <https://www.google-analytics.com>; rel="preconnect"; crossorigin'; } } + my $headers = $self->SUPER::header(%headers) || ''; - return $self->SUPER::header(%headers) || ""; + if ($self->server_software eq 'Bugzilla::Quantum::Plugin::Glue') { + my $c = Bugzilla::request_cache->{mojo_controller}; + $c->res->headers(Mojo::Headers->parse($headers)); + return ''; + } + else { + return $headers; + } } sub param { diff --git a/Bugzilla/Quantum/CGI.pm b/Bugzilla/Quantum/CGI.pm index 4cbbe0418..4d43158cc 100644 --- a/Bugzilla/Quantum/CGI.pm +++ b/Bugzilla/Quantum/CGI.pm @@ -6,133 +6,52 @@ # defined by the Mozilla Public License, v. 2.0. package Bugzilla::Quantum::CGI; -use 5.10.1; -use Carp qw(confess); -use Moo; +use Mojo::Base 'Mojolicious::Controller'; -has 'controller' => ( - is => 'ro', - handles => [qw[req res]], -); +use CGI::Compile; +use Bugzilla::Constants qw(bz_locations); +use File::Slurper qw(read_text); +use File::Spec::Functions qw(catfile); +use Sub::Quote 2.005000; +use Taint::Util qw(untaint); -has 'csp_object' => ( - is => 'ro', - writer => 'set_csp_object', -); +my %CGIS; +my %SKIP = ( 'xmlrpc.cgi' => 1, 'jsonrpc.cgi' => 1, 'rest.cgi' => 1); -with 'Bugzilla::CGI::Role'; +_load_all(); -sub script_name { - my ($self) = @_; - - return $self->req->env->{SCRIPT_NAME}; -} - -sub referer { - my ($self) = @_; - - return $self->req->headers->referrer; -} - -sub http { - my ($self, $header) = @_; - return $self->req->headers->header($header); -} - -sub header { - my ($self, @args) = @_; - return '' if @args == 0; - - if (@args == 1) { - $self->res->headers->content_type($args[0]); +sub expose_routes { + my ($class, $r) = @_; + foreach my $cgi (keys %CGIS) { + $r->any("/$cgi")->to("CGI#$CGIS{$cgi}"); } - - return ''; } -sub cookie { ## no critic (unpack) - my $self = shift; - my $c = $self->controller; - if (@_ == 1 && !ref $_[0]) { - my ($name) = @_; - return $c->cookie($name); - } - else { - die "cookie(@_) is not understood"; +sub _load_all { + foreach my $script (glob '*.cgi') { + next if $SKIP{$script}; + my $name = _load_cgi($script); + $CGIS{ $script } = $name; } } -sub user_agent { - my $self = shift; - - return $self->req->headers->user_agent; -} - -sub url { ## no critic (unpack) - my $self = shift; - my $c = $self->controller; - if ($_[0] eq '-relative' && $_[1] == 1) { - return $c->url_for; - } - else { - confess "url(@_) is not understood"; - } -} - -sub param { ## no critic (unpack) - my $self = shift; - if (@_ == 1) { - my ($name) = @_; - return $self->req->param($name); - } - else { - die "param(@_) is not understood"; - } -} - -sub delete { ## no critic (builtin) - my ($self, $name) = @_; - $self->req->params->remove($name); -} - -sub redirect { - my ($self, $location) = @_; - - $self->controller->redirect_to($location); -} - -sub Vars { - my ($self) = @_; - - return $self->req->query_params->to_hash; -} - -sub query_string { - my ($self) = @_; - - return $self->req->query_params->to_string; -} - -sub send_cookie { - my ($self, %params) = @_; - my $name = delete $params{'-name'}; - my $value = delete $params{'-value'} or ThrowCodeError('cookies_need_value'); - state $uri = URI->new( Bugzilla->localconfig->{urlbase} ); - my %attrs = ( - path => $uri->path, - secure => lc( $uri->scheme ) eq 'https', - samesite => 'Lax', +sub _load_cgi { + my ($file) = @_; + my $name = $file; + $name =~ s/\.cgi$//s; + $name =~ s/\W+/_/gs; + my $subname = "handle_$name"; + my $content = read_text(catfile(bz_locations->{cgi_path}, $file)); + untaint($content); + $content = 'my ($self) = @_; ' . $content; + my %options = ( + package => __PACKAGE__ . "::$name", + file => $file, + line => 1, + no_defer => 1, ); - my $expires = delete $params{'-expires'}; - $attrs{expires} = $expires if $expires; - $attrs{httponly} = 1 if delete $params{'-httponly'}; - - if (keys %params) { - die "Unknown keys: " . join(", ", keys %params); - } - - $self->controller->cookie($name, $value, \%params); + quote_sub $subname, $content, {}, \%options; + return $subname; } -1; - +1;
\ No newline at end of file diff --git a/Bugzilla/Quantum/Legacy.pm b/Bugzilla/Quantum/Legacy.pm deleted file mode 100644 index d093d76a0..000000000 --- a/Bugzilla/Quantum/Legacy.pm +++ /dev/null @@ -1,58 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. -# -# This Source Code Form is "Incompatible With Secondary Licenses", as -# defined by the Mozilla Public License, v. 2.0. - -package Bugzilla::Quantum::Legacy; -use Mojo::Base 'Mojolicious::Controller'; -use CGI::Compile; -use File::Spec::Functions qw(catfile); -use Bugzilla::Constants qw(bz_locations); -use Taint::Util qw(untaint); -use Sub::Name qw(subname); -use File::Slurper qw(read_text); -use Sub::Quote 2.005000; -use Try::Tiny; - -my %CGIS; -my %SKIP = ( 'xmlrpc.cgi' => 1, 'jsonrpc.cgi' => 1, 'rest.cgi' => 1); - -_load_all(); - -sub expose_routes { - my ($class, $r) = @_; - foreach my $cgi (keys %CGIS) { - $r->any("/$cgi")->to("Legacy#$CGIS{$cgi}"); - } -} - -sub _load_all { - foreach my $script (glob '*.cgi') { - next if $SKIP{$script}; - my $name = _load_cgi($script); - $CGIS{ $script } = $name; - } -} - -sub _load_cgi { - my ($file) = @_; - my $name = $file; - $name =~ s/\./_/g; - $name =~ s/\W+/_/g; - my $content = read_text(catfile(bz_locations->{cgi_path}, $file)); - untaint($content); - $content = 'my ($self) = @_; ' . $content; - my %options = ( - package => __PACKAGE__ . "::$name", - file => $file, - line => 1, - no_defer => 1, - ); - quote_sub $name, $content, {}, \%options; - return $name; -} - - -1; diff --git a/Bugzilla/Quantum/Plugin/Glue.pm b/Bugzilla/Quantum/Plugin/Glue.pm index a28c2598d..abada14f8 100644 --- a/Bugzilla/Quantum/Plugin/Glue.pm +++ b/Bugzilla/Quantum/Plugin/Glue.pm @@ -10,8 +10,9 @@ use Mojo::Base 'Mojolicious::Plugin'; use Try::Tiny; use Bugzilla::Constants; -use Bugzilla::Quantum::CGI; use Bugzilla::Quantum::Template; +use Socket qw(AF_INET inet_aton); +use Sys::Hostname; sub register { my ( $self, $app, $conf ) = @_; @@ -46,13 +47,13 @@ sub register { around_dispatch => sub { my ($next, $c) = @_; try { - local %{ Bugzilla->request_cache } = (); local $CGI::Compile::USE_REAL_EXIT = 0; - # HACK, should just make i_am_cgi smarter. - local $ENV{'SERVER_SOFTWARE'} = 1; - Bugzilla->cgi( Bugzilla::Quantum::CGI->new(controller => $c) ); + local %ENV = _ENV($c); + Bugzilla::init_page(); + Bugzilla::request_cache->{mojo_controller} = $c; Bugzilla->template( Bugzilla::Quantum::Template->new( controller => $c, template => $template ) ); $next->(); + Bugzilla::_cleanup; ## no critic (private) } catch { die $_ unless ref $_ eq 'ARRAY' && $_->[0] eq "EXIT\n" || /\bModPerl::Util::exit\b/; }; @@ -60,4 +61,45 @@ sub register { ); } +sub _ENV { + my ($c) = @_; + my $tx = $c->tx; + my $req = $tx->req; + my $headers = $req->headers; + my $content_length = $req->content->is_multipart ? $req->body_size : $headers->content_length; + my %env_headers = ( HTTP_COOKIE => '', HTTP_REFERER => '' ); + + for my $name ( @{ $headers->names } ) { + my $key = uc "http_$name"; + $key =~ s!\W!_!g; + $env_headers{$key} = $headers->header($name); + } + + if ( my $userinfo = $c->req->url->to_abs->userinfo ) { + $remote_user = $userinfo =~ /([^:]+)/ ? $1 : ''; + } + elsif ( my $authenticate = $headers->authorization ) { + $remote_user = $authenticate =~ /Basic\s+(.*)/ ? b64_decode $1 : ''; + $remote_user = $remote_user =~ /([^:]+)/ ? $1 : ''; + } + + return ( + CONTENT_LENGTH => $content_length || 0, + CONTENT_TYPE => $headers->content_type || '', + GATEWAY_INTERFACE => 'CGI/1.1', + HTTPS => $req->is_secure ? 'YES' : 'NO', + %env_headers, + QUERY_STRING => $c->stash('cgi.query_string') || $req->url->query->to_string, + REMOTE_ADDR => $tx->remote_address, + REMOTE_HOST => gethostbyaddr( inet_aton( $tx->remote_address || '127.0.0.1' ), AF_INET ) || '', + REMOTE_PORT => $tx->remote_port, + REMOTE_USER => $remote_user || '', + REQUEST_METHOD => $req->method, + SCRIPT_NAME => $req->env->{SCRIPT_NAME} SERVER_NAME => hostname, + SERVER_PORT => $tx->local_port, + SERVER_PROTOCOL => $req->is_secure ? 'HTTPS' : 'HTTP', # TODO: Version is missing + SERVER_SOFTWARE => __PACKAGE__, + ); +} + 1;
\ No newline at end of file |