importxml.pl 22.1 KB
Newer Older
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
#!/usr/bonsaitools/bin/perl -w 
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# 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.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Dawn Endico <endico@mozilla.org>


# This script reads in xml bug data from standard input and inserts 
# a new bug into bugzilla. Everything before the beginning <?xml line
# is removed so you can pipe in email messages.

use diagnostics;
use strict;

31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
#####################################################################
#
# This script is used import bugs from another installation of bugzilla.
# Moving a bug on another system will send mail to an alias provided by
# the administrator of the target installation (you). Set up an alias
# similar to the one given below so this mail will be automatically 
# run by this script and imported into your database.  Run 'newaliases'
# after adding this alias to your aliases file. Make sure your sendmail
# installation is configured to allow mail aliases to execute code. 
#
# bugzilla-import: "|/usr/bin/perl /opt/bugzilla/importxml.pl"
#
#####################################################################


46 47 48
# figure out which path this script lives in. Set the current path to
# this and add it to @INC so this will work when run as part of mail
# alias by the mailer daemon
49 50 51 52 53
# since "use lib" is run at compile time, we need to enclose the
# $::path declaration in a BEGIN block so that it is executed before
# the rest of the file is compiled.
BEGIN {
 $::path = $0;
54 55
 $::path =~ m#(.*)/[^/]+#;
 $::path = $1;
56 57
 $::path ||= '.';  # $0 is empty at compile time.  This line will
                   # have no effect on this script at runtime.
58
}
59

60 61
chdir $::path;
use lib ($::path);
62

63 64 65 66 67 68 69 70
use XML::Parser;
use Data::Dumper;
$Data::Dumper::Useqq = 1;

require "CGI.pl";
require "globals.pl";
$::lockcount = 0;

71 72 73
GetVersionTable();
ConnectToDatabase();

74

75 76
sub sillyness {
    my $zz;
77
    $zz = $Data::Dumper::Useqq;
78 79
    $zz = %::components;
    $zz = %::versions;
80
    $zz = %::keywordsbyname;
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
    $zz = @::legal_bug_status;
    $zz = @::legal_opsys;
    $zz = @::legal_platform;
    $zz = @::legal_priority;
    $zz = @::legal_product;
    $zz = @::legal_severity;
    $zz = @::legal_resolution;
    $zz = %::target_milestone;
}

sub UnQuoteXMLChars {
    $_[0] =~ s/&amp;/&/g;
    $_[0] =~ s/&lt;/</g;
    $_[0] =~ s/&gt;/>/g;
    $_[0] =~ s/&apos;/'/g;
    $_[0] =~ s/&quot;/"/g;
#    $_[0] =~ s/([\x80-\xFF])/&XmlUtf8Encode(ord($1))/ge;
    return($_[0]);
}

101 102 103 104 105 106 107
sub MailMessage {
  my $subject = shift @_;
  my $message = shift @_;
  my @recipients = @_;

  my $to = join (", ", @recipients);
  my $header = "To: $to\n";
108 109 110
  my $from = Param("moved-from-address");
  $from =~ s/@/\@/g;
  $header.= "From: Bugzilla <$from>\n";
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
  $header.= "Subject: $subject\n\n";

  open(SENDMAIL,
    "|/usr/lib/sendmail -ODeliveryMode=background -t") ||
      die "Can't open sendmail";
  print SENDMAIL $header . $message . "\n";
  close SENDMAIL;

  Log($subject . " sent to: $to");
}


sub Log {
    my ($str) = (@_);
    Lock();
    open(FID, ">>data/maillog") || die "Can't write to data/maillog";
    print FID time2str("%D %H:%M", time()) . ": $str\n";
    close FID;
    Unlock();
}

sub Lock {
    if ($::lockcount <= 0) {
        $::lockcount = 0;
        if (!open(LOCKFID, ">>data/maillock")) {
            mkdir "data", 0777;
            chmod 0777, "data";
            open(LOCKFID, ">>data/maillock") || die "Can't open lockfile.";
        }
        my $val = flock(LOCKFID,2);
        if (!$val) { # '2' is magic 'exclusive lock' const.
            print "Content-type: text/html\n\n";
            print "Lock failed: $val\n";
        }
        chmod 0666, "data/maillock";
    }
    $::lockcount++;
}

