Bug 147833 - start using CGI.pm

r=gerv, justdave
This commit is contained in:
bbaetz%student.usyd.edu.au 2002-10-26 01:57:09 +00:00
Родитель 0a26e05e50
Коммит a81c77a9a2
12 изменённых файлов: 328 добавлений и 301 удалений

Просмотреть файл

@ -0,0 +1,149 @@
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Bradley Baetz <bbaetz@student.usyd.edu.au>
use strict;
package Bugzilla::CGI;
use CGI qw(-no_xhtml -oldstyle_urls :private_tempfiles);
use base qw(CGI);
use Bugzilla::Util;
# CGI.pm uses AUTOLOAD, but explicitly defines a DESTROY sub.
# We need to do so, too, otherwise perl dies when the object is destroyed
# and we don't have a DESTROY method (because CGI.pm's AUTOLOAD will |die|
# on getting an unknown sub to try to call)
sub DESTROY {};
sub new {
my ($invocant, @args) = @_;
my $class = ref($invocant) || $invocant;
my $self = $class->SUPER::new(@args);
# Check for errors
# All of the Bugzilla code wants to do this, so do it here instead of
# in each script
my $err = $self->cgi_error;
if ($err) {
# XXX - under mod_perl we can use the request object to
# enable the apache ErrorDocument stuff, which is localisable
# (and localised by default under apache2).
# This doesn't appear to be possible under mod_cgi.
# Under mod_perl v2, though, this happens automatically, and the
# message body is ignored.
# Note that this error block is only triggered by CGI.pm for malformed
# multipart requests, and so should never happen unless there is a
# browser bug.
# Using CGI.pm to do this means that ThrowCodeError prints the
# content-type again...
#print $self->header(-status => $err);
print "Status: $err\n";
my $vars = {};
if ($err =~ m/(\d{3})\s(.*)/) {
$vars->{http_error_code} = $1;
$vars->{http_error_string} = $2;
} else {
$vars->{http_error_string} = $err;
}
&::ThrowCodeError("cgi_error", $vars);
}
return $self;
}
# We want this sorted plus the ability to exclude certain params
sub canonicalise_query {
my ($self, @exclude) = @_;
# Reconstruct the URL by concatenating the sorted param=value pairs
my @parameters;
foreach my $key (sort($self->param())) {
# Leave this key out if it's in the exclude list
next if lsearch(\@exclude, $key) != -1;
my $esc_key = url_quote($key);
foreach my $value ($self->param($key)) {
if ($value) {
my $esc_value = url_quote($value);
push(@parameters, "$esc_key=$esc_value");
}
}
}
return join("&", @parameters);
}
1;
__END__
=head1 NAME
Bugzilla::CGI - CGI handling for Bugzilla
=head1 SYNOPSIS
use Bugzilla::CGI;
my $cgi = new Bugzilla::CGI();
=head1 DESCRIPTION
This package inherits from the standard CGI module, to provide additional
Bugzilla-specific functionality. In general, see L<the CGI.pm docs|CGI> for
documention.
=head1 CHANGES FROM L<CGI.PM|CGI>
Bugzilla::CGI has some differences from L<CGI.pm|CGI>.
=over 4
=item C<cgi_error> is automatically checked
After creating the CGI object, C<Bugzilla::CGI> automatically checks
I<cgi_error>, and throws a CodeError if a problem is detected.
=back
=head1 ADDITIONAL FUNCTIONS
I<Bugzilla::CGI> also includes additional functions.
=over 4
=item C<canonicalise_query(@exclude)>
This returns a sorted string of the paramaters, suitable for use in a url.
Values in C<@exclude> are not included in the result.
=back

Просмотреть файл

