post_bug.cgi 20.7 KB
Newer Older
1
#!/usr/bin/perl -wT
2
# -*- Mode: perl; indent-tabs-mode: nil -*-
terry%netscape.com's avatar
terry%netscape.com committed
3
#
4 5 6 7 8 9 10 11 12 13
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
terry%netscape.com's avatar
terry%netscape.com committed
14
# The Original Code is the Bugzilla Bug Tracking System.
15
#
terry%netscape.com's avatar
terry%netscape.com committed
16
# The Initial Developer of the Original Code is Netscape Communications
17 18 19 20
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
terry%netscape.com's avatar
terry%netscape.com committed
21
# Contributor(s): Terry Weissman <terry@mozilla.org>
22
#                 Dan Mosedale <dmose@mozilla.org>
23
#                 Joe Robins <jmrobins@tgix.com>
24
#                 Gervase Markham <gerv@gerv.net>
25
#                 Marc Schumann <wurblzap@gmail.com>
terry%netscape.com's avatar
terry%netscape.com committed
26

27
use strict;
28 29
use lib qw(.);

30
use Bugzilla;
31
use Bugzilla::Attachment;
32
use Bugzilla::Constants;
33
use Bugzilla::Util;
34
use Bugzilla::Error;
35
use Bugzilla::Bug;
36
use Bugzilla::User;
37
use Bugzilla::Field;
38
use Bugzilla::Product;
39
use Bugzilla::Component;
40
use Bugzilla::Keyword;
41
use Bugzilla::Token;
42

43
my $user = Bugzilla->login(LOGIN_REQUIRED);
44

45
my $cgi = Bugzilla->cgi;
46
my $dbh = Bugzilla->dbh;
47 48
my $template = Bugzilla->template;
my $vars = {};
49

50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
######################################################################
# Subroutines
######################################################################

# Determines whether or not a group is active by checking
# the "isactive" column for the group in the "groups" table.
# Note: This function selects groups by id rather than by name.
sub GroupIsActive {
    my ($group_id) = @_;
    $group_id ||= 0;
    detaint_natural($group_id);
    my ($is_active) = Bugzilla->dbh->selectrow_array(
        "SELECT isactive FROM groups WHERE id = ?", undef, $group_id);
    return $is_active;
}

######################################################################
# Main Script
######################################################################

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
# Detect if the user already used the same form to submit a bug
my $token = trim($cgi->param('token'));
if ($token) {
    my ($creator_id, $date, $old_bug_id) = Bugzilla::Token::GetTokenData($token);
    unless ($creator_id
              && ($creator_id == $user->id)
              && ($old_bug_id =~ "^createbug:"))
    {
        # The token is invalid.
        ThrowUserError('token_inexistent');
    }

    $old_bug_id =~ s/^createbug://;

    if ($old_bug_id && (!$cgi->param('ignore_token')
                        || ($cgi->param('ignore_token') != $old_bug_id)))
    {
        $vars->{'bugid'} = $old_bug_id;
        $vars->{'allow_override'} = defined $cgi->param('ignore_token') ? 0 : 1;

        print $cgi->header();
        $template->process("bug/create/confirm-create-dupe.html.tmpl", $vars)
           || ThrowTemplateError($template->error());
        exit;
    }
}    

97 98
# do a match on the fields if applicable

99
&Bugzilla::User::match_field ($cgi, {
100 101
    'cc'            => { 'type' => 'multi'  },
    'assigned_to'   => { 'type' => 'single' },
102
    'qa_contact'    => { 'type' => 'single' },
103
    '^requestee_type-(\d+)$' => { 'type' => 'multi' },
104
});
105 106 107 108 109

# The format of the initial comment can be structured by adding fields to the
# enter_bug template and then referencing them in the comment template.
my $comment;

110 111
my $format = $template->get_format("bug/create/comment",
                                   scalar($cgi->param('format')), "txt");
112

113
$template->process($format->{'template'}, $vars, \$comment)
114 115 116
  || ThrowTemplateError($template->error());

ValidateComment($comment);
117

118
# Check that the product exists and that the user
119
# is allowed to enter bugs into this product.
120
$user->can_enter_product(scalar $cgi->param('product'), 1);
121

122
my $product = Bugzilla::Product::check_product(scalar $cgi->param('product'));
dmose%mozilla.org's avatar
dmose%mozilla.org committed
123