sub Unlock {
    $::lockcount--;
    if ($::lockcount <= 0) {
        flock(LOCKFID,8);       # '8' is magic 'unlock' const.
        close LOCKFID;
    }
}


159 160 161 162 163 164 165 166 167 168 169 170 171 172
my $xml;
while (<>) {
 $xml .= $_;
}
# remove everything in file before xml header (i.e. remove the mail header)
$xml =~ s/^.+(<\?xml version.+)$/$1/s;

my $parser = new XML::Parser(Style => 'Tree');
my $tree = $parser->parse($xml);

my $maintainer;
if (defined $tree->[1][0]->{'maintainer'}) {
  $maintainer= $tree->[1][0]->{'maintainer'}; 
} else {
173 174 175
  my $subject = "Bug import error: no maintainer";
  my $message = "Cannot import these bugs because no maintainer for "; 
  $message .=   "the exporting db is given.\n";
176
  $message .=   "\n\nPlease re-open the original bug.\n";
177 178 179
  $message .= "\n\n$xml";
  my @to = (Param("maintainer"));
  MailMessage ($subject, $message, @to);
180 181 182 183 184 185 186
  exit;
}

my $exporter;
if (defined $tree->[1][0]->{'exporter'}) {
  $exporter = $tree->[1][0]->{'exporter'};
} else {
187 188
  my $subject = "Bug import error: no exporter";
  my $message = "Cannot import these bugs because no exporter is given.\n";
189
  $message .=   "\n\nPlease re-open the original bug.\n";
190 191 192 193 194 195
  $message .= "\n\n$xml";
  my @to = (Param("maintainer"), $maintainer);
  MailMessage ($subject, $message, @to);
  exit;
}

196 197 198 199 200 201 202 203 204 205 206

unless ( Param("move-enabled") ) {
  my $subject = "Error: bug importing is disabled here";
  my $message = "Cannot import these bugs because importing is disabled\n";
  $message .= "at this site. For more info, contact ";
  $message .=  Param("maintainer") . ".\n";
  my @to = (Param("maintainer"), $maintainer, $exporter);
  MailMessage ($subject, $message, @to);
  exit;
}

207 208 209 210 211
my $exporterid = DBname_to_id($exporter);
if ( ! $exporterid ) {
  my $subject = "Bug import error: invalid exporter";
  my $message = "The user <$tree->[1][0]->{'exporter'}> who tried to move\n";
  $message .= "bugs here does not have an account in this database.\n";
212
  $message .= "\n\nPlease re-open the original bug.\n";
213
  $message .= "\n\n$xml";
214
  my @to = (Param("maintainer"), $maintainer, $exporter);
215
  MailMessage ($subject, $message, @to);
216 217 218 219 220 221 222
  exit;
}

my $urlbase;
if (defined $tree->[1][0]->{'urlbase'}) {
  $urlbase= $tree->[1][0]->{'urlbase'}; 
} else {
223 224
  my $subject = "Bug import error: invalid exporting database";
  my $message = "Cannot import these bugs because the name of the exporting db was not given.\n";
225
  $message .= "\n\nPlease re-open the original bug.\n";
226 227 228
  $message .= "\n\n$xml";
  my @to = (Param("maintainer"), $maintainer, $exporter);
  MailMessage ($subject, $message, @to);
229 230 231 232
  exit;
}
  