@ -40,6 +40,7 @@ use Date::Format;
use Date::Parse;
# Create a new Search
# Note that the param argument may be modified by Bugzilla::Search
sub new {
my $invocant = shift;
my $class = ref($invocant) || $invocant;
@ -55,7 +56,7 @@ sub new {
sub init {
my $self = shift;
my $fieldsref = $self->{'fields'};
my $urlstr = $self->{'url'};
my $params = $self->{'params'};
my $debug = 0;
@ -64,9 +65,6 @@ sub init {
my @wherepart;
my @having = ("(cntuseringroups = cntbugingroups OR canseeanyway)");
@fields = @$fieldsref if $fieldsref;
my %F;
my %M;
&::ParseUrlString($urlstr, \%F, \%M);
my @specialchart;
my @andlist;
@ -96,8 +94,8 @@ sub init {
}
my $minvotes;
if (defined $F{'votes'}) {
my $c = trim($F{'votes'});
if (defined $params->param('votes')) {
my $c = trim($params->param('votes'));
if ($c ne "") {
if ($c !~ /^[0-9]*$/) {
$::vars->{'value'} = $c;
@ -107,12 +105,12 @@ sub init {
}
}
if ($M{'bug_id'}) {
if ($params->param('bug_id')) {
my $type = "anyexact";
if ($F{'bugidtype'} && $F{'bugidtype'} eq 'exclude') {
if ($params->param('bugidtype') && $params->param('bugidtype') eq 'exclude') {
$type = "nowords";
}
push(@specialchart, ["bug_id", $type, join(',', @{$M{'bug_id'}})]);
push(@specialchart, ["bug_id", $type, join(',', $params->param('bug_id'))]);
}
my @legal_fields = ("product", "version", "rep_platform", "op_sys",
@ -120,33 +118,33 @@ sub init {
"assigned_to", "reporter", "component",
"target_milestone", "bug_group");
foreach my $field (keys %F) {
foreach my $field ($params->param()) {
if (lsearch(\@legal_fields, $field) != -1) {
push(@specialchart, [$field, "anyexact",
join(',', @{$M{$field}})]);
join(',', $params->param($field))]);
}
}
if ($F{'product'}) {
if ($params->param('product')) {
push(@supptables, "products products_");
push(@wherepart, "products_.id = bugs.product_id");
push(@specialchart, ["products_.name", "anyexact",
join(',',@{$M{'product'}})]);
join(',',$params->param('product'))]);
}
if ($F{'component'}) {
if ($params->param('component')) {
push(@supptables, "components components_");
push(@wherepart, "components_.id = bugs.component_id");
push(@specialchart, ["components_.name", "anyexact",
join(',',@{$M{'component'}})]);
join(',',$params->param('component'))]);
}
if ($F{'keywords'}) {
my $t = $F{'keywords_type'};
if ($params->param('keywords')) {
my $t = $params->param('keywords_type');
if (!$t || $t eq "or") {
$t = "anywords";
}
push(@specialchart, ["keywords", $t, $F{'keywords'}]);
push(@specialchart, ["keywords", $t, $params->param('keywords')]);
}
if (lsearch($fieldsref, "(SUM(ldtime.work_time)*COUNT(DISTINCT ldtime.bug_when)/COUNT(bugs.bug_id)) AS actual_time") != -1) {
@ -155,14 +153,14 @@ sub init {
}
foreach my $id ("1", "2") {
if (!defined ($F{"email$id"})) {
if (!defined ($params->param("email$id"))) {
next;
}
my $email = trim($F{"email$id"});
my $email = trim($params->param("email$id"));
if ($email eq "") {
next;
}
my $type = $F{"emailtype$id"};
my $type = $params->param("emailtype$id");
if ($type eq "exact") {
$type = "anyexact";
foreach my $name (split(',', $email)) {
@ -175,11 +173,11 @@ sub init {
my @clist;
foreach my $field ("assigned_to", "reporter", "cc", "qa_contact") {
if ($F{"email$field$id"}) {
if ($params->param("email$field$id")) {
push(@clist, $field, $type, $email);
}
}
if ($F{"emaillongdesc$id"}) {
if ($params->param("emaillongdesc$id")) {
my $table = "longdescs_";
push(@supptables, "longdescs $table");
push(@wherepart, "$table.bug_id = bugs.bug_id");
@ -197,8 +195,8 @@ sub init {
}
if (defined $F{'changedin'}) {
my $c = trim($F{'changedin'});
if (defined $params->param('changedin')) {
my $c = trim($params->param('changedin'));
if ($c ne "") {
if ($c !~ /^[0-9]*$/) {
$::vars->{'value'} = $c;
@ -209,15 +207,15 @@ sub init {
}
}
my $ref = $M{'chfield'};
my @chfield = $params->param('chfield');
if (defined $ref) {
my $which = lsearch($ref, "[Bug creation]");
if (@chfield) {
my $which = lsearch(\@chfield, "[Bug creation]");
if ($which >= 0) {
splice(@$ref, $which, 1);
splice(@chfield, $which, 1);
push(@specialchart, ["creation_ts", "greaterthan",
SqlifyDate($F{'chfieldfrom'})]);
my $to = $F{'chfieldto'};
SqlifyDate($params->param('chfieldfrom'))]);
my $to = $params->param('chfieldto');
if (defined $to) {
$to = trim($to);
if ($to ne "" && $to !~ /^now$/i) {
@ -228,18 +226,18 @@ sub init {
}
}
if (defined $ref && 0 < @$ref) {
if (@chfield) {
push(@supptables, "bugs_activity actcheck");
my @list;
foreach my $f (@$ref) {
foreach my $f (@chfield) {
push(@list, "\nactcheck.fieldid = " . &::GetFieldID($f));
}
push(@wherepart, "actcheck.bug_id = bugs.bug_id");
push(@wherepart, "(" . join(' OR ', @list) . ")");
push(@wherepart, "actcheck.bug_when >= " .
&::SqlQuote(SqlifyDate($F{'chfieldfrom'})));
my $to = $F{'chfieldto'};
&::SqlQuote(SqlifyDate($params->param('chfieldfrom'))));
my $to = $params->param('chfieldto');
if (defined $to) {
$to = trim($to);
if ($to ne "" && $to !~ /^now$/i) {
@ -247,7 +245,7 @@ sub init {
&::SqlQuote(SqlifyDate($to)));
}
}
my $value = $F{'chfieldvalue'};
my $value = $params->param('chfieldvalue');
if (defined $value) {
$value = trim($value);
if ($value ne "") {
@ -259,12 +257,12 @@ sub init {
foreach my $f ("short_desc", "long_desc", "bug_file_loc",
"status_whiteboard") {
if (defined $F{$f}) {
my $s = trim($F{$f});
if (defined $params->param($f)) {
my $s = trim($params->param($f));
if ($s ne "") {
my $n = $f;
my $q = &::SqlQuote($s);
my $type = $F{$f . "_type"};
my $type = $params->param($f . "_type");
push(@specialchart, [$f, $type, $s]);
}
}
@ -516,7 +514,7 @@ sub init {
if ($t eq "anywords") {
$term = $haveawordterm;
} elsif ($t eq "allwords") {
$ref = $funcsbykey{",$t"};
my $ref = $funcsbykey{",$t"};
&$ref;
if ($term && $haveawordterm) {
$term = "(($term) AND $haveawordterm)";
@ -533,7 +531,7 @@ sub init {
my $table = "dependson_" . $chartid;
push(@supptables, "dependencies $table");
$ff = "$table.$f";
$ref = $funcsbykey{",$t"};
my $ref = $funcsbykey{",$t"};
&$ref;
push(@wherepart, "$table.blocked = bugs.bug_id");
},
@ -542,7 +540,7 @@ sub init {
my $table = "blocked_" . $chartid;
push(@supptables, "dependencies $table");
$ff = "$table.$f";
$ref = $funcsbykey{",$t"};
my $ref = $funcsbykey{",$t"};
&$ref;
push(@wherepart, "$table.dependson = bugs.bug_id");
},
@ -672,9 +670,9 @@ sub init {
# first we delete any sign of "Chart #-1" from the HTML form hash
# since we want to guarantee the user didn't hide something here
my @badcharts = grep /^(field|type|value)-1-/, (keys %F);
my @badcharts = grep /^(field|type|value)-1-/, $params->param();
foreach my $field (@badcharts) {
delete $F{$field};
$params->delete($field);
}
# now we take our special chart and stuff it into the form hash
@ -683,11 +681,11 @@ sub init {
foreach my $ref (@specialchart) {
my $col = 0;
while (@$ref) {
$F{"field$chart-$row-$col"} = shift(@$ref);
$F{"type$chart-$row-$col"} = shift(@$ref);
$F{"value$chart-$row-$col"} = shift(@$ref);
$params->param("field$chart-$row-$col", shift(@$ref));
$params->param("type$chart-$row-$col", shift(@$ref));
$params->param("value$chart-$row-$col", shift(@$ref));
if ($debug) {
print qq{<p>$F{"field$chart-$row-$col"} | $F{"type$chart-$row-$col"} | $F{"value$chart-$row-$col"}*</p>\n};
print qq{<p>$params->param("field$chart-$row-$col") | $params->param("type$chart-$row-$col") | $params->param("value$chart-$row-$col")*</p>\n};
}
$col++;
@ -786,19 +784,19 @@ sub init {
$row = 0;
for ($chart=-1 ;
$chart < 0 || exists $F{"field$chart-0-0"} ;
$chart < 0 || $params->param("field$chart-0-0") ;
$chart++) {
$chartid = $chart >= 0 ? $chart : "";
for ($row = 0 ;
exists $F{"field$chart-$row-0"} ;
$params->param("field$chart-$row-0") ;
$row++) {
my @orlist;
for (my $col = 0 ;
exists $F{"field$chart-$row-$col"} ;
$params->param("field$chart-$row-$col") ;
$col++) {
$f = $F{"field$chart-$row-$col"} || "noop";
$t = $F{"type$chart-$row-$col"} || "noop";
$v = $F{"value$chart-$row-$col"};
$f = $params->param("field$chart-$row-$col") || "noop";
$t = $params->param("type$chart-$row-$col") || "noop";
$v = $params->param("value$chart-$row-$col");
$v = "" if !defined $v;
$v = trim($v);
if ($f eq "noop" || $t eq "noop" || $v eq "") {
@ -841,8 +839,8 @@ sub init {
}
else {
# This field and this type don't work together.
$::vars->{'field'} = $F{"field$chart-$row-$col"};
$::vars->{'type'} = $F{"type$chart-$row-$col"};
$::vars->{'field'} = $params->param("field$chart-$row-$col");
$::vars->{'type'} = $params->param("type$chart-$row-$col");
&::ThrowCodeError("field_type_mismatch");
}
}

Просмотреть файл

@ -27,7 +27,7 @@ package Bugzilla::Util;
use base qw(Exporter);
@Bugzilla::Util::EXPORT = qw(is_tainted trick_taint detaint_natural
html_quote value_quote
html_quote url_quote value_quote
lsearch max min
trim);
@ -64,6 +64,13 @@ sub html_quote {
return $var;
}
# This orignally came from CGI.pm, by Lincoln D. Stein
sub url_quote {
my ($toencode) = (@_);
$toencode =~ s/([^a-zA-Z0-9_\-.])/uc sprintf("%%%02x",ord($1))/eg;
return $toencode;
}
sub value_quote {
my ($var) = (@_);
$var =~ s/\&/\&amp;/g;
@ -134,6 +141,7 @@ Bugzilla::Util - Generic utility functions for bugzilla
# Functions for quoting
html_quote($var);
url_quote($var);
value_quote($var);
# Functions for searching
@ -200,6 +208,10 @@ be done in the template where possible.
Returns a value quoted for use in HTML, with &, E<lt>, E<gt>, and E<34> being
replaced with their appropriate HTML entities.
=item C<url_quote($val)>
Quotes characters so that they may be included as part of a url.
=item C<value_quote($val)>
As well as escaping html like C<html_quote>, this routine converts newlines

Просмотреть файл

@ -46,7 +46,6 @@ use Bugzilla::Config;
sub CGI_pl_sillyness {
my $zz;
$zz = %::MFORM;
$zz = %::dontchange;
}
@ -83,151 +82,6 @@ sub url_decode {
return $todecode;
}
# Quotify a string, suitable for putting into a URL.
sub url_quote {
my($toencode) = (@_);
$toencode=~s/([^a-zA-Z0-9_\-.])/uc sprintf("%%%02x",ord($1))/eg;
return $toencode;
}
sub ParseUrlString {
my ($buffer, $f, $m) = (@_);
undef %$f;
undef %$m;
my %isnull;
# We must make sure that the CGI params remain tainted.
# This means that if for some reason you want to make this code
# use a regexp and $1, $2, ... (or use a helper function which does so)
# you must |use re 'taint'| _and_ make sure that you don't run into
# http://bugs.perl.org/perlbug.cgi?req=bug_id&bug_id=20020704.001
my @args = split('&', $buffer);
foreach my $arg (@args) {
my ($name, $value) = split('=', $arg, 2);
$value = '' if not defined $value;
$name = url_decode($name);
$value = url_decode($value);
if ($value ne "") {
if (defined $f->{$name}) {
$f->{$name} .= $value;
my $ref = $m->{$name};
push @$ref, $value;
} else {
$f->{$name} = $value;
$m->{$name} = [$value];
}
} else {
$isnull{$name} = 1;
}
}
if (%isnull) {
foreach my $name (keys(%isnull)) {
if (!defined $f->{$name}) {
$f->{$name} = "";
$m->{$name} = [];
}
}
}
}
sub ProcessFormFields {
my ($buffer) = (@_);
return ParseUrlString($buffer, \%::FORM, \%::MFORM);
}
sub ProcessMultipartFormFields {
my ($boundary) = @_;
# Initialize variables that store whether or not we are parsing a header,
# the name of the part we are parsing, and its value (which is incomplete
# until we finish parsing the part).
my $inheader = 1;
my $fieldname = "";
my $fieldvalue = "";
# Read the input stream line by line and parse it into a series of parts,
# each one containing a single form field and its value and each one
# separated from the next by the value of $boundary.
my $remaining = $ENV{"CONTENT_LENGTH"};
while ($remaining > 0 && ($_ = <STDIN>)) {
$remaining -= length($_);
# If the current input line is a boundary line, save the previous
# form value and reset the storage variables.
if ($_ =~ m/^-*\Q$boundary\E/) {
if ( $fieldname ) {
chomp($fieldvalue);
$fieldvalue =~ s/\r$//;
if ( defined $::FORM{$fieldname} ) {
$::FORM{$fieldname} .= $fieldvalue;
push @{$::MFORM{$fieldname}}, $fieldvalue;
} else {
$::FORM{$fieldname} = $fieldvalue;
$::MFORM{$fieldname} = [$fieldvalue];
}
}
$inheader = 1;
$fieldname = "";
$fieldvalue = "";
# If the current input line is a header line, look for a blank line
# (meaning the end of the headers), a Content-Disposition header
# (containing the field name and, for uploaded file parts, the file
# name), or a Content-Type header (containing the content type for
# file parts).
} elsif ( $inheader ) {
if (m/^\s*$/) {
$inheader = 0;
} elsif (m/^Content-Disposition:\s*form-data\s*;\s*name\s*=\s*"([^\"]+)"/i) {
$fieldname = $1;
if (m/;\s*filename\s*=\s*"([^\"]+)"/i) {
$::FILE{$fieldname}->{'filename'} = $1;
}
} elsif ( m|^Content-Type:\s*([^/]+/[^\s;]+)|i ) {
$::FILE{$fieldname}->{'contenttype'} = $1;
}
# If the current input line is neither a boundary line nor a header,
# it must be part of the field value, so append it to the value.
} else {
$fieldvalue .= $_;
}
}
}
sub CanonicaliseParams {
my ($buffer, $exclude) = (@_);
my %pieces;
# Split the buffer up into key/value pairs, and store the non-empty ones
my @args = split('&', $buffer);
foreach my $arg (@args) {
my ($name, $value) = split('=', $arg, 2);
if ($value) {
push(@{$pieces{$name}}, $value);
}
}
# Reconstruct the URL by concatenating the sorted param=value pairs
my @parameters;
foreach my $key (sort keys %pieces) {
# Leave this key out if it's in the exclude list
next if lsearch($exclude, $key) != -1;
foreach my $value (@{$pieces{$key}}) {
push(@parameters, "$key=$value");
}
}
return join("&", @parameters);
}
# check and see if a given field exists, is non-empty, and is set to a
# legal value. assume a browser bug and abort appropriately if not.
# if $legalsRef is not passed, just check to make sure the value exists and
@ -1020,52 +874,31 @@ sub GetBugActivity {
return(\@operations, $incomplete_data);
}
############# Live code below here (that is, not subroutine defs) #############
$| = 1;
use Bugzilla::CGI();
# Uncommenting this next line can help debugging.
# print "Content-type: text/html\n\nHello mom\n";
# XXX - mod_perl, this needs to move into all the scripts individually
# Once we do that, look into setting DISABLE_UPLOADS, and overriding
# on a per-script basis
$::cgi = new Bugzilla::CGI();
# foreach my $k (sort(keys %ENV)) {
# print "$k $ENV{$k}<br>\n";
# }
# Set up stuff for compatibility with the old CGI.pl code
# This code will be removed as soon as possible, in favour of
# using the CGI.pm stuff directly
if (defined $ENV{"REQUEST_METHOD"}) {
if ($ENV{"REQUEST_METHOD"} eq "GET") {
if (defined $ENV{"QUERY_STRING"}) {
$::buffer = $ENV{"QUERY_STRING"};
} else {
$::buffer = "";
}
ProcessFormFields $::buffer;
} else {
if (exists($ENV{"CONTENT_TYPE"}) && $ENV{"CONTENT_TYPE"} =~
m@multipart/form-data; boundary=\s*([^; ]+)@) {
ProcessMultipartFormFields($1);
$::buffer = "";
} else {
read STDIN, $::buffer, $ENV{"CONTENT_LENGTH"} ||
die "Couldn't get form data";
ProcessFormFields $::buffer;
}
}
# XXX - mod_perl - reset these between runs
foreach my $name ($::cgi->param()) {
my @val = $::cgi->param($name);
$::FORM{$name} = join('', @val);
$::MFORM{$name} = \@val;
}
if (defined $ENV{"HTTP_COOKIE"}) {
# Don't trust anything which came in as a cookie
use re 'taint';
foreach my $pair (split(/;/, $ENV{"HTTP_COOKIE"})) {
$pair = trim($pair);
if ($pair =~ /^([^=]*)=(.*)$/) {
if (!exists($::COOKIE{$1})) {
$::COOKIE{$1} = $2;
}
} else {
$::COOKIE{$pair} = "";
}
}
$::buffer = $::cgi->query_string();
foreach my $name ($::cgi->cookie()) {
$::COOKIE{$name} = $::cgi->cookie($name);
}
1;

Просмотреть файл

@ -33,16 +33,11 @@ use strict;
use lib qw(.);
use vars qw(
$cgi
$template
$vars
);
# Win32 specific hack to avoid a hang when creating/showing an attachment
if ($^O eq 'MSWin32') {
binmode(STDIN);
binmode(STDOUT);
}
# Include the Bugzilla CGI and general utility library.
require "CGI.pl";
@ -89,12 +84,12 @@ elsif ($action eq "insert")
ValidateBugID($::FORM{'bugid'});
ValidateComment($::FORM{'comment'});
validateFilename();
validateData();
validateDescription();
validateIsPatch();
my $data = validateData();
validateDescription();
validateContentType() unless $::FORM{'ispatch'};
validateObsolete() if $::FORM{'obsolete'};
insert();
insert($data);
}
elsif ($action eq "edit")
{
@ -198,13 +193,14 @@ sub validateContentType
}
elsif ($::FORM{'contenttypemethod'} eq 'autodetect')
{
my $contenttype = $cgi->uploadInfo($cgi->param('data'))->{'Content-Type'};
# The user asked us to auto-detect the content type, so use the type
# specified in the HTTP request headers.
if ( !$::FILE{'data'}->{'contenttype'} )
if ( !$contenttype )
{
ThrowUserError("missing_content_type");
}
$::FORM{'contenttype'} = $::FILE{'data'}->{'contenttype'};
$::FORM{'contenttype'} = $contenttype;
}
elsif ($::FORM{'contenttypemethod'} eq 'list')
{
@ -247,29 +243,40 @@ sub validatePrivate
sub validateData
{
$::FORM{'data'}
my $maxsize = $::FORM{'ispatch'} ? Param('maxpatchsize') : Param('maxattachmentsize');
$maxsize *= 1024; # Convert from K
my $fh = $cgi->upload('data');
my $data;
# We could get away with reading only as much as required, except that then
# we wouldn't have a size to print to the error handler below.
{
# enable 'slurp' mode
local $/;
$data = <$fh>;
}
$data
|| ThrowUserError("zero_length_file");
my $len = length($::FORM{'data'});
my $maxpatchsize = Param('maxpatchsize');
my $maxattachmentsize = Param('maxattachmentsize');
# Makes sure the attachment does not exceed either the "maxpatchsize" or
# the "maxattachmentsize" parameter.
if ( $::FORM{'ispatch'} && $maxpatchsize && $len > $maxpatchsize*1024 )
{
$vars->{'filesize'} = sprintf("%.0f", $len/1024);
ThrowUserError("patch_too_large");
} elsif ( !$::FORM{'ispatch'} && $maxattachmentsize && $len > $maxattachmentsize*1024 ) {
$vars->{'filesize'} = sprintf("%.0f", $len/1024);
ThrowUserError("file_too_large");
# Make sure the attachment does not exceed the maximum permitted size
my $len = length($data);
if ($maxsize && $len > $maxsize) {
$vars->{'filesize'} = sprintf("%.0f", $len/1024);
if ( $::FORM{'ispatch'} ) {
ThrowUserError("patch_too_large");
} else {
ThrowUserError("file_too_large");
}
}
return $data;
}
sub validateFilename
{
defined $::FILE{'data'}
defined $cgi->upload('data')
|| ThrowUserError("file_not_specified");
}
@ -428,13 +435,15 @@ sub enter
sub insert
{
my ($data) = @_;
# Insert a new attachment into the database.
# Escape characters in strings that will be used in SQL statements.
my $filename = SqlQuote($::FILE{'data'}->{'filename'});
my $filename = SqlQuote($cgi->param('data'));
my $description = SqlQuote($::FORM{'description'});
my $contenttype = SqlQuote($::FORM{'contenttype'});
my $thedata = SqlQuote($::FORM{'data'});
my $thedata = SqlQuote($data);
my $isprivate = $::FORM{'isprivate'} ? 1 : 0;
# Insert the attachment into the database.

Просмотреть файл

@ -33,7 +33,7 @@ use strict;
use lib qw(.);
use vars qw($template $vars);
use vars qw($cgi $template $vars);
use Bugzilla::Search;
@ -229,13 +229,17 @@ if ($::FORM{'cmdtype'} eq "runnamed") {
$::FORM{'remaction'} = "run";
}
# The params object to use for the actual query itsself
# This will be modified, so make a copy
my $params = new Bugzilla::CGI($cgi);
# Take appropriate action based on user's request.
if ($::FORM{'cmdtype'} eq "dorem") {
if ($::FORM{'remaction'} eq "run") {
$::buffer = LookupNamedQuery($::FORM{"namedcmd"});
my $query = LookupNamedQuery($::FORM{"namedcmd"});
$vars->{'title'} = "Bug List: $::FORM{'namedcmd'}";
ProcessFormFields($::buffer);
$order = $::FORM{'order'} || $order;
$params = new Bugzilla::CGI($query);
$order = $params->param('order') || $order;
}
elsif ($::FORM{'remaction'} eq "load") {
my $url = "query.cgi?" . LookupNamedQuery($::FORM{"namedcmd"});
@ -391,14 +395,14 @@ DefineColumn("percentage_complete","(100*((SUM(ldtime.work_time)*COUNT(DISTINCT
# Determine the columns that will be displayed in the bug list via the
# columnlist CGI parameter, the user's preferences, or the default.
my @displaycolumns = ();
if (defined $::FORM{'columnlist'}) {
if ($::FORM{'columnlist'} eq "all") {
if (defined $params->param('columnlist')) {
if ($params->param('columnlist') eq "all") {
# If the value of the CGI parameter is "all", display all columns,
# but remove the redundant "summaryfull" column.
@displaycolumns = grep($_ ne 'summaryfull', keys(%$columns));
}
else {
@displaycolumns = split(/[ ,]+/, $::FORM{'columnlist'});
@displaycolumns = split(/[ ,]+/, $params->param('columnlist'));
}
}
elsif (defined $::COOKIE{'COLUMNLIST'}) {
@ -424,9 +428,10 @@ else {
# number of votes and the votes column is not already on the list.
# Some versions of perl will taint 'votes' if this is done as a single
# statement, because $::FORM{'votes'} is tainted at this point
$::FORM{'votes'} ||= "";
if (trim($::FORM{'votes'}) && !grep($_ eq 'votes', @displaycolumns)) {
# statement, because the votes param is tainted at this point
my $votes = $params->param('votes');
$votes ||= "";
if (trim($votes) && !grep($_ eq 'votes', @displaycolumns)) {
push(@displaycolumns, 'votes');
}
@ -479,7 +484,7 @@ my @selectnames = map($columns->{$_}->{'name'}, @selectcolumns);
# Generate the basic SQL query that will be used to generate the bug list.
my $search = new Bugzilla::Search('fields' => \@selectnames,
'url' => $::buffer);
'params' => $params);
my $query = $search->getSQL();
@ -489,7 +494,7 @@ my $query = $search->getSQL();
# Add to the query some instructions for sorting the bug list.
if ($::COOKIE{'LASTORDER'} && (!$order || $order =~ /^reuse/i)) {
$order = url_decode($::COOKIE{'LASTORDER'});
$order = $::COOKIE{'LASTORDER'};
$order_from_cookie = 1;
}

Просмотреть файл

@ -179,6 +179,13 @@ sub have_vers {
$vnum = ${"${pkg}::VERSION"} || ${"${pkg}::Version"} || 0;
$vnum = -1 if $@;
# CGI's versioning scheme went 2.75, 2.751, 2.752, 2.753, 2.76
# That breaks the standard version tests, so we need to manually correct
# the version
if ($pkg eq 'CGI' && $vnum =~ /(2\.7\d)(\d+)/) {
$vnum = $1 . "." . $2;
}
if ($vnum eq "-1") { # string compare just in case it's non-numeric
$vstr = "not found";
}
@ -201,8 +208,8 @@ my $modules = [
version => '1.52'
},
{
name => 'CGI::Carp',
version => '0'
name => 'CGI',
version => '2.88'
},
{
name => 'Data::Dumper',

Просмотреть файл

@ -1584,7 +1584,7 @@ $::template ||= Template->new(
# characters NOT in the regex set: [a-zA-Z0-9_\-.]. The 'uri'
# filter should be used for a full URL that may have
# characters that need encoding.
url_quote => \&url_quote ,
url_quote => \&Bugzilla::Util::url_quote,
# In CSV, quotes are doubled, and any value containing a quote or a
# comma is enclosed in quotes.

Просмотреть файл

@ -697,7 +697,11 @@ if (Param("usebugaliases") && defined($::FORM{'alias'})) {
# with that value.
DoComma();
$::query .= "alias = ";
$::query .= ($alias eq "") ? "NULL" : SqlQuote($alias);
if ($alias eq "") {
$::query .= "NULL";
} else {
$::query .= SqlQuote($alias);
}
}
}

Просмотреть файл

@ -26,7 +26,7 @@ use lib ".";
require "CGI.pl";
use vars qw($template $vars);
use vars qw($cgi $template $vars);
use Bugzilla::Search;
@ -77,11 +77,13 @@ my @axis_fields = ($row_field, $col_field, $tbl_field);
my @selectnames = map($columns{$_}, @axis_fields);
# Clone the params, so that Bugzilla::Search can modify them
my $params = new Bugzilla::CGI($cgi);
my $search = new Bugzilla::Search('fields' => \@selectnames,
'url' => $::buffer);
'params' => $params);
my $query = $search->getSQL();
SendSQL($query, $::userid);
SendSQL($query);
# We have a hash of hashes for the data itself, and a hash to hold the
# row/col/table names.
@ -108,12 +110,14 @@ $vars->{'names'} = \%names;
$vars->{'data'} = \%data;
$vars->{'time'} = time();
$::buffer =~ s/format=[^&]*&?//g;
$cgi->delete('format');
# Calculate the base query URL for the hyperlinked numbers
$vars->{'buglistbase'} = CanonicaliseParams($::buffer,
["x_axis_field", "y_axis_field", "z_axis_field", @axis_fields]);
$vars->{'buffer'} = $::buffer;
$vars->{'querybase'} = $cgi->canonicalise_query("x_axis_field",
"y_axis_field",
"z_axis_field",
@axis_fields);
$vars->{'query'} = $cgi->query_string();
# Generate and return the result from the appropriate template.
my $format = GetFormat("reports/report", $::FORM{'format'}, $::FORM{'ctype'});

Просмотреть файл

@ -47,6 +47,11 @@
[% ELSIF error == "attachment_already_obsolete" %]
Attachment #[% attachid FILTER html %] ([% description FILTER html %])
is already obsolete.
[% ELSIF error == "cgi_error" %]
[% title = "CGI Error" %]
Bugzilla has had trouble interpreting your CGI request;
[%+ Param('browserbugmessage') %]
[% ELSIF error == "chart_data_not_generated" %]
The tool which gathers bug counts has not been run yet.
@ -236,7 +241,7 @@
<pre>
Variables:
[% FOREACH key = variables.keys %]
[%+ key %]: [%+ variables.$key %]
[%+ key FILTER html %]: [%+ variables.$key FILTER html %]
[% END %]
</pre>
[% END %]

Просмотреть файл

@ -21,7 +21,8 @@
#%]
[%# INTERFACE:
# basequery: The base query for this table, in URL form
# querybase: The base query for this table, in URL form
# query: The query for this table, in URL form
# data: hash of hash of hash of numbers. Bug counts.
# names: hash of hash of strings. Names of tables, rows and columns.
# col_field: string. Name of the field being plotted as columns.
@ -149,7 +150,7 @@
[% col_idx = 1 - col_idx %]
<td class="[% classes.$row_idx.$col_idx %]" align="center">
[% IF data.$tbl.$col.$row AND data.$tbl.$col.$row > 0 %]
<a href="buglist.cgi?[% buglistbase %]&
<a href="buglist.cgi?[% querybase FILTER html %]&amp;
[% tbl_field FILTER url_quote %]=[% tbl FILTER url_quote %]&amp;
[% row_field FILTER url_quote %]=[% row FILTER url_quote %]&amp;
[% col_field FILTER url_quote %]=[% col FILTER url_quote %]">
@ -160,7 +161,7 @@
</td>
[% END %]
<td class="ttotal" align="right">
<a href="buglist.cgi?[% buglistbase %]&
<a href="buglist.cgi?[% querybase FILTER html %]&amp;
[% tbl_field FILTER url_quote %]=[% tbl FILTER url_quote %]&amp;
[% row_field FILTER url_quote %]=[% row FILTER url_quote %]">
[% row_total %]</a>
@ -178,7 +179,7 @@
[% NEXT IF col == "" %]
<td class="ttotal" align="center">
<a href="buglist.cgi?[% buglistbase %]&
<a href="buglist.cgi?[% querybase FILTER html %]&amp;
[% tbl_field FILTER url_quote %]=[% tbl FILTER url_quote %]&amp;
[% col_field FILTER url_quote %]=[% col FILTER url_quote %]">
[% col_totals.$col %]</a>
@ -187,7 +188,7 @@
[% END %]
<td class="ttotal" align="right">
<strong>
<a href="buglist.cgi?[% buglistbase %]">[% grand_total %]</a>
<a href="buglist.cgi?[% querybase FILTER html %]">[% grand_total %]</a>
</strong>
</td>
</tr>
@ -202,7 +203,7 @@
[% END %]
<a href="query.cgi?[% buffer %]&format=report-table">Edit this report</a>
<a href="query.cgi?[% query FILTER html %]&amp;format=report-table">Edit this report</a>
</div>
<br>