~ubuntu-branches/ubuntu/edgy/bugzilla/edgy

« back to all changes in this revision

Viewing changes to post_bug.cgi

  • Committer: Bazaar Package Importer
  • Author(s): Alexis Sukrieh
  • Date: 2005-10-03 16:51:01 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051003165101-38n0y5qofd68vole
Tags: 2.18.4-1
* New upstream minor release
  + Fixed a security issue: It was possible to bypass the "user
    visibility groups" restrictions if user-matching was turned on
    in "substring" mode.
  + Fixed a security issue: config.cgi exposed information to users who
    weren't logged in, even when "requirelogin" was turned on in Bugzilla.
  (closes: #331206)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bonsaitools/bin/perl -wT
 
1
#!/usr/bin/perl -wT
2
2
# -*- Mode: perl; indent-tabs-mode: nil -*-
3
3
#
4
4
# The contents of this file are subject to the Mozilla Public
23
23
#                 Joe Robins <jmrobins@tgix.com>
24
24
#                 Gervase Markham <gerv@gerv.net>
25
25
 
26
 
use diagnostics;
27
26
use strict;
28
 
use lib '/usr/share/bugzilla/lib';
 
27
use lib qw(.);
29
28
 
 
29
use Bugzilla;
 
30
use Bugzilla::Constants;
30
31
require "CGI.pl";
31
 
require "bug_form.pl";
 
32
 
 
33
use Bugzilla::Bug;
 
34
 
 
35
use Bugzilla::User;
32
36
 
33
37
# Shut up misguided -w warnings about "used only once". For some reason,
34
38
# "use vars" chokes on me when I try it here.
35
39
sub sillyness {
36
40
    my $zz;
37
41
    $zz = $::buffer;
38
 
    $zz = $::usergroupset;
39
42
    $zz = %::COOKIE;
40
43
    $zz = %::components;
41
44
    $zz = %::versions;
50
53
# Use global template variables.
51
54
use vars qw($vars $template);
52
55
 
53
 
ConnectToDatabase();
54
 
confirm_login();
55
 
 
 
56
my $user = Bugzilla->login(LOGIN_REQUIRED);
 
57
 
 
58
my $cgi = Bugzilla->cgi;
 
59
 
 
60
# do a match on the fields if applicable
 
61
 
 
62
&Bugzilla::User::match_field ({
 
63
    'cc'            => { 'type' => 'multi'  },
 
64
    'assigned_to'   => { 'type' => 'single' },
 
65
});
56
66
 
57
67
# The format of the initial comment can be structured by adding fields to the
58
68
# enter_bug template and then referencing them in the comment template.
60
70
 
61
71
$vars->{'form'} = \%::FORM;
62
72
 
63
 
# We can't use ValidateOutputFormat here because it defaults to HTML.
64
 
my $template_name = "bug/create/comment";
65
 
$template_name .= ($::FORM{'format'} ? "-$::FORM{'format'}" : "");
 
73
my $format = GetFormat("bug/create/comment", $::FORM{'format'}, "txt");
66
74
 
67
 
$template->process("$template_name.txt.tmpl", $vars, \$comment)
 
75
$template->process($format->{'template'}, $vars, \$comment)
68
76
  || ThrowTemplateError($template->error());
69
77
 
70
78
ValidateComment($comment);
71
79
 
 
80
# Check that the product exists and that the user
 
81
# is allowed to enter bugs into this product.
72
82
my $product = $::FORM{'product'};
 
83
CanEnterProductOrWarn($product);
 
84
 
 
85
my $product_id = get_product_id($product);
73
86
 
74
87
# Set cookies
75
88
my $cookiepath = Param("cookiepath");
76
89
if (exists $::FORM{'product'}) {
77
 
    if (exists $::FORM{'version'}) {           
78
 
        print "Set-Cookie: VERSION-$product=$::FORM{'version'} ; " .
79
 
              "path=$cookiepath ; expires=Sat, 30-Jun-2029 00:00:00 GMT\n"; 
 
90
    if (exists $::FORM{'version'}) {
 
91
        $cgi->send_cookie(-name => "VERSION-$product",
 
92
                          -value => $cgi->param('version'),
 
93
                          -expires => "Fri, 01-Jan-2038 00:00:00 GMT");
80
94
    }
81
95
}
82
96
 
83
97
if (defined $::FORM{'maketemplate'}) {
84
98
    $vars->{'url'} = $::buffer;
85
99
    
86
 
    print "Content-type: text/html\n\n";
 
100
    print $cgi->header();
87
101
    $template->process("bug/create/make-template.html.tmpl", $vars)
88
102
      || ThrowTemplateError($template->error());
89
103
    exit;
92
106
umask 0;
93
107
 
94
108
# Some sanity checking
95
 
if(Param("usebuggroupsentry") && GroupExists($product)) {
96
 
    if(!UserInGroup($product)) {
97
 
        DisplayError("Sorry; you do not have the permissions necessary to enter
98
 
                      a bug against this product.", "Permission Denied");
99
 
        exit;
100
 
    }
101
 
}
102
 
 
103
 
if (!$::FORM{'component'}) {
104
 
    DisplayError("You must choose a component that corresponds to this bug.
105
 
                  If necessary, just guess.");
106
 
    exit;                  
107
 
}
 
109
my $component_id = get_component_id($product_id, $::FORM{component});
 
110
$component_id || ThrowUserError("require_component");
108
111
 
109
112
if (!defined $::FORM{'short_desc'} || trim($::FORM{'short_desc'}) eq "") {
110
 
    DisplayError("You must enter a summary for this bug.");
111
 
    exit;
 
113
    ThrowUserError("require_summary");
 
114
}
 
115
 
 
116
# Check that if required a description has been provided
 
117
# This has to go somewhere after 'maketemplate' 
 
118
#  or it breaks bookmarks with no comments.
 
119
if (Param("commentoncreate") && !trim($::FORM{'comment'})) {
 
120
    ThrowUserError("description_required");
112
121
}
113
122
 
114
123
# If bug_file_loc is "http://", the default, strip it out and use an empty
121
130
# Default assignee is the component owner.
122
131
if ($::FORM{'assigned_to'} eq "") {
123
132
    SendSQL("SELECT initialowner FROM components " .
124
 
            "WHERE program=$sql_product AND value=$sql_component");
 
133
            "WHERE id = $component_id");
125
134
    $::FORM{'assigned_to'} = FetchOneColumn();
126
135
} else {
127
136
    $::FORM{'assigned_to'} = DBNameToIdAndCheck(trim($::FORM{'assigned_to'}));
128
137
}
129
138
 
130
 
my @bug_fields = ("product", "version", "rep_platform",
 
139
my @bug_fields = ("version", "rep_platform",
131
140
                  "bug_severity", "priority", "op_sys", "assigned_to",
132
 
                  "bug_status", "bug_file_loc", "short_desc", "component",
133
 
                  "target_milestone");
 
141
                  "bug_status", "bug_file_loc", "short_desc",
 
142
                  "target_milestone", "status_whiteboard");
134
143
 
135
144
if (Param("useqacontact")) {
136
145
    SendSQL("SELECT initialqacontact FROM components " .
137
 
            "WHERE program=$sql_product AND value=$sql_component");
 
146
            "WHERE id = $component_id");
138
147
    my $qa_contact = FetchOneColumn();
139
148
    if (defined $qa_contact && $qa_contact != 0) {
140
149
        $::FORM{'qa_contact'} = $qa_contact;
142
151
    }
143
152
}
144
153
 
145
 
if (exists $::FORM{'bug_status'}) {
146
 
    # Ignore the given status, so that we can set it to UNCONFIRMED
147
 
    # or NEW, depending on votestoconfirm if either the given state was
148
 
    # unconfirmed (so that a user can't override the below check), or if
149
 
    # the user doesn't have permission to change the default status anyway
150
 
    if ($::FORM{'bug_status'} eq $::unconfirmedstate
151
 
        || (!UserInGroup("canedit") && !UserInGroup("canconfirm"))) {
152
 
        delete $::FORM{'bug_status'};
153
 
    }
154
 
}
155
 
 
156
 
if (!exists $::FORM{'bug_status'}) {
 
154
if (UserInGroup("editbugs") || UserInGroup("canconfirm")) {
 
155
    # Default to NEW if the user hasn't selected another status
 
156
    $::FORM{'bug_status'} ||= "NEW";
 
157
} else {
 
158
    # Default to UNCONFIRMED if we are using it, NEW otherwise
157
159
    $::FORM{'bug_status'} = $::unconfirmedstate;
158
 
    SendSQL("SELECT votestoconfirm FROM products WHERE product=$sql_product");
 
160
    SendSQL("SELECT votestoconfirm FROM products WHERE id = $product_id");
159
161
    if (!FetchOneColumn()) {
160
162
        $::FORM{'bug_status'} = "NEW";
161
163
    }
162
164
}
163
165
 
164
166
if (!exists $::FORM{'target_milestone'}) {
165
 
    SendSQL("SELECT defaultmilestone FROM products WHERE product=$sql_product");
 
167
    SendSQL("SELECT defaultmilestone FROM products WHERE name=$sql_product");
166
168
    $::FORM{'target_milestone'} = FetchOneColumn();
167
169
}
168
170
 
200
202
    $::FORM{'everconfirmed'} = 1;
201
203
}
202
204
 
 
205
$::FORM{'product_id'} = $product_id;
 
206
push(@used_fields, "product_id");
 
207
$::FORM{component_id} = $component_id;
 
208
push(@used_fields, "component_id");
 
209
 
203
210
my %ccids;
204
211
my @cc;
205
212
 
206
213
# Create the ccid hash for inserting into the db
207
 
# and the list for passing to processmail
 
214
# and the list for passing to Bugzilla::BugMail::Send
208
215
# use a hash rather than a list to avoid adding users twice
209
216
if (defined $::FORM{'cc'}) {
210
217
    foreach my $person (split(/[ ,]/, $::FORM{'cc'})) {
212
219
            my $ccid = DBNameToIdAndCheck($person);
213
220
            if ($ccid && !$ccids{$ccid}) {
214
221
                $ccids{$ccid} = 1;
215
 
                # if we got here, the DB has already verified that the email
216
 
                # is legit.  Unless the admin has screwed with the emailregexp
217
 
                # it'll be safe.
218
 
                trick_taint($person);
219
222
                push(@cc, $person);
220
223
            }
221
224
        }
222
225
    }
223
226
}
 
227
# Check for valid keywords and create list of keywords to be added to db
 
228
# (validity routine copied from process_bug.cgi)
 
229
my @keywordlist;
 
230
my %keywordseen;
 
231
 
 
232
if ($::FORM{'keywords'} && UserInGroup("editbugs")) {
 
233
    foreach my $keyword (split(/[\s,]+/, $::FORM{'keywords'})) {
 
234
        if ($keyword eq '') {
 
235
           next;
 
236
        }
 
237
        my $i = GetKeywordIdFromName($keyword);
 
238
        if (!$i) {
 
239
            ThrowUserError("unknown_keyword",
 
240
                           { keyword => $keyword });
 
241
        }
 
242
        if (!$keywordseen{$i}) {
 
243
            push(@keywordlist, $i);
 
244
            $keywordseen{$i} = 1;
 
245
        }
 
246
    }
 
247
}
 
248
 
 
249
# Check for valid dependency info. 
 
250
foreach my $field ("dependson", "blocked") {
 
251
    if (UserInGroup("editbugs") && defined($::FORM{$field}) &&
 
252
        $::FORM{$field} ne "") {
 
253
        my @validvalues;
 
254
        foreach my $id (split(/[\s,]+/, $::FORM{$field})) {
 
255
            next unless $id;
 
256
            ValidateBugID($id, $field);
 
257
            push(@validvalues, $id);
 
258
        }
 
259
        $::FORM{$field} = join(",", @validvalues);
 
260
    }
 
261
}
 
262
# Gather the dependecy list, and make sure there are no circular refs
 
263
my %deps;
 
264
if (UserInGroup("editbugs") && defined($::FORM{'dependson'})) {
 
265
    my $me = "blocked";
 
266
    my $target = "dependson";
 
267
    my %deptree;
 
268
    for (1..2) {
 
269
        $deptree{$target} = [];
 
270
        my %seen;
 
271
        foreach my $i (split('[\s,]+', $::FORM{$target})) {
 
272
            if (!exists $seen{$i}) {
 
273
                push(@{$deptree{$target}}, $i);
 
274
                $seen{$i} = 1;
 
275
            }
 
276
        }
 
277
        # populate $deps{$target} as first-level deps only.
 
278
        # and find remainder of dependency tree in $deptree{$target}
 
279
        @{$deps{$target}} = @{$deptree{$target}};
 
280
        my @stack = @{$deps{$target}};
 
281
        while (@stack) {
 
282
            my $i = shift @stack;
 
283
            SendSQL("select $target from dependencies where $me = " .
 
284
                    SqlQuote($i));
 
285
            while (MoreSQLData()) {
 
286
                my $t = FetchOneColumn();
 
287
                if (!exists $seen{$t}) {
 
288
                    push(@{$deptree{$target}}, $t);
 
289
                    push @stack, $t;
 
290
                    $seen{$t} = 1;
 
291
                } 
 
292
            }
 
293
        }
 
294
        
 
295
        if ($me eq 'dependson') {
 
296
            my @deps   =  @{$deptree{'dependson'}};
 
297
            my @blocks =  @{$deptree{'blocked'}};
 
298
            my @union = ();
 
299
            my @isect = ();
 
300
            my %union = ();
 
301
            my %isect = ();
 
302
            foreach my $b (@deps, @blocks) { $union{$b}++ && $isect{$b}++ }
 
303
            @union = keys %union;
 
304
            @isect = keys %isect;
 
305
            if (@isect > 0) {
 
306
                my $both;
 
307
                foreach my $i (@isect) {
 
308
                    $both = $both . GetBugLink($i, "#" . $i) . " ";
 
309
                }
 
310
 
 
311
                ThrowUserError("dependency_loop_multi",
 
312
                               { both => $both },
 
313
                               "abort");
 
314
            }
 
315
        }
 
316
        my $tmp = $me;
 
317
        $me = $target;
 
318
        $target = $tmp;
 
319
    }
 
320
}
224
321
 
225
322
# Build up SQL string to add bug.
 
323
# creation_ts will only be set when all other fields are defined.
226
324
my $sql = "INSERT INTO bugs " . 
227
 
  "(" . join(",", @used_fields) . ", reporter, creation_ts, groupset) " . 
 
325
  "(" . join(",", @used_fields) . ", reporter, " .
 
326
  "estimated_time, remaining_time) " .
228
327
  "VALUES (";
229
328
 
230
329
foreach my $field (@used_fields) {
237
336
# OK except for the fact that it causes e-mail to be suppressed.
238
337
$comment = $comment ? $comment : " ";
239
338
 
240
 
$sql .= "$::userid, now(), (0";
 
339
$sql .= "$::userid, ";
 
340
 
 
341
# Time Tracking
 
342
if (UserInGroup(Param("timetrackinggroup")) &&
 
343
    defined $::FORM{'estimated_time'}) {
 
344
 
 
345
    my $est_time = $::FORM{'estimated_time'};
 
346
    if ($est_time =~ /^(?:\d+(?:\.\d*)?|\.\d+)$/) {
 
347
        $sql .= SqlQuote($est_time) . "," . SqlQuote($est_time);
 
348
    } else {
 
349
        ThrowUserError("need_positive_number",
 
350
                       { field => 'estimated_time' });
 
351
    }
 
352
} else {
 
353
    $sql .= "0, 0";
 
354
}
 
355
$sql .= ")";
241
356
 
242
357
# Groups
 
358
my @groupstoadd = ();
243
359
foreach my $b (grep(/^bit-\d*$/, keys %::FORM)) {
244
360
    if ($::FORM{$b}) {
245
361
        my $v = substr($b, 4);
246
362
        $v =~ /^(\d+)$/
247
 
          || ThrowCodeError("One of the group bits submitted was invalid.",
248
 
                                                                undef, "abort");
 
363
          || ThrowCodeError("group_id_invalid", undef, "abort");
249
364
        if (!GroupIsActive($v)) {
250
365
            # Prevent the user from adding the bug to an inactive group.
251
366
            # Should only happen if there is a bug in Bugzilla or the user
252
367
            # hacked the "enter bug" form since otherwise the UI 
253
368
            # for adding the bug to the group won't appear on that form.
254
 
            ThrowCodeError("Attempted to add bug to an inactive group, " . 
255
 
                           "identified by the bit '$v'.", undef, "abort");
256
 
        }
257
 
        $sql .= " + $v";    # Carefully written so that the math is
258
 
                            # done by MySQL, which can handle 64-bit math,
259
 
                            # and not by Perl, which I *think* can not.
260
 
    }
261
 
}
262
 
 
263
 
$sql .= ") & $::usergroupset)\n";
264
 
 
265
 
# Lock tables before inserting records for the new bug into the database
266
 
# if we are using a shadow database to prevent shadow database corruption
267
 
# when two bugs get created at the same time.
268
 
SendSQL("LOCK TABLES bugs WRITE, longdescs WRITE, cc WRITE, profiles READ") if Param("shadowdb");
 
369
            $vars->{'bit'} = $v;
 
370
            ThrowCodeError("inactive_group", undef, "abort");
 
371
        }
 
372
        SendSQL("SELECT user_id FROM user_group_map 
 
373
                 WHERE user_id = $::userid
 
374
                 AND group_id = $v
 
375
                 AND isbless = 0");
 
376
        my ($permit) = FetchSQLData();
 
377
        if (!$permit) {
 
378
            SendSQL("SELECT othercontrol FROM group_control_map
 
379
                     WHERE group_id = $v AND product_id = $product_id");
 
380
            my ($othercontrol) = FetchSQLData();
 
381
            $permit = (($othercontrol == CONTROLMAPSHOWN)
 
382
                       || ($othercontrol == CONTROLMAPDEFAULT));
 
383
        }
 
384
        if ($permit) {
 
385
            push(@groupstoadd, $v)
 
386
        }
 
387
    }
 
388
}
 
389
 
 
390
SendSQL("SELECT DISTINCT groups.id, groups.name, " .
 
391
        "membercontrol, othercontrol " .
 
392
        "FROM groups LEFT JOIN group_control_map " .
 
393
        "ON group_id = id AND product_id = $product_id " .
 
394
        " WHERE isbuggroup != 0 AND isactive != 0 ORDER BY description");
 
395
while (MoreSQLData()) {
 
396
    my ($id, $groupname, $membercontrol, $othercontrol ) = FetchSQLData();
 
397
    $membercontrol ||= 0;
 
398
    $othercontrol ||= 0;
 
399
    # Add groups required
 
400
    if (($membercontrol == CONTROLMAPMANDATORY)
 
401
       || (($othercontrol == CONTROLMAPMANDATORY) 
 
402
            && (!UserInGroup($groupname)))) {
 
403
        # User had no option, bug needs to be in this group.
 
404
        push(@groupstoadd, $id)
 
405
    }
 
406
}
269
407
 
270
408
# Add the bug report to the DB.
 
409
SendSQL("LOCK TABLES bugs WRITE, bug_group_map WRITE, longdescs WRITE,
 
410
         cc WRITE, keywords WRITE, dependencies WRITE,
 
411
         bugs_activity WRITE, groups READ, user_group_map READ,
 
412
         keyworddefs READ, fielddefs READ");
 
413
 
271
414
SendSQL($sql);
272
415
 
 
416
SendSQL("select now()");
 
417
my $timestamp = FetchOneColumn();
 
418
 
273
419
# Get the bug ID back.
274
420
SendSQL("select LAST_INSERT_ID()");
275
421
my $id = FetchOneColumn();
276
422
 
277
 
# Add the comment
278
 
SendSQL("INSERT INTO longdescs (bug_id, who, bug_when, thetext) 
279
 
         VALUES ($id, $::userid, now(), " . SqlQuote($comment) . ")");
 
423
# Add the group restrictions
 
424
foreach my $grouptoadd (@groupstoadd) {
 
425
    SendSQL("INSERT INTO bug_group_map (bug_id, group_id)
 
426
             VALUES ($id, $grouptoadd)");
 
427
}
 
428
 
 
429
# Add the initial comment, allowing for the fact that it may be private
 
430
my $privacy = 0;
 
431
if (Param("insidergroup") && UserInGroup(Param("insidergroup"))) {
 
432
    $privacy = $::FORM{'commentprivacy'} ? 1 : 0;
 
433
}
 
434
 
 
435
SendSQL("INSERT INTO longdescs (bug_id, who, bug_when, thetext, isprivate) 
 
436
         VALUES ($id, " . SqlQuote($user->id) . ", " . SqlQuote($timestamp) . 
 
437
        ", " . SqlQuote($comment) . ", $privacy)");
280
438
 
281
439
# Insert the cclist into the database
282
440
foreach my $ccid (keys(%ccids)) {
283
441
    SendSQL("INSERT INTO cc (bug_id, who) VALUES ($id, $ccid)");
284
442
}
285
443
 
286
 
SendSQL("UNLOCK TABLES") if Param("shadowdb");
287
 
 
288
 
# Assemble the -force* strings so this counts as "Added to this capacity"
289
 
my @ARGLIST = ();
290
 
if (@cc) {
291
 
    push (@ARGLIST, "-forcecc", join(",", @cc));
 
444
my @all_deps;
 
445
if (UserInGroup("editbugs")) {
 
446
    foreach my $keyword (@keywordlist) {
 
447
        SendSQL("INSERT INTO keywords (bug_id, keywordid) 
 
448
                 VALUES ($id, $keyword)");
 
449
    }
 
450
    if (@keywordlist) {
 
451
        # Make sure that we have the correct case for the kw
 
452
        SendSQL("SELECT name FROM keyworddefs WHERE id IN ( " .
 
453
                join(',', @keywordlist) . ")");
 
454
        my @list;
 
455
        while (MoreSQLData()) {
 
456
            push (@list, FetchOneColumn());
 
457
        }
 
458
        SendSQL("UPDATE bugs SET keywords = " .
 
459
                SqlQuote(join(', ', @list)) .
 
460
                " WHERE bug_id = $id");
 
461
    }
 
462
    if (defined $::FORM{'dependson'}) {
 
463
        my $me = "blocked";
 
464
        my $target = "dependson";
 
465
        for (1..2) {
 
466
            foreach my $i (@{$deps{$target}}) {
 
467
                SendSQL("INSERT INTO dependencies ($me, $target) values " .
 
468
                        "($id, $i)");
 
469
                push(@all_deps, $i); # list for mailing dependent bugs
 
470
                # Log the activity for the other bug:
 
471
                LogActivityEntry($i, $me, "", $id, $user->id, $timestamp);
 
472
            }
 
473
            my $tmp = $me;
 
474
            $me = $target;
 
475
            $target = $tmp;
 
476
        }
 
477
    }
292
478
}
293
479
 
294
 
push (@ARGLIST, "-forceowner", DBID_to_name($::FORM{assigned_to}));
 
480
# All fields related to the newly created bug are set.
 
481
# The bug can now be made accessible.
 
482
SendSQL("UPDATE bugs SET creation_ts = " . SqlQuote($timestamp) .
 
483
        " WHERE bug_id = $id");
 
484
 
 
485
SendSQL("UNLOCK TABLES");
 
486
 
 
487
# Gather everyone interested in the details of the new bug (forced recipients)
 
488
my $mailrecipients = { 'cc' => \@cc,
 
489
                       'owner' => DBID_to_name($::FORM{'assigned_to'}),
 
490
                       'reporter' => $::COOKIE{'Bugzilla_login'},
 
491
                       'changer' => $::COOKIE{'Bugzilla_login'} };
295
492
 
296
493
if (defined $::FORM{'qa_contact'}) {
297
 
    push (@ARGLIST, "-forceqacontact", DBID_to_name($::FORM{'qa_contact'}));
 
494
    $mailrecipients->{'qacontact'} = DBID_to_name($::FORM{'qa_contact'});
298
495
}
299
496
 
300
 
push (@ARGLIST, "-forcereporter", DBID_to_name($::userid));
301
 
 
302
 
push (@ARGLIST, $id, $::COOKIE{'Bugzilla_login'});
303
 
 
304
 
# Send mail to let people know the bug has been created.
305
 
# See attachment.cgi for explanation of why it's done this way.
306
 
my $mailresults = '';
307
 
open(PMAIL, "-|") or exec('/usr/share/bugzilla/lib/processmail', @ARGLIST);
308
 
$mailresults .= $_ while <PMAIL>;
309
 
close(PMAIL);
310
 
 
311
 
# Tell the user all about it
312
497
$vars->{'id'} = $id;
313
 
$vars->{'mail'} = $mailresults;
314
 
$vars->{'type'} = "created";
315
 
 
316
 
print "Content-type: text/html\n\n";
 
498
my $bug = new Bugzilla::Bug($id, $::userid);
 
499
$vars->{'bug'} = $bug;
 
500
 
 
501
ThrowCodeError("bug_error", { bug => $bug }) if $bug->error;
 
502
 
 
503
$vars->{'sentmail'} = [];
 
504
 
 
505
push (@{$vars->{'sentmail'}}, { type => 'created',
 
506
                                id => $id,
 
507
                                mailrecipients => $mailrecipients
 
508
                              });
 
509
 
 
510
foreach my $i (@all_deps) {
 
511
    push (@{$vars->{'sentmail'}}, { type => 'dep',
 
512
                                    id => $i,
 
513
                                    mailrecipients => {
 
514
                                      # Only force changer for dep BugMail
 
515
                                      'changer' => $::COOKIE{'Bugzilla_login'}
 
516
                                    }
 
517
                                  });
 
518
}
 
519
 
 
520
my @bug_list;
 
521
if ($::COOKIE{"BUGLIST"}) {
 
522
    @bug_list = split(/:/, $::COOKIE{"BUGLIST"});
 
523
}
 
524
$vars->{'bug_list'} = \@bug_list;
 
525
 
 
526
print $cgi->header();
317
527
$template->process("bug/create/created.html.tmpl", $vars)
318
528
  || ThrowTemplateError($template->error());
319
529
 
320
 
$::FORM{'id'} = $id;
321
530
 
322
 
show_bug("header is already done");