]> git.donarmstrong.com Git - debbugs.git/blob - scripts/process.in
[project @ 2003-03-28 00:24:50 by cjwatson]
[debbugs.git] / scripts / process.in
1 #!/usr/bin/perl
2 # $Id: process.in,v 1.63 2003/03/28 00:24:50 cjwatson Exp $
3 #
4 # Usage: process nn
5 # Temps:  incoming/Pnn
6
7 use Mail::Address;
8 use MIME::Parser;
9
10 $config_path = '/etc/debbugs';
11 $lib_path = '/usr/lib/debbugs';
12
13 require "$config_path/config";
14 require "$lib_path/errorlib";
15 $ENV{'PATH'} = $lib_path.':'.$ENV{'PATH'};
16
17 chdir( "$gSpoolDir" ) || die "chdir spool: $!\n";
18
19 #open(DEBUG,"> /tmp/debbugs.debug");
20 umask(002);
21 open DEBUG, ">/dev/null";
22
23 defined( $intdate= time ) || &quit( "failed to get time: $!" );
24
25 $_=shift;
26 m/^([BMQFDU])(\d*)\.\d+$/ || &quit("bad argument");
27 $codeletter= $1;
28 $tryref= length($2) ? $2+0 : -1;
29 $nn= $_;
30
31 if (!rename("incoming/G$nn","incoming/P$nn")) 
32 {
33     $_=$!.'';  m/no such file or directory/i && exit 0;
34     &quit("renaming to lock: $!");
35 }
36
37 $baddress= 'submit' if $codeletter eq 'B';
38 $baddress= 'maintonly' if $codeletter eq 'M';
39 $baddress= 'quiet' if $codeletter eq 'Q';
40 $baddress= 'forwarded' if $codeletter eq 'F';
41 $baddress= 'done' if $codeletter eq 'D';
42 $baddress= 'submitter' if $codeletter eq 'U';
43 $baddress || &quit("bad codeletter $codeletter");
44 $baddressroot= $baddress;
45 $baddress= "$tryref-$baddress" if $tryref>=0;
46
47 open(M,"incoming/P$nn");
48 @log=<M>;
49 close(M);
50
51 @msg=@log;
52 chomp @msg;
53
54 print DEBUG "###\n",join("##\n",@msg),"\n###\n";
55
56 chop($tdate= `date -u '+%a, %d %h %Y %T GMT'`);
57 $fwd= <<END;
58 Received: via spool by $baddress\@$gEmailDomain id=$nn
59           (code $codeletter ref $tryref); $tdate
60 END
61
62 # header and decoded body respectively
63 my (@headerlines, @bodylines);
64
65 my $parser = new MIME::Parser;
66 mkdir "$gSpoolDir/mime.tmp", 0777;
67 $parser->output_under("$gSpoolDir/mime.tmp");
68 my $entity = eval { $parser->parse_data(join('',@log)) };
69
70 if ($entity and $entity->head->tags) {
71     @headerlines = @{$entity->head->header};
72     chomp @headerlines;
73
74     my $entity_body = getmailbody($entity);
75     @bodylines = $entity_body ? $entity_body->as_lines() : ();
76     chomp @bodylines;
77
78     # set $i to beginning of encoded body data, so we can dump it out
79     # verbatim later
80     $i = 0;
81     ++$i while $msg[$i] =~ /./;
82 } else {
83     # Legacy pre-MIME code, kept around in case MIME::Parser fails.
84     for ($i = 0; $i <= $#msg; $i++) {
85         $_ = $msg[$i];
86         last unless length($_);
87         while ($msg[$i+1] =~ m/^\s/) {
88             $i++;
89             $_ .= "\n".$msg[$i];
90         }
91         push @headerlines, $_;
92     }
93
94     @bodylines = @msg[$i..$#msg];
95 }
96
97 for my $hdr (@headerlines) {
98     $_ = $hdr;
99     s/\n\s/ /g;
100     &finish if m/^x-loop: (\S+)$/i && $1 eq "$gMaintainerEmail";
101     my $ins = !m/^subject:/i && !m/^reply-to:/i && !m/^return-path:/i
102            && !m/^From / && !m/^X-Debbugs-CC:/i && !m/^received:/i;
103     $fwd .= $hdr."\n" if $ins;
104     # print DEBUG ">$_<\n";
105     if (s/^(\S+):\s*//) {
106         my $v = lc $1;
107         print DEBUG ">$v=$_<\n";
108         $header{$v} = $_;
109     } else {
110         print DEBUG "!>$_<\n";
111     }
112 }
113
114 # remove blank lines
115 shift @bodylines while @bodylines and $bodylines[0] !~ /\S/;
116
117 # Strip off RFC2440-style PGP clearsigning.
118 if (@bodylines and $bodylines[0] =~ /^-----BEGIN PGP SIGNED/) {
119     shift @bodylines while @bodylines and length $bodylines[0];
120     shift @bodylines while @bodylines and $bodylines[0] !~ /\S/;
121     for my $findsig (0 .. $#bodylines) {
122         if ($bodylines[$findsig] =~ /^-----BEGIN PGP SIGNATURE/) {
123             $#bodylines = $findsig - 1;
124             last;
125         }
126     }
127     map { s/^- // } @bodylines;
128 }
129
130 # extract pseudo-headers
131 for my $phline (@bodylines)
132 {
133     last if $phline !~ m/^([\w]+):\s*(\S.*)/;
134     my ($fn, $fv) = ($1, $2);
135     print DEBUG ">$fn|$fv|\n";
136     $fn = lc $fn;
137     $fv = lc $fv;
138     $pheader{$fn} = $fv;
139     print DEBUG ">$fn~$fv<\n";
140 }
141
142
143 $fwd .= join("\n",@msg[$i..$#msg]);
144
145 print DEBUG "***\n$fwd\n***\n";
146
147 if (defined $header{'resent-from'} && !defined $header{'from'}) {
148     $header{'from'} = $header{'resent-from'};
149 }
150 defined($header{'from'}) || &quit("no From header");
151 $replyto= defined($header{'reply-to'}) ? $header{'reply-to'} : $header{'from'};
152
153 $_= $replyto;
154 $_= "$2 <$1>" if m/^([^\<\> \t\n\(\)]+) \(([^\(\)\<\>]+)\)$/;
155 $replytocompare= $_;
156 print DEBUG "replytocompare >$replytocompare<\n";
157     
158 if (!defined($header{'subject'})) 
159 {
160         $brokenness.= <<END;
161
162 Your message did not contain a Subject field. They are recommended and
163 useful because the title of a $gBug is determined using this field.
164 Please remember to include a Subject field in your messages in future.
165 END
166
167 # RFC822 actually lists it as an `optional-field'.
168
169     $subject= '(no subject)';
170 } else { 
171     $subject= $header{'subject'}; 
172 }
173
174 $ref=-1;
175 $subject =~ s/^Re:\s*//i; $_= $subject."\n";
176 if ($tryref < 0 && m/^Bug ?\#(\d+)\D/i) {
177     $tryref= $1+0; 
178 }
179
180 if ($tryref >= 0) 
181 {
182     $bfound= &lockreadbugmerge($tryref);
183     if ($bfound) { 
184         $ref= $tryref; 
185     } else {
186         &htmllog("Reply","sent", $replyto,"Unknown problem report number <code>$tryref</code>.");
187         &sendmessage(<<END, '');
188 From: $gMaintainerEmail ($gProject $gBug Tracking System)
189 To: $replyto
190 Subject: Unknown problem report $gBug#$tryref ($subject)
191 Message-ID: <handler.x.$nn.unknown\@$gEmailDomain>
192 In-Reply-To: $header{'message-id'}
193 References: $header{'message-id'} $s_msgid
194 Precedence: bulk
195 X-$gProject-PR-Message: error
196
197 You sent a message to the $gBug tracking system which gave (in the
198 Subject line or encoded into the recipient at $gEmailDomain),
199 the number of a nonexistent $gBug report (#$tryref).
200
201 This may be because that $gBug report has been resolved for more than $gRemoveAge
202 days, and the record of it has been expunged, or because you mistyped
203 the $gBug report number.
204
205 Your message was dated $header{'date'} and was sent to
206 $baddress\@$gEmailDomain.  It had
207 Message-ID $header{'message-id'}
208 and Subject $subject.
209
210 It has been filed (under junk) but otherwise ignored.
211
212 Please consult your records to find the correct $gBug report number, or
213 contact me, the system administrator, for assistance.
214
215 $gMaintainer
216 (administrator, $gProject $gBugs database)
217
218 (NB: If you are a system administrator and have no idea what I am
219 talking about this indicates a serious mail system misconfiguration
220 somewhere.  Please contact me immediately.)
221
222 END
223         &appendlog;
224         &finish;
225     }
226 } else { 
227     &filelock('lock/-1'); 
228 }
229
230 if ($codeletter eq 'D' || $codeletter eq 'F') 
231 {
232     if ($replyto =~ m/$gBounceFroms/o ||
233         $header{'from'} =~ m/$gBounceFroms/o)
234     { 
235         &quit("bounce detected !  Mwaap! Mwaap!"); 
236     }
237     $markedby= $header{'from'} eq $replyto ? $replyto :
238                "$header{'from'} (reply to $replyto)";
239     if ($codeletter eq 'F') {
240         (&appendlog,&finish) if length($s_forwarded);
241         $receivedat= "forwarded\@$gEmailDomain";
242         $markaswhat= 'forwarded';
243         $set_forwarded= $header{'to'};
244         if ( length( $gListDomain ) > 0 && length( $gFowardList ) > 0 ) {
245             $generalcc= "$gFowardList\@$gListDomain";
246         } else { 
247             $generalcc=''; 
248         }
249     } else {
250         (&appendlog,&finish) if length($s_done);
251         $receivedat= "done\@$gEmailDomain";
252         $markaswhat= 'done';
253         $set_done= $header{'from'};
254         if ( length( $gListDomain ) > 0 && length( $gDoneList ) > 0 ) {
255             $generalcc= "$gDoneList\@$gListDomain";
256         } else { 
257             $generalcc=''; 
258         }
259     }
260     if ($ref<0) {
261         &htmllog("Warning","sent",$replyto,"Message ignored.");
262         &sendmessage(<<END, '');
263 From: $gMaintainerEmail ($gProject $gBug Tracking System)
264 To: $replyto
265 Subject: Message with no $gBug number ignored by $receivedat
266          ($subject)
267 Message-ID: <header.x.$nn.warnignore\@$gEmailDomain>
268 In-Reply-To: $header{'message-id'}
269 References: $header{'message-id'} $s_msgid
270 Precedence: bulk
271 X-$gProject-PR-Message: error
272
273 You sent a message to the $gProject $gBug tracking system old-style
274 unified mark as $markaswhat address ($receivedat),
275 without a recognisable $gBug number in the Subject.
276 Your message has been filed under junk but otherwise ignored.
277
278 If you don't know what I'm talking about then probably either:
279
280 (a) you unwittingly sent a message to done\@$gEmailDomain
281 because you replied to all recipients of the message a developer used
282 to mark a $gBug as done and you modified the Subject.  In this case,
283 please do not be alarmed.  To avoid confusion do not do it again, but
284 there is no need to apologise or mail anyone asking for an explanation.
285
286 (b) you are a system administrator, reading this because the $gBug 
287 tracking system is responding to a misdirected bounce message.  In this
288 case there is a serious mail system misconfiguration somewhere - please
289 contact me immediately.
290
291 Your message was dated $header{'date'} and had
292 message-id $header{'message-id'}
293 and subject $subject.
294
295 If you need any assistance or explanation please contact me.
296
297 $gMaintainer
298 (administrator, $gProject $gBugs database)
299
300 END
301         &appendlog;
302         &finish;
303     }
304
305     &checkmaintainers;
306
307     $noticeccval.= join(', ', grep($_ ne $replyto,@maintaddrs,@addsrcaddrs));
308     $noticeccval =~ s/\s+\n\s+/ /g; 
309     $noticeccval =~ s/^\s+/ /; $noticeccval =~ s/\s+$//;
310
311     if (length($noticeccval)) { $noticecc= "Cc: $noticeccval\n"; }
312     if (length($generalcc)) { $noticecc.= "Bcc: $generalcc\n"; }
313
314     @process= ($ref,split(/ /,$s_mergedwith));
315     $orgref= $ref;
316
317     for $ref (@process) {
318         if ($ref != $orgref) {
319             &unfilelock;
320             &lockreadbug($ref) || die "huh ? $ref from $orgref out of @process";
321         }
322         $s_done= $set_done if defined($set_done);
323         $s_forwarded= $set_forwarded if defined($set_forwarded);
324         my $hash = get_hashname($ref);
325         &overwrite("db-h/$hash/$ref.status",
326            "$s_originator\n$s_date\n$s_subject\n$s_msgid\n".
327            "$s_package\n$s_keywords\n$s_done\n$s_forwarded\n$s_mergedwith\n$s_severity\n");
328         &bughook('change',$ref,
329            "$s_originator\n$s_date\n$s_subject\n$s_msgid\n".
330            "$s_package\n$s_keywords\n$s_done\n$s_forwarded\n$s_mergedwith\n$s_severity\n");
331
332         open(O,"db-h/$hash/$ref.report") || &quit("read original report: $!");
333         $x= join('',<O>); close(O);
334         if ($codeletter eq 'F') {
335             &htmllog("Reply","sent",$replyto,"You have marked $gBug as forwarded.");
336             &sendmessage(<<END."---------------------------------------\n".join( "\n", @msg ), '');
337 From: $gMaintainerEmail ($gProject $gBug Tracking System)
338 To: $replyto
339 ${noticecc}Subject: $gBug#$ref: marked as forwarded ($s_subject)
340 Message-ID: <header.$ref.$nn.ackfwdd\@$gEmailDomain>
341 In-Reply-To: $header{'message-id'}
342 References: $header{'message-id'} $s_msgid
343 Precedence: bulk
344 X-$gProject-PR-Message: forwarded $ref
345 X-$gProject-PR-Package: $s_package
346 X-$gProject-PR-Keywords: $s_keywords
347
348 Your message dated $header{'date'}
349 with message-id $header{'message-id'}
350 has caused the $gProject $gBug report #$ref,
351 regarding $s_subject
352 to be marked as having been forwarded to the upstream software
353 author(s) $s_forwarded.
354
355 (NB: If you are a system administrator and have no idea what I am
356 talking about this indicates a serious mail system misconfiguration
357 somewhere.  Please contact me immediately.)
358
359 $gMaintainer
360 (administrator, $gProject $gBugs database)
361
362 END
363
364         } else {
365             &htmllog("Reply","sent",$replyto,"You have taken responsibility.");
366             &sendmessage(<<END."--------------------------------------\n".$x."---------------------------------------\n".join( "\n", @msg ), '');
367 From: $gMaintainerEmail ($gProject $gBug Tracking System)
368 To: $replyto
369 ${noticecc}Subject: $gBug#$ref: marked as done ($s_subject)
370 Message-ID: <handler.$ref.$nn.ackdone\@$gEmailDomain>
371 In-Reply-To: $header{'message-id'}
372 References: $header{'message-id'} $s_msgid
373 Precedence: bulk
374 X-$gProject-PR-Message: closed $ref
375 X-$gProject-PR-Package: $s_package
376 X-$gProject-PR-Keywords: $s_keywords
377
378 Your message dated $header{'date'}
379 with message-id $header{'message-id'}
380 and subject line $subject
381 has caused the attached $gBug report to be marked as done.
382
383 This means that you claim that the problem has been dealt with.
384 If this is not the case it is now your responsibility to reopen the
385 $gBug report if necessary, and/or fix the problem forthwith.
386
387 (NB: If you are a system administrator and have no idea what I am
388 talking about this indicates a serious mail system misconfiguration
389 somewhere.  Please contact me immediately.)
390
391 $gMaintainer
392 (administrator, $gProject $gBugs database)
393
394 END
395             &htmllog("Notification","sent",$s_originator, 
396                 "$gBug acknowledged by developer.");
397             &sendmessage(<<END.join("\n",@msg),'');
398 From: $gMaintainerEmail ($gProject $gBug Tracking System)
399 To: $s_originator
400 Subject: $gBug#$ref acknowledged by developer
401          ($header{'subject'})
402 Message-ID: <handler.$ref.$nn.notifdone\@$gEmailDomain>
403 In-Reply-To: $s_msgid
404 References: $header{'message-id'} $s_msgid
405 X-$gProject-PR-Message: they-closed $ref
406 X-$gProject-PR-Package: $s_package
407 X-$gProject-PR-Keywords: $s_keywords
408 Reply-To: $ref\@$gEmailDomain
409
410 This is an automatic notification regarding your $gBug report
411 #$ref: $s_subject,
412 which was filed against the $s_package package.
413
414 It has been closed by one of the developers, namely
415 $markedby.
416
417 Their explanation is attached below.  If this explanation is
418 unsatisfactory and you have not received a better one in a separate
419 message then please contact the developer, by replying to this email.
420
421 $gMaintainer
422 (administrator, $gProject $gBugs database)
423
424 END
425         }
426         &appendlog;
427     }
428     &finish;
429 }
430
431 if ($ref<0) {
432     if ($codeletter eq 'U') {
433         &htmllog("Warning","sent",$replyto,"Message not forwarded.");
434         &sendmessage(<<END, '');
435 From: $gMaintainerEmail ($gProject $gBug Tracking System)
436 To: $replyto
437 Subject: Message with no $gBug number cannot be sent to submitter !
438          ($subject)
439 Message-ID: <handler.x.$nn.nonumnosub\@$gEmailDomain>
440 In-Reply-To: $header{'message-id'}
441 References: $header{'message-id'} $s_msgid
442 Precedence: bulk
443 X-$gProject-PR-Message: error
444
445 You sent a message to the $gProject $gBug tracking system send to $gBug 
446 report submitter address $baddress\@$gEmailDomain, without a
447 recognisable $gBug number in the Subject.  Your message has been filed
448 under junk but otherwise ignored.
449
450 If you don't know what I'm talking about then probably either:
451
452 (a) you unwittingly sent a message to $baddress\@$gEmailDomain
453 because you replied to all recipients of the message a developer sent
454 to a $gBug's submitter and you modified the Subject.  In this case,
455 please do not be alarmed.  To avoid confusion do not do it again, but
456 there is no need to apologise or mail anyone asking for an
457 explanation.
458
459 (b) you are a system administrator, reading this because the $gBug 
460 tracking system is responding to a misdirected bounce message.  In this
461 case there is a serious mail system misconfiguration somewhere - please
462 contact me immediately.
463
464 Your message was dated $header{'date'} and had
465 message-id $header{'message-id'}
466 and subject $subject.
467
468 If you need any assistance or explanation please contact me.
469
470 $gMaintainer
471 (administrator, $gProject $gBugs database)
472
473 END
474         &appendlog;
475         &finish;
476     }
477     if (!defined($pheader{'package'})) {
478         &htmllog("Warning","sent",$replyto,"Message not forwarded.");
479         &sendmessage(<<END."---------------------------------------------------------------------------\n".join("\n", @msg), '');
480 From: $gMaintainerEmail ($gProject $gBug Tracking System)
481 To: $replyto
482 Subject: Message with no Package: tag cannot be processed!
483          ($subject)
484 Message-ID: <handler.x.$nn.nonumnosub\@$gEmailDomain>
485 In-Reply-To: $header{'message-id'}
486 References: $header{'message-id'} $s_msgid
487 Precedence: bulk
488 X-$gProject-PR-Message: error
489
490 Your message didn't have a Package: line at the start (in the
491 pseudo-header following the real mail header), or didn't have a
492 pseudo-header at all.
493
494 This makes it much harder for us to categorise and deal with your
495 problem report. Please _resubmit_ your report and tell us which package
496 the report is on. For help, check out http://$gWebDomain/Reporting$gHTMLSuffix.
497
498 Your message was dated $header{'date'} and had
499 message-id $header{'message-id'}
500 and subject $subject.
501 The complete text of it is attached to this message.
502
503 If you need any assistance or explanation please contact me.
504
505 $gMaintainer
506 (administrator, $gProject $gBugs database)
507
508 END
509         &appendlog;
510         &finish;
511     } else {
512         $s_package= $pheader{'package'}; 
513     }
514
515     $s_versions= '';
516     if (defined($pheader{'version'})) {
517         $s_versions = $pheader{'version'};
518         $s_versions =~ s/\s+/ /;
519         # BUG: need to bounce unknown versions back to submitter here
520     }
521
522     $s_fixed_versions= '';
523     if (defined($pheader{'fixed-in-version'})) {
524         $s_fixed_versions = $pheader{'fixed-in-version'};
525         $s_fixed_versions =~ s/\s+/ /;
526     }
527
528     $s_keywords= '';
529     if (defined($pheader{'keywords'})) {
530         $s_keywords= $pheader{'keywords'};
531     } elsif (defined($pheader{'tags'})) {
532         $s_keywords= $pheader{'tags'};
533     }
534     if (length($s_keywords)) {
535         my @kws;
536         my %gkws = map { ($_, 1) } @gTags;
537         foreach my $kw (sort split(/[,\s]+/, lc($s_keywords))) {
538             push @kws, $kw if (defined $gkws{$kw});
539         }
540         $s_keywords = join(" ", @kws);
541     }
542     $s_severity= '';
543     if (defined($pheader{'severity'}) || defined($pheader{'priority'})) {
544         $s_severity= $pheader{'severity'};
545         $s_severity= $pheader{'priority'} unless ($s_severity);
546         $s_severity =~ s/^\s*(.+)\s*$/$1/;
547
548         if (!grep($_ eq $s_severity, @severities, "$gDefaultSeverity")) {
549             $brokenness.= <<END;
550
551 Your message specified a Severity: in the pseudo-header, but
552 the severity value $s_severity was not recognised.
553 The default severity $gDefaultSeverity is being used instead.
554 The recognised values are: $gShowSeverities.
555 END
556 # if we use @gSeverityList array in the above line, perl -c gives:
557 # In string, @gSeverityList now must be written as \@gSeverityList at
558 #          process line 452, near "$gDefaultSeverity is being used instead.
559             $s_severity= '';
560         }
561     }
562     &filelock("nextnumber.lock");
563     open(N,"nextnumber") || &quit("nextnumber: read: $!");
564     $v=<N>; $v =~ s/\n$// || &quit("nextnumber bad format");
565     $ref= $v+0;  $v += 1;  $newref=1;
566     &overwrite('nextnumber', "$v\n");
567     &unfilelock;
568     my $hash = get_hashname($ref);
569     &overwrite("db-h/$hash/$ref.log",'');
570     &overwrite("db-h/$hash/$ref.status",
571                "$replyto\n$intdate\n$subject\n$header{'message-id'}\n".
572                "$s_package\n$s_keywords\n\n\n\n$s_severity\n$s_versions\n".
573                "$s_fixed_versions\n");
574     &bughook('new',$ref,
575                "$replyto\n$intdate\n$subject\n$header{'message-id'}\n".
576                "$s_package\n$s_keywords\n\n\n\n$s_severity\n$s_versions\n".
577                "$s_fixed_versions\n");
578     &overwrite("db-h/$hash/$ref.report",
579                join("\n",@msg)."\n");
580 }
581
582 &checkmaintainers;
583
584 print DEBUG "maintainers >@maintaddrs<\n";
585
586 $orgsender= defined($header{'sender'}) ? "Original-Sender: $header{'sender'}\n" : '';
587 $newsubject= $subject;  $newsubject =~ s/^$gBug#$ref:*\s*//;
588
589 $xcchdr= $header{ 'x-debbugs-cc' };
590 if ($xcchdr =~ m/\S/) {
591     push(@resentccs,$xcchdr);
592     $resentccexplain.= <<END;
593
594 As you requested using X-Debbugs-CC, your message was also forwarded to
595    $xcchdr
596 (after having been given a $gBug report number, if it did not have one).
597 END
598 }
599
600 if (@maintaddrs && ($codeletter eq 'B' || $codeletter eq 'M')) {
601     push(@resentccs,@maintaddrs);
602     $resentccexplain.= <<END." ".join("\n ",@maintaddrs)."\n";
603
604 Your message has been sent to the package maintainer(s):
605 END
606 }
607
608 push(@resentccs, @addsrcaddrs);
609
610 $veryquiet= $codeletter eq 'Q';
611 if ($codeletter eq 'M' && !@maintaddrs) {
612     $veryquiet= 1;
613     $brokenness.= <<END;
614
615 You requested that the message be sent to the package maintainer(s)
616 but either the $gBug report is not associated with any package (probably
617 because of a missing Package pseudo-header field in the original $gBug
618 report), or the package(s) specified do not have any maintainer(s).
619
620 Your message has *not* been sent to any package maintainers; it has
621 merely been filed in the $gBug tracking system.  If you require assistance
622 please contact $gMaintainerEmail quoting the $gBug number $ref.
623 END
624 }
625
626 $resentccval.= join(', ',@resentccs);
627 $resentccval =~ s/\s+\n\s+/ /g; $resentccval =~ s/^\s+/ /; $resentccval =~ s/\s+$//;
628 if (length($resentccval)) { 
629     $resentcc= "Resent-CC: $resentccval\n"; 
630 }
631
632 if ($codeletter eq 'U') {
633     &htmllog("Message", "sent on", $s_originator, "$gBug#$ref.");
634     &sendmessage(<<END,$s_originator,@resentccs);
635 Subject: $gBug#$ref: $newsubject
636 Reply-To: $replyto, $ref-quiet\@$gEmailDomain
637 ${orgsender}Resent-To: $s_originator
638 ${resentcc}Resent-Date: $tdate
639 Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
640 Resent-Sender: $gMaintainerEmail
641 X-$gProject-PR-Message: report $ref
642 X-$gProject-PR-Package: $s_package
643 X-$gProject-PR-Keywords: $s_keywords
644 $fwd
645 END
646 } elsif ($codeletter eq 'B') {
647     &htmllog($newref ? "Report" : "Information", "forwarded",
648              join(', ',"$gSubmitList\@$gListDomain",@resentccs),
649              "<code>$gBug#$ref</code>".
650              (length($s_package)? "; Package <code>".&sani($s_package)."</code>" : '').
651              ".");
652     &sendmessage(<<END,"$gSubmitList\@$gListDomain",@resentccs);
653 Subject: $gBug#$ref: $newsubject
654 Reply-To: $replyto, $ref\@$gEmailDomain
655 Resent-From: $header{'from'}
656 ${orgsender}Resent-To: $gSubmitList\@$gListDomain
657 ${resentcc}Resent-Date: $tdate
658 Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
659 Resent-Sender: $gMaintainerEmail
660 X-$gProject-PR-Message: report $ref
661 X-$gProject-PR-Package: $s_package
662 X-$gProject-PR-Keywords: $s_keywords
663 $fwd
664 END
665 } elsif (@resentccs) {
666     # D and F done far earlier; B just done - so this must be M or Q
667     # We preserve whichever it was in the Reply-To (possibly adding
668     # the $gBug#).
669     &htmllog($newref ? "Report" : "Information", "forwarded",
670              $resentccval,
671              "<code>$gBug#$ref</code>".
672              (length($s_package)? "; Package <code>".&sani($s_package)."</code>" : '').
673              ".");
674     &sendmessage(<<END,@resentccs);
675 Subject: $gBug#$ref: $newsubject
676 Reply-To: $replyto, $ref-$baddressroot\@$gEmailDomain
677 Resent-From: $header{'from'}
678 ${orgsender}Resent-To: $resentccval
679 Resent-Date: $tdate
680 Resent-Message-ID: <handler.$ref.$nn\@$gEmailDomain>
681 Resent-Sender: $gMaintainerEmail
682 X-$gProject-PR-Message: report $ref
683 X-$gProject-PR-Package: $s_package
684 X-$gProject-PR-Keywords: $s_keywords
685 $fwd
686 END
687 }
688
689 $htmlbreak= length($brokenness) ? "<p>\n".&sani($brokenness)."\n<p>\n" : '';
690 $htmlbreak =~ s/\n\n/\n<P>\n\n/g;
691 if (length($resentccval)) {
692     $htmlbreak = "  Copy sent to <code>".&sani($resentccval)."</code>.".
693         $htmlbreak;
694 }
695 if ($newref) {
696     &htmllog("Acknowledgement","sent",$replyto,
697              ($veryquiet ?
698               "New $gBug report received and filed, but not forwarded." :
699               "New $gBug report received and forwarded."). $htmlbreak);
700     &sendmessage($veryquiet ? <<END : $codeletter eq 'M' ? <<END : <<END,'');
701 From: $gMaintainerEmail ($gProject $gBug Tracking System)
702 To: $replyto
703 Subject: $gBug#$ref: Acknowledgement of QUIET report
704          ($subject)
705 Message-ID: <handler.$ref.$nn.ackquiet\@$gEmailDomain>
706 In-Reply-To: $header{'message-id'}
707 References: $header{'message-id'}
708 Precedence: bulk
709 X-$gProject-PR-Message: ack-quiet $ref
710 X-$gProject-PR-Package: $s_package
711 X-$gProject-PR-Keywords: $s_keywords
712 Reply-To: $ref-quiet\@$gEmailDomain
713
714 Thank you for the problem report you have sent regarding $gProject.
715 This is an automatically generated reply, to let you know your message
716 has been received.  It has not been forwarded to the developers or
717 their mailing list; you should ensure that the developers are aware of
718 the problem you have entered into the system - preferably quoting the
719 $gBug reference number, #$ref.
720 $resentccexplain
721 If you wish to submit further information on your problem, please send it
722 to $ref-$baddressroot\@$gEmailDomain (and *not*
723 to $baddress\@$gEmailDomain).
724
725 Please do not reply to the address at the top of this message,
726 unless you wish to report a problem with the $gBug-tracking system.
727 $brokenness
728 $gMaintainer
729 (administrator, $gProject $gBugs database)
730 END
731 From: $gMaintainerEmail ($gProject $gBug Tracking System)
732 To: $replyto
733 Subject: $gBug#$ref: Acknowledgement of maintainer-only report
734          ($subject)
735 Message-ID: <handler.$ref.$nn.ackmaint\@$gEmailDomain>
736 In-Reply-To: $header{'message-id'}
737 References: $header{'message-id'}
738 Precedence: bulk
739 X-$gProject-PR-Message: ack-maintonly $ref
740 X-$gProject-PR-Package: $s_package
741 X-$gProject-PR-Keywords: $s_keywords
742 Reply-To: $ref-maintonly\@$gEmailDomain
743
744 Thank you for the problem report you have sent regarding $gProject.
745 This is an automatically generated reply, to let you know your message has
746 been received.  It is being forwarded to the developers (but not the mailing
747 list, as you requested) for their attention; they will reply in due course.
748 $resentccexplain
749 If you wish to submit further information on your problem, please send
750 it to $ref-$baddressroot\@$gEmailDomain (and *not*
751 to $baddress\@$gEmailDomain).
752
753 Please do not reply to the address at the top of this message,
754 unless you wish to report a problem with the $gBug-tracking system.
755 $brokenness
756 $gMaintainer
757 (administrator, $gProject $gBugs database)
758 END
759 From: $gMaintainerEmail ($gProject $gBug Tracking System)
760 To: $replyto
761 Subject: $gBug#$ref: Acknowledgement ($subject)
762 Message-ID: <handler.$ref.$nn.ack\@$gEmailDomain>
763 In-Reply-To: $header{'message-id'}
764 References: $header{'message-id'}
765 Precedence: bulk
766 X-$gProject-PR-Message: ack $ref
767 X-$gProject-PR-Package: $s_package
768 X-$gProject-PR-Keywords: $s_keywords
769 Reply-To: $ref\@$gEmailDomain
770
771 Thank you for the problem report you have sent regarding $gProject.
772 This is an automatically generated reply, to let you know your message has
773 been received.  It is being forwarded to the developers mailing list for
774 their attention; they will reply in due course.
775 $resentccexplain
776 If you wish to submit further information on your problem, please send
777 it to $ref\@$gEmailDomain (and *not* to
778 $baddress\@$gEmailDomain).
779
780 Please do not reply to the address at the top of this message,
781 unless you wish to report a problem with the $gBug-tracking system.
782 $brokenness
783 $gMaintainer
784 (administrator, $gProject $gBugs database)
785 END
786 } elsif ($codeletter ne 'U' and
787          $header{'precedence'} !~ /\b(?:bulk|junk|list)\b/) {
788     &htmllog("Acknowledgement","sent",$replyto,
789              ($veryquiet ? "Extra info received and filed, but not forwarded." :
790               $codeletter eq 'M' ? "Extra info received and forwarded to maintainer." :
791               "Extra info received and forwarded to list."). $htmlbreak);
792     &sendmessage($veryquiet ? <<END : $codeletter eq 'M' ? <<END : <<END,'');
793 From: $gMaintainerEmail ($gProject $gBug Tracking System)
794 To: $replyto
795 Subject: $gBug#$ref: Info received and FILED only
796          (was $subject)
797 Message-ID: <handler.$ref.$nn.ackinfoquiet\@$gEmailDomain>
798 In-Reply-To: $header{'message-id'}
799 References: $header{'message-id'}
800 Precedence: bulk
801 X-$gProject-PR-Message: ack-info-quiet $ref
802 X-$gProject-PR-Package: $s_package
803 X-$gProject-PR-Keywords: $s_keywords
804 Reply-To: $ref-quiet\@$gEmailDomain
805
806 Thank you for the additional information you have supplied regarding
807 this problem report.  It has NOT been forwarded to the developers, but
808 will accompany the original report in the $gBug tracking system.  Please
809 ensure that you yourself have sent a copy of the additional
810 information to any relevant developers or mailing lists.
811 $resentccexplain
812 If you wish to continue to submit further information on your problem,
813 please send it to $ref-$baddressroot\@$gEmailDomain, as before.
814
815 Please do not reply to the address at the top of this message,
816 unless you wish to report a problem with the $gBug-tracking system.
817 $brokenness
818 $gMaintainer
819 (administrator, $gProject $gBugs database)
820 END
821 From: $gMaintainerEmail ($gProject $gBug Tracking System)
822 To: $replyto
823 Subject: $gBug#$ref: Info received for maintainer only
824          (was $subject)
825 Message-ID: <handler.$ref.$nn.ackinfomaint\@$gEmailDomain>
826 In-Reply-To: $header{'message-id'}
827 References: $header{'message-id'}
828 Precedence: bulk
829 X-$gProject-PR-Message: ack-info-maintonly $ref
830 X-$gProject-PR-Package: $s_package
831 X-$gProject-PR-Keywords: $s_keywords
832 Reply-To: $ref-maintonly\@$gEmailDomain
833
834 Thank you for the additional information you have supplied regarding
835 this problem report.  It has been forwarded to the developer(s) (but
836 not to the mailing list) to accompany the original report.
837 $resentccexplain
838 If you wish to continue to submit further information on your problem,
839 please send it to $ref-$baddressroot\@$gEmailDomain, as before.
840
841 Please do not reply to the address at the top of this message,
842 unless you wish to report a problem with the $gBug-tracking system.
843 $brokenness
844 $gMaintainer
845 (administrator, $gProject $gBugs database)
846 END
847 From: $gMaintainerEmail ($gProject $gBug Tracking System)
848 To: $replyto
849 Subject: $gBug#$ref: Info received (was $subject)
850 Message-ID: <handler.$ref.$nn.ackinfo\@$gEmailDomain>
851 In-Reply-To: $header{'message-id'}
852 References: $header{'message-id'}
853 Precedence: bulk
854 X-$gProject-PR-Message: ack-info $ref
855 X-$gProject-PR-Package: $s_package
856 X-$gProject-PR-Keywords: $s_keywords
857 Disabled-Doogie-Reply-To: $ref\@$gEmailDomain
858
859 Thank you for the additional information you have supplied regarding
860 this problem report.  It has been forwarded to the developer(s) and
861 to the developers mailing list to accompany the original report.
862 $resentccexplain
863 If you wish to continue to submit further information on your problem,
864 please send it to $ref\@$gEmailDomain, as before.
865
866 Please do not reply to the address at the top of this message,
867 unless you wish to report a problem with the $gBug-tracking system.
868 $brokenness
869 $gMaintainer
870 (administrator, $gProject $gBugs database)
871 END
872 }
873
874 &appendlog;
875 &finish;
876
877 sub overwrite {
878     local ($f,$v) = @_;
879     open(NEW,">$f.new") || &quit("$f.new: create: $!");
880     print(NEW "$v") || &quit("$f.new: write: $!");
881     close(NEW) || &quit("$f.new: close: $!");
882     rename("$f.new","$f") || &quit("rename $f.new to $f: $!");
883 }
884
885 sub appendlog {
886     my $hash = get_hashname($ref);
887     if (!open(AP,">>db-h/$hash/$ref.log")) {
888         print DEBUG "failed open log<\n";
889         print DEBUG "failed open log err $!<\n";
890         &quit("opening db-h/$hash/$ref.log (li): $!");
891     }
892     print(AP "\7\n",@{escapelog(@log)},"\n\3\n") || &quit("writing db-h/$hash/$ref.log (li): $!");
893     close(AP) || &quit("closing db-h/$hash/$ref.log (li): $!");
894 }
895
896 sub finish {
897     utime(time,time,"db");
898     local ($u);
899     while ($u= $cleanups[$#cleanups]) { &$u; }
900     unlink("incoming/P$nn") || &quit("unlinking incoming/P$nn: $!");
901     exit $_[0];
902 }
903
904 &quit("wot no exit");
905
906 sub chldhandle { $chldexit = 'yes'; }
907
908 sub htmllog {
909     local ($whatobj,$whatverb,$where,$desc) = @_;
910     my $hash = get_hashname($ref);
911     open(AP,">>db-h/$hash/$ref.log") || &quit("opening db-h/$hash/$ref.log (lh): $!");
912     print(AP
913           "\6\n".
914           "<strong>$whatobj $whatverb</strong> to <code>".&sani($where).
915           "</code>:<br>\n". $desc.
916           "\n\3\n") || &quit("writing db-h/$hash/$ref.log (lh): $!");
917     close(AP) || &quit("closing db-h/$hash/$ref.log (lh): $!");
918 }    
919
920 sub get_addresses {
921         return
922                 map { $_->address() }
923                 map { Mail::Address->parse($_) } @_;
924 }
925
926 sub sendmessage {
927     local ($msg,@recips) = @_;
928     if ($recips[0] eq '' && $#recips == 0) { @recips= ('-t'); }
929     $msg = "X-Loop: $gMaintainerEmail\n" . $msg;
930
931     my $hash = get_hashname($ref);
932     #save email to the log
933     open(AP,">>db-h/$hash/$ref.log") || &quit("opening db-h/$hash/$ref.log (lo): $!");
934     print(AP "\2\n",join("\4",@recips),"\n\5\n",@{escapelog($msg)},"\n\3\n") ||
935         &quit("writing db-h/$hash/$ref.log (lo): $!");
936     close(AP) || &quit("closing db-h/$hash/$ref.log (lo): $!");
937     
938 #if debbuging.. save email to a log
939 #    open AP, ">>debug";
940 #    print AP join( '|', @recips )."\n>>";
941 #    print AP get_addresses( @recips );
942 #    print AP "<<\n".$msg;
943 #    print AP "\n--------------------------------------------------------\n";
944 #    close AP;
945
946     #start mailing
947     $_ = '';
948     $SIG{'CHLD'}='chldhandle';
949     #print DEBUG "mailing sigchild set up<\n";
950     $chldexit = 'no';
951     $c= open(U,"-|");
952     #print DEBUG "mailing opened pipe fork<\n";
953     defined($c) || die $!;
954     #print DEBUG "mailing opened pipe fork ok $c<\n";
955     if (!$c) { # ie, we are in the child process
956         #print DEBUG "mailing child<\n";
957         unless (open(STDERR,">&STDOUT")) {
958             #print DEBUG "mailing child opened stderr<\n";
959             print STDOUT "redirect stderr: $!\n";
960             #print DEBUG "mailing child opened stderr fail<\n";
961             exit 1;
962             #print DEBUG "mailing child opened stderr fail exit !?<\n";
963         }
964         #print DEBUG "mailing child opened stderr ok<\n";
965         $c= open(D,"|-");
966         #print DEBUG "mailing child forked again<\n";
967         defined($c) || die $!;
968         #print DEBUG "mailing child forked again ok $c<\n";
969         if (!$c) { # ie, we are the child process
970             #print DEBUG "mailing grandchild<\n";
971             exec '/usr/lib/sendmail','-f'."$gMaintainerEmail",'-odq','-oem','-oi',get_addresses(@recips);
972             #print DEBUG "mailing grandchild exec failed<\n";
973             die $!;
974             #print DEBUG "mailing grandchild died !?<\n";
975         }
976         #print DEBUG "mailing child not grandchild<\n";
977         print(D $msg) || die $!;
978         #print DEBUG "mailing child printed msg<\n";
979         close(D);
980         #print DEBUG "mailing child closed pipe<\n";
981         die "\n*** command returned exit status $?\n" if $?;
982         #print DEBUG "mailing child exit status ok<\n";
983         exit 0;
984         #print DEBUG "mailing child exited ?!<\n";
985     }
986     #print DEBUG "mailing parent<\n";
987     $results='';
988     #print DEBUG "mailing parent results emptied<\n";
989     while( $chldexit eq 'no' ) { $results.= $_; }
990     #print DEBUG "mailing parent results read >$results<\n";
991     close(U);
992     #print DEBUG "mailing parent results closed<\n";
993     $results.= "\n*** child returned exit status $?\n" if $?;
994     #print DEBUG "mailing parent exit status ok<\n";
995     $SIG{'CHLD'}='DEFAULT';
996     #print DEBUG "mailing parent sigchild default<\n";
997     if (length($results)) { &quit("running sendmail: $results"); }
998     #print DEBUG "mailing parent results ok<\n";
999 }
1000
1001 sub checkmaintainers {
1002     return if $maintainerschecked++;
1003     return if !length($s_package);
1004     open(MAINT,"$gMaintainerFile") || die &quit("maintainers open: $!");
1005     while (<MAINT>) {
1006         m/^\n$/ && next;
1007         m/^\s*$/ && next;
1008         m/^(\S+)\s+(\S.*\S)\s*\n$/ || &quit("maintainers bogus \`$_'");
1009         $a= $1; $b= $2; $a =~ y/A-Z/a-z/;
1010         $maintainerof{$1}= $2;
1011     }
1012     close(MAINT);
1013     open(MAINT,"$gMaintainerFileOverride") || die &quit("maintainers.override open: $!");
1014     while (<MAINT>) {
1015         m/^\n$/ && next;
1016         m/^\s*$/ && next;
1017         m/^(\S+)\s+(\S.*\S)\s*\n$/ || &quit("maintainers.override bogus \`$_'");
1018         $a= $1; $b= $2; $a =~ y/A-Z/a-z/;
1019         $maintainerof{$1}= $2;
1020     }
1021     close(MAINT);
1022     open(SOURCES,"$gPackageSource") || &quit("pkgsrc open: $!");
1023     while (<SOURCES>) {
1024         next unless m/^(\S+)\s+\S+\s+(\S.*\S)\s*$/;
1025         ($a,$b)=($1,$2);
1026         $a =~ y/A-Z/a-z/;
1027         $pkgsrc{$a} = $b;
1028     }
1029     close(SOURCES);
1030     $anymaintfound=0; $anymaintnotfound=0;
1031     for $p (split(m/[ \t?,()]+/,$s_package)) {
1032         $p =~ y/A-Z/a-z/;
1033         if (defined $gSubscriptionDomain) {
1034             if (defined($pkgsrc{$p})) {
1035                 push @addsrcaddrs, "$pkgsrc{$p}\@$gSubscriptionDomain";
1036             } else {
1037                 push @addsrcaddrs, "$p\@$gSubscriptionDomain";
1038             }
1039         }
1040         if (defined($maintainerof{$p})) {
1041             print DEBUG "maintainer add >$p|$maintainerof{$p}<\n";
1042             $addmaint= $maintainerof{$p};
1043             push(@maintaddrs,$addmaint) unless
1044                 $addmaint eq $replyto || grep($_ eq $addmaint, @maintaddrs);
1045             $anymaintfound++;
1046         } else {
1047             print DEBUG "maintainer none >$p<\n";
1048             push(@maintaddrs,$gUnknownMaintainerEmail) unless $anymaintnotfound;
1049             $anymaintnotfound++;
1050             last;
1051         }
1052     }
1053 }