Tidy up some loose ends that no longer work after the apache-1.x server on
hub.freebsd.org and the supporting 15 year old binaries have gone away. Highlights: - Sync up the cgi scripts to be closer to the standard page look and feel and the canonical url locations. - Adjust the search controls to include the docs.freebsd.org doc set. - Replace the remaining wais search references. - Fix up the embedded paths that depended on a symlink and/or nfs jungle on hub. These aren't present in the jail this now runs in. - Fix a typo (stray backtick) in one of the header entities. - Remove the remaining no-longer-functional gnats components - they ran on hub and no longer exist. Build tested by: gjb Brought to you by: lots of coffee, profanity and confusion.
This commit is contained in:
parent
349ae4118b
commit
e984dc3473
Notes:
svn2git
2020-12-08 03:00:23 +00:00
svn path=/head/; revision=46874
37 changed files with 28 additions and 5136 deletions
|
|
@ -1,41 +0,0 @@
|
||||||
# $FreeBSD$
|
|
||||||
package Gnats;
|
|
||||||
|
|
||||||
# We probably don't have "our" in this Perl
|
|
||||||
use vars qw/
|
|
||||||
$gnats_root
|
|
||||||
$query_pr
|
|
||||||
$submission_address
|
|
||||||
$submission_program
|
|
||||||
$use_mail
|
|
||||||
/;
|
|
||||||
|
|
||||||
$gnats_root="/usr/local/libexec/gnats";
|
|
||||||
$query_pr="/usr/local/bin/query-pr.web";
|
|
||||||
$submission_address="freebsd-gnats-submit\@FreeBSD.org";
|
|
||||||
$use_mail=1;
|
|
||||||
|
|
||||||
if ($use_mail) {
|
|
||||||
if (-e "/usr/lib/sendmail") { $submission_program = "/usr/lib/sendmail -t" };
|
|
||||||
if (-e "/usr/sbin/sendmail") { $submission_program = "/usr/sbin/sendmail -t" };
|
|
||||||
} else {
|
|
||||||
if (-e "$gnats_root/queue-pr") { $submission_program = "$gnats_root/queue-pr -q" };
|
|
||||||
}
|
|
||||||
|
|
||||||
##### End site specific stuff
|
|
||||||
|
|
||||||
BEGIN {
|
|
||||||
use Exporter();
|
|
||||||
use vars qw/$VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS/;
|
|
||||||
$VERSION = 0.01; # Has to have two decimal places
|
|
||||||
@ISA = qw/Exporter/;
|
|
||||||
# Names for sets of symbols
|
|
||||||
%EXPORT_TAGS = (
|
|
||||||
'standard'=>[qw/$gnats_root $query_pr $submission_address
|
|
||||||
$submission_program/],
|
|
||||||
);
|
|
||||||
Exporter::export_tags('standard');
|
|
||||||
Exporter::export_ok_tags('standard');
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
@ -1,641 +0,0 @@
|
||||||
#!/usr/bin/perl -Tw
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Copyright (C) 2011, Shaun Amott <shaun@FreeBSD.org>
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
package GnatsPR;
|
|
||||||
|
|
||||||
#use MIME::Base64; # ports/converters/p5-MIME-Base64
|
|
||||||
#use MIME::QuotedPrint; #
|
|
||||||
#use Convert::UU qw(uudecode uuencode); # ports/converters/p5-Convert-UU
|
|
||||||
|
|
||||||
use GnatsPR::Section::Text;
|
|
||||||
use GnatsPR::Section::Patch;
|
|
||||||
use GnatsPR::Section::Email;
|
|
||||||
use GnatsPR::Section::StateChange;
|
|
||||||
use GnatsPR::Section::FieldStart;
|
|
||||||
|
|
||||||
use GnatsPR::SectionIterator;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
require 5.006;
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Constants
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
use constant ENCODING_BASE64 => 1;
|
|
||||||
use constant ENCODING_QP => 2;
|
|
||||||
|
|
||||||
use constant PATCH_ANY => 0x0001;
|
|
||||||
use constant PATCH_DIFF => 0x0002;
|
|
||||||
use constant PATCH_UUENC => 0x0004;
|
|
||||||
use constant PATCH_UUENC_BIN => 0x0008;
|
|
||||||
use constant PATCH_SHAR => 0x0010;
|
|
||||||
use constant PATCH_BASE64 => 0x0020;
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: new()
|
|
||||||
# Desc: Constructor - Parses data if provided.
|
|
||||||
#
|
|
||||||
# Args: [data] - Raw data (or ref. to) from query-pr (optional)
|
|
||||||
#
|
|
||||||
# Retn: $self
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub new
|
|
||||||
{
|
|
||||||
my $class = shift;
|
|
||||||
my ($data) = @_;
|
|
||||||
|
|
||||||
my $self = {
|
|
||||||
blobs_single => {}, # Raw text, single-line fields
|
|
||||||
blobs_multi => {}, # Raw text, multi-line fields
|
|
||||||
header => {}, # E-mail header bits
|
|
||||||
sections => {}, # Hash of arrayrefs of sections
|
|
||||||
fromwebform => 0, # PR came from the web form?
|
|
||||||
numfields => 0 # Number of fields we have
|
|
||||||
};
|
|
||||||
|
|
||||||
bless $self, $class;
|
|
||||||
|
|
||||||
if (defined $data) {
|
|
||||||
ref $data
|
|
||||||
? $self->Parse($data)
|
|
||||||
: $self->Parse(\$data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: Header()
|
|
||||||
# Desc: Return a value from the header hash.
|
|
||||||
#
|
|
||||||
# Args: $key - Header name, case insensitive.
|
|
||||||
#
|
|
||||||
# Retn: $val - Value.
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub Header
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
my ($key) = @_;
|
|
||||||
|
|
||||||
return $self->{header}->{lc $key};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: FieldSingle()
|
|
||||||
# Desc: Return a single line field value.
|
|
||||||
#
|
|
||||||
# Args: $key - Field name.
|
|
||||||
#
|
|
||||||
# Retn: $val - Value.
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub FieldSingle
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
my ($key) = @_;
|
|
||||||
|
|
||||||
return $self->{blobs_single}->{$key};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: Parse()
|
|
||||||
# Desc: Parse a blob of text from query-pr into a structured unit for easy
|
|
||||||
# manipulation.
|
|
||||||
#
|
|
||||||
# Args: \$data - Raw data from query-pr (non-ref scalar is acceptable too).
|
|
||||||
#
|
|
||||||
# Retn: n/a
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub Parse
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
my ($data) = @_;
|
|
||||||
|
|
||||||
my $ismulti = 0;
|
|
||||||
my $pastheader = 0;
|
|
||||||
|
|
||||||
# GNATS ensures that > isn't allowed as the first
|
|
||||||
# character on a line, except for field headers.
|
|
||||||
# Any lines beginning with > will be shunted into
|
|
||||||
# 'Unformatted'
|
|
||||||
my @fieldblobs = split /\n>(?!\s)/m, $$data;
|
|
||||||
|
|
||||||
# In the rare case the Unformatted field did
|
|
||||||
# have some debris, be sure to assemble it back
|
|
||||||
# into a complete section.
|
|
||||||
while ($fieldblobs[$#fieldblobs] !~ /^Unformatted:/) {
|
|
||||||
my $last = pop @fieldblobs;
|
|
||||||
exists $fieldblobs[$#fieldblobs] or last;
|
|
||||||
$fieldblobs[$#fieldblobs] .= $last;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach my $blob (@fieldblobs) {
|
|
||||||
my $key;
|
|
||||||
|
|
||||||
# Parse e-mail header; we only care about a few
|
|
||||||
# fields, not the e-mail routing stuff.
|
|
||||||
if (!$pastheader) {
|
|
||||||
foreach my $line (split /\n/, $blob) {
|
|
||||||
if ($line =~ /^(\S+):\s*(.*)$/) {
|
|
||||||
my $val = $2;
|
|
||||||
$key = lc $1;
|
|
||||||
|
|
||||||
# Ignore multiple defs (e.g. Received: headers)
|
|
||||||
exists $self->{header}->{$key}
|
|
||||||
and next;
|
|
||||||
|
|
||||||
$self->{header}->{$key} = $val;
|
|
||||||
} elsif ($line =~ /^\s+(.*)$/) {
|
|
||||||
my $val = $1;
|
|
||||||
|
|
||||||
defined $key
|
|
||||||
or next;
|
|
||||||
|
|
||||||
# No field to append to
|
|
||||||
exists $self->{header}->{$key}
|
|
||||||
or next;
|
|
||||||
|
|
||||||
$self->{header}->{$key} .= "\n$val";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$pastheader = 1;
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($blob =~ s/^([^:]+):(\n|\s*)//) {
|
|
||||||
$key = $1;
|
|
||||||
#$ismulti = ($2 and $2 eq "\n");
|
|
||||||
|
|
||||||
# It's multi-liners from here on in
|
|
||||||
$key eq 'Organization'
|
|
||||||
and $ismulti = 1;
|
|
||||||
} else {
|
|
||||||
# Hmm...
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Remove leading/trailing whitespace
|
|
||||||
$blob =~ s/^[\n\s]+//;
|
|
||||||
$blob =~ s/[\n\s]+$//;
|
|
||||||
|
|
||||||
if ($ismulti) {
|
|
||||||
$self->{blobs_multi}->{$key} = $blob;
|
|
||||||
} else {
|
|
||||||
$self->{blobs_single}->{$key} = $blob;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->{numfields} = scalar @fieldblobs;
|
|
||||||
|
|
||||||
$self->{fromwebform} =
|
|
||||||
$self->{header}->{'x-send-pr-version'} =~ /^www-/;
|
|
||||||
|
|
||||||
$self->ParseBlobs();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: ParseBlobs()
|
|
||||||
# Desc: Parse all the raw field "blobs" into section objects.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: n/a
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub ParseBlobs
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
foreach my $field (keys %{$self->{blobs_multi}}) {
|
|
||||||
$self->{sections}->{$field} = [];
|
|
||||||
|
|
||||||
push @{$self->{sections}->{$field}},
|
|
||||||
new GnatsPR::Section::FieldStart($field);
|
|
||||||
|
|
||||||
if ($field eq 'Fix') {
|
|
||||||
$self->ParsePatches($field, \($self->{blobs_multi}->{$field}));
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($field eq 'Audit-Trail') {
|
|
||||||
# We'll break up the Audit-Trail field by change events.
|
|
||||||
# This is the most reliable way to split, although it's far
|
|
||||||
# from perfect. We'll then look for e-mail responses inside
|
|
||||||
# each chunk for further splitting later.
|
|
||||||
#
|
|
||||||
# Notes/Caveats:
|
|
||||||
# - If someone happened to paste an audit trail event
|
|
||||||
# inside another's "Why" field, it'd break this. I haven't
|
|
||||||
# seen this yet and don't expect to.
|
|
||||||
# - The From-To field has to come first. No reason it wouldn't
|
|
||||||
# under normal circumstances.
|
|
||||||
# - Pasted e-mails in the Why field will be promoted to
|
|
||||||
# responses, although they often break the GNATS conventions
|
|
||||||
# we (ab)use to find e-mails (e.g.: leading space on message
|
|
||||||
# body lines), which makes this more difficult.
|
|
||||||
my @auditevents =
|
|
||||||
split /(?=^(?:[A-Za-z_]+)-Changed-From-To: (?:.*?)\s*$)/m,
|
|
||||||
$self->{blobs_multi}->{$field};
|
|
||||||
|
|
||||||
foreach my $evt (@auditevents) {
|
|
||||||
my $sect = new GnatsPR::Section::StateChange;
|
|
||||||
my $gotwhat = 0;
|
|
||||||
my $gotsect = 0;
|
|
||||||
while ($evt =~ s/^([A-Za-z_]+)-Changed-([A-Za-z_-]+?): (.*?)\s*\n//) {
|
|
||||||
my ($what, $key, $val) = ($1, $2, $3);
|
|
||||||
|
|
||||||
if (!$gotwhat) {
|
|
||||||
$sect->what($what);
|
|
||||||
$gotwhat = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
$gotsect = 1;
|
|
||||||
|
|
||||||
if ($key eq 'From-To') {
|
|
||||||
my $fromto = $val;
|
|
||||||
if ($fromto =~ /^(.*)->(.*)$/) {
|
|
||||||
$sect->from($1);
|
|
||||||
$sect->to($2);
|
|
||||||
}
|
|
||||||
} elsif ($key eq 'When') {
|
|
||||||
$sect->when($val);
|
|
||||||
} elsif ($key eq 'By') {
|
|
||||||
$sect->by($val);
|
|
||||||
} elsif ($key eq 'Why') {
|
|
||||||
# This is the last one; it's a multi-line
|
|
||||||
# field (remainder of the text.)
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
push @{$self->{sections}->{$field}}, $sect
|
|
||||||
if ($gotsect);
|
|
||||||
|
|
||||||
# Now look for blocks that appear to be e-mail replies
|
|
||||||
# Note: these header fields are the only ones we allow
|
|
||||||
# as the first header; we could feasibly back-
|
|
||||||
# track to find the start of the block (in case
|
|
||||||
# we're not there already), but the more headers
|
|
||||||
# we accept the more likely this will break on
|
|
||||||
# some unexpected content.
|
|
||||||
my $next_email = qr/^(From|To|Cc|Subject|Date): (.*)$/m;
|
|
||||||
my $gotwhy = 0;
|
|
||||||
|
|
||||||
while ($evt =~ /$next_email/) {
|
|
||||||
my $match_start = $-[0];
|
|
||||||
my ($header, $body, $indented);
|
|
||||||
my $why;
|
|
||||||
|
|
||||||
$match_start > 0
|
|
||||||
and $why = substr($evt, 0, $match_start, '');
|
|
||||||
|
|
||||||
if ($gotsect) {
|
|
||||||
# We now know where "Why" terminates
|
|
||||||
$sect->why($why) if $sect;
|
|
||||||
} elsif ($why) {
|
|
||||||
# If the first block was a date block,
|
|
||||||
# we need to use a text section for the
|
|
||||||
# intermediate text instead.
|
|
||||||
push @{$self->{sections}->{$field}},
|
|
||||||
new GnatsPR::Section::Text($why)
|
|
||||||
unless ($why =~ /^[\n\s]+$/);
|
|
||||||
}
|
|
||||||
|
|
||||||
$gotwhy = 1;
|
|
||||||
$sect = undef;
|
|
||||||
|
|
||||||
# Chop leading blank lines
|
|
||||||
$evt =~ s/^\n+//;
|
|
||||||
|
|
||||||
if ($evt =~ /^$/m) {
|
|
||||||
# First blank line signals the end of the
|
|
||||||
# e-mail header
|
|
||||||
$header = substr($evt, 0, $+[0]+1, '');
|
|
||||||
|
|
||||||
# Deciding where the body ends is more
|
|
||||||
# difficult...
|
|
||||||
|
|
||||||
# First, let's see if the message is
|
|
||||||
# indented (per GNATS standards)
|
|
||||||
$indented = ($evt =~ /^ /);
|
|
||||||
|
|
||||||
# If, so, find the next blank line, which
|
|
||||||
# signals the body end.
|
|
||||||
if ($indented) {
|
|
||||||
if ($evt =~ /^$/m) {
|
|
||||||
$body = substr($evt, 0, $-[0], '');
|
|
||||||
} else {
|
|
||||||
$body = $evt;
|
|
||||||
}
|
|
||||||
$body =~ s/^ //mg; # Remove indent char
|
|
||||||
} else {
|
|
||||||
# Look for another e-mail block
|
|
||||||
if ($evt =~ /$next_email/) {
|
|
||||||
$body = substr($evt, 0, $-[0], '');
|
|
||||||
} else {
|
|
||||||
# Otherwise, use the whole section
|
|
||||||
$body = $evt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
push @{$self->{sections}->{$field}},
|
|
||||||
new GnatsPR::Section::Email($header, $body);
|
|
||||||
} else {
|
|
||||||
# No end-of-header marker: no choice but to
|
|
||||||
# dump the (possible) e-mail into the Why field
|
|
||||||
|
|
||||||
if ($gotsect && $sect) {
|
|
||||||
$sect->why($evt);
|
|
||||||
} elsif ($evt) {
|
|
||||||
push @{$self->{sections}->{$field}},
|
|
||||||
new GnatsPR::Section::Text($evt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check for dangling "Why" block
|
|
||||||
if (!$gotwhy) {
|
|
||||||
if ($gotsect && $sect) {
|
|
||||||
$sect->why($evt);
|
|
||||||
} elsif ($evt) {
|
|
||||||
push @{$self->{sections}->{$field}},
|
|
||||||
new GnatsPR::Section::Text($evt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Everything else is just text
|
|
||||||
push @{$self->{sections}->{$field}},
|
|
||||||
new GnatsPR::Section::Text($self->{blobs_multi}->{$field});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: ParsePatches()
|
|
||||||
# Desc: Parse the patches out of the given blob of text, emitting Patch and
|
|
||||||
# Text sections as appropriate.
|
|
||||||
#
|
|
||||||
# Args: $field - Field to push new sections to.
|
|
||||||
# \$text - Raw text
|
|
||||||
#
|
|
||||||
# Retn: n/a
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub ParsePatches
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
my ($field, $text) = @_;
|
|
||||||
|
|
||||||
while (my $pi = $self->FindPatchStart($text)) {
|
|
||||||
# Everything up to this fragment can be
|
|
||||||
# promoted to a text section
|
|
||||||
push @{$self->{sections}->{$field}},
|
|
||||||
new GnatsPR::Section::Text(substr(
|
|
||||||
$$text,
|
|
||||||
0,
|
|
||||||
$pi->{start},
|
|
||||||
''
|
|
||||||
))
|
|
||||||
unless $pi->{start} == 0;
|
|
||||||
|
|
||||||
$pi->{start} = 0;
|
|
||||||
|
|
||||||
$self->FindPatchEnd($text, $pi);
|
|
||||||
|
|
||||||
# Try to determine if a web/send-pr attachment
|
|
||||||
# has another type of patch inside.
|
|
||||||
if ($pi->{type} eq 'stdattach' or $pi->{type} eq 'webattach') {
|
|
||||||
if (my $pi2 = $self->FindPatchStart($text)) {
|
|
||||||
# Upgrade to more specific type
|
|
||||||
$pi->{type} = $pi2->{type}
|
|
||||||
if ($pi2->{start} == 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
push @{$self->{sections}->{$field}},
|
|
||||||
new GnatsPR::Section::Patch(substr(
|
|
||||||
$$text,
|
|
||||||
0,
|
|
||||||
$pi->{size},
|
|
||||||
''
|
|
||||||
), $pi->{name}, $pi->{type});
|
|
||||||
|
|
||||||
$$text =~ s/^[\n\s]+//;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Rest of the field is text
|
|
||||||
push @{$self->{sections}->{$field}},
|
|
||||||
new GnatsPR::Section::Text($$text)
|
|
||||||
if ($$text);
|
|
||||||
|
|
||||||
$text = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: FindPatchStart()
|
|
||||||
# Desc: Find the beginning of the first patch inside the given text blob,
|
|
||||||
# if there is one.
|
|
||||||
#
|
|
||||||
# Args: \$text - Raw text
|
|
||||||
#
|
|
||||||
# Retn: \%pi - Hash of patch info (or undef):
|
|
||||||
# - start - Start offset of patch
|
|
||||||
# - type - Type of attachment found
|
|
||||||
# - name - Filename, if available
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub FindPatchStart
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
my ($text) = @_;
|
|
||||||
|
|
||||||
# Patch from web CGI script. Characteristics:
|
|
||||||
# - Only ever one of them.
|
|
||||||
# - Appended to the end of Fix:
|
|
||||||
# - Blank line after header line
|
|
||||||
# - Could contain other types of patch (e.g. shar(1) archive)
|
|
||||||
if ($$text =~ /^Patch attached with submission follows:$/m && $self->{fromwebform}) {
|
|
||||||
my $start = $+[0]; # The newline on the above
|
|
||||||
|
|
||||||
# Next non-blank line (i.e. start of patch)
|
|
||||||
if ($$text =~ /\G^./m) {
|
|
||||||
$start += $+[0]+1;
|
|
||||||
return {start => $start, type => 'webattach'};
|
|
||||||
}
|
|
||||||
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Patch from send-pr(1). Characteristics:
|
|
||||||
# - Has header and footer line.
|
|
||||||
# - Appended to the end of Fix:
|
|
||||||
# - User has an opportunity to edit/mangle.
|
|
||||||
# - Could contain other types of patch (e.g. shar(1) archive)
|
|
||||||
if ($$text =~ /^---{1,8}\s?([A-Za-z0-9-_.,:%]+) (begins|starts) here\s?---+\n/mi) {
|
|
||||||
my $r = {start => $-[0], type => 'stdattach', name => $1};
|
|
||||||
|
|
||||||
# Chop header line
|
|
||||||
substr($$text, $-[0], $+[0] - $-[0], '');
|
|
||||||
|
|
||||||
return $r;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Patch files from diff(1). Characteristics:
|
|
||||||
# - Easy to find start.
|
|
||||||
# - Difficult to find the end.
|
|
||||||
$$text =~ /^((?:(?:---|\*\*\*)\ (?:\S+)\s*(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\ .*)
|
|
||||||
|(?:(?:---|\*\*\*)\ (?:\S+)\s*(?:\d\d\d\d-\d\d-\d\d\ \d\d:\d\d:\d\d\.\d+)\ .*)
|
|
||||||
|(diff\ -.*?\ .*?\ .*)|(Index:\ \S+)
|
|
||||||
|(\*{3}\ \d+,\d+\ \*{4}))$/mx
|
|
||||||
and return {start => $-[0], type => 'diff'};
|
|
||||||
|
|
||||||
# Shell archive from shar(1)
|
|
||||||
$$text =~ /^# This is a shell archive\. Save it in a file, remove anything before/m
|
|
||||||
and return {start => $-[0], type => 'shar'};
|
|
||||||
|
|
||||||
# UUencoded file. Characteristics:
|
|
||||||
# - Has header and footer.
|
|
||||||
$$text =~ /^begin \d\d\d (.*)/m
|
|
||||||
and return {start => $-[0], type => 'uuencoded', name => $1};
|
|
||||||
|
|
||||||
# Base64 encoded file. Characteristics:
|
|
||||||
# - Has header and footer.
|
|
||||||
$$text =~ /^begin-base64 \d\d\d (.*)/m
|
|
||||||
and return {start => $-[0], type => 'base64', name => $1};
|
|
||||||
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: FindPatchEnd()
|
|
||||||
# Desc: Find the end of the first patch inside the given text blob, if any.
|
|
||||||
#
|
|
||||||
# Args: \$text - Raw text
|
|
||||||
# \%pi - Patch info hash from FindPatchStart(). We'll add more data:
|
|
||||||
# - size - Length of the patch.
|
|
||||||
#
|
|
||||||
# Retn: \%pi - Same as above, except undef will be returned if no actual
|
|
||||||
# endpoint was found (size in pi would extend to the end of the
|
|
||||||
# text blob in this case.)
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub FindPatchEnd
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
my ($text, $pi) = @_;
|
|
||||||
|
|
||||||
$pi->{size} = 0;
|
|
||||||
|
|
||||||
if ($pi->{type} eq 'webattach') {
|
|
||||||
$$text =~ /$/
|
|
||||||
and $pi->{size} = $+[0];
|
|
||||||
} elsif ($pi->{type} eq 'stdattach') {
|
|
||||||
$$text =~ /^---{1,8}\s?\Q$pi->{name}\E ends here\s?---+/mi
|
|
||||||
and $pi->{size} = $-[0]-1;
|
|
||||||
# Chop footer line
|
|
||||||
substr($$text, $-[0], $+[0] - $-[0], '');
|
|
||||||
} elsif ($pi->{type} eq 'diff') {
|
|
||||||
# XXX: could do better
|
|
||||||
$$text =~ /^$/m
|
|
||||||
and $pi->{size} = $-[0]-1;
|
|
||||||
} elsif ($pi->{type} eq 'shar') {
|
|
||||||
$$text =~ /^exit$/m
|
|
||||||
and $pi->{size} = $+[0];
|
|
||||||
} elsif ($pi->{type} eq 'uuencoded') {
|
|
||||||
$$text =~ /^end$/m
|
|
||||||
and $pi->{size} = $+[0];
|
|
||||||
} elsif ($pi->{type} eq 'base64') {
|
|
||||||
$$text =~ /^====$/m
|
|
||||||
and $pi->{size} = $+[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($pi->{size} == 0) {
|
|
||||||
$pi->{size} = length $$text;
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $pi;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: GetAttachment()
|
|
||||||
# Desc: Recursively search sections for a downloadable attachment.
|
|
||||||
#
|
|
||||||
# Args: $num - Attachment index (counts from 1)
|
|
||||||
#
|
|
||||||
# Retn: $sec - Attachment section (or undef)
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub GetAttachment
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
my ($num) = @_;
|
|
||||||
my $cur = 1;
|
|
||||||
|
|
||||||
my $iter = GnatsPR::SectionIterator->new($self, 'Fix', 'Audit-Trail');
|
|
||||||
|
|
||||||
while (my $item = $iter->next()) {
|
|
||||||
if (ref $item eq 'GnatsPR::Section::Patch') {
|
|
||||||
# Patch sections
|
|
||||||
return $item if ($cur++ == $num);
|
|
||||||
} elsif (ref $item eq 'GnatsPR::Section::Email') {
|
|
||||||
# Attachments from MIME messages
|
|
||||||
my $mime_iter = GnatsPR::MIMEIterator->new($item);
|
|
||||||
while (my $part = $mime_iter->next()) {
|
|
||||||
if ($part->isattachment) {
|
|
||||||
return $part if ($cur++ == $num);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
@ -1,153 +0,0 @@
|
||||||
#!/usr/bin/perl -Tw
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Copyright (C) 2011, Shaun Amott <shaun@FreeBSD.org>
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
package GnatsPR::MIMEIterator;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
require 5.006;
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: new()
|
|
||||||
# Desc: Constructor.
|
|
||||||
#
|
|
||||||
# Args: $email - GnatsPR::Section::Email instance.
|
|
||||||
#
|
|
||||||
# Retn: $self
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub new
|
|
||||||
{
|
|
||||||
my $class = shift;
|
|
||||||
my $email = shift;
|
|
||||||
|
|
||||||
my $self = {
|
|
||||||
idxlist => [ -1 ],
|
|
||||||
email => undef
|
|
||||||
};
|
|
||||||
|
|
||||||
bless $self, $class;
|
|
||||||
|
|
||||||
$self->{email} = $email;
|
|
||||||
|
|
||||||
return $self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: next()
|
|
||||||
# Desc: Return next iterator element.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: $next
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub next
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
my $curr = $self->_current();
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
my $next = ++$self->{idxlist}->[$#{$self->{idxlist}}];
|
|
||||||
|
|
||||||
# Past last element?
|
|
||||||
if ($next > $#{$curr->{mimeparts}}) {
|
|
||||||
# Back out
|
|
||||||
pop @{$self->{idxlist}};
|
|
||||||
|
|
||||||
# Reached the root
|
|
||||||
$#{$self->{idxlist}} > -1
|
|
||||||
or return undef;
|
|
||||||
|
|
||||||
$curr = $self->_current();
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $rpart = $curr->{mimeparts}->[$self->{idxlist}->[$#{$self->{idxlist}}]];
|
|
||||||
|
|
||||||
# Container part? - find a leaf node
|
|
||||||
while ($#{$rpart->{mimeparts}} > -1) {
|
|
||||||
$rpart = $rpart->{mimeparts}->[0];
|
|
||||||
push @{$self->{idxlist}}, 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $rpart;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: isfirst()
|
|
||||||
# Desc: Determine if the iterator is at the first element.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: $isfirst - true/false
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub isfirst
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
return (
|
|
||||||
$#{$self->{idxlist}} == 0
|
|
||||||
and $self->{idxlist}->[$#{$self->{idxlist}}] == 0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: _current()
|
|
||||||
# Desc: Traverse to, and return, the current container element.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: $curr
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub _current
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
my $curr = $self->{email};
|
|
||||||
|
|
||||||
# Find current MIME part container
|
|
||||||
for (my $depth = 0; $depth < $#{$self->{idxlist}}; $depth++) {
|
|
||||||
$curr = $curr->{mimeparts}->[$self->{idxlist}->[$depth]];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $curr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
# $FreeBSD$
|
|
||||||
|
|
||||||
.if exists(../Makefile.conf)
|
|
||||||
.include "../Makefile.conf"
|
|
||||||
.endif
|
|
||||||
.if exists(../Makefile.inc)
|
|
||||||
.include "../Makefile.inc"
|
|
||||||
.endif
|
|
||||||
|
|
||||||
SUBDIR= Section
|
|
||||||
|
|
||||||
DATA= MIMEIterator.pm Section.pm SectionIterator.pm
|
|
||||||
|
|
||||||
.include "${DOC_PREFIX}/share/mk/web.site.mk"
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
# $FreeBSD$
|
|
||||||
|
|
||||||
WEBBASE?= /data/cgi/GnatsPR
|
|
||||||
DOC_PREFIX?= ${.CURDIR}/../../../../..
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
#!/usr/bin/perl -Tw
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Copyright (C) 2011, Shaun Amott <shaun@FreeBSD.org>
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
package Section;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
require 5.006;
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: new()
|
|
||||||
# Desc: Constructor.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: $self
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub new
|
|
||||||
{
|
|
||||||
my $class = shift;
|
|
||||||
|
|
||||||
my $self = {
|
|
||||||
};
|
|
||||||
|
|
||||||
bless $self, $class;
|
|
||||||
return $self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
@ -1,189 +0,0 @@
|
||||||
#!/usr/bin/perl -Tw
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Copyright (C) 2011, Shaun Amott <shaun@FreeBSD.org>
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
package GnatsPR::Section::Email;
|
|
||||||
|
|
||||||
use GnatsPR::Section::MIME;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
require 5.006;
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: new()
|
|
||||||
# Desc: Constructor.
|
|
||||||
#
|
|
||||||
# Args: $header - Raw e-mail header.
|
|
||||||
# $body - Raw message body.
|
|
||||||
#
|
|
||||||
# Retn: $self
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub new
|
|
||||||
{
|
|
||||||
my $class = shift;
|
|
||||||
my ($header, $body) = @_;
|
|
||||||
|
|
||||||
my $self = {
|
|
||||||
headerblob => '',
|
|
||||||
bodyblob => '',
|
|
||||||
|
|
||||||
headers => {},
|
|
||||||
|
|
||||||
mimeparts => []
|
|
||||||
};
|
|
||||||
|
|
||||||
bless $self, $class;
|
|
||||||
|
|
||||||
$self->{headerblob} = $header;
|
|
||||||
$self->{bodyblob} = $body;
|
|
||||||
|
|
||||||
$self->ParseHeader() if ($header);
|
|
||||||
$self->ParseBody() if ($body);
|
|
||||||
|
|
||||||
return $self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: ParseHeader()
|
|
||||||
# Desc: Parse header blob into fields.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: n/a
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub ParseHeader
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
my $key;
|
|
||||||
|
|
||||||
foreach my $line (split /\n/, $self->{headerblob}) {
|
|
||||||
if ($line =~ /^(\S+):\s*(.*)$/) {
|
|
||||||
my $val = $2;
|
|
||||||
$key = lc $1;
|
|
||||||
|
|
||||||
# Ignore multiple defs (e.g. Received: headers)
|
|
||||||
exists $self->{headers}->{$key}
|
|
||||||
and next;
|
|
||||||
|
|
||||||
$self->{headers}->{$key} = $val;
|
|
||||||
} elsif ($line =~ /^\s*(.*)$/) {
|
|
||||||
my $val = $1;
|
|
||||||
|
|
||||||
defined $key
|
|
||||||
or next;
|
|
||||||
|
|
||||||
# No field to append to
|
|
||||||
exists $self->{headers}->{$key}
|
|
||||||
or next;
|
|
||||||
|
|
||||||
$self->{headers}->{$key} .= ' '.$val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: ParseBody()
|
|
||||||
# Desc: Parse body blob.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: n/a
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub ParseBody
|
|
||||||
{
|
|
||||||
# XXX: recurse to second-level parts
|
|
||||||
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
$self->{mimeparts} = [];
|
|
||||||
|
|
||||||
# First of all - attempt to split into MIME parts
|
|
||||||
# Note that since GNATS nukes a bunch of the headers
|
|
||||||
# that we need, this is purely of a heuristic nature.
|
|
||||||
|
|
||||||
# Technically less permissive than RFC1341
|
|
||||||
|
|
||||||
my $nextbound = qr/^--([A-Za-z0-9'()+_,-.\/:=?]{6,70})$/m;
|
|
||||||
my $first = 1;
|
|
||||||
|
|
||||||
while ($self->{bodyblob} =~ s/$nextbound//m) {
|
|
||||||
my $last;
|
|
||||||
|
|
||||||
if ($first) {
|
|
||||||
my $boundary = $1;
|
|
||||||
$nextbound = qr/^--\Q$boundary\E(--)?$/m;
|
|
||||||
$last = 0;
|
|
||||||
$first = 0;
|
|
||||||
} else {
|
|
||||||
$last = ($2 and $2 eq '--');
|
|
||||||
}
|
|
||||||
|
|
||||||
# Promote to MIME part
|
|
||||||
|
|
||||||
push @{$self->{mimeparts}},
|
|
||||||
new GnatsPR::Section::MIME(
|
|
||||||
substr($self->{bodyblob}, 0, $-[0], '')
|
|
||||||
)
|
|
||||||
unless ($-[0] == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!@{$self->{mimeparts}}) {
|
|
||||||
# No parts - just plain text
|
|
||||||
push @{$self->{mimeparts}},
|
|
||||||
new GnatsPR::Section::MIME($self->{bodyblob});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: Header()
|
|
||||||
# Desc: Return a header field.
|
|
||||||
#
|
|
||||||
# Args: $key - Header name, case insensitive.
|
|
||||||
#
|
|
||||||
# Retn: $val - Value.
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub Header
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
my ($key) = @_;
|
|
||||||
|
|
||||||
return $self->{headers}->{lc $key};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
#!/usr/bin/perl -Tw
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Copyright (C) 2011, Shaun Amott <shaun@FreeBSD.org>
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
package GnatsPR::Section::FieldStart;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
require 5.006;
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: new()
|
|
||||||
# Desc: Constructor.
|
|
||||||
#
|
|
||||||
# Args: $name - Field name.
|
|
||||||
#
|
|
||||||
# Retn: $self
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub new
|
|
||||||
{
|
|
||||||
my $class = shift;
|
|
||||||
my ($name) = @_;
|
|
||||||
|
|
||||||
my $self = {
|
|
||||||
name => ''
|
|
||||||
};
|
|
||||||
|
|
||||||
bless $self, $class;
|
|
||||||
|
|
||||||
$self->{name} = $name;
|
|
||||||
|
|
||||||
return $self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: string()
|
|
||||||
# Desc: Return the field name.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: $string
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub string
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
return $self->{name};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
@ -1,334 +0,0 @@
|
||||||
#!/usr/bin/perl -Tw
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Copyright (C) 2011, Shaun Amott <shaun@FreeBSD.org>
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
package GnatsPR::Section::MIME;
|
|
||||||
|
|
||||||
use MIME::Base64; # ports/converters/p5-MIME-Base64
|
|
||||||
use MIME::QuotedPrint; #
|
|
||||||
use Convert::UU qw(uudecode uuencode); # ports/converters/p5-Convert-UU
|
|
||||||
|
|
||||||
use Encode;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
require 5.006;
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: new()
|
|
||||||
# Desc: Constructor.
|
|
||||||
#
|
|
||||||
# Args: $blob - Raw MIME part, inc. any headers.
|
|
||||||
#
|
|
||||||
# Retn: $self
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub new
|
|
||||||
{
|
|
||||||
my $class = shift;
|
|
||||||
my ($blob) = @_;
|
|
||||||
|
|
||||||
my $self = {
|
|
||||||
body => '',
|
|
||||||
decoded_body => '',
|
|
||||||
headers => {},
|
|
||||||
binary => 0,
|
|
||||||
encoded => 0,
|
|
||||||
attachment => 0,
|
|
||||||
filename => '',
|
|
||||||
mimeparts => [] # Sub parts (usually empty)
|
|
||||||
};
|
|
||||||
|
|
||||||
bless $self, $class;
|
|
||||||
|
|
||||||
$self->{body} = $blob;
|
|
||||||
|
|
||||||
$self->Parse() if ($blob);
|
|
||||||
|
|
||||||
return $self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Accessors
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub body
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
$self->{body} = $_[0] if @_;
|
|
||||||
return $self->{body};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub isbinary
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
return $self->{binary};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub isencoded
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
return $self->{encoded};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub isattachment
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
return $self->{attachment};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub filename
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
return $self->{filename};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub data
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
return $self->{encoded} ? $self->{decoded_body} : $self->{body};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub size
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
return length($self->{encoded} ? $self->{decoded_body} : $self->{body});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: Parse()
|
|
||||||
# Desc: Parse and decode raw MIME part.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: n/a
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub Parse
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
my $charset;
|
|
||||||
|
|
||||||
$self->{body} =~ s/^[\n\s]+//;
|
|
||||||
$self->{body} =~ s/[\n\s]+$/\n/;
|
|
||||||
|
|
||||||
$self->ParseHeader();
|
|
||||||
|
|
||||||
# Determine if we're a multi-part container
|
|
||||||
if (lc $self->header('content-type') =~ /multipart/
|
|
||||||
and $self->header('content-type:boundary')) {
|
|
||||||
my $bound = $self->header('content-type:boundary');
|
|
||||||
@{$self->{mimeparts}} =
|
|
||||||
map {
|
|
||||||
new GnatsPR::Section::MIME($_);
|
|
||||||
}
|
|
||||||
grep !/^[\n\s]*$/,
|
|
||||||
split /^--\Q$bound\E(?:--)?$/m, $self->{body};
|
|
||||||
$self->{body} = undef;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($self->header('content-type:charset')) {
|
|
||||||
my $cs = $self->header('content-type:charset');
|
|
||||||
|
|
||||||
if ($cs =~ /utf.*8/i) {
|
|
||||||
$cs = 'utf-8';
|
|
||||||
} else {
|
|
||||||
$cs = Encode::resolve_alias($cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($cs and $cs ne 'ascii') {
|
|
||||||
$charset = $cs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Look for Quoted-Printable (explicit or using a silly heuristic)
|
|
||||||
if (lc $self->header('content-transfer-encoding') eq 'quoted-printable'
|
|
||||||
or $self->{body} =~ /=[0-9A-Fa-f]{2}=[0-9A-Fa-f]{2}/) {
|
|
||||||
$self->{body} = decode_qp($self->{body});
|
|
||||||
$self->{body} = decode($charset, $self->{body})
|
|
||||||
if ($charset);
|
|
||||||
|
|
||||||
# Base64 -- probably better not to decode
|
|
||||||
} elsif (lc $self->header('content-transfer-encoding') eq 'base64') {
|
|
||||||
$self->{decoded_body} = decode_base64($self->{body});
|
|
||||||
$self->{decoded_body} = decode($charset, $self->{decoded_body})
|
|
||||||
if ($charset);
|
|
||||||
$self->{encoded} = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Catches too much stuff that we can display
|
|
||||||
#if ($self->header('content-type')
|
|
||||||
# && $self->header('content-type') !~ 'text/') {
|
|
||||||
# $self->{binary} = 1;
|
|
||||||
#}
|
|
||||||
|
|
||||||
if (lc $self->header('content-disposition') eq 'attachment') {
|
|
||||||
my $filename =
|
|
||||||
$self->header('content-disposition:filename')
|
|
||||||
|| $self->header('content-type:name')
|
|
||||||
|| $self->header('x-attachment-id')
|
|
||||||
|| 'attachment';
|
|
||||||
|
|
||||||
$filename =~ '(?:\.gz|\.bz2|\.zip|\.tar)$'
|
|
||||||
and $self->{binary} = 1;
|
|
||||||
|
|
||||||
$self->{attachment} = 1;
|
|
||||||
$self->{filename} = $filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($self->{body} =~ /^begin \d\d\d (.*)/ && !$self->{encoded}) {
|
|
||||||
$self->{decoded_body} = uudecode($self->{body});
|
|
||||||
$self->{encoded} = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: ParseHeader()
|
|
||||||
# Desc: Parse out any MIME header fields.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: n/a
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub ParseHeader
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
my $header = '';
|
|
||||||
my $key;
|
|
||||||
|
|
||||||
# Start with some defaults
|
|
||||||
$self->{headers}->{'content-type'} = 'text/plain';
|
|
||||||
|
|
||||||
# No header?
|
|
||||||
$self->{body} =~ /^Content-/i
|
|
||||||
or return;
|
|
||||||
|
|
||||||
# Ensure we have an end-of-header marker. Returning here
|
|
||||||
# will result in some bodyless headers being dumped as
|
|
||||||
# text (example in conf/138672) -- but I think this is
|
|
||||||
# the safe option, in case such a header is in fact the
|
|
||||||
# body of a malformed message.
|
|
||||||
$self->{body} =~ /^$/m and $+[0] != length($self->{body}) or return;
|
|
||||||
|
|
||||||
$header = substr($self->{body}, 0, $+[0]+1, '');
|
|
||||||
|
|
||||||
$self->{body} =~ s/^[\n\s]+//;
|
|
||||||
|
|
||||||
foreach my $line (split /\n/, $header) {
|
|
||||||
if ($line =~ /^(\S+): (.*)$/) {
|
|
||||||
$key = lc $1;
|
|
||||||
$self->{headers}->{$key} = $2;
|
|
||||||
} elsif ($line =~ /^\s+(.*)$/) {
|
|
||||||
$key or next;
|
|
||||||
$self->{headers}->{$key} .= ' ' . $1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Split up aggregate headers into individual values
|
|
||||||
|
|
||||||
foreach my $key (keys %{$self->{headers}}) {
|
|
||||||
$self->{headers}->{$key} =~ /;/ or next;
|
|
||||||
|
|
||||||
my @chars = split //, $self->{headers}->{$key};
|
|
||||||
my $inquote = 0;
|
|
||||||
my $gotkey = 0;
|
|
||||||
my $k = '';
|
|
||||||
my $v = '';
|
|
||||||
|
|
||||||
foreach my $char (@chars) {
|
|
||||||
if ($char eq '"') {
|
|
||||||
$inquote = !$inquote;
|
|
||||||
next;
|
|
||||||
} elsif ($char eq '=' && !$inquote) {
|
|
||||||
$gotkey = 1;
|
|
||||||
next;
|
|
||||||
} elsif ($char eq ';' && !$inquote) {
|
|
||||||
if ($k and $v) {
|
|
||||||
$k = lc $k;
|
|
||||||
$self->{headers}->{"$key:$k"} = $v;
|
|
||||||
}
|
|
||||||
$k = $v = '';
|
|
||||||
$gotkey = 0;
|
|
||||||
next;
|
|
||||||
} elsif (($char eq ' ' or $char eq '\t') && !$inquote) {
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($gotkey) {
|
|
||||||
$v .= $char;
|
|
||||||
} else {
|
|
||||||
$k .= $char;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($k and $v) {
|
|
||||||
$k = lc $k;
|
|
||||||
$self->{headers}->{"$key:$k"} = $v;
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->{headers}->{$key} =~ s/;.*$//;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Normalise
|
|
||||||
|
|
||||||
$self->{headers}->{'content-type'} =
|
|
||||||
lc $self->{headers}->{'content-type'};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: header()
|
|
||||||
# Desc: Return header.
|
|
||||||
#
|
|
||||||
# Args: $key
|
|
||||||
#
|
|
||||||
# Retn: $val
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub header
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
my ($key) = @_;
|
|
||||||
|
|
||||||
$key = lc $key;
|
|
||||||
|
|
||||||
return $self->{headers}->{$key}
|
|
||||||
if (exists $self->{headers}->{$key});
|
|
||||||
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
# $FreeBSD$
|
|
||||||
|
|
||||||
.if exists(../Makefile.conf)
|
|
||||||
.include "../Makefile.conf"
|
|
||||||
.endif
|
|
||||||
.if exists(../Makefile.inc)
|
|
||||||
.include "../Makefile.inc"
|
|
||||||
.endif
|
|
||||||
|
|
||||||
DATA= Email.pm FieldStart.pm MIME.pm Patch.pm StateChange.pm Text.pm
|
|
||||||
|
|
||||||
.include "${DOC_PREFIX}/share/mk/web.site.mk"
|
|
||||||
|
|
@ -1,188 +0,0 @@
|
||||||
#!/usr/bin/perl -Tw
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Copyright (C) 2011, Shaun Amott <shaun@FreeBSD.org>
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
package GnatsPR::Section::Patch;
|
|
||||||
|
|
||||||
use MIME::Base64; # ports/converters/p5-MIME-Base64
|
|
||||||
use Convert::UU qw(uudecode uuencode); # ports/converters/p5-Convert-UU
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
require 5.006;
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: new()
|
|
||||||
# Desc: Constructor.
|
|
||||||
#
|
|
||||||
# Args: $text - Blob of text.
|
|
||||||
# $filename - Filename of patch, if we have one.
|
|
||||||
# $type - Patch type string (if known).
|
|
||||||
#
|
|
||||||
# Retn: $self
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub new
|
|
||||||
{
|
|
||||||
my $class = shift;
|
|
||||||
my ($text, $filename, $type) = @_;
|
|
||||||
|
|
||||||
my $self = {
|
|
||||||
text => '',
|
|
||||||
filename => 'patch.txt',
|
|
||||||
binary => 0,
|
|
||||||
encoded => 0,
|
|
||||||
type => 'unknown'
|
|
||||||
};
|
|
||||||
|
|
||||||
bless $self, $class;
|
|
||||||
|
|
||||||
$self->{text} = $text;
|
|
||||||
|
|
||||||
$self->{filename} = $filename if $filename;
|
|
||||||
$self->{type} = $type if $type;
|
|
||||||
|
|
||||||
$self->{filename} =~ '(?:\.gz|\.bz2|\.zip|\.tar)$'
|
|
||||||
and $self->{binary} = 1;
|
|
||||||
|
|
||||||
if ($self->{type} eq 'uuencoded') {
|
|
||||||
$self->{encoded} = 1;
|
|
||||||
$self->{decoded_text} = uudecode($self->{text});
|
|
||||||
} elsif ($self->{type} eq 'base64') {
|
|
||||||
$self->{encoded} = 1;
|
|
||||||
$self->{decoded_text} = decode_base64($self->{text});
|
|
||||||
}
|
|
||||||
|
|
||||||
return $self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: string()
|
|
||||||
# Desc: Return string contained within.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: $string
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub string
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
return $self->{text};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: size()
|
|
||||||
# Desc: Return the length of the contained data.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: $string
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub size
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
return length($self->{encoded} ? $self->{decoded_text} : $self->{text});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: data()
|
|
||||||
# Desc: Return the raw decoded (if possible/necessary) data.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: $string
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub data
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
return $self->{encoded} ? $self->{decoded_text} : $self->{text};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: filename()
|
|
||||||
# Desc: Return the patch's filename.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: $filename
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub filename
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
return $self->{filename};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: type()
|
|
||||||
# Desc: Return the patch's type.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: $type
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub type
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
return $self->{type};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: isbinary()
|
|
||||||
# Desc: Is patch binary?
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: $type
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub isbinary
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
return $self->{binary};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
@ -1,117 +0,0 @@
|
||||||
#!/usr/bin/perl -Tw
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Copyright (C) 2011, Shaun Amott <shaun@FreeBSD.org>
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
package GnatsPR::Section::StateChange;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
require 5.006;
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: new()
|
|
||||||
# Desc: Constructor.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: $self
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub new
|
|
||||||
{
|
|
||||||
my $class = shift;
|
|
||||||
|
|
||||||
my $self = {
|
|
||||||
what => '', # State or Responsible
|
|
||||||
from => '', # Change from
|
|
||||||
to => '', # Change to
|
|
||||||
why => '', # Reason for change
|
|
||||||
when => '', # Date of change
|
|
||||||
by => '' # Who changed it
|
|
||||||
};
|
|
||||||
|
|
||||||
bless $self, $class;
|
|
||||||
|
|
||||||
return $self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Accessors
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub what
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
$self->{what} = $_[0] if @_;
|
|
||||||
return $self->{what};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub from
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
$self->{from} = $_[0] if @_;
|
|
||||||
return $self->{from};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub to
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
$self->{to} = $_[0] if @_;
|
|
||||||
return $self->{to};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub why
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
if (scalar @_) {
|
|
||||||
$self->{why} = $_[0];
|
|
||||||
$self->{why} =~ s/^\s+//;
|
|
||||||
$self->{why} =~ s/[\n\s]+$//;
|
|
||||||
}
|
|
||||||
return $self->{why};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub when
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
$self->{when} = $_[0] if @_;
|
|
||||||
return $self->{when};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub by
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
$self->{by} = $_[0] if @_;
|
|
||||||
return $self->{by};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
#!/usr/bin/perl -Tw
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Copyright (C) 2011, Shaun Amott <shaun@FreeBSD.org>
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
package GnatsPR::Section::Text;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
require 5.006;
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: new()
|
|
||||||
# Desc: Constructor.
|
|
||||||
#
|
|
||||||
# Args: $text - Blob of text.
|
|
||||||
#
|
|
||||||
# Retn: $self
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub new
|
|
||||||
{
|
|
||||||
my $class = shift;
|
|
||||||
my ($text) = @_;
|
|
||||||
|
|
||||||
my $self = {
|
|
||||||
text => ''
|
|
||||||
};
|
|
||||||
|
|
||||||
bless $self, $class;
|
|
||||||
|
|
||||||
$text =~ s/[\s\n]+$//s; # Tidy up trailing whitespace
|
|
||||||
|
|
||||||
$self->{text} = $text;
|
|
||||||
|
|
||||||
return $self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: string()
|
|
||||||
# Desc: Return string contained within.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: $string
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub string
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
return $self->{text};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
@ -1,114 +0,0 @@
|
||||||
#!/usr/bin/perl -Tw
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Copyright (C) 2011, Shaun Amott <shaun@FreeBSD.org>
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
package GnatsPR::SectionIterator;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
require 5.006;
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: new()
|
|
||||||
# Desc: Constructor.
|
|
||||||
#
|
|
||||||
# Args: $gnatspr - GnatsPR instance.
|
|
||||||
# @fields - Which fields we want sections from. The order determines
|
|
||||||
# the order of the returned sections. Undefined behaviour if
|
|
||||||
# no no fields specified.
|
|
||||||
#
|
|
||||||
# Retn: $self
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub new
|
|
||||||
{
|
|
||||||
my $class = shift;
|
|
||||||
my $gnatspr = shift;
|
|
||||||
|
|
||||||
my $self = {
|
|
||||||
gnatspr => $gnatspr,
|
|
||||||
currfield => -1,
|
|
||||||
currsection => -1,
|
|
||||||
wantfields => []
|
|
||||||
};
|
|
||||||
|
|
||||||
bless $self, $class;
|
|
||||||
|
|
||||||
while (my $f = shift) {
|
|
||||||
push @{$self->{wantfields}}, $f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: next()
|
|
||||||
# Desc: Return next iterator element.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: $next
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub next
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
my ($fieldkey, $maxsection);
|
|
||||||
|
|
||||||
# Next section
|
|
||||||
$self->{currsection}++;
|
|
||||||
|
|
||||||
# First field?
|
|
||||||
$self->{currfield} == -1
|
|
||||||
and $self->{currfield} = 0;
|
|
||||||
|
|
||||||
$fieldkey = $self->{wantfields}->[$self->{currfield}];
|
|
||||||
$maxsection = $#{$self->{gnatspr}->{sections}->{$fieldkey}};
|
|
||||||
|
|
||||||
# We've passed the last section in this field
|
|
||||||
while ($self->{currsection} > $maxsection) {
|
|
||||||
# Next field, first section
|
|
||||||
$self->{currfield}++;
|
|
||||||
$self->{currsection} = 0;
|
|
||||||
|
|
||||||
# Run out of fields?
|
|
||||||
$self->{currfield} > $#{$self->{wantfields}}
|
|
||||||
and return undef;
|
|
||||||
|
|
||||||
# Update, and go back to check next field
|
|
||||||
$fieldkey = $self->{wantfields}->[$self->{currfield}];
|
|
||||||
$maxsection = $#{$self->{gnatspr}->{sections}->{$fieldkey}};
|
|
||||||
}
|
|
||||||
|
|
||||||
return $self->{gnatspr}->{sections}->{$fieldkey}->[$self->{currsection}];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
@ -8,28 +8,17 @@
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
DATA=
|
DATA=
|
||||||
DATA+= Gnats.pm
|
|
||||||
DATA+= GnatsPR.pm
|
|
||||||
DATA+= cgi-lib.pl
|
DATA+= cgi-lib.pl
|
||||||
DATA+= cgi-style.pl
|
DATA+= cgi-style.pl
|
||||||
DATA+= query-pr-lib.pl
|
|
||||||
|
|
||||||
CGI=
|
CGI=
|
||||||
CGI+= confirm-code.cgi
|
|
||||||
CGI+= dosendpr.cgi
|
|
||||||
CGI+= getmsg.cgi
|
CGI+= getmsg.cgi
|
||||||
CGI+= mailindex.cgi
|
CGI+= mailindex.cgi
|
||||||
CGI+= man.cgi
|
CGI+= man.cgi
|
||||||
CGI+= mid.cgi
|
CGI+= mid.cgi
|
||||||
CGI+= mirror.cgi
|
CGI+= mirror.cgi
|
||||||
CGI+= missing_handler.cgi
|
|
||||||
CGI+= monthly.cgi
|
CGI+= monthly.cgi
|
||||||
CGI+= ports.cgi
|
CGI+= ports.cgi
|
||||||
CGI+= query-pr.cgi
|
|
||||||
CGI+= query-pr-summary.cgi
|
|
||||||
CGI+= search.cgi
|
|
||||||
|
|
||||||
SUBDIR= GnatsPR
|
|
||||||
|
|
||||||
.SUFFIXES: .C .cgi
|
.SUFFIXES: .C .cgi
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ if (!defined($hsty_base)) {
|
||||||
# However, if we aren't running as a cgi, or if we're
|
# However, if we aren't running as a cgi, or if we're
|
||||||
# running on cgi, hub, docs or people, use the absolute home path.
|
# running on cgi, hub, docs or people, use the absolute home path.
|
||||||
if (!defined($ENV{'HTTP_HOST'}) ||
|
if (!defined($ENV{'HTTP_HOST'}) ||
|
||||||
$ENV{'HTTP_HOST'} =~ /(cgi|hub|docs|people).freebsd.org/i) {
|
$ENV{'HTTP_HOST'} =~ /(cgi|hub|docs|people|mailarchive.ysv).freebsd.org/i) {
|
||||||
|
|
||||||
$hsty_base = '//www.FreeBSD.org'
|
$hsty_base = '//www.FreeBSD.org'
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -22,7 +22,7 @@ if (!defined($hsty_base)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!defined($hsty_email)) {
|
if (!defined($hsty_email)) {
|
||||||
$hsty_email = 'www@FreeBSD.org';
|
$hsty_email = 'Contact';
|
||||||
}
|
}
|
||||||
if (!defined($hsty_author)) {
|
if (!defined($hsty_author)) {
|
||||||
$hsty_author = "<a href='$hsty_base/mailto.html'>$hsty_email</a>";
|
$hsty_author = "<a href='$hsty_base/mailto.html'>$hsty_email</a>";
|
||||||
|
|
@ -83,7 +83,7 @@ $i_topbar = qq`
|
||||||
<div id="search">
|
<div id="search">
|
||||||
<form method="get" id="search" action="https://duckduckgo.com/">
|
<form method="get" id="search" action="https://duckduckgo.com/">
|
||||||
<h2 class="blockhide"><label for="words">Search</label></h2>
|
<h2 class="blockhide"><label for="words">Search</label></h2>
|
||||||
<input type="hidden" name="sites" value="www.FreeBSD.org,lists.FreeBSD.org,wiki.FreeBSD.org,forums.FreeBSD.org" />
|
<input type="hidden" name="sites" value="www.FreeBSD.org,docs.FreeBSD.org,lists.FreeBSD.org,wiki.FreeBSD.org,forums.FreeBSD.org" />
|
||||||
<input type="hidden" name="ka" value="v" />
|
<input type="hidden" name="ka" value="v" />
|
||||||
<input type="hidden" name="kt" value="v" />
|
<input type="hidden" name="kt" value="v" />
|
||||||
<input type="hidden" name="kh" value="1" />
|
<input type="hidden" name="kh" value="1" />
|
||||||
|
|
@ -160,8 +160,8 @@ $i_topbar = qq`
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="$hsty_base/commercial/commercial.html">Vendors</a></li>
|
<li><a href="$hsty_base/commercial/commercial.html">Vendors</a></li>
|
||||||
<li><a href="//security.FreeBSD.org/">Security Information</a></li>
|
<li><a href="//security.FreeBSD.org/">Security Information</a></li>
|
||||||
<li><a href="$hsty_base/cgi/query-pr-summary.cgi">Bug Reports</a></li>
|
<li><a href="https://bugs.freebsd.org/bugzilla/search/">Bug Reports</a></li>
|
||||||
<li><a href="$hsty_base/send-pr.html">Submit Bug-report</a></li>
|
<li><a href="$hsty_base/support.html">Submit Bug-report</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -1,117 +0,0 @@
|
||||||
#!/usr/bin/perl -T
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#
|
|
||||||
# Copyright (c) 2003 Eric Anderson
|
|
||||||
# Copyright (c) 2005 Ceri Davies <ceri@FreeBSD.org>
|
|
||||||
|
|
||||||
use DB_File;
|
|
||||||
use Fcntl qw(:DEFAULT :flock);
|
|
||||||
use POSIX qw(strftime);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
require './cgi-lib.pl';
|
|
||||||
|
|
||||||
$ENV{"PATH"} = "/bin:/usr/bin";
|
|
||||||
$ENV{"TMPDIR"} = "/tmp";
|
|
||||||
|
|
||||||
my($fd, $db_obj, %db_hash, $currenttime, $randomcode, $pngbindata, $randompick, $pnmlist, $i);
|
|
||||||
my(%db, $expiretime, $rfc1123_expiry, $pnmcat, $pnmtopng, $pnmdatadir, $dbpath, $FORM_db);
|
|
||||||
# %in cannot be declared with 'my', or ReadParse fails.
|
|
||||||
use vars qw/ %in /;
|
|
||||||
|
|
||||||
############################################
|
|
||||||
# generate 8 character code from A-Z0-9 (no I,O,0,1 for clarity)
|
|
||||||
my @availchars = qw(A B C D E F G H J K L M N P Q R S T U V W X Y Z
|
|
||||||
2 3 4 5 6 7 8 9);
|
|
||||||
|
|
||||||
$pnmcat = "/usr/local/bin/pnmcat";
|
|
||||||
$pnmtopng = "/usr/local/bin/pnmtopng";
|
|
||||||
$pnmdatadir = "../gifs/";
|
|
||||||
$expiretime = 0; # Default for the Expires: header
|
|
||||||
############################################
|
|
||||||
|
|
||||||
# The code databases that we know about. If a query comes in for
|
|
||||||
# anything else, we return a zero byte "image" (rather than an image
|
|
||||||
# with a rude word in, which was tempting).
|
|
||||||
|
|
||||||
%db = (
|
|
||||||
# The querypr one is not used, but stands as an example.
|
|
||||||
# querypr => {
|
|
||||||
# path => '/usr/local/www/var/confirm-code/querypr-code.db',
|
|
||||||
# lifespan => 2700,
|
|
||||||
# },
|
|
||||||
sendpr => {
|
|
||||||
path => '/usr/local/www/var/confirm-code/sendpr-code.db',
|
|
||||||
lifespan => 2700,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
&ReadParse(*in);
|
|
||||||
$FORM_db = $in{"db"}; $FORM_db ||= "junk";
|
|
||||||
|
|
||||||
$currenttime = time();
|
|
||||||
$rfc1123_expiry = strftime "%a, %b %d %H:%M:%S %Y %Z",
|
|
||||||
gmtime($currenttime + $expiretime);
|
|
||||||
|
|
||||||
if (exists($db{$FORM_db})) {
|
|
||||||
$dbpath = $db{$FORM_db}->{'path'};
|
|
||||||
$expiretime = $db{$FORM_db}->{'lifespan'};
|
|
||||||
|
|
||||||
# DB stuff here
|
|
||||||
$db_obj = tie(%db_hash, 'DB_File', $dbpath, O_CREAT|O_RDWR, 0644)
|
|
||||||
or die "dbcreate $dbpath $!";
|
|
||||||
$fd = $db_obj->fd;
|
|
||||||
open(DB_FH, "+<&=$fd") or die "fdopen $!";
|
|
||||||
|
|
||||||
unless (flock (DB_FH, LOCK_EX | LOCK_NB)) {
|
|
||||||
unless (flock (DB_FH, LOCK_EX)) { die "flock: $!" }
|
|
||||||
}
|
|
||||||
|
|
||||||
&gencode;
|
|
||||||
|
|
||||||
while ($db_hash{$randomcode}) {
|
|
||||||
# it already exists so:
|
|
||||||
# we check age (over x seconds old?)
|
|
||||||
# if it is, override with new date
|
|
||||||
# if not, generate a new code
|
|
||||||
if ( ($currenttime - $expiretime) <= $db_hash{$randomcode}) {
|
|
||||||
&gencode;
|
|
||||||
} else {
|
|
||||||
delete $db_hash{"$randomcode"};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$db_hash{$randomcode} = $currenttime;
|
|
||||||
|
|
||||||
$db_obj->sync(); # to flush
|
|
||||||
flock(DB_FH, LOCK_UN);
|
|
||||||
undef $db_obj; # removing the last reference to the DB
|
|
||||||
# closes it. Closing DB_FH is implicit.
|
|
||||||
untie %db_hash;
|
|
||||||
|
|
||||||
$/ = "";
|
|
||||||
|
|
||||||
open(BUILDPNG, "$pnmcat -lr $pnmlist | $pnmtopng 2>/dev/null |");
|
|
||||||
$pngbindata = <BUILDPNG>;
|
|
||||||
close(BUILDPNG);
|
|
||||||
} else {
|
|
||||||
$pngbindata = undef;
|
|
||||||
};
|
|
||||||
|
|
||||||
print "Pragma: no-cache\n";
|
|
||||||
print "Expires: $rfc1123_expiry\n";
|
|
||||||
print "Content-type: image/png\n\n";
|
|
||||||
print "$pngbindata";
|
|
||||||
|
|
||||||
############################################
|
|
||||||
sub gencode {
|
|
||||||
srand( time() ^ ($$ + ($$ << 15)) );
|
|
||||||
|
|
||||||
for ($i = 0; $i < 8; $i++) {
|
|
||||||
$randompick = $availchars[int(rand(@availchars))];
|
|
||||||
$randomcode .= "$randompick";
|
|
||||||
$pnmlist .= "$pnmdatadir$randompick\.pnm ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,226 +0,0 @@
|
||||||
#!/usr/bin/perl
|
|
||||||
#
|
|
||||||
# Send-pr perl script to send a pr.
|
|
||||||
#
|
|
||||||
# Copyright (c) 1996 Free Range Media
|
|
||||||
#
|
|
||||||
# Copying and distribution permitted under the conditions of the
|
|
||||||
# GNU General Public License Version 2.
|
|
||||||
# (http://www.gnu.ai.mit.edu/copyleft/gpl.html)
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
|
|
||||||
use Socket;
|
|
||||||
use CGI qw/:standard/;
|
|
||||||
use DB_File;
|
|
||||||
use Fcntl qw(:DEFAULT :flock);
|
|
||||||
require "./Gnats.pm"; import Gnats;
|
|
||||||
|
|
||||||
my $blackhole = "dnsbl.njabl.org";
|
|
||||||
my $openproxyip = "127.0.0.9";
|
|
||||||
my $blackhole_err = 0;
|
|
||||||
my $openproxy;
|
|
||||||
|
|
||||||
my $expiretime = 2700;
|
|
||||||
$dbpath = "/usr/local/www/var/confirm-code/sendpr-code.db";
|
|
||||||
|
|
||||||
# Maximum size of patch that we'll accept from send-pr.html.
|
|
||||||
$maxpatch = 102400;
|
|
||||||
|
|
||||||
my $patchbuf;
|
|
||||||
my $patchhandle;
|
|
||||||
|
|
||||||
# Environment variables to stuff in the PR header.
|
|
||||||
my @ENV_captures = qw/ REMOTE_HOST
|
|
||||||
REMOTE_ADDR
|
|
||||||
REMOTE_PORT
|
|
||||||
HTTP_REFERER
|
|
||||||
HTTP_CLIENT_IP
|
|
||||||
HTTP_FORWARDED
|
|
||||||
HTTP_VIA
|
|
||||||
HTTP_X_FORWARDED_FOR /;
|
|
||||||
|
|
||||||
# env2hdr (@ENV_captures)
|
|
||||||
# Returns X-header style headers for inclusion in the header of a PR
|
|
||||||
sub env2hdr (@) {
|
|
||||||
my $headers = "";
|
|
||||||
foreach my $var (@_) {
|
|
||||||
next unless $ENV{$var};
|
|
||||||
$headers .= "X-$var: $ENV{$var}\n";
|
|
||||||
}
|
|
||||||
return $headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
# isopenproxy ($ip, $blackhole_zone, $positive_ip)
|
|
||||||
# Returns undef on error, 0 if DNS lookup fails, $positive_ip if verified
|
|
||||||
# proxy. A DNS lookup failing can either means that there was a network
|
|
||||||
# problem, or that the IP is not listed in the blackhole zone.
|
|
||||||
sub isopenproxy ($$$) {
|
|
||||||
# If $? is already set, then a successful gethostbyname() leaves it set
|
|
||||||
local $?;
|
|
||||||
my ($ip, $zone, $proxyip) = @_;
|
|
||||||
my ($reversed_ip, $packed);
|
|
||||||
if (!defined $proxyip) { return undef };
|
|
||||||
|
|
||||||
$reversed_ip = join('.', reverse split(/\./, $ip));
|
|
||||||
$packed = gethostbyname("${reversed_ip}.${blackhole}");
|
|
||||||
return undef if $?;
|
|
||||||
|
|
||||||
if ($packed && (inet_ntoa($packed) eq $proxyip)) {
|
|
||||||
return $proxyip;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub prerror {
|
|
||||||
print start_html("Problem Report Error");
|
|
||||||
print "<p>There is an error in the configuration of the problem\n",
|
|
||||||
"report form generator. Please back up one page and report\n",
|
|
||||||
"the problem to the owner of that page.<br />",
|
|
||||||
"Report <span class=\"prerror\">$_[0]</span>.</p>";
|
|
||||||
print end_html();
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub piloterror {
|
|
||||||
print start_html("Problem Report Error");
|
|
||||||
print "<p>There is an error with your problem\n",
|
|
||||||
"report submission.\n",
|
|
||||||
"The problem was: <span class=\"prerror\">$_[0]</span>.</p>";
|
|
||||||
print end_html();
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
print header();
|
|
||||||
|
|
||||||
&prerror("request method problem") if $ENV{'REQUEST_METHOD'} eq 'GET';
|
|
||||||
|
|
||||||
if (!$submission_program) { &prerror("submit program problem"); }
|
|
||||||
|
|
||||||
if ($patchhandle = upload('patch')) {
|
|
||||||
# use bytes;
|
|
||||||
unless ((uploadInfo($patchhandle)->{'Content-Type'} =~ m!^text/.*!) ||
|
|
||||||
(uploadInfo($patchhandle)->{'Content-Type'} =~ m!^application/shar$!)) {
|
|
||||||
&piloterror("<p>Patch file has wrong content type: got " .
|
|
||||||
uploadInfo($patchhandle)->{'Content-Type'} .
|
|
||||||
" but was expecting one matching text/.* or application/shar.</p>" .
|
|
||||||
"<p>Try renaming the file to have a .txt extension" .
|
|
||||||
" to convince your browser to do the right thing.</p>");
|
|
||||||
}
|
|
||||||
read($patchhandle,$patchbuf,$maxpatch + 1);
|
|
||||||
if (length($patchbuf) > $maxpatch) {
|
|
||||||
&piloterror("Patch file too big (over ${maxpatch} bytes)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Verify the code...
|
|
||||||
|
|
||||||
$db_obj = tie(%db_hash, 'DB_File', $dbpath, O_CREAT|O_RDWR, 0644)
|
|
||||||
or die "dbcreate $dbpath $!";
|
|
||||||
$fd = $db_obj->fd;
|
|
||||||
open(DB_FH, "+<&=$fd") or die "fdopen $!";
|
|
||||||
|
|
||||||
unless (flock (DB_FH, LOCK_EX | LOCK_NB)) {
|
|
||||||
unless (flock (DB_FH, LOCK_EX)) { die "flock: $!" }
|
|
||||||
}
|
|
||||||
|
|
||||||
$codeentered = param('code-confirm');
|
|
||||||
$codeentered =~ s/.*/\U$&/; # Turn input uppercase
|
|
||||||
$currenttime = time();
|
|
||||||
if (defined($codeentered) && $codeentered && $db_hash{$codeentered} &&
|
|
||||||
(($currenttime - $expiretime) <= $db_hash{$codeentered})) {
|
|
||||||
if (!param('email') || !param('originator') ||
|
|
||||||
!param('synopsis')) {
|
|
||||||
print start_html("Problem Report Error");
|
|
||||||
print "<h1>Bad Data</h1><p>You need to specify at least your ",
|
|
||||||
"electronic mail address, your name and a synopsis ",
|
|
||||||
"of the problem.<br /> Please return to the form and add the ",
|
|
||||||
"missing information. Thank you.</p>";
|
|
||||||
print end_html();
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
print start_html("Problem Report Error");
|
|
||||||
print "<h1>Incorrect confirmation code</h1><p>You need to enter the correct ",
|
|
||||||
"code from the image displayed. Please return to the form and enter the ",
|
|
||||||
"code exactly as shown. Thank you.</p>";
|
|
||||||
print end_html();
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
# This code has now been used, so remove it.
|
|
||||||
delete $db_hash{"$codeentered"};
|
|
||||||
|
|
||||||
# Sweep for and remove expired codes.
|
|
||||||
foreach $randomcode (keys %db_hash) {
|
|
||||||
if ( ($currenttime - $expiretime) >= $db_hash{$randomcode}) {
|
|
||||||
delete $db_hash{"$randomcode"};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$db_obj->sync(); # to flush
|
|
||||||
flock(DB_FH, LOCK_UN);
|
|
||||||
undef $db_obj; # removing the last reference to the DB
|
|
||||||
# closes it. Closing DB_FH is implicit.
|
|
||||||
untie %db_hash;
|
|
||||||
|
|
||||||
|
|
||||||
$openproxy = isopenproxy($ENV{'REMOTE_ADDR'}, $blackhole, $openproxyip);
|
|
||||||
if (defined $openproxy) {
|
|
||||||
if ($openproxy) {
|
|
||||||
&prerror("$ENV{'REMOTE_ADDR'} is an open proxy server");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$blackhole_err++;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Build the PR.
|
|
||||||
$pr = "To: $submission_address\n" .
|
|
||||||
"From: " . param('originator') . " <" . param('email') . ">\n" .
|
|
||||||
"Subject: " . param('synopsis') . "\n" .
|
|
||||||
env2hdr(@ENV_captures);
|
|
||||||
if ($blackhole_err) {
|
|
||||||
$pr .= "X-REMOTE_ADDR-Is-Open-Proxy: Maybe\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$pr .= "X-Send-Pr-Version: www-3.1\n" .
|
|
||||||
"X-GNATS-Notify: \n\n" .
|
|
||||||
">Submitter-Id:\t" . param('submitterid') . "\n" .
|
|
||||||
">Originator:\t" . param('originator') . "\n" .
|
|
||||||
">Organization:\t" . param('organization') . "\n" .
|
|
||||||
">Confidential:\t" . param('confidential') . "\n" .
|
|
||||||
">Synopsis:\t" . param('synopsis') . "\n" .
|
|
||||||
">Severity:\t" . param('severity') . "\n" .
|
|
||||||
">Priority:\t" . param('priority') . "\n" .
|
|
||||||
">Category:\t" . param('category') . "\n" .
|
|
||||||
">Class:\t\t" . param('class') . "\n" .
|
|
||||||
">Release:\t" . param('release') . "\n" .
|
|
||||||
">Environment:\t" . param('environment') . "\n" .
|
|
||||||
">Description:\n" . param('description') . "\n" .
|
|
||||||
">How-To-Repeat:\n" . param('howtorepeat') . "\n" .
|
|
||||||
">Fix:\n" . param('fix') . "\n";
|
|
||||||
|
|
||||||
if (length($patchbuf) > 0) {
|
|
||||||
$pr .= "\nPatch attached with submission follows:\n\n"
|
|
||||||
. $patchbuf . "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
# remove any carriage returns that appear in the report.
|
|
||||||
$pr =~ s/\r//g;
|
|
||||||
|
|
||||||
if (open (SUBMIT, "|$submission_program")){
|
|
||||||
|
|
||||||
print SUBMIT $pr;
|
|
||||||
print SUBMIT "\n.\n";
|
|
||||||
close (SUBMIT);
|
|
||||||
print start_html("Thank you for the problem report");
|
|
||||||
print "<h1>Thank You</h1>",
|
|
||||||
"<p>Thank you for the problem report. You should receive confirmation",
|
|
||||||
" of your report by electronic mail within a day.</p>";
|
|
||||||
} else {
|
|
||||||
print start_html("Error raising problem report");
|
|
||||||
print "<h1>Error</h1><p>An error occured processing your problem report.</p>";
|
|
||||||
}
|
|
||||||
print end_html();
|
|
||||||
|
|
@ -26,7 +26,7 @@ pre a:visited { color: #220000; }
|
||||||
#
|
#
|
||||||
# Files MUST be fully qualified and MUST start with this path.
|
# Files MUST be fully qualified and MUST start with this path.
|
||||||
#
|
#
|
||||||
$messagepath = "/usr/local/www/db/text/";
|
$messagepath = "/usr/local/www/mailindex/archive/";
|
||||||
$messagepathcurrent = "/usr/local/www/mid/archive/";
|
$messagepathcurrent = "/usr/local/www/mid/archive/";
|
||||||
$ftparchive = 'ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/mailing-lists/archive';
|
$ftparchive = 'ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/mailing-lists/archive';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,10 +42,10 @@ my $up = 0;
|
||||||
$| = 1;
|
$| = 1;
|
||||||
|
|
||||||
# mail archive location
|
# mail archive location
|
||||||
$maildir = '/g/mail/archive';
|
$maildir = '/home/mail/archive';
|
||||||
|
|
||||||
# mailindex program
|
# mailindex program
|
||||||
$mailindex = '/usr/local/www/mid/bin/mailindex';
|
$mailindex = '/usr/local/www/mailindex/bin/mailindex';
|
||||||
|
|
||||||
|
|
||||||
$query = new CGI();
|
$query = new CGI();
|
||||||
|
|
@ -82,7 +82,7 @@ sub file_not_exists {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($file =~ s%^archive/%%) {
|
if ($file =~ s%^archive/%%) {
|
||||||
$maildir = '/g/www/db/text';
|
$maildir = '/usr/local/www/mailindex/archive';
|
||||||
&file_not_exists("$maildir/$file") if (! -f "$maildir/$file");
|
&file_not_exists("$maildir/$file") if (! -f "$maildir/$file");
|
||||||
} elsif ($file =~ s%^current/%% && $file =~ /^freebsd-|^cvs-/) {
|
} elsif ($file =~ s%^current/%% && $file =~ /^freebsd-|^cvs-/) {
|
||||||
&file_not_exists("$file") if (! -f "$maildir/$file");
|
&file_not_exists("$file") if (! -f "$maildir/$file");
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,9 @@ require "./cgi-lib.pl";
|
||||||
require "./cgi-style.pl";
|
require "./cgi-style.pl";
|
||||||
|
|
||||||
$home = '/usr/local/www/mailindex';
|
$home = '/usr/local/www/mailindex';
|
||||||
$prefix= "/usr/local/www/db/text";
|
$prefix= "/usr/local/www/mailindex/archive";
|
||||||
$lookupdir = "$home/message-id"; # database(s) directory
|
$lookupdir = "$home/message-id"; # database(s) directory
|
||||||
$databaseDefault = 'mid'; # default database
|
$databaseDefault = 'mid'; # default database
|
||||||
$bindir = "$home/bin"; # where search scripts located
|
|
||||||
$script = $ENV{'SCRIPT_NAME'};
|
$script = $ENV{'SCRIPT_NAME'};
|
||||||
$shortid = 1;
|
$shortid = 1;
|
||||||
$lookCommand = "/usr/bin/look";
|
$lookCommand = "/usr/bin/look";
|
||||||
|
|
@ -90,7 +89,7 @@ sub get_id {
|
||||||
local($id, $file, $start) = split($", $idlist[0]);
|
local($id, $file, $start) = split($", $idlist[0]);
|
||||||
$location =~ s%/[^/]+$%%;
|
$location =~ s%/[^/]+$%%;
|
||||||
local($host) = $ENV{'HTTP_HOST'};
|
local($host) = $ENV{'HTTP_HOST'};
|
||||||
$location = 'http://' . $host . $location;
|
$location = '//' . $host . $location;
|
||||||
$start =~ s/\s+$//;
|
$start =~ s/\s+$//;
|
||||||
|
|
||||||
print "Location: $location/getmsg.cgi?fetch=$start+0+" .
|
print "Location: $location/getmsg.cgi?fetch=$start+0+" .
|
||||||
|
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
#!/usr/bin/perl -T
|
|
||||||
# Copyright (c) July 1997-2011. Wolfram Schneider <wosch@FreeBSD.org>
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# missing_handler.cgi - User friendly error response (Apache style)
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# default apache message:
|
|
||||||
# ----------------------------------------------------------------------
|
|
||||||
# File Not found
|
|
||||||
# The requested URL /~wosch/test/bla was not found on this server.
|
|
||||||
# ----------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# missing_handler.cgi message:
|
|
||||||
# ----------------------------------------------------------------------
|
|
||||||
# FreeBSD.org - Document not found
|
|
||||||
#
|
|
||||||
# The file
|
|
||||||
#
|
|
||||||
# http://www.FreeBSD.org/~wosch/test/bla
|
|
||||||
#
|
|
||||||
# does not exist at this server. You are coming from
|
|
||||||
#
|
|
||||||
# http://www.FreeBSD.org/~wosch/test/error.html.
|
|
||||||
#
|
|
||||||
# The closest match to your request is http://www.FreeBSD.org.
|
|
||||||
# Please contact the server administrator wosch@FreeBSD.org.
|
|
||||||
#
|
|
||||||
# Thank you very much!
|
|
||||||
#
|
|
||||||
# _________________________________________________________________
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
# ----------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub escape($) { $_ = $_[0]; s/&/&/g; s/</</g; s/>/>/g; $_; }
|
|
||||||
sub escape2($) { $_ = $_[0]; s/</</g; s/>/>/g; $_; }
|
|
||||||
|
|
||||||
# output title
|
|
||||||
$title = $ENV{'MISSING_HANDLER_TITLE'} ||
|
|
||||||
'FreeBSD.org - Document not found';
|
|
||||||
|
|
||||||
# footer message
|
|
||||||
$footer = $ENV{'MISSING_HANDLER_FOOT'} || '';
|
|
||||||
|
|
||||||
|
|
||||||
# Server environment variables
|
|
||||||
$http_referer=escape($ENV{'HTTP_REFERER'});
|
|
||||||
$redirect_url=escape($ENV{'REDIRECT_URL'});
|
|
||||||
$server_admin=escape($ENV{'SERVER_ADMIN'});
|
|
||||||
$http_host=escape($ENV{'HTTP_HOST'});
|
|
||||||
$server_name=escape($ENV{'SERVER_NAME'});
|
|
||||||
|
|
||||||
# rfc1738 says that ";"|"/"|"?"|":"|"@"|"&"|"=" may be reserved.
|
|
||||||
$http_referer_url = escape2($ENV{'HTTP_REFERER'});
|
|
||||||
$http_referer_url =~ s/([^a-zA-Z0-9;\/?:&=\.%])/sprintf("%%%02x",ord($1))/eg;
|
|
||||||
$redirect_url_save = escape2($ENV{'REDIRECT_URL'});
|
|
||||||
$redirect_url_save =~ s/([^a-zA-Z0-9;\/?:&=])/sprintf("%%%02x",ord($1))/eg;
|
|
||||||
|
|
||||||
|
|
||||||
$hsty_base = 'http://www.FreeBSD.org';
|
|
||||||
require './cgi-style.pl';
|
|
||||||
print &html_header($title);
|
|
||||||
|
|
||||||
# HTML body
|
|
||||||
print qq[<p>The file</p>
|
|
||||||
<blockquote><b>
|
|
||||||
http://$http_host$redirect_url
|
|
||||||
</b></blockquote>
|
|
||||||
<p>does not exist at this server.</p>\n];
|
|
||||||
|
|
||||||
if ($http_referer) {
|
|
||||||
print qq{<p>You are coming from</p>
|
|
||||||
<blockquote>
|
|
||||||
<a href="$http_referer_url">$http_referer</a>.
|
|
||||||
</blockquote>
|
|
||||||
\n};
|
|
||||||
}
|
|
||||||
|
|
||||||
print qq[<p>
|
|
||||||
The closest match to your request is
|
|
||||||
<a href="http://$server_name">http://$server_name</a>.
|
|
||||||
|
|
||||||
Please contact the members of the
|
|
||||||
FreeBSD Documentation Project <<a href="mailto:freebsd-doc\@FreeBSD.org?subject=Document%20not%20found%20-%20http://$http_host$redirect_url_save&body=$http_referer_url">freebsd-doc\@FreeBSD.org</a>>
|
|
||||||
or the server administrator
|
|
||||||
<a href="mailto:$server_admin?subject=Document%20not%20found%20-%20http://$http_host$redirect_url_save&body=$http_referer_url">$server_admin</a>.</p>
|
|
||||||
|
|
||||||
<p>Please try our
|
|
||||||
<a href="http://www.FreeBSD.org/search/index-site.html">Site Map</a> or
|
|
||||||
<a href="http://www.FreeBSD.org/search/search.html">Search Page</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>Thank you very much!</p>
|
|
||||||
];
|
|
||||||
|
|
||||||
print&html_footer;
|
|
||||||
exit;
|
|
||||||
|
|
@ -458,10 +458,10 @@ Search for:
|
||||||
%d = (
|
%d = (
|
||||||
'name', 'Package Name', 'all', 'All',
|
'name', 'Package Name', 'all', 'All',
|
||||||
'maintainer', 'Maintainer', 'text', 'Description',
|
'maintainer', 'Maintainer', 'text', 'Description',
|
||||||
'pkgdescr', 'Long Description', 'requires', 'Requires',
|
'requires', 'Requires',
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach ( 'all', 'name', 'text', 'pkgdescr', 'maintainer', 'requires' ) {
|
foreach ( 'all', 'name', 'text', 'maintainer', 'requires' ) {
|
||||||
print "<option"
|
print "<option"
|
||||||
. ( ( $_ eq $stype ) ? ' selected="selected" ' : ' ' )
|
. ( ( $_ eq $stype ) ? ' selected="selected" ' : ' ' )
|
||||||
. qq{value="$_">}
|
. qq{value="$_">}
|
||||||
|
|
@ -588,15 +588,6 @@ if ( $path_info eq "/source" ) {
|
||||||
&exit;
|
&exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Full text search in ports/<category>/port>/pkg-descr
|
|
||||||
if ( $stype eq 'pkgdescr' ) {
|
|
||||||
local ($url) =
|
|
||||||
'http://www.FreeBSD.org/cgi/search.cgi?source=pkgdescr&max=25';
|
|
||||||
$query =~ s/\s+/+/g;
|
|
||||||
print "Location: $url&words=$query\n\n";
|
|
||||||
&exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $stype eq "faq" ) {
|
if ( $stype eq "faq" ) {
|
||||||
print &short_html_header( "FreeBSD Ports Search FAQ", 1 );
|
print &short_html_header( "FreeBSD Ports Search FAQ", 1 );
|
||||||
&faq;
|
&faq;
|
||||||
|
|
|
||||||
|
|
@ -1,167 +0,0 @@
|
||||||
#!/usr/bin/perl -Tw
|
|
||||||
# $FreeBSD$
|
|
||||||
|
|
||||||
sub get_categories {
|
|
||||||
@categories = ();
|
|
||||||
|
|
||||||
open(Q, 'query-pr.web --list-categories 2>/dev/null |') ||
|
|
||||||
die "Cannot get categories\n";
|
|
||||||
|
|
||||||
while(<Q>) {
|
|
||||||
chop;
|
|
||||||
local ($cat, $desc, $responsible, $notify) = split(/:/);
|
|
||||||
push(@categories, $cat);
|
|
||||||
$catdesc{$cat} = $desc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_states {
|
|
||||||
@states = ();
|
|
||||||
|
|
||||||
open(Q, 'query-pr.web --list-states 2>/dev/null |') ||
|
|
||||||
die "Cannot get states\n";
|
|
||||||
|
|
||||||
while(<Q>) {
|
|
||||||
chop;
|
|
||||||
local ($state, $type, $desc) = split(/:/);
|
|
||||||
push(@states, $state);
|
|
||||||
$statedesc{$state} = $desc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_classes {
|
|
||||||
@classes = ();
|
|
||||||
|
|
||||||
open(Q, 'query-pr.web --list-classes 2>/dev/null |') ||
|
|
||||||
die "Cannot get classes\n";
|
|
||||||
|
|
||||||
while(<Q>) {
|
|
||||||
chop;
|
|
||||||
local ($class, $type, $desc) = split(/:/);
|
|
||||||
push(@classes, $class);
|
|
||||||
$classdesc{$class} = $desc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub displayform {
|
|
||||||
print qq`
|
|
||||||
<p>To query the GNATS Database for specific PR number, please fill in
|
|
||||||
this form:</p>
|
|
||||||
<form action='./query-pr.cgi' method='get'>
|
|
||||||
<table cellspacing='0' cellpadding='3' class='headtable'>
|
|
||||||
<tr><td width='130'><b>PR number:</b></td><td><input type='text'
|
|
||||||
name='pr' maxlength='30' /></td></tr>
|
|
||||||
<tr><td width='130'><b>Category:</b></td><td><input type='text'
|
|
||||||
name='cat' maxlength='30' /> (optional)</td></tr>
|
|
||||||
<tr><td colspan='2'><input type='submit' value='Submit' />
|
|
||||||
<input type='reset' value='Reset Form' /></td></tr>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<p>Alternatively, it is possible to select items you wish to search for.
|
|
||||||
Multiple items are AND'ed together.<br />
|
|
||||||
To generate current list of all open PRs in GNATS database, just press
|
|
||||||
the "Query PRs" button.
|
|
||||||
</p>
|
|
||||||
<form method='get' action='./query-pr-summary.cgi'>
|
|
||||||
|
|
||||||
<table cellspacing="0" cellpadding="3" class="headtable">
|
|
||||||
<tr>
|
|
||||||
<td><b>Category</b>:</td>
|
|
||||||
<td><select name='category'>
|
|
||||||
<option selected='selected' value=''>Any</option>`;
|
|
||||||
|
|
||||||
&get_categories;
|
|
||||||
foreach (sort @categories) {
|
|
||||||
#print "<option value='$_'>$_ ($catdesc{$_})</option>\n";
|
|
||||||
print "<option>$_</option>\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
print qq`
|
|
||||||
</select></td>
|
|
||||||
<td><b>Severity</b>:</td>
|
|
||||||
<td><select name='severity'>
|
|
||||||
<option selected='selected' value=''>Any</option>
|
|
||||||
<option>non-critical</option>
|
|
||||||
<option>serious</option>
|
|
||||||
<option>critical</option>
|
|
||||||
</select></td>
|
|
||||||
</tr><tr>
|
|
||||||
<td><b>Priority</b>:</td>
|
|
||||||
<td><select name='priority'>
|
|
||||||
<option selected='selected' value=''>Any</option>
|
|
||||||
<option>low</option>
|
|
||||||
<option>medium</option>
|
|
||||||
<option>high</option>
|
|
||||||
</select></td>
|
|
||||||
<td><b>Class</b>:</td>
|
|
||||||
<td><select name='class'>
|
|
||||||
<option selected='selected' value=''>Any</option>
|
|
||||||
`;
|
|
||||||
|
|
||||||
&get_classes;
|
|
||||||
foreach (@classes) {
|
|
||||||
#print "<option value='$_'>$_ ($classdesc{$_})</option>\n";
|
|
||||||
print "<option>$_</option>\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
print qq`</select></td>
|
|
||||||
</tr><tr>
|
|
||||||
<td><b>State</b>:</td>
|
|
||||||
<td><select name='state'>
|
|
||||||
<option selected='selected' value=''>Any</option>
|
|
||||||
`;
|
|
||||||
|
|
||||||
&get_states;
|
|
||||||
foreach (@states) {
|
|
||||||
($us = $_) =~ s/^./\U$&/;
|
|
||||||
print "<option value='$_'>";
|
|
||||||
#print "$us ($statedesc{$_})</option>\n";
|
|
||||||
print "$us</option>\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
print qq`</select></td>
|
|
||||||
<td><b>Sort by</b>:</td>
|
|
||||||
<td><select name='sort'>
|
|
||||||
<option value='none'>No Sort</option>
|
|
||||||
<option value='lastmod'>Last-Modified</option>
|
|
||||||
<option value='category'>Category</option>
|
|
||||||
<option value='responsible'>Responsible Party</option>
|
|
||||||
</select></td>
|
|
||||||
</tr><tr>
|
|
||||||
<!-- We don't use submitter Submitter: -->
|
|
||||||
<td><b>Text in single-line fields</b>:</td>
|
|
||||||
<td><input type='text' name='text' /></td>
|
|
||||||
<td><b>Responsible</b>:</td>
|
|
||||||
<td><input type='text' name='responsible' /></td>
|
|
||||||
</tr><tr>
|
|
||||||
<td><b>Text in multi-line fields</b>:</td>
|
|
||||||
<td><input type='text' name='multitext' /></td>
|
|
||||||
<td><b>Originator</b>:</td>
|
|
||||||
<td><input type='text' name='originator' /></td>
|
|
||||||
</tr><tr>
|
|
||||||
<td><b>Closed reports too</b>:</td>
|
|
||||||
<td><input name='closedtoo' value='on' type='checkbox' /></td>
|
|
||||||
<td><b>Release</b>:</td>
|
|
||||||
<td><select name='release'>
|
|
||||||
<option selected='selected' value=''>Any</option>
|
|
||||||
<option value='^FreeBSD [2345678]'>Pre-8.X</option>
|
|
||||||
<option value='^FreeBSD 10'>10.X only</option>
|
|
||||||
<option value='^FreeBSD 9'>9.X only</option>
|
|
||||||
<option value='^FreeBSD 8'>8.X only</option>
|
|
||||||
<option value='^FreeBSD 7'>7.X only</option>
|
|
||||||
<option value='^FreeBSD 6'>6.X only</option>
|
|
||||||
<option value='^FreeBSD 5'>5.X only</option>
|
|
||||||
<option value='^FreeBSD 4'>4.X only</option>
|
|
||||||
<option value='^FreeBSD 3'>3.X only</option>
|
|
||||||
<option value='^FreeBSD 2'>2.X only</option>
|
|
||||||
</select></td>
|
|
||||||
</tr>
|
|
||||||
<tr><td colspan="2"><input type='submit' value='Query PRs' />
|
|
||||||
<input type='reset' value='Reset Form' /></td></tr>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
||||||
|
|
@ -1,473 +0,0 @@
|
||||||
#!/usr/bin/perl -T
|
|
||||||
# $FreeBSD$
|
|
||||||
|
|
||||||
$html_mode = 1 if $ENV{'DOCUMENT_ROOT'};
|
|
||||||
$self_ref = $ENV{'SCRIPT_NAME'};
|
|
||||||
($query_pr_ref = $self_ref) =~ s/-summary//;
|
|
||||||
|
|
||||||
$ENV{'PATH'} = '/bin:/usr/bin:/usr/sbin:/sbin:/usr/local/bin';
|
|
||||||
|
|
||||||
$project = 'FreeBSD';
|
|
||||||
$mail_prefix = 'freebsd-';
|
|
||||||
$mail_unass = 'freebsd-bugs';
|
|
||||||
$ports_unass = 'ports-bugs';
|
|
||||||
$closed_too = 0;
|
|
||||||
|
|
||||||
require './cgi-lib.pl';
|
|
||||||
require './cgi-style.pl';
|
|
||||||
require './query-pr-lib.pl';
|
|
||||||
|
|
||||||
if (!$ENV{'QUERY_STRING'} or $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);
|
|
||||||
} else {
|
|
||||||
&Getopts('CcqRr:s:T:');
|
|
||||||
|
|
||||||
$input{'responsible'} = 'summary' if $opt_R;
|
|
||||||
if ($opt_r) {
|
|
||||||
($input{'responsible'}) = ($opt_r =~ m/^(\^?[-_a-zA-Z0-9@.]*\$?)$/);
|
|
||||||
die 'Insecure args' if ($input{'responsible'} ne $opt_r)
|
|
||||||
}
|
|
||||||
if ($opt_s) {
|
|
||||||
($input{'state'}) = ($opt_s =~ m/^([a-zA-Z]*)$/);
|
|
||||||
die 'Insecure args' if ($input{'state'} ne $opt_s)
|
|
||||||
}
|
|
||||||
$input{'quiet'} = 'yes' if $opt_q;
|
|
||||||
if ($opt_C) {
|
|
||||||
$query_args = '--confidential=yes ';
|
|
||||||
} elsif (!$opt_c) {
|
|
||||||
$query_args = '--restricted ';
|
|
||||||
}
|
|
||||||
if ($opt_T) {
|
|
||||||
($tag) = ($opt_T =~ m/^(\^?[-_a-zA-Z0-9@.]*\$?)$/);
|
|
||||||
die 'Insecure args' if ($tag ne $opt_T);
|
|
||||||
$input{'text'} = '\[' . $tag . '\]';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$closed_too = 1 if $input{'state'} eq 'closed' ||
|
|
||||||
($input{'closedtoo'} && ($input{'multitext'} || $input{'text'} || $input{'responsible'} || $input{'originator'}));
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
|
||||||
|
|
||||||
%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) {
|
|
||||||
|
|
||||||
$pr = '<pre>'; $pr_e = '</pre>';
|
|
||||||
$h1 = '<h1>'; $h1_e = '</h1>';
|
|
||||||
$h3 = '<h3>'; $h3_e = '</h3>';
|
|
||||||
$hr = '<hr/>';
|
|
||||||
|
|
||||||
$table = "<table width='100%' border='0' cellspacing='1' cellpadding='0'>";
|
|
||||||
$table_e = '</table>';
|
|
||||||
|
|
||||||
# Customizations for the look and feel of the summary tables.
|
|
||||||
$t_style = "<style type='text/css'><!--\n" .
|
|
||||||
"table { background-color: #ccc; color: #000; }\n" .
|
|
||||||
"tr { padding: 0; }\n" .
|
|
||||||
"th { background-color: #cbd2ec; color: #000; padding: 2px;\n" .
|
|
||||||
" text-align: left; font-weight: normal; font-style: italic; }\n" .
|
|
||||||
"td { color: #000; padding: 2px; }\n" .
|
|
||||||
"td a { text-decoration: none; }\n" .
|
|
||||||
".o { background-color: #fff; }\n" .
|
|
||||||
".a { background-color: #cffafd; }\n" .
|
|
||||||
".f { background-color: #ffc; }\n" .
|
|
||||||
".p { background-color: #d1fbd6; }\n" .
|
|
||||||
".s { background-color: #fcccd9; }\n" .
|
|
||||||
".c { background-color: #c1d5db; }\n" .
|
|
||||||
"--></style>";
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
$pr = ''; $pr_e = '';
|
|
||||||
$h1 = ''; $h1_e = '';
|
|
||||||
$h3 = ''; $h3_e = '';
|
|
||||||
$hr = "\n----------------------------------------" .
|
|
||||||
"---------------------------------------\n";
|
|
||||||
|
|
||||||
$table = '';
|
|
||||||
$table_e = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
sub cgiparam {
|
|
||||||
local ($result) = @_;
|
|
||||||
|
|
||||||
$result =~ s/[^A-Za-z0-9+.@-]/"%".sprintf("%02X", unpack("C", $&))/ge;
|
|
||||||
$result;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub header_info {
|
|
||||||
if ($html_mode) {
|
|
||||||
print &html_header("Current $project problem reports");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print "Current $project problem reports\n";
|
|
||||||
}
|
|
||||||
if (!$input{'quiet'}) {
|
|
||||||
print "The following is an old and incomplete of current problems submitted by $project users. ";
|
|
||||||
if ($html_mode) {
|
|
||||||
print <<EOM;
|
|
||||||
<h1>FreeBSD has migrated to <a href="https://bugs.FreeBSD.org/search/">Bugzilla</a>. Please update your bookmarks and try your search there.</h1>
|
|
||||||
EOM
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($html_mode) {
|
|
||||||
|
|
||||||
# These self references are attempts to only change a single variable at a time.
|
|
||||||
# If someone does a multiple-variable query they will probably do weird things.
|
|
||||||
|
|
||||||
$self_ref1 = $self_ref . '?';
|
|
||||||
$self_ref1 .= 'sort=' . html_fixline($input{'sort'}) if $input{'sort'};
|
|
||||||
print "<p>You may view summaries by <a href='$self_ref1'>Severity</a>, ";
|
|
||||||
$self_ref1 .= '&' if ($self_ref1 !~/\?$/);
|
|
||||||
print "<a href='${self_ref1}state=summary'>State</a>, ";
|
|
||||||
print "<a href='${self_ref1}category=summary'>Category</a>, or ";
|
|
||||||
print "<a href='${self_ref1}responsible=summary'>Responsible Party</a>.\n";
|
|
||||||
|
|
||||||
$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 .= $_ . '=' . cgiparam($input{$_});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
print 'You may also sort by ';
|
|
||||||
print "<a href='$self_ref2&sort=lastmod'>Last-Modified</a>, ";
|
|
||||||
print "<a href='$self_ref2&sort=category'>Category</a>, or ";
|
|
||||||
print "<a href='$self_ref2&sort=responsible'>Responsible Party</a>.\n";
|
|
||||||
print "Or <a href='$self_ref?query'>formulate a specific query</a>.\n";
|
|
||||||
|
|
||||||
$self_ref3 = $self_ref . '?';
|
|
||||||
foreach ('category', 'originator', 'priority', 'class', 'responsible',
|
|
||||||
'severity', 'state', 'submitter', 'text', 'multitext', 'sort') {
|
|
||||||
if ($input{$_}) {
|
|
||||||
$self_ref3 .= '&' if ($self_ref2 !~/\?$/);
|
|
||||||
$self_ref3 .= $_ . '=' . cgiparam($input{$_});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($input{'closedtoo'}) {
|
|
||||||
print "<a href='$self_ref3'>Do not show closed reports</a>.";
|
|
||||||
} else {
|
|
||||||
print "<a href='$self_ref3&closedtoo=on'>Include closed reports too</a>.";
|
|
||||||
}
|
|
||||||
|
|
||||||
print "</p>\n";
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&header_info;
|
|
||||||
|
|
||||||
#Usage: query-pr [-FGhiPRqVx] [-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]
|
|
||||||
# [-b date] [-a date] [-B date] [-M date] [-z date] [-Z date]
|
|
||||||
# [-y synopsis] [-A release] [--full] [--help] [--print-path] [--version]
|
|
||||||
# [--summary] [--sql] [--skip-closed] [--category=category]
|
|
||||||
# [--confidential=yes|no] [--directory=directory] [--output=outfile]
|
|
||||||
# [--originator=name] [--priority=level] [--class=class]
|
|
||||||
# [--responsible=person] [--release=release] [--restricted]
|
|
||||||
# [--quarter=quarter] [--keywords=regexp]
|
|
||||||
# [--required-before=date] [--required-after=date]
|
|
||||||
# [--arrived-before=date] [--arrived-after=date]
|
|
||||||
# [--modified-before=date] [--modified-after=date]
|
|
||||||
# [--closed-before=date] [--closed-after=date]
|
|
||||||
# [--severity=severity] [--state=state] [--submitter=submitter]
|
|
||||||
# [--list-categories] [--list-classes] [--list-responsible]
|
|
||||||
# [--list-states] [--list-submitters] [--list-config]
|
|
||||||
# [--synopsis=synopsis] [--text=text] [--multitext=mtext] [PR] [PR]...
|
|
||||||
|
|
||||||
$query_args .= ' --skip-closed' unless $closed_too;
|
|
||||||
|
|
||||||
# Only read the appropriate PR's.
|
|
||||||
foreach ('category', 'originator', 'priority', 'class', 'responsible',
|
|
||||||
'release', 'severity', 'state', 'submitter', 'text', 'multitext') {
|
|
||||||
if ($input{$_} && $input{$_} ne 'summary') {
|
|
||||||
# Check if the arguments provided by user are secure.
|
|
||||||
# This is required to be able to run this script in
|
|
||||||
# taint mode (perl -T)
|
|
||||||
if ($input{$_} =~ /^([-^'\/\[\]\@\s\w.]+)$/) {
|
|
||||||
$d = $1;
|
|
||||||
$d =~ s/^"(.*)"$/$&/;
|
|
||||||
$d =~ s/'/\\'/;
|
|
||||||
$query_args .= " --${_}='$d'";
|
|
||||||
} else {
|
|
||||||
print "Insecure data in ${_}! Ignoring this filter.<br />".
|
|
||||||
"Only alphanumeric characters and ', /, -, [, ], ^, @ are allowed.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&read_gnats($query_args);
|
|
||||||
|
|
||||||
if ($input{'sort'} eq 'lastmod') {
|
|
||||||
@prs = sort {$lastmod{$b} cmp $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}Please try <a href='https://bugs.FreeBSD.org/search/'>bugzilla</a> for an up to date search mechanism.${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));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
print &html_footer if $html_mode;
|
|
||||||
|
|
||||||
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_summary {
|
|
||||||
&get_categories;
|
|
||||||
foreach (keys %status) {
|
|
||||||
s|/\d+||;
|
|
||||||
$cat{$_}++;
|
|
||||||
}
|
|
||||||
foreach (@categories) {
|
|
||||||
next unless $cat{$_}; # skip categories with no bugs.
|
|
||||||
print "${h3}Problems in category: $_ ($catdesc{$_})${h3_e}\n";
|
|
||||||
if (/^(\w+)/) {
|
|
||||||
&printcnt(&gnats_summary("\$cat eq \"$1\"", $html_mode));
|
|
||||||
} else {
|
|
||||||
print "\n??? weird category $_\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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_summary {
|
|
||||||
&get_states;
|
|
||||||
foreach (@states) {
|
|
||||||
next if ($_ eq "closed" && !$input{"closedtoo"});
|
|
||||||
print "${h3}Problems in state: $_${h3_e}\n";
|
|
||||||
if (/^(\w)/) {
|
|
||||||
&printcnt(&gnats_summary("\$state eq \"$1\" ", $html_mode));
|
|
||||||
} else {
|
|
||||||
print "\n??? bad state $state\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub severity_summary {
|
|
||||||
print "${h3}Critical problems${h3_e}\n";
|
|
||||||
&printcnt(&gnats_summary('$severity eq "critical"', $html_mode));
|
|
||||||
|
|
||||||
print "${h3}Serious problems${h3_e}\n";
|
|
||||||
&printcnt(&gnats_summary('$severity eq "serious"', $html_mode));
|
|
||||||
|
|
||||||
print "${h3}Non-critical problems${h3_e}\n";
|
|
||||||
&printcnt(&gnats_summary('$severity eq "non-critical"', $html_mode));
|
|
||||||
}
|
|
||||||
|
|
||||||
sub read_gnats {
|
|
||||||
local($report) = @_[0];
|
|
||||||
|
|
||||||
open(Q, "query-pr.web $report 2>/dev/null |") || die "Cannot query the PR's\n";
|
|
||||||
|
|
||||||
while(<Q>) {
|
|
||||||
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/o) or ($resp =~ /$ports_unass/o));
|
|
||||||
$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;
|
|
||||||
|
|
||||||
foreach (@prs) {
|
|
||||||
$state = $status{$_};
|
|
||||||
$date = $date{$_};
|
|
||||||
$resp = $resp{$_};
|
|
||||||
$syn = $syn{$_};
|
|
||||||
$severity = $sev{$_};
|
|
||||||
($cat, $number) = m|^([^/]+)/(\d+)$|;
|
|
||||||
|
|
||||||
next if (($report ne '') && (eval($report) == 0));
|
|
||||||
|
|
||||||
if ($htmlmode) {
|
|
||||||
$title = "<a href='$query_pr_ref?pr=$cat/$number'>$_</a>";
|
|
||||||
$syn = &html_fixline($syn);
|
|
||||||
gnats_summary_line_html($counter, $state, $date, $title, $resp, $syn);
|
|
||||||
} else {
|
|
||||||
$title = $_;
|
|
||||||
gnats_summary_line_text($counter, $state, $date, $title, $resp, $syn);
|
|
||||||
}
|
|
||||||
|
|
||||||
$counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($htmlmode) {
|
|
||||||
print "${table_e}\n" if $counter;
|
|
||||||
} else {
|
|
||||||
print "${pr_e}\n" if $counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
$counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub gnats_summary_line_html {
|
|
||||||
local($counter) = shift;
|
|
||||||
local($state) = shift;
|
|
||||||
local($date) = shift;
|
|
||||||
local($title) = shift;
|
|
||||||
local($resp) = shift;
|
|
||||||
local($syn) = shift;
|
|
||||||
|
|
||||||
if ($counter == 0) {
|
|
||||||
print "$table<tr><th>S</th><th>Submitted</th><th>Tracker</th><th>Resp.</th><th>Description</th></tr>\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
print "<tr class='$state'><td>$state</td><td>$date</td><td>$title</td><td>$resp</td><td>$syn</td></tr>\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub gnats_summary_line_text {
|
|
||||||
local($counter) = shift;
|
|
||||||
local($state) = shift;
|
|
||||||
local($date) = shift;
|
|
||||||
local($title) = shift;
|
|
||||||
local($resp) = shift;
|
|
||||||
local($syn) = shift;
|
|
||||||
|
|
||||||
# Print the banner line if this is the first iteration.
|
|
||||||
print "${pr}\nS Submitted Tracker Resp. Description${hr}"
|
|
||||||
if ($counter == 0);
|
|
||||||
print "$state $date $title" .
|
|
||||||
(' ' x (17 - length($_))) .
|
|
||||||
$resp . (' ' x (10 - length($resp))) .
|
|
||||||
substr($syn,0,39) . "\n";
|
|
||||||
}
|
|
||||||
|
|
@ -1,858 +0,0 @@
|
||||||
#!/usr/bin/perl -Tw
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# GNATS query-pr Interface, Generation III
|
|
||||||
#
|
|
||||||
# Copyright (C) 2006-2011, Shaun Amott <shaun@FreeBSD.org>
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
#
|
|
||||||
# Useful PRs for testing:
|
|
||||||
#
|
|
||||||
# - ports/147261 - RFC 2047 words, attachments, interjected e-mail (inc.
|
|
||||||
# malformed header)
|
|
||||||
# - ports/138672 - Lots of attachments, multi-level MIME.
|
|
||||||
# - ports/132344 - Base64-encoded attachment.
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
BEGIN { push @INC, '.'; }
|
|
||||||
|
|
||||||
use CGI;
|
|
||||||
|
|
||||||
use GnatsPR;
|
|
||||||
use GnatsPR::SectionIterator;
|
|
||||||
use GnatsPR::MIMEIterator;
|
|
||||||
|
|
||||||
#use MIME::EncWords (decode_mimewords); # mail/p5-MIME-EncWords
|
|
||||||
sub decode_mimewords { wantarray ? @_ : join ' ', @_; } # Temp. substitute for the above
|
|
||||||
|
|
||||||
require './cgi-style.pl';
|
|
||||||
require './query-pr-lib.pl';
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Constants
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
use constant EXIT_NOPRS => 1;
|
|
||||||
use constant EXIT_DBBUSY => 2;
|
|
||||||
use constant EXIT_NOPATCH => 3;
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Globals
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
our $valid_category = '[a-z0-9][A-Za-z0-9-_]{1,25}';
|
|
||||||
our $valid_pr = '\d{1,8}';
|
|
||||||
|
|
||||||
our $stylesheet = "$main::hsty_base/layout/css/query-pr.css";
|
|
||||||
|
|
||||||
our $iscgi = defined $ENV{'SCRIPT_NAME'};
|
|
||||||
|
|
||||||
# Keep this ahead of CGI
|
|
||||||
|
|
||||||
if (!$iscgi && !exists $ENV{'REQUEST_METHOD'}) {
|
|
||||||
# Makes debugging easier
|
|
||||||
$ENV{'REQUEST_METHOD'} = 'GET';
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stuff from cgi-style.pl
|
|
||||||
|
|
||||||
$main::hsty_base ||= '';
|
|
||||||
$main::t_style ||= '';
|
|
||||||
$main::hsty_charset ||= '';
|
|
||||||
|
|
||||||
$main::hsty_charset = 'utf-8';
|
|
||||||
|
|
||||||
$main::t_style =
|
|
||||||
qq{<link href="$stylesheet" rel="stylesheet" type="text/css" />
|
|
||||||
<link rel="search" type="application/opensearchdescription+xml"
|
|
||||||
href="http://www.freebsd.org/search/opensearch/query-pr.xml"
|
|
||||||
title="FreeBSD Bugs" />
|
|
||||||
};
|
|
||||||
|
|
||||||
# Global CGI accessor
|
|
||||||
|
|
||||||
our $q = new CGI;
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Environment vars
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
$ENV{'PATH'} = '/bin:/usr/bin:/usr/sbin:/sbin:/usr/local/bin';
|
|
||||||
|
|
||||||
$ENV{'SCRIPT_NAME'} ||= $0;
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Begin Code
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
main();
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Main routine
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub main
|
|
||||||
{
|
|
||||||
my ($PR, $category, $rawdata, $gnatspr);
|
|
||||||
|
|
||||||
binmode STDOUT, ':utf8';
|
|
||||||
|
|
||||||
if ($q->param('pr')) {
|
|
||||||
$PR = $q->param('pr');
|
|
||||||
} elsif ($q->param('q')) {
|
|
||||||
$PR = $q->param('q');
|
|
||||||
} elsif ($q->param('prp')) {
|
|
||||||
# Legacy param format
|
|
||||||
my $prp = $q->param('prp');
|
|
||||||
|
|
||||||
if ($prp =~ /^(\d+)-(\d+)/) {
|
|
||||||
my $get = $2;
|
|
||||||
$PR = $1;
|
|
||||||
|
|
||||||
$q->param(-name => 'pr', -value => $PR);
|
|
||||||
$q->param(-name => 'getpatch', -value => $get);
|
|
||||||
} else {
|
|
||||||
ErrorExit();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ErrorExit(EXIT_NOPRS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($PR =~ /^($valid_category)\/($valid_pr)$/) {
|
|
||||||
$category = $1;
|
|
||||||
$PR = $2;
|
|
||||||
}
|
|
||||||
|
|
||||||
length $PR > 0
|
|
||||||
or ErrorExit();
|
|
||||||
|
|
||||||
# category may be undef
|
|
||||||
$rawdata = DoQueryPR($PR, $category);
|
|
||||||
|
|
||||||
# Dump the raw PR data if requested
|
|
||||||
if ($q->param('f') && $q->param('f') eq 'raw') {
|
|
||||||
print "Content-type: text/plain; charset=UTF-8\r\n\r\n";
|
|
||||||
print $$rawdata;
|
|
||||||
Exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
# Run PR text through the parser
|
|
||||||
$gnatspr = GnatsPR->new($rawdata);
|
|
||||||
|
|
||||||
# User is requesting a patch extraction?
|
|
||||||
if ($q->param('getpatch')) {
|
|
||||||
my ($patch, $patchnum);
|
|
||||||
|
|
||||||
$patchnum = $q->param('getpatch');
|
|
||||||
$patchnum =~ s/[^0-9]+//g;
|
|
||||||
|
|
||||||
$patch = $gnatspr->GetAttachment($patchnum);
|
|
||||||
|
|
||||||
defined $patch
|
|
||||||
or ErrorExit(EXIT_NOPATCH);
|
|
||||||
|
|
||||||
printf 'Content-type: %s; charset=UTF-8'."\r\n",
|
|
||||||
($patch->isbinary ? 'application/octet-stream' : 'text/plain');
|
|
||||||
|
|
||||||
printf 'Content-Length: %s'."\r\n"
|
|
||||||
. 'Content-Disposition: inline; filename="%s"'."\r\n\r\n",
|
|
||||||
$patch->size,
|
|
||||||
$patch->filename;
|
|
||||||
|
|
||||||
print $patch->data;
|
|
||||||
print "\n";
|
|
||||||
|
|
||||||
Exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
# Otherwise, output PR
|
|
||||||
|
|
||||||
PrintPR($gnatspr);
|
|
||||||
|
|
||||||
Exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: DoQueryPR()
|
|
||||||
# Desc: Invoke the query-pr binary and return the results as a blob of text.
|
|
||||||
# Exits gracefully on failure.
|
|
||||||
#
|
|
||||||
# Args: $PR - PR number
|
|
||||||
# $cat - PR category (optional)
|
|
||||||
#
|
|
||||||
# Retn: \$data - Ref. to raw data.
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub DoQueryPR
|
|
||||||
{
|
|
||||||
my ($PR, $cat) = @_;
|
|
||||||
my ($data);
|
|
||||||
|
|
||||||
$PR =~ s/[^0-9]+//g;
|
|
||||||
$PR = quotemeta $PR;
|
|
||||||
|
|
||||||
# Note: query-pr.web is just an anti DoS wrapper around query-pr which
|
|
||||||
# makes sure we do not run too many query-pr instances at once.
|
|
||||||
if (defined $cat) {
|
|
||||||
$cat =~ s/[^0-9A-Za-z-]+//g;
|
|
||||||
$cat = quotemeta $cat;
|
|
||||||
$data = qx(query-pr.web --full --category=${cat} ${PR} 2>&1);
|
|
||||||
} else {
|
|
||||||
$data = qx(query-pr.web --full ${PR} 2>&1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$data or $data =~ /^query-pr(:?\.(:?real|web))?: /) {
|
|
||||||
ErrorExit(EXIT_NOPRS);
|
|
||||||
} elsif ($data =~ /^lockf: /) {
|
|
||||||
ErrorExit(EXIT_DBBUSY);
|
|
||||||
}
|
|
||||||
|
|
||||||
return \$data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: PrintPR()
|
|
||||||
# Desc: Output the parsed PR.
|
|
||||||
#
|
|
||||||
# Args: $gnatspr - GnatsPR instance.
|
|
||||||
#
|
|
||||||
# Retn: n/a
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub PrintPR
|
|
||||||
{
|
|
||||||
my ($gnatspr) = @_;
|
|
||||||
|
|
||||||
# Page title
|
|
||||||
|
|
||||||
print html_header(
|
|
||||||
"FreeBSD has migrated to Bugzilla. Please check the current <a href='https://bugs.FreeBSD.org/"
|
|
||||||
. $gnatspr->FieldSingle('Number') . "'/>Bugzilla version</a> of this PR."
|
|
||||||
);
|
|
||||||
print "<h3>The historical version shown below is likely out of date and is for debugging purposes only!</h3>\n";
|
|
||||||
|
|
||||||
print "<h3>" .
|
|
||||||
$q->escapeHTML(
|
|
||||||
$gnatspr->FieldSingle('Category')
|
|
||||||
. '/'
|
|
||||||
. $gnatspr->FieldSingle('Number')
|
|
||||||
. ': '
|
|
||||||
. $gnatspr->FieldSingle('Synopsis')
|
|
||||||
) . "</h3>\n";
|
|
||||||
|
|
||||||
# Header stuff of interest
|
|
||||||
|
|
||||||
print $q->start_table({-class => 'headtable'});
|
|
||||||
|
|
||||||
foreach my $field ('From', 'Date', 'Subject') {
|
|
||||||
my $val = $q->escapeHTML(
|
|
||||||
scalar decode_mimewords($gnatspr->Header($field))
|
|
||||||
);
|
|
||||||
print $q->Tr(
|
|
||||||
$q->td({-class => 'key'}, $field . ':'),
|
|
||||||
$q->td({-class => 'val'}, $val)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
print $q->Tr(
|
|
||||||
$q->td({-class => 'key'}, 'Send-pr version:'),
|
|
||||||
$q->td({-class => 'val'}, $q->escapeHTML($gnatspr->Header('x-send-pr-version')))
|
|
||||||
);
|
|
||||||
|
|
||||||
print $q->end_table;
|
|
||||||
|
|
||||||
# Single fields
|
|
||||||
|
|
||||||
print $q->start_table({-class => 'headtable'});
|
|
||||||
|
|
||||||
foreach my $field (
|
|
||||||
'Number',
|
|
||||||
'Category',
|
|
||||||
'Synopsis',
|
|
||||||
'Severity',
|
|
||||||
'Priority',
|
|
||||||
'Responsible',
|
|
||||||
'State',
|
|
||||||
'Class',
|
|
||||||
'Arrival-Date',
|
|
||||||
'Closed-Date',
|
|
||||||
'Last-Modified',
|
|
||||||
'Originator',
|
|
||||||
'Release'
|
|
||||||
) {
|
|
||||||
my $val = $q->escapeHTML($gnatspr->FieldSingle($field));
|
|
||||||
print $q->Tr(
|
|
||||||
$q->td({-class => 'key'}, $field . ":"),
|
|
||||||
$q->td({-class => 'val'}, $val)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
print $q->end_table;
|
|
||||||
|
|
||||||
# Sections
|
|
||||||
|
|
||||||
my $iter = GnatsPR::SectionIterator->new(
|
|
||||||
$gnatspr,
|
|
||||||
# Fields we want sections from; this also
|
|
||||||
# dictates the order they will come.
|
|
||||||
'Organization',
|
|
||||||
'Environment',
|
|
||||||
'Description',
|
|
||||||
'How-To-Repeat',
|
|
||||||
'Fix',
|
|
||||||
'Release-Note',
|
|
||||||
'Audit-Trail',
|
|
||||||
'Unformatted'
|
|
||||||
);
|
|
||||||
|
|
||||||
my $replynum = 0;
|
|
||||||
my $patchnum = 0;
|
|
||||||
|
|
||||||
while (my $item = $iter->next()) {
|
|
||||||
# Start of new field
|
|
||||||
if (ref $item eq 'GnatsPR::Section::FieldStart') {
|
|
||||||
my $text = $item->string();
|
|
||||||
$text = $q->escapeHTML($text);
|
|
||||||
#print $q->h2($text);
|
|
||||||
print $q->table({-class => 'mfieldtable'},
|
|
||||||
$q->Tr($q->td({-class => 'blkhead'}, $text)));
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
# A chunk of text
|
|
||||||
if (ref $item eq 'GnatsPR::Section::Text') {
|
|
||||||
my $text = $item->string();
|
|
||||||
$text = $q->escapeHTML($text);
|
|
||||||
$text = Linkify($text);
|
|
||||||
$text = AddBreaks($text);
|
|
||||||
|
|
||||||
# Table used to ensure text CSS consistency (evil, I know)
|
|
||||||
print $q->table($q->tbody($q->Tr($q->td({class => 'mfield'}, $text))))
|
|
||||||
if $text;
|
|
||||||
#print $q->p($text);
|
|
||||||
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Patch block
|
|
||||||
if (ref $item eq 'GnatsPR::Section::Patch') {
|
|
||||||
my $text = $item->string();
|
|
||||||
$text = $q->escapeHTML($text);
|
|
||||||
$text = ColourPatch($text)
|
|
||||||
if ($item->type eq 'diff');
|
|
||||||
$text = AddBreaks($text); # Unless binary
|
|
||||||
|
|
||||||
print AttachmentHeader($item->{filename}, ++$patchnum);
|
|
||||||
print $text;
|
|
||||||
print AttachmentFooter();
|
|
||||||
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Audit-Trail state/responsible change block
|
|
||||||
if (ref $item eq 'GnatsPR::Section::StateChange') {
|
|
||||||
# This must be hard-coded - the old value will still
|
|
||||||
# linger in PRs, even if the script moves.
|
|
||||||
my $selfurl = "http://www.freebsd.org/cgi/query-pr.cgi?pr="
|
|
||||||
. $gnatspr->FieldSingle('Number');
|
|
||||||
|
|
||||||
# Remove the URL, as it is merely clutter
|
|
||||||
my $why = $item->why;
|
|
||||||
$why =~ s/[\n\s]*\Q$selfurl\E[\n\s]*$//i;
|
|
||||||
$item->why($why);
|
|
||||||
|
|
||||||
print $q->table({-class => 'auditblock', -cellspacing => '1'},
|
|
||||||
$q->Tr(
|
|
||||||
$q->th(
|
|
||||||
{-colspan => 2, -class => 'info'},
|
|
||||||
$q->escapeHTML($item->what) . " Changed"
|
|
||||||
)
|
|
||||||
),
|
|
||||||
|
|
||||||
$q->Tr(
|
|
||||||
$q->td({-class => 'key'}, 'From-To:'),
|
|
||||||
$q->td(
|
|
||||||
$q->escapeHTML(
|
|
||||||
$item->from . '->' . $item->to
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
|
|
||||||
$q->Tr(
|
|
||||||
$q->td({-class => 'key'}, 'By:'),
|
|
||||||
$q->td($q->escapeHTML($item->by))
|
|
||||||
),
|
|
||||||
|
|
||||||
$q->Tr(
|
|
||||||
$q->td({-class => 'key'}, 'When:'),
|
|
||||||
$q->td($q->escapeHTML($item->when))
|
|
||||||
),
|
|
||||||
|
|
||||||
$q->Tr(
|
|
||||||
$q->td({-class => 'key'}, 'Why:'),
|
|
||||||
AddBreaks($q->td($q->escapeHTML($item->why)))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Reply via E-mail
|
|
||||||
if (ref $item eq 'GnatsPR::Section::Email') {
|
|
||||||
print $q->start_table({-class => 'replyblock',
|
|
||||||
-cellspacing => '1'});
|
|
||||||
|
|
||||||
$replynum++;
|
|
||||||
|
|
||||||
print $q->Tr($q->th(
|
|
||||||
{-colspan => 2, -class => 'info'},
|
|
||||||
'Reply via E-mail '
|
|
||||||
. $q->a({href => '#reply'.$replynum,
|
|
||||||
name => 'reply'.$replynum}, '[Link]')
|
|
||||||
));
|
|
||||||
|
|
||||||
# Try to determine if sender is submitter
|
|
||||||
|
|
||||||
my $fromtag = FromSubmitter($item, $gnatspr)
|
|
||||||
? $q->b(' [submitter]') : '';
|
|
||||||
|
|
||||||
# Print header
|
|
||||||
|
|
||||||
foreach my $f ('From', 'To', 'Date') {
|
|
||||||
print $q->Tr(
|
|
||||||
$q->td({-class => 'key'}, $f . ':'),
|
|
||||||
$q->td({-class => 'val'},
|
|
||||||
$q->escapeHTML(
|
|
||||||
scalar decode_mimewords($item->Header($f))
|
|
||||||
)
|
|
||||||
.
|
|
||||||
(($f eq 'From') ? $fromtag : '')
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
print $q->start_Tr;
|
|
||||||
print $q->start_td({-colspan => 2});
|
|
||||||
|
|
||||||
# MIME parts
|
|
||||||
|
|
||||||
my $mime_iter = GnatsPR::MIMEIterator->new($item);
|
|
||||||
|
|
||||||
while (my $part = $mime_iter->next()) {
|
|
||||||
my $ctype = $part->header('content-type');
|
|
||||||
my $elide = 0;
|
|
||||||
|
|
||||||
print $q->hr({-class => 'mimeboundary'})
|
|
||||||
unless ($mime_iter->isfirst);
|
|
||||||
|
|
||||||
$part->isattachment
|
|
||||||
and ++$patchnum;
|
|
||||||
|
|
||||||
# Skip (inline) HTML parts -- but only if we have
|
|
||||||
# a plaintext part. We could possibly be a bit more
|
|
||||||
# rigorous in verifying the existence of the latter,
|
|
||||||
# but testing for the MIME header or other part will
|
|
||||||
# suffice, as it is unlikely a HTML-only e-mail will
|
|
||||||
# have more than that single part.
|
|
||||||
if ($ctype eq 'text/html' && !$part->isattachment &&
|
|
||||||
!$mime_iter->isfirst) {
|
|
||||||
$elide = 1;
|
|
||||||
|
|
||||||
# S/MIME signatures - of questionable value here
|
|
||||||
} elsif ($ctype eq 'application/pkcs7-signature') {
|
|
||||||
$elide = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($elide) {
|
|
||||||
if ($part->isattachment) {
|
|
||||||
my $url = $q->url(-full => 1, -query => 1);
|
|
||||||
|
|
||||||
my $dlink =
|
|
||||||
$q->a({-href => $url . '&getpatch=' . $patchnum},
|
|
||||||
'[Download]');
|
|
||||||
|
|
||||||
print $q->div(
|
|
||||||
{-class => 'elidemsg'},
|
|
||||||
'Attachment of type "' . $q->escapeHTML($ctype)
|
|
||||||
. '" ' . $dlink
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
print $q->div(
|
|
||||||
{-class => 'elidemsg'},
|
|
||||||
'MIME part of type "' . $q->escapeHTML($ctype)
|
|
||||||
. '" elided'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
$part->isattachment
|
|
||||||
and print AttachmentHeader($part->filename, $patchnum);
|
|
||||||
|
|
||||||
if ($part->isbinary) { # Implies isattachment
|
|
||||||
print $q->escapeHTML($part->body);
|
|
||||||
} else {
|
|
||||||
my $text;
|
|
||||||
|
|
||||||
if ($part->header('content-type') eq 'text/plain'
|
|
||||||
&& !$part->isattachment) {
|
|
||||||
# ColourEmail escapes too
|
|
||||||
$text = Linkify(ColourEmail($part->data));
|
|
||||||
} else {
|
|
||||||
$text = $q->escapeHTML($part->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($part->isattachment
|
|
||||||
&& $part->filename =~ /\.(?:diff|patch)\b/i) {
|
|
||||||
$text = ColourPatch($text);
|
|
||||||
}
|
|
||||||
|
|
||||||
print AddBreaks($text);
|
|
||||||
}
|
|
||||||
|
|
||||||
$part->isattachment
|
|
||||||
and print AttachmentFooter();
|
|
||||||
}
|
|
||||||
|
|
||||||
print $q->end_td;
|
|
||||||
print $q->end_Tr;
|
|
||||||
}
|
|
||||||
|
|
||||||
print $q->end_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
print FooterLinks($gnatspr);
|
|
||||||
|
|
||||||
print html_footer();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: AddBreaks()
|
|
||||||
# Desc: Convert newlines to HTML break elements.
|
|
||||||
#
|
|
||||||
# Args: $text - Input
|
|
||||||
#
|
|
||||||
# Retn: $text - Output
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub AddBreaks
|
|
||||||
{
|
|
||||||
my $text = shift;
|
|
||||||
|
|
||||||
$text =~ s/\n/<br \/>/g;
|
|
||||||
|
|
||||||
return $text;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: Linkify()
|
|
||||||
# Desc: Perform any fancy formatting on the message (e.g. HTML-ify URLs) and
|
|
||||||
# return the result.
|
|
||||||
#
|
|
||||||
# Args: $html - Input string
|
|
||||||
#
|
|
||||||
# Retn: $html - Output string
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub Linkify
|
|
||||||
{
|
|
||||||
my ($html) = @_;
|
|
||||||
|
|
||||||
# XXX: clean up
|
|
||||||
|
|
||||||
$html or return '';
|
|
||||||
|
|
||||||
my $iv = 'A-Za-z0-9\-_\/#@\$=\\\\';
|
|
||||||
|
|
||||||
my $scriptname = $q->escapeHTML($ENV{'SCRIPT_NAME'});
|
|
||||||
|
|
||||||
# PR references
|
|
||||||
$html =~
|
|
||||||
s/(?<![$iv])($valid_category)\/($valid_pr)(?![$iv])/<a href="${scriptname}?pr=$2&cat=$1">$1\/$2<\/a>/g;
|
|
||||||
|
|
||||||
# URLs
|
|
||||||
$html =~
|
|
||||||
s/((?:https?|ftps?):\/\/[^\s\/]+\/[][\w=.,\'\(\)\~\?\!\&\/\%\$\{\}:;@#+-]*)/<a href="$1">$1<\/a>/g;
|
|
||||||
|
|
||||||
return $html;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: ColourPatch()
|
|
||||||
# Desc: Apply 'cdiff' style colours to a patch.
|
|
||||||
#
|
|
||||||
# Args: $html - Input string
|
|
||||||
#
|
|
||||||
# Retn: $html - Output string
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub ColourPatch
|
|
||||||
{
|
|
||||||
my ($html) = @_;
|
|
||||||
my $res = '';
|
|
||||||
|
|
||||||
# XXX: clean up
|
|
||||||
|
|
||||||
my $plus_s = $q->start_span({-class => 'patch_plusline'});
|
|
||||||
my $minus_s = $q->start_span({-class => 'patch_minusline'});
|
|
||||||
my $context_s = $q->start_span({-class => 'patch_contextline'});
|
|
||||||
my $revinfo_s = $q->start_span({-class => 'patch_revinfo'});
|
|
||||||
my $at_s = $q->start_span({-class => 'patch_hunkinfo'});
|
|
||||||
my $all_e = $q->end_span;
|
|
||||||
|
|
||||||
# Expand tabs
|
|
||||||
while ($html =~ s/\t/" " x (8 - ((length($`)-1) % 8))/e) {};
|
|
||||||
|
|
||||||
foreach my $line (split /\n/, $html) {
|
|
||||||
$line =~ s/^(\+.*)$/${plus_s}$1${all_e}/o;
|
|
||||||
$line =~ s/^(-.*)$/${minus_s}$1${all_e}/o
|
|
||||||
if $line !~ s/^(--- \d+,\d+ ----.*)$/${revinfo_s}$1${all_e}/o;
|
|
||||||
$line =~ s/^(\*\*\* \d+,\d+ *\*\*\*.*)$/${revinfo_s}$1${all_e}/o;
|
|
||||||
$line =~ s/^(\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*)$/${revinfo_s}$1${all_e}/o;
|
|
||||||
$line =~ s/^(!.*)$/${context_s}$1${all_e}/o;
|
|
||||||
$line =~ s/^(@@.*$)/${at_s}$1${all_e}/o;
|
|
||||||
$line =~ s/^ / /;
|
|
||||||
$res .= "$line\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$res =~ s/\n$//;
|
|
||||||
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: ColourEmail()
|
|
||||||
# Desc: Colourise quoting levels in e-mails, and escape.
|
|
||||||
#
|
|
||||||
# Args: $email - Input string
|
|
||||||
#
|
|
||||||
# Retn: $email - Output string
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub ColourEmail
|
|
||||||
{
|
|
||||||
my ($email) = @_;
|
|
||||||
|
|
||||||
my $result = '';
|
|
||||||
|
|
||||||
foreach my $line (split /\n/, $email) {
|
|
||||||
if ($line =~ /^\s*((?:>\s*)+)(.*)$/) {
|
|
||||||
my $levels = $1;
|
|
||||||
my $text = $2;
|
|
||||||
my $depth;
|
|
||||||
|
|
||||||
$depth = $levels;
|
|
||||||
$depth =~ s/[^>]+//g;
|
|
||||||
$depth = length $depth;
|
|
||||||
|
|
||||||
$levels =~ s/>/>/g;
|
|
||||||
|
|
||||||
# Vim style rather than mutt
|
|
||||||
|
|
||||||
$result .= $q->span({
|
|
||||||
-class => 'quote' . ($depth % 2 ? 0 : 1)
|
|
||||||
}, $levels . $q->escapeHTML($text));
|
|
||||||
} else {
|
|
||||||
$result .= $q->escapeHTML($line);
|
|
||||||
}
|
|
||||||
$result .= "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: Exit()
|
|
||||||
# Desc: Exit script.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: n/a
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub Exit
|
|
||||||
{
|
|
||||||
# Introduce a short delay, as a DoS protection measure
|
|
||||||
select undef, undef, undef, 0.35
|
|
||||||
unless !$iscgi;
|
|
||||||
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: ErrorExit()
|
|
||||||
# Desc: Print an error message and exit.
|
|
||||||
#
|
|
||||||
# Args: $code - EXIT_* code
|
|
||||||
#
|
|
||||||
# Retn: n/a
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub ErrorExit
|
|
||||||
{
|
|
||||||
my ($code) = @_;
|
|
||||||
|
|
||||||
my $url = $q->url(-full => 1, -query => 1);
|
|
||||||
|
|
||||||
if ($code == EXIT_NOPRS) {
|
|
||||||
print html_header("FreeBSD has migrated to <a href='https://bugs.FreeBSD.org/search/'>Bugzilla</a>. Try your search there.");
|
|
||||||
print html_footer();
|
|
||||||
} elsif ($code == EXIT_DBBUSY) {
|
|
||||||
print html_header("PR Database Busy");
|
|
||||||
print $q->p(
|
|
||||||
'Please '
|
|
||||||
. $q->a({-href => $url}, 'try again')
|
|
||||||
. ' later'
|
|
||||||
);
|
|
||||||
print html_footer();
|
|
||||||
} elsif ($code == EXIT_NOPATCH) {
|
|
||||||
print "Content-type: text/plain; charset=UTF-8\r\n\r\n";
|
|
||||||
print "No such patch!\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
Exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: FromSubmitter()
|
|
||||||
# Desc: Try determine if the sender of a reply is the sender of the PR.
|
|
||||||
#
|
|
||||||
# Args: $item - GnatsPR::Section::Email instance.
|
|
||||||
# $gnatspr - GnatsPR instance
|
|
||||||
#
|
|
||||||
# Retn: $result - Is sender the submitter?
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub FromSubmitter
|
|
||||||
{
|
|
||||||
my ($item, $gnatspr) = @_;
|
|
||||||
|
|
||||||
my $from = lc $item->Header('From');
|
|
||||||
my $submitter = lc $gnatspr->Header('From');
|
|
||||||
|
|
||||||
$from =~ s/^.*<// and $from =~ s/>.*$//;
|
|
||||||
$from =~ s/\s+//g;
|
|
||||||
$submitter =~ s/^.*<// and $submitter =~ s/>.*$//;
|
|
||||||
$submitter =~ s/\s+//g;
|
|
||||||
|
|
||||||
return $from eq $submitter;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: AttachmentHeader()
|
|
||||||
# Desc: Construct an attachment block header.
|
|
||||||
#
|
|
||||||
# Args: $filename - Name of attachment.
|
|
||||||
# $patchnum - Patch index.
|
|
||||||
#
|
|
||||||
# Retn: $text - Header text.
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub AttachmentHeader
|
|
||||||
{
|
|
||||||
my ($filename, $patchnum) = @_;
|
|
||||||
|
|
||||||
my $text = '';
|
|
||||||
|
|
||||||
my $url = $q->url(-full => 1, -query => 1);
|
|
||||||
|
|
||||||
$text .= $q->start_table({-class => 'patchblock', -cellspacing => '1'});
|
|
||||||
$text .=
|
|
||||||
$q->Tr(
|
|
||||||
$q->td({-class => 'info'}, $q->b(
|
|
||||||
'Download ' . $q->a({-href => $url . '&getpatch=' . $patchnum},
|
|
||||||
$filename)
|
|
||||||
))
|
|
||||||
);
|
|
||||||
|
|
||||||
$text .= $q->start_tbody;
|
|
||||||
$text .= $q->start_Tr;
|
|
||||||
$text .= $q->start_td({-class => 'content'});
|
|
||||||
$text .= $q->start_pre({-class => 'attachwin'});
|
|
||||||
|
|
||||||
return $text;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: AttachmentFooter()
|
|
||||||
# Desc: Construct an attachment block footer.
|
|
||||||
#
|
|
||||||
# Args: n/a
|
|
||||||
#
|
|
||||||
# Retn: $text - Footer text.
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub AttachmentFooter
|
|
||||||
{
|
|
||||||
my $text = '';
|
|
||||||
|
|
||||||
$text .= $q->end_pre;
|
|
||||||
$text .= $q->end_td;
|
|
||||||
$text .= $q->end_Tr;
|
|
||||||
$text .= $q->end_tbody;
|
|
||||||
$text .= $q->end_table;
|
|
||||||
|
|
||||||
return $text;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Func: FooterLinks()
|
|
||||||
# Desc: Construct the page footer links (for a valid PR page)
|
|
||||||
#
|
|
||||||
# Args: $gnatspr - GnatsPR instance.
|
|
||||||
#
|
|
||||||
# Retn: $text - Footer text.
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
sub FooterLinks
|
|
||||||
{
|
|
||||||
my ($gnatspr) = @_;
|
|
||||||
|
|
||||||
my $url = $q->url(-full => 1, -query => 1);
|
|
||||||
|
|
||||||
return $q->div({-class => 'footerlinks'},
|
|
||||||
$q->a({-href => $url . '&f=raw'}, 'Raw PR')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,267 +0,0 @@
|
||||||
#!/usr/bin/perl -T
|
|
||||||
#
|
|
||||||
# mail-archive.pl -- a CGI interface to a wais indexed maling list archive.
|
|
||||||
#
|
|
||||||
# Origin:
|
|
||||||
# Tony Sanders <sanders@bsdi.com>, Nov 1993
|
|
||||||
#
|
|
||||||
# Hacked beyond recognition by:
|
|
||||||
# John Fieber <jfieber@cs.smith.edu>, Nov 1994
|
|
||||||
#
|
|
||||||
# Format the mail messages a little nicer.
|
|
||||||
# Add code to check database status before searching.
|
|
||||||
# John Fieber <jfieber@indiana.edu>, Aug 1996
|
|
||||||
#
|
|
||||||
# Disclaimer:
|
|
||||||
# This is pretty ugly in places.
|
|
||||||
#
|
|
||||||
# $FreeBSD$
|
|
||||||
|
|
||||||
|
|
||||||
$server_root = '/usr/local/www';
|
|
||||||
$waisq = "/usr/local/www/bin/waisq";
|
|
||||||
$sourcepath = "$server_root/db/index";
|
|
||||||
$hints = "/search/searchhints.html";
|
|
||||||
$searchpage = '/search/search.html';
|
|
||||||
$myurl = $ENV{'SCRIPT_NAME'};
|
|
||||||
$ENV{PATH} = "/bin:/usr/bin:/usr/local/bin";
|
|
||||||
|
|
||||||
use IPC::Open2 'open2';
|
|
||||||
require "./cgi-lib.pl";
|
|
||||||
require "./cgi-style.pl";
|
|
||||||
|
|
||||||
@months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
|
|
||||||
|
|
||||||
sub escape($) { $_ = $_[0]; s/&/&/g; s/</</g; s/>/>/g; $_; }
|
|
||||||
|
|
||||||
sub do_wais {
|
|
||||||
&ReadParse;
|
|
||||||
|
|
||||||
@FORM_words = map { s|"||g; $_ } split(/ /, escape($in{"words"}));
|
|
||||||
@FORM_source = split(/\0/, escape($in{"source"}));
|
|
||||||
($FORM_max) = $in{"max"} =~ m|^(\d+)$|;
|
|
||||||
$FORM_docnum = $in{"docnum"};
|
|
||||||
$FORM_index = $in{"index"};
|
|
||||||
|
|
||||||
if ($FORM_index =~ /^re[sc]ent$/) {
|
|
||||||
$sourcepath = "$server_root/db/index-recent";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($#FORM_words < 0) {
|
|
||||||
print &html_header("Mail Archive Search") .
|
|
||||||
"<p>No search term given.";
|
|
||||||
print "<p>\nPlease return to the " .
|
|
||||||
"search page and fill out the 'Search for' field!\n";
|
|
||||||
print &html_footer;
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AVAIL_source = &checksource(@FORM_source);
|
|
||||||
if ($#FORM_source != $#AVAIL_source) {
|
|
||||||
$j = 0;
|
|
||||||
$k = 0;
|
|
||||||
foreach $i (0 .. $#FORM_source) {
|
|
||||||
if ($FORM_source[$i] ne $AVAIL_source[$j]) {
|
|
||||||
$badsource[$k] = $FORM_source[$i];
|
|
||||||
$k++;
|
|
||||||
} else {
|
|
||||||
$j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$badsource = join("</em>, <em>", @badsource);
|
|
||||||
$badsource =~ s/,([^,]*)$/ and $1/;
|
|
||||||
if ($#FORM_source - $#AVAIL_source > 1) {
|
|
||||||
$availmsg = "<p>[The <em>$badsource</em> archives are currently unavailable.]</p>";
|
|
||||||
} else {
|
|
||||||
$availmsg = "<p>[The <em>$badsource</em> archive is currently unavailable.]</p>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($#AVAIL_source < 0) {
|
|
||||||
$i = join("</em>, <em>", @FORM_source);
|
|
||||||
$i =~ s/,([^,]*)$/ and $1/;
|
|
||||||
print &html_header("Mail Archive Search") .
|
|
||||||
"<p>None of the archives you requested (<em>$i</em>) are " .
|
|
||||||
" available at this time.</p>\n";
|
|
||||||
print "<p>Please try again later, or return to the " .
|
|
||||||
"search page and select a different archive.</p>\n";
|
|
||||||
print &html_footer;
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Now we formulate the question to ask the server
|
|
||||||
foreach $i (@AVAIL_source) {
|
|
||||||
$w_sources .= "(:source-id\n :filename \"$i.src\"\n ) ";
|
|
||||||
}
|
|
||||||
$w_question = "\n (:question
|
|
||||||
:version 2
|
|
||||||
:seed-words \"@FORM_words\"
|
|
||||||
:relevant-documents
|
|
||||||
( )
|
|
||||||
:sourcepath \"$sourcepath/:\"
|
|
||||||
:sources
|
|
||||||
( $w_sources )
|
|
||||||
:maximum-results $FORM_max
|
|
||||||
:result-documents
|
|
||||||
( )
|
|
||||||
)\n";
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# First case, no document number so this is a regular search
|
|
||||||
#
|
|
||||||
print &html_header("Search Results");
|
|
||||||
print $availmsg;
|
|
||||||
if ($#AVAIL_source > 0) {
|
|
||||||
$src = join("</em>, <em>", @AVAIL_source);
|
|
||||||
$src =~ s/,([^,]*)$/ and $1/;
|
|
||||||
print "<p>The archives <em>$src</em> contain ";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print "The archive <em>@AVAIL_source</em> contains ";
|
|
||||||
}
|
|
||||||
print " the following items relevant to \`@FORM_words\':\n";
|
|
||||||
print "<ol>\n";
|
|
||||||
|
|
||||||
&open2(WAISOUT, WAISIN, $waisq, "-g");
|
|
||||||
print WAISIN $w_question;
|
|
||||||
|
|
||||||
local(@mylist) = ();
|
|
||||||
local($hits, $score, $headline, $lines, $bytes, $docid, $date, $file);
|
|
||||||
|
|
||||||
while (<WAISOUT>) {
|
|
||||||
/:original-local-id.*#\(\s+([^\)]*)/ &&
|
|
||||||
($docid = pack("C*", split(/\s+/, $1)),
|
|
||||||
$docid =~ s/\s+/+/g);
|
|
||||||
/:score\s+(\d+)/ && ($score = $1);
|
|
||||||
/:filename "(.*)"/ && ($file = $1);
|
|
||||||
/:number-of-lines\s+(\d+)/ && ($lines = $1);
|
|
||||||
/:number-of-bytes\s+(\d+)/ && ($bytes = $1);
|
|
||||||
/:headline "(.*)"/ && ($headline = $1,
|
|
||||||
$headline =~ s/[Rr]e://); # XXX
|
|
||||||
/:date "(\d+)"/ && $docid !~ /\.src$/ && ($date = $1, $hits++,
|
|
||||||
push(@mylist, join("\t", $date, $headline, $docid,
|
|
||||||
$bytes, $lines, $file, $score, $hits)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($in{'sort'} eq "date") {
|
|
||||||
foreach (reverse sort {$a <=> $b} @mylist) {
|
|
||||||
($date, $headline, $docid, $bytes, $lines,
|
|
||||||
$file, $score, $hits) = split("\t");
|
|
||||||
&docdone;
|
|
||||||
}
|
|
||||||
} elsif ($in{'sort'} eq "subject") {
|
|
||||||
local(@a, @c, $b, $d);
|
|
||||||
foreach (@mylist) {
|
|
||||||
@a = split("\t");
|
|
||||||
$b = $a[0];
|
|
||||||
# swap date and subject
|
|
||||||
if ($a[1] =~ /(^[^:]+)(Re:.*)/) {
|
|
||||||
$a[0] = "$2\t$1";
|
|
||||||
} else {
|
|
||||||
$a[0] = "$a[1]\t.";
|
|
||||||
}
|
|
||||||
$a[1] = $b;
|
|
||||||
push(@c, join("\t", @a));
|
|
||||||
}
|
|
||||||
local($subject, $author);
|
|
||||||
foreach (sort {$a cmp $b} @c) {
|
|
||||||
($subject, $author, $date, $docid, $bytes,
|
|
||||||
$lines, $file, $score, $hits) = split("\t");
|
|
||||||
$headline = $author . $subject;
|
|
||||||
&docdone;
|
|
||||||
}
|
|
||||||
|
|
||||||
} elsif ($in{'sort'} eq "author") {
|
|
||||||
local(@a, @c, $b);
|
|
||||||
foreach (@mylist) {
|
|
||||||
@a = split("\t");
|
|
||||||
# swap date and subject
|
|
||||||
$b = $a[0]; $a[0] = $a[1]; $a[1] = $b;
|
|
||||||
push(@c, join("\t", @a));
|
|
||||||
}
|
|
||||||
foreach (sort {$a cmp $b} @c) {
|
|
||||||
($headline, $date, $docid, $bytes,
|
|
||||||
$lines, $file, $score, $hits) = split("\t");
|
|
||||||
&docdone;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
foreach (@mylist) {
|
|
||||||
($date, $headline, $docid, $bytes,
|
|
||||||
$lines, $file, $score, $hits) = split("\t");
|
|
||||||
&docdone;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#print qq[in: $in{'sort'}\n];
|
|
||||||
|
|
||||||
print "</ol>\n";
|
|
||||||
|
|
||||||
print "<p>Didn't get what you expected? ";
|
|
||||||
print "<a href=\"$hints\">Look here for searching hints</a>.</p>";
|
|
||||||
|
|
||||||
print qq{<p><a href="$searchpage">Return to the search page</a></p>\n};
|
|
||||||
|
|
||||||
if ($hits == 0) {
|
|
||||||
print "Nothing found.\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
print &html_footer;
|
|
||||||
close(WAISOUT);
|
|
||||||
close(WAISIN);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
# Given an array of sources (sans .src extension), this routine
|
|
||||||
# checks to see if they actually exist, and if they do, if they
|
|
||||||
# are currently available (ie, not being updated). It returns
|
|
||||||
# an array of sources that are actually available.
|
|
||||||
|
|
||||||
sub checksource {
|
|
||||||
local (@sources) = @_;
|
|
||||||
|
|
||||||
$j = 0;
|
|
||||||
foreach $i (@sources) {
|
|
||||||
($i) = $i =~ m|^([-a-z0-9]*)|;
|
|
||||||
if (stat("$sourcepath/$i.src")) {
|
|
||||||
if (!stat("$sourcepath/$i.update.lock")) {
|
|
||||||
$goodsources[$j] = $i;
|
|
||||||
$j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(@goodsources);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub docdone {
|
|
||||||
$file =~ s/\.src$//;
|
|
||||||
if ($headline =~ /Search produced no result/) {
|
|
||||||
print "<p>The archive <em>$file</em> contains no relevant documents.</p>"
|
|
||||||
} else {
|
|
||||||
$headline = escape($headline);
|
|
||||||
$headline =~ s/\\"/\"/g;
|
|
||||||
if ($file eq "www" || $file =~ /^www-[a-z][a-z]$/ || $file eq 'pkgdescr' || $file eq "manpages") {
|
|
||||||
print "<li><a href=\"$headline\">$headline</a>\n";
|
|
||||||
} else {
|
|
||||||
print "<li><a href=\"getmsg.cgi?fetch=${docid}\">$headline</a>\n";
|
|
||||||
}
|
|
||||||
print "<br/>";
|
|
||||||
# print "<input type=\"checkbox\" name=\"rf\" value=\"$docnum\"/>";
|
|
||||||
print "Score: <em>$score</em>; ";
|
|
||||||
$_ = $date;
|
|
||||||
/^(..?)(..)(..)$/ && ($yr = $1 + ($1 > 69 ? 1900 : 2000), $mo = $months[$2 - 1], $dy = $3);
|
|
||||||
print "Lines: <em>$lines</em>; ";
|
|
||||||
print "${dy}-${mo}-${yr}; ";
|
|
||||||
print "Archive: <em>$file</em>";
|
|
||||||
print "<p></p></li>\n";
|
|
||||||
}
|
|
||||||
$score = $headline = $lines = $bytes = $docid = $date = $file = '';
|
|
||||||
$yr = $mo = $dy = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
$| = 1;
|
|
||||||
open (STDERR,"> /dev/null");
|
|
||||||
#open (STDERR,">> /tmp/search");
|
|
||||||
eval '&do_wais';
|
|
||||||
if ($@) {
|
|
||||||
warn "eval failed: $@";
|
|
||||||
}
|
|
||||||
|
|
@ -14,7 +14,6 @@ DATA+= global.css
|
||||||
DATA+= iefixes.css
|
DATA+= iefixes.css
|
||||||
DATA+= layout.css
|
DATA+= layout.css
|
||||||
DATA+= navigation.css
|
DATA+= navigation.css
|
||||||
DATA+= query-pr.css
|
|
||||||
DATA+= table.css
|
DATA+= table.css
|
||||||
DATA+= text.css
|
DATA+= text.css
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,172 +0,0 @@
|
||||||
/*
|
|
||||||
* CSS stylesheet for the new query-pr interface.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2011, Shaun Amott <shaun@FreeBSD.org>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* $FreeBSD$
|
|
||||||
*/
|
|
||||||
|
|
||||||
.attachwin {
|
|
||||||
font-size: 100%;
|
|
||||||
margin-top: 0px;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
overflow: scroll;
|
|
||||||
max-height: 600px;
|
|
||||||
max-width: 655px;
|
|
||||||
width: 655px;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
font-family: "Courier New", "Courier", monospace;
|
|
||||||
font-size: 100%;
|
|
||||||
white-space: pre;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fields */
|
|
||||||
|
|
||||||
td {
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mfield, p {
|
|
||||||
padding-left: 1.4em;
|
|
||||||
padding-right: 1.4em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.headtable {
|
|
||||||
border-left: 1px solid #999999;
|
|
||||||
border-bottom: 1px solid #999999;
|
|
||||||
width: 100%;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.headtable .key {
|
|
||||||
font-weight: bold;
|
|
||||||
width: 12em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.headtable .val {
|
|
||||||
}
|
|
||||||
|
|
||||||
.headtable .blkhead {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mfieldtable {
|
|
||||||
border-left: 1px solid #999999;
|
|
||||||
border-bottom: 1px solid #999999;
|
|
||||||
width: 100%;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
margin-top: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Patch block */
|
|
||||||
|
|
||||||
.patchblock {
|
|
||||||
border: 1px solid #999999;
|
|
||||||
background-color: #EFEFBB;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
max-width: 675px;
|
|
||||||
margin-top: 1.4em;
|
|
||||||
}
|
|
||||||
.patchblock .info {
|
|
||||||
background-color: #ACACAA;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
.patchblock .content {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Audit block */
|
|
||||||
|
|
||||||
.auditblock {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
border: 1px solid #999999;
|
|
||||||
background-color: #EFEFEF;
|
|
||||||
width: 90%;
|
|
||||||
margin-top: 1.4em;
|
|
||||||
}
|
|
||||||
.auditblock .key {
|
|
||||||
font-weight: bold;
|
|
||||||
width: 6.0em;
|
|
||||||
}
|
|
||||||
.auditblock .info {
|
|
||||||
background-color: #ACACAA;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Reply block */
|
|
||||||
|
|
||||||
.replyblock {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
border: 1px solid #999999;
|
|
||||||
background-color: #EFEFEF;
|
|
||||||
width: 90%;
|
|
||||||
margin-top: 1.4em;
|
|
||||||
}
|
|
||||||
.replyblock .info {
|
|
||||||
background-color: #AA9900;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.replyblock .key {
|
|
||||||
background-color: #CCCCCC;
|
|
||||||
font-weight: bold;
|
|
||||||
width: 6.0em;
|
|
||||||
}
|
|
||||||
.replyblock .val {
|
|
||||||
background-color: #CCCCCC;
|
|
||||||
}
|
|
||||||
|
|
||||||
.quote0 { color: #DD0000; }
|
|
||||||
.quote1 { color: #0000DD; }
|
|
||||||
|
|
||||||
.patch_plusline { color: #FF0000; }
|
|
||||||
.patch_minusline { color: #0000FF; }
|
|
||||||
.patch_contextline { color: #00AA00; }
|
|
||||||
.patch_revinfo { font-weight: bold; }
|
|
||||||
.patch_hunkinfo { font-weight: bold; }
|
|
||||||
|
|
||||||
.mimeboundary { border-top: 1px #DD0000 dashed; border-bottom: 0px; }
|
|
||||||
|
|
||||||
.elidemsg {
|
|
||||||
padding: 4px;
|
|
||||||
background-color: #C6C6C6;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #444444;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Footer */
|
|
||||||
|
|
||||||
.footerlinks {
|
|
||||||
margin-top: 40px;
|
|
||||||
}
|
|
||||||
|
|
@ -15,15 +15,6 @@
|
||||||
<body class="navinclude.developers">
|
<body class="navinclude.developers">
|
||||||
<img align="right" alt="McKinley die" src="mckinley-die.png"/>
|
<img align="right" alt="McKinley die" src="mckinley-die.png"/>
|
||||||
|
|
||||||
<p>Search the ia64 mailing list archives:</p>
|
|
||||||
|
|
||||||
<form action="&cgibase;/search.cgi" method="get">
|
|
||||||
<input name="words" size="50" type="text"/>
|
|
||||||
<input name="max" type="hidden" value="25"/>
|
|
||||||
<input name="source" type="hidden" value="freebsd-ia64"/>
|
|
||||||
<input type="submit" value="Go"/>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<h3><a name="toc">Table Of Contents</a></h3>
|
<h3><a name="toc">Table Of Contents</a></h3>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,6 @@ DATA+= opensearch.js
|
||||||
DATA+= man.xml
|
DATA+= man.xml
|
||||||
DATA+= man-freebsd-release-ports.xml
|
DATA+= man-freebsd-release-ports.xml
|
||||||
DATA+= ports.xml
|
DATA+= ports.xml
|
||||||
DATA+= query-pr.xml
|
|
||||||
DATA+= web.xml
|
|
||||||
DATA+= web-all.xml
|
|
||||||
DATA+= message-id.xml
|
DATA+= message-id.xml
|
||||||
|
|
||||||
# external sites
|
# external sites
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,6 @@ function install(link) {
|
||||||
<li><a href="man.xml" onclick= "return install(this)">FreeBSD Manual Pages</a></li>
|
<li><a href="man.xml" onclick= "return install(this)">FreeBSD Manual Pages</a></li>
|
||||||
<li><a href="man-freebsd-release-ports.xml" onclick= "return install(this)">FreeBSD + Ports Manual Pages</a></li>
|
<li><a href="man-freebsd-release-ports.xml" onclick= "return install(this)">FreeBSD + Ports Manual Pages</a></li>
|
||||||
<li><a href="ports.xml" onclick= "return install(this)">FreeBSD Ports and Packages Collection</a></li>
|
<li><a href="ports.xml" onclick= "return install(this)">FreeBSD Ports and Packages Collection</a></li>
|
||||||
<li><a href="query-pr.xml" onclick= "return install(this)">FreeBSD Problem Reports</a></li>
|
|
||||||
<li><a href="web-all.xml" onclick= "return install(this)">FreeBSD Fulltext Search Web + Manual + Ports Pages</a></li>
|
|
||||||
<li><a href="web.xml" onclick= "return install(this)">FreeBSD Fulltext Search Web Pages</a></li>
|
|
||||||
<li><a href="message-id.xml" onclick= "return install(this)">FreeBSD Mailing List Message-ID Search</a></li>
|
<li><a href="message-id.xml" onclick= "return install(this)">FreeBSD Mailing List Message-ID Search</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
||||||
|
|
||||||
<!-- $FreeBSD$ -->
|
|
||||||
|
|
||||||
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
|
|
||||||
xml:lang="de">
|
|
||||||
<ShortName>FreeBSD Bugs</ShortName>
|
|
||||||
<LongName>FreeBSD Problem Reports</LongName>
|
|
||||||
<Description>FreeBSD Problem Reports</Description>
|
|
||||||
<Url template="http://www.freebsd.org/cgi/query-pr.cgi?pr={searchTerms}&sourceid=opensearch" type="text/html" />
|
|
||||||
<Developer>The FreeBSD Project</Developer>
|
|
||||||
<Contact>http://www.freebsd.org/</Contact>
|
|
||||||
<Image height="16" type="image/x-icon" width="16">http://www.freebsd.org/favicon.ico</Image>
|
|
||||||
<Language>en</Language>
|
|
||||||
<InputEncoding>ISO-8859-1</InputEncoding>
|
|
||||||
</OpenSearchDescription>
|
|
||||||
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
||||||
|
|
||||||
<!-- $FreeBSD$ -->
|
|
||||||
|
|
||||||
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
|
|
||||||
xml:lang="de">
|
|
||||||
<ShortName>FreeBSD Web All</ShortName>
|
|
||||||
<LongName>FreeBSD Web + Man + Ports Pages</LongName>
|
|
||||||
<Description>FreeBSD Web Pages</Description>
|
|
||||||
<Url template="http://www.freebsd.org/cgi/search.cgi?max=100&source=www&source=manpages&source=pkgdescr&words={searchTerms}&sourceid=opensearch" type="text/html" />
|
|
||||||
<Developer>The FreeBSD Project</Developer>
|
|
||||||
<Contact>http://www.freebsd.org/</Contact>
|
|
||||||
<Image height="16" type="image/x-icon" width="16">http://www.freebsd.org/favicon.ico</Image>
|
|
||||||
<Language>en</Language>
|
|
||||||
<InputEncoding>ISO-8859-1</InputEncoding>
|
|
||||||
</OpenSearchDescription>
|
|
||||||
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
||||||
|
|
||||||
<!-- $FreeBSD$ -->
|
|
||||||
|
|
||||||
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
|
|
||||||
xml:lang="de">
|
|
||||||
<ShortName>FreeBSD Web</ShortName>
|
|
||||||
<LongName>FreeBSD Web Pages</LongName>
|
|
||||||
<Description>FreeBSD Web Pages</Description>
|
|
||||||
<Url template="http://www.freebsd.org/cgi/search.cgi?max=100&source=www&words={searchTerms}&sourceid=opensearch" type="text/html" />
|
|
||||||
<Developer>The FreeBSD Project</Developer>
|
|
||||||
<Contact>http://www.freebsd.org/</Contact>
|
|
||||||
<Image height="16" type="image/x-icon" width="16">http://www.freebsd.org/favicon.ico</Image>
|
|
||||||
<Language>en</Language>
|
|
||||||
<InputEncoding>ISO-8859-1</InputEncoding>
|
|
||||||
</OpenSearchDescription>
|
|
||||||
|
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
|
|
||||||
<form action="https://duckduckgo.com/" method="get">
|
<form action="https://duckduckgo.com/" method="get">
|
||||||
<h2 class="blockhide"><label for="words">Search</label></h2>
|
<h2 class="blockhide"><label for="words">Search</label></h2>
|
||||||
<input type="hidden" name="sites" value="www.FreeBSD.org,lists.FreeBSD.org,wiki.FreeBSD.org,forums.FreeBSD.org" />
|
<input type="hidden" name="sites" value="www.FreeBSD.org,docs.FreeBSD.org/doc,wiki.FreeBSD.org,forums.FreeBSD.org" />
|
||||||
<input type="hidden" name="ka" value="v" />
|
<input type="hidden" name="ka" value="v" />
|
||||||
<input type="hidden" name="kt" value="v" />
|
<input type="hidden" name="kt" value="v" />
|
||||||
<input type="hidden" name="kh" value="1" />
|
<input type="hidden" name="kh" value="1" />
|
||||||
|
|
@ -96,611 +96,18 @@
|
||||||
<p>The mailing lists (as well as many others) have also been archived by <a
|
<p>The mailing lists (as well as many others) have also been archived by <a
|
||||||
href="http://markmail.org/browse/?q=list:org.freebsd">MarkMail</a>.</p>
|
href="http://markmail.org/browse/?q=list:org.freebsd">MarkMail</a>.</p>
|
||||||
|
|
||||||
<form action="&cgibase;/search.cgi" method="get">
|
<form action="https://duckduckgo.com/" method="get">
|
||||||
|
<h2 class="blockhide"><label for="mlwords">Search</label></h2>
|
||||||
<h3>Search for:</h3>
|
<input type="hidden" name="sites" value="docs.FreeBSD.org/mail,lists.FreeBSD.org/pipermail" />
|
||||||
|
<input type="hidden" name="ka" value="v" />
|
||||||
<p><em>Note: Use the operators AND or NOT to limit your
|
<input type="hidden" name="kt" value="v" />
|
||||||
search. <a href="searchhints.html">Look here
|
<input type="hidden" name="kh" value="1" />
|
||||||
for more hints</a>.</em></p>
|
<input type="hidden" name="kj" value="r2" />
|
||||||
|
<input id="mlwords" name="q" type="text" size="50" maxlength="255" />
|
||||||
<p><input type="text" name="words" size="50"/><br/>
|
|
||||||
Limit the number of results to
|
|
||||||
|
|
||||||
<select name="max">
|
|
||||||
<option value="5">5</option>
|
|
||||||
<option value="10">10</option>
|
|
||||||
<option value="25" selected="selected">25</option>
|
|
||||||
<option value="50">50</option>
|
|
||||||
<option value="100">100</option>
|
|
||||||
<option value="250">250</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
sort by
|
|
||||||
|
|
||||||
<select name="sort">
|
|
||||||
<option value="score">score</option>
|
|
||||||
<option value="date">score & date</option>
|
|
||||||
<option value="subject">subject</option>
|
|
||||||
<option value="author">author</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
Search
|
|
||||||
|
|
||||||
<select name="index">
|
|
||||||
<option value="recent" selected="selected">recent</option>
|
|
||||||
<option value="all">all</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
<input id="mlsubmit" name="submit" type="submit" value="Submit Query" />
|
||||||
<input type="submit"/> <input type="reset"/></p>
|
<input id="mlreset" type="reset" value="Reset" />
|
||||||
|
|
||||||
<h3>In archive(s):</h3>
|
|
||||||
|
|
||||||
<p><em>Note: Searching more than three or four archives at once may
|
|
||||||
yield inaccurate results.</em></p>
|
|
||||||
|
|
||||||
<h3>General Archives</h3>
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-advocacy"/> <strong>Advocacy</strong></td>
|
|
||||||
<td>FreeBSD Evangelism</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-announce"/> <strong>Announce</strong></td>
|
|
||||||
<td>Important events / milestones</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-chat"/> <strong>Chat</strong></td>
|
|
||||||
<td>Random topics (sometimes) related to FreeBSD</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-jobs"/> <strong>Jobs</strong></td>
|
|
||||||
<td>FreeBSD related job announcements and resumes</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-newbies"/> <strong>Newbies</strong></td>
|
|
||||||
<td>New FreeBSD users activities and discussion</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source" checked="checked"
|
|
||||||
value="freebsd-questions"/> <strong>Questions</strong></td>
|
|
||||||
<td>General questions</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-security-notifications"/> <strong>Security Notifications</strong></td>
|
|
||||||
<td>Announcements regarding FreeBSD security issues (including, e.g., CERT notices)</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-user-groups"/> <strong>User-Groups</strong></td>
|
|
||||||
<td>A forum for FreeBSD user groups</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>System Use and Administration</h3>
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-bugs"/> <strong>Bugs</strong></td>
|
|
||||||
<td>Reports and discussion of bugs</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-cluster"/> <strong>Cluster</strong></td>
|
|
||||||
<td>Discussions related to using FreeBSD in clustered environments</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-hardware"/> <strong>Hardware</strong></td>
|
|
||||||
<td>Discussions concerning hardware as it relates to FreeBSD</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-isp"/> <strong>ISP</strong></td>
|
|
||||||
<td>Discussions for ISPs using FreeBSD</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-performance"/> <strong>Performance</strong></td>
|
|
||||||
<td>Discussions of the performance of FreeBSD under high load or extreme conditions</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-security"/> <strong>Security</strong></td>
|
|
||||||
<td>FreeBSD computer security issues (DES, Kerberos, etc.)</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-stable"/> <strong>Stable</strong></td>
|
|
||||||
<td>Discussion of the FreeBSD-stable branch of the development tree</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Developer</h3>
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-acpi"/> <strong>ACPI</strong></td>
|
|
||||||
<td>ACPI and power management development</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-afs"/> <strong>Afs</strong></td>
|
|
||||||
<td>Porting and using AFS (the Andrew File System) from CMU/Transarc</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-alpha"/> <strong>Alpha</strong></td>
|
|
||||||
<td>Porting FreeBSD to the DEC Alpha</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-amd64"/> <strong>AMD64</strong></td>
|
|
||||||
<td>Porting FreeBSD to the AMD64</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-apache"/> <strong>Apache</strong></td>
|
|
||||||
<td>Discussion about Apache related ports</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-arch"/> <strong>Arch</strong></td>
|
|
||||||
<td>Architecture and design discussions</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-arm"/> <strong>ARM</strong></td>
|
|
||||||
<td>Porting FreeBSD to the StrongArm</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-atm"/> <strong>ATM</strong></td>
|
|
||||||
<td>Using ATM networking with FreeBSD</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-audit"/> <strong>Audit</strong></td>
|
|
||||||
<td>Source code audit project</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-binup"/> <strong>Binup</strong></td>
|
|
||||||
<td>Design and development of the binary update system</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-bluetooth"/> <strong>Bluetooth</strong></td>
|
|
||||||
<td>Discussion about FreeBSD support for Bluetooth</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-chromium"/> <strong>Chromium</strong></td>
|
|
||||||
<td>FreeBSD-specific Chromium issues</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-bugbusters"/> <strong>Bugbusters</strong></td>
|
|
||||||
<td>Coordination of the Problem Report handling effort</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="cvs-all"/> <strong>Commit (all)</strong></td>
|
|
||||||
<td>All Changes made to all FreeBSD source trees</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="cvs-doc"/> <strong>Commit (doc)</strong></td>
|
|
||||||
<td>Changes made to the FreeBSD documents source tree</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="cvs-ports"/> <strong>Commit (ports)</strong></td>
|
|
||||||
<td>Changes made to the FreeBSD ports source tree</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="cvs-projects"/> <strong>Commit (projects)</strong></td>
|
|
||||||
<td>Changes made to the FreeBSD projects source tree</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="cvs-src"/> <strong>Commit (src)</strong></td>
|
|
||||||
<td>Changes made to the FreeBSD main source tree</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-config"/> <strong>Config</strong></td>
|
|
||||||
<td>Development of FreeBSD installation and configuration tools</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-current"/> <strong>Current</strong></td>
|
|
||||||
<td>Use of FreeBSD-current sources</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-cvsweb"/> <strong>CVSweb</strong></td>
|
|
||||||
<td>Technical discussions about use, development and maintenance of FreeBSD-CVSweb</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-database"/> <strong>Database</strong></td>
|
|
||||||
<td>Discussing database use and development under FreeBSD</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-doc"/> <strong>Doc</strong></td>
|
|
||||||
<td>Discussions concerning documentation</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-drivers"/> <strong>Drivers</strong></td>
|
|
||||||
<td>Writing device drivers for FreeBSD</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-embedded"/> <strong>Embedded</strong></td>
|
|
||||||
<td>Discussions about using FreeBSD in embedded systems</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-emulation"/> <strong>Emulation</strong></td>
|
|
||||||
<td>Emulating other systems on FreeBSD</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-firewire"/> <strong>Firewire</strong></td>
|
|
||||||
<td>Design and implementation
|
|
||||||
of a Firewire (aka IEEE 1394 aka iLink) subsystem for FreeBSD</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-fs"/> <strong>Fs</strong></td>
|
|
||||||
<td>Discussions concerning FreeBSD filesystems</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-geom"/> <strong>GEOM</strong></td>
|
|
||||||
<td>GEOM-specific discussions and implementations</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-gnome"/> <strong>Gnome</strong></td>
|
|
||||||
<td>Discussions concerning the FreeBSD GNOME project</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-hackers"/> <strong>Hackers</strong></td>
|
|
||||||
<td>General technical discussions</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-i18n"/> <strong>I18n</strong></td>
|
|
||||||
<td>FreeBSD Internationalization</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-i386"/> <strong>i386</strong></td>
|
|
||||||
<td>i386-specific issues for FreeBSD</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-ia32"/> <strong>ia32</strong></td>
|
|
||||||
<td>FreeBSD on the IA32 platform</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-ia64"/> <strong>ia64</strong></td>
|
|
||||||
<td>Porting FreeBSD to Intel's upcoming IA64 systems</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-ipfw"/> <strong>ipfw</strong></td>
|
|
||||||
<td>Technical discussion concerning the redesign of the IP firewall code</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-isdn"/> <strong>ISDN</strong></td>
|
|
||||||
<td>Development of ISDN support for FreeBSD</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-java"/> <strong>&java;</strong></td>
|
|
||||||
<td>JDK porting and application development</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-libh"/> <strong>libh</strong></td>
|
|
||||||
<td>The second generation installation and package system</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-mips"/> <strong>MIPS</strong></td>
|
|
||||||
<td>Porting FreeBSD to MIPS</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-multimedia"/> <strong>Multimedia</strong></td>
|
|
||||||
<td>Discussions about FreeBSD as a multimedia platform</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-mobile"/> <strong>Mobile</strong></td>
|
|
||||||
<td>Using FreeBSD in a mobile environment</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-mozilla"/> <strong>Mozilla</strong></td>
|
|
||||||
<td>Porting mozilla to FreeBSD</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-net"/> <strong>Net</strong></td>
|
|
||||||
<td>Networking discussion and TCP/IP source code</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-new-bus"/> <strong>New Bus</strong></td>
|
|
||||||
<td>Technical discussions on Bus Architecture</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-office"/> <strong>Office</strong></td>
|
|
||||||
<td>Office applications on FreeBSD</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-openoffice"/> <strong>OpenOffice</strong></td>
|
|
||||||
<td>Discussions concerning the FreeBSD OpenOffice and StarOffice ports</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-perl"/> <strong>Perl</strong></td>
|
|
||||||
<td>Maintenance of a number of perl-related ports</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-pf"/> <strong>PF</strong></td>
|
|
||||||
<td>Discussion and questions about the packet filter firewall system</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-platforms"/> <strong>Platforms</strong></td>
|
|
||||||
<td>Cross-platform FreeBSD issues (non-Intel FreeBSD ports)</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-policy"/> <strong>Policy</strong></td>
|
|
||||||
<td>FreeBSD core team policy decisions</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-ports-bugs"/> <strong>Ports Bugs</strong></td>
|
|
||||||
<td>Bug reports concerning FreeBSD's ports collection</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-ports"/> <strong>Ports</strong></td>
|
|
||||||
<td>Discussions concerning FreeBSD's ports collection</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-ppc"/> <strong>PPC</strong></td>
|
|
||||||
<td>Porting FreeBSD to the PowerPC</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-python"/> <strong>Python</strong></td>
|
|
||||||
<td>FreeBSD-specific Python issues</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-qa"/> <strong>QA</strong></td>
|
|
||||||
<td>Discussion of quality assurance issues</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-rc"/> <strong>rc</strong></td>
|
|
||||||
<td>Discussion related to /etc/rc.d design and implementation</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-realtime"/> <strong>Realtime</strong></td>
|
|
||||||
<td>Development of realtime extensions to FreeBSD</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-scsi"/> <strong>SCSI</strong></td>
|
|
||||||
<td>Discussions about FreeBSD's SCSI support</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-small"/> <strong>Small</strong></td>
|
|
||||||
<td>Using FreeBSD in embedded applications</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-smp"/> <strong>SMP</strong></td>
|
|
||||||
<td>FreeBSD on multi-processor platforms</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-sparc64"/> <strong>SPARC64</strong></td>
|
|
||||||
<td>Porting FreeBSD to the SPARC64</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-standards"/> <strong>Standards</strong></td>
|
|
||||||
<td>FreeBSD Conformance to the C99 and the &posix; standards</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-threads"/> <strong>Threads</strong></td>
|
|
||||||
<td>Discussion about threading models in FreeBSD, including KSE and others</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-tilera"/> <strong>Tilera</strong></td>
|
|
||||||
<td>Porting FreeBSD to the Tilera family of CPUs</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-tokenring"/> <strong>Tokenring</strong></td>
|
|
||||||
<td>Support Token Ring in FreeBSD</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-toolchain"/> <strong>Toolchain</strong></td>
|
|
||||||
<td>Maintenance of FreeBSD's integrated toolchain</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-usb"/> <strong>USB</strong></td>
|
|
||||||
<td>Discussion about FreeBSD support for USB</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-vuxml"/> <strong>VuXML</strong></td>
|
|
||||||
<td>Discussion on VuXML infrastructure</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-x11"/> <strong>X11</strong></td>
|
|
||||||
<td>Maintenance and support of X11 on FreeBSD</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-xfce"/> <strong>XFCE</strong></td>
|
|
||||||
<td>XFCE for FreeBSD — porting and maintaining</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Limited lists</h3>
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-hubs"/> <strong>Hubs</strong></td>
|
|
||||||
<td>People running mirror sites (infrastructural support)</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-install"/> <strong>Install</strong></td>
|
|
||||||
<td>Installation system development</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-wireless"/> <strong>Wireless</strong></td>
|
|
||||||
<td>802.11 stack, tools, device driver development</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><input type="checkbox" name="source"
|
|
||||||
value="freebsd-www"/> <strong>WWW</strong></td>
|
|
||||||
<td>Web site maintainers</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p><input type="submit"/></p>
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
<div id="search" xmlns="http://www.w3.org/1999/xhtml">
|
<div id="search" xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<form method="get" id="search" action="https://duckduckgo.com/">
|
<form method="get" id="search" action="https://duckduckgo.com/">
|
||||||
<h2 class="blockhide"><label for="words">&header2.word.search;</label></h2>
|
<h2 class="blockhide"><label for="words">&header2.word.search;</label></h2>
|
||||||
<input type="hidden" name="sites" value="www.FreeBSD.org,lists.FreeBSD.org,wiki.FreeBSD.org,forums.FreeBSD.org" />
|
<input type="hidden" name="sites" value="www.FreeBSD.org,docs.FreeBSD.org,lists.FreeBSD.org,wiki.FreeBSD.org,forums.FreeBSD.org" />
|
||||||
<input type="hidden" name="ka" value="v" />
|
<input type="hidden" name="ka" value="v" />
|
||||||
<input type="hidden" name="kt" value="v" />
|
<input type="hidden" name="kt" value="v" />
|
||||||
<input type="hidden" name="kh" value="1" />
|
<input type="hidden" name="kh" value="1" />
|
||||||
|
|
@ -184,7 +184,7 @@
|
||||||
|
|
||||||
<div xmlns="http://www.w3.org/1999/xhtml" id="headercontainer">
|
<div xmlns="http://www.w3.org/1999/xhtml" id="headercontainer">
|
||||||
<div id="header">
|
<div id="header">
|
||||||
&header2.logo-red.label;`
|
&header2.logo-red.label;
|
||||||
|
|
||||||
<div id="headerlogoleft">
|
<div id="headerlogoleft">
|
||||||
&header2.logo-red;
|
&header2.logo-red;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue