different fields we keep an activity log on. The bugs_activity table now has a pointer into that table instead of recording the name directly. Set up a new, highly experimental email-notification scheme. To turn it on, the maintainer has to turn on the "New email tech" param, and then individual users have to turn on the "New email tech" preference. git-svn-id: svn://10.0.0.236/trunk@58386 18797224-902f-48f8-a5cc-f745e15eee43
684 lines
20 KiB
Perl
Executable File
684 lines
20 KiB
Perl
Executable File
#!/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): Terry Weissman <terry@mozilla.org>,
|
|
# Bryce Nesbitt <bryce-mozilla@nextbus.com>
|
|
|
|
# To recreate the shadow database, run "processmail regenerate" .
|
|
|
|
use diagnostics;
|
|
use strict;
|
|
|
|
require "globals.pl";
|
|
|
|
$| = 1;
|
|
|
|
umask(0);
|
|
|
|
$::lockcount = 0;
|
|
my $regenerate = 0;
|
|
my $nametoexclude = "";
|
|
|
|
my @forcecc;
|
|
|
|
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 "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;
|
|
}
|
|
}
|
|
|
|
sub FileSize {
|
|
my ($filename) = (@_);
|
|
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
|
|
$atime,$mtime,$ctime,$blksize,$blocks)
|
|
= stat($filename);
|
|
if (defined $size) {
|
|
return $size;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
sub Different {
|
|
my ($file1, $file2) = (@_);
|
|
my $size1 = FileSize($file1);
|
|
my $size2 = FileSize($file2);
|
|
if ($size1 != $size2) {
|
|
return 1;
|
|
}
|
|
open(FID1, "<$file1") || die "Can't open $file1";
|
|
open(FID2, "<$file2") || die "Can't open $file2";
|
|
my $d1;
|
|
my $d2;
|
|
if (read(FID1, $d1, $size1) ne $size1) {
|
|
die "Can't read $size1 bytes from $file1";
|
|
}
|
|
if (read(FID2, $d2, $size2) ne $size2) {
|
|
die "Can't read $size2 bytes from $file2";
|
|
}
|
|
close FID1;
|
|
close FID2;
|
|
return ($d1 ne $d2);
|
|
}
|
|
|
|
|
|
sub DescCC {
|
|
my ($cclist) = (@_);
|
|
if (scalar(@$cclist) <= 0) {
|
|
return "";
|
|
}
|
|
return "Cc: " . join(", ", @$cclist) . "\n";
|
|
}
|
|
|
|
|
|
sub DescDependencies {
|
|
my ($id) = (@_);
|
|
if (!Param("usedependencies")) {
|
|
return "";
|
|
}
|
|
my $result = "";
|
|
my $me = "blocked";
|
|
my $target = "dependson";
|
|
my $title = "BugsThisDependsOn";
|
|
for (1..2) {
|
|
SendSQL("select $target from dependencies where $me = $id order by $target");
|
|
my @list;
|
|
while (MoreSQLData()) {
|
|
push(@list, FetchOneColumn());
|
|
}
|
|
if (@list) {
|
|
my @verbose;
|
|
my $count = 0;
|
|
foreach my $i (@list) {
|
|
SendSQL("select bug_status, resolution from bugs where bug_id = $i");
|
|
my ($bug_status, $resolution) = (FetchSQLData());
|
|
my $desc;
|
|
if ($bug_status eq "NEW" || $bug_status eq "ASSIGNED" ||
|
|
$bug_status eq "REOPENED") {
|
|
$desc = "";
|
|
} else {
|
|
$desc = "[$resolution]";
|
|
}
|
|
push(@verbose, $i . "$desc");
|
|
$count++;
|
|
}
|
|
if ($count > 5) {
|
|
$result .= "$title: Big list (more than 5) has been omitted\n";
|
|
} else {
|
|
$result .= "$title: " . join(', ', @verbose) . "\n";
|
|
}
|
|
}
|
|
my $tmp = $me;
|
|
$me = $target;
|
|
$target = $tmp;
|
|
$title = "OtherBugsDependingOnThis";
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
|
|
|
|
sub GetBugText {
|
|
my ($id) = (@_);
|
|
undef %::bug;
|
|
|
|
my @collist = ("bug_id", "product", "version", "rep_platform", "op_sys",
|
|
"bug_status", "resolution", "priority", "bug_severity",
|
|
"assigned_to", "reporter", "bug_file_loc",
|
|
"short_desc", "component", "qa_contact", "target_milestone",
|
|
"status_whiteboard", "groupset");
|
|
|
|
my $query = "select " . join(", ", @collist) .
|
|
" from bugs where bug_id = $id";
|
|
|
|
SendSQL($query);
|
|
|
|
my @row;
|
|
if (!(@row = FetchSQLData())) {
|
|
return "";
|
|
}
|
|
foreach my $field (@collist) {
|
|
$::bug{$field} = shift @row;
|
|
if (!defined $::bug{$field}) {
|
|
$::bug{$field} = "";
|
|
}
|
|
}
|
|
|
|
$::bug{'assigned_to'} = DBID_to_name($::bug{'assigned_to'});
|
|
$::bug{'reporter'} = DBID_to_name($::bug{'reporter'});
|
|
my $qa_contact = "";
|
|
my $target_milestone = "";
|
|
my $status_whiteboard = "";
|
|
if (Param('useqacontact') && $::bug{'qa_contact'} > 0) {
|
|
$::bug{'qa_contact'} = DBID_to_name($::bug{'qa_contact'});
|
|
$qa_contact = "QAContact: $::bug{'qa_contact'}\n";
|
|
} else {
|
|
$::bug{'qa_contact'} = "";
|
|
}
|
|
if (Param('usetargetmilestone') && $::bug{'target_milestone'} ne "") {
|
|
$target_milestone = "TargetMilestone: $::bug{'target_milestone'}\n";
|
|
}
|
|
if (Param('usestatuswhiteboard') && $::bug{'status_whiteboard'} ne "") {
|
|
$status_whiteboard = "StatusWhiteboard: $::bug{'status_whiteboard'}\n";
|
|
}
|
|
|
|
$::bug{'long_desc'} = GetLongDescription($id);
|
|
|
|
my @cclist;
|
|
@cclist = split(/,/, ShowCcList($id));
|
|
my @voterlist;
|
|
SendSQL("select profiles.login_name from votes, profiles where votes.bug_id = $id and profiles.userid = votes.who");
|
|
while (MoreSQLData()) {
|
|
my $v = FetchOneColumn();
|
|
push(@voterlist, $v);
|
|
}
|
|
$::bug{'cclist'} = join(',', @cclist);
|
|
$::bug{'voterlist'} = join(',', @voterlist);
|
|
|
|
if (Param("prettyasciimail")) {
|
|
my $temp = formline <<'END',$::bug{'short_desc'},$id,$::bug{'product'},$::bug{'bug_status'},$::bug{'version'},$::bug{'resolution'},$::bug{'rep_platform'},$::bug{'bug_severity'},$::bug{'op_sys'},$::bug{'priority'},$::bug{'component'},$::bug{'assigned_to'},$::bug{'reporter'},$qa_contact,DescCC(\@cclist),$target_milestone,${status_whiteboard},$::bug{'bug_file_loc'},DescDependencies($id);
|
|
+============================================================================+
|
|
| @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
|
|
+----------------------------------------------------------------------------+
|
|
| Bug #: @<<<<<<<<<<< Product: @<<<<<<<<<<<<<<<<<<<<<< |
|
|
| Status: @<<<<<<<<<<<<<<<<<< Version: @<<<<<<<<<<<<<<<<<<<<<< |
|
|
| Resolution: @<<<<<<<<<<<<<<<<<< Platform: @<<<<<<<<<<<<<<<<<<<<<< |
|
|
| Severity: @<<<<<<<<<<<<<<<<<< OS/Version: @<<<<<<<<<<<<<<<<<<<<<< |
|
|
| Priority: @<<<<<<<<<<<<<<<<<< Component: @<<<<<<<<<<<<<<<<<<<<<< |
|
|
+----------------------------------------------------------------------------+
|
|
| Assigned To: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
|
|
| Reported By: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
|
|
| ~QA Contact: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
|
|
| ~ CC list: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
|
|
+----------------------------------------------------------------------------+
|
|
| ~ Milestone: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
|
|
|~ Whiteboard: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
|
|
| URL: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
|
|
|~Dependencies: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
|
|
+============================================================================+
|
|
| DESCRIPTION |
|
|
END
|
|
|
|
my $prettymail = $^A . $::bug{'long_desc'};
|
|
return $prettymail;
|
|
|
|
|
|
} else {
|
|
return "Bug\#: $id
|
|
Product: $::bug{'product'}
|
|
Version: $::bug{'version'}
|
|
Platform: $::bug{'rep_platform'}
|
|
OS/Version: $::bug{'op_sys'}
|
|
Status: $::bug{'bug_status'}
|
|
Resolution: $::bug{'resolution'}
|
|
Severity: $::bug{'bug_severity'}
|
|
Priority: $::bug{'priority'}
|
|
Component: $::bug{'component'}
|
|
AssignedTo: $::bug{'assigned_to'}
|
|
ReportedBy: $::bug{'reporter'}
|
|
$qa_contact$target_milestone${status_whiteboard}URL: $::bug{'bug_file_loc'}
|
|
" . DescCC(\@cclist) . "Summary: $::bug{'short_desc'}
|
|
" . DescDependencies($id) . "
|
|
$::bug{'long_desc'}
|
|
";
|
|
}
|
|
|
|
}
|
|
|
|
|
|
my $didexclude = 0;
|
|
my %seen;
|
|
my @sentlist;
|
|
sub fixaddresses {
|
|
my ($field, $list) = (@_);
|
|
my @result;
|
|
foreach my $i (@$list) {
|
|
if (!defined $i || $i eq "") {
|
|
next;
|
|
}
|
|
SendSQL("select emailnotification, groupset & $::bug{'groupset'} from profiles where login_name = " .
|
|
SqlQuote($i));
|
|
my ($emailnotification, $groupset) = (FetchSQLData());
|
|
if ($groupset ne $::bug{'groupset'}) {
|
|
next;
|
|
}
|
|
if ($emailnotification eq "CConly") {
|
|
if ($field ne "cc") {
|
|
next;
|
|
}
|
|
}
|
|
if ($emailnotification eq "ExcludeSelfChanges" &&
|
|
(lc($i) eq $nametoexclude)) {
|
|
$didexclude = 1;
|
|
next;
|
|
}
|
|
|
|
if (!defined $::nomail{$i} && !defined $seen{$i}) {
|
|
push(@result, $i . Param('emailsuffix'));
|
|
$seen{$i} = 1;
|
|
}
|
|
}
|
|
return join(", ", @result);
|
|
}
|
|
|
|
|
|
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 FormatTriple {
|
|
my ($a, $b, $c) = (@_);
|
|
$^A = "";
|
|
my $temp = formline << 'END', $a, $b, $c;
|
|
^>>>>>>>>>>>>>>>>>>|^<<<<<<<<<<<<<<<<<<<<<<<<<<<|^<<<<<<<<<<<<<<<<<<<<<<<<<<~~
|
|
END
|
|
; # This semicolon appeases my emacs editor macros. :-)
|
|
return $^A;
|
|
}
|
|
|
|
sub FormatDouble {
|
|
my ($a, $b) = (@_);
|
|
$a .= ":";
|
|
$^A = "";
|
|
my $temp = formline << 'END', $a, $b;
|
|
^>>>>>>>>>>>>>>>>>> ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~~
|
|
END
|
|
; # This semicolon appeases my emacs editor macros. :-)
|
|
return $^A;
|
|
}
|
|
|
|
|
|
sub NewProcessOneBug {
|
|
my ($id) = (@_);
|
|
|
|
my @headerlist;
|
|
my %values;
|
|
my %defmailhead;
|
|
my %fielddescription;
|
|
|
|
my $msg = "";
|
|
|
|
SendSQL("SELECT name, description, mailhead FROM fielddefs " .
|
|
"ORDER BY sortkey");
|
|
while (MoreSQLData()) {
|
|
my ($field, $description, $mailhead) = (FetchSQLData());
|
|
push(@headerlist, $field);
|
|
$defmailhead{$field} = $mailhead;
|
|
$fielddescription{$field} = $description;
|
|
}
|
|
SendSQL("SELECT " . join(',', @::log_columns) . ", lastdiffed, now() " .
|
|
"FROM bugs WHERE bug_id = $id");
|
|
my @row = FetchSQLData();
|
|
foreach my $i (@::log_columns) {
|
|
$values{$i} = shift(@row);
|
|
}
|
|
my ($start, $end) = (@row);
|
|
$values{'cc'} = ShowCcList($id);
|
|
|
|
|
|
$values{'assigned_to'} = DBID_to_name($values{'assigned_to'});
|
|
$values{'reporter'} = DBID_to_name($values{'reporter'});
|
|
if ($values{'qa_contact'}) {
|
|
$values{'qa_contact'} = DBID_to_name($values{'qa_contact'});
|
|
}
|
|
|
|
my @diffs;
|
|
|
|
|
|
SendSQL("SELECT profiles.login_name, fielddefs.description, " .
|
|
" bug_when, oldvalue, newvalue " .
|
|
"FROM bugs_activity, fielddefs, profiles " .
|
|
"WHERE bug_id = $id " .
|
|
" AND fielddefs.fieldid = bugs_activity.fieldid " .
|
|
" AND profiles.userid = who " .
|
|
" AND bug_when > '$start' " .
|
|
" AND bug_when <= '$end' " .
|
|
"ORDER BY bug_when"
|
|
);
|
|
|
|
while (MoreSQLData()) {
|
|
my @row = FetchSQLData();
|
|
push(@diffs, \@row);
|
|
}
|
|
|
|
my $difftext = "";
|
|
my $lastwho = "";
|
|
foreach my $ref (@diffs) {
|
|
my ($who, $what, $when, $old, $new) = (@$ref);
|
|
if ($who ne $lastwho) {
|
|
$lastwho = $who;
|
|
$difftext .= "\n$who changed:\n\n";
|
|
$difftext .= FormatTriple("What ", "Old Value", "New Value");
|
|
$difftext .= ('-' x 76) . "\n";
|
|
}
|
|
$difftext .= FormatTriple($what, $old, $new);
|
|
}
|
|
|
|
$difftext = trim($difftext);
|
|
|
|
|
|
my $newcomments = GetLongDescription($id, $start, $end);
|
|
|
|
my $count = 0;
|
|
for my $person ($values{'assigned_to'}, $values{'reporter'},
|
|
split(/,/, $values{'cc'}),
|
|
@forcecc) {
|
|
$count++;
|
|
if ($seen{$person}) {
|
|
next;
|
|
}
|
|
|
|
SendSQL("SELECT userid, emailnotification, newemailtech," .
|
|
" groupset & $values{'groupset'} " .
|
|
"FROM profiles WHERE login_name = " . SqlQuote($person));
|
|
my ($userid, $emailnotification, $newemailtech,
|
|
$groupset) = (FetchSQLData());
|
|
if (!$newemailtech || !Param('newemailtech')) {
|
|
next;
|
|
}
|
|
$seen{$person} = 1;
|
|
if ($groupset ne $values{'groupset'}) {
|
|
next;
|
|
}
|
|
if ($emailnotification eq "ExcludeSelfChanges" &&
|
|
lc($person) eq $nametoexclude) {
|
|
$didexclude = 1;
|
|
next;
|
|
}
|
|
if ($emailnotification eq "CCOnly" && $count < 3) {
|
|
next;
|
|
}
|
|
|
|
my %mailhead = %defmailhead;
|
|
|
|
# SendSQL("SELECT name, mailhead, maildiffs FROM diffprefs, fielddefs WHERE fielddefs.fieldid = diffprefs.fieldid AND userid = $userid");
|
|
# while (MoreSQLData()) {
|
|
# my ($field, $h, $d) = (FetchSQLData());
|
|
# $mailhead{$field} = $h;
|
|
# $maildiffs{$field} = $d;
|
|
# }
|
|
|
|
# my $maxlen = 0;
|
|
# foreach my $f (keys %mailhead) {
|
|
# if ($mailhead{$f}) {
|
|
# my $l = length($fielddescription{$f});
|
|
# if ($maxlen < $l) {
|
|
# $maxlen = $l;
|
|
# }
|
|
# }
|
|
# }
|
|
|
|
my $head = "";
|
|
|
|
foreach my $f (@headerlist) {
|
|
if ($mailhead{$f}) {
|
|
my $value = $values{$f};
|
|
if (!defined $value) {
|
|
# Probaby ought to whine or something. ###
|
|
next;
|
|
}
|
|
my $desc = $fielddescription{$f};
|
|
$head .= FormatDouble($desc, $value);
|
|
|
|
# my $extra = $maxlen - length($desc);
|
|
# $head .= ($extra x " ");
|
|
# $head .= $desc . ": ";
|
|
# while (1) {
|
|
# if (length($value) < 70) {
|
|
# $head .= $value . "\n";
|
|
# last;
|
|
# }
|
|
# my $pos = rindex($value, " ", 70);
|
|
# if ($pos < 0) {
|
|
# $pos = rindex($value, ",", 70);
|
|
# if ($pos < 0) {
|
|
# $pos = 70;
|
|
# }
|
|
# }
|
|
# $head .= substr($value, 0, 70) . "\n";
|
|
# $head .= (($extra + 2) x " ");
|
|
# $value = substr($value, 70);
|
|
# }
|
|
}
|
|
}
|
|
if ($difftext eq "" && $newcomments eq "") {
|
|
# Whoops, no differences!
|
|
next;
|
|
}
|
|
|
|
my $isnew = ($start !~ m/[1-9]/);
|
|
|
|
my %substs;
|
|
$substs{"neworchanged"} = $isnew ? "New" : "Changed";
|
|
$substs{"to"} = $person;
|
|
$substs{"cc"} = '';
|
|
$substs{"bugid"} = $id;
|
|
if ($isnew) {
|
|
$substs{"diffs"} = $head . "\n\n" . $newcomments;
|
|
} else {
|
|
$substs{"diffs"} = $difftext . "\n\n" . $newcomments;
|
|
}
|
|
$substs{"summary"} = $values{'short_desc'};
|
|
|
|
# my $template = Param("changedmail");
|
|
my $template = "From: bugzilla-daemon
|
|
To: %to%
|
|
Cc: %cc%
|
|
Subject: [Bug %bugid%] %neworchanged% - %summary%
|
|
|
|
%urlbase%show_bug.cgi?id=%bugid%
|
|
|
|
%diffs%";
|
|
|
|
my $msg = PerformSubsts(Param("changedmail"), \%substs);
|
|
open(SENDMAIL, "|/usr/lib/sendmail -t") ||
|
|
die "Can't open sendmail";
|
|
|
|
print SENDMAIL trim($msg);
|
|
close SENDMAIL;
|
|
push(@sentlist, $person);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SendSQL("UPDATE bugs SET lastdiffed = '$end', delta_ts = delta_ts " .
|
|
"WHERE bug_id = $id");
|
|
}
|
|
|
|
|
|
|
|
sub ProcessOneBug {
|
|
my $i = $_[0];
|
|
NewProcessOneBug($i);
|
|
my $old = "shadow/$i";
|
|
my $new = "shadow/$i.tmp.$$";
|
|
my $diffs = "shadow/$i.diffs.$$";
|
|
my $verb = "Changed";
|
|
if (!stat($old)) {
|
|
mkdir "shadow", 0777;
|
|
chmod 0777, "shadow";
|
|
open(OLD, ">$old") || die "Couldn't create null $old";
|
|
close OLD;
|
|
$verb = "New";
|
|
}
|
|
my $text = GetBugText($i);
|
|
if ($text eq "") {
|
|
die "Couldn't find bug $i.";
|
|
}
|
|
open(FID, ">$new") || die "Couldn't create $new";
|
|
print FID $text;
|
|
close FID;
|
|
if (Different($old, $new)) {
|
|
system("diff -c -b $old $new > $diffs");
|
|
my $tolist = fixaddresses("to",
|
|
[$::bug{'assigned_to'}, $::bug{'reporter'},
|
|
$::bug{'qa_contact'}]);
|
|
my @combinedcc;
|
|
foreach my $v (split(/,/, "$::bug{'cclist'},$::bug{'voterlist'}")) {
|
|
push @combinedcc, $v;
|
|
}
|
|
push (@combinedcc, (@forcecc));
|
|
my $cclist = fixaddresses("cc", \@combinedcc);
|
|
my $logstr = "Bug $i $verb";
|
|
if ($tolist ne "" || $cclist ne "") {
|
|
my %substs;
|
|
|
|
$substs{"fullbugreport"} = $text; # added ability to include the full bug report
|
|
$substs{"to"} = $tolist;
|
|
$substs{"cc"} = $cclist;
|
|
$substs{"bugid"} = $i;
|
|
$substs{"diffs"} = "";
|
|
open(DIFFS, "<$diffs") || die "Can't open $diffs";
|
|
while (<DIFFS>) {
|
|
$substs{"diffs"} .= $_;
|
|
}
|
|
close DIFFS;
|
|
$substs{"neworchanged"} = $verb;
|
|
$substs{"summary"} = $::bug{'short_desc'};
|
|
my $msg = PerformSubsts(Param("changedmail"), \%substs);
|
|
|
|
if (!$regenerate) {
|
|
# Note: fixaddresses may result in a Cc: only. This seems
|
|
# harmless.
|
|
open(SENDMAIL, "|/usr/lib/sendmail -t") ||
|
|
die "Can't open sendmail";
|
|
|
|
print SENDMAIL $msg;
|
|
close SENDMAIL;
|
|
foreach my $n (split(/[, ]+/, "$tolist,$cclist")) {
|
|
if ($n ne "") {
|
|
push(@sentlist, $n);
|
|
}
|
|
}
|
|
|
|
$logstr = "$logstr; mail sent to $tolist, $cclist";
|
|
}
|
|
if (@sentlist) {
|
|
print "<B>Email sent to:</B> " . join(", ", @sentlist) . "\n";
|
|
if ($didexclude) {
|
|
print "<B>Excluding:</B> $nametoexclude (<a href=changepassword.cgi>change your preferences</a> if you wish not to be excluded)\n";
|
|
}
|
|
}
|
|
}
|
|
unlink($diffs);
|
|
Log($logstr);
|
|
}
|
|
rename($new, $old) || die "Can't rename $new to $old";
|
|
chmod 0666, $old;
|
|
if ($regenerate) {
|
|
print "$i ";
|
|
}
|
|
%seen = ();
|
|
@sentlist = ();
|
|
}
|
|
|
|
# Code starts here
|
|
|
|
ConnectToDatabase();
|
|
GetVersionTable();
|
|
Lock();
|
|
|
|
if (open(FID, "<data/nomail")) {
|
|
while (<FID>) {
|
|
$::nomail{trim($_)} = 1;
|
|
}
|
|
close FID;
|
|
}
|
|
|
|
# To recreate the shadow database, run "processmail regenerate" .
|
|
if ($ARGV[0] eq "regenerate") {
|
|
$regenerate = 1;
|
|
shift @ARGV;
|
|
SendSQL("select bug_id from bugs order by bug_id");
|
|
my @regenerate_list;
|
|
while (my @row = FetchSQLData()) {
|
|
push @regenerate_list, $row[0];
|
|
}
|
|
foreach my $i (@regenerate_list) {
|
|
ProcessOneBug($i);
|
|
Unlock();
|
|
Lock();
|
|
}
|
|
print("\n");
|
|
exit;
|
|
}
|
|
|
|
if ($ARGV[0] eq "-forcecc") {
|
|
shift(@ARGV);
|
|
foreach my $i (split(/,/, shift(@ARGV))) {
|
|
push(@forcecc, trim($i));
|
|
}
|
|
}
|
|
|
|
if (($#ARGV < 0) || ($#ARGV > 1)) {
|
|
print "Usage error: processmail {bugid} {nametoexclude}\nOr: processmail regenerate\n";
|
|
exit;
|
|
}
|
|
|
|
if ($#ARGV == 1) {
|
|
$nametoexclude = lc($ARGV[1]);
|
|
}
|
|
|
|
if ($ARGV[0] eq "rescanall") {
|
|
print "<br> Collecting bug ids...\n";
|
|
SendSQL("select bug_id from bugs where to_days(now()) - to_days(delta_ts) <= 2 order by bug_id");
|
|
my @list;
|
|
while (my @row = FetchSQLData()) {
|
|
push @list, $row[0];
|
|
}
|
|
foreach my $id (@list) {
|
|
$ARGV[0] = $id;
|
|
print "<br> Doing bug $id\n";
|
|
ProcessOneBug($ARGV[0]);
|
|
}
|
|
} else {
|
|
ProcessOneBug($ARGV[0]);
|
|
}
|
|
|
|
exit;
|