summaryrefslogtreecommitdiffstats
path: root/chart.cgi
diff options
context:
space:
mode:
Diffstat (limited to 'chart.cgi')
-rwxr-xr-xchart.cgi402
1 files changed, 209 insertions, 193 deletions
diff --git a/chart.cgi b/chart.cgi
index 36357cb3c..9ea747fce 100755
--- a/chart.cgi
+++ b/chart.cgi
@@ -47,27 +47,28 @@ use Bugzilla::Token;
# when preparing Bugzilla for mod_perl, this script used these
# variables in so many subroutines that it was easier to just
# make them globals.
-local our $cgi = Bugzilla->cgi;
+local our $cgi = Bugzilla->cgi;
local our $template = Bugzilla->template;
-local our $vars = {};
+local our $vars = {};
my $dbh = Bugzilla->dbh;
$cgi->content_security_policy(report_only => 0);
my $user = Bugzilla->login(LOGIN_REQUIRED);
if (!Bugzilla->feature('new_charts')) {
- ThrowCodeError('feature_disabled', { feature => 'new_charts' });
+ ThrowCodeError('feature_disabled', {feature => 'new_charts'});
}
# Go back to query.cgi if we are adding a boolean chart parameter.
if (grep(/^cmd-/, $cgi->param())) {
- my $params = $cgi->canonicalise_query("format", "ctype", "action");
- print $cgi->redirect("query.cgi?format=" . $cgi->param('query_format') .
- ($params ? "&$params" : ""));
- exit;
+ my $params = $cgi->canonicalise_query("format", "ctype", "action");
+ print $cgi->redirect("query.cgi?format="
+ . $cgi->param('query_format')
+ . ($params ? "&$params" : ""));
+ exit;
}
-my $action = $cgi->param('action');
+my $action = $cgi->param('action');
my $series_id = $cgi->param('series_id');
$vars->{'doc_section'} = 'reporting.html#charts';
@@ -77,284 +78,299 @@ $vars->{'doc_section'} = 'reporting.html#charts';
# series_id they apply to (e.g. subscribe, unsubscribe).
my @actions = grep(/^action-/, $cgi->param());
if ($actions[0] && $actions[0] =~ /^action-([^\d]+)(\d*)$/) {
- $action = $1;
- $series_id = $2 if $2;
+ $action = $1;
+ $series_id = $2 if $2;
}
$action ||= "assemble";
# Go to buglist.cgi if we are doing a search.
if ($action eq "search") {
- my $params = $cgi->canonicalise_query("format", "ctype", "action");
- print $cgi->redirect("buglist.cgi" . ($params ? "?$params" : ""));
- exit;
+ my $params = $cgi->canonicalise_query("format", "ctype", "action");
+ print $cgi->redirect("buglist.cgi" . ($params ? "?$params" : ""));
+ exit;
}
-$user->in_group(Bugzilla->params->{"chartgroup"})
- || ThrowUserError("auth_failure", {group => Bugzilla->params->{"chartgroup"},
- action => "use",
- object => "charts"});
+$user->in_group(Bugzilla->params->{"chartgroup"}) || ThrowUserError(
+ "auth_failure",
+ {
+ group => Bugzilla->params->{"chartgroup"},
+ action => "use",
+ object => "charts"
+ }
+);
# Only admins may create public queries
$user->in_group('admin') || $cgi->delete('public');
# All these actions relate to chart construction.
if ($action =~ /^(assemble|add|remove|sum|subscribe|unsubscribe)$/) {
- # These two need to be done before the creation of the Chart object, so
- # that the changes they make will be reflected in it.
- if ($action =~ /^subscribe|unsubscribe$/) {
- detaint_natural($series_id) || ThrowCodeError("invalid_series_id");
- my $series = new Bugzilla::Series($series_id);
- $series->$action($user->id);
- }
-
- my $chart = new Bugzilla::Chart($cgi);
-
- if ($action =~ /^remove|sum$/) {
- $chart->$action(getSelectedLines());
- }
- elsif ($action eq "add") {
- my @series_ids = getAndValidateSeriesIDs();
- $chart->add(@series_ids);
- }
- view($chart);
+ # These two need to be done before the creation of the Chart object, so
+ # that the changes they make will be reflected in it.
+ if ($action =~ /^subscribe|unsubscribe$/) {
+ detaint_natural($series_id) || ThrowCodeError("invalid_series_id");
+ my $series = new Bugzilla::Series($series_id);
+ $series->$action($user->id);
+ }
+
+ my $chart = new Bugzilla::Chart($cgi);
+
+ if ($action =~ /^remove|sum$/) {
+ $chart->$action(getSelectedLines());
+ }
+ elsif ($action eq "add") {
+ my @series_ids = getAndValidateSeriesIDs();
+ $chart->add(@series_ids);
+ }
+
+ view($chart);
}
elsif ($action eq "plot") {
- plot();
+ plot();
}
elsif ($action eq "wrap") {
- # For CSV "wrap", we go straight to "plot".
- if ($cgi->param('ctype') && $cgi->param('ctype') eq "csv") {
- plot();
- }
- else {
- wrap();
- }
+
+ # For CSV "wrap", we go straight to "plot".
+ if ($cgi->param('ctype') && $cgi->param('ctype') eq "csv") {
+ plot();
+ }
+ else {
+ wrap();
+ }
}
elsif ($action eq "create") {
- assertCanCreate($cgi);
- my $token = $cgi->param('token');
- check_hash_token($token, ['create-series']);
+ assertCanCreate($cgi);
+ my $token = $cgi->param('token');
+ check_hash_token($token, ['create-series']);
- my $series = new Bugzilla::Series($cgi);
+ my $series = new Bugzilla::Series($cgi);
- ThrowUserError("series_already_exists", {'series' => $series})
- if $series->existsInDatabase;
+ ThrowUserError("series_already_exists", {'series' => $series})
+ if $series->existsInDatabase;
- $series->writeToDatabase();
- $vars->{'message'} = "series_created";
- $vars->{'series'} = $series;
+ $series->writeToDatabase();
+ $vars->{'message'} = "series_created";
+ $vars->{'series'} = $series;
- my $chart = new Bugzilla::Chart($cgi);
- view($chart);
+ my $chart = new Bugzilla::Chart($cgi);
+ view($chart);
}
elsif ($action eq "edit") {
- my $series = assertCanEdit($series_id);
- edit($series);
+ my $series = assertCanEdit($series_id);
+ edit($series);
}
elsif ($action eq "alter") {
- my $series = assertCanEdit($series_id);
- my $token = $cgi->param('token');
- check_hash_token($token, [$series->id, $series->name]);
- # XXX - This should be replaced by $series->set_foo() methods.
- $series = new Bugzilla::Series($cgi);
-
- # We need to check if there is _another_ series in the database with
- # our (potentially new) name. So we call existsInDatabase() to see if
- # the return value is us or some other series we need to avoid stomping
- # on.
- my $id_of_series_in_db = $series->existsInDatabase();
- if (defined($id_of_series_in_db) &&
- $id_of_series_in_db != $series->{'series_id'})
- {
- ThrowUserError("series_already_exists", {'series' => $series});
- }
-
- $series->writeToDatabase();
- $vars->{'changes_saved'} = 1;
-
- edit($series);
+ my $series = assertCanEdit($series_id);
+ my $token = $cgi->param('token');
+ check_hash_token($token, [$series->id, $series->name]);
+
+ # XXX - This should be replaced by $series->set_foo() methods.
+ $series = new Bugzilla::Series($cgi);
+
+ # We need to check if there is _another_ series in the database with
+ # our (potentially new) name. So we call existsInDatabase() to see if
+ # the return value is us or some other series we need to avoid stomping
+ # on.
+ my $id_of_series_in_db = $series->existsInDatabase();
+ if (defined($id_of_series_in_db)
+ && $id_of_series_in_db != $series->{'series_id'})
+ {
+ ThrowUserError("series_already_exists", {'series' => $series});
+ }
+
+ $series->writeToDatabase();
+ $vars->{'changes_saved'} = 1;
+
+ edit($series);
}
elsif ($action eq "confirm-delete") {
- $vars->{'series'} = assertCanEdit($series_id);
+ $vars->{'series'} = assertCanEdit($series_id);
- print $cgi->header();
- $template->process("reports/delete-series.html.tmpl", $vars)
- || ThrowTemplateError($template->error());
+ print $cgi->header();
+ $template->process("reports/delete-series.html.tmpl", $vars)
+ || ThrowTemplateError($template->error());
}
elsif ($action eq "delete") {
- my $series = assertCanEdit($series_id);
- my $token = $cgi->param('token');
- check_hash_token($token, [$series->id, $series->name]);
-
- $dbh->bz_start_transaction();
-
- $series->remove_from_db();
- # Remove (sub)categories which no longer have any series.
- foreach my $cat (qw(category subcategory)) {
- my $is_used = $dbh->selectrow_array("SELECT COUNT(*) FROM series WHERE $cat = ?",
- undef, $series->{"${cat}_id"});
- if (!$is_used) {
- $dbh->do('DELETE FROM series_categories WHERE id = ?',
- undef, $series->{"${cat}_id"});
- }
+ my $series = assertCanEdit($series_id);
+ my $token = $cgi->param('token');
+ check_hash_token($token, [$series->id, $series->name]);
+
+ $dbh->bz_start_transaction();
+
+ $series->remove_from_db();
+
+ # Remove (sub)categories which no longer have any series.
+ foreach my $cat (qw(category subcategory)) {
+ my $is_used
+ = $dbh->selectrow_array("SELECT COUNT(*) FROM series WHERE $cat = ?",
+ undef, $series->{"${cat}_id"});
+ if (!$is_used) {
+ $dbh->do('DELETE FROM series_categories WHERE id = ?',
+ undef, $series->{"${cat}_id"});
}
- $dbh->bz_commit_transaction();
+ }
+ $dbh->bz_commit_transaction();
- $vars->{'message'} = "series_deleted";
- $vars->{'series'} = $series;
- view();
+ $vars->{'message'} = "series_deleted";
+ $vars->{'series'} = $series;
+ view();
}
elsif ($action eq "convert_search") {
- my $saved_search = $cgi->param('series_from_search') || '';
- my ($query) = grep { $_->name eq $saved_search } @{ $user->queries };
- my $url = '';
- if ($query) {
- my $params = new Bugzilla::CGI($query->edit_link);
- # These two parameters conflict with the one below.
- $url = $params->canonicalise_query('format', 'query_format');
- $url = '&' . html_quote($url);
- }
- print $cgi->redirect(-location => Bugzilla->localconfig->{urlbase} . "query.cgi?format=create-series$url");
+ my $saved_search = $cgi->param('series_from_search') || '';
+ my ($query) = grep { $_->name eq $saved_search } @{$user->queries};
+ my $url = '';
+ if ($query) {
+ my $params = new Bugzilla::CGI($query->edit_link);
+
+ # These two parameters conflict with the one below.
+ $url = $params->canonicalise_query('format', 'query_format');
+ $url = '&' . html_quote($url);
+ }
+ print $cgi->redirect(-location => Bugzilla->localconfig->{urlbase}
+ . "query.cgi?format=create-series$url");
}
else {
- ThrowUserError('unknown_action', {action => $action});
+ ThrowUserError('unknown_action', {action => $action});
}
exit;
# Find any selected series and return either the first or all of them.
sub getAndValidateSeriesIDs {
- my @series_ids = grep(/^\d+$/, $cgi->param("name"));
+ my @series_ids = grep(/^\d+$/, $cgi->param("name"));
- return wantarray ? @series_ids : $series_ids[0];
+ return wantarray ? @series_ids : $series_ids[0];
}
# Return a list of IDs of all the lines selected in the UI.
sub getSelectedLines {
- my @ids = map { /^select(\d+)$/ ? $1 : () } $cgi->param();
+ my @ids = map { /^select(\d+)$/ ? $1 : () } $cgi->param();
- return @ids;
+ return @ids;
}
# Check if the user is the owner of series_id or is an admin.
sub assertCanEdit {
- my $series_id = shift;
- my $user = Bugzilla->user;
+ my $series_id = shift;
+ my $user = Bugzilla->user;
- my $series = new Bugzilla::Series($series_id)
- || ThrowCodeError('invalid_series_id');
+ my $series
+ = new Bugzilla::Series($series_id) || ThrowCodeError('invalid_series_id');
- if (!$user->in_group('admin') && $series->{creator_id} != $user->id) {
- ThrowUserError('illegal_series_edit');
- }
+ if (!$user->in_group('admin') && $series->{creator_id} != $user->id) {
+ ThrowUserError('illegal_series_edit');
+ }
- return $series;
+ return $series;
}
# Check if the user is permitted to create this series with these parameters.
sub assertCanCreate {
- my ($cgi) = shift;
- my $user = Bugzilla->user;
+ my ($cgi) = shift;
+ my $user = Bugzilla->user;
- $user->in_group("editbugs") || ThrowUserError("illegal_series_creation");
+ $user->in_group("editbugs") || ThrowUserError("illegal_series_creation");
- # Check permission for frequency
- my $min_freq = 7;
- # Upstreaming: denied, as this min_freq feature is going away.
- if ($cgi->param('frequency') < $min_freq && !$user->in_group("bz_canusewhines")) {
- ThrowUserError("illegal_frequency", { 'minimum' => $min_freq });
- }
+ # Check permission for frequency
+ my $min_freq = 7;
+
+ # Upstreaming: denied, as this min_freq feature is going away.
+ if ($cgi->param('frequency') < $min_freq && !$user->in_group("bz_canusewhines"))
+ {
+ ThrowUserError("illegal_frequency", {'minimum' => $min_freq});
+ }
}
sub validateWidthAndHeight {
- $vars->{'width'} = $cgi->param('width');
- $vars->{'height'} = $cgi->param('height');
-
- if (defined($vars->{'width'})) {
- (detaint_natural($vars->{'width'}) && $vars->{'width'} > 0)
- || ThrowCodeError("invalid_dimensions");
- }
-
- if (defined($vars->{'height'})) {
- (detaint_natural($vars->{'height'}) && $vars->{'height'} > 0)
- || ThrowCodeError("invalid_dimensions");
- }
-
- # The equivalent of 2000 square seems like a very reasonable maximum size.
- # This is merely meant to prevent accidental or deliberate DOS, and should
- # have no effect in practice.
- if ($vars->{'width'} && $vars->{'height'}) {
- (($vars->{'width'} * $vars->{'height'}) <= 4000000)
- || ThrowUserError("chart_too_large");
- }
+ $vars->{'width'} = $cgi->param('width');
+ $vars->{'height'} = $cgi->param('height');
+
+ if (defined($vars->{'width'})) {
+ (detaint_natural($vars->{'width'}) && $vars->{'width'} > 0)
+ || ThrowCodeError("invalid_dimensions");
+ }
+
+ if (defined($vars->{'height'})) {
+ (detaint_natural($vars->{'height'}) && $vars->{'height'} > 0)
+ || ThrowCodeError("invalid_dimensions");
+ }
+
+ # The equivalent of 2000 square seems like a very reasonable maximum size.
+ # This is merely meant to prevent accidental or deliberate DOS, and should
+ # have no effect in practice.
+ if ($vars->{'width'} && $vars->{'height'}) {
+ (($vars->{'width'} * $vars->{'height'}) <= 4000000)
+ || ThrowUserError("chart_too_large");
+ }
}
sub edit {
- my $series = shift;
+ my $series = shift;
- $vars->{'category'} = Bugzilla::Chart::getVisibleSeries();
- $vars->{'default'} = $series;
+ $vars->{'category'} = Bugzilla::Chart::getVisibleSeries();
+ $vars->{'default'} = $series;
- print $cgi->header();
- $template->process("reports/edit-series.html.tmpl", $vars)
- || ThrowTemplateError($template->error());
+ print $cgi->header();
+ $template->process("reports/edit-series.html.tmpl", $vars)
+ || ThrowTemplateError($template->error());
}
sub plot {
- validateWidthAndHeight();
- $vars->{'chart'} = new Bugzilla::Chart($cgi);
+ validateWidthAndHeight();
+ $vars->{'chart'} = new Bugzilla::Chart($cgi);
- my $format = $template->get_format("reports/chart", "", scalar($cgi->param('ctype')));
+ my $format
+ = $template->get_format("reports/chart", "", scalar($cgi->param('ctype')));
- # Debugging PNGs is a pain; we need to be able to see the error messages
- if ($cgi->param('debug')) {
- print $cgi->header();
- $vars->{'chart'}->dump();
- }
+ # Debugging PNGs is a pain; we need to be able to see the error messages
+ if ($cgi->param('debug')) {
+ print $cgi->header();
+ $vars->{'chart'}->dump();
+ }
- print $cgi->header($format->{'ctype'});
- disable_utf8() if ($format->{'ctype'} =~ /^image\//);
+ print $cgi->header($format->{'ctype'});
+ disable_utf8() if ($format->{'ctype'} =~ /^image\//);
- $template->process($format->{'template'}, $vars)
- || ThrowTemplateError($template->error());
+ $template->process($format->{'template'}, $vars)
+ || ThrowTemplateError($template->error());
}
sub wrap {
- validateWidthAndHeight();
+ validateWidthAndHeight();
- # We create a Chart object so we can validate the parameters
- my $chart = new Bugzilla::Chart($cgi);
+ # We create a Chart object so we can validate the parameters
+ my $chart = new Bugzilla::Chart($cgi);
- $vars->{'time'} = localtime(time());
+ $vars->{'time'} = localtime(time());
- $vars->{'imagebase'} = $cgi->canonicalise_query(
- "action", "action-wrap", "ctype", "format", "width", "height");
+ $vars->{'imagebase'}
+ = $cgi->canonicalise_query("action", "action-wrap", "ctype", "format",
+ "width", "height");
- print $cgi->header();
- $template->process("reports/chart.html.tmpl", $vars)
- || ThrowTemplateError($template->error());
+ print $cgi->header();
+ $template->process("reports/chart.html.tmpl", $vars)
+ || ThrowTemplateError($template->error());
}
sub view {
- my $chart = shift;
+ my $chart = shift;
- # Set defaults
- foreach my $field ('category', 'subcategory', 'name', 'ctype') {
- $vars->{'default'}{$field} = $cgi->param($field) || 0;
- }
+ # Set defaults
+ foreach my $field ('category', 'subcategory', 'name', 'ctype') {
+ $vars->{'default'}{$field} = $cgi->param($field) || 0;
+ }
- # Pass the state object to the display UI.
- $vars->{'chart'} = $chart;
- $vars->{'category'} = Bugzilla::Chart::getVisibleSeries();
+ # Pass the state object to the display UI.
+ $vars->{'chart'} = $chart;
+ $vars->{'category'} = Bugzilla::Chart::getVisibleSeries();
- print $cgi->header();
+ print $cgi->header();
- # If we have having problems with bad data, we can set debug=1 to dump
- # the data structure.
- $chart->dump() if $cgi->param('debug');
+ # If we have having problems with bad data, we can set debug=1 to dump
+ # the data structure.
+ $chart->dump() if $cgi->param('debug');
- $template->process("reports/create-chart.html.tmpl", $vars)
- || ThrowTemplateError($template->error());
+ $template->process("reports/create-chart.html.tmpl", $vars)
+ || ThrowTemplateError($template->error());
}