X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=scripts%2Fprocess.in;h=aed342303bb4532ef79135ba31d6a02eb71c6b54;hb=24a9fde3b533874d639fd79b2dd9b54f287e3ba0;hp=d857f8d29eb757ad527b976c256b8ca9fe1b2bcb;hpb=a637d40bcf091d949b9959fb7e3ee7991e50aa3b;p=debbugs.git diff --git a/scripts/process.in b/scripts/process.in index d857f8d..209d9db 100755 --- a/scripts/process.in +++ b/scripts/process.in @@ -4,18 +4,26 @@ # Usage: process nn # Temps: incoming/Pnn -use POSIX qw(strftime tzset); -$ENV{"TZ"} = 'UTC'; -tzset(); +use POSIX qw(strftime); use MIME::Parser; use Debbugs::MIME qw(decode_rfc1522 create_mime_message); use Debbugs::Mail qw(send_mail_message encode_headers); +use Debbugs::Packages qw(getpkgsrc); +use Debbugs::User qw(read_usertags write_usertags); -$config_path = '/etc/debbugs'; -$lib_path = '/usr/lib/debbugs'; +use Debbugs::CGI qw(html_escape); + +use Debbugs::Log qw(:misc); + +# TODO DLA; needs config reworking and errorlib reworking +# use warnings; +# use strict; + +use Debbugs::Status qw(:versions); +use Debbugs::Config qw(:globals); +my $lib_path = $gLibPath; -require "$config_path/config"; require "$lib_path/errorlib"; $ENV{'PATH'} = $lib_path.':'.$ENV{'PATH'}; @@ -25,13 +33,13 @@ chdir( "$gSpoolDir" ) || die "chdir spool: $!\n"; umask(002); open DEBUG, ">/dev/null"; -defined( $intdate= time ) || &quit( "failed to get time: $!" ); +my $intdate = time or quit("failed to get time: $!"); $_=shift; -m/^([BMQFDUL])(\d*)\.\d+$/ || &quit("bad argument"); -$codeletter= $1; -$tryref= length($2) ? $2+0 : -1; -$nn= $_; +m/^([BMQFDUL])(\d*)\.\d+$/ or quit("bad argument: $_"); +my $codeletter= $1; +my $tryref= length($2) ? $2 : -1; +my $nn= $_; if (!rename("incoming/G$nn","incoming/P$nn")) { @@ -39,7 +47,7 @@ if (!rename("incoming/G$nn","incoming/P$nn")) &quit("renaming to lock: $!"); } -$baddress= 'submit' if $codeletter eq 'B'; +my $baddress= 'submit' if $codeletter eq 'B'; $baddress= 'maintonly' if $codeletter eq 'M'; $baddress= 'quiet' if $codeletter eq 'Q'; $baddress= 'forwarded' if $codeletter eq 'F'; @@ -47,20 +55,20 @@ $baddress= 'done' if $codeletter eq 'D'; $baddress= 'submitter' if $codeletter eq 'U'; bug_list_forward($nn) if $codeletter eq 'L'; $baddress || &quit("bad codeletter $codeletter"); -$baddressroot= $baddress; +my $baddressroot= $baddress; $baddress= "$tryref-$baddress" if $tryref>=0; open(M,"incoming/P$nn"); -@log=; +my @log=; close(M); -@msg=@log; +my @msg = @log; chomp @msg; print DEBUG "###\n",join("##\n",@msg),"\n###\n"; -$tdate = strftime "%a, %d %h %Y %T UTC", localtime; -$fwd= <output_under("$gSpoolDir/mime.tmp"); my $entity = eval { $parser->parse_data(join('',@log)) }; +my $i; if ($entity and $entity->head->tags) { @headerlines = @{$entity->head->header}; chomp @headerlines; @@ -144,7 +153,8 @@ for my $phline (@bodylines) $fv =~ s/\s*$//; print DEBUG ">$fn|$fv|\n"; $fn = lc $fn; - $fv = lc $fv; + # Don't lc owner or forwarded + $fv = lc $fv unless $fh =~ /^(?:owner|forwarded|usertags|version|source-version)$/; $pheader{$fn} = $fv; print DEBUG ">$fn~$fv<\n"; } @@ -163,7 +173,7 @@ if (defined $header{'resent-from'} && !defined $header{'from'}) { } defined($header{'from'}) || &quit("no From header"); -$replyto = $header{'reply-to'}; +my $replyto = $header{'reply-to'}; $replyto = '' unless defined $replyto; $replyto =~ s/^ +//; $replyto =~ s/ +$//; @@ -171,11 +181,7 @@ unless (length $replyto) { $replyto = $header{'from'}; } -$_= $replyto; -$_= "$2 <$1>" if m/^([^\<\> \t\n\(\)]+) \(([^\(\)\<\>]+)\)$/; -$replytocompare= $_; -print DEBUG "replytocompare >$replytocompare<\n"; - +my $subject = '(no subject)'; if (!defined($header{'subject'})) { $brokenness.= <{package} or defined $pheader{package}) { + my $pkg_src = getpkgsrc(); + $source_package = $pkg_src->{defined $data->{package}?$data->{package}:$pheader{package}}; +} +$source_pr_header = "X-$gProject-PR-Source: $source_package\n" + if defined $source_package and length $source_package; + +# Done and Forwarded Bugs if ($codeletter eq 'D' || $codeletter eq 'F') { if ($replyto =~ m/$gBounceFroms/o || @@ -263,18 +280,22 @@ if ($codeletter eq 'D' || $codeletter eq 'F') $markedby= $header{'from'} eq $replyto ? $replyto : "$header{'from'} (reply to $replyto)"; my @generalcc; - if ($codeletter eq 'F') { + if ($codeletter eq 'F') { # Forwarded (&appendlog,&finish) if length($data->{forwarded}); $receivedat= "forwarded\@$gEmailDomain"; $markaswhat= 'forwarded'; $set_forwarded= $header{'to'}; + # Dissallow forwarded being set to this bug tracking system + if (defined $set_forwarded and $set_forwarded =~ /\Q$gEmailDomain\E/) { + undef $set_forwarded; + } if ( length( $gListDomain ) > 0 && length( $gForwardList ) > 0 ) { push @generalcc, "$gForwardList\@$gListDomain"; $generalcc= "$gForwardList\@$gListDomain"; } else { $generalcc=''; } - } else { + } else { # Done if (length($data->{done}) and not defined $pheader{'source-version'} and not defined $pheader{'version'}) { @@ -346,7 +367,6 @@ END $noticeccval.= join(', ', grep($_ ne $replyto,@maintaddrs)); $noticeccval =~ s/\s+\n\s+/ /g; $noticeccval =~ s/^\s+/ /; $noticeccval =~ s/\s+$//; - if (length($noticeccval)) { $noticecc= "Cc: $noticeccval\n"; } @process= ($ref,split(/ /,$data->{mergedwith})); $orgref= $ref; @@ -395,8 +415,10 @@ END Precedence => 'bulk', "X-$gProject-PR-Message" => "forwarded $ref", "X-$gProject-PR-Package" => $data->{package}, - "X-$gProject-PR-Keywords" => $data->{keywords} - ],< $data->{keywords}, + # Only have a X-$gProject-PR-Source when we know the source package + length($source_package)?("X-$gProject-PR-Source" => $source_package):(), + ],< 'bulk', "X-$gProject-PR-Message" => "closed $ref", "X-$gProject-PR-Package" => $data->{package}, - "X-$gProject-PR-Keywords" => $data->{keywords} - ],< $data->{keywords}, + # Only have a X-$gProject-PR-Source when we know the source package + length($source_package)?("X-$gProject-PR-Source" => $source_package):(), + ],< "$gMaintainerEmail", From => "$gMaintainerEmail ($gProject $gBug Tracking System)", To => "$data->{originator}", - Subject => "$gBug#$ref acknowledged by developer ($header{'subject'})", + Subject => "$gBug#$ref closed by $markedby ($header{'subject'})", "Message-ID" => "", "In-Reply-To" => "$data->{msgid}", References => "$header{'message-id'} $data->{msgid}", "X-$gProject-PR-Message" => "they-closed $ref", "X-$gProject-PR-Package" => "$data->{package}", "X-$gProject-PR-Keywords" => "$data->{keywords}", + # Only have a X-$gProject-PR-Source when we know the source package + length($source_package)?("X-$gProject-PR-Source" => $source_package):(), "Reply-To" => "$ref\@$gEmailDomain", "Content-Type" => 'text/plain; charset="utf-8"', ],<{subject}, -which was filed against the $data->{package} package. +which was filed against the $data->{package} package: + +#$ref: $data->{subject} -It has been closed by one of the developers, namely -$markedby. +It has been closed by $markedby. Their explanation is attached below. If this explanation is unsatisfactory and you have not received a better one in a separate -message then please contact the developer, by replying to this email. +message then please contact $markedby by replying +to this email. $gMaintainer (administrator, $gProject $gBugs database) @@ -628,6 +655,35 @@ END $data->{subject} = $subject; $data->{msgid} = $header{'message-id'}; writebug($ref, $data); + # Deal with usertags + if (exists $pheader{usertags}) { + my $user = $replyto; + $user = $pheader{user} if exists $pheader{user}; + $user =~ s/,.*//; + $user =~ s/^.*<(.*)>.*$/$1/; + $user =~ s/[(].*[)]//; + $user =~ s/^\s*(\S+)\s+.*$/$1/; + if ($user ne '' and Debbugs::User::is_valid_user($user)) { + $pheader{usertags} =~ s/(?:^\s+|\s+$)//g; + my %user_tags; + read_usertags(\%user_tags,$user); + for my $tag (split /[,\s]+/, $pheader{usertags}) { + if ($tag =~ /^[a-zA-Z0-9.+\@-]+/) { + my %bugs_with_tag; + @bugs_with_tag{@{$user_tags{$tag}}} = (1) x @{$user_tags{$tag}}; + $bugs_with_tag{$ref} = 1; + $user_tags{$tag} = [keys %bugs_with_tag]; + } + } + write_usertags(\%user_tags,$user); + } + else { + $brokenness .=<{package} X-$gProject-PR-Keywords: $data->{keywords} -$fwd +${source_pr_header}$fwd END -} elsif ($codeletter eq 'B') { +} elsif ($codeletter eq 'B') { # Sent to submit &htmllog($newref ? "Report" : "Information", "forwarded", join(', ',"$gSubmitList\@$gListDomain",@resentccs), "$gBug#$ref". - (length($data->{package})? "; Package ".&sani($data->{package})."" : ''). + (length($data->{package})? "; Package ".html_escape($data->{package})."" : ''). "."); &sendmessage(<{package} X-$gProject-PR-Keywords: $data->{keywords} -$fwd +${source_pr_header}$fwd END -} elsif (@resentccs or @bccs) { +} elsif (@resentccs or @bccs) { # Quiet or Maintainer # D and F done far earlier; B just done - so this must be M or Q # We preserve whichever it was in the Reply-To (possibly adding # the $gBug#). @@ -745,13 +801,13 @@ END &htmllog($newref ? "Report" : "Information", "forwarded", $resentccval, "$gBug#$ref". - (length($data->{package}) ? "; Package ".&sani($data->{package})."" : ''). + (length($data->{package}) ? "; Package ".html_escape($data->{package})."" : ''). "."); } else { &htmllog($newref ? "Report" : "Information", "stored", "", "$gBug#$ref". - (length($data->{package}) ? "; Package ".&sani($data->{package})."" : ''). + (length($data->{package}) ? "; Package ".html_escape($data->{package})."" : ''). "."); } &sendmessage(<{package} X-$gProject-PR-Keywords: $data->{keywords} -$fwd +${source_pr_header}$fwd END } -$htmlbreak= length($brokenness) ? "