124
# Set cookies
125 126
if (defined $cgi->param('product')) {
    if (defined $cgi->param('version')) {
127
        $cgi->send_cookie(-name => "VERSION-" . $product->name,
128 129
                          -value => $cgi->param('version'),
                          -expires => "Fri, 01-Jan-2038 00:00:00 GMT");
130 131
    }
}
terry%netscape.com's avatar
terry%netscape.com committed
132

133
if (defined $cgi->param('maketemplate')) {
134
    $vars->{'url'} = $cgi->query_string();
135
    $vars->{'short_desc'} = $cgi->param('short_desc');
terry%netscape.com's avatar
terry%netscape.com committed
136
    
137
    print $cgi->header();
138 139
    $template->process("bug/create/make-template.html.tmpl", $vars)
      || ThrowTemplateError($template->error());
140
    exit;
terry%netscape.com's avatar
terry%netscape.com committed
141 142
}

143
umask 0;
terry%netscape.com's avatar
terry%netscape.com committed
144

145
# Some sanity checking
146 147
$cgi->param('component') || ThrowUserError("require_component");
my $component = Bugzilla::Component::check_component($product, scalar $cgi->param('component'));
terry%netscape.com's avatar
terry%netscape.com committed
148

149 150 151
# Set the parameter to itself, but cleaned up
$cgi->param('short_desc', clean_text($cgi->param('short_desc')));

152
if (!defined $cgi->param('short_desc')
153
    || $cgi->param('short_desc') eq "") {
154
    ThrowUserError("require_summary");
155 156
}

157 158 159
# Check that if required a description has been provided
# This has to go somewhere after 'maketemplate' 
#  or it breaks bookmarks with no comments.
160
if (Bugzilla->params->{"commentoncreate"} && !trim($cgi->param('comment'))) {
161 162 163
    ThrowUserError("description_required");
}

164 165 166
# If bug_file_loc is "http://", the default, use an empty value instead.
$cgi->param('bug_file_loc', '') if $cgi->param('bug_file_loc') eq 'http://';

167 168

# Default assignee is the component owner.
169
if (!UserInGroup("editbugs") || $cgi->param('assigned_to') eq "") {
170
    $cgi->param(-name => 'assigned_to', -value => $component->default_assignee->id);
171
} else {
172
    $cgi->param(-name => 'assigned_to',
173
                -value => login_to_id(trim($cgi->param('assigned_to')), THROW_ERROR));
terry%netscape.com's avatar
terry%netscape.com committed
174 175
}

176 177 178 179

my @enter_bug_field_names = map {$_->name} Bugzilla->get_fields({ custom => 1,
    obsolete => 0, enter_bug => 1});

180
my @bug_fields = ("version", "rep_platform",
181
                  "bug_severity", "priority", "op_sys", "assigned_to",
182
                  "bug_status", "everconfirmed", "bug_file_loc", "short_desc",
183 184
                  "target_milestone", "status_whiteboard",
                  @enter_bug_field_names);
185

186
if (Bugzilla->params->{"usebugaliases"}) {
187 188 189 190 191 192 193 194
   my $alias = trim($cgi->param('alias') || "");
   if ($alias ne "") {
       ValidateBugAlias($alias);
       $cgi->param('alias', $alias);
       push (@bug_fields,"alias");
   }
}

195
# Retrieve the default QA contact if the field is empty
196
if (Bugzilla->params->{"useqacontact"}) {
197
    my $qa_contact;
198 199
    if (!UserInGroup("editbugs") || !defined $cgi->param('qa_contact')
        || trim($cgi->param('qa_contact')) eq "") {
200
        $qa_contact = $component->default_qa_contact->id;
201
    } else {
202
        $qa_contact = login_to_id(trim($cgi->param('qa_contact')), THROW_ERROR);
203 204
    }

205
    if ($qa_contact) {
206
        $cgi->param(-name => 'qa_contact', -value => $qa_contact);
207 208 209 210
        push(@bug_fields, "qa_contact");
    }
}

211 212 213 214
# Check the bug status.
# This order is important, see below.
my @valid_statuses = ('UNCONFIRMED', 'NEW', 'ASSIGNED');

