CGI-Info
view release on metacpan or search on metacpan
lib/CGI/Info.pm view on Meta::CPAN
=head3 API SPECIFICATION
=head4 Input
{
field => { type => 'scalar', optional => 1 },
}
=head4 Output
# When $field is supplied
{ type => 'scalar', optional => 1 }
# When $field is omitted (delegates to params())
{ type => 'hashref', optional => 1 }
=head3 MESSAGES
| Level | Message | Meaning | Action |
|-------|------------------------------------------|--------------------------------------|-----------------------------------------|
| warn | param: <field> isn't in the allow list | Caller requested a parameter outside | Review the allow list passed to new() |
| | | the schema set by params(allow=>\%h) | or params(); add the key if legitimate |
=cut
sub param {
my ($self, $field) = @_;
if(!defined($field)) {
return $self->params();
}
# Is this a permitted argument?
if($self->{allow} && !exists($self->{allow}->{$field})) {
$self->_warn({
warning => "param: $field isn't in the allow list"
});
return;
}
# Prevent deep recursion which can happen when a validation routine calls param()
my $allow;
if($self->{in_param} && $self->{allow}) {
$allow = delete $self->{allow};
}
$self->{in_param} = 1;
my $params = $self->params();
$self->{in_param} = 0;
$self->{allow} = $allow if($allow);
if($params) {
return Return::Set::set_return($params->{$field}, { type => 'string' });
}
}
sub _sanitise_input :Protected {
my $arg = shift;
# Protected function: inline check because the ($) prototype means no $self,
unless($ENV{HARNESS_ACTIVE}) {
my $calling_pkg = (caller)[0];
unless($calling_pkg && ($calling_pkg eq __PACKAGE__ || $calling_pkg->isa(__PACKAGE__))) {
Carp::croak('_sanitise_input() is a protected function and cannot be called from outside ' . __PACKAGE__);
}
}
return if(!defined($arg));
# Remove hacking attempts and spaces
$arg =~ s/[\r\n]//g;
$arg =~ s/\s+$//;
$arg =~ s/^\s+//;
# Possessive quantifier prevents catastrophic backtracking when input
# contains '<!--' with no matching closing '-->'.
$arg =~ s/<!--[^-]*+(?:-(?!->)[^-]*+)*+-->//g;
# Allow :
# $arg =~ s/[;<>\*|`&\$!?#\(\)\[\]\{\}'"\\\r]//g;
# return $arg;
# return String::EscapeCage->new(convert_XSS($arg))->escapecstring();
return convert_XSS($arg);
}
sub _multipart_data :Protected {
my ($self, $args) = @_;
$self->_trace('Entering _multipart_data');
my $total_bytes = $$args{length};
$self->_debug("_multipart_data: total_bytes = $total_bytes");
if($total_bytes == 0) {
return;
}
unless($stdin_data) {
while(<STDIN>) {
chop(my $line = $_);
$line =~ s/[\r\n]//g;
$stdin_data .= "$line\n";
}
if(!$stdin_data) {
return;
}
}
my $boundary = $$args{boundary};
my @pairs;
my $writing_file = 0;
my $key;
my $value;
my $in_header = 0;
my $fout;
foreach my $line(split(/\n/, $stdin_data)) {
if($line =~ /^--\Q$boundary\E--$/) {
last;
}
lib/CGI/Info.pm view on Meta::CPAN
if(!defined($self->{'logger'})) {
Carp::croak($params->{'warning'});
}
}
# Ensure all environment variables are sanitized and validated before use.
# Use regular expressions to enforce strict input formats.
sub _get_env :Protected {
my ($self, $var) = @_;
return unless defined $ENV{$var};
# Strict sanitization: allow alphanumeric and limited special characters
if($ENV{$var} =~ /^[\w\.\-\/:\\]+$/) {
return $ENV{$var};
}
$self->_warn("Invalid value in environment variable: $var");
return;
}
=head2 reset
Class method to reset the class.
You should do this in an FCGI environment before instantiating,
but nowhere else.
=cut
sub reset {
my $class = shift;
unless($class eq __PACKAGE__) {
carp('Reset is a class method');
return;
}
$stdin_data = undef;
}
sub AUTOLOAD
{
our $AUTOLOAD;
my $self = shift or return;
return if(!defined($AUTOLOAD));
# Extract the method name from the AUTOLOAD variable
my ($method) = $AUTOLOAD =~ /::(\w+)$/;
# Skip if called on destruction
return if($method eq 'DESTROY');
Carp::croak(__PACKAGE__, ": Unknown method $method") if(!ref($self));
# Allow the AUTOLOAD feature to be disabled
Carp::croak(__PACKAGE__, ": Unknown method $method") if(exists($self->{'auto_load'}) && boolean($self->{'auto_load'})->isFalse());
# Ensure the method is called on the correct package object or a subclass
return unless((ref($self) eq __PACKAGE__) || (UNIVERSAL::isa((caller)[0], __PACKAGE__)));
# Validate method name - only allow safe parameter names
Carp::croak(__PACKAGE__, ": Invalid method name: $method") unless $method =~ /^[a-zA-Z_][a-zA-Z0-9_]*$/;
# Delegate to the param method
return $self->param($method);
}
=head1 AUTHOR
Nigel Horne, C<< <njh at nigelhorne.com> >>
=head1 BUGS
is_tablet() only currently detects the iPad and Windows PCs. Android strings
don't differ between tablets and smartphones.
params() returns a ref which means that calling routines can change the hash
for other routines.
Take a local copy before making amendments to the table if you don't want unexpected
things to happen.
=head1 SEE ALSO
=over 4
=item * L<Configure an Object at Runtime|Object::Configure>
=item * L<Test Dashboard|https://nigelhorne.github.io/CGI-Info/coverage/>
=item * L<HTTP::BrowserDetect>
=item * L<https://github.com/mitchellkrogza/apache-ultimate-bad-bot-blocker>
=back
=head1 REPOSITORY
L<https://github.com/nigelhorne/CGI-Info>
=head1 SUPPORT
This module is provided as-is without any warranty.
Please report any bugs or feature requests to C<bug-cgi-info at rt.cpan.org>,
or through the web interface at
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=CGI-Info>.
I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.
You can find documentation for this module with the perldoc command.
perldoc CGI::Info
You can also look for information at:
=over 4
=item * MetaCPAN
( run in 4.335 seconds using v1.01-cache-2.11-cpan-364913b4093 )