shell bypass 403
# Data::Report::Plugin::Csv.pm -- CSV plugin for Data::Report
# RCS Info : $Id: Csv.pm,v 1.9 2008/08/18 09:51:23 jv Exp $
# Author : Johan Vromans
# Created On : Thu Jan 5 18:47:37 2006
# Last Modified By: Johan Vromans
# Last Modified On: Mon Aug 18 11:45:48 2008
# Update Count : 119
# Status : Unknown, Use with caution!
package Data::Report::Plugin::Csv;
use strict;
use warnings;
use base qw(Data::Report::Base);
################ API ################
my $csv_implementation = 0;
sub start {
my ($self, @args) = @_;
$self->SUPER::start(@args);
$self->set_separator(",") unless $self->get_separator;
$self->_select_csv_method unless $csv_implementation;
return;
}
sub finish {
my ($self) = @_;
$self->SUPER::finish();
}
sub add {
my ($self, $data) = @_;
my $style = delete($data->{_style});
my $sep = $self->get_separator;
$self->SUPER::add($data);
return unless %$data;
if ( $style and my $t = $self->_getstyle($style) ) {
return if $t->{ignore};
}
$self->_checkhdr;
my $line;
$line = $self->_csv
( map {
$data->{$_->{name}} || ""
}
grep {
my $t = $self->_getstyle($style, $_->{name});
! $t->{ignore};
}
@{$self->_get_fields}
);
$self->_print($line, "\n");
}
sub set_separator { $_[0]->{sep} = $_[1] }
sub get_separator { $_[0]->{sep} || "," }
################ Pseudo-Internal (used by Base class) ################
sub _std_heading {
my ($self) = @_;
my $sep = $self->get_separator;
$self->_print($self->_csv
(map {
$_->{title}
}
grep {
my $t = $self->_getstyle("_head", $_->{name});
! $t->{ignore};
}
@{$self->_get_fields}),
"\n");
}
################ Internal (used if no alternatives) ################
sub _csv_internal {
join(shift->get_separator,
map {
# Quotes must be doubled.
s/"/""/g;
# Always quote (compatible with Text::CSV)
$_ = '"' . $_ . '"';
$_;
} @_);
}
sub _set_csv_method {
my ($self, $class) = @_;
no warnings qw(redefine);
if ( $class && $class->isa("Text::CSV_XS") ) {
# Use always_quote to be compatible with Text::CSV.
# Use binary to deal with non-ASCII text.
$csv_implementation = Text::CSV_XS->new
({ sep_char => $self->get_separator,
always_quote => 1,
binary => 1,
});
# Assign the method.
*_csv = sub {
shift;
$csv_implementation->combine(@_);
$csv_implementation->string;
};
warn("# CSV plugin uses Text::CSV_XS $Text::CSV_XS::VERSION\n")
if $ENV{AUTOMATED_TESTING};
}
elsif ( $class && $class->isa("Text::CSV") ) {
# With modern Text::CSV, it will use Text::CSV_XS if possible.
# So this gotta be Text::CSV_PP...
$csv_implementation = Text::CSV->new
({ always_quote => 1,
binary => 1,
});
# Assign the method.
*_csv = sub {
shift;
$csv_implementation->combine(@_);
$csv_implementation->string;
};
warn("# CSV plugin uses Text::CSV $Text::CSV::VERSION, PP version $Text::CSV_PP::VERSION\n")
if $ENV{AUTOMATED_TESTING};
}
else {
# Use our internal method.
*_csv = \&_csv_internal;
$csv_implementation = "Data::Report::Plugin::Csv::_csv_internal";
warn("# CSV plugin uses built-in CSV packer\n")
if $ENV{AUTOMATED_TESTING};
}
return $csv_implementation;
}
sub _select_csv_method {
my $self = shift;
$csv_implementation = 0;
eval {
require Text::CSV_XS;
$self->_set_csv_method(Text::CSV_XS::);
};
return $csv_implementation if $csv_implementation;
if ( $self->get_separator eq "," ) {
eval {
require Text::CSV;
$self->_set_csv_method(Text::CSV::);
};
}
return $csv_implementation if $csv_implementation;
# Use our internal method.
$self->_set_csv_method();
return $csv_implementation;
}
1;