summaryrefslogtreecommitdiff
blob: dda7a46f7446ccad8786efcdccc578ba79e66ac7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/usr/bin/perl -T
# 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::ModPerl;

use 5.10.1;
use strict;
use warnings;

# This sets up our libpath without having to specify it in the mod_perl
# configuration.
use File::Basename;
use lib dirname(__FILE__);
use Bugzilla::Constants ();
use lib Bugzilla::Constants::bz_locations()->{'ext_libpath'};

# If you have an Apache2::Status handler in your Apache configuration,
# you need to load Apache2::Status *here*, so that any later-loaded modules
# can report information to Apache2::Status.
#use Apache2::Status ();

# We don't want to import anything into the global scope during
# startup, so we always specify () after using any module in this
# file.

use Apache2::Log ();
use Apache2::ServerUtil;
use ModPerl::RegistryLoader ();
use File::Basename          ();
use DateTime                ();

# This loads most of our modules.
use Bugzilla ();

# Loading Bugzilla.pm doesn't load this, though, and we want it preloaded.
use Bugzilla::BugMail               ();
use Bugzilla::CGI                   ();
use Bugzilla::Extension             ();
use Bugzilla::Install::Requirements ();
use Bugzilla::Util                  ();
use Bugzilla::RNG                   ();
use Bugzilla::ModPerl               ();

## REDHAT EXTENSION BEGIN 1764397
use Carp ();
$Carp::MaxArgNums = -1;
$SIG{__WARN__} = \&Carp::cluck;
$SIG{__DIE__}  = \&Carp::confess;
## REDHAT EXTENSION END 1764397

# Make warnings go to the virtual host's log and not the main
# server log.
BEGIN { *CORE::GLOBAL::warn = \&Apache2::ServerRec::warn; }

# Pre-compile the CGI.pm methods that we're going to use.
Bugzilla::CGI->compile(qw(:cgi :push));

use Apache2::SizeLimit;

# This means that every httpd child will die after processing
# a CGI if it is taking up more than 45MB of RAM all by itself,
# not counting RAM it is sharing with the other httpd processes.

## REDHAT EXTENSION 1009195
# See RT 215521 for why we increased it from 45MB to 250MB
# And see BMO 979727 for why it was changed to 700MB
Apache2::SizeLimit->set_max_unshared_size(2_000_000);

my $cgi_path = Bugzilla::Constants::bz_locations()->{'cgi_path'};

# Set up the configuration for the web server
my $server = Apache2::ServerUtil->server;
my $conf   = Bugzilla::ModPerl->apache_config($cgi_path);
$server->add_config([grep { length $_ } split("\n", $conf)]);

# Pre-load all extensions
$Bugzilla::extension_packages = Bugzilla::Extension->load_all();

# Force instantiation of template so Bugzilla::Template::PreloadProvider can do its magic.
Bugzilla->template;

# Have ModPerl::RegistryLoader pre-compile all CGI scripts.
my $rl = new ModPerl::RegistryLoader();

# If we try to do this in "new" it fails because it looks for a
# Bugzilla/ModPerl/ResponseHandler.pm
$rl->{package} = 'Bugzilla::ModPerl::ResponseHandler';
my $feature_files = Bugzilla::Install::Requirements::map_files_to_features();

# Prevent "use lib" from doing anything when the .cgi files are compiled.
# This is important to prevent the current directory from getting into
# @INC and messing things up. (See bug 630750.)
no warnings 'redefine';
local *lib::import = sub { };
use warnings;

foreach my $file (glob "$cgi_path/*.cgi") {
  my $base_filename = File::Basename::basename($file);
  if (my $feature = $feature_files->{$base_filename}) {
    next if !Bugzilla->feature($feature);
  }
  Bugzilla::Util::trick_taint($file);
  $rl->handler($file, $file);
}

package Bugzilla::ModPerl::ResponseHandler;

use 5.10.1;
use strict;
use warnings;

use parent qw(ModPerl::Registry);
use Bugzilla;
use Bugzilla::Constants qw(USAGE_MODE_REST);
use Bugzilla::Util;
use Time::HiRes;

sub handler : method {
  my $class = shift;

  # $0 is broken under mod_perl before 2.0.2, so we have to set it
  # here explicitly or init_page's shutdownhtml code won't work right.
  $0 = $ENV{'SCRIPT_FILENAME'};

  # Prevent "use lib" from modifying @INC in the case where a .cgi file
  # is being automatically recompiled by mod_perl when Apache is
  # running. (This happens if a file changes while Apache is already
  # running.)
  no warnings 'redefine';
  local *lib::import = sub { };
  use warnings;

  Bugzilla::init_page();
  my $start  = Time::HiRes::time();
  my $result = $class->SUPER::handler(@_);

  # If this isn't set then CGI must have died!
  if (Bugzilla->request_cache->{cgi}) {
    Bugzilla->logger->info("[request_time] "
        . redact(Bugzilla->cgi->request_uri)
        . " took "
        . (Time::HiRes::time() - $start)
        . " seconds to execute");
  }
  else {
    Bugzilla->logger->info("[request_time] "
        . "CGI DIED! It took "
        . (Time::HiRes::time() - $start)
        . " seconds to execute");

    return $result;
  }

  # When returning data from the REST api we must only return 200 or 304,
  # which tells Apache not to append its error html documents to the
  # response.
  ## RED HAT EXTENSION START 1597096 1611065
  # But we do need the real errors to return errors
  if (Bugzilla->usage_mode == USAGE_MODE_REST) {
    if ($result >= 201 && $result < 204) {
      return Apache2::Const::OK;
    }
    elsif ($result >= 300 && $result < 304) {
      return Apache2::Const::OK;
    }
  }

  if (Bugzilla->usage_mode == USAGE_MODE_REST) {

    # handle Jira being a bad actor
    my $not_jira = Bugzilla->cgi->request_uri !~ m{/applinks/};
    return $not_jira && $result != 304 ? Apache2::Const::OK : $result;
  }

  return $result;
  ## RED HAT EXTENSION END 1597096 1611065
}


package Bugzilla::ModPerl::CleanupHandler;

use 5.10.1;
use strict;
use warnings;

use Apache2::Const -compile => qw(OK);

sub handler {
  my $r = shift;

  Bugzilla::_cleanup();

  # Sometimes mod_perl doesn't properly call DESTROY on all
  # the objects in pnotes()
  foreach my $key (keys %{$r->pnotes}) {
    delete $r->pnotes->{$key};
  }

  return Apache2::Const::OK;
}

1;