215
my $bug_status = 'UNCONFIRMED';
216
if ($user->in_group('editbugs') || $user->in_group('canconfirm')) {
217
    # Default to NEW if the user with privs hasn't selected another status.
218 219 220
    $bug_status = scalar($cgi->param('bug_status')) || 'NEW';
}
elsif (!$product->votes_to_confirm) {
221
    $bug_status = 'NEW';
222
}
223
$cgi->param(-name => 'bug_status', -value => $bug_status);
224

225 226 227 228
# Reject 'UNCONFIRMED' as a valid status if the product
# doesn't require votes to confirm its bugs.
shift @valid_statuses if !$product->votes_to_confirm;

229
if (!defined $cgi->param('target_milestone')) {
230
    $cgi->param(-name => 'target_milestone', -value => $product->default_milestone);
231 232
}

233 234
if (!Bugzilla->params->{'letsubmitterchoosepriority'}) {
    $cgi->param(-name => 'priority', -value => Bugzilla->params->{'defaultpriority'});
235 236
}

237
# Some more sanity checking
238 239 240 241
check_field('rep_platform', scalar $cgi->param('rep_platform'));
check_field('bug_severity', scalar $cgi->param('bug_severity'));
check_field('priority',     scalar $cgi->param('priority'));
check_field('op_sys',       scalar $cgi->param('op_sys'));
242
check_field('bug_status',   scalar $cgi->param('bug_status'), \@valid_statuses);
243
check_field('version',      scalar $cgi->param('version'),
244
            [map($_->name, @{$product->versions})]);
245
check_field('target_milestone', scalar $cgi->param('target_milestone'),
246
            [map($_->name, @{$product->milestones})]);
247 248 249 250 251

foreach my $field_name ('assigned_to', 'bug_file_loc', 'comment') {
    defined($cgi->param($field_name))
      || ThrowCodeError('undefined_field', { field => $field_name });
}
252

253 254 255
my $everconfirmed = ($cgi->param('bug_status') eq 'UNCONFIRMED') ? 0 : 1;
$cgi->param(-name => 'everconfirmed', -value => $everconfirmed);

256
my @used_fields;
257
foreach my $field (@bug_fields) {
258
    if (defined $cgi->param($field)) {
259
        push (@used_fields, $field);
260 261
    }
}
262

263
$cgi->param(-name => 'product_id', -value => $product->id);
264
push(@used_fields, "product_id");
265
$cgi->param(-name => 'component_id', -value => $component->id);
266 267
push(@used_fields, "component_id");

268 269 270 271
my %ccids;

# Create the ccid hash for inserting into the db
# use a hash rather than a list to avoid adding users twice
272 273
if (defined $cgi->param('cc')) {
    foreach my $person ($cgi->param('cc')) {
274
        next unless $person;
275
        my $ccid = login_to_id($person, THROW_ERROR);
276 277
        if ($ccid && !$ccids{$ccid}) {
           $ccids{$ccid} = 1;
278 279 280
        }
    }
}
281 282 283 284 285
# Check for valid keywords and create list of keywords to be added to db
# (validity routine copied from process_bug.cgi)
my @keywordlist;
my %keywordseen;

286 287
if ($cgi->param('keywords') && UserInGroup("editbugs")) {
    foreach my $keyword (split(/[\s,]+/, $cgi->param('keywords'))) {
288 289 290
        if ($keyword eq '') {
           next;
        }
291 292
        my $keyword_obj = new Bugzilla::Keyword({name => $keyword});
        if (!$keyword_obj) {
293 294
            ThrowUserError("unknown_keyword",
                           { keyword => $keyword });
295
        }
296 297 298
        if (!$keywordseen{$keyword_obj->id}) {
            push(@keywordlist, $keyword_obj->id);
            $keywordseen{$keyword_obj->id} = 1;
299 300 301
        }
    }
}
302

303
if (Bugzilla->params->{"strict_isolation"}) {
304 305 306
    my @blocked_users = ();
    my %related_users = %ccids;
    $related_users{$cgi->param('assigned_to')} = 1;
307
    if (Bugzilla->params->{'useqacontact'} && $cgi->param('qa_contact')) {
308 309 310 311
        $related_users{$cgi->param('qa_contact')} = 1;
    }
    foreach my $pid (keys %related_users) {
        my $related_user = Bugzilla::User->new($pid);
312
        if (!$related_user->can_edit_product($product->id)) {
313 314 315 316 317 318 319
            push (@blocked_users, $related_user->login);
        }
    }
    if (scalar(@blocked_users)) {
        ThrowUserError("invalid_user_group", 
            {'users' => \@blocked_users,
             'new' => 1,
320
             'product' => $product->name
321 322 323 324
            });
    }
}

