]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
experimental: Not part of normal bugzilla distibution. Bug.pm creates a bug object...
authorendico%mozilla.org <>
Fri, 9 Jun 2000 03:30:10 +0000 (03:30 +0000)
committerendico%mozilla.org <>
Fri, 9 Jun 2000 03:30:10 +0000 (03:30 +0000)
Bug.pm [new file with mode: 0755]
Bugzilla/Bug.pm [new file with mode: 0755]
export_bug.cgi
importxml.pl
xml.cgi [new file with mode: 0755]

diff --git a/Bug.pm b/Bug.pm
new file mode 100755 (executable)
index 0000000..2488574
--- /dev/null
+++ b/Bug.pm
@@ -0,0 +1,369 @@
+#!/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>
+#                 Terry Weissman <terry@mozilla.org>
+
+use diagnostics;
+use strict;
+
+use DBI;
+use RelationSet;
+require "globals.pl";
+require "CGI.pl";
+package Bug;
+use CGI::Carp qw(fatalsToBrowser);
+my %bug;
+my %ok_field;
+
+for my $key (qw (bug_id product version rep_platform op_sys bug_status 
+                resolution priority bug_severity component assigned_to
+                reporter bug_file_loc short_desc target_milestone 
+                qa_contact status_whiteboard creation_ts groupset 
+                delta_ts votes) ){
+    $ok_field{$key}++;
+    }
+
+# create a new empty bug
+#
+sub new {
+  my $type = shift();
+
+  # create a ref to an empty hash and bless it
+  #
+  my $self = {%bug};
+  bless $self, $type;
+
+  # construct from a hash containing a bug's info
+  #
+  if ($#_ == 1) {
+    $self->initBug(@_);
+  } else {
+    confess("invalid number of arguments \($#_\)($_)");
+  }
+
+  # bless as a Bug
+  #
+  return $self;
+}
+
+
+
+# dump info about bug into hash unless user doesn't have permission
+# user_id 0 is used when person is not logged in.
+#
+sub initBug  {
+  my $self = shift();
+  my ($bug_id, $user_id) = (@_);
+
+
+  if ( (! defined $bug_id) || (!$bug_id) ) {
+    # no bug number given
+    return {};
+  }
+
+  if (! defined $user_id) {
+    $user_id = 0;
+  }
+
+  &::ConnectToDatabase();
+  &::GetVersionTable();
+
+  # this verification should already have been done by caller
+  # my $loginok = quietly_check_login();
+  my $usergroupset = "0";
+  if (defined $::usergroupset) {
+    $usergroupset = $::usergroupset;
+  }
+
+  my $query = "
+    select
+      bugs.bug_id, product, version, rep_platform, op_sys, bug_status,
+      resolution, priority, bug_severity, component, assigned_to, reporter,
+      bug_file_loc, short_desc, target_milestone, qa_contact,
+      status_whiteboard, date_format(creation_ts,'%Y-%m-%d %H:%i'),
+      groupset, delta_ts, sum(votes.count)
+    from bugs left join votes using(bug_id)
+    where bugs.bug_id = $bug_id
+    and bugs.groupset & $usergroupset = bugs.groupset
+    group by bugs.bug_id";
+
+  &::SendSQL($query);
+  my @row;
+
+  if (@row = &::FetchSQLData()) {
+    my $count = 0;
+    my %fields;
+    foreach my $field ("bug_id", "product", "version", "rep_platform",
+                       "op_sys", "bug_status", "resolution", "priority",
+                       "bug_severity", "component", "assigned_to", "reporter",
+                       "bug_file_loc", "short_desc", "target_milestone",
+                       "qa_contact", "status_whiteboard", "creation_ts",
+                       "groupset", "delta_ts", "votes") {
+       $fields{$field} = shift @row;
+       if ($fields{$field}) {
+           $bug{$field} = $fields{$field};
+       }
+       $count++;
+    }
+  } else {
+    &::SendSQL("select groupset from bugs where bug_id = $bug_id");
+    if (@row = &::FetchSQLData()) {
+      $bug{'bug_id'} = $bug_id;
+      $bug{'error'} = "NotPermitted";
+      return $self;
+    } else {
+      $bug{'bug_id'} = $bug_id;
+      $bug{'error'} = "NotFound";
+      return $self;
+    }
+  }
+
+  if ($bug{'short_desc'}) {
+    $bug{'short_desc'} = QuoteXMLChars( $bug{'short_desc'} );
+  }
+
+  if (defined $bug{'status_whiteboard'}) {
+    $bug{'status_whiteboard'} = QuoteXMLChars($bug{'status_whiteboard'});
+  }
+
+  $bug{'assigned_to'} = &::DBID_to_real_or_loginname($bug{'assigned_to'});
+  $bug{'reporter'} = &::DBID_to_real_or_loginname($bug{'reporter'});
+
+  my $ccSet = new RelationSet;
+  $ccSet->mergeFromDB("select who from cc where bug_id=$bug_id");
+  my @cc = $ccSet->toArrayOfStrings();
+  if (@cc) {
+    $bug{'cc'} = \@cc;
+  }
+
+  if (&::Param("useqacontact") && (defined $bug{'qa_contact'}) ) {
+    my $name = $bug{'qa_contact'} > 0 ? &::DBID_to_name($bug{'qa_contact'}) :"";
+    if ($name) {
+      $bug{'qa_contact'} = $name;
+    }
+  }
+
+  if (@::legal_keywords) {
+    &::SendSQL("SELECT keyworddefs.name 
+              FROM keyworddefs, keywords
+             WHERE keywords.bug_id = $bug_id 
+               AND keyworddefs.id = keywords.keywordid
+          ORDER BY keyworddefs.name");
+    my @list;
+    while (&::MoreSQLData()) {
+        push(@list, &::FetchOneColumn());
+    }
+    if (@list) {
+      $bug{'keywords'} = &::html_quote(join(', ', @list));
+    }
+  }
+
+  &::SendSQL("select attach_id, creation_ts, description 
+           from attachments 
+           where bug_id = $bug_id");
+  my @attachments;
+  while (&::MoreSQLData()) {
+    my ($attachid, $date, $desc) = (&::FetchSQLData());
+    if ($date =~ /^(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/) {
+        $date = "$3/$4/$2 $5:$6";
+      my %attach;
+      $attach{'attachid'} = $attachid;
+      $attach{'date'} = $date;
+      $attach{'desc'} = &::html_quote($desc);
+      push @attachments, \%attach;
+    }
+  }
+  if (@attachments) {
+    $bug{'attachments'} = \@attachments;
+  }
+
+  &::SendSQL("select bug_id, who, bug_when, thetext 
+           from longdescs 
+           where bug_id = $bug_id");
+  my @longdescs;
+  while (&::MoreSQLData()) {
+    my ($bug_id, $who, $bug_when, $thetext) = (&::FetchSQLData());
+    my %longdesc;
+    $longdesc{'who'} = $who;
+    $longdesc{'bug_when'} = $bug_when;
+    $longdesc{'thetext'} = &::html_quote($thetext);
+    push @longdescs, \%longdesc;
+  }
+  if (@longdescs) {
+    $bug{'longdescs'} = \@longdescs;
+  }
+
+  if (&::Param("usedependencies")) {
+    my @depends = EmitDependList("blocked", "dependson", $bug_id);
+    if ( @depends ) {
+      $bug{'dependson'} = \@depends;
+    }
+    my @blocks = EmitDependList("dependson", "blocked", $bug_id);
+    if ( @blocks ) {
+      $bug{'blocks'} = \@blocks;
+    }
+  }
+  return $self;
+}
+
+
+
+# given a bug hash, emit xml for it. with file header provided by caller
+#
+sub emitXML {
+  ( $#_ == 0 ) || confess("invalid number of arguments");
+  my $self = shift();
+  my $xml;
+
+
+  if (exists $bug{'error'}) {
+    $xml .= "<bug error=\"$bug{'error'}\">\n";
+    $xml .= "  <bug_id>$bug{'bug_id'}</bug_id>\n";
+    $xml .= "</bug>\n";
+    return $xml;
+  }
+
+  $xml .= "<bug>\n";
+
+  foreach my $field ("bug_id", "urlbase", "bug_status", "product",
+      "priority", "version", "rep_platform", "assigned_to", "delta_ts", 
+      "component", "reporter", "target_milestone", "bug_severity", 
+      "creation_ts", "qa_contact", "op_sys", "resolution", "bug_file_loc",
+      "short_desc", "keywords", "status_whiteboard") {
+    if ($bug{$field}) {
+      $xml .= "  <$field>" . $bug{$field} . "</$field>\n";
+    }
+  }
+
+  foreach my $field ("dependson", "blocks", "cc") {
+    if (defined $bug{$field}) {
+      for (my $i=0 ; $i < @{$bug{$field}} ; $i++) {
+        $xml .= "  <$field>" . $bug{$field}[$i] . "</$field>\n";
+      }
+    }
+  }
+
+  if (defined $bug{'longdescs'}) {
+    for (my $i=0 ; $i < @{$bug{'longdescs'}} ; $i++) {
+      $xml .= "  <long_desc>\n"; 
+      $xml .= "   <who>" . &::DBID_to_name($bug{'longdescs'}[$i]->{'who'}) 
+                         . "</who>\n"; 
+      $xml .= "   <bug_when>" . $bug{'longdescs'}[$i]->{'bug_when'} 
+                              . "</bug_when>\n"; 
+      $xml .= "   <thetext>" . QuoteXMLChars($bug{'longdescs'}[$i]->{'thetext'})
+                             . "</thetext>\n"; 
+      $xml .= "  </long_desc>\n"; 
+    }
+  }
+
+  if (defined $bug{'attachments'}) {
+    for (my $i=0 ; $i < @{$bug{'attachments'}} ; $i++) {
+      $xml .= "  <attachment>\n"; 
+      $xml .= "    <attachid>" . $bug{'attachments'}[$i]->{'attachid'}
+                              . "</attachid>\n"; 
+      $xml .= "    <date>" . $bug{'attachments'}[$i]->{'date'} . "</date>\n"; 
+      $xml .= "    <desc>" . $bug{'attachments'}[$i]->{'desc'} . "</desc>\n"; 
+    # $xml .= "    <type>" . $bug{'attachments'}[$i]->{'type'} . "</type>\n"; 
+    # $xml .= "    <data>" . $bug{'attachments'}[$i]->{'data'} . "</data>\n"; 
+      $xml .= "  </attachment>\n"; 
+    }
+  }
+
+  $xml .= "</bug>\n";
+  return $xml;
+}
+
+
+
+sub EmitDependList {
+  my ($myfield, $targetfield, $bug_id) = (@_);
+  my @list;
+  &::SendSQL("select dependencies.$targetfield, bugs.bug_status
+           from dependencies, bugs
+           where dependencies.$myfield = $bug_id
+             and bugs.bug_id = dependencies.$targetfield
+           order by dependencies.$targetfield");
+  while (&::MoreSQLData()) {
+    my ($i, $stat) = (&::FetchSQLData());
+    push @list, $i;
+  }
+  return @list;
+}
+
+
+
+sub QuoteXMLChars {
+  $_[0] =~ s/</&lt;/g;
+  $_[0] =~ s/>/&gt;/g;
+  $_[0] =~ s/'/&apos;/g;
+  $_[0] =~ s/"/&quot;/g;
+  $_[0] =~ s/&/&amp;/g;
+# $_[0] =~ s/([\x80-\xFF])/&XmlUtf8Encode(ord($1))/ge;
+  return($_[0]);
+}
+
+
+sub XML_Header {
+  my ($urlbase, $version, $maintainer, $exporter) = (@_);
+
+  my $xml;
+  $xml = "<?xml version=\"1.0\" standalone=\"no\"?>\n";
+  $xml .= "<!DOCTYPE bugzilla SYSTEM \"$urlbase";
+  if (! ($urlbase =~ /.+\/$/)) {
+    $xml .= "/";
+  }
+  $xml .= "bugzilla.dtd\">\n";
+  $xml .= "<bugzilla";
+  if (defined $exporter) {
+    $xml .= " exporter=\"$exporter\"";
+  }
+  $xml .= " version=\"$version\"";
+  $xml .= " urlbase=\"$urlbase\"";
+  $xml .= " maintainer=\"$maintainer\">\n";
+  return ($xml);
+}
+
+
+sub XML_Footer {
+  return ("</bugzilla>\n");
+}
+
+sub AUTOLOAD {
+  use vars qw($AUTOLOAD);
+  my $self = shift;
+  my $type = ref($self) || $self;
+  my $attr = $AUTOLOAD;
+
+  $attr =~ s/.*:://;
+  return unless $attr=~ /[^A-Z]/;
+  if (@_) {
+    $bug{$attr} = shift;
+    return;
+  }
+  confess "invalid bug attribute $attr" unless $ok_field{$attr};
+  if (defined $bug{$attr}) {
+    return $bug{$attr};
+  } else {
+    return '';
+  }
+}
+
+1;
diff --git a/Bugzilla/Bug.pm b/Bugzilla/Bug.pm
new file mode 100755 (executable)
index 0000000..2488574
--- /dev/null
@@ -0,0 +1,369 @@
+#!/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>
+#                 Terry Weissman <terry@mozilla.org>
+
+use diagnostics;
+use strict;
+
+use DBI;
+use RelationSet;
+require "globals.pl";
+require "CGI.pl";
+package Bug;
+use CGI::Carp qw(fatalsToBrowser);
+my %bug;
+my %ok_field;
+
+for my $key (qw (bug_id product version rep_platform op_sys bug_status 
+                resolution priority bug_severity component assigned_to
+                reporter bug_file_loc short_desc target_milestone 
+                qa_contact status_whiteboard creation_ts groupset 
+                delta_ts votes) ){
+    $ok_field{$key}++;
+    }
+
+# create a new empty bug
+#
+sub new {
+  my $type = shift();
+
+  # create a ref to an empty hash and bless it
+  #
+  my $self = {%bug};
+  bless $self, $type;
+
+  # construct from a hash containing a bug's info
+  #
+  if ($#_ == 1) {
+    $self->initBug(@_);
+  } else {
+    confess("invalid number of arguments \($#_\)($_)");
+  }
+
+  # bless as a Bug
+  #
+  return $self;
+}
+
+
+
+# dump info about bug into hash unless user doesn't have permission
+# user_id 0 is used when person is not logged in.
+#
+sub initBug  {
+  my $self = shift();
+  my ($bug_id, $user_id) = (@_);
+
+
+  if ( (! defined $bug_id) || (!$bug_id) ) {
+    # no bug number given
+    return {};
+  }
+
+  if (! defined $user_id) {
+    $user_id = 0;
+  }
+
+  &::ConnectToDatabase();
+  &::GetVersionTable();
+
+  # this verification should already have been done by caller
+  # my $loginok = quietly_check_login();
+  my $usergroupset = "0";
+  if (defined $::usergroupset) {
+    $usergroupset = $::usergroupset;
+  }
+
+  my $query = "
+    select
+      bugs.bug_id, product, version, rep_platform, op_sys, bug_status,
+      resolution, priority, bug_severity, component, assigned_to, reporter,
+      bug_file_loc, short_desc, target_milestone, qa_contact,
+      status_whiteboard, date_format(creation_ts,'%Y-%m-%d %H:%i'),
+      groupset, delta_ts, sum(votes.count)
+    from bugs left join votes using(bug_id)
+    where bugs.bug_id = $bug_id
+    and bugs.groupset & $usergroupset = bugs.groupset
+    group by bugs.bug_id";
+
+  &::SendSQL($query);
+  my @row;
+
+  if (@row = &::FetchSQLData()) {
+    my $count = 0;
+    my %fields;
+    foreach my $field ("bug_id", "product", "version", "rep_platform",
+                       "op_sys", "bug_status", "resolution", "priority",
+                       "bug_severity", "component", "assigned_to", "reporter",
+                       "bug_file_loc", "short_desc", "target_milestone",
+                       "qa_contact", "status_whiteboard", "creation_ts",
+                       "groupset", "delta_ts", "votes") {
+       $fields{$field} = shift @row;
+       if ($fields{$field}) {
+           $bug{$field} = $fields{$field};
+       }
+       $count++;
+    }
+  } else {
+    &::SendSQL("select groupset from bugs where bug_id = $bug_id");
+    if (@row = &::FetchSQLData()) {
+      $bug{'bug_id'} = $bug_id;
+      $bug{'error'} = "NotPermitted";
+      return $self;
+    } else {
+      $bug{'bug_id'} = $bug_id;
+      $bug{'error'} = "NotFound";
+      return $self;
+    }
+  }
+
+  if ($bug{'short_desc'}) {
+    $bug{'short_desc'} = QuoteXMLChars( $bug{'short_desc'} );
+  }
+
+  if (defined $bug{'status_whiteboard'}) {
+    $bug{'status_whiteboard'} = QuoteXMLChars($bug{'status_whiteboard'});
+  }
+
+  $bug{'assigned_to'} = &::DBID_to_real_or_loginname($bug{'assigned_to'});
+  $bug{'reporter'} = &::DBID_to_real_or_loginname($bug{'reporter'});
+
+  my $ccSet = new RelationSet;
+  $ccSet->mergeFromDB("select who from cc where bug_id=$bug_id");
+  my @cc = $ccSet->toArrayOfStrings();
+  if (@cc) {
+    $bug{'cc'} = \@cc;
+  }
+
+  if (&::Param("useqacontact") && (defined $bug{'qa_contact'}) ) {
+    my $name = $bug{'qa_contact'} > 0 ? &::DBID_to_name($bug{'qa_contact'}) :"";
+    if ($name) {
+      $bug{'qa_contact'} = $name;
+    }
+  }
+
+  if (@::legal_keywords) {
+    &::SendSQL("SELECT keyworddefs.name 
+              FROM keyworddefs, keywords
+             WHERE keywords.bug_id = $bug_id 
+               AND keyworddefs.id = keywords.keywordid
+          ORDER BY keyworddefs.name");
+    my @list;
+    while (&::MoreSQLData()) {
+        push(@list, &::FetchOneColumn());
+    }
+    if (@list) {
+      $bug{'keywords'} = &::html_quote(join(', ', @list));
+    }
+  }
+
+  &::SendSQL("select attach_id, creation_ts, description 
+           from attachments 
+           where bug_id = $bug_id");
+  my @attachments;
+  while (&::MoreSQLData()) {
+    my ($attachid, $date, $desc) = (&::FetchSQLData());
+    if ($date =~ /^(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/) {
+        $date = "$3/$4/$2 $5:$6";
+      my %attach;
+      $attach{'attachid'} = $attachid;
+      $attach{'date'} = $date;
+      $attach{'desc'} = &::html_quote($desc);
+      push @attachments, \%attach;
+    }
+  }
+  if (@attachments) {
+    $bug{'attachments'} = \@attachments;
+  }
+
+  &::SendSQL("select bug_id, who, bug_when, thetext 
+           from longdescs 
+           where bug_id = $bug_id");
+  my @longdescs;
+  while (&::MoreSQLData()) {
+    my ($bug_id, $who, $bug_when, $thetext) = (&::FetchSQLData());
+    my %longdesc;
+    $longdesc{'who'} = $who;
+    $longdesc{'bug_when'} = $bug_when;
+    $longdesc{'thetext'} = &::html_quote($thetext);
+    push @longdescs, \%longdesc;
+  }
+  if (@longdescs) {
+    $bug{'longdescs'} = \@longdescs;
+  }
+
+  if (&::Param("usedependencies")) {
+    my @depends = EmitDependList("blocked", "dependson", $bug_id);
+    if ( @depends ) {
+      $bug{'dependson'} = \@depends;
+    }
+    my @blocks = EmitDependList("dependson", "blocked", $bug_id);
+    if ( @blocks ) {
+      $bug{'blocks'} = \@blocks;
+    }
+  }
+  return $self;
+}
+
+
+
+# given a bug hash, emit xml for it. with file header provided by caller
+#
+sub emitXML {
+  ( $#_ == 0 ) || confess("invalid number of arguments");
+  my $self = shift();
+  my $xml;
+
+
+  if (exists $bug{'error'}) {
+    $xml .= "<bug error=\"$bug{'error'}\">\n";
+    $xml .= "  <bug_id>$bug{'bug_id'}</bug_id>\n";
+    $xml .= "</bug>\n";
+    return $xml;
+  }
+
+  $xml .= "<bug>\n";
+
+  foreach my $field ("bug_id", "urlbase", "bug_status", "product",
+      "priority", "version", "rep_platform", "assigned_to", "delta_ts", 
+      "component", "reporter", "target_milestone", "bug_severity", 
+      "creation_ts", "qa_contact", "op_sys", "resolution", "bug_file_loc",
+      "short_desc", "keywords", "status_whiteboard") {
+    if ($bug{$field}) {
+      $xml .= "  <$field>" . $bug{$field} . "</$field>\n";
+    }
+  }
+
+  foreach my $field ("dependson", "blocks", "cc") {
+    if (defined $bug{$field}) {
+      for (my $i=0 ; $i < @{$bug{$field}} ; $i++) {
+        $xml .= "  <$field>" . $bug{$field}[$i] . "</$field>\n";
+      }
+    }
+  }
+
+  if (defined $bug{'longdescs'}) {
+    for (my $i=0 ; $i < @{$bug{'longdescs'}} ; $i++) {
+      $xml .= "  <long_desc>\n"; 
+      $xml .= "   <who>" . &::DBID_to_name($bug{'longdescs'}[$i]->{'who'}) 
+                         . "</who>\n"; 
+      $xml .= "   <bug_when>" . $bug{'longdescs'}[$i]->{'bug_when'} 
+                              . "</bug_when>\n"; 
+      $xml .= "   <thetext>" . QuoteXMLChars($bug{'longdescs'}[$i]->{'thetext'})
+                             . "</thetext>\n"; 
+      $xml .= "  </long_desc>\n"; 
+    }
+  }
+
+  if (defined $bug{'attachments'}) {
+    for (my $i=0 ; $i < @{$bug{'attachments'}} ; $i++) {
+      $xml .= "  <attachment>\n"; 
+      $xml .= "    <attachid>" . $bug{'attachments'}[$i]->{'attachid'}
+                              . "</attachid>\n"; 
+      $xml .= "    <date>" . $bug{'attachments'}[$i]->{'date'} . "</date>\n"; 
+      $xml .= "    <desc>" . $bug{'attachments'}[$i]->{'desc'} . "</desc>\n"; 
+    # $xml .= "    <type>" . $bug{'attachments'}[$i]->{'type'} . "</type>\n"; 
+    # $xml .= "    <data>" . $bug{'attachments'}[$i]->{'data'} . "</data>\n"; 
+      $xml .= "  </attachment>\n"; 
+    }
+  }
+
+  $xml .= "</bug>\n";
+  return $xml;
+}
+
+
+
+sub EmitDependList {
+  my ($myfield, $targetfield, $bug_id) = (@_);
+  my @list;
+  &::SendSQL("select dependencies.$targetfield, bugs.bug_status
+           from dependencies, bugs
+           where dependencies.$myfield = $bug_id
+             and bugs.bug_id = dependencies.$targetfield
+           order by dependencies.$targetfield");
+  while (&::MoreSQLData()) {
+    my ($i, $stat) = (&::FetchSQLData());
+    push @list, $i;
+  }
+  return @list;
+}
+
+
+
+sub QuoteXMLChars {
+  $_[0] =~ s/</&lt;/g;
+  $_[0] =~ s/>/&gt;/g;
+  $_[0] =~ s/'/&apos;/g;
+  $_[0] =~ s/"/&quot;/g;
+  $_[0] =~ s/&/&amp;/g;
+# $_[0] =~ s/([\x80-\xFF])/&XmlUtf8Encode(ord($1))/ge;
+  return($_[0]);
+}
+
+
+sub XML_Header {
+  my ($urlbase, $version, $maintainer, $exporter) = (@_);
+
+  my $xml;
+  $xml = "<?xml version=\"1.0\" standalone=\"no\"?>\n";
+  $xml .= "<!DOCTYPE bugzilla SYSTEM \"$urlbase";
+  if (! ($urlbase =~ /.+\/$/)) {
+    $xml .= "/";
+  }
+  $xml .= "bugzilla.dtd\">\n";
+  $xml .= "<bugzilla";
+  if (defined $exporter) {
+    $xml .= " exporter=\"$exporter\"";
+  }
+  $xml .= " version=\"$version\"";
+  $xml .= " urlbase=\"$urlbase\"";
+  $xml .= " maintainer=\"$maintainer\">\n";
+  return ($xml);
+}
+
+
+sub XML_Footer {
+  return ("</bugzilla>\n");
+}
+
+sub AUTOLOAD {
+  use vars qw($AUTOLOAD);
+  my $self = shift;
+  my $type = ref($self) || $self;
+  my $attr = $AUTOLOAD;
+
+  $attr =~ s/.*:://;
+  return unless $attr=~ /[^A-Z]/;
+  if (@_) {
+    $bug{$attr} = shift;
+    return;
+  }
+  confess "invalid bug attribute $attr" unless $ok_field{$attr};
+  if (defined $bug{$attr}) {
+    return $bug{$attr};
+  } else {
+    return '';
+  }
+}
+
+1;
index d7421c3213c5d0ff893680e014605df529835be5..2b32678f22a9001c2e7ef4b929c996f67bc4e397 100755 (executable)
@@ -295,7 +295,7 @@ foreach my $field ("bug_id", "urlbase", "bug_status", "product", "priority",
   "version", "rep_platform", "assigned_to", "delta_ts", "component", 
   "reporter", "target_milestone", "bug_severity", "creation_ts", 
   "qa_contact", "op_sys", "resolution", "bug_file_loc", "short_desc", 
-  "keywords", "status_whiteboard") {
+  "keywords", "groupset", "status_whiteboard") {
     if ($bug{$field}) {
       $xml .= "  <$field>" . $bug{$field} . "</$field>\n";
     }
index 4a41009fdab9f87a69a1cc6397298e9c3c2261c5..7872cfa802c8324540f578cabd0459e7063f2000 100755 (executable)
@@ -28,6 +28,9 @@
 use diagnostics;
 use strict;
 use XML::Parser;
+use Data::Dumper;
+$Data::Dumper::Useqq = 1;
+
 require "CGI.pl";
 require "globals.pl";
 
@@ -107,327 +110,349 @@ if ( ! $exporterid ) {
 }
 
 
-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 
-    bug_id rep_platform short_desc assigned_to resolution
-    delta_ts component reporter urlbase target_milestone bug_severity 
-    creation_ts qa_contact keyword status_whiteboard op_sys blocks)) {
-  $all_fields{$field} = "x"; 
-}
+my $bugqty = ($#{@{$tree}->[1]} +1 -3) / 4;
+print "Importing $bugqty bugs from $urlbase,\n  sent by $exporter.\n";
+for (my $k=1 ; $k <= $bugqty ; $k++) {
+  my $cur = $k*4;
+
+  if (defined $tree->[1][$cur][0]->{'error'}) {
+    print "\nError in bug $tree->[1][$cur][4][2]\@$urlbase:";
+    print " $tree->[1][$cur][0]->{'error'}\n";
+    if ($tree->[1][$cur][0]->{'error'} =~ /NotFound/) {
+      print "$exporter tried to move bug $tree->[1][$cur][4][2] here";
+      print " but $urlbase reports that this bug does not exist.\n"; 
+    } elsif ( $tree->[1][$cur][0]->{'error'} =~ /NotPermitted/) {
+      print "$exporter tried to move bug $tree->[1][$cur][4][2] here";
+      print " but $urlbase reports that $exporter does not have access";
+      print " to that bug.\n";
+    }
+    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 
+      bug_id rep_platform short_desc assigned_to resolution
+      delta_ts component reporter urlbase target_milestone bug_severity 
+      creation_ts qa_contact keyword status_whiteboard op_sys blocks)) {
+    $all_fields{$field} = "x"; 
+  }
  
  
-my %bug_fields;
-my $err = "";
-for (my $i=3 ; $i < $#{@{$tree}->[1][4]} ; $i=$i+4) {
-  if (defined $multiple_fields{$tree->[1][4][$i]}) {
-    if (defined $bug_fields{$tree->[1][4][$i]}) {
-      $bug_fields{$tree->[1][4][$i]} .= " " .  $tree->[1][4][$i+1][2];
-    } else {
-      $bug_fields{$tree->[1][4][$i]} = $tree->[1][4][$i+1][2];
-    }
-  } elsif (defined $all_fields{$tree->[1][4][$i]}) {
-    $bug_fields{$tree->[1][4][$i]} = $tree->[1][4][$i+1][2];
-  } else {
-    $err .= "---\n";
-    $err .= "Unknown bug field \"$tree->[1][4][$i]\"";
-    $err .= " encountered while moving bug\n";
-    $err .= "<$tree->[1][4][$i]>";
-    if (defined $tree->[1][4][$i+1][3]) {
-      $err .= "\n";
-      for (my $j=3 ; $j < $#{@{$tree}->[1][4][$i+1]} ; $j=$j+4) {
-        $err .= "  <". $tree->[1][4][$i+1][$j] . ">";
-        $err .= " $tree->[1][4][$i+1][$j+1][2] ";
-        $err .= "</". $tree->[1][4][$i+1][$j] . ">\n";
+  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];
       }
+    } elsif (defined $all_fields{$tree->[1][$cur][$i]}) {
+      $bug_fields{$tree->[1][$cur][$i]} = $tree->[1][$cur][$i+1][2];
     } else {
-      $err .= " $tree->[1][4][$i+1][2] ";
+      $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";
     }
-    $err .= "</$tree->[1][4][$i]>\n";
   }
-}
 
-my @long_descs;
-for (my $i=3 ; $i < $#{@{$tree}->[1][4]} ; $i=$i+4) {
-  if ($tree->[1][4][$i] =~ /long_desc/) {
-    my %long_desc;
-    $long_desc{'who'} = $tree->[1][4][$i+1][4][2];
-    $long_desc{'bug_when'} = $tree->[1][4][$i+1][8][2];
-    $long_desc{'thetext'} = $tree->[1][4][$i+1][12][2];
-    push @long_descs, \%long_desc;
+  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;
+    }
   }
-}
 
-# 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 $i=0 ; $i < $#sorted_descs ; $i++) {
-  unless ( $i==0 ) {
-    $long_description .= "\n\n\n------- Additional Comments From ";
-    $long_description .= "$sorted_descs[$i]->{'who'} "; 
-    $long_description .= "$sorted_descs[$i]->{'bug_when'}"; 
-    $long_description .= " ----\n\n";
+  # 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";
+    }
+    $long_description .=  "$sorted_descs[$z]->{'thetext'}\n";
   }
-  $long_description .=  "$sorted_descs[$i]->{'thetext'}\n"
-}
 
 
-my $comments;
-my $query = "INSERT INTO bugs (\n";
-my $values = "VALUES (\n";
-
-$comments .= "\n\n------- Bug Moved by $exporter "; 
-$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";
-}
+  my $comments;
+  my $query = "INSERT INTO bugs (\n";
+  my $values = "VALUES (\n";
+
+  $comments .= "\n\n------- Bug Moved by $exporter "; 
+  $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";
+  }
 
 
-foreach my $field ( qw(creation_ts delta_ts keywords status_whiteboard) ) {
-    if ( (defined $bug_fields{$field}) && ($bug_fields{$field}) ){
-      $query .= "$field,\n";
-      $values .= SqlQuote($bug_fields{$field}) . ",\n";
-    }
-}
+  foreach my $field ( qw(creation_ts delta_ts keywords status_whiteboard) ) {
+      if ( (defined $bug_fields{$field}) && ($bug_fields{$field}) ){
+        $query .= "$field,\n";
+        $values .= SqlQuote($bug_fields{$field}) . ",\n";
+      }
+  }
 
-if ( (defined $bug_fields{'short_desc'}) && ($bug_fields{'short_desc'}) ){
-      $query .= "short_desc,\n";
+  if ( (defined $bug_fields{'short_desc'}) && ($bug_fields{'short_desc'}) ){
+        $query .= "short_desc,\n";
       $values .= SqlQuote(UnQuoteXMLChars($bug_fields{'short_desc'})) . ",\n";
-    }
+      }
 
-my @product;
-if (defined ($bug_fields{'product'}) &&
-     (@product = grep /^$bug_fields{'product'}$/i, @::legal_product) ){
-  $query .= "product,\n";
-  $values .= SqlQuote($product[0]) . ",\n";
-} else {
-  $query .= "product,\n";
-  $values .= "\'Browser\',\n";
-  $product[0] = "Browser";
-  $err .= "Unknown product $bug_fields{'product'}. ";
-  $err .= "Moving to default product \"Browser\".\n";
-}
+  my @product;
+  if (defined ($bug_fields{'product'}) &&
+       (@product = grep /^$bug_fields{'product'}$/i, @::legal_product) ){
+    $query .= "product,\n";
+    $values .= SqlQuote($product[0]) . ",\n";
+  } else {
+    $query .= "product,\n";
+    $values .= "\'Browser\',\n";
+    $product[0] = "Browser";
+    $err .= "Unknown product $bug_fields{'product'}. ";
+    $err .= "Moving to default product \"Browser\".\n";
+  }
 
-if (defined  ($::versions{$product[0]} ) &&
-   (my @version = grep /^$bug_fields{'version'}$/i, 
-                       @{$::versions{$product[0]}}) ){
-  $values .= SqlQuote($version[0]) . ",\n";
-  $query .= "version,\n";
-} else {
-  $query .= "version,\n";
-  $values .= "\'@{$::versions{$product[0]}}->[0]\',\n";
-  $err .= "Unknown version $bug_fields{'version'} in product $product[0]. ";
-  $err .= "Setting version to \"@{$::versions{$product[0]}}->[0]\".\n";
-}
+  if (defined  ($::versions{$product[0]} ) &&
+     (my @version = grep /^$bug_fields{'version'}$/i, 
+                         @{$::versions{$product[0]}}) ){
+    $values .= SqlQuote($version[0]) . ",\n";
+    $query .= "version,\n";
+  } else {
+    $query .= "version,\n";
+    $values .= "\'@{$::versions{$product[0]}}->[0]\',\n";
+    $err .= "Unknown version $bug_fields{'version'} in product $product[0]. ";
+    $err .= "Setting version to \"@{$::versions{$product[0]}}->[0]\".\n";
+  }
 
-if (defined ($bug_fields{'priority'}) &&
-     (my @priority = grep /^$bug_fields{'priority'}$/i, @::legal_priority) ){
-  $values .= SqlQuote($priority[0]) . ",\n";
-  $query .= "priority,\n";
-} else {
-  $values .= "\'P3\',\n";
-  $query .= "priority,\n";
-  $err .= "Unknown priority ";
-  $err .= (defined $bug_fields{'priority'})?$bug_fields{'priority'}:"unknown";
-  $err .= ". Setting to default priority \"P3\".\n";
-}
+  if (defined ($bug_fields{'priority'}) &&
+       (my @priority = grep /^$bug_fields{'priority'}$/i, @::legal_priority) ){
+    $values .= SqlQuote($priority[0]) . ",\n";
+    $query .= "priority,\n";
+  } else {
+    $values .= "\'P3\',\n";
+    $query .= "priority,\n";
+    $err .= "Unknown priority ";
+    $err .= (defined $bug_fields{'priority'})?$bug_fields{'priority'}:"unknown";
+    $err .= ". Setting to default priority \"P3\".\n";
+  }
 
-if (defined ($bug_fields{'rep_platform'}) &&
-     (my @platform = grep /^$bug_fields{'rep_platform'}$/i, @::legal_platform) ){
-  $values .= SqlQuote($platform[0]) . ",\n";
-  $query .= "rep_platform,\n";
-} else {
-  $values .= "\'Other\',\n";
-  $query .= "rep_platform,\n";
-  $err .= "Unknown platform ";
-  $err .= (defined $bug_fields{'rep_platform'})?
-                   $bug_fields{'rep_platform'}:"unknown";
-  $err .= ". Setting to default platform \"Other\".\n";
-}
+  if (defined ($bug_fields{'rep_platform'}) &&
+       (my @platform = grep /^$bug_fields{'rep_platform'}$/i, @::legal_platform) ){
+    $values .= SqlQuote($platform[0]) . ",\n";
+    $query .= "rep_platform,\n";
+  } else {
+    $values .= "\'Other\',\n";
+    $query .= "rep_platform,\n";
+    $err .= "Unknown platform ";
+    $err .= (defined $bug_fields{'rep_platform'})?
+                     $bug_fields{'rep_platform'}:"unknown";
+    $err .= ". Setting to default platform \"Other\".\n";
+  }
 
-if (defined ($bug_fields{'op_sys'}) &&
+  if (defined ($bug_fields{'op_sys'}) &&
      (my @opsys = grep /^$bug_fields{'op_sys'}$/i, @::legal_opsys) ){
-  $values .= SqlQuote($opsys[0]) . ",\n";
-  $query .= "op_sys,\n";
-} else {
-  $values .= "\'other\',\n";
-  $query .= "op_sys,\n";
-  $err .= "Unknown operating system ";
-  $err .= (defined $bug_fields{'op_sys'})?$bug_fields{'op_sys'}:"unknown";
-  $err .= ". Setting to default OS \"other\".\n";
-}
+    $values .= SqlQuote($opsys[0]) . ",\n";
+    $query .= "op_sys,\n";
+  } else {
+    $values .= "\'other\',\n";
+    $query .= "op_sys,\n";
+    $err .= "Unknown operating system ";
+    $err .= (defined $bug_fields{'op_sys'})?$bug_fields{'op_sys'}:"unknown";
+    $err .= ". Setting to default OS \"other\".\n";
+  }
 
-my @component;
-if (defined  ($::components{$product[0]} ) &&
-   (@component = grep /^$bug_fields{'component'}$/i, 
+  my @component;
+  if (defined  ($::components{$product[0]} ) &&
+     (@component = grep /^$bug_fields{'component'}$/i, 
                        @{$::components{$product[0]}}) ){
-  $values .= SqlQuote($component[0]) . ",\n";
-  $query .= "component,\n";
-} else {
-  $component[0] = $::components{$product[0]}->[0];
-  $values .= SqlQuote($component[0]) . ",\n";
-  $query .= "component,\n";
-  $err .= "Unknown component \"";
-  $err .= (defined $bug_fields{'component'})?$bug_fields{'component'}:"unknown";
-  $err .= "\" in product \"$product[0]\".\n";
-  $err .= "   Setting to this product\'s first component, ";
-  $err .= "\'$::components{$product[0]}->[0]\'.\n";
-}
-
-if (Param("usetargetmilestone")) {
-  if (defined  ($::target_milestone{$product[0]} ) &&
-     (my @tm = grep /^$bug_fields{'target_milestone'}$/i, 
-                       @{$::target_milestone{$product[0]}}) ){
-    $values .= SqlQuote($tm[0]) . ",\n";
-    $query .= "target_milestone,\n";
+    $values .= SqlQuote($component[0]) . ",\n";
+    $query .= "component,\n";
   } else {
-    SendSQL("SELECT defaultmilestone FROM products " .
-            "WHERE product = " . SqlQuote($product[0]));
-    my $tm = FetchOneColumn();
-    $values .= "\'$tm\',\n";
-    $query .= "target_milestone,\n";
-    $err .= "Unknown milestone \"";
-    $err .= (defined $bug_fields{'target_milestone'})?
-            $bug_fields{'target_milestone'}:"unknown";
+    $component[0] = $::components{$product[0]}->[0];
+    $values .= SqlQuote($component[0]) . ",\n";
+    $query .= "component,\n";
+    $err .= "Unknown component \"";
+    $err .= (defined $bug_fields{'component'})?$bug_fields{'component'}:"unknown";
     $err .= "\" in product \"$product[0]\".\n";
-    $err .= "   Setting to default milestone for this product, ";
-    $err .= "\'" . $tm . "\'\n";
+    $err .= "   Setting to this product\'s first component, ";
+    $err .= "\'$::components{$product[0]}->[0]\'.\n";
   }
-}
 
-if (defined ($bug_fields{'bug_severity'}) &&
-     (my @severity= grep /^$bug_fields{'bug_severity'}$/i, 
-                         @::legal_severity) ){
-  $values .= SqlQuote($severity[0]) . ",\n";
-  $query .= "bug_severity,\n";
-} else {
-  $values .= "\'normal',\n";
-  $query .= "bug_severity,\n";
-  $err .= "Unknown severity ";
-  $err .= (defined $bug_fields{'bug_severity'})?
-                   $bug_fields{'bug_severity'}:"unknown";
-  $err .= ". Setting to default severity \"normal\".\n";
-}
+  if (Param("usetargetmilestone")) {
+    if (defined  ($::target_milestone{$product[0]} ) &&
+       (my @tm = grep /^$bug_fields{'target_milestone'}$/i, 
+                       @{$::target_milestone{$product[0]}}) ){
+      $values .= SqlQuote($tm[0]) . ",\n";
+      $query .= "target_milestone,\n";
+    } else {
+      SendSQL("SELECT defaultmilestone FROM products " .
+              "WHERE product = " . SqlQuote($product[0]));
+      my $tm = FetchOneColumn();
+      $values .= "\'$tm\',\n";
+      $query .= "target_milestone,\n";
+      $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";
+    }
+  }
 
-my $changed_owner = 0;
-if ( ($bug_fields{'assigned_to'}) && 
-     ( DBname_to_id($bug_fields{'assigned_to'})) ) {
-  $values .= "'" . DBname_to_id($bug_fields{'assigned_to'}) . "',\n";
-  $query .= "assigned_to,\n";
-} else {
-  $values .= "'" . $exporterid . "',\n";
-  $query .= "assigned_to,\n";
-  $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";
-  $err .= "   it here, $bug_fields{'exporter'}\n";
-  if ( $bug_fields{'assigned_to'} ) {
-    $err .= "   Previous owner was $bug_fields{'assigned_to'}.\n";
+  if (defined ($bug_fields{'bug_severity'}) &&
+       (my @severity= grep /^$bug_fields{'bug_severity'}$/i, 
+                           @::legal_severity) ){
+    $values .= SqlQuote($severity[0]) . ",\n";
+    $query .= "bug_severity,\n";
   } else {
-    $err .= "   Previous owner is unknown.\n";
+    $values .= "\'normal',\n";
+    $query .= "bug_severity,\n";
+    $err .= "Unknown severity ";
+    $err .= (defined $bug_fields{'bug_severity'})?
+                     $bug_fields{'bug_severity'}:"unknown";
+    $err .= ". Setting to default severity \"normal\".\n";
   }
-}
 
-my @resolution;
-if (defined ($bug_fields{'resolution'}) &&
-     (@resolution= grep /^$bug_fields{'resolution'}$/i, @::legal_resolution) ){
-  $values .= SqlQuote($resolution[0]) . ",\n";
-  $query .= "resolution,\n";
-} elsif ( (defined $bug_fields{'resolution'}) && (!$resolution[0]) ){
-  $err .= "Unknown resolution \"$bug_fields{'resolution'}\".\n";
-}
+  my $changed_owner = 0;
+  if ( ($bug_fields{'assigned_to'}) && 
+       ( DBname_to_id($bug_fields{'assigned_to'})) ) {
+    $values .= "'" . DBname_to_id($bug_fields{'assigned_to'}) . "',\n";
+    $query .= "assigned_to,\n";
+  } else {
+    $values .= "'" . $exporterid . "',\n";
+    $query .= "assigned_to,\n";
+    $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";
+    $err .= "   it here, $bug_fields{'exporter'}\n";
+    if ( $bug_fields{'assigned_to'} ) {
+      $err .= "   Previous owner was $bug_fields{'assigned_to'}.\n";
+    } else {
+      $err .= "   Previous owner is unknown.\n";
+    }
+  }
 
-# 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]) ) {
-  $values .= "\'NEW\',\n";
-  $query .= "bug_status,\n";
-  $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
-  $values .= "\'NEW\',\n";
-  $query .= "bug_status,\n";
-  $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
-  $values .= SqlQuote($status[0]) . ",\n";
-  $query .= "bug_status,\n";
-} else {
-  # if all else fails, make the bug new
-  $values .= "\'NEW\',\n";
-  $query .= "bug_status,\n";
-  $err .= "Unknown status ";
-  $err .= (defined $bug_fields{'bug_status'})?
-                   $bug_fields{'bug_status'}:"unknown";
-  $err .= ". Setting to default status \"NEW\".\n";
-}
+  my @resolution;
+  if (defined ($bug_fields{'resolution'}) &&
+       (@resolution= grep /^$bug_fields{'resolution'}$/i, @::legal_resolution) ){
+    $values .= SqlQuote($resolution[0]) . ",\n";
+    $query .= "resolution,\n";
+  } elsif ( (defined $bug_fields{'resolution'}) && (!$resolution[0]) ){
+    $err .= "Unknown resolution \"$bug_fields{'resolution'}\".\n";
+  }
 
-if (Param("useqacontact")) {
-  my $qa_contact;
-  if ( (defined $bug_fields{'qa_contact'}) &&
-       ($qa_contact  = DBname_to_id($bug_fields{'qa_contact'})) ){
-    $values .= "'$qa_contact'";
-    $query .= "qa_contact\n";
+  # 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]) ) {
+    $values .= "\'NEW\',\n";
+    $query .= "bug_status,\n";
+    $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
+    $values .= "\'NEW\',\n";
+    $query .= "bug_status,\n";
+    $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
+    $values .= SqlQuote($status[0]) . ",\n";
+    $query .= "bug_status,\n";
   } else {
-    SendSQL("select initialqacontact from components where program=" .
-            SqlQuote($product[0]) .
-            " and value=" . SqlQuote($component[0]) );
-    $qa_contact = FetchOneColumn();
-    $values .= SqlQuote(DBname_to_id($qa_contact)) . "\n";
-    $query .= "qa_contact\n";
-    $err .= "Setting qa contact to the default for this product.\n";
-    $err .= "   This bug either had no qa contact or an invalid one.\n";
+    # if all else fails, make the bug new
+    $values .= "\'NEW\',\n";
+    $query .= "bug_status,\n";
+    $err .= "Unknown status ";
+    $err .= (defined $bug_fields{'bug_status'})?
+                     $bug_fields{'bug_status'}:"unknown";
+    $err .= ". Setting to default status \"NEW\".\n";
   }
-}
 
-$query .= ") $values )\n";
-SendSQL($query);
-SendSQL("select LAST_INSERT_ID()");
-my $id = FetchOneColumn();
+  if (Param("useqacontact")) {
+    my $qa_contact;
+    if ( (defined $bug_fields{'qa_contact'}) &&
+         ($qa_contact  = DBname_to_id($bug_fields{'qa_contact'})) ){
+      $values .= "'$qa_contact'";
+      $query .= "qa_contact\n";
+    } else {
+      SendSQL("select initialqacontact from components where program=" .
+              SqlQuote($product[0]) .
+              " and value=" . SqlQuote($component[0]) );
+      $qa_contact = FetchOneColumn();
+      $values .= SqlQuote(DBname_to_id($qa_contact)) . "\n";
+      $query .= "qa_contact\n";
+      $err .= "Setting qa contact to the default for this product.\n";
+      $err .= "   This bug either had no qa contact or an invalid one.\n";
+    }
+  }
 
-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) .")");
+  $query .= ") $values )\n";
+  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) .")");
+      }
+    }
   }
-}
 
 
-$long_description .= "\n" . $comments;
-if ($err) {
-  $long_description .= "\n$err\n";
-}
+  $long_description .= "\n" . $comments;
+  if ($err) {
+    $long_description .= "\n$err\n";
+  }
 