233
my $bugqty = ($#{@{$tree}->[1]} +1 -3) / 4;
234
my $log = "Imported $bugqty bug(s) from $urlbase,\n  sent by $exporter.\n\n";
235 236 237 238
for (my $k=1 ; $k <= $bugqty ; $k++) {
  my $cur = $k*4;

  if (defined $tree->[1][$cur][0]->{'error'}) {
239 240
    $log .= "\nError in bug $tree->[1][$cur][4][2]\@$urlbase:";
    $log .= " $tree->[1][$cur][0]->{'error'}\n";
241
    if ($tree->[1][$cur][0]->{'error'} =~ /NotFound/) {
242 243
      $log .= "$exporter tried to move bug $tree->[1][$cur][4][2] here";
      $log .= " but $urlbase reports that this bug does not exist.\n"; 
244
    } elsif ( $tree->[1][$cur][0]->{'error'} =~ /NotPermitted/) {
245 246 247
      $log .= "$exporter tried to move bug $tree->[1][$cur][4][2] here";
      $log .= " but $urlbase reports that $exporter does not have access";
      $log .= " to that bug.\n";
248 249 250 251 252 253 254 255 256 257
    }
    next;
  }

  my %multiple_fields;
  foreach my $field (qw (dependson cc long_desc blocks)) {
    $multiple_fields{$field} = "x"; 
  }
  my %all_fields;
  foreach my $field (qw (dependson product bug_status priority cc version 
258
      bug_id rep_platform short_desc assigned_to bug_file_loc resolution
259
      delta_ts component reporter urlbase target_milestone bug_severity 
260
      creation_ts qa_contact keywords status_whiteboard op_sys blocks)) {
261 262
    $all_fields{$field} = "x"; 
  }
263 264
 
 
265 266 267 268 269 270 271 272
  my %bug_fields;
  my $err = "";
  for (my $i=3 ; $i < $#{@{$tree}->[1][$cur]} ; $i=$i+4) {
    if (defined $multiple_fields{$tree->[1][$cur][$i]}) {
      if (defined $bug_fields{$tree->[1][$cur][$i]}) {
        $bug_fields{$tree->[1][$cur][$i]} .= " " .  $tree->[1][$cur][$i+1][2];
      } else {
        $bug_fields{$tree->[1][$cur][$i]} = $tree->[1][$cur][$i+1][2];
273
      }
274 275
    } elsif (defined $all_fields{$tree->[1][$cur][$i]}) {
      $bug_fields{$tree->[1][$cur][$i]} = $tree->[1][$cur][$i+1][2];
276
    } else {
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
      $err .= "---\n";
      $err .= "Unknown bug field \"$tree->[1][$cur][$i]\"";
      $err .= " encountered while moving bug\n";
      $err .= "<$tree->[1][$cur][$i]>";
      if (defined $tree->[1][$cur][$i+1][3]) {
        $err .= "\n";
        for (my $j=3 ; $j < $#{@{$tree}->[1][$cur][$i+1]} ; $j=$j+4) {
          $err .= "  <". $tree->[1][$cur][$i+1][$j] . ">";
          $err .= " $tree->[1][$cur][$i+1][$j+1][2] ";
          $err .= "</". $tree->[1][$cur][$i+1][$j] . ">\n";
        }
      } else {
        $err .= " $tree->[1][$cur][$i+1][2] ";
      }
      $err .= "</$tree->[1][$cur][$i]>\n";
292 293 294
    }
  }

295 296 297 298 299 300 301 302 303
  my @long_descs;
  for (my $i=3 ; $i < $#{@{$tree}->[1][$cur]} ; $i=$i+4) {
    if ($tree->[1][$cur][$i] =~ /long_desc/) {
      my %long_desc;
      $long_desc{'who'} = $tree->[1][$cur][$i+1][4][2];
      $long_desc{'bug_when'} = $tree->[1][$cur][$i+1][8][2];
      $long_desc{'thetext'} = $tree->[1][$cur][$i+1][12][2];
      push @long_descs, \%long_desc;
    }
304 305
  }

306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
  # instead of giving each comment its own item in the longdescs
  # table like it should have, lets cat them all into one big
  # comment otherwise we would have to lie often about who
  # authored the comment since commenters in one bugzilla probably
  # don't have accounts in the other one.
  sub by_date {my @a; my @b; $a->{'bug_when'} cmp $b->{'bug_when'}; }
  my @sorted_descs = sort by_date @long_descs;
  my $long_description = "";
  for (my $z=0 ; $z <= $#sorted_descs ; $z++) {
    unless ( $z==0 ) {
      $long_description .= "\n\n\n------- Additional Comments From ";
      $long_description .= "$sorted_descs[$z]->{'who'} "; 
      $long_description .= "$sorted_descs[$z]->{'bug_when'}"; 
      $long_description .= " ----\n\n";
    }
321 322
    $long_description .=  UnQuoteXMLChars($sorted_descs[$z]->{'thetext'});
    $long_description .=  "\n";
323 324
  }

325 326
  my $comments;

327
  $comments .= "\n\n------- Bug moved to this database by $exporter "; 
328 329 330 331 332 333 334 335 336 337 338 339 340 341
  $comments .= time2str("%Y-%m-%d %H:%M", time);
  $comments .= " -------\n\n";
  $comments .= "This bug previously known as bug $bug_fields{'bug_id'} at ";
  $comments .= $urlbase . "\n";
  $comments .= $urlbase . "show_bug.cgi?";
  $comments .= "id=" . $bug_fields{'bug_id'} . "\n";
  $comments .= "Originally filed under the $bug_fields{'product'} ";
  $comments .= "product and $bug_fields{'component'} component.\n";
  if (defined $bug_fields{'dependson'}) {
    $comments .= "Bug depends on bug(s) $bug_fields{'dependson'}.\n";
  }
  if (defined $bug_fields{'blocks'}) {
  $comments .= "Bug blocks bug(s) $bug_fields{'blocks'}.\n";
  }
342

343 344 345
  my @query = ();
  my @values = ();
  foreach my $field ( qw(creation_ts delta_ts status_whiteboard) ) {
346
      if ( (defined $bug_fields{$field}) && ($bug_fields{$field}) ){
347 348
        push (@query, "$field");
        push (@values, SqlQuote($bug_fields{$field}));
349 350
      }
  }
351

352
  if ( (defined $bug_fields{'bug_file_loc'}) && ($bug_fields{'bug_file_loc'}) ){
353 354
      push (@query, "bug_file_loc");
      push (@values, SqlQuote(UnQuoteXMLChars($bug_fields{'bug_file_loc'})));
355 356
      }

357
  if ( (defined $bug_fields{'short_desc'}) && ($bug_fields{'short_desc'}) ){
358 359
      push (@query, "short_desc");
      push (@values, SqlQuote(UnQuoteXMLChars($bug_fields{'short_desc'})) );
360
      }
361

362 363 364 365 366 367 368 369 370 371 372 373 374 375

  my $prod;
  my $comp;
  my $default_prod = Param("moved-default-product");
  my $default_comp = Param("moved-default-component");
  if ( (defined ($bug_fields{'product'})) &&
       (defined ($bug_fields{'component'})) ) {
     $prod = $bug_fields{'product'};
     $comp = $bug_fields{'component'};
  } else {
     $prod = $default_prod;
     $comp = $default_comp;
  }

376
  my @product;
377 378 379 380 381 382 383 384 385 386 387 388 389
  my @component;
  if ((@product = grep /^$prod$/i, @::legal_product) &&
      (@component = grep /^$comp$/i, @{$::components{$product[0]}}) ) {
    push (@query, "product");
    push (@values, SqlQuote($product[0]) );
    push (@query, "component");
    push (@values, SqlQuote($component[0]) );
  } elsif ((@product = grep /^$default_prod$/i, @::legal_product) &&
      (@component = grep /^$default_comp$/i, @{$::components{$product[0]}}) ) {
    push (@query, "product");
    push (@values, SqlQuote($product[0]) );
    push (@query, "component");
    push (@values, SqlQuote($component[0]) );
390
  } else {
391 392 393 394 395 396 397 398 399 400
    my $subject = "Bug import error: invalid default product or component";
    my $message = "Cannot import these bugs because an invalid default ";
    $message .= "product and/or component was defined for the target db.\n";
    $message .= Param("maintainer") . " needs to fix the definitions of ";
    $message .= "moved-default-product and moved-default-component.\n";
    $message .= "\n\nPlease re-open the original bug.\n";
    $message .= "\n\n$xml";
    my @to = (Param("maintainer"), $maintainer, $exporter);
    MailMessage ($subject, $message, @to);
    exit;
401
  }
402

403 404 405
  if (defined  ($::versions{$product[0]} ) &&
     (my @version = grep /^$bug_fields{'version'}$/i, 
                         @{$::versions{$product[0]}}) ){
406 407
    push (@values, SqlQuote($version[0]) );
    push (@query, "version");
408
  } else {
409 410
    push (@query, "version");
    push (@values, SqlQuote(@{$::versions{$product[0]}}->[0]));
411 412 413
    $err .= "Unknown version $bug_fields{'version'} in product $product[0]. ";
    $err .= "Setting version to \"@{$::versions{$product[0]}}->[0]\".\n";
  }
414

415 416
  if (defined ($bug_fields{'priority'}) &&
       (my @priority = grep /^$bug_fields{'priority'}$/i, @::legal_priority) ){
417 418
    push (@values, SqlQuote($priority[0]) );
    push (@query, "priority");
419
  } else {
420 421
    push (@values, SqlQuote("P3"));
    push (@query, "priority");
422 423 424 425
    $err .= "Unknown priority ";
    $err .= (defined $bug_fields{'priority'})?$bug_fields{'priority'}:"unknown";
    $err .= ". Setting to default priority \"P3\".\n";
  }
426

427 428
  if (defined ($bug_fields{'rep_platform'}) &&
       (my @platform = grep /^$bug_fields{'rep_platform'}$/i, @::legal_platform) ){
429 430
    push (@values, SqlQuote($platform[0]) );
    push (@query, "rep_platform");
431
  } else {
432 433
    push (@values, SqlQuote("Other") );
    push (@query, "rep_platform");
434 435 436 437 438
    $err .= "Unknown platform ";
    $err .= (defined $bug_fields{'rep_platform'})?
                     $bug_fields{'rep_platform'}:"unknown";
    $err .= ". Setting to default platform \"Other\".\n";
  }
439

440
  if (defined ($bug_fields{'op_sys'}) &&
441
     (my @opsys = grep /^$bug_fields{'op_sys'}$/i, @::legal_opsys) ){
442 443
    push (@values, SqlQuote($opsys[0]) );
    push (@query, "op_sys");
444
  } else {
445 446
    push (@values, SqlQuote("other"));
    push (@query, "op_sys");
447 448 449 450
    $err .= "Unknown operating system ";
    $err .= (defined $bug_fields{'op_sys'})?$bug_fields{'op_sys'}:"unknown";
    $err .= ". Setting to default OS \"other\".\n";
  }
451

452 453 454 455
  if (Param("usetargetmilestone")) {
    if (defined  ($::target_milestone{$product[0]} ) &&
       (my @tm = grep /^$bug_fields{'target_milestone'}$/i, 
                       @{$::target_milestone{$product[0]}}) ){
456 457
      push (@values, SqlQuote($tm[0]) );
      push (@query, "target_milestone");
458 459 460 461
    } else {
      SendSQL("SELECT defaultmilestone FROM products " .
              "WHERE product = " . SqlQuote($product[0]));
      my $tm = FetchOneColumn();
462 463
      push (@values, SqlQuote($tm));
      push (@query, "target_milestone");
464 465 466 467 468 469 470 471
      $err .= "Unknown milestone \"";
      $err .= (defined $bug_fields{'target_milestone'})?
              $bug_fields{'target_milestone'}:"unknown";
      $err .= "\" in product \"$product[0]\".\n";
      $err .= "   Setting to default milestone for this product, ";
      $err .= "\'" . $tm . "\'\n";
    }
  }
472

473 474 475
  if (defined ($bug_fields{'bug_severity'}) &&
       (my @severity= grep /^$bug_fields{'bug_severity'}$/i, 
                           @::legal_severity) ){
476 477
    push (@values, SqlQuote($severity[0]) );
    push (@query, "bug_severity");
478
  } else {
479 480
    push (@values, SqlQuote("normal"));
    push (@query, "bug_severity");
481 482 483 484
    $err .= "Unknown severity ";
    $err .= (defined $bug_fields{'bug_severity'})?
                     $bug_fields{'bug_severity'}:"unknown";
    $err .= ". Setting to default severity \"normal\".\n";
485 486
  }

487 488
  my $reporterid = DBname_to_id($bug_fields{'reporter'});
  if ( ($bug_fields{'reporter'}) && ( $reporterid ) ) {
489 490
    push (@values, SqlQuote($reporterid));
    push (@query, "reporter");
491
  } else {
492 493
    push (@values, SqlQuote($exporterid));
    push (@query, "reporter");
494 495 496 497 498 499 500 501 502 503
    $err .= "The original reporter of this bug does not have\n";
    $err .= "   an account here. Reassigning to the person who moved\n";
    $err .= "   it here, $exporter.\n";
    if ( $bug_fields{'reporter'} ) {
      $err .= "   Previous reporter was $bug_fields{'reporter'}.\n";
    } else {
      $err .= "   Previous reporter is unknown.\n";
    }
  }

504 505 506
  my $changed_owner = 0;
  if ( ($bug_fields{'assigned_to'}) && 
       ( DBname_to_id($bug_fields{'assigned_to'})) ) {
507 508
    push (@values, SqlQuote(DBname_to_id($bug_fields{'assigned_to'})));
    push (@query, "assigned_to");
509
  } else {
510 511
    push (@values, SqlQuote($exporterid) );
    push (@query, "assigned_to");
512 513 514
    $changed_owner = 1;
    $err .= "The original owner of this bug does not have\n";
    $err .= "   an account here. Reassigning to the person who moved\n";
515
    $err .= "   it here, $exporter.\n";
516 517 518 519 520 521
    if ( $bug_fields{'assigned_to'} ) {
      $err .= "   Previous owner was $bug_fields{'assigned_to'}.\n";
    } else {
      $err .= "   Previous owner is unknown.\n";
    }
  }
522

523 524 525
  my @resolution;
  if (defined ($bug_fields{'resolution'}) &&
       (@resolution= grep /^$bug_fields{'resolution'}$/i, @::legal_resolution) ){
526 527
    push (@values, SqlQuote($resolution[0]) );
    push (@query, "resolution");
528 529 530
  } elsif ( (defined $bug_fields{'resolution'}) && (!$resolution[0]) ){
    $err .= "Unknown resolution \"$bug_fields{'resolution'}\".\n";
  }
531

532 533 534 535
  # if the bug's owner changed, mark the bug NEW, unless a valid 
  # resolution is set, which indicates that the bug should be closed.
  #
  if ( ($changed_owner) && (!$resolution[0]) ) {
536 537
    push (@values, SqlQuote("NEW"));
    push (@query, "bug_status");
538 539 540 541 542 543 544
    $err .= "Bug assigned to new owner, setting status to \"NEW\".\n";
    $err .= "   Previous status was \"";
    $err .= (defined $bug_fields{'bug_status'})?
                     $bug_fields{'bug_status'}:"unknown";
    $err .= "\".\n";
  } elsif ( (defined ($bug_fields{'resolution'})) && (!$resolution[0]) ){
    #if the resolution was illegal then set status to NEW
545 546
    push (@values, SqlQuote("NEW"));
    push (@query, "bug_status");
547 548 549 550 551 552 553 554
    $err .= "Resolution was invalid. Setting status to \"NEW\".\n";
    $err .= "   Previous status was \"";
    $err .= (defined $bug_fields{'bug_status'})?
                     $bug_fields{'bug_status'}:"unknown";
    $err .= "\".\n";
  } elsif (defined ($bug_fields{'bug_status'}) &&
       (my @status = grep /^$bug_fields{'bug_status'}$/i, @::legal_bug_status) ){
    #if a bug status was set then use it, if its legal
555 556
    push (@values, SqlQuote($status[0]));
    push (@query, "bug_status");
557
  } else {
558
    # if all else fails, make the bug new
559 560
    push (@values, SqlQuote("NEW"));
    push (@query, "bug_status");
561 562 563 564
    $err .= "Unknown status ";
    $err .= (defined $bug_fields{'bug_status'})?
                     $bug_fields{'bug_status'}:"unknown";
    $err .= ". Setting to default status \"NEW\".\n";
565 566
  }

567 568 569 570
  if (Param("useqacontact")) {
    my $qa_contact;
    if ( (defined $bug_fields{'qa_contact'}) &&
         ($qa_contact  = DBname_to_id($bug_fields{'qa_contact'})) ){
571 572
      push (@values, SqlQuote($qa_contact));
      push (@query, "qa_contact");
573 574 575 576 577
    } else {
      SendSQL("select initialqacontact from components where program=" .
              SqlQuote($product[0]) .
              " and value=" . SqlQuote($component[0]) );
      $qa_contact = FetchOneColumn();
578 579
      push (@values, SqlQuote(DBname_to_id($qa_contact)) );
      push (@query, "qa_contact");
580 581 582 583
      $err .= "Setting qa contact to the default for this product.\n";
      $err .= "   This bug either had no qa contact or an invalid one.\n";
    }
  }
584

585 586 587 588 589 590

  my $query  = "INSERT INTO bugs (\n" 
               . join (",\n", @query)
               . "\n) VALUES (\n"
               . join (",\n", @values)
               . "\n)\n";
591 592 593 594 595 596 597 598 599 600 601
  SendSQL($query);
  SendSQL("select LAST_INSERT_ID()");
  my $id = FetchOneColumn();

  if (defined $bug_fields{'cc'}) {
    foreach my $person (split(/[ ,]/, $bug_fields{'cc'})) {
      my $uid;
      if ( ($person ne "") && ($uid = DBname_to_id($person)) ) {
        SendSQL("insert into cc (bug_id, who) values ($id, " . SqlQuote($uid) .")");
      }
    }
602 603
  }

604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621
  if (defined ($bug_fields{'keywords'})) {
    my %keywordseen;
    foreach my $keyword (split(/[\s,]+/, $bug_fields{'keywords'})) {
      if ($keyword eq '') {
        next;
      }
      my $i = $::keywordsbyname{$keyword};
      if (!$i) {
        $err .= "Skipping unknown keyword: $keyword.\n";
        next;
      }
      if (!$keywordseen{$i}) {
        SendSQL("INSERT INTO keywords (bug_id, keywordid) VALUES ($id, $i)");
        $keywordseen{$i} = 1;
      }
    }
  }

622 623 624 625
  $long_description .= "\n" . $comments;
  if ($err) {
    $long_description .= "\n$err\n";
  }
626

627 628
  SendSQL("INSERT INTO longdescs (bug_id, who, bug_when, thetext) VALUES " .
    "($id, $exporterid, now(), " . SqlQuote($long_description) . ")");
629

630 631 632
  $log .= "Bug $urlbase/show_bug.cgi?id=$bug_fields{'bug_id'} ";
  $log .= "imported as bug $id.\n";
  $log .= Param("urlbase") . "/show_bug.cgi?id=$id\n\n";
633
  if ($err) {
634 635
    $log .= "The following problems were encountered creating bug $id.\n";
    $log .= "You may have to set certain fields in the new bug by hand.\n\n";
636
    $log .= $err;
637
    $log .= "\n\n\n";
638
  }
639 640

  system("./processmail", $id, $exporter);
641
}
642

643 644
my $subject = "$bugqty bug(s) successfully moved from $urlbase to " 
               . Param("urlbase") ;
645 646
my @to = ($exporter);
MailMessage ($subject, $log, @to);