325 326
# Check for valid dependency info. 
foreach my $field ("dependson", "blocked") {
327
    if (UserInGroup("editbugs") && $cgi->param($field)) {
328
        my @validvalues;
329
        foreach my $id (split(/[\s,]+/, $cgi->param($field))) {
330
            next unless $id;
331
            # $field is not passed to ValidateBugID to prevent adding new 
332
            # dependencies on inaccessible bugs.
333
            ValidateBugID($id);
334 335
            push(@validvalues, $id);
        }
336
        $cgi->param(-name => $field, -value => join(",", @validvalues));
337 338
    }
}
339
# Gather the dependency list, and make sure there are no circular refs
340
my %deps;
341
if (UserInGroup("editbugs")) {
342 343
    %deps = Bugzilla::Bug::ValidateDependencies(scalar($cgi->param('dependson')),
                                                scalar($cgi->param('blocked')));
344 345
}

346
# get current time
347
my $timestamp = $dbh->selectrow_array(q{SELECT NOW()});
348

349
# Build up SQL string to add bug.
350
# creation_ts will only be set when all other fields are defined.
351 352

my @fields_values;
terry%netscape.com's avatar
terry%netscape.com committed
353

354
foreach my $field (@used_fields) {
355 356 357
    my $value = $cgi->param($field);
    trick_taint($value);
    push (@fields_values, $value);
terry%netscape.com's avatar
terry%netscape.com committed
358 359
}

360 361 362 363 364 365 366
my $sql_used_fields = join(", ", @used_fields);
my $sql_placeholders = "?, " x scalar(@used_fields);

my $query = qq{INSERT INTO bugs ($sql_used_fields, reporter, delta_ts,
                                 estimated_time, remaining_time, deadline)
               VALUES ($sql_placeholders ?, ?, ?, ?, ?)};

367
$comment =~ s/\r\n?/\n/g;     # Get rid of \r.
368
$comment = trim($comment);
369
# If comment is all whitespace, it'll be null at this point. That's
370 371
# OK except for the fact that it causes e-mail to be suppressed.
$comment = $comment ? $comment : " ";
372

373 374 375 376 377
push (@fields_values, $user->id);
push (@fields_values, $timestamp);

my $est_time = 0;
my $deadline;
378 379

# Time Tracking
380
if (UserInGroup(Bugzilla->params->{"timetrackinggroup"}) &&
381
    defined $cgi->param('estimated_time')) {
382

383
    $est_time = $cgi->param('estimated_time');
384
    Bugzilla::Bug::ValidateTime($est_time, 'estimated_time');
385 386
    trick_taint($est_time);

387
}
388

389 390
push (@fields_values, $est_time, $est_time);

391 392 393
if ( UserInGroup(Bugzilla->params->{"timetrackinggroup"})
     && $cgi->param('deadline') ) 
{
394 395 396
    validate_date($cgi->param('deadline'))
      || ThrowUserError('illegal_date', {date => $cgi->param('deadline'),
                                         format => 'YYYY-MM-DD'});
397 398
    $deadline = $cgi->param('deadline');
    trick_taint($deadline);
399 400
}

401
push (@fields_values, $deadline);
402

403
# Groups
404
my @groupstoadd = ();
405 406 407 408 409
my $sth_othercontrol = $dbh->prepare(q{SELECT othercontrol
                                         FROM group_control_map
                                        WHERE group_id = ?
                                          AND product_id = ?});

