--- /dev/null
+#!/usr/bin/perl
+# $Id: db2html.in,v 1.22 2004/04/19 10:03:53 cjwatson Exp $
+# usage: db2html [-diff] [-stampfile=<stampfile>] [-lastrun=<days>] <wwwbase>
+
+#load the necessary libraries/configuration
+$config_path = '/etc/debbugs';
+$lib_path = '/usr/lib/debbugs';
+
+require("$config_path/config");
+require("$config_path/text");
+require("$lib_path/errorlib");
+$ENV{'PATH'} = $lib_path.':'.$ENV{'PATH'};
+
+use POSIX qw(strftime tzset);
+$ENV{"TZ"} = 'UTC';
+tzset();
+
+#set current working directory
+chdir("$gSpoolDir") || die "chdir spool: $!\n";
+
+#setup variables
+$diff = 0;
+$stampfile = 'stamp.html';
+$tail_html = $gHTMLTail;
+$expirynote_html = '';
+$expirynote_html = $gHTMLExpireNote if $gRemoveAge;
+$shorthead = ' Ref * Package Keywords/Subject Submitter';
+$shortindex = '';
+$amonths = -1;
+$indexunmatched = '';
+%displayshowpendings = ('pending','outstanding',
+ 'done','resolved',
+ 'forwarded','forwarded to upstream software authors');
+
+#set timestamp for html files
+$dtime = strftime "%a, %e %b %Y %T UTC", localtime;
+$tail_html =~ s/SUBSTITUTE_DTIME/$dtime/;
+
+#check for commandline switches
+while (@ARGV && $ARGV[0] =~ m/^-/)
+{ if ($ARGV[0] eq '-diff') { $diff=1; }
+ elsif ($ARGV[0] =~ m/^-lastrun\=([0-9.]+)$/) { $lastrun= $1; undef $stampfile; }
+ elsif ($ARGV[0] =~ m/^-full$/) { undef $lastrun; undef $stampfile; }
+ elsif ($ARGV[0] =~ m/^-stampfile\=(\S+)$/) { $stampfile= $1; }
+ else { &quit("bad usage"); }
+ shift;
+}
+
+#check for remaing argument, only one...
+@ARGV==1 or die;
+$wwwbase= shift(@ARGV);
+
+#get starting time
+defined($startdate= time) || &quit("failed to get time: $!");
+
+$|=1;
+
+#if stamp file was given,
+if (defined($stampfile))
+{ if (open(X,"< $stampfile"))
+ { $lastrun= -M X;
+ close(X);
+ printf "progress last run %.7f days\n",$lastrun;
+ } else { print "progress stamp file $stampfile: $! - full\n"; }
+}
+
+#only process file if greater than last run...
+if (defined($lastrun) && -M "db-h" > $lastrun)
+{ $_= $gHTMLStamp;
+ s/SUBSTITUTE_DTIME/$dtime/o;
+ s/\<\!\-\-updateupdate\-\-\>.*\<\!\-\-\/updateupdate\-\-\>/check/;
+ &file('ix/zstamp.html','non',$_."</body></html>\n");
+ print "noremoves";
+# print "db2html: no changes since last run\n";
+ exit 0;
+}
+
+#parse maintainer file
+open(MM,"$gMaintainerFile") || &quit("open $gMaintainerFile: $!");
+while(<MM>)
+{ m/^(\S+)\s+(\S.*\S)\s*$/ || &quit("$gMaintainerFile: \`$_'");
+ ($a,$b)=($1,$2);
+ $a =~ y/A-Z/a-z/;
+ $maintainer{$a}= $b;
+}
+close(MM);
+
+#load all database files
+opendir(D,'db-h') || &quit("opendir db-h: $!");
+@dirs = grep(s#^#db-h/#,grep(/^\d+$/,readdir(D)));
+closedir(D);
+foreach my $dir (@dirs) {
+ opendir(D,$dir);
+ push @files, grep(/^-?\d+\.log$/,readdir(D));
+ closedir(D);
+}
+@files = sort { $a <=> $b } @files;
+
+for $pending (qw(pending done forwarded))
+{ for $severity (@showseverities)
+ { eval "\$index${pending}${severity}= \$iiindex${pending}${severity}= ''; 1;"
+ or &quit("reset \$index${pending}${severity}: $@");
+ }
+}
+
+for $f (@files)
+{ next unless $f =~ m/^(-?\d+)\.log$/;
+ $ref= $1;
+ #((print STDERR "$ref\n"),
+ #next
+ #)
+ # unless $ref =~ m/^-/ || $ref =~ m/^124/;
+ &filelock("lock/$ref");
+ $preserveonly= defined($lastrun) && -M "db-h/".get_hashname($ref)."/$ref.log" > $lastrun;
+ if ($ref =~ m/^-\d$/)
+ { $week= $ref eq '-1' ? 'this week' :
+ $ref eq '-2' ? 'last week' :
+ $ref eq '-3' ? 'two weeks ago' :
+ ($ref-1)." weeks ago";
+ $linkto= "ju/unmatched$ref";
+ $short= "junk, $week";
+ $descriptivehead=
+ "This includes messages sent to <code>done\@$gEmailDomain</code>\n".
+ "which did not have a $gBug reference number in the Subject line\n".
+ "or which contained an\n".
+ "unknown or out of date $gBug report number (these cause a warning\n".
+ "to be sent to the sender) and details about the messages\n".
+ "sent to <code>request@$gEmailDomain</code> (all of which".
+ "produce replies).\n";
+ $indexlink= "Messages not matched to a specific $gBug report - $week";
+ $data->{subject}= '';
+ $indexentry= '';
+ undef $tpack;
+ undef $tmaint;
+ undef $iiref;
+ $tpackfile= "pnone.html";
+ $indexpart= 'unmatched';
+ } else
+ {
+ $data=readbug($ref);
+ $_= $data->{package}; y/A-Z/a-z/; $_= $` if m/[^-+._a-z0-9()]/;
+ $tpack= $_;
+ if ($data->{severity} eq '' || $data->{severity} eq 'normal')
+ { $showseverity= '';
+ $addseverity= $gDefaultSeverity;
+ } elsif (isstrongseverity($data->{severity}))
+ { $showseverity= "<strong>Severity: $data->{severity}</strong>;\n";
+ $addseverity= $data->{severity};
+ } else
+ { $showseverity= "Severity: <em>$data->{severity}</em>;\n";
+ $addseverity= $data->{severity};
+ }
+ $days= int(($startdate - $data->{date})/86400); close(S);
+ $indexlink= "#$ref: ".&sani($data->{subject});
+ $indexentry= '';
+ $packfile= length($tpack) ? "pa/l$tpack.html" : "pa/none.html";
+ $indexentry .= "Package: <A href=\"../$packfile\"><strong>".
+ &sani($data->{package})."</strong></A>;\n"
+ if length($data->{package});
+ $indexentry .= $showseverity;
+ $indexentry .= "Reported by: ".&sani($data->{originator});
+ $indexentry .= ";\nOwned by: ".&sani($data->{owner})
+ if length($data->{owner});
+ $indexentry .= ";\nKeywords: ".&sani($data->{keywords})
+ if length($data->{keywords});
+ $linkto= $ref; $linkto =~ s,^..,$&/$&,;
+ @merged= split(/ /,$data->{mergedwith});
+ if (@merged)
+ { $mseparator= ";\nmerged with ";
+ for $m (@merged)
+ { $mfile= $m; $mfile =~ s,^..,$&/$&,;
+ $indexentry .= $mseparator."<A href=\"../$mfile.html\">#$m</A>";
+ $mseparator= ",\n";
+ }
+ }
+ $daysold=$submitted='';
+ if (length($data->{done}))
+ { $indexentry .= ";\n<strong>Done:</strong> ".&sani($data->{done});
+ $indexpart= "done$addseverity";
+ } elsif (length($data->{forwarded}))
+ { $indexentry .= ";\n<strong>Forwarded</strong> to ".&sani($data->{forwarded});
+ $indexpart= "forwarded$addseverity";
+ } else
+ { $cmonths= int($days/30);
+ if ($cmonths != $amonths)
+ { $msg= $cmonths == 0 ? "Submitted in the last month" :
+ $cmonths == 1 ? "Over one month old" :
+ $cmonths == 2 ? "Over two months old - attention is required" :
+ "OVER $cmonths MONTHS OLD - ATTENTION IS REQUIRED";
+ $shortindex .= "</pre><h2>$msg:</h2><pre>\n$shorthead\n";
+ $amonths= $cmonths;
+ }
+ $pad= 6-length(sprintf("%d",$f));
+ $thissient=
+ ($pad>0 ? ' 'x$pad : '').
+ sprintf("<A href=\"../%s.html\">%d</A>",$linkto,$ref).
+ &sani(sprintf(" %-1.1s %-10.10s %-35.35s %-.25s\n",
+ $data->{severity},
+ $data->{package},
+ (length($data->{keywords}) ? $data->{keywords}.'/' : '').
+ $data->{subject}, $data->{originator}));
+ $shortindex.= $thissient;
+ $sient{"$ref $data->{package}"}= $thissient;
+ if ($days >= 7)
+ { $font= $days <= 30 ? '' :
+ $days <= 60 ? 'em' :
+ 'strong';
+ $efont= length($font) ? "</$font>" : '';
+ $font= length($font) ? "<$font>" : '';
+ $daysold= "; $font$days days old$efont";
+ }
+ if ($preserveonly) {
+ $submitted = 'THIS IS A BUG IN THE BUG PROCESSOR';
+ } else {
+ $submitted = strftime "%a, %e %b %Y %T %Z", localtime($data->{date});
+ }
+ $submitted= "; dated $submitted";
+ $indexpart= "pending$addseverity";
+ }
+ $iiref= $ref;
+ $short= $ref; $short =~ s/^\d+/#$&/;
+ $tmaint= defined($maintainer{$tpack}) ? $maintainer{$tpack} : '(unknown)';
+ $qpackage= &sani($_);
+ $descriptivehead= $indexentry.$submitted.";\nMaintainer for $qpackage is\n".
+ '<A href="../ma/l'.&maintencoded($tmaint).'.html">'.&sani($tmaint).'</A>.';
+ $indexentry .= $daysold;
+ $indexentry .= ".";
+ }
+ $indexadd='';
+ $indexadd .= "<!--iid $iiref-->" if defined($iiref);
+ $indexadd .= "<li><A href=\"../$linkto.html\">".$indexlink."</A>";
+ $indexadd .= "<br>\n".$indexentry if length($indexentry);
+ $indexadd .= "<!--/iid-->" if defined($iiref);
+ $indexadd .= "\n";
+ $estr= "\$index$indexpart = \$indexadd.\$index$indexpart; 1;";
+ eval($estr) || &quit("eval add to \$index$indexpart ($estr) failed: $@");
+ #print STDERR ">$estr|$indexadd<\n";
+ $indexadd= "<!--ii $iiref-->\n" if defined($iiref);
+ eval("\$iiindex$indexpart = \$indexadd.\$iiindex$indexpart; 1;") ||
+ &quit("eval add to \$iiindex$indexpart failed: $@");
+ if (defined($tmaint))
+ { $countpermaint{$tmaint} += length($data->{done}) ? 0 : length($data->{forwarded}) ? 0 : 1;
+ eval("\$permaint${indexpart}{\$tmaint} .= \$indexadd; 1;") ||
+ &quit("eval add to \$permaint${indexpart}{\$tmaint} failed: $@");
+ }
+ if (defined($tpack))
+ { $countperpack{$tpack} += length($data->{done}) ? 0 : length($data->{forwarded}) ? 0 : 1;
+ eval("\$perpack${indexpart}{\$tpack} .= \$indexadd; 1;") ||
+ &quit("eval add to \$perpack${indexpart}{\$tpack} failed: $@");
+ }
+ if ($preserveonly) { &preserve("$linkto.html"); &preserve("$linkto-b.html"); &unfilelock; next; }
+ my $hash = get_hashname($ref);
+ open(L,"db-h/$hash/$ref.log") || &quit("open db-h/$hash/$ref.log: $!");
+ $log='';
+ $boring=''; $xmessage= 0;
+ $normstate= 'kill-init';
+ $suppressnext= 0;
+ while(<L>) {
+ if (m/^\07$/) {
+ $normstate eq 'kill-init' || $normstate eq 'kill-end' ||
+ &quit("$ref ^G in state $normstate");
+ $normstate= 'incoming-recv';
+ } elsif (m/^\01$/) {
+ $normstate eq 'kill-init' || $normstate eq 'kill-end' ||
+ &quit("$ref ^A in state $normstate");
+ $normstate= 'autocheck';
+ } elsif (m/^\02$/) {
+ $normstate eq 'kill-init' || $normstate eq 'kill-end' ||
+ &quit("$ref ^B in state $normstate");
+ $normstate= 'recips';
+ } elsif (m/^\03$/) {
+ $normstate eq 'go' || $normstate eq 'go-nox' || $normstate eq 'html' ||
+ &quit("$ref ^C in state $normstate");
+ $this .= "</pre>\n" if $normstate eq 'go' || $normstate eq 'go-nox';
+ if ($normstate eq 'html') {
+ $xmessage++;
+ $this .= " <em><A href=\"../$linkto-b.html#m$xmessage\">Full text</A>".
+ " available.</em>";
+ }
+ if ($suppressnext && $normstate ne 'html') {
+ $ntis= $this; $ntis =~ s:\<pre\>:</A><pre>:i;
+ $boring .= "<hr><A name=\"m$xmessage\">\n$ntis\n";
+ } else {
+ $log = $this. "<hr>\n". $log;
+ }
+ $suppressnext= $normstate eq 'html';
+ $normstate= 'kill-end';
+ } elsif (m/^\05$/) {
+ $normstate eq 'kill-body' || &quit("^E in state $normstate");
+ $this .= "<pre>\n";
+ $normstate= 'go';
+ } elsif (m/^\06$/) {
+ $normstate eq 'kill-init' || $normstate eq 'kill-end' ||
+ &quit("$ref ^F in state $normstate");
+ $normstate= 'html'; $this= '';
+ } elsif ($normstate eq 'incoming-recv') {
+ $pl= $_; $pl =~ s/\n+$//;
+ m/^Received: \(at (\S+)\) by (\S+)\;/ ||
+ &quit("bad line \`$pl' in state incoming-recv");
+ $this = "<h2>Message received at ".&sani("$1\@$2").":</h2><br>\n".
+ "<pre>\n".
+ "$_";
+ $normstate= 'go';
+ } elsif ($normstate eq 'html') {
+ $this .= $_;
+ } elsif ($normstate eq 'go') {
+ s/^\030//;
+ $this .= &sani($_);
+ } elsif ($normstate eq 'go-nox') {
+ next if !s/^X//;
+ $this .= &sani($_);
+ } elsif ($normstate eq 'recips') {
+ if (m/^-t$/) {
+ $this = "<h2>Message sent:</h2><br>\n";
+ } else {
+ s/\04/, /g; s/\n$//;
+ $this = "<h2>Message sent to ".&sani($_).":</h2><br>\n";
+ }
+ $normstate= 'kill-body';
+ } elsif ($normstate eq 'autocheck') {
+ next if !m/^X-Debian-Bugs(-\w+)?: This is an autoforward from (\S+)/;
+ $normstate= 'autowait';
+ $this = "<h2>Message received at $2:</h2><br>\n";
+ } elsif ($normstate eq 'autowait') {
+ next if !m/^$/;
+ $normstate= 'go-nox';
+ $this .= "<pre>\n";
+ } else {
+ &quit("$ref state $normstate line \`$_'");
+ }
+ }
+ &quit("$ref state $normstate at end") unless $normstate eq 'kill-end';
+ close(L);
+ if (length($boring)) {
+ &file("$linkto-b.html",'non',
+ "<html><head><title>$gProject $gBug report logs - ".
+ "$short, boring messages</title>\n".
+ "<link rev=\"made\" href=\"mailto:$gMaintainerEmail)\">\n".
+ "</head>$gHTMLStart<h1>$gProject $gBugreport logs -".
+ "\n <A href=\"../$linkto.html\">$short</A>,".
+ " boring messages</h1>\n$boring\n<hr>\n".
+ $tail_html."</body></html>\n");
+ }
+ &file("$linkto.html",'non',
+ "<html><head><title>$gProject $gBug report logs - ".
+ "$short</title>\n".
+ "<link rev=\"made\" href=\"mailto:$gMaintainerEmail\">\n".
+ "</head>$gHTMLStart<h1>$gProject $gBug report logs - $short<br>\n".
+ &sani($data->{subject})."</h1>".
+ "$descriptivehead\n".
+ "\n<hr>\n".
+ $log.
+ $tail_html."</body></html>\n");
+ &unfilelock;
+}
+
+sub maintsort {
+ $_= $_[0];
+ s/([^<>()]+) \(([^()<>]+)\)/$2 \<$1\>/;
+
+ s/\s+/ /g;
+ s/^\s*//;
+ $email= s/ *\<[^<>()]+\>$//g ? $& : '';
+ $_= "$1 $_" if s/ (\S+)$//;
+ $_.= $email;
+ $_;
+}
+
+sub maintencoded {
+ return $maintencoded{$_[0]} if defined($maintencoded{$_[0]});
+ local ($input)= @_;
+ local ($todo,$encoded)= ($input);
+ while ($todo =~ m/\W/) {
+ $encoded.=$`.sprintf("-%02x_",unpack("C",$&));
+ $todo= $';
+ }
+ $encoded.= $todo;
+ $encoded =~ s/-2e_/\./g;
+ $encoded =~ s/^([^,]+)-20_-3c_(.*)-40_(.*)-3e_/$1,$2,$3,/;
+ $encoded =~ s/^(.*)-40_(.*)-20_-28_([^,]+)-29_$/,$1,$2,$3/;
+ $encoded =~ s/-20_/_/g;
+ $encoded =~ s/-([^_]+)_-/-$1/g;
+ $maintencoded{$input}= $encoded;
+}
+
+for $tmaint (keys %countpermaint) {
+ $_= $tmaint;
+ $after=$before=$sort2d=$sort2s=$sort1d=$sort1s='';
+ $after= "$&$after" if s/\s*\<[^<>()]+\>\s*$//;
+ $after= "$&$after" if s/\s*\)\s*$//;
+ $after= "$&$after" if s/\s*,.*$//;
+ $before.= $& if s/^.*\(\s*//;
+ $sort2d= $& if s/\S+$//;
+ $sort1d= $_;
+ while (s/^([^()<>]+)\. */$1 /) { };
+ s/\s+$//; y/A-Za-z/a-zA-Z/; $sort1s= $_;
+ $sort2s= $sort2d; $sort2s =~ y/A-Za-z/a-zA-Z/;
+ $maintsort{$tmaint}= $sort2s.' '.$sort1s.' '.$before.$sort1d.$sort2d.$after;
+ $maintdisplay{$tmaint}=
+ &sani($before).'<strong>'.&sani($sort1d.$sort2d).'</strong>'.&sani($after);
+}
+
+sub heading ($$) {
+ my ($pt,$sv) = @_;
+ return $displayshowseverities{$sv}.' - '.$displayshowpendings{$pt};
+}
+
+sub makeindex ($$$) {
+ my ($varprefix,$varsuffix,$tkey) = @_;
+ my ($pending,$severity,$anydone,$text);
+ $anydone= 0;
+ $text= '';
+ for $pending (qw(pending forwarded done)) {
+ for $severity (@showseverities) {
+ $estr= "\$value= \\${varprefix}${pending}${severity}${varsuffix}; 1;";
+#print STDERR $estr;
+ eval $estr
+ or &quit("eval get \$${varprefix}${pending}${severity} failed: $@");
+#print STDERR ">$$value<\n";
+ next unless length($$value);
+ $text.= "<hr>\n<h2>".&heading($pending,$severity).":</h2>\n".
+ "(List of <A href=\"../si/$pending$severity.html\">all".
+ " such $gBugs</A> is available.)\n<ul>\n".
+ $$value.
+ "</ul>\n";
+ $anydone=1 if $pending eq 'done';
+ }
+ }
+ $text.= $expirynote_html if $anydone;
+ return $text;
+}
+
+&file("ix/full.html",'def',
+ $gFullIndex.
+ makeindex('$index',"",'').
+ "<hr>\n".
+ $tail_html."</body><html>\n");
+
+&file("ju/junk.html",'non',
+ $gJunkIndex.
+ "<hr>\n<h2>Junk (messages without a specific $gBug report number):</h2>\n".
+ "(\`this week' is everything since last Wednesday.)\n<ul>\n".
+ $indexunmatched.
+ "</ul><hr>\n".
+ $tail_html."</body><html>\n");
+
+$nobugs_html= "No reports are currently in this state.";
+$who_html= $gProject;
+$owner_addr= $gMaintainerEmail;
+$otherindex_html= "For other kinds of index or for other information about
+$gProject and the $gBug system, see the <A HREF=\"../../\">$gBug system top-level
+contents WWW page</A>.
+
+";
+
+for $pending (qw(pending forwarded done)) {
+ for $severity (@showseverities) {
+ eval "\$value= \\\$iiindex${pending}${severity}; 1;"
+ or &quit("eval get \$iiindex${pendingtype}${severity} failed: $@");
+ $value= \$nobugs_html if !length($$value);
+ $headstring= &heading($pending,$severity);
+ &file("si/$pending$severity.html",'ref',
+ "<html><head><title>$who_html $gBug reports: $headstring</title>\n".
+ "<link rev=\"made\" href=\"mailto:".&sani($owner_addr)."\">\n".
+ "</head>$gHTMLStart<h1>$who_html $gBug reports: $headstring</h1>\n".
+ $otherindex_html.
+ ($pending eq 'done' ? "<P>\n$expirynote_html" : '').
+ "<hr>\n<ul>\n".
+ $$value.
+ "</ul>\n<hr>\n".
+ $tail_html."</body></html>\n");
+ }
+}
+
+sub individualindexes ($\@&\%&&$$$$$&&) {
+ my ($filename,$keysref,$getfilenameref,$countref,$getdisplayref,
+ $getsimpledisplayref,$what,$caveat,$whatplural,$abbrev,$ihead,
+ $getxinforef,$getxindexref) = @_;
+ my ($itext,$i,$tkey,$sani,$count,$tfilename,$refto,$backnext,$xitext,$bugbugs);
+ $itext='';
+ for ($i=0; $i<=$#$keysref; $i++) {
+ $tkey= $$keysref[$i];
+ $tfilename= &$getfilenameref($tkey);
+ $sani= &$getsimpledisplayref($tkey);
+ $count= $$countref{$tkey};
+ $count= $count >= 1 ? "$count" : "no";
+ $bugbugs= $count == 1 ? "$gBug" : "$gBugs";
+ $xitext= &$getxindexref($tkey);
+ $xitext= length($xitext) ? "$count $bugbugs; $xitext"
+ : "$count outstanding $bugbugs";
+ $itext .= "<li><A href=\"../$tfilename\">".&$getdisplayref($tkey)."</A>"."\n".
+ " ($xitext)\n";
+ $backnext= '';
+ if ($i>0) {
+ $refto= $$keysref[$i-1];
+ $xitext= &$getxindexref($refto);
+ $xitext= " ($xitext)" if length($xitext);
+ $backnext .= "<br>\nPrevious $what in list, <A href=\"../".
+ &$getfilenameref($refto)."\">".&$getdisplayref($refto)."</A>".
+ "$xitext\n";
+ }
+ if ($i<$#$keysref) {
+ $refto= $$keysref[$i+1];
+ $xitext= &$getxindexref($refto);
+ $xitext= " ($xitext)" if length($xitext);
+ $backnext .= "<br>\nNext $what in list, <A href=\"../".
+ &$getfilenameref($refto)."\">".&$getdisplayref($refto)."</A>".
+ "$xitext\n";
+ }
+ &file($tfilename,'ref',
+ "<html><head><title>$gProject $gBug reports: $what $sani</title>\n".
+ "<link rev=\"made\" href=\"mailto:$gMaintainerEmail\">\n".
+ "</head>$gHTMLStart<h1>$gProject $gBug reports: $what $sani</h1>\n".
+ &$getxinforef($tkey).
+ $caveat.
+ "See the <A href=\"../$filename\">listing of $whatplural</A>.\n".
+ $backnext.
+ &makeindex("\$per${abbrev}","{\$tkey}",$tkey).
+ "<hr>\n".
+ $tail_html."</body></html>\n");
+ }
+ &file($filename,'non',
+ $ihead.
+ "<hr><ul>\n".
+ $itext.
+ "</ul><hr>\n".
+ $tail_html."</body></html>\n");
+}
+
+@maintainers= sort { $maintsort{$a} cmp $maintsort{$b}; } keys %countpermaint;
+individualindexes('ix/maintainers.html',
+ @maintainers,
+ sub { 'ma/l'.&maintencoded($_[0]).'.html'; },
+ %countpermaint,
+ sub { $maintdisplay{$_[0]}; },
+ sub { &sani($_[0]); },
+ 'maintainer',
+ "Note that there may be other reports filed under different
+ variations on the maintainer\'s name and email address.<P>",
+ 'maintainers',
+ 'maint',
+ $gMaintIndex,
+ sub { return ''; },
+ sub { return ''; });
+
+@packages= sort keys %countperpack;
+individualindexes('ix/packages.html',
+ @packages,
+ sub { length($_[0]) ? "pa/l$_[0].html" : 'pa/none.html'; },
+ %countperpack,
+ sub { length($_[0]) ? $_[0] : 'not specified'; },
+ sub { &sani(length($_[0]) ? $_[0] : 'not specified'); },
+ 'package',
+ "Note that with multi-binary packages there may be other
+ reports filed under the different binary package names.<P>",
+ 'packages',
+ 'pack',
+ $gPackageIndex,
+ sub {
+ return unless defined($maintainer{$_[0]});
+ $tmaint= $maintainer{$_[0]};
+ return "Maintainer for $_[0] is <A href=\"../ma/l".
+ &maintencoded($tmaint).
+ ".html\">".&sani($tmaint)."</A>.\n<p>\n";
+ },
+ sub {
+ return unless defined($maintainer{$_[0]});
+ $tmaint= $maintainer{$_[0]};
+ return "<A href=\"../ma/l".
+ &maintencoded($tmaint).
+ ".html\">".&sani($tmaint)."</A>";
+ });
+
+&file('ix/summary.html','non',
+ $gSummaryIndex.
+ "<hr><pre>\n".
+ $shortindex.
+ "</pre><hr>\n".
+ $tail_html."</body></html>\n");
+
+$bypackageindex='';
+for $k (map {$_->[0] }
+ sort { $a->[2] cmp $b->[2] || $a->[1] <=> $b->[1] }
+ map { [$_, split(' ',$_,2)] } keys %sient)
+ { $bypackageindex.= $sient{$k}; }
+&file('ix/psummary.html','non',
+ $gPackageLog.
+ "<hr><pre>\n$shorthead\n".
+ $bypackageindex.
+ "</pre><hr>\n".
+ $tail_html."</body></html>\n");
+
+open(P,"$gPseudoDescFile") ||
+ &quit("$gPseudoDescFile: $!");
+$ppd=''; while(<P>) { s/\s*\n$//; $ppd.= &sani($_)."\n"; } close(P);
+&file('ix/pseudopackages.html','non',
+ $gPseudoIndex.
+ "<hr><pre>\n$ppd".
+ "</pre><hr>\n".
+ $tail_html."</body></html>\n");
+
+$_= $gHTMLStamp; s/SUBSTITUTE_DTIME/$dtime/o;
+
+&file('ix/zstamp.html','non',$_."</body></html>\n");
+
+sub notimestamp ($) {
+ $_= $_[0];
+ s/\<\!\-\-timestamp\-\-\>\n.*\n\<\!\-\-\/timestamp\-\-\>\n//;
+ return $_;
+}
+
+sub file {
+ local ($name,$ii,$file)= @_;
+ if ($diff) {
+ $cmppath= "$wwwbase/$name".($ii eq 'ref' ? '.ref' : '');
+ if (open(ORIG,"$cmppath")) {
+ undef $/; $orig= <ORIG>; $/= "\n";
+ close(ORIG);
+ if (¬imestamp($orig) eq ¬imestamp($file)) {
+ print "preserve $name\n";
+ return;
+ }
+ defined($c= open(P,"-|")) or &quit("pipe/fork for diff: $!");
+ if (!$c) {
+ open(Q,"|diff -e $cmppath -") or die "pipe/fork II for diff: $!\n";
+ print Q $file or die "write orig to diff: $!\n";
+ close(Q); $?==0 || $?==256 or die "diff gave $?\n";
+ exit($?>>8);
+ }
+ undef $/; $difftxt= <P>; $/= "\n";
+ close(P); $?==0 || $?==256 or die "diff fork gave $?\n";
+ if ($?==0) {
+ print "preserve $name\n";
+ return;
+ }
+ $v= (split(/\n/,$difftxt));
+ print "diff $v $ii $name\n${difftxt}thatdiff $name\n"
+ or &quit("stdout (diff): $!");
+ return;
+ }
+ }
+ $v= (split(/\n/,$file));
+ print "file $v $ii $name\n${file}thatfile $name\n" or &quit("stdout: $!");
+}
+
+sub preserve {
+ print "preserve $_[0]\n";
+}
+
+print "end\n";
+
+while ($u= $cleanups[$#cleanups]) { &$u; }
+exit 0;