use Debbugs::Common qw(:util :quit :misc :lock);
-use Debbugs::Status qw(:read :status :write :versions);
+use Debbugs::Status qw(:read :status :write :versions :hook);
use Debbugs::MIME qw(decode_rfc1522 encode_rfc1522);
use Debbugs::Mail qw(send_mail_message);
use Debbugs::Status qw(splitpackages);
use Debbugs::CGI qw(html_escape);
-use Debbugs::Control qw(:archive :log);
+use Debbugs::Control qw(:all);
use Debbugs::Log qw(:misc);
use Debbugs::Text qw(:templates);
}
}
$header{'message-id'} ||= '';
+$header{subject} ||= '';
grep(s/\s+$//,@bodylines);
# This is an error counter which should be incremented every time there is an error.
my $errors = 0;
-my $controlrequestaddr= ($control ? 'control' : 'request').$config{email_domain};
+my $controlrequestaddr= ($control ? 'control' : 'request').'@'.$config{email_domain};
my $transcript_scalar = '';
my $transcript = IO::Scalar->new(\$transcript_scalar) or
die "Unable to create new IO::Scalar";
# recipients of mail
my %recipients;
+# affected_packages
+my %affected_packages;
my $ok = 0;
my $unknowns = 0;
my $procline=0;
last;
}
$_= $bodylines[$procline]; s/\s+$//;
+ # Remove BOM markers from UTF-8 strings
+ # Fixes #488554
+ s/\xef\xbb\xbf//g;
next unless m/\S/;
print {$transcript} "> $_\n";
next if m/^\s*\#/;
Debbugs::User::read_usertags(\%ut, $user);
my @oldtags = (); my @newtags = (); my @badtags = ();
my %chtags;
- for my $t (split /[,\s]+/, $tags) {
- if ($t =~ m/^[a-zA-Z0-9.+\@-]+$/) {
- $chtags{$t} = 1;
- } else {
- push @badtags, $t;
- }
+ if (defined $tags and length $tags) {
+ for my $t (split /[,\s]+/, $tags) {
+ if ($t =~ m/^[a-zA-Z0-9.+\@-]+$/) {
+ $chtags{$t} = 1;
+ } else {
+ push @badtags, $t;
+ }
+ }
}
if (@badtags) {
print {$transcript} "Ignoring illegal tag/s: ".join(', ', @badtags).".\nPlease use only alphanumerics, at, dot, plus and dash.\n";
"closed") .
", send any further explanations to $data->{originator}";
do {
- add_recipients(data => $data, recipients => \%recipients);
- if ( length( $gDoneList ) > 0 and
- length( $gListDomain ) > 0 ) {
- add_recipients(recipients => \%recipients,
- type => 'cc',
- address => "$gDoneList\@$gListDomain",
- );
- }
- $data->{done}= $replyto;
+ $affected_packages{$data->{package}} = 1;
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ actions_taken => {done => 1},
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
+ $data->{done}= $replyto;
my @keywords= split ' ', $data->{keywords};
my $extramessage = '';
if (grep $_ eq 'pending', @keywords) {
$action= "$gBug assigned to package \`$newpackage'.";
}
do {
- add_recipients(data => $data, recipients => \%recipients);
+ $affected_packages{$data->{package}} = 1;
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
$data->{package}= $newpackage;
$data->{found_versions}= [];
$data->{fixed_versions}= [];
# TODO: what if $newpackage is a source package?
addfoundversions($data, $data->{package}, $version, 'binary');
- add_recipients(data => $data, recipients => \%recipients);
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
} while (&getnextbug);
}
} elsif (m/^reopen\s+\#?(-?\d+)$/i ? ($noriginator='', 1) :
$noriginator eq '' ? "$gBug reopened, originator not changed." :
"$gBug reopened, originator set to $noriginator.";
do {
- add_recipients(data => $data, recipients => \%recipients);
+ $affected_packages{$data->{package}} = 1;
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
$data->{originator}= $noriginator eq '' ? $data->{originator} : $noriginator;
$data->{fixed_versions}= [];
$data->{done}= '';
"$gBug marked as found in version $version." :
"$gBug reopened.";
do {
- add_recipients(data => $data, recipients => \%recipients);
+ $affected_packages{$data->{package}} = 1;
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
# The 'done' field gets a bit weird with version
# tracking, because a bug may be closed by multiple
# people in different branches. Until we have something
$extramessage= "(By the way, this $gBug is currently marked as done.)\n";
}
do {
- add_recipients(data => $data, recipients => \%recipients);
+ $affected_packages{$data->{package}} = 1;
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
removefoundversions($data, $data->{package}, $version, 'binary');
} while (&getnextbug);
}
"$gBug marked as fixed in version $version." :
"$gBug reopened.";
do {
- add_recipients(data => $data, recipients => \%recipients);
+ $affected_packages{$data->{package}} = 1;
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
addfixedversions($data, $data->{package}, $version, 'binary');
} while (&getnextbug);
}
"$gBug no longer marked as fixed in version $version." :
"$gBug reopened.";
do {
- add_recipients(data => $data, recipients => \%recipients);
+ $affected_packages{$data->{package}} = 1;
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
removefixedversions($data, $data->{package}, $version, 'binary');
} while (&getnextbug);
}
elsif (&getbug) {
if (&checkpkglimit) {
&foundbug;
- add_recipients(data => $data, recipients => \%recipients);
+ $affected_packages{$data->{package}} = 1;
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
$oldsubmitter= $data->{originator};
$data->{originator}= $newsubmitter;
$action= "Changed $gBug submitter from $oldsubmitter to $newsubmitter.";
$extramessage= "(By the way, this $gBug is currently marked as done.)\n";
}
do {
- add_recipients(data => $data, recipients => \%recipients);
- if (length($gForwardList)>0 && length($gListDomain)>0 ) {
- add_recipients(recipients => \%recipients,
- type => 'cc',
- address => "$gForwardList\@$gListDomain",
- );
- }
- $data->{forwarded}= $whereto;
+ $affected_packages{$data->{package}} = 1;
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ actions_taken => {forwarded => 1},
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
+ $data->{forwarded}= $whereto;
} while (&getnextbug);
}
} elsif (m/^notforwarded\s+\#?(-?\d+)$/i) {
} else {
$action= "Removed annotation that $gBug had been forwarded to $data->{forwarded}.";
do {
- add_recipients(data => $data, recipients => \%recipients);
+ $affected_packages{$data->{package}} = 1;
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
$data->{forwarded}= '';
} while (&getnextbug);
}
$printseverity= "$gDefaultSeverity" if $printseverity eq '';
$action= "Severity set to \`$newseverity' from \`$printseverity'";
do {
- add_recipients(data => $data, recipients => \%recipients);
+ $affected_packages{$data->{package}} = 1;
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
if (defined $gStrongList and isstrongseverity($newseverity)) {
addbcc("$gStrongList\@$gListDomain");
}
$action= "Tags removed: " . join(", ", @okaytags);
}
do {
- add_recipients(data => $data, recipients => \%recipients);
+ $affected_packages{$data->{package}} = 1;
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
$data->{keywords} = '' if ($addsub eq "set");
# Allow removing obsolete tags.
if ($addsub eq "sub") {
$ok++;
my $bugnum = $2; my $blockers = $4;
my $addsub = "add";
- $addsub = "sub" if ($1 eq "un");
+ $addsub = "sub" if (defined $1 and $1 eq "un");
if ($bugnum =~ m/^-\d+$/ && defined $clonebugs{$bugnum}) {
$bugnum = $clonebugs{$bugnum};
}
my %removedblocks;
my %addedblocks;
do {
- add_recipients(data => $data, recipients => \%recipients);
+ $affected_packages{$data->{package}} = 1;
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
my @oldblockerlist = split ' ', $data->{blockedby};
$data->{blockedby} = '' if ($addsub eq "set");
foreach my $b (@okayblockers) {
if (&getbug) {
if (&checkpkglimit) {
&foundbug;
- add_recipients(data => $data, recipients => \%recipients);
+ $affected_packages{$data->{package}} = 1;
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
my $oldtitle = $data->{subject};
$data->{subject}= $newtitle;
$action= "Changed $gBug title to `$newtitle' from `$oldtitle'.";
my $discref= $ref;
@bug_affected{@newmergelist} = 1 x @newmergelist;
do {
- add_recipients(data => $data, recipients => \%recipients);
+ $affected_packages{$data->{package}} = 1;
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
$data->{mergedwith}= ($ref == $discref) ? ''
: join(' ',grep($_ ne $ref,@newmergelist));
} while (&getnextbug);
&checkmatch('blocked-by','m_blockedby',$data->{blockedby},@newmergelist);
&checkmatch('done mark','m_done',length($data->{done}) ? 'done' : 'open',@newmergelist);
&checkmatch('owner','m_owner',$data->{owner},@newmergelist);
+ &checkmatch('summary','m_summary',$data->{summary},@newmergelist);
+ &checkmatch('affects','m_affects',$data->{affects},@newmergelist);
foreach my $t (split /\s+/, $data->{keywords}) { $tags{$t} = 1; }
foreach my $f (@{$data->{found_versions}}) { $found{$f} = 1; }
foreach my $f (@{$data->{fixed_versions}}) { $fixed{$f} = 1; }
delete @fixed{keys %found};
for $ref (@newmergelist) {
&getbug || die "huh ? $gBug $ref disappeared during merge";
- add_recipients(data => $data, recipients => \%recipients);
+ $affected_packages{$data->{package}} = 1;
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
@bug_affected{@newmergelist} = 1 x @newmergelist;
$data->{mergedwith}= join(' ',grep($_ != $ref,@newmergelist));
$data->{keywords}= join(' ', keys %tags);
delete @fixed{keys %found};
for $ref (@newmergelist) {
&getbug || die "huh ? $gBug $ref disappeared during merge";
- add_recipients(data => $data, recipients => \%recipients);
+ $affected_packages{$data->{package}} = 1;
+ add_recipients(data => $data,
+ recipients => \%recipients,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ );
@bug_affected{@newmergelist} = 1 x @newmergelist;
$data->{mergedwith}= join(' ',grep($_ != $ref,@newmergelist));
$data->{keywords}= join(' ', keys %tags);
$data->{found_versions}= [sort keys %found];
$data->{fixed_versions}= [sort keys %fixed];
- my @field_list = qw(forwarded package severity blocks blockedby owner done);
+ my @field_list = qw(forwarded package severity blocks blockedby owner done affects summary);
@{$data}{@field_list} = @{$master_bug_data}{@field_list};
&savebug;
}
$ref = $origref;
$bug_affected{$ref} = 1;
if (&setbug) {
+ $affected_packages{$data->{package}} = 1;
if (length($data->{mergedwith})) {
print {$transcript} "$gBug is marked as being merged with others. Use an existing clone.\n\n";
$errors++;
%limit_pkgs = ();
print {$transcript} "Not ignoring any bugs.\n\n";
}
- } elsif (m/^owner\s+\#?(-?\d+)\s+((?:\S.*\S)|\!)$/i) {
+ } elsif (m/^affects?\s+\#?(-?\d+)(?:\s+((?:[=+-])?)\s*(\S.*)?)?\s*$/i) {
+ $ok++;
+ $ref = $1;
+ my $add_remove = $2 || '';
+ my $packages = $3 || '';
+ $ref = $clonebugs{$ref} if exists $clonebugs{$ref};
+ $bug_affected{$ref} = 1;
+ eval {
+ affects(bug => $ref,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ requester => $header{from},
+ request_addr => $controlrequestaddr,
+ message => \@log,
+ recipients => \%recipients,
+ packages => [splitpackages($3)],
+ ($add_remove eq '+'?(add => 1):()),
+ ($add_remove eq '-'?(remove => 1):()),
+ );
+ };
+ if ($@) {
+ $errors++;
+ print {$transcript} "Failed to give $ref a summary: $@";
+ }
+
+ } elsif (m/^summary\s+\#?(-?\d+)\s*(\d+|)\s*$/i) {
+ $ok++;
+ $ref = $1;
+ my $summary_msg = length($2)?$2:undef;
+ $ref = $clonebugs{$ref} if exists $clonebugs{$ref};
+ $bug_affected{$ref} = 1;
+ eval {
+ summary(bug => $ref,
+ transcript => $transcript,
+ ($dl > 0 ? (debug => $transcript):()),
+ requester => $header{from},
+ request_addr => $controlrequestaddr,
+ message => \@log,
+ recipients => \%recipients,
+ summary => $summary_msg,
+ );
+ };
+ if ($@) {
+ $errors++;
+ print {$transcript} "Failed to give $ref a summary: $@";
+ }
+
+ } elsif (m/^owner\s+\#?(-?\d+)\s+((?:\S.*\S)|\!)\s*$/i) {
$ok++;
$ref = $1;
+ $ref = $clonebugs{$ref} if exists $clonebugs{$ref};
my $newowner = $2;
if ($newowner eq '!') {
$newowner = $replyto;
owner => $newowner,
);
};
- } elsif (m/^noowner\s+\#?(-?\d+)$/i) {
+ if ($@) {
+ $errors++;
+ print {$transcript} "Failed to mark $ref as having an owner: $@";
+ }
+ } elsif (m/^noowner\s+\#?(-?\d+)\s*$/i) {
$ok++;
$ref = $1;
+ $ref = $clonebugs{$ref} if exists $clonebugs{$ref};
$bug_affected{$ref} = 1;
eval {
owner(bug => $ref,
} elsif (m/^unarchive\s+#?(\d+)$/i) {
$ok++;
$ref = $1;
+ $ref = $clonebugs{$ref} if exists $clonebugs{$ref};
$bug_affected{$ref} = 1;
eval {
bug_unarchive(bug => $ref,
} elsif (m/^archive\s+#?(\d+)$/i) {
$ok++;
$ref = $1;
+ $ref = $clonebugs{$ref} if exists $clonebugs{$ref};
$bug_affected{$ref} = 1;
eval {
bug_archive(bug => $ref,
print {$transcript} "\n";
}
-print {$transcript} "MC\n" if $dl>1;
-my @maintccs= ();
-my @maintccaddrs = ();
-my %maintccreasons;
-for my $maint (keys %maintccreasons) {
-print {$transcript} "MM|$maint|\n" if $dl>1;
- next if $maint eq $replyto;
- my $reasonstring= '';
- my $reasonsref= $maintccreasons{$maint};
-print {$transcript} "MY|$maint|\n" if $dl>2;
- for my $p (sort keys %$reasonsref) {
-print {$transcript} "MP|$p|\n" if $dl>2;
- $reasonstring.= ', ' if length($reasonstring);
- $reasonstring.= $p.' ' if length($p);
- $reasonstring.= join(' ',map("#$_",sort keys %{$$reasonsref{$p}}));
- }
- if (length($reasonstring) > 40) {
- (substr $reasonstring, 37) = "...";
- }
- $reasonstring = "" if (!defined($reasonstring));
- push(@maintccs,"$maint ($reasonstring)");
- push(@maintccaddrs,"$maint");
-}
-
-my $maintccs = "";
-if (@maintccs) {
- print {$transcript} "MC|".join(', ',@maintccs)."|\n" if $dl>2;
- $maintccs .= "Cc: " . join(",\n ",@maintccs) . "\n";
-}
+my @maintccs = determine_recipients(recipients => \%recipients,
+ address_only => 1,
+ cc => 1,
+ );
+my $maintccs = 'Cc: '.join(",\n ",
+ determine_recipients(recipients => \%recipients,
+ cc => 1,
+ )
+ )."\n";
-my %packagepr;
-for my $maint (keys %maintccreasons) {
- for my $package (keys %{$maintccreasons{$maint}}) {
- next unless length $package;
- $packagepr{$package} = 1;
- }
-}
my $packagepr = '';
-$packagepr = "X-${gProject}-PR-Package: " . join(keys %packagepr) . "\n" if keys %packagepr;
+$packagepr = "X-${gProject}-PR-Package: " . join(keys %affected_packages) . "\n" if keys %affected_packages;
# Add Bcc's to subscribed bugs
# now handled by Debbugs::Recipients
(administrator, $gProject $gBugs database)
END
-my $repliedshow= join(', ',$replyto,@maintccaddrs);
+my $repliedshow= join(', ',$replyto,
+ determine_recipients(recipients => \%recipients,
+ cc => 1,
+ address_only => 1,
+ )
+ );
# -1 is the service.in log
&filelock("lock/-1");
open(AP,">>db-h/-1.log") || die "open db-h/-1.log: $!";
&unfilelock;
utime(time,time,"db-h");
-&sendmailmessage($reply,exists $header{'x-debbugs-no-ack'}?():$replyto,@maintccaddrs,@bcc);
+&sendmailmessage($reply,
+ exists $header{'x-debbugs-no-ack'}?():$replyto,
+ make_list(values %{{determine_recipients(recipients => \%recipients,
+ address_only => 1,
+ )}}
+ ),
+ );
unlink("incoming/P$nn") || die "unlinking incoming/P$nn: $!";
}
sub sendhelp {
- &sendtxthelpraw("bug-log-mailserver.txt","instructions for request\@$gEmailDomain");
- &sendtxthelpraw("bug-maint-mailcontrol.txt","instructions for control\@$gEmailDomain")
- if $control;
+ if ($control) {
+ &sendtxthelpraw("bug-maint-mailcontrol.txt","instructions for control\@$gEmailDomain")
+ }
+ else {
+ &sendtxthelpraw("bug-log-mailserver.txt","instructions for request\@$gEmailDomain");
+ }
}
#sub unimplemented {
# print {$transcript} "Sorry, command $_[0] not yet implemented.\n\n";
#}
-
+our %checkmatch_values;
sub checkmatch {
my ($string,$mvarname,$svarvalue,@newmergelist) = @_;
my ($mvarvalue);
if (@newmergelist) {
- eval "\$mvarvalue= \$$mvarname";
+ $mvarvalue = $checkmatch_values{$mvarname};
print {$transcript} "D| checkmatch \`$string' /$mvarname/$mvarvalue/$svarvalue/\n"
if $dl;
$mismatch .=
} else {
print {$transcript} "D| setupmatch \`$string' /$mvarname/$svarvalue/\n"
if $dl;
- eval "\$$mvarname= \$svarvalue";
+ $checkmatch_values{$mvarname} = $svarvalue;
}
}