\n".&sani($brokenness)."\n

\n" : ''; +$htmlbreak= length($brokenness) ? "

\n".html_escape($brokenness)."\n

\n" : ''; $htmlbreak =~ s/\n\n/\n

\n\n/g; if (length($resentccval)) { - $htmlbreak = " Copy sent to ".&sani($resentccval).".". + $htmlbreak = " Copy sent to ".html_escape($resentccval).".". $htmlbreak; } unless (exists $header{'x-debbugs-no-ack'}) { @@ -781,20 +837,23 @@ unless (exists $header{'x-debbugs-no-ack'}) { ($veryquiet ? "New $gBug report received and filed, but not forwarded." : "New $gBug report received and forwarded."). $htmlbreak); - &sendmessage($veryquiet ? < -In-Reply-To: $header{'message-id'} -References: $header{'message-id'} -Precedence: bulk -X-$gProject-PR-Message: ack-quiet $ref -X-$gProject-PR-Package: $data->{package} -X-$gProject-PR-Keywords: $data->{keywords} -Reply-To: $ref-quiet\@$gEmailDomain - + if ($veryquiet) { + &sendmessage(create_mime_message( + ["X-Loop" => "$gMaintainerEmail", + From => "$gMaintainerEmail ($gProject $gBug Tracking System)", + To => $replyto, + Subject => "$gBug#$ref: Acknowledgement of QUIET report ($subject)", + "Message-ID" => "", + "In-Reply-To" => $header{'message-id'}, + References => $header{'message-id'}, + Precedence => 'bulk', + "X-$gProject-PR-Message" => "ack-quiet $ref", + "X-$gProject-PR-Package" => $data->{package}, + "X-$gProject-PR-Keywords" => $data->{keywords}, + # Only have a X-$gProject-PR-Source when we know the source package + length($source_package)?("X-$gProject-PR-Source" => $source_package):(), + "Reply-To" => "$ref-quiet\@$gEmailDomain", + ],< -In-Reply-To: $header{'message-id'} -References: $header{'message-id'} -Precedence: bulk -X-$gProject-PR-Message: ack-maintonly $ref -X-$gProject-PR-Package: $data->{package} -X-$gProject-PR-Keywords: $data->{keywords} -Reply-To: $ref-maintonly\@$gEmailDomain - + } + elsif ($codeletter eq 'M') { # Maintonly + &sendmessage(create_mime_message( + ["X-Loop" => "$gMaintainerEmail", + From => "$gMaintainerEmail ($gProject $gBug Tracking System)", + To => $replyto, + Subject => "$gBug#$ref: Acknowledgement of maintainer-only report ($subject)", + "Message-ID" => "", + "In-Reply-To" => $header{'message-id'}, + References => $header{'message-id'}, + Precedence => 'bulk', + "X-$gProject-PR-Message" => "ack-maintonly $ref", + "X-$gProject-PR-Package" => $data->{package}, + "X-$gProject-PR-Keywords" => $data->{keywords}, + # Only have a X-$gProject-PR-Source when we know the source package + length($source_package)?("X-$gProject-PR-Source" => $source_package):(), + "Reply-To" => "$ref-maintonly\@$gEmailDomain", + ],< -In-Reply-To: $header{'message-id'} -References: $header{'message-id'} -Precedence: bulk -X-$gProject-PR-Message: ack $ref -X-$gProject-PR-Package: $data->{package} -X-$gProject-PR-Keywords: $data->{keywords} -Reply-To: $ref\@$gEmailDomain - + } + else { + &sendmessage(create_mime_message( + ["X-Loop" => "$gMaintainerEmail", + From => "$gMaintainerEmail ($gProject $gBug Tracking System)", + To => $replyto, + Subject => "$gBug#$ref: Acknowledgement ($subject)", + "Message-ID" => "", + "In-Reply-To" => $header{'message-id'}, + References => $header{'message-id'}, + Precedence => 'bulk', + "X-$gProject-PR-Message" => "ack $ref", + "X-$gProject-PR-Package" => $data->{package}, + "X-$gProject-PR-Keywords" => $data->{keywords}, + # Only have a X-$gProject-PR-Source when we know the source package + length($source_package)?("X-$gProject-PR-Source" => $source_package):(), + "Reply-To" => "$ref\@$gEmailDomain", + ],< -In-Reply-To: $header{'message-id'} -References: $header{'message-id'} -Precedence: bulk -X-$gProject-PR-Message: ack-info-quiet $ref -X-$gProject-PR-Package: $data->{package} -X-$gProject-PR-Keywords: $data->{keywords} -Reply-To: $ref-quiet\@$gEmailDomain - + if ($veryquiet) { + &sendmessage(create_mime_message( + ["X-Loop" => "$gMaintainerEmail", + From => "$gMaintainerEmail ($gProject $gBug Tracking System)", + To => $replyto, + Subject => "$gBug#$ref: Info received and FILED only (was $subject)", + "Message-ID" => "", + "In-Reply-To" => $header{'message-id'}, + References => $header{'message-id'}, + Precedence => 'bulk', + "X-$gProject-PR-Message" => "ack-info-quiet $ref", + "X-$gProject-PR-Package" => $data->{package}, + "X-$gProject-PR-Keywords" => $data->{keywords}, + # Only have a X-$gProject-PR-Source when we know the source package + length($source_package)?("X-$gProject-PR-Source" => $source_package):(), + "Reply-To" => "$ref-maintonly\@$gEmailDomain", + ],< -In-Reply-To: $header{'message-id'} -References: $header{'message-id'} -Precedence: bulk -X-$gProject-PR-Message: ack-info-maintonly $ref -X-$gProject-PR-Package: $data->{package} -X-$gProject-PR-Keywords: $data->{keywords} -Reply-To: $ref-maintonly\@$gEmailDomain - + } + elsif ($codeletter eq 'M') { + &sendmessage(create_mime_message( + ["X-Loop" => "$gMaintainerEmail", + From => "$gMaintainerEmail ($gProject $gBug Tracking System)", + To => $replyto, + Subject => "$gBug#$ref: Info received for maintainer only (was $subject)", + "Message-ID" => "", + "In-Reply-To" => $header{'message-id'}, + References => "$header{'message-id'} $data->{msgid}", + Precedence => 'bulk', + "X-$gProject-PR-Message" => "ack-info-maintonly $ref", + "X-$gProject-PR-Package" => $data->{package}, + "X-$gProject-PR-Keywords" => $data->{keywords}, + "Reply-To" => "$ref-maintonly\@$gEmailDomain", + ],< -In-Reply-To: $header{'message-id'} -References: $header{'message-id'} -Precedence: bulk -X-$gProject-PR-Message: ack-info $ref -X-$gProject-PR-Package: $data->{package} -X-$gProject-PR-Keywords: $data->{keywords} - + } + else { + &sendmessage(create_mime_message( + ["X-Loop" => "$gMaintainerEmail", + From => "$gMaintainerEmail ($gProject $gBug Tracking System)", + To => $replyto, + Subject => "$gBug#$ref: Info received ($subject)", + "Message-ID" => "", + "In-Reply-To" => $header{'message-id'}, + References => "$header{'message-id'} $data->{msgid}", + Precedence => 'bulk', + "X-$gProject-PR-Message" => "ack-info $ref", + "X-$gProject-PR-Package" => $data->{package}, + "X-$gProject-PR-Keywords" => $data->{keywords}, + # Only have a X-$gProject-PR-Source when we know the source package + length($source_package)?("X-$gProject-PR-Source" => $source_package):(), + "Reply-To" => "$ref\@$gEmailDomain", + ],<$whatobj $whatverb". - ($where eq '' ? "" : " to ".&sani($where).""). + ($where eq '' ? "" : " to ".html_escape($where).""). ":
\n". $desc. "\n\3\n") || &quit("writing db-h/$hash/$ref.log (lh): $!"); close(AP) || &quit("closing db-h/$hash/$ref.log (lh): $!"); @@ -1063,7 +1156,7 @@ sub sendmessage { #save email to the log open(AP,">>db-h/$hash/$ref.log") || &quit("opening db-h/$hash/$ref.log (lo): $!"); print(AP "\2\n",join("\4",@$recips),"\n\5\n", - @{escapelog(stripbccs($msg))},"\n\3\n") || + escape_log(stripbccs($msg)),"\n\3\n") || &quit("writing db-h/$hash/$ref.log (lo): $!"); close(AP) || &quit("closing db-h/$hash/$ref.log (lo): $!"); @@ -1078,6 +1171,7 @@ sub sendmessage { recipients => $recips); } +my $maintainerschecked = 0; sub checkmaintainers { return if $maintainerschecked++; return if !length($data->{package}); @@ -1087,7 +1181,8 @@ sub checkmaintainers { m/^\s*$/ && next; m/^(\S+)\s+(\S.*\S)\s*\n$/ || &quit("maintainers bogus \`$_'"); $a= $1; $b= $2; $a =~ y/A-Z/a-z/; - $maintainerof{$1}= $2; + # use the package which is normalized to lower case; we do this because we lc the pseudo headers. + $maintainerof{$a}= $2; } close(MAINT); open(MAINT,"$gMaintainerFileOverride") || die &quit("maintainers.override open: $!"); @@ -1096,7 +1191,8 @@ sub checkmaintainers { m/^\s*$/ && next; m/^(\S+)\s+(\S.*\S)\s*\n$/ || &quit("maintainers.override bogus \`$_'"); $a= $1; $b= $2; $a =~ y/A-Z/a-z/; - $maintainerof{$1}= $2; + # use the package which is normalized to lower case; we do this because we lc the pseudo headers. + $maintainerof{$a}= $2; } close(MAINT); open(SOURCES,"$gPackageSource") || &quit("pkgsrc open: $!");