diff --git a/data/cgi/query-pr-phk.cgi b/data/cgi/query-pr-phk.cgi
new file mode 100755
index 0000000000..bee7c90dec
--- /dev/null
+++ b/data/cgi/query-pr-phk.cgi
@@ -0,0 +1,519 @@
+#!/usr/bin/perl
+# $Id: query-pr-phk.cgi,v 1.1 1998-08-14 06:08:47 phk Exp $
+
+$html_mode = 1 if $ENV{'DOCUMENT_ROOT'};
+$self_ref = $ENV{'SCRIPT_NAME'};
+($query_pr_ref = $self_ref) =~ s/-phk//;
+
+$ENV{'PATH'} = '/bin:/usr/bin:/usr/sbin:/sbin:/usr/local/bin';
+
+$project = "FreeBSD";
+$mail_prefix = "freebsd-";
+$mail_unass = "freebsd-bugs";
+
+%statemap = (
+ "open", "o",
+ "analyzed", "a",
+ "feedback", "f",
+ "suspended", "s",
+ "closed", "c"
+);
+
+%severitymap = (
+ "critical", "c",
+ "serious", "s",
+ "non-critical", "n"
+);
+
+%prioritymap = (
+ "high", "h",
+ "medium", "m",
+ "low", "l"
+);
+
+require "cgi-lib.pl";
+require "cgi-style.pl";
+require "getopts.pl";
+
+if ($ENV{'QUERY_STRING'} eq 'query') {
+ print &html_header("Query $project problem reports");
+ &displayform;
+ print &html_footer;
+ exit(0);
+}
+
+if ($html_mode) {
+ $query_args = '--restricted ';
+ &ReadParse(*input) if $html_mode;
+
+} else {
+ &Getopts('CcqRr:s:');
+
+ $input{"responsible"} = "summary" if $opt_R;
+ $input{"responsible"} = $opt_r if $opt_r;
+ $input{"state"} = $opt_s if $opt_s;
+ $input{"quiet"} = $opt_q if $opt_q;
+ if ($opt_C) {
+ $query_args = '--confidential=yes ';
+ } elsif (!$opt_c) {
+ $query_args = '--restricted ';
+ }
+}
+
+#------------------------------------------------------------------------
+
+%mons = ('Jan', '01', 'Feb', '02', 'Mar', '03',
+ 'Apr', '04', 'May', '05', 'Jun', '06',
+ 'Jul', '07', 'Aug', '08', 'Sep', '09',
+ 'Oct', '10', 'Nov', '11', 'Dec', '12');
+
+
+if ($html_mode) {
+ $h1 = "
"; $h1_e = "
";
+ $h2 = ""; $h2_e = "
";
+ $h3 = ""; $h3_e = "
";
+ $h4 = ""; $h4_e = "
";
+ $p = "" ; $p_e = "
";
+ $br = "
";
+
+ $st = ""; $st_e = "";
+ $pr = ""; $pr_e = "
";
+ $dl = ""; $dl_e = "
";
+ $dt = "";
+ $dd = ""; $dd_x = "";
+ $hr = "
";
+
+# print "Content-type: text/html\n";
+
+} else {
+
+ $h1 = ""; $h1_e = "";
+ $h2 = ""; $h2_e = "";
+ $h3 = ""; $h3_e = "";
+ $h4 = ""; $h4_e = "";
+ $p = ""; $p_e = "";
+ $br = "";
+ $st = ""; $st_e = "";
+ $pr = ""; $pr_e = "";
+ $dl = ""; $dl_e = "";
+ $dt = "";
+ $dd = " "; $dd_x = " ";
+ $hr = "\n----------------------------------------" .
+ "---------------------------------------\n";
+}
+
+sub header_info {
+ if ($html_mode) {
+ print &html_header("Current $project problem reports");
+ }
+ else {
+ print "Current $project problem reports\n";
+ }
+
+print <You may view summaries by Severity, ';
+$self_ref1 .= '&' if ($self_ref1 !~/\?$/);
+print 'State, ';
+print 'Category, or ';
+print 'Responsible Party.';
+
+$self_ref2 = $self_ref . '?';
+foreach ("category", "originator", "priority", "class", "responsible",
+ "severity", "state", "submitter", "text", "multitext", "closedtoo") {
+ if ($input{$_}) {
+ $self_ref2 .= '&' if ($self_ref2 !~/\?$/);
+ $self_ref2 .= $_ . '=' . $input{$_};
+ }
+}
+
+print 'You may also sort by ';
+print 'Last-Modified, ';
+print 'Category, or ';
+print 'Responsible Party.', "\n";
+print 'Or formulate a specific query.';
+ }
+}
+
+sub trailer_info {
+ print &html_footer if $html_mode;
+}
+
+&header_info;
+
+#Usage: query-pr [-FhiPqVx] [-C confidential] [-c category] [-d directory]
+# [-e severity] [-m mtext] [-O originator] [-o outfile] [-p priority]
+# [-L class] [-r responsible] [-S submitter] [-s state] [-t text]
+# [--full] [--help] [--sql] [--print-path] [--summary] [--version]
+# [--skip-closed] [--category=category] [--confidential=yes|no]
+# [--directory=directory] [--output=outfile] [--originator=name]
+# [--priority=level] [--class=class] [--responsible=person]
+# [--severity=severity] [--state=state] [--submitter=submitter]
+# [--list-categories] [--list-responsible] [--list-submitters]
+# [--text=text] [--multitext=mtext] [PR] [PR]...
+
+$query_args .= " --skip-closed" unless $input{"closedtoo"};
+
+# Only read the appropriate PR's.
+foreach ("category", "originator", "priority", "class", "responsible",
+ "severity", "state", "submitter", "text", "multitext") {
+ if ($input{$_} && $input{$_} ne "summary") {
+ $query_args .= " --${_}=$input{$_}";
+ }
+}
+
+&read_gnats($query_args);
+
+if ($input{'sort'} eq 'lastmod') {
+ @prs = sort {$lastmod{$b} <=> $lastmod{$a}} @prs;
+} elsif ($input{'sort'} eq 'category') {
+ @prs = sort {($ca,$na)=split(m|/|,$a); ($cb,$nb)=split(m|/|,$b); $ca eq $cb ? $na <=> $nb : $ca cmp $cb} @prs;
+} elsif ($input{'sort'} eq 'responsible') {
+ @prs = sort {$resp{$a} cmp $resp{$b}} @prs;
+} else {
+ $input{'sort'} = 'none';
+}
+
+if ($#prs < $[) {
+ print "${h1}No matches to your query${h1_e}\n";
+
+} elsif ($input{'responsible'} eq 'summary') {
+ &resp_summary;
+
+} elsif ($input{'state'} eq 'summary') {
+ &state_summary;
+
+} elsif ($input{'category'} eq 'summary') {
+ &cat_summary;
+
+} elsif ($input{'severity'} eq '') {
+ &severity_summary;
+
+} else {
+ &printcnt(&gnats_summary(1, $html_mode));
+
+}
+
+&trailer_info;
+exit(0);
+
+#------------------------------------------------------------------------
+
+sub getline {
+ local($_) = @_;
+ ($tag,$remainder) = split(/[ \t]+/, $_, 2);
+ return $remainder;
+}
+
+sub html_fixline {
+ local($line) = @_[0];
+
+ $line =~ s/&/&/g;
+ $line =~ s/</g;
+ $line =~ s/>/>/g;
+
+ $line;
+}
+
+sub printcnt {
+ local($cnt) = $_[0];
+
+ if ($cnt) {
+ printf("%d problem%s total.\n\n", $cnt, $cnt == 1 ? "" : "s");
+ }
+}
+
+sub cat_query {
+ local($cat) = $_[0];
+
+ &printcnt(&gnats_summary("\$cat eq \"$cat\"", $html_mode));
+}
+
+sub cat_summary {
+ foreach (keys %status) {
+ s|/\d+||;
+ $cat{$_}++;
+ }
+ foreach (sort keys %cat) {
+ &cat_query($_);
+ }
+}
+
+sub resp_query {
+ local($resp) = @_[0];
+ local($cnt);
+
+ $cnt = &gnats_summary("\$resp eq \"$resp\"", $html_mode);
+ print "${hr}${b}No problem reports assigned to $resp${b_e}\n"
+ if (!$input{"quiet"} && $cnt == 0);
+}
+
+sub resp_summary {
+ local($who, %who);
+
+ foreach (keys %resp) {
+ $who{$resp{$_}}++;
+ }
+ foreach $who (sort keys %who) {
+ $cnt = &gnats_summary("\$resp eq \"$who\"", $html_mode);
+ }
+}
+
+sub state_query {
+ local($state) = @_[0];
+
+ print "${h3}Problems in state: $state${h3_e}\n";
+ $state = $statemap{$state} if ($statemap{$state} ne '');
+ &printcnt(&gnats_summary("\$state eq \"$state\" ", $html_mode));
+}
+
+sub state_summary {
+ foreach (sort keys %statemap) {
+ next if ($_ eq "closed" && !$input{"closedtoo"});
+ &state_query($_);
+ }
+}
+
+sub severity_summary {
+ &printcnt(&gnats_summary('', $html_mode));
+}
+
+sub get_categories {
+ open(Q, "query-pr --list-categories 2>/dev/null |") ||
+ die "Cannot get categories\n";
+
+ while() {
+ chop;
+ local ($cat, $desc, $responsible, $notify) = split(/:/);
+ push(@categories, $cat);
+ }
+}
+
+sub read_gnats {
+ local($report) = @_[0];
+
+ open(Q, "query-pr $report 2>/dev/null |") || die "Cannot query the PR's\n";
+
+ while() {
+ chop;
+ if(/^>Number:/) {
+ $number = &getline($_);
+
+ } elsif (/Arrival-Date:/) {
+ $date = &getline($_);
+ # strip timezone if any (between HH:MM:SS and YYYY at end of line):
+ $date =~ s/(\d\d:\d\d:\d\d)\D+(\d{4})$/\1 \2/;
+ ($dow,$mon,$day,$time,$year,$xtra) = split(/[ \t]+/, $date);
+ $day = "0$day" if $day =~ /^[0-9]$/;
+ $date = "$year/$mons{$mon}/$day";
+
+ } elsif (/>Last-Modified:/) {
+ $lastmod = &getline($_);
+ if ($lastmod =~ /^[ ]*$/) {
+ $lastmod = $date;
+ } else {
+ # strip timezone if any (between HH:MM:SS and YYYY at end of line):
+ $lastmod =~ s/(\d\d:\d\d:\d\d)\D+(\d{4})$/\1 \2/;
+ ($dow,$mon,$day,$time,$year,$xtra) = split(/[ \t]+/, $lastmod);
+ $day = "0$day" if $day =~ /^[0-9]$/;
+ $lastmod = "$year/$mons{$mon}/$day";
+ }
+
+ } elsif (/>Category:/) {
+ $cat = &getline($_);
+
+ } elsif (/>Severity:/) {
+ $sev = &getline($_);
+
+ } elsif (/>Responsible:/) {
+ $resp = &getline($_);
+ $resp =~ s/@.*//;
+ $resp =~ tr/A-Z/a-z/;
+ $resp = "" if ($resp =~ /$mail_unass/);
+ $resp =~ s/^$mail_prefix//;
+
+ } elsif (/>State:/) {
+ $status = &getline($_);
+ $status =~ s/(.).*/\1/;
+
+ } elsif (/>Synopsis:/) {
+ $syn = &getline($_);
+ $syn =~ s/[\t]+/ /g;
+
+ } elsif (/^$/) {
+ $_ = sprintf("%s/%s", $cat, $number);
+
+ $status{$_} = $status;
+ $date{$_} = $date;
+ $resp{$_} = $resp;
+ $syn{$_} = $syn;
+ $sev{$_} = $sev;
+ $lastmod{$_} = $lastmod;
+ push(@prs,$_);
+ }
+ }
+ close(Q);
+}
+
+sub gnats_summary {
+ local($report) = @_[0];
+ local($htmlmode) = @_[1];
+ local($counter) = 0;
+ local($iteration)= 0;
+
+ foreach (@prs) {
+ $state = $status{$_};
+ $date = $date{$_};
+ $lastmod = $lastmod{$_};
+ $resp = $resp{$_};
+ $syn = $syn{$_};
+ $severity = $sev{$_};
+ ($cat, $number) = m|^([^/]+)/(\d+)$|;
+
+ next if (($report ne '') && (eval($report) == 0));
+ next if ($cat eq 'ports');
+
+ print "${pr}\nS Modified Tracker Resp. Description${hr}"
+ if ($iteration++ == 0);
+
+ $syn = &html_fixline($syn) if $htmlmode;
+
+ if ($htmlmode) {
+ $title = '' .
+ $_ . '';
+ } else {
+ $title = $_;
+ }
+
+ print "$state [$lastmod] $title" .
+ (' ' x (11 - length($_))) .
+ $resp . (' ' x (9 - length($resp))) .
+ ($htmlmode ? $syn : substr($syn,0,41))
+ . "\n";
+
+ ++$counter;
+ }
+
+ print "${pr_e}\n" if $iteration;
+
+ $counter;
+}
+
+sub displayform {
+print qq`
+Please select the items you wish to search for. Multiple items are AND'ed
+together.
+
+
+`;
+}