-SendSQL("INSERT INTO longdescs (bug_id, who, bug_when, thetext) VALUES " .
-  "($id, $exporterid, now(), " . SqlQuote($long_description) . ")");
+  SendSQL("INSERT INTO longdescs (bug_id, who, bug_when, thetext) VALUES " .
+    "($id, $exporterid, now(), " . SqlQuote($long_description) . ")");
 
-print "Bug $bug_fields{'bug_id'}\@$urlbase ";
-print "imported as bug $id.\n";
+  print "Bug $bug_fields{'bug_id'}\@$urlbase ";
+  print "imported as bug $id.\n";
+}
diff --git a/xml.cgi b/xml.cgi
new file mode 100755 (executable)
index 0000000..9cfe314
--- /dev/null
+++ b/xml.cgi
@@ -0,0 +1,58 @@
+#!/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>
+#                 Terry Weissman <terry@mozilla.org>
+
+use diagnostics;
+use strict;
+use Bug;
+require "CGI.pl";
+
+if (!defined $::FORM{'id'} || $::FORM{'id'} !~ /^\s*\d+(,\d+)*\s*$/) {
+  print "Content-type: text/html\n\n";
+  PutHeader("Display as XML");
+  print "<FORM METHOD=GET ACTION=\"xml.cgi\">\n";
+  print "Display bugs as XML by entering a list of bug numbers here:\n";
+  print "<INPUT NAME=id>\n";
+  print "<INPUT TYPE=\"submit\" VALUE=\"Display as XML\"><br>\n";
+  print "  (e.g. 1000,1001,1002)\n";
+  print "</FORM>\n";
+  PutFooter();
+  exit;
+}
+
+quietly_check_login();
+my $exporter;
+if (defined $::COOKIE{"Bugzilla_login"}) {
+  $exporter = $::COOKIE{"Bugzilla_login"};
+}
+
+my @ids = split ( /,/, $::FORM{'id'} );
+
+print "Content-type: text/plain\n\n";
+print Bug::XML_Header( Param("urlbase"), $::param{'version'}, 
+                        Param("maintainer"), $exporter );
+foreach my $id (@ids) {
+  my $bug = new Bug($id, $::userid);
+  print $bug->emitXML;
+$bug->bug_status("BLAH");
+}
+print Bug::XML_Footer;