410 411
foreach my $b (grep(/^bit-\d*$/, $cgi->param())) {
    if ($cgi->param($b)) {
412
        my $v = substr($b, 4);
413
        detaint_natural($v)
414
          || ThrowUserError("invalid_group_ID");
415 416 417 418 419
        if (!GroupIsActive($v)) {
            # Prevent the user from adding the bug to an inactive group.
            # Should only happen if there is a bug in Bugzilla or the user
            # hacked the "enter bug" form since otherwise the UI 
            # for adding the bug to the group won't appear on that form.
420
            $vars->{'bit'} = $v;
421
            ThrowCodeError("inactive_group");
422
        }
423
        my ($permit) = $user->in_group_id($v);
424
        if (!$permit) {
425
            my $othercontrol = $dbh->selectrow_array($sth_othercontrol, 
426
                                                     undef, ($v, $product->id));
427 428 429 430
            $permit = (($othercontrol == CONTROLMAPSHOWN)
                       || ($othercontrol == CONTROLMAPDEFAULT));
        }
        if ($permit) {
431 432
            push(@groupstoadd, $v)
        }
433 434 435
    }
}

436 437 438 439 440 441 442 443 444
my $groups = $dbh->selectall_arrayref(q{
                 SELECT DISTINCT groups.id, groups.name, membercontrol,
                                 othercontrol, description
                            FROM groups
                       LEFT JOIN group_control_map 
                              ON group_id = id
                             AND product_id = ?
                           WHERE isbuggroup != 0
                             AND isactive != 0
445
                        ORDER BY description}, undef, $product->id);
446 447 448

foreach my $group (@$groups) {
    my ($id, $groupname, $membercontrol, $othercontrol) = @$group;
449 450 451 452 453 454 455 456 457 458
    $membercontrol ||= 0;
    $othercontrol ||= 0;
    # Add groups required
    if (($membercontrol == CONTROLMAPMANDATORY)
       || (($othercontrol == CONTROLMAPMANDATORY) 
            && (!UserInGroup($groupname)))) {
        # User had no option, bug needs to be in this group.
        push(@groupstoadd, $id)
    }
}
459

460
# Add the bug report to the DB.
461 462
$dbh->bz_lock_tables('bugs WRITE', 'bug_group_map WRITE', 'longdescs WRITE',
                     'cc WRITE', 'keywords WRITE', 'dependencies WRITE',
463 464
                     'bugs_activity WRITE', 'groups READ',
                     'user_group_map READ', 'group_group_map READ',
465 466
                     'keyworddefs READ', 'fielddefs READ');

467
$dbh->do($query, undef, @fields_values);
468

469
# Get the bug ID back.
470
my $id = $dbh->bz_last_key('bugs', 'bug_id');
terry%netscape.com's avatar
terry%netscape.com committed
471

472
# Add the group restrictions
473 474
my $sth_addgroup = $dbh->prepare(q{
            INSERT INTO bug_group_map (bug_id, group_id) VALUES (?, ?)});
475
foreach my $grouptoadd (@groupstoadd) {
476
    $sth_addgroup->execute($id, $grouptoadd);
477 478
}

479 480
# Add the initial comment, allowing for the fact that it may be private
my $privacy = 0;
481 482 483
if (Bugzilla->params->{"insidergroup"} 
    && UserInGroup(Bugzilla->params->{"insidergroup"})) 
{
484
    $privacy = $cgi->param('commentprivacy') ? 1 : 0;
485 486
}

487 488 489 490
trick_taint($comment);
$dbh->do(q{INSERT INTO longdescs (bug_id, who, bug_when, thetext,isprivate)
           VALUES (?, ?, ?, ?, ?)}, undef, ($id, $user->id, $timestamp,
                                            $comment, $privacy));
terry%netscape.com's avatar
terry%netscape.com committed
491

492
# Insert the cclist into the database
493
my $sth_cclist = $dbh->prepare(q{INSERT INTO cc (bug_id, who) VALUES (?,?)});
494
foreach my $ccid (keys(%ccids)) {
495
    $sth_cclist->execute($id, $ccid);
terry%netscape.com's avatar
terry%netscape.com committed
496 497
}

498
my @all_deps;
499 500
my $sth_addkeyword = $dbh->prepare(q{
            INSERT INTO keywords (bug_id, keywordid) VALUES (?, ?)});
