From 4a66989c7cf4bcb1afce0c4e39a3f1c87ef0e57c Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Tue, 3 Apr 2018 23:05:04 -0400 Subject: Bug 1455495 - Replace apache with Mojolicious --- Bugzilla/Quantum/CGI.pm | 162 ++++++++++++++++++++++++++++ Bugzilla/Quantum/Plugin/BasicAuth.pm | 40 +++++++ Bugzilla/Quantum/Plugin/BlockIP.pm | 43 ++++++++ Bugzilla/Quantum/Plugin/Glue.pm | 114 ++++++++++++++++++++ Bugzilla/Quantum/Plugin/Hostage.pm | 80 ++++++++++++++ Bugzilla/Quantum/SES.pm | 203 +++++++++++++++++++++++++++++++++++ Bugzilla/Quantum/Static.pm | 30 ++++++ Bugzilla/Quantum/Stdout.pm | 59 ++++++++++ Bugzilla/Quantum/Template.pm | 39 +++++++ 9 files changed, 770 insertions(+) create mode 100644 Bugzilla/Quantum/CGI.pm create mode 100644 Bugzilla/Quantum/Plugin/BasicAuth.pm create mode 100644 Bugzilla/Quantum/Plugin/BlockIP.pm create mode 100644 Bugzilla/Quantum/Plugin/Glue.pm create mode 100644 Bugzilla/Quantum/Plugin/Hostage.pm create mode 100644 Bugzilla/Quantum/SES.pm create mode 100644 Bugzilla/Quantum/Static.pm create mode 100644 Bugzilla/Quantum/Stdout.pm create mode 100644 Bugzilla/Quantum/Template.pm (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/CGI.pm b/Bugzilla/Quantum/CGI.pm new file mode 100644 index 000000000..85f14cf83 --- /dev/null +++ b/Bugzilla/Quantum/CGI.pm @@ -0,0 +1,162 @@ +# 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::CGI; +use Mojo::Base 'Mojolicious::Controller'; + +use CGI::Compile; +use Bugzilla::Constants qw(bz_locations); +use Bugzilla::Quantum::Stdout; +use File::Slurper qw(read_text); +use File::Spec::Functions qw(catfile); +use Sub::Name; +use Sub::Quote 2.005000; +use Try::Tiny; +use Taint::Util qw(untaint); +use Socket qw(AF_INET inet_aton); +use Sys::Hostname; +use English qw(-no_match_vars); + +our $C; +my %SEEN; + +sub load_all { + my ($class, $r) = @_; + + foreach my $file (glob '*.cgi') { + my $name = _file_to_method($file); + $class->load_one($name, $file); + $r->any("/$file")->to("CGI#$name"); + } +} + +sub load_one { + my ($class, $name, $file) = @_; + my $package = __PACKAGE__ . "::$name", + my $inner_name = "_$name"; + my $content = read_text( catfile( bz_locations->{cgi_path}, $file ) ); + $content = "package $package; $content"; + untaint($content); + my %options = ( + package => $package, + file => $file, + line => 1, + no_defer => 1, + ); + die "Tried to load $file more than once" if $SEEN{$file}++; + my $inner = quote_sub $inner_name, $content, {}, \%options; + my $wrapper = sub { + my ($c) = @_; + my $stdin = $c->_STDIN; + my $stdout = ''; + local $C = $c; + local %ENV = $c->_ENV($file); + local *STDIN; ## no critic (local) + local $CGI::Compile::USE_REAL_EXIT = 0; + local $PROGRAM_NAME = $file; + open STDIN, '<', $stdin->path or die "STDIN @{[$stdin->path]}: $!" if -s $stdin->path; + tie *STDOUT, 'Bugzilla::Quantum::Stdout', controller => $c; ## no critic (tie) + try { + Bugzilla->init_page(); + $inner->(); + } + catch { + die $_ unless ref $_ eq 'ARRAY' && $_->[0] eq "EXIT\n"; + } + finally { + untie *STDOUT; + $c->finish; + Bugzilla->_cleanup; ## no critic (private) + CGI::initialize_globals(); + }; + }; + + no strict 'refs'; ## no critic (strict) + *{$name} = subname($name, $wrapper); + return 1; +} + +sub _ENV { + my ($c, $script_name) = @_; + 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); + } + + my $remote_user; + 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 : ''; + } + my $path_info = $c->param('PATH_INFO'); + my %captures = %{ $c->stash->{'mojo.captures'} // {} }; + foreach my $key (keys %captures) { + if ($key eq 'controller' || $key eq 'action' || $key eq 'PATH_INFO' || $key =~ /^REWRITE_/) { + delete $captures{$key}; + } + } + my $cgi_query = Mojo::Parameters->new(%captures); + $cgi_query->append($req->url->query); + my $prefix = $c->stash->{bmo_prefix} ? '/bmo/' : '/'; + + return ( + %ENV, + 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 => $cgi_query->to_string, + PATH_INFO => $path_info ? "/$path_info" : '', + REMOTE_ADDR => $tx->original_remote_address, + REMOTE_HOST => $tx->original_remote_address, + REMOTE_PORT => $tx->remote_port, + REMOTE_USER => $remote_user || '', + REQUEST_METHOD => $req->method, + SCRIPT_NAME => "$prefix$script_name", + SERVER_NAME => hostname, + SERVER_PORT => $tx->local_port, + SERVER_PROTOCOL => $req->is_secure ? 'HTTPS' : 'HTTP', # TODO: Version is missing + SERVER_SOFTWARE => __PACKAGE__, + ); +} + +sub _STDIN { + my $c = shift; + my $stdin; + + if ( $c->req->content->is_multipart ) { + $stdin = Mojo::Asset::File->new; + $stdin->add_chunk( $c->req->build_body ); + } + else { + $stdin = $c->req->content->asset; + } + + return $stdin if $stdin->isa('Mojo::Asset::File'); + return Mojo::Asset::File->new->add_chunk( $stdin->slurp ); +} + +sub _file_to_method { + my ($name) = @_; + $name =~ s/\./_/s; + $name =~ s/\W+/_/gs; + return $name; +} + + +1; diff --git a/Bugzilla/Quantum/Plugin/BasicAuth.pm b/Bugzilla/Quantum/Plugin/BasicAuth.pm new file mode 100644 index 000000000..bc79c89ef --- /dev/null +++ b/Bugzilla/Quantum/Plugin/BasicAuth.pm @@ -0,0 +1,40 @@ +# 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::Plugin::BasicAuth; +use 5.10.1; +use Mojo::Base qw(Mojolicious::Plugin); + +use Bugzilla::Logging; +use Carp; + +sub register { + my ( $self, $app, $conf ) = @_; + + $app->renderer->add_helper( + basic_auth => sub { + my ($c, $realm, $auth_user, $auth_pass) = @_; + my $req = $c->req; + my ($user, $password) = $req->url->to_abs->userinfo =~ /^([^:]+):(.*)/; + + unless ($realm && $auth_user && $auth_pass) { + croak 'basic_auth() called with missing parameters.'; + } + + unless ($user eq $auth_user && $password eq $auth_pass) { + WARN('username and password do not match'); + $c->res->headers->www_authenticate("Basic realm=\"$realm\""); + $c->res->code(401); + $c->rendered; + return 0; + } + + return 1; + } + ); +} + +1; diff --git a/Bugzilla/Quantum/Plugin/BlockIP.pm b/Bugzilla/Quantum/Plugin/BlockIP.pm new file mode 100644 index 000000000..fbfffad66 --- /dev/null +++ b/Bugzilla/Quantum/Plugin/BlockIP.pm @@ -0,0 +1,43 @@ +package Bugzilla::Quantum::Plugin::BlockIP; +use 5.10.1; +use Mojo::Base 'Mojolicious::Plugin'; + +use Bugzilla::Memcached; + +use constant BLOCK_TIMEOUT => 60*60; + +my $MEMCACHED = Bugzilla::Memcached->_new()->{memcached}; + +sub register { + my ( $self, $app, $conf ) = @_; + + $app->hook(before_routes => \&_before_routes); + $app->helper(block_ip => \&_block_ip); + $app->helper(unblock_ip => \&_unblock_ip); +} + +sub _block_ip { + my ($class, $ip) = @_; + $MEMCACHED->set("block_ip:$ip" => 1, BLOCK_TIMEOUT) if $MEMCACHED; +} + +sub _unblock_ip { + my ($class, $ip) = @_; + $MEMCACHED->delete("block_ip:$ip") if $MEMCACHED; +} + +sub _before_routes { + my ( $c ) = @_; + return if $c->stash->{'mojo.static'}; + + my $ip = $c->tx->remote_address; + if ($MEMCACHED && $MEMCACHED->get("block_ip:$ip")) { + $c->block_ip($ip); + $c->res->code(429); + $c->res->message("Too Many Requests"); + $c->res->body("Too Many Requests"); + $c->finish; + } +} + +1; diff --git a/Bugzilla/Quantum/Plugin/Glue.pm b/Bugzilla/Quantum/Plugin/Glue.pm new file mode 100644 index 000000000..4261d6729 --- /dev/null +++ b/Bugzilla/Quantum/Plugin/Glue.pm @@ -0,0 +1,114 @@ +# 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::Plugin::Glue; +use 5.10.1; +use Mojo::Base 'Mojolicious::Plugin'; + +use Try::Tiny; +use Bugzilla::Constants; +use Bugzilla::Quantum::Template; +use Bugzilla::Logging; +use Bugzilla::RNG (); +use JSON::MaybeXS qw(decode_json); + +sub register { + my ( $self, $app, $conf ) = @_; + + my %D; + if ($ENV{BUGZILLA_HTTPD_ARGS}) { + my $args = decode_json($ENV{BUGZILLA_HTTPD_ARGS}); + foreach my $arg (@$args) { + if ($arg =~ /^-D(\w+)$/) { + $D{$1} = 1; + } + else { + die "Unknown httpd arg: $arg"; + } + } + } + + # hypnotoad is weird and doesn't look for MOJO_LISTEN itself. + $app->config( + hypnotoad => { + listen => [ $ENV{MOJO_LISTEN} ], + }, + ); + + # Make sure each httpd child receives a different random seed (bug 476622). + # Bugzilla::RNG has one srand that needs to be called for + # every process, and Perl has another. (Various Perl modules still use + # the built-in rand(), even though we never use it in Bugzilla itself, + # so we need to srand() both of them.) + # Also, ping the dbh to force a reconnection. + Mojo::IOLoop->next_tick( + sub { + Bugzilla::RNG::srand(); + srand(); + eval { Bugzilla->dbh->ping }; + } + ); + + $app->hook( + before_dispatch => sub { + my ($c) = @_; + if ($D{HTTPD_IN_SUBDIR}) { + my $path = $c->req->url->path; + if ($path =~ s{^/bmo}{}s) { + $c->stash->{bmo_prefix} = 1; + $c->req->url->path($path); + } + } + Log::Log4perl::MDC->put(request_id => $c->req->request_id); + } + ); + + Bugzilla::Extension->load_all(); + if ($app->mode ne 'development') { + Bugzilla->preload_features(); + DEBUG("preloading templates"); + Bugzilla->preload_templates(); + DEBUG("done preloading templates"); + } + $app->secrets([Bugzilla->localconfig->{side_wide_secret}]); + + $app->renderer->add_handler( + 'bugzilla' => sub { + my ( $renderer, $c, $output, $options ) = @_; + my $vars = delete $c->stash->{vars}; + + # Helpers + my %helper; + foreach my $method ( grep {m/^\w+\z/} keys %{ $renderer->helpers } ) { + my $sub = $renderer->helpers->{$method}; + $helper{$method} = sub { $c->$sub(@_) }; + } + $vars->{helper} = \%helper; + + # The controller + $vars->{c} = $c; + my $name = $options->{template}; + unless ($name =~ /\./) { + $name = sprintf '%s.%s.tmpl', $options->{template}, $options->{format}; + } + my $template = Bugzilla->template; + $template->process( $name, $vars, $output ) + or die $template->error; + } + ); + + $app->log( + MojoX::Log::Log4perl::Tiny->new( + logger => Log::Log4perl->get_logger(ref $app) + ) + ); +} + + + + +1; diff --git a/Bugzilla/Quantum/Plugin/Hostage.pm b/Bugzilla/Quantum/Plugin/Hostage.pm new file mode 100644 index 000000000..42a05a910 --- /dev/null +++ b/Bugzilla/Quantum/Plugin/Hostage.pm @@ -0,0 +1,80 @@ +package Bugzilla::Quantum::Plugin::Hostage; +use 5.10.1; +use Mojo::Base 'Mojolicious::Plugin'; + +sub _attachment_root { + my ($base) = @_; + return undef unless $base; + return $base =~ m{^https?://(?:bug)?\%bugid\%\.([a-zA-Z\.-]+)} + ? $1 + : undef; +} + +sub _attachment_host_regex { + my ($base) = @_; + return undef unless $base; + my $val = $base; + $val =~ s{^https?://}{}s; + $val =~ s{/$}{}s; + my $regex = quotemeta $val; + $regex =~ s/\\\%bugid\\\%/\\d+/g; + return qr/^$regex$/s; +} + +sub register { + my ( $self, $app, $conf ) = @_; + + $app->hook(before_routes => \&_before_routes); +} + +sub _before_routes { + my ( $c ) = @_; + state $urlbase = Bugzilla->localconfig->{urlbase}; + state $urlbase_uri = URI->new($urlbase); + state $urlbase_host = $urlbase_uri->host; + state $urlbase_host_regex = qr/^bug(\d+)\.\Q$urlbase_host\E$/; + state $attachment_base = Bugzilla->localconfig->{attachment_base}; + state $attachment_root = _attachment_root($attachment_base); + state $attachment_host_regex = _attachment_host_regex($attachment_base); + + my $stash = $c->stash; + my $req = $c->req; + my $url = $req->url->to_abs; + + return if $stash->{'mojo.static'}; + + my $hostname = $url->host; + return if $hostname eq $urlbase_host; + + my $path = $url->path; + return if $path eq '/__lbheartbeat__'; + + if ($attachment_base && $hostname eq $attachment_root) { + $c->redirect_to($urlbase); + return; + } + elsif ($attachment_base && $hostname =~ $attachment_host_regex) { + if ($path =~ m{^/attachment\.cgi}s) { + return; + } else { + my $new_uri = $url->clone; + $new_uri->scheme($urlbase_uri->scheme); + $new_uri->host($urlbase_host); + $c->redirect_to($new_uri); + return; + } + } + elsif (my ($id) = $hostname =~ $urlbase_host_regex) { + my $new_uri = $urlbase_uri->clone; + $new_uri->path('/show_bug.cgi'); + $new_uri->query_form(id => $id); + $c->redirect_to($new_uri); + return; + } + else { + $c->redirect_to($urlbase); + return; + } +} + +1; \ No newline at end of file diff --git a/Bugzilla/Quantum/SES.pm b/Bugzilla/Quantum/SES.pm new file mode 100644 index 000000000..47c591fb5 --- /dev/null +++ b/Bugzilla/Quantum/SES.pm @@ -0,0 +1,203 @@ +package Bugzilla::Quantum::SES; +# 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. + +use 5.10.1; +use Mojo::Base qw( Mojolicious::Controller ); + +use Bugzilla::Constants qw(ERROR_MODE_DIE); +use Bugzilla::Logging; +use Bugzilla::Mailer qw(MessageToMTA); +use Bugzilla::User (); +use Bugzilla::Util qw(html_quote remote_ip); +use JSON::MaybeXS qw(decode_json); +use LWP::UserAgent (); +use Try::Tiny qw(catch try); + +sub main { + my ($self) = @_; + Bugzilla->error_mode(ERROR_MODE_DIE); + my $message = $self->_decode_json_wrapper( $self->req->body ) // return; + my $message_type = $self->req->headers->header('X-Amz-SNS-Message-Type') // '(missing)'; + + if ( $message_type eq 'SubscriptionConfirmation' ) { + $self->_confirm_subscription($message); + } + + elsif ( $message_type eq 'Notification' ) { + my $notification = $self->_decode_json_wrapper( $message->{Message} ) // return; + unless ( + # https://docs.aws.amazon.com/ses/latest/DeveloperGuide/event-publishing-retrieving-sns-contents.html + $self->_handle_notification( $notification, 'eventType' ) + + # https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html + || $self->_handle_notification( $notification, 'notificationType' ) + ) + { + WARN('Failed to find notification type'); + $self->_respond( 400 => 'Bad Request' ); + } + } + + else { + WARN("Unsupported message-type: $message_type"); + $self->_respond( 200 => 'OK' ); + } +} + +sub _confirm_subscription { + my ($self, $message) = @_; + + my $subscribe_url = $message->{SubscribeURL}; + if ( !$subscribe_url ) { + WARN('Bad SubscriptionConfirmation request: missing SubscribeURL'); + $self->_respond( 400 => 'Bad Request' ); + return; + } + + my $ua = ua(); + my $res = $ua->get( $message->{SubscribeURL} ); + if ( !$res->is_success ) { + WARN( 'Bad response from SubscribeURL: ' . $res->status_line ); + $self->_respond( 400 => 'Bad Request' ); + return; + } + + $self->_respond( 200 => 'OK' ); +} + +sub _handle_notification { + my ( $self, $notification, $type_field ) = @_; + + if ( !exists $notification->{$type_field} ) { + return 0; + } + my $type = $notification->{$type_field}; + + if ( $type eq 'Bounce' ) { + $self->_process_bounce($notification); + } + elsif ( $type eq 'Complaint' ) { + $self->_process_complaint($notification); + } + else { + WARN("Unsupported notification-type: $type"); + $self->_respond( 200 => 'OK' ); + } + return 1; +} + +sub _process_bounce { + my ($self, $notification) = @_; + + # disable each account that is bouncing + foreach my $recipient ( @{ $notification->{bounce}->{bouncedRecipients} } ) { + my $address = $recipient->{emailAddress}; + my $reason = sprintf '(%s) %s', $recipient->{action} // 'error', $recipient->{diagnosticCode} // 'unknown'; + + my $user = Bugzilla::User->new( { name => $address, cache => 1 } ); + if ($user) { + + # never auto-disable admin accounts + if ( $user->in_group('admin') ) { + Bugzilla->audit("ignoring bounce for admin <$address>: $reason"); + } + + else { + my $template = Bugzilla->template_inner(); + my $vars = { + mta => $notification->{bounce}->{reportingMTA} // 'unknown', + reason => $reason, + }; + my $disable_text; + $template->process( 'admin/users/bounce-disabled.txt.tmpl', $vars, \$disable_text ) + || die $template->error(); + + $user->set_disabledtext($disable_text); + $user->set_disable_mail(1); + $user->update(); + Bugzilla->audit( "bounce for <$address> disabled userid-" . $user->id . ": $reason" ); + } + } + + else { + Bugzilla->audit("bounce for <$address> has no user: $reason"); + } + } + + $self->_respond( 200 => 'OK' ); +} + +sub _process_complaint { + my ($self) = @_; + + # email notification to bugzilla admin + my ($notification) = @_; + my $template = Bugzilla->template_inner(); + my $json = JSON::MaybeXS->new( + pretty => 1, + utf8 => 1, + canonical => 1, + ); + + foreach my $recipient ( @{ $notification->{complaint}->{complainedRecipients} } ) { + my $reason = $notification->{complaint}->{complaintFeedbackType} // 'unknown'; + my $address = $recipient->{emailAddress}; + Bugzilla->audit("complaint for <$address> for '$reason'"); + my $vars = { + email => $address, + user => Bugzilla::User->new( { name => $address, cache => 1 } ), + reason => $reason, + notification => $json->encode($notification), + }; + my $message; + $template->process( 'email/ses-complaint.txt.tmpl', $vars, \$message ) + || die $template->error(); + MessageToMTA($message); + } + + $self->_respond( 200 => 'OK' ); +} + +sub _respond { + my ( $self, $code, $message ) = @_; + $self->render(text => "$message\n", status => $code); +} + +sub _decode_json_wrapper { + my ($self, $json) = @_; + my $result; + if ( !defined $json ) { + WARN( 'Missing JSON from ' . $self->tx->remote_address ); + $self->_respond( 400 => 'Bad Request' ); + return undef; + } + my $ok = try { + $result = decode_json($json); + } + catch { + WARN( 'Malformed JSON from ' . $self->tx->remote_address ); + $self->_respond( 400 => 'Bad Request' ); + return undef; + }; + return $ok ? $result : undef; +} + +sub ua { + my $ua = LWP::UserAgent->new(); + $ua->timeout(10); + $ua->protocols_allowed( [ 'http', 'https' ] ); + if ( my $proxy_url = Bugzilla->params->{'proxy_url'} ) { + $ua->proxy( [ 'http', 'https' ], $proxy_url ); + } + else { + $ua->env_proxy; + } + return $ua; +} + +1; \ No newline at end of file diff --git a/Bugzilla/Quantum/Static.pm b/Bugzilla/Quantum/Static.pm new file mode 100644 index 000000000..2bb54990e --- /dev/null +++ b/Bugzilla/Quantum/Static.pm @@ -0,0 +1,30 @@ +# 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::Static; +use Mojo::Base 'Mojolicious::Static'; +use Bugzilla::Constants qw(bz_locations); + +my $LEGACY_RE = qr{ + ^ (?:static/v[0-9]+\.[0-9]+/) ? + ( (?:extensions/[^/]+/web|(?:image|skin|j)s)/.+) + $ +}xs; + +sub file { + my ($self, $rel) = @_; + + if (my ($legacy_rel) = $rel =~ $LEGACY_RE) { + local $self->{paths} = [ bz_locations->{cgi_path} ]; + return $self->SUPER::file($legacy_rel); + } + else { + return $self->SUPER::file($rel); + } +} + +1; diff --git a/Bugzilla/Quantum/Stdout.pm b/Bugzilla/Quantum/Stdout.pm new file mode 100644 index 000000000..2cdba9160 --- /dev/null +++ b/Bugzilla/Quantum/Stdout.pm @@ -0,0 +1,59 @@ +# 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::Stdout; +use 5.10.1; +use Moo; + +use Bugzilla::Logging; +use Encode; + +has 'controller' => ( + is => 'ro', + required => 1, +); + +has '_encoding' => ( + is => 'rw', + default => '', +); + +sub TIEHANDLE { ## no critic (unpack) + my $class = shift; + + return $class->new(@_); +} + +sub PRINTF { ## no critic (unpack) + my $self = shift; + $self->PRINT(sprintf @_); +} + +sub PRINT { ## no critic (unpack) + my $self = shift; + my $c = $self->controller; + my $bytes = join '', @_; + return unless $bytes; + if ($self->_encoding) { + $bytes = encode($self->_encoding, $bytes); + } + $c->write($bytes); +} + +sub BINMODE { + my ($self, $mode) = @_; + if ($mode) { + if ($mode eq ':bytes' or $mode eq ':raw') { + $self->_encoding(''); + } + elsif ($mode eq ':utf8') { + $self->_encoding('utf8'); + } + } +} + +1; diff --git a/Bugzilla/Quantum/Template.pm b/Bugzilla/Quantum/Template.pm new file mode 100644 index 000000000..2442f1134 --- /dev/null +++ b/Bugzilla/Quantum/Template.pm @@ -0,0 +1,39 @@ +# 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::Template; +use 5.10.1; +use Moo; + +has 'controller' => ( + is => 'ro', + required => 1, +); + +has 'template' => ( + is => 'ro', + required => 1, + handles => ['error', 'get_format'], +); + +sub process { + my ($self, $file, $vars, $output) = @_; + + if (@_ < 4) { + $self->controller->stash->{vars} = $vars; + $self->controller->render(template => $file, handler => 'bugzilla'); + return 1; + } + elsif (@_ == 4) { + return $self->template->process($file, $vars, $output); + } + else { + die __PACKAGE__ . '->process() called with too many arguments'; + } +} + +1; \ No newline at end of file -- cgit v1.2.3-24-g4f1b From 482953b67c0c348c4fc8df77609bb6aaf6ceb326 Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Thu, 19 Jul 2018 11:22:00 -0400 Subject: fix lint errors --- Bugzilla/Quantum/CGI.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/CGI.pm b/Bugzilla/Quantum/CGI.pm index 85f14cf83..0e09d795e 100644 --- a/Bugzilla/Quantum/CGI.pm +++ b/Bugzilla/Quantum/CGI.pm @@ -90,12 +90,12 @@ sub _ENV { for my $name ( @{ $headers->names } ) { my $key = uc "http_$name"; - $key =~ s!\W!_!g; + $key =~ s/\W/_/g; $env_headers{$key} = $headers->header($name); } my $remote_user; - if ( my $userinfo = $c->req->url->to_abs->userinfo ) { + if ( my $userinfo = $req->url->to_abs->userinfo ) { $remote_user = $userinfo =~ /([^:]+)/ ? $1 : ''; } elsif ( my $authenticate = $headers->authorization ) { -- cgit v1.2.3-24-g4f1b From a46ca861f527d75fe28f784794207f50e8ec7f2b Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Thu, 19 Jul 2018 12:18:47 -0400 Subject: fix errors from group review --- Bugzilla/Quantum/CGI.pm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/CGI.pm b/Bugzilla/Quantum/CGI.pm index 0e09d795e..ba09dded6 100644 --- a/Bugzilla/Quantum/CGI.pm +++ b/Bugzilla/Quantum/CGI.pm @@ -52,7 +52,6 @@ sub load_one { my $wrapper = sub { my ($c) = @_; my $stdin = $c->_STDIN; - my $stdout = ''; local $C = $c; local %ENV = $c->_ENV($file); local *STDIN; ## no critic (local) @@ -102,7 +101,7 @@ sub _ENV { $remote_user = $authenticate =~ /Basic\s+(.*)/ ? b64_decode $1 : ''; $remote_user = $remote_user =~ /([^:]+)/ ? $1 : ''; } - my $path_info = $c->param('PATH_INFO'); + my $path_info = $c->stash->{'mojo.captures'}{'PATH_INFO'}; my %captures = %{ $c->stash->{'mojo.captures'} // {} }; foreach my $key (keys %captures) { if ($key eq 'controller' || $key eq 'action' || $key eq 'PATH_INFO' || $key =~ /^REWRITE_/) { -- cgit v1.2.3-24-g4f1b From e84956b1f37a7248ebc5d43bd64e6360c257ad0f Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Mon, 23 Jul 2018 11:16:47 -0400 Subject: some cleanups --- Bugzilla/Quantum/CGI.pm | 71 ++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 36 deletions(-) (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/CGI.pm b/Bugzilla/Quantum/CGI.pm index ba09dded6..ab092140c 100644 --- a/Bugzilla/Quantum/CGI.pm +++ b/Bugzilla/Quantum/CGI.pm @@ -25,40 +25,39 @@ our $C; my %SEEN; sub load_all { - my ($class, $r) = @_; + my ( $class, $r ) = @_; - foreach my $file (glob '*.cgi') { - my $name = _file_to_method($file); - $class->load_one($name, $file); + foreach my $file ( glob '*.cgi' ) { + my $name = _file_to_method($file); + $class->load_one( $name, $file ); $r->any("/$file")->to("CGI#$name"); } } sub load_one { - my ($class, $name, $file) = @_; - my $package = __PACKAGE__ . "::$name", - my $inner_name = "_$name"; - my $content = read_text( catfile( bz_locations->{cgi_path}, $file ) ); + my ( $class, $name, $file ) = @_; + my $package = __PACKAGE__ . "::$name", my $inner_name = "_$name"; + my $content = read_text( catfile( bz_locations->{cgi_path}, $file ) ); $content = "package $package; $content"; untaint($content); my %options = ( - package => $package, - file => $file, - line => 1, + package => $package, + file => $file, + line => 1, no_defer => 1, ); die "Tried to load $file more than once" if $SEEN{$file}++; my $inner = quote_sub $inner_name, $content, {}, \%options; my $wrapper = sub { my ($c) = @_; - my $stdin = $c->_STDIN; - local $C = $c; - local %ENV = $c->_ENV($file); - local *STDIN; ## no critic (local) + my $stdin = $c->_STDIN; + local $C = $c; + local %ENV = $c->_ENV($file); local $CGI::Compile::USE_REAL_EXIT = 0; - local $PROGRAM_NAME = $file; + local $PROGRAM_NAME = $file; + local *STDIN; ## no critic (local) open STDIN, '<', $stdin->path or die "STDIN @{[$stdin->path]}: $!" if -s $stdin->path; - tie *STDOUT, 'Bugzilla::Quantum::Stdout', controller => $c; ## no critic (tie) + tie *STDOUT, 'Bugzilla::Quantum::Stdout', controller => $c; ## no critic (tie) try { Bugzilla->init_page(); $inner->(); @@ -69,23 +68,24 @@ sub load_one { finally { untie *STDOUT; $c->finish; - Bugzilla->_cleanup; ## no critic (private) + Bugzilla->cleanup; CGI::initialize_globals(); }; }; - no strict 'refs'; ## no critic (strict) - *{$name} = subname($name, $wrapper); + no strict 'refs'; ## no critic (strict) + *{$name} = subname( $name, $wrapper ); return 1; } + sub _ENV { - my ($c, $script_name) = @_; - my $tx = $c->tx; - my $req = $tx->req; - my $headers = $req->headers; + my ( $c, $script_name ) = @_; + 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 => '' ); + my %env_headers = ( HTTP_COOKIE => '', HTTP_REFERER => '' ); for my $name ( @{ $headers->names } ) { my $key = uc "http_$name"; @@ -103,13 +103,13 @@ sub _ENV { } my $path_info = $c->stash->{'mojo.captures'}{'PATH_INFO'}; my %captures = %{ $c->stash->{'mojo.captures'} // {} }; - foreach my $key (keys %captures) { - if ($key eq 'controller' || $key eq 'action' || $key eq 'PATH_INFO' || $key =~ /^REWRITE_/) { + foreach my $key ( keys %captures ) { + if ( $key eq 'controller' || $key eq 'action' || $key eq 'PATH_INFO' || $key =~ /^REWRITE_/ ) { delete $captures{$key}; } } my $cgi_query = Mojo::Parameters->new(%captures); - $cgi_query->append($req->url->query); + $cgi_query->append( $req->url->query ); my $prefix = $c->stash->{bmo_prefix} ? '/bmo/' : '/'; return ( @@ -119,17 +119,17 @@ sub _ENV { GATEWAY_INTERFACE => 'CGI/1.1', HTTPS => $req->is_secure ? 'YES' : 'NO', %env_headers, - QUERY_STRING => $cgi_query->to_string, - PATH_INFO => $path_info ? "/$path_info" : '', - REMOTE_ADDR => $tx->original_remote_address, - REMOTE_HOST => $tx->original_remote_address, - REMOTE_PORT => $tx->remote_port, - REMOTE_USER => $remote_user || '', + QUERY_STRING => $cgi_query->to_string, + PATH_INFO => $path_info ? "/$path_info" : '', + REMOTE_ADDR => $tx->original_remote_address, + REMOTE_HOST => $tx->original_remote_address, + REMOTE_PORT => $tx->remote_port, + REMOTE_USER => $remote_user || '', REQUEST_METHOD => $req->method, SCRIPT_NAME => "$prefix$script_name", SERVER_NAME => hostname, SERVER_PORT => $tx->local_port, - SERVER_PROTOCOL => $req->is_secure ? 'HTTPS' : 'HTTP', # TODO: Version is missing + SERVER_PROTOCOL => $req->is_secure ? 'HTTPS' : 'HTTP', # TODO: Version is missing SERVER_SOFTWARE => __PACKAGE__, ); } @@ -157,5 +157,4 @@ sub _file_to_method { return $name; } - 1; -- cgit v1.2.3-24-g4f1b From 0108df4cc381df0b013addaed565595b8bb23299 Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Mon, 23 Jul 2018 11:20:47 -0400 Subject: more tidy --- Bugzilla/Quantum/Plugin/Glue.pm | 30 +++++++++++------------------- Bugzilla/Quantum/Static.pm | 4 ++-- Bugzilla/Quantum/Stdout.pm | 22 +++++++++++----------- Bugzilla/Quantum/Template.pm | 39 --------------------------------------- 4 files changed, 24 insertions(+), 71 deletions(-) delete mode 100644 Bugzilla/Quantum/Template.pm (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/Plugin/Glue.pm b/Bugzilla/Quantum/Plugin/Glue.pm index 4261d6729..f99026690 100644 --- a/Bugzilla/Quantum/Plugin/Glue.pm +++ b/Bugzilla/Quantum/Plugin/Glue.pm @@ -11,7 +11,6 @@ use Mojo::Base 'Mojolicious::Plugin'; use Try::Tiny; use Bugzilla::Constants; -use Bugzilla::Quantum::Template; use Bugzilla::Logging; use Bugzilla::RNG (); use JSON::MaybeXS qw(decode_json); @@ -20,10 +19,10 @@ sub register { my ( $self, $app, $conf ) = @_; my %D; - if ($ENV{BUGZILLA_HTTPD_ARGS}) { - my $args = decode_json($ENV{BUGZILLA_HTTPD_ARGS}); + if ( $ENV{BUGZILLA_HTTPD_ARGS} ) { + my $args = decode_json( $ENV{BUGZILLA_HTTPD_ARGS} ); foreach my $arg (@$args) { - if ($arg =~ /^-D(\w+)$/) { + if ( $arg =~ /^-D(\w+)$/ ) { $D{$1} = 1; } else { @@ -56,25 +55,25 @@ sub register { $app->hook( before_dispatch => sub { my ($c) = @_; - if ($D{HTTPD_IN_SUBDIR}) { + if ( $D{HTTPD_IN_SUBDIR} ) { my $path = $c->req->url->path; - if ($path =~ s{^/bmo}{}s) { + if ( $path =~ s{^/bmo}{}s ) { $c->stash->{bmo_prefix} = 1; $c->req->url->path($path); } } - Log::Log4perl::MDC->put(request_id => $c->req->request_id); + Log::Log4perl::MDC->put( request_id => $c->req->request_id ); } ); Bugzilla::Extension->load_all(); - if ($app->mode ne 'development') { + if ( $app->mode ne 'development' ) { Bugzilla->preload_features(); DEBUG("preloading templates"); Bugzilla->preload_templates(); DEBUG("done preloading templates"); } - $app->secrets([Bugzilla->localconfig->{side_wide_secret}]); + $app->secrets( [ Bugzilla->localconfig->{side_wide_secret} ] ); $app->renderer->add_handler( 'bugzilla' => sub { @@ -92,23 +91,16 @@ sub register { # The controller $vars->{c} = $c; my $name = $options->{template}; - unless ($name =~ /\./) { + unless ( $name =~ /\./ ) { $name = sprintf '%s.%s.tmpl', $options->{template}, $options->{format}; } my $template = Bugzilla->template; $template->process( $name, $vars, $output ) - or die $template->error; + or die $template->error; } ); - $app->log( - MojoX::Log::Log4perl::Tiny->new( - logger => Log::Log4perl->get_logger(ref $app) - ) - ); + $app->log( MojoX::Log::Log4perl::Tiny->new( logger => Log::Log4perl->get_logger( ref $app ) ) ); } - - - 1; diff --git a/Bugzilla/Quantum/Static.pm b/Bugzilla/Quantum/Static.pm index 2bb54990e..d687873ab 100644 --- a/Bugzilla/Quantum/Static.pm +++ b/Bugzilla/Quantum/Static.pm @@ -16,9 +16,9 @@ my $LEGACY_RE = qr{ }xs; sub file { - my ($self, $rel) = @_; + my ( $self, $rel ) = @_; - if (my ($legacy_rel) = $rel =~ $LEGACY_RE) { + if ( my ($legacy_rel) = $rel =~ $LEGACY_RE ) { local $self->{paths} = [ bz_locations->{cgi_path} ]; return $self->SUPER::file($legacy_rel); } diff --git a/Bugzilla/Quantum/Stdout.pm b/Bugzilla/Quantum/Stdout.pm index 2cdba9160..699ec164a 100644 --- a/Bugzilla/Quantum/Stdout.pm +++ b/Bugzilla/Quantum/Stdout.pm @@ -22,35 +22,35 @@ has '_encoding' => ( default => '', ); -sub TIEHANDLE { ## no critic (unpack) +sub TIEHANDLE { ## no critic (unpack) my $class = shift; return $class->new(@_); } -sub PRINTF { ## no critic (unpack) +sub PRINTF { ## no critic (unpack) my $self = shift; - $self->PRINT(sprintf @_); + $self->PRINT( sprintf @_ ); } -sub PRINT { ## no critic (unpack) - my $self = shift; - my $c = $self->controller; +sub PRINT { ## no critic (unpack) + my $self = shift; + my $c = $self->controller; my $bytes = join '', @_; return unless $bytes; - if ($self->_encoding) { - $bytes = encode($self->_encoding, $bytes); + if ( $self->_encoding ) { + $bytes = encode( $self->_encoding, $bytes ); } $c->write($bytes); } sub BINMODE { - my ($self, $mode) = @_; + my ( $self, $mode ) = @_; if ($mode) { - if ($mode eq ':bytes' or $mode eq ':raw') { + if ( $mode eq ':bytes' or $mode eq ':raw' ) { $self->_encoding(''); } - elsif ($mode eq ':utf8') { + elsif ( $mode eq ':utf8' ) { $self->_encoding('utf8'); } } diff --git a/Bugzilla/Quantum/Template.pm b/Bugzilla/Quantum/Template.pm deleted file mode 100644 index 2442f1134..000000000 --- a/Bugzilla/Quantum/Template.pm +++ /dev/null @@ -1,39 +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::Template; -use 5.10.1; -use Moo; - -has 'controller' => ( - is => 'ro', - required => 1, -); - -has 'template' => ( - is => 'ro', - required => 1, - handles => ['error', 'get_format'], -); - -sub process { - my ($self, $file, $vars, $output) = @_; - - if (@_ < 4) { - $self->controller->stash->{vars} = $vars; - $self->controller->render(template => $file, handler => 'bugzilla'); - return 1; - } - elsif (@_ == 4) { - return $self->template->process($file, $vars, $output); - } - else { - die __PACKAGE__ . '->process() called with too many arguments'; - } -} - -1; \ No newline at end of file -- cgit v1.2.3-24-g4f1b From 8d59839660e4aa848c32295c1851bb0180f90116 Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Mon, 23 Jul 2018 11:24:13 -0400 Subject: more tidy --- Bugzilla/Quantum/Plugin/BasicAuth.pm | 10 +++++----- Bugzilla/Quantum/Plugin/BlockIP.pm | 20 ++++++++++---------- Bugzilla/Quantum/Plugin/Hostage.pm | 29 +++++++++++++++-------------- 3 files changed, 30 insertions(+), 29 deletions(-) (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/Plugin/BasicAuth.pm b/Bugzilla/Quantum/Plugin/BasicAuth.pm index bc79c89ef..e17273404 100644 --- a/Bugzilla/Quantum/Plugin/BasicAuth.pm +++ b/Bugzilla/Quantum/Plugin/BasicAuth.pm @@ -16,15 +16,15 @@ sub register { $app->renderer->add_helper( basic_auth => sub { - my ($c, $realm, $auth_user, $auth_pass) = @_; + my ( $c, $realm, $auth_user, $auth_pass ) = @_; my $req = $c->req; - my ($user, $password) = $req->url->to_abs->userinfo =~ /^([^:]+):(.*)/; + my ( $user, $password ) = $req->url->to_abs->userinfo =~ /^([^:]+):(.*)/; - unless ($realm && $auth_user && $auth_pass) { + unless ( $realm && $auth_user && $auth_pass ) { croak 'basic_auth() called with missing parameters.'; } - unless ($user eq $auth_user && $password eq $auth_pass) { + unless ( $user eq $auth_user && $password eq $auth_pass ) { WARN('username and password do not match'); $c->res->headers->www_authenticate("Basic realm=\"$realm\""); $c->res->code(401); @@ -37,4 +37,4 @@ sub register { ); } -1; +1; \ No newline at end of file diff --git a/Bugzilla/Quantum/Plugin/BlockIP.pm b/Bugzilla/Quantum/Plugin/BlockIP.pm index fbfffad66..ebeb2a4aa 100644 --- a/Bugzilla/Quantum/Plugin/BlockIP.pm +++ b/Bugzilla/Quantum/Plugin/BlockIP.pm @@ -4,34 +4,34 @@ use Mojo::Base 'Mojolicious::Plugin'; use Bugzilla::Memcached; -use constant BLOCK_TIMEOUT => 60*60; +use constant BLOCK_TIMEOUT => 60 * 60; -my $MEMCACHED = Bugzilla::Memcached->_new()->{memcached}; +my $MEMCACHED = Bugzilla::Memcached->new()->{memcached}; sub register { my ( $self, $app, $conf ) = @_; - $app->hook(before_routes => \&_before_routes); - $app->helper(block_ip => \&_block_ip); - $app->helper(unblock_ip => \&_unblock_ip); + $app->hook( before_routes => \&_before_routes ); + $app->helper( block_ip => \&_block_ip ); + $app->helper( unblock_ip => \&_unblock_ip ); } sub _block_ip { - my ($class, $ip) = @_; - $MEMCACHED->set("block_ip:$ip" => 1, BLOCK_TIMEOUT) if $MEMCACHED; + my ( $class, $ip ) = @_; + $MEMCACHED->set( "block_ip:$ip" => 1, BLOCK_TIMEOUT ) if $MEMCACHED; } sub _unblock_ip { - my ($class, $ip) = @_; + my ( $class, $ip ) = @_; $MEMCACHED->delete("block_ip:$ip") if $MEMCACHED; } sub _before_routes { - my ( $c ) = @_; + my ($c) = @_; return if $c->stash->{'mojo.static'}; my $ip = $c->tx->remote_address; - if ($MEMCACHED && $MEMCACHED->get("block_ip:$ip")) { + if ( $MEMCACHED && $MEMCACHED->get("block_ip:$ip") ) { $c->block_ip($ip); $c->res->code(429); $c->res->message("Too Many Requests"); diff --git a/Bugzilla/Quantum/Plugin/Hostage.pm b/Bugzilla/Quantum/Plugin/Hostage.pm index 42a05a910..19c77995e 100644 --- a/Bugzilla/Quantum/Plugin/Hostage.pm +++ b/Bugzilla/Quantum/Plugin/Hostage.pm @@ -6,14 +6,14 @@ sub _attachment_root { my ($base) = @_; return undef unless $base; return $base =~ m{^https?://(?:bug)?\%bugid\%\.([a-zA-Z\.-]+)} - ? $1 - : undef; + ? $1 + : undef; } sub _attachment_host_regex { my ($base) = @_; return undef unless $base; - my $val = $base; + my $val = $base; $val =~ s{^https?://}{}s; $val =~ s{/$}{}s; my $regex = quotemeta $val; @@ -24,11 +24,11 @@ sub _attachment_host_regex { sub register { my ( $self, $app, $conf ) = @_; - $app->hook(before_routes => \&_before_routes); + $app->hook( before_routes => \&_before_routes ); } sub _before_routes { - my ( $c ) = @_; + my ($c) = @_; state $urlbase = Bugzilla->localconfig->{urlbase}; state $urlbase_uri = URI->new($urlbase); state $urlbase_host = $urlbase_uri->host; @@ -43,31 +43,32 @@ sub _before_routes { return if $stash->{'mojo.static'}; - my $hostname = $url->host; + my $hostname = $url->host; return if $hostname eq $urlbase_host; my $path = $url->path; return if $path eq '/__lbheartbeat__'; - if ($attachment_base && $hostname eq $attachment_root) { + if ( $attachment_base && $hostname eq $attachment_root ) { $c->redirect_to($urlbase); return; } - elsif ($attachment_base && $hostname =~ $attachment_host_regex) { - if ($path =~ m{^/attachment\.cgi}s) { + elsif ( $attachment_base && $hostname =~ $attachment_host_regex ) { + if ( $path =~ m{^/attachment\.cgi}s ) { return; - } else { + } + else { my $new_uri = $url->clone; - $new_uri->scheme($urlbase_uri->scheme); + $new_uri->scheme( $urlbase_uri->scheme ); $new_uri->host($urlbase_host); $c->redirect_to($new_uri); return; } } - elsif (my ($id) = $hostname =~ $urlbase_host_regex) { + elsif ( my ($id) = $hostname =~ $urlbase_host_regex ) { my $new_uri = $urlbase_uri->clone; $new_uri->path('/show_bug.cgi'); - $new_uri->query_form(id => $id); + $new_uri->query_form( id => $id ); $c->redirect_to($new_uri); return; } @@ -77,4 +78,4 @@ sub _before_routes { } } -1; \ No newline at end of file +1; -- cgit v1.2.3-24-g4f1b From 7361facceb4b2bf96a72ff0ab3a06f125a5ebe7e Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Mon, 23 Jul 2018 11:41:14 -0400 Subject: more tidy --- Bugzilla/Quantum/CGI.pm | 14 +++++++------- Bugzilla/Quantum/Plugin/BlockIP.pm | 4 ++-- Bugzilla/Quantum/Plugin/Glue.pm | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/CGI.pm b/Bugzilla/Quantum/CGI.pm index ab092140c..7585d888a 100644 --- a/Bugzilla/Quantum/CGI.pm +++ b/Bugzilla/Quantum/CGI.pm @@ -9,17 +9,17 @@ package Bugzilla::Quantum::CGI; use Mojo::Base 'Mojolicious::Controller'; use CGI::Compile; -use Bugzilla::Constants qw(bz_locations); -use Bugzilla::Quantum::Stdout; -use File::Slurper qw(read_text); -use File::Spec::Functions qw(catfile); -use Sub::Name; -use Sub::Quote 2.005000; use Try::Tiny; use Taint::Util qw(untaint); -use Socket qw(AF_INET inet_aton); use Sys::Hostname; +use Sub::Quote 2.005000; +use Sub::Name; +use Socket qw(AF_INET inet_aton); +use File::Spec::Functions qw(catfile); +use File::Slurper qw(read_text); use English qw(-no_match_vars); +use Bugzilla::Quantum::Stdout; +use Bugzilla::Constants qw(bz_locations); our $C; my %SEEN; diff --git a/Bugzilla/Quantum/Plugin/BlockIP.pm b/Bugzilla/Quantum/Plugin/BlockIP.pm index ebeb2a4aa..058ecbf64 100644 --- a/Bugzilla/Quantum/Plugin/BlockIP.pm +++ b/Bugzilla/Quantum/Plugin/BlockIP.pm @@ -34,8 +34,8 @@ sub _before_routes { if ( $MEMCACHED && $MEMCACHED->get("block_ip:$ip") ) { $c->block_ip($ip); $c->res->code(429); - $c->res->message("Too Many Requests"); - $c->res->body("Too Many Requests"); + $c->res->message('Too Many Requests'); + $c->res->body('Too Many Requests'); $c->finish; } } diff --git a/Bugzilla/Quantum/Plugin/Glue.pm b/Bugzilla/Quantum/Plugin/Glue.pm index f99026690..02514a0f8 100644 --- a/Bugzilla/Quantum/Plugin/Glue.pm +++ b/Bugzilla/Quantum/Plugin/Glue.pm @@ -48,7 +48,7 @@ sub register { sub { Bugzilla::RNG::srand(); srand(); - eval { Bugzilla->dbh->ping }; + try { Bugzilla->dbh->ping }; } ); @@ -69,9 +69,9 @@ sub register { Bugzilla::Extension->load_all(); if ( $app->mode ne 'development' ) { Bugzilla->preload_features(); - DEBUG("preloading templates"); + DEBUG('preloading templates'); Bugzilla->preload_templates(); - DEBUG("done preloading templates"); + DEBUG('done preloading templates'); } $app->secrets( [ Bugzilla->localconfig->{side_wide_secret} ] ); -- cgit v1.2.3-24-g4f1b From 2112e905d869d7e7d204eca5c1aeca2a4762775b Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Tue, 31 Jul 2018 17:12:20 -0400 Subject: hypnotoad should always expect a proxy --- Bugzilla/Quantum/Plugin/Glue.pm | 1 + 1 file changed, 1 insertion(+) (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/Plugin/Glue.pm b/Bugzilla/Quantum/Plugin/Glue.pm index 02514a0f8..ea21429bd 100644 --- a/Bugzilla/Quantum/Plugin/Glue.pm +++ b/Bugzilla/Quantum/Plugin/Glue.pm @@ -34,6 +34,7 @@ sub register { # hypnotoad is weird and doesn't look for MOJO_LISTEN itself. $app->config( hypnotoad => { + proxy => 1, listen => [ $ENV{MOJO_LISTEN} ], }, ); -- cgit v1.2.3-24-g4f1b From f9088d8cfaccf32674909db948be7d1400993acd Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Tue, 31 Jul 2018 21:37:33 -0400 Subject: add version --- Bugzilla/Quantum/Stdout.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/Stdout.pm b/Bugzilla/Quantum/Stdout.pm index 699ec164a..be7b546ea 100644 --- a/Bugzilla/Quantum/Stdout.pm +++ b/Bugzilla/Quantum/Stdout.pm @@ -41,7 +41,7 @@ sub PRINT { ## no critic (unpack) if ( $self->_encoding ) { $bytes = encode( $self->_encoding, $bytes ); } - $c->write($bytes); + $c->write($bytes.$\); } sub BINMODE { -- cgit v1.2.3-24-g4f1b From 8dda66ee78df54d38d86c7e7ed0c8695fec78e40 Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Tue, 31 Jul 2018 23:49:38 -0400 Subject: add more debugging but also probably fix redirect problem --- Bugzilla/Quantum/CGI.pm | 2 +- Bugzilla/Quantum/Plugin/Hostage.pm | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/CGI.pm b/Bugzilla/Quantum/CGI.pm index 7585d888a..0a74f1ee5 100644 --- a/Bugzilla/Quantum/CGI.pm +++ b/Bugzilla/Quantum/CGI.pm @@ -117,7 +117,7 @@ sub _ENV { CONTENT_LENGTH => $content_length || 0, CONTENT_TYPE => $headers->content_type || '', GATEWAY_INTERFACE => 'CGI/1.1', - HTTPS => $req->is_secure ? 'YES' : 'NO', + HTTPS => $req->is_secure ? 'on' : 'off', %env_headers, QUERY_STRING => $cgi_query->to_string, PATH_INFO => $path_info ? "/$path_info" : '', diff --git a/Bugzilla/Quantum/Plugin/Hostage.pm b/Bugzilla/Quantum/Plugin/Hostage.pm index 19c77995e..cbde7b5ee 100644 --- a/Bugzilla/Quantum/Plugin/Hostage.pm +++ b/Bugzilla/Quantum/Plugin/Hostage.pm @@ -1,6 +1,7 @@ package Bugzilla::Quantum::Plugin::Hostage; use 5.10.1; use Mojo::Base 'Mojolicious::Plugin'; +use Bugzilla::Logging; sub _attachment_root { my ($base) = @_; @@ -50,6 +51,7 @@ sub _before_routes { return if $path eq '/__lbheartbeat__'; if ( $attachment_base && $hostname eq $attachment_root ) { + DEBUG("redirecting to $urlbase because $hostname is $attachment_root"); $c->redirect_to($urlbase); return; } @@ -61,6 +63,7 @@ sub _before_routes { my $new_uri = $url->clone; $new_uri->scheme( $urlbase_uri->scheme ); $new_uri->host($urlbase_host); + DEBUG("redirecting to $new_uri because $hostname matches attachment regex"); $c->redirect_to($new_uri); return; } @@ -69,10 +72,12 @@ sub _before_routes { my $new_uri = $urlbase_uri->clone; $new_uri->path('/show_bug.cgi'); $new_uri->query_form( id => $id ); + DEBUG("redirecting to $new_uri because $hostname includes bug id"); $c->redirect_to($new_uri); return; } else { + DEBUG("redirecting to $urlbase because $hostname doesn't make sense"); $c->redirect_to($urlbase); return; } -- cgit v1.2.3-24-g4f1b From ef2ec2c8682d51a9a4d21c4f431ce0f9f1ae0d88 Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Tue, 31 Jul 2018 23:49:38 -0400 Subject: Fix a module loading problem --- Bugzilla/Quantum/Plugin/Glue.pm | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/Plugin/Glue.pm b/Bugzilla/Quantum/Plugin/Glue.pm index ea21429bd..ded4daf15 100644 --- a/Bugzilla/Quantum/Plugin/Glue.pm +++ b/Bugzilla/Quantum/Plugin/Glue.pm @@ -67,13 +67,7 @@ sub register { } ); - Bugzilla::Extension->load_all(); - if ( $app->mode ne 'development' ) { - Bugzilla->preload_features(); - DEBUG('preloading templates'); - Bugzilla->preload_templates(); - DEBUG('done preloading templates'); - } + $app->secrets( [ Bugzilla->localconfig->{side_wide_secret} ] ); $app->renderer->add_handler( -- cgit v1.2.3-24-g4f1b From 96e529c4357f7f7832465b71f42994854a174cdd Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Wed, 8 Aug 2018 20:05:13 -0400 Subject: fix glaring error --- Bugzilla/Quantum/SES.pm | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/SES.pm b/Bugzilla/Quantum/SES.pm index 47c591fb5..26df7a3eb 100644 --- a/Bugzilla/Quantum/SES.pm +++ b/Bugzilla/Quantum/SES.pm @@ -133,10 +133,7 @@ sub _process_bounce { } sub _process_complaint { - my ($self) = @_; - - # email notification to bugzilla admin - my ($notification) = @_; + my ($self, $notification) = @_; my $template = Bugzilla->template_inner(); my $json = JSON::MaybeXS->new( pretty => 1, @@ -200,4 +197,4 @@ sub ua { return $ua; } -1; \ No newline at end of file +1; -- cgit v1.2.3-24-g4f1b From 59fe9f7c0e56abd084c711455d5639d163312e52 Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Wed, 8 Aug 2018 22:29:23 -0400 Subject: add more testing --- Bugzilla/Quantum/SES.pm | 58 +++++++++++++++++++++++++++++++++++++++++++--- Bugzilla/Quantum/Stdout.pm | 3 ++- 2 files changed, 57 insertions(+), 4 deletions(-) (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/SES.pm b/Bugzilla/Quantum/SES.pm index 26df7a3eb..119769b32 100644 --- a/Bugzilla/Quantum/SES.pm +++ b/Bugzilla/Quantum/SES.pm @@ -18,7 +18,24 @@ use JSON::MaybeXS qw(decode_json); use LWP::UserAgent (); use Try::Tiny qw(catch try); +use Types::Standard qw( :all ); +use Type::Utils; +use Type::Params qw( compile ); + +my $Invocant = class_type { class => __PACKAGE__ }; + sub main { + my ($self) = @_; + try { + $self->_main; + } + catch { + FATAL($_); + die $_; + }; +} + +sub _main { my ($self) = @_; Bugzilla->error_mode(ERROR_MODE_DIE); my $message = $self->_decode_json_wrapper( $self->req->body ) // return; @@ -70,8 +87,17 @@ sub _confirm_subscription { $self->_respond( 200 => 'OK' ); } +my $NotificationType = Enum [qw( Bounce Complaint )]; +my $TypeField = Enum [qw(eventType notificationType)]; +my $Notification = Dict [ + eventType => Optional [$NotificationType], + notificationType => Optional [$NotificationType], + slurpy Any, +]; + sub _handle_notification { - my ( $self, $notification, $type_field ) = @_; + state $check = compile($Invocant, $Notification, $TypeField ); + my ( $self, $notification, $type_field ) = $check->(@_); if ( !exists $notification->{$type_field} ) { return 0; @@ -91,8 +117,23 @@ sub _handle_notification { return 1; } +my $BouncedRecipients = ArrayRef[ + Dict[ + emailAddress => Str, + action => Str, + diagnosticCode => Int, + slurpy Any, + ], +]; +my $BounceNotification = Dict[ + bounce => Dict[ + bouncedRecipients => $BouncedRecipients, + reportingMTA => Str, + ], +]; sub _process_bounce { - my ($self, $notification) = @_; + state $check = compile($Invocant, $BounceNotification); + my ($self, $notification) = $check->(@_); # disable each account that is bouncing foreach my $recipient ( @{ $notification->{bounce}->{bouncedRecipients} } ) { @@ -132,8 +173,19 @@ sub _process_bounce { $self->_respond( 200 => 'OK' ); } +my $ComplainedRecipients = ArrayRef[Dict[ emailAddress => Str, slurpy Any ]]; +my $ComplaintNotification = Dict[ + complaint => Dict [ + complainedRecipients => $ComplainedRecipients, + complaintFeedbackType => Str, + slurpy Any, + ], + slurpy Any, +]; + sub _process_complaint { - my ($self, $notification) = @_; + state $check = compile($Invocant, $ComplaintNotification); + my ($self, $notification) = $check->(@_); my $template = Bugzilla->template_inner(); my $json = JSON::MaybeXS->new( pretty => 1, diff --git a/Bugzilla/Quantum/Stdout.pm b/Bugzilla/Quantum/Stdout.pm index be7b546ea..9cf19992c 100644 --- a/Bugzilla/Quantum/Stdout.pm +++ b/Bugzilla/Quantum/Stdout.pm @@ -11,6 +11,7 @@ use Moo; use Bugzilla::Logging; use Encode; +use English qw(-no_match_vars); has 'controller' => ( is => 'ro', @@ -41,7 +42,7 @@ sub PRINT { ## no critic (unpack) if ( $self->_encoding ) { $bytes = encode( $self->_encoding, $bytes ); } - $c->write($bytes.$\); + $c->write($bytes . ( $OUTPUT_RECORD_SEPARATOR // '' ) ); } sub BINMODE { -- cgit v1.2.3-24-g4f1b From bea9c36dd3209ae1126a48ed1ed5d6023579fcf5 Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Wed, 8 Aug 2018 22:30:23 -0400 Subject: better FATAL error --- Bugzilla/Quantum/SES.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/SES.pm b/Bugzilla/Quantum/SES.pm index 119769b32..2a1c65802 100644 --- a/Bugzilla/Quantum/SES.pm +++ b/Bugzilla/Quantum/SES.pm @@ -30,7 +30,7 @@ sub main { $self->_main; } catch { - FATAL($_); + FATAL("Error in SES Handler: ", $_); die $_; }; } -- cgit v1.2.3-24-g4f1b From f2f8c5e6532db45adab694846237992dc6b498e8 Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Wed, 8 Aug 2018 22:33:57 -0400 Subject: diagnostic code is a string --- Bugzilla/Quantum/SES.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/SES.pm b/Bugzilla/Quantum/SES.pm index 2a1c65802..4badbc247 100644 --- a/Bugzilla/Quantum/SES.pm +++ b/Bugzilla/Quantum/SES.pm @@ -121,7 +121,7 @@ my $BouncedRecipients = ArrayRef[ Dict[ emailAddress => Str, action => Str, - diagnosticCode => Int, + diagnosticCode => Str, slurpy Any, ], ]; -- cgit v1.2.3-24-g4f1b From 50d22b447383e9ac2a88dde5a61cb4eeaf83236f Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Wed, 8 Aug 2018 22:36:24 -0400 Subject: one more slurpy type --- Bugzilla/Quantum/SES.pm | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/SES.pm b/Bugzilla/Quantum/SES.pm index 4badbc247..824ce58d3 100644 --- a/Bugzilla/Quantum/SES.pm +++ b/Bugzilla/Quantum/SES.pm @@ -125,12 +125,16 @@ my $BouncedRecipients = ArrayRef[ slurpy Any, ], ]; -my $BounceNotification = Dict[ - bounce => Dict[ +my $BounceNotification = Dict [ + bounce => Dict [ bouncedRecipients => $BouncedRecipients, - reportingMTA => Str, + reportingMTA => Str, + bounceSubType => Str, + bounceType => Str, + slurpy Any, ], ]; + sub _process_bounce { state $check = compile($Invocant, $BounceNotification); my ($self, $notification) = $check->(@_); -- cgit v1.2.3-24-g4f1b From e90495d2aaee38547c06ccac1235ff1b6e4cdc82 Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Wed, 8 Aug 2018 22:38:30 -0400 Subject: once more --- Bugzilla/Quantum/SES.pm | 1 + 1 file changed, 1 insertion(+) (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/SES.pm b/Bugzilla/Quantum/SES.pm index 824ce58d3..e447b036a 100644 --- a/Bugzilla/Quantum/SES.pm +++ b/Bugzilla/Quantum/SES.pm @@ -133,6 +133,7 @@ my $BounceNotification = Dict [ bounceType => Str, slurpy Any, ], + slurpy Any, ]; sub _process_bounce { -- cgit v1.2.3-24-g4f1b From 74520b1b65b7dd7fded658033d19db55fa77f319 Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Wed, 8 Aug 2018 22:46:07 -0400 Subject: more type checking --- Bugzilla/Quantum/SES.pm | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/SES.pm b/Bugzilla/Quantum/SES.pm index e447b036a..03916075d 100644 --- a/Bugzilla/Quantum/SES.pm +++ b/Bugzilla/Quantum/SES.pm @@ -31,7 +31,7 @@ sub main { } catch { FATAL("Error in SES Handler: ", $_); - die $_; + $self->_respond( 400 => 'Bad Request' ); }; } @@ -67,7 +67,8 @@ sub _main { } sub _confirm_subscription { - my ($self, $message) = @_; + state $check = compile($Invocant, Dict[SubscribeURL => Str, slurpy Any]); + my ($self, $message) = $check->(@_); my $subscribe_url = $message->{SubscribeURL}; if ( !$subscribe_url ) { @@ -223,13 +224,9 @@ sub _respond { } sub _decode_json_wrapper { - my ($self, $json) = @_; + state $check = compile($Invocant, Str); + my ($self, $json) = $check->(@_); my $result; - if ( !defined $json ) { - WARN( 'Missing JSON from ' . $self->tx->remote_address ); - $self->_respond( 400 => 'Bad Request' ); - return undef; - } my $ok = try { $result = decode_json($json); } -- cgit v1.2.3-24-g4f1b From d57aefa118802606ea7cc424aaa62173be9eec41 Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Wed, 22 Aug 2018 10:33:25 -0400 Subject: add graphs to the path --- Bugzilla/Quantum/Static.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Bugzilla/Quantum') diff --git a/Bugzilla/Quantum/Static.pm b/Bugzilla/Quantum/Static.pm index d687873ab..c01f062a4 100644 --- a/Bugzilla/Quantum/Static.pm +++ b/Bugzilla/Quantum/Static.pm @@ -11,7 +11,7 @@ use Bugzilla::Constants qw(bz_locations); my $LEGACY_RE = qr{ ^ (?:static/v[0-9]+\.[0-9]+/) ? - ( (?:extensions/[^/]+/web|(?:image|skin|j)s)/.+) + ( (?:extensions/[^/]+/web|(?:image|graph|skin|j)s)/.+) $ }xs; -- cgit v1.2.3-24-g4f1b