enter_bug.cgi 22 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
# Corporation. Portions created by Netscape are Copyright (C) 1998
# Netscape Communications Corporation. All Rights Reserved.
# 
terry%netscape.com's avatar
terry%netscape.com committed
20
# Contributor(s): Terry Weissman <terry@mozilla.org>
21
#                 Dave Miller <justdave@syndicomm.com>
22
#                 Joe Robins <jmrobins@tgix.com>
23
#                 Gervase Markham <gerv@gerv.net>
24
#                 Shane H. W. Travis <travis@sedsystems.ca>
terry%netscape.com's avatar
terry%netscape.com committed
25

26
##############################################################################
27 28 29 30
#
# enter_bug.cgi
# -------------
# Displays bug entry form. Bug fields are specified through popup menus, 
31 32
# drop-down lists, or text fields. Default for these values can be 
# passed in as parameters to the cgi.
33
#
34
##############################################################################
35

36
use strict;
terry%netscape.com's avatar
terry%netscape.com committed
37

38 39
use lib qw(.);

40
use Bugzilla;
41
use Bugzilla::Constants;
42
use Bugzilla::Bug;
43
use Bugzilla::User;
44
use Bugzilla::Product;
45
require "globals.pl";
46

47
use vars qw(
48
  @enterable_products
49 50 51 52
  @legal_opsys
  @legal_platform
  @legal_priority
  @legal_severity
53
  @legal_keywords
54
  %versions
55
  %target_milestone
56 57 58 59
);

# If we're using bug groups to restrict bug entry, we need to know who the 
# user is right from the start. 
60
Bugzilla->login(LOGIN_REQUIRED) if AnyEntryGroups();
61

62 63 64
my $cloned_bug;
my $cloned_bug_id;

65
my $cgi = Bugzilla->cgi;
66 67
my $template = Bugzilla->template;
my $vars = {};
68

69 70
my $product = $cgi->param('product');

71
if (!defined $product || $product eq "") {
72
    GetVersionTable();
73
    Bugzilla->login();
74

75
    if ( ! Param('useclassification') ) {
76
        # Just use a fake value for the Classification.
77
        $cgi->param(-name => 'classification', 
78
                    -value => '__all');
79 80 81 82 83 84 85
    }

    if (!$cgi->param('classification')) {
        my $classifications = Bugzilla->user->get_selectable_classifications();
        foreach my $classification (@$classifications) {
            my $found = 0;
            foreach my $p (@enterable_products) {
86
               if (Bugzilla->user->can_enter_product($p)
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
                   && IsInClassification($classification->{name},$p)) {
                       $found = 1; 
               }
            }
            if ($found == 0) {
                @$classifications = grep($_->{name} ne $classification->{name},
                                         @$classifications);
            }
        }

        if (scalar(@$classifications) == 0) {
            ThrowUserError("no_products");
        } 
        elsif (scalar(@$classifications) > 1) {
            $vars->{'classifications'} = $classifications;

            $vars->{'target'} = "enter_bug.cgi";
            $vars->{'format'} = $cgi->param('format');
105
           
106 107 108 109 110 111 112 113 114
            $vars->{'cloned_bug_id'} = $cgi->param('cloned_bug_id');

            print $cgi->header();
            $template->process("global/choose-classification.html.tmpl", $vars)
               || ThrowTemplateError($template->error());
            exit;        
        }
        $cgi->param(-name => 'classification', -value => @$classifications[0]->name);
    }
115

116
    my %products;
117
    # XXX - This loop should work in some more sensible, efficient way.
118
    foreach my $p (@enterable_products) {
119
        if (Bugzilla->user->can_enter_product($p)) {
120 121
            if (IsInClassification(scalar $cgi->param('classification'),$p) ||
                $cgi->param('classification') eq "__all") {
122 123
                my $product_object = new Bugzilla::Product({name => $p});
                $products{$p} = $product_object->description;
124
            }
125
        }
126
    }
127
 
128
    my $prodsize = scalar(keys %products);
129
    if ($prodsize == 0) {
130
        ThrowUserError("no_products");
131 132
    } 
    elsif ($prodsize > 1) {
133 134 135 136
        my %classifications;
        if ( ! Param('useclassification') ) {
            @{$classifications{"all"}} = keys %products;
        }
137
        elsif ($cgi->param('classification') eq "__all") {
138 139
            %classifications = %::classifications;
        } else {
140 141
            $classifications{$cgi->param('classification')} =
                $::classifications{$cgi->param('classification')};
142
        }
143
        $vars->{'proddesc'} = \%products;
144
        $vars->{'classifications'} = \%classifications;
145 146

        $vars->{'target'} = "enter_bug.cgi";
147
        $vars->{'format'} = $cgi->param('format');
148 149

        $vars->{'cloned_bug_id'} = $cgi->param('cloned_bug_id');
150
        
151
        print $cgi->header();
152 153
        $template->process("global/choose-product.html.tmpl", $vars)
          || ThrowTemplateError($template->error());
154
        exit;        
155 156 157
    } else {
        # Only one product exists
        $product = (keys %products)[0];
158
    }
159
}
terry%netscape.com's avatar
terry%netscape.com committed
160