501 502
if (UserInGroup("editbugs")) {
    foreach my $keyword (@keywordlist) {
503
        $sth_addkeyword->execute($id, $keyword);
504
    }
505 506
    if (@keywordlist) {
        # Make sure that we have the correct case for the kw
507
        my $kw_ids = join(', ', @keywordlist);
508
        my $list = $dbh->selectcol_arrayref(qq{
509 510
                                    SELECT name 
                                      FROM keyworddefs 
511 512
                                     WHERE id IN ($kw_ids)
                                  ORDER BY name});
513 514 515 516
        my $kw_list = join(', ', @$list);
        $dbh->do(q{UPDATE bugs 
                      SET delta_ts = ?, keywords = ? 
                    WHERE bug_id = ?}, undef, ($timestamp, $kw_list, $id));
517
    }
518 519 520
    if ($cgi->param('dependson') || $cgi->param('blocked')) {
        foreach my $pair (["blocked", "dependson"], ["dependson", "blocked"]) {
            my ($me, $target) = @{$pair};
521 522
            my $sth_dep = $dbh->prepare(qq{
                        INSERT INTO dependencies ($me, $target) VALUES (?, ?)});
523
            foreach my $i (@{$deps{$target}}) {
524
                $sth_dep->execute($id, $i);
525 526
                push(@all_deps, $i); # list for mailing dependent bugs
                # Log the activity for the other bug:
527
                LogActivityEntry($i, $me, "", $id, $user->id, $timestamp);
528 529 530
            }
        }
    }
531 532
}

533 534 535 536 537 538 539
# All fields related to the newly created bug are set.
# The bug can now be made accessible.
$dbh->do("UPDATE bugs SET creation_ts = ? WHERE bug_id = ?",
          undef, ($timestamp, $id));

$dbh->bz_unlock_tables();

540 541
my $bug = new Bugzilla::Bug($id, $user->id);

542 543 544 545
# Add an attachment if requested.
if (defined($cgi->upload('data')) || $cgi->param('attachurl')) {
    $cgi->param('isprivate', $cgi->param('commentprivacy'));
    Bugzilla::Attachment->insert_attachment_for_bug(!THROW_ERROR,
546
                                                    $bug, $user, $timestamp,
547 548 549 550 551 552 553 554 555 556
                                                    \$vars)
        || ($vars->{'message'} = 'attachment_creation_failed');

    # Determine if Patch Viewer is installed, for Diff link
    eval {
        require PatchReader;
        $vars->{'patchviewerinstalled'} = 1;
    };
}

557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576
# Add flags, if any. To avoid dying if something goes wrong
# while processing flags, we will eval() flag validation.
# This requires to be in batch mode.
# XXX: this can go away as soon as flag validation is able to
#      fail without dying.
Bugzilla->batch(1);
eval {
    # Make sure no flags have already been set for this bug.
    # Impossible? - Well, depends if you hack the URL or not.
    # Passing a bug ID of 0 will make it complain if it finds one.
    Bugzilla::Flag::validate($cgi, 0);
    Bugzilla::FlagType::validate($cgi, $id);
    Bugzilla::Flag::process($bug, undef, $timestamp, $cgi);
};
Bugzilla->batch(0);
if ($@) {
    $vars->{'message'} = 'flag_creation_failed';
    $vars->{'flag_creation_error'} = $@;
}

577
# Email everyone the details of the new bug 
578
$vars->{'mailrecipients'} = {'changer' => $user->login};
579

580
$vars->{'id'} = $id;
581
$vars->{'bug'} = $bug;
terry%netscape.com's avatar
terry%netscape.com committed
582

583
ThrowCodeError("bug_error", { bug => $bug }) if $bug->error;
584 585 586 587 588 589

$vars->{'sentmail'} = [];

push (@{$vars->{'sentmail'}}, { type => 'created',
                                id => $id,
                              });
590

591
foreach my $i (@all_deps) {
592
    push (@{$vars->{'sentmail'}}, { type => 'dep', id => $i, });
593
}
594

595
my @bug_list;
596 597
if ($cgi->cookie("BUGLIST")) {
    @bug_list = split(/:/, $cgi->cookie("BUGLIST"));
598
}
599
$vars->{'bug_list'} = \@bug_list;
600
$vars->{'use_keywords'} = 1 if Bugzilla::Keyword::keyword_count();
601

602 603 604 605 606 607
if ($token) {
    trick_taint($token);
    $dbh->do('UPDATE tokens SET eventdata = ? WHERE token = ?', undef, 
             ("createbug:$id", $token));
}

608
print $cgi->header();
609 610
$template->process("bug/create/created.html.tmpl", $vars)
  || ThrowTemplateError($template->error());
611

612