SQL-Injection vermeiden. Fix für Revisionen 2936, 2937.
[kivitendo-erp.git] / SL / ReportGenerator.pm
index f3030b2..67d69a9 100644 (file)
@@ -46,9 +46,13 @@ sub new {
     'variable_list' => '',
   };
 
+  $self->{data_present} = 0;
+
+  bless $self, $type;
+
   $self->set_options(@_) if (@_);
 
-  return bless $self, $type;
+  return $self;
 }
 
 sub set_columns {
@@ -105,7 +109,14 @@ sub add_data {
       $self->{form}->error('Incorrect usage -- expecting hash or array ref');
     }
 
+    my @columns_with_default_alignment = grep { defined $self->{columns}->{$_}->{align} } keys %{ $self->{columns} };
+
     foreach my $row (@{ $row_set }) {
+      foreach my $column (@columns_with_default_alignment) {
+        $row->{$column}          ||= { };
+        $row->{$column}->{align}   = $self->{columns}->{$column}->{align} unless (defined $row->{$column}->{align});
+      }
+
       foreach my $field (qw(data link)) {
         map { $row->{$_}->{$field} = [ $row->{$_}->{$field} ] if (ref $row->{$_}->{$field} ne 'ARRAY') } keys %{ $row };
       }
@@ -113,6 +124,8 @@ sub add_data {
 
     push @{ $self->{data} }, $row_set;
     $last_row_set = $row_set;
+
+    $self->{data_present} = 1;
   }
 
   return $last_row_set;
@@ -134,7 +147,8 @@ sub add_control {
 sub clear_data {
   my $self = shift;
 
-  $self->{data} = [];
+  $self->{data}         = [];
+  $self->{data_present} = 0;
 }
 
 sub set_options {
@@ -217,7 +231,7 @@ sub get_visible_columns {
   my $self   = shift;
   my $format = shift;
 
-  return grep { my $c = $self->{columns}->{$_}; $c && $c->{visible} && (($c->{visible} == 1) || ($c->{visible} =~ /${format}/i)) } @{ $self->{column_order} };
+  return grep { my $c = $self->{columns}->{$_}; $c && $c->{visible} && (($c->{visible} == 1) || ($c->{visible} =~ /\Q${format}\E/i)) } @{ $self->{column_order} };
 }
 
 sub html_format {
@@ -254,20 +268,33 @@ sub prepare_html_content {
   }
 
   my ($outer_idx, $inner_idx) = (0, 0);
+  my $next_border_top;
   my @rows;
 
   foreach my $row_set (@{ $self->{data} }) {
     if ('HASH' eq ref $row_set) {
+      if ($row_set->{type} eq 'separator') {
+        if (! scalar @rows) {
+          $next_border_top = 1;
+        } else {
+          $rows[-1]->{BORDER_BOTTOM} = 1;
+        }
+
+        next;
+      }
+
       my $row_data = {
         'IS_CONTROL'      => 1,
-        'IS_SEPARATOR'    => $row_set->{type} eq 'separator',
         'IS_COLSPAN_DATA' => $row_set->{type} eq 'colspan_data',
         'NUM_COLUMNS'     => scalar @visible_columns,
+        'BORDER_TOP'      => $next_border_top,
         'data'            => $row_set->{data},
       };
 
       push @rows, $row_data;
 
+      $next_border_top = 0;
+
       next;
     }
 
@@ -279,12 +306,20 @@ sub prepare_html_content {
       foreach my $col_name (@visible_columns) {
         my $col = $row->{$col_name};
         $col->{CELL_ROWS} = [ ];
-        foreach my $i (0 .. scalar(@{ $col->{data} })) {
+        foreach my $i (0 .. scalar(@{ $col->{data} }) - 1) {
           push @{ $col->{CELL_ROWS} }, {
             'data' => $self->html_format($col->{data}->[$i]),
             'link' => $col->{link}->[$i],
           };
-        };
+        }
+
+        # Force at least a   to be displayed so that browsers
+        # will format the table cell (e.g. borders etc).
+        if (!scalar @{ $col->{CELL_ROWS} }) {
+          push @{ $col->{CELL_ROWS} }, { 'data' => ' ' };
+        } elsif ((1 == scalar @{ $col->{CELL_ROWS} }) && !$col->{CELL_ROWS}->[0]->{data}) {
+          $col->{CELL_ROWS}->[0]->{data} = ' ';
+        }
       }
 
       my $row_data = {
@@ -292,9 +327,12 @@ sub prepare_html_content {
         'outer_idx'     => $outer_idx,
         'outer_idx_odd' => $outer_idx % 2,
         'inner_idx'     => $inner_idx,
+        'BORDER_TOP'    => $next_border_top,
       };
 
       push @rows, $row_data;
+
+      $next_border_top = 0;
     }
   }
 
@@ -313,13 +351,14 @@ sub prepare_html_content {
     'RAW_BOTTOM_INFO_TEXT' => $opts->{raw_bottom_info_text},
     'ALLOW_PDF_EXPORT'     => $allow_pdf_export,
     'ALLOW_CSV_EXPORT'     => $opts->{allow_csv_export},
-    'SHOW_EXPORT_BUTTONS'  => $allow_pdf_export || $opts->{allow_csv_export},
+    'SHOW_EXPORT_BUTTONS'  => ($allow_pdf_export || $opts->{allow_csv_export}) && $self->{data_present},
     'COLUMN_HEADERS'       => \@column_headers,
     'NUM_COLUMNS'          => scalar @column_headers,
     'ROWS'                 => \@rows,
     'EXPORT_VARIABLES'     => \@export_variables,
     'EXPORT_VARIABLE_LIST' => $self->{export}->{variable_list},
     'EXPORT_NEXTSUB'       => $self->{export}->{nextsub},
+    'DATA_PRESENT'         => $self->{data_present},
   };
 
   return $variables;