161 162 163
##############################################################################
# Useful Subroutines
##############################################################################
164 165
sub formvalue {
    my ($name, $default) = (@_);
166
    return $cgi->param($name) || $default || "";
167
}
terry%netscape.com's avatar
terry%netscape.com committed
168

169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
# Takes the name of a field and a list of possible values for that 
# field. Returns the first value in the list that is actually a 
# valid value for that field.
# The field should be named after its DB table.
# Returns undef if none of the platforms match.
sub pick_valid_field_value (@) {
    my ($field, @values) = @_;
    my $dbh = Bugzilla->dbh;

    foreach my $value (@values) {
        return $value if $dbh->selectrow_array(
            "SELECT 1 FROM $field WHERE value = ?", undef, $value); 
    }
    return undef;
}

185
sub pickplatform {
186 187
    return formvalue("rep_platform") if formvalue("rep_platform");

188 189
    my @platform;

190
    if (Param('defaultplatform')) {
191
        @platform = Param('defaultplatform');
192
    } else {
193 194 195
        # If @platform is a list, this function will return the first
        # item in the list that is a valid platform choice. If
        # no choice is valid, we return "Other".
196
        for ($ENV{'HTTP_USER_AGENT'}) {
197
        #PowerPC
198 199 200
            /\(.*PowerPC.*\)/i && do {@platform = "Macintosh"; last;};
            /\(.*PPC.*\)/ && do {@platform = "Macintosh"; last;};
            /\(.*AIX.*\)/ && do {@platform = "Macintosh"; last;};
201
        #Intel x86
202
            /\(.*[ix0-9]86.*\)/ && do {@platform = "PC"; last;};
203
        #Versions of Windows that only run on Intel x86
204 205
            /\(.*Win(?:dows )[39M].*\)/ && do {@platform = "PC"; last};
            /\(.*Win(?:dows )16.*\)/ && do {@platform = "PC"; last;};
206
        #Sparc
207 208
            /\(.*sparc.*\)/ && do {@platform = "Sun"; last;};
            /\(.*sun4.*\)/ && do {@platform = "Sun"; last;};
209
        #Alpha
210 211 212
            /\(.*AXP.*\)/i && do {@platform = "DEC"; last;};
            /\(.*[ _]Alpha.\D/i && do {@platform = "DEC"; last;};
            /\(.*[ _]Alpha\)/i && do {@platform = "DEC"; last;};
213
        #MIPS
214 215
            /\(.*IRIX.*\)/i && do {@platform = "SGI"; last;};
            /\(.*MIPS.*\)/i && do {@platform = "SGI"; last;};
216
        #68k
217 218
            /\(.*68K.*\)/ && do {@platform = "Macintosh"; last;};
            /\(.*680[x0]0.*\)/ && do {@platform = "Macintosh"; last;};
219
        #HP
220
            /\(.*9000.*\)/ && do {@platform = "HP"; last;};
221
        #ARM
222
#            /\(.*ARM.*\) && do {$platform = "ARM";};
223
        #Stereotypical and broken
224 225 226 227 228 229 230 231
            /\(.*Macintosh.*\)/ && do {@platform = "Macintosh"; last;};
            /\(.*Mac OS [89].*\)/ && do {@platform = "Macintosh"; last;};
            /\(Win.*\)/ && do {@platform = "PC"; last;};
            /\(.*Win(?:dows[ -])NT.*\)/ && do {@platform = "PC"; last;};
            /\(.*OSF.*\)/ && do {@platform = "DEC"; last;};
            /\(.*HP-?UX.*\)/i && do {@platform = "HP"; last;};
            /\(.*IRIX.*\)/i && do {@platform = "SGI"; last;};
            /\(.*(SunOS|Solaris).*\)/ && do {@platform = "Sun"; last;};
232
        #Braindead old browsers who didn't follow convention:
233 234
            /Amiga/ && do {@platform = "Macintosh"; last;};
            /WinMosaic/ && do {@platform = "PC"; last;};
235
        }
terry%netscape.com's avatar
terry%netscape.com committed
236
    }
237 238

    return pick_valid_field_value('rep_platform', @platform) || "Other";
terry%netscape.com's avatar
terry%netscape.com committed
239 240
}

241 242 243
sub pickos {
    if (formvalue('op_sys') ne "") {
        return formvalue('op_sys');
terry%netscape.com's avatar
terry%netscape.com committed
244
    }
245 246 247

    my @os;

248
    if (Param('defaultopsys')) {
249
        @os = Param('defaultopsys');
250
    } else {
251 252 253
        # This function will return the first
        # item in @os that is a valid platform choice. If
        # no choice is valid, we return "Other".
254
        for ($ENV{'HTTP_USER_AGENT'}) {
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
            /\(.*IRIX.*\)/ && do {@os = "IRIX"; last;};
            /\(.*OSF.*\)/ && do {@os = "OSF/1"; last;};
            /\(.*Linux.*\)/ && do {@os = "Linux"; last;};
            /\(.*Solaris.*\)/ && do {@os = "Solaris"; last;};
            /\(.*SunOS 5.*\)/ && do {@os = "Solaris"; last;};
            /\(.*SunOS.*sun4u.*\)/ && do {@os = "Solaris"; last;};
            /\(.*SunOS.*\)/ && do {@os = "SunOS"; last;};
            /\(.*HP-?UX.*\)/ && do {@os = "HP-UX"; last;};
            /\(.*BSD\/(?:OS|386).*\)/ && do {@os = "BSDI"; last;};
            /\(.*FreeBSD.*\)/ && do {@os = "FreeBSD"; last;};
            /\(.*OpenBSD.*\)/ && do {@os = "OpenBSD"; last;};
            /\(.*NetBSD.*\)/ && do {@os = "NetBSD"; last;};
            /\(.*BeOS.*\)/ && do {@os = "BeOS"; last;};
            /\(.*AIX.*\)/ && do {@os = "AIX"; last;};
            /\(.*OS\/2.*\)/ && do {@os = "OS/2"; last;};
            /\(.*QNX.*\)/ && do {@os = "Neutrino"; last;};
            /\(.*VMS.*\)/ && do {@os = "OpenVMS"; last;};
            /\(.*Windows XP.*\)/ && do {@os = "Windows XP"; last;};
            /\(.*Windows NT 5\.2.*\)/ && do {@os = "Windows Server 2003"; last;};
            /\(.*Windows NT 5\.1.*\)/ && do {@os = "Windows XP"; last;};
            /\(.*Windows 2000.*\)/ && do {@os = "Windows 2000"; last;};
            /\(.*Windows NT 5.*\)/ && do {@os = "Windows 2000"; last;};
            /\(.*Win.*9[8x].*4\.9.*\)/ && do {@os = "Windows ME"; last;};
            /\(.*Win(?:dows )M[Ee].*\)/ && do {@os = "Windows ME"; last;};
            /\(.*Win(?:dows )98.*\)/ && do {@os = "Windows 98"; last;};
            /\(.*Win(?:dows )95.*\)/ && do {@os = "Windows 95"; last;};
            /\(.*Win(?:dows )16.*\)/ && do {@os = "Windows 3.1"; last;};
            /\(.*Win(?:dows[ -])NT.*\)/ && do {@os = "Windows NT"; last;};
            /\(.*Windows.*NT.*\)/ && do {@os = "Windows NT"; last;};
            /\(.*32bit.*\)/ && do {@os = "Windows 95"; last;};
            /\(.*16bit.*\)/ && do {@os = "Windows 3.1"; last;};
            /\(.*Mac OS 9.*\)/ && do {@os = "Mac System 9.x"; last;};
            /\(.*Mac OS 8\.6.*\)/ && do {@os = "Mac System 8.6"; last;};
            /\(.*Mac OS 8\.5.*\)/ && do {@os = "Mac System 8.5"; last;};
289
        # Bugzilla doesn't have an entry for 8.1
290 291 292 293 294 295
            /\(.*Mac OS 8\.1.*\)/ && do {@os = "Mac System 8.0"; last;};
            /\(.*Mac OS 8\.0.*\)/ && do {@os = "Mac System 8.0"; last;};
            /\(.*Mac OS 8[^.].*\)/ && do {@os = "Mac System 8.0"; last;};
            /\(.*Mac OS 8.*\)/ && do {@os = "Mac System 8.6"; last;};
            /\(.*Mac OS X.*\)/ && do {@os = "Mac OS X 10.0"; last;};
            /\(.*Darwin.*\)/ && do {@os = "Mac OS X 10.0"; last;};
296
        # Silly
297 298 299
            /\(.*Mac.*PowerPC.*\)/ && do {@os = "Mac System 9.x"; last;};
            /\(.*Mac.*PPC.*\)/ && do {@os = "Mac System 9.x"; last;};
            /\(.*Mac.*68k.*\)/ && do {@os = "Mac System 8.0"; last;};
300
        # Evil
301 302 303 304 305
            /Amiga/i && do {@os = "Other"; last;};
            /WinMosaic/ && do {@os = "Windows 95"; last;};
            /\(.*PowerPC.*\)/ && do {@os = "Mac System 9.x"; last;};
            /\(.*PPC.*\)/ && do {@os = "Mac System 9.x"; last;};
            /\(.*68K.*\)/ && do {@os = "Mac System 8.0"; last;};
306
        }
terry%netscape.com's avatar
terry%netscape.com committed
307
    }
308 309 310 311 312

    push(@os, "Windows") if grep(/^Windows /, @os);
    push(@os, "Mac OS") if grep(/^Mac /, @os);

    return pick_valid_field_value('op_sys', @os) || "Other";
terry%netscape.com's avatar
terry%netscape.com committed
313
}
314 315 316
##############################################################################
# End of subroutines
##############################################################################
terry%netscape.com's avatar
terry%netscape.com committed
317

318
Bugzilla->login(LOGIN_REQUIRED) if (!(AnyEntryGroups()));
terry%netscape.com's avatar
terry%netscape.com committed
319

320 321 322 323 324 325 326
# If a user is trying to clone a bug
#   Check that the user has authorization to view the parent bug
#   Create an instance of Bug that holds the info from the parent
$cloned_bug_id = $cgi->param('cloned_bug_id');

if ($cloned_bug_id) {
    ValidateBugID($cloned_bug_id);
327
    $cloned_bug = new Bugzilla::Bug($cloned_bug_id, Bugzilla->user->id);
328 329
}

330
# We need to check and make sure
331
# that the user has permission to enter a bug against this product.
332 333 334
my $prod_obj = new Bugzilla::Product({name => $product});
# Update the product name to get the correct case.
$product = $prod_obj->name if defined $prod_obj;
335
Bugzilla->user->can_enter_product($product, 1);
336

337
GetVersionTable();
terry%netscape.com's avatar
terry%netscape.com committed
338

339 340
my $product_id = get_product_id($product);

341
if (1 == @{$::components{$product}}) {
342
    # Only one component; just pick it.
343
    $cgi->param('component', $::components{$product}->[0]);
344 345
}

346
my @components;
347

348 349 350 351 352 353 354 355 356 357 358 359
my $dbh = Bugzilla->dbh;
my $sth = $dbh->prepare(
       q{SELECT name, description, p1.login_name, p2.login_name 
           FROM components 
      LEFT JOIN profiles p1 ON components.initialowner = p1.userid
      LEFT JOIN profiles p2 ON components.initialqacontact = p2.userid
          WHERE product_id = ?
          ORDER BY name});

$sth->execute($product_id);
while (my ($name, $description, $owner, $qacontact)
       = $sth->fetchrow_array()) {
360 361 362
    push @components, {
        name => $name,
        description => $description,
363 364
        initialowner => $owner,
        initialqacontact => $qacontact || '',
365
    };
366 367
}

368
my %default;
terry%netscape.com's avatar
terry%netscape.com committed
369

370 371 372 373 374 375 376 377 378
$vars->{'product'}               = $product;
$vars->{'component_'}            = \@components;

$vars->{'priority'}              = \@legal_priority;
$vars->{'bug_severity'}          = \@legal_severity;
$vars->{'rep_platform'}          = \@legal_platform;
$vars->{'op_sys'}                = \@legal_opsys; 

$vars->{'use_keywords'}          = 1 if (@::legal_keywords);
terry%netscape.com's avatar
terry%netscape.com committed
379

380 381 382
$vars->{'assigned_to'}           = formvalue('assigned_to');
$vars->{'assigned_to_disabled'}  = !UserInGroup('editbugs');
$vars->{'cc_disabled'}           = 0;
383

384 385 386
$vars->{'qa_contact'}           = formvalue('qa_contact');
$vars->{'qa_contact_disabled'}  = !UserInGroup('editbugs');

387
$vars->{'cloned_bug_id'}         = $cloned_bug_id;
388

389
if ($cloned_bug_id) {
390

391 392 393 394 395
    $default{'component_'}    = $cloned_bug->{'component'};
    $default{'priority'}      = $cloned_bug->{'priority'};
    $default{'bug_severity'}  = $cloned_bug->{'bug_severity'};
    $default{'rep_platform'}  = $cloned_bug->{'rep_platform'};
    $default{'op_sys'}        = $cloned_bug->{'op_sys'};
396

397 398
    $vars->{'short_desc'}     = $cloned_bug->{'short_desc'};
    $vars->{'bug_file_loc'}   = $cloned_bug->{'bug_file_loc'};
399
    $vars->{'keywords'}       = $cloned_bug->keywords;
400 401
    $vars->{'dependson'}      = $cloned_bug_id;
    $vars->{'blocked'}        = "";
402
    $vars->{'deadline'}       = $cloned_bug->{'deadline'};
403

404 405
    if (defined $cloned_bug->cc) {
        $vars->{'cc'}         = join (" ", @{$cloned_bug->cc});
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
    } else {
        $vars->{'cc'}         = formvalue('cc');
    }

# We need to ensure that we respect the 'insider' status of
# the first comment, if it has one. Either way, make a note
# that this bug was cloned from another bug.

    $cloned_bug->longdescs();
    my $isprivate             = $cloned_bug->{'longdescs'}->[0]->{'isprivate'};

    $vars->{'comment'}        = "";
    $vars->{'commentprivacy'} = 0;

    if ( !($isprivate) ||
         ( ( Param("insidergroup") ) && 
           ( UserInGroup(Param("insidergroup")) ) ) 
       ) {
        $vars->{'comment'}        = $cloned_bug->{'longdescs'}->[0]->{'body'};
        $vars->{'commentprivacy'} = $isprivate;
    }
427

428 429
# Ensure that the groupset information is set up for later use.
    $cloned_bug->groups();
430

431
} # end of cloned bug entry form
432

433
else {
434

435 436 437 438 439 440 441 442 443 444 445
    $default{'component_'}    = formvalue('component');
    $default{'priority'}      = formvalue('priority', Param('defaultpriority'));
    $default{'bug_severity'}  = formvalue('bug_severity', Param('defaultseverity'));
    $default{'rep_platform'}  = pickplatform();
    $default{'op_sys'}        = pickos();

    $vars->{'short_desc'}     = formvalue('short_desc');
    $vars->{'bug_file_loc'}   = formvalue('bug_file_loc', "http://");
    $vars->{'keywords'}       = formvalue('keywords');
    $vars->{'dependson'}      = formvalue('dependson');
    $vars->{'blocked'}        = formvalue('blocked');
446
    $vars->{'deadline'}       = formvalue('deadline');
447

448
    $vars->{'cc'}             = join(', ', $cgi->param('cc'));
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466

    $vars->{'comment'}        = formvalue('comment');
    $vars->{'commentprivacy'} = formvalue('commentprivacy');

} # end of normal/bookmarked entry form


# IF this is a cloned bug,
# AND the clone's product is the same as the parent's
#   THEN use the version from the parent bug
# ELSE IF a version is supplied in the URL
#   THEN use it
# ELSE IF there is a version in the cookie
#   THEN use it (Posting a bug sets a cookie for the current version.)
# ELSE
#   The default version is the last one in the list (which, it is
#   hoped, will be the most recent one).
#
467 468
# Eventually maybe each product should have a "current version"
# parameter.
469
$vars->{'version'} = $::versions{$product} || [];
470 471 472 473 474

if ( ($cloned_bug_id) &&
     ("$product" eq "$cloned_bug->{'product'}" ) ) {
    $default{'version'} = $cloned_bug->{'version'};
} elsif (formvalue('version')) {
475
    $default{'version'} = formvalue('version');
476 477 478
} elsif (defined $cgi->cookie("VERSION-$product") &&
    lsearch($vars->{'version'}, $cgi->cookie("VERSION-$product")) != -1) {
    $default{'version'} = $cgi->cookie("VERSION-$product");
479 480 481
} else {
    $default{'version'} = $vars->{'version'}->[$#{$vars->{'version'}}];
}
482

483 484 485
# Only used with placeholders below
trick_taint($product);

486 487 488 489 490 491
# Get list of milestones.
if ( Param('usetargetmilestone') ) {
    $vars->{'target_milestone'} = $::target_milestone{$product};
    if (formvalue('target_milestone')) {
       $default{'target_milestone'} = formvalue('target_milestone');
    } else {
492 493 494
       $default{'target_milestone'} =
                $dbh->selectrow_array('SELECT defaultmilestone FROM products
                                       WHERE name = ?', undef, $product);
495 496 497 498
    }
}


499 500
# List of status values for drop-down.
my @status;
501

502 503 504 505 506 507 508
# Construct the list of allowable values.  There are three cases:
# 
#  case                                 values
#  product does not have confirmation   NEW
#  confirmation, user cannot confirm    UNCONFIRMED
#  confirmation, user can confirm       NEW, UNCONFIRMED.

509 510 511
my $votestoconfirm = $dbh->selectrow_array('SELECT votestoconfirm FROM products
                                            WHERE name = ?', undef, $product);
if ($votestoconfirm) {
512 513 514
    if (UserInGroup("editbugs") || UserInGroup("canconfirm")) {
        push(@status, "NEW");
    }
515
    push(@status, 'UNCONFIRMED');
516 517
} else {
    push(@status, "NEW");
518 519
}

520
$vars->{'bug_status'} = \@status; 
521

522 523 524 525 526 527 528 529 530
# Get the default from a template value if it is legitimate.
# Otherwise, set the default to the first item on the list.

if (formvalue('bug_status') && (lsearch(\@status, formvalue('bug_status')) >= 0)) {
    $default{'bug_status'} = formvalue('bug_status');
} else {
    $default{'bug_status'} = $status[0];
}
 
531 532 533 534 535 536 537 538
my $grouplist = $dbh->selectall_arrayref(
                  q{SELECT DISTINCT groups.id, groups.name, groups.description,
                                    membercontrol, othercontrol
                      FROM groups
                 LEFT JOIN group_control_map
                        ON group_id = id AND product_id = ?
                     WHERE isbuggroup != 0 AND isactive != 0
                  ORDER BY description}, undef, $product_id);
539

540
my @groups;
541

542 543
foreach my $row (@$grouplist) {
    my ($id, $groupname, $description, $membercontrol, $othercontrol) = @$row;
544 545 546 547 548 549 550 551
    # Only include groups if the entering user will have an option.
    next if ((!$membercontrol) 
               || ($membercontrol == CONTROLMAPNA) 
               || ($membercontrol == CONTROLMAPMANDATORY)
               || (($othercontrol != CONTROLMAPSHOWN) 
                    && ($othercontrol != CONTROLMAPDEFAULT)
                    && (!UserInGroup($groupname)))
             );
552 553
    my $check;

554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
    # If this is a cloned bug, 
    # AND the product for this bug is the same as for the original
    #   THEN set a group's checkbox if the original also had it on
    # ELSE IF this is a bookmarked template
    #   THEN set a group's checkbox if was set in the bookmark
    # ELSE
    #   set a groups's checkbox based on the group control map
    #
    if ( ($cloned_bug_id) &&
         ("$product" eq "$cloned_bug->{'product'}" ) ) {
        foreach my $i (0..(@{$cloned_bug->{'groups'}}-1) ) {
            if ($cloned_bug->{'groups'}->[$i]->{'bit'} == $id) {
                $check = $cloned_bug->{'groups'}->[$i]->{'ison'};
            }
        }
    }
    elsif(formvalue("maketemplate") ne "") {
571 572 573
        $check = formvalue("bit-$id", 0);
    }
    else {
574 575 576 577
        # Checkbox is checked by default if $control is a default state.
        $check = (($membercontrol == CONTROLMAPDEFAULT)
                 || (($othercontrol == CONTROLMAPDEFAULT)
                      && (!UserInGroup($groupname))));
578 579
    }

580 581 582 583 584 585 586 587
    my $group = 
    {
        'bit' => $id , 
        'checked' => $check , 
        'description' => $description 
    };

    push @groups, $group;        
588
}
terry%netscape.com's avatar
terry%netscape.com committed
589

590 591
$vars->{'group'} = \@groups;

592
$vars->{'default'} = \%default;
terry%netscape.com's avatar
terry%netscape.com committed
593

594 595 596
my $format = $template->get_format("bug/create/create",
                                   scalar $cgi->param('format'), 
                                   scalar $cgi->param('ctype'));
597

598
print $cgi->header($format->{'ctype'});
599
$template->process($format->{'template'}, $vars)
600
  || ThrowTemplateError($template->error());          
601