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