CGI-Info
view release on metacpan or search on metacpan
t/function.t view on Meta::CPAN
$ENV{GATEWAY_INTERFACE} = 'CGI/1.1';
$ENV{REQUEST_METHOD} = 'DELETE';
my $info = CGI::Info->new();
$info->params();
is($info->status(), $config{status_method_na}, 'DELETE yields 405');
};
# ============================================================
# 4. params()
# ============================================================
# Simple GET with two parameters
subtest 'params() - GET simple query' => sub {
plan tests => 3;
reset_env();
$ENV{GATEWAY_INTERFACE} = 'CGI/1.1';
$ENV{REQUEST_METHOD} = 'GET';
$ENV{QUERY_STRING} = 'foo=bar&baz=42';
my $info = CGI::Info->new();
my $p = $info->params();
ok(defined $p, 'params() returns defined value');
is($p->{foo}, 'bar', 'foo=bar parsed correctly');
is($p->{baz}, '42', 'baz=42 parsed correctly');
};
diag("Testing params() edge cases") if $ENV{TEST_VERBOSE};
# Empty QUERY_STRING returns undef
subtest 'params() - empty QUERY_STRING returns undef' => sub {
plan tests => 1;
reset_env();
$ENV{GATEWAY_INTERFACE} = 'CGI/1.1';
$ENV{REQUEST_METHOD} = 'GET';
$ENV{QUERY_STRING} = '';
my $info = CGI::Info->new();
ok(!defined $info->params(), 'empty QUERY_STRING returns undef');
};
# allow hashref filters out unlisted keys
subtest 'params() - allow filters unknown keys' => sub {
plan tests => 2;
reset_env();
$ENV{GATEWAY_INTERFACE} = 'CGI/1.1';
$ENV{REQUEST_METHOD} = 'GET';
$ENV{QUERY_STRING} = 'good=1&evil=2';
my $info = CGI::Info->new();
my $p = $info->params(allow => { good => qr/^\d+$/ });
ok(defined $p->{good}, 'allowed key is present in result');
ok(!defined $p->{evil}, 'disallowed key is absent from result');
};
# allow regex mismatch removes value and sets 422
subtest 'params() - allow regex mismatch blocks value and sets 422' => sub {
plan tests => 2;
reset_env();
$ENV{GATEWAY_INTERFACE} = 'CGI/1.1';
$ENV{REQUEST_METHOD} = 'GET';
$ENV{QUERY_STRING} = 'id=abc';
my $info = CGI::Info->new();
my $p = $info->params(allow => { id => qr/^\d+$/ });
ok(!defined $p, 'regex-blocked parameter excluded from result');
is($info->status(), $config{status_unproc}, 'status 422 set on validation failure');
};
# allow exact-string comparison
subtest 'params() - allow exact-string match passes valid value' => sub {
plan tests => 1;
reset_env();
$ENV{GATEWAY_INTERFACE} = 'CGI/1.1';
$ENV{REQUEST_METHOD} = 'GET';
$ENV{QUERY_STRING} = 'color=blue';
my $info = CGI::Info->new();
my $p = $info->params(allow => { color => 'blue' });
ok(defined $p, 'exact-string allow passes matching value');
};
# allow coderef validator
subtest 'params() - allow coderef validator' => sub {
plan tests => 2;
reset_env();
$ENV{GATEWAY_INTERFACE} = 'CGI/1.1';
$ENV{REQUEST_METHOD} = 'GET';
$ENV{QUERY_STRING} = 'num=4&num2=3';
my $info = CGI::Info->new();
my $p = $info->params(allow => {
num => sub { ($_[1] % 2) == 0 }, # even => accept
num2 => sub { ($_[1] % 2) == 0 }, # odd => reject
});
ok(defined $p->{num}, 'even number passes coderef validator');
ok(!defined $p->{num2}, 'odd number blocked by coderef validator');
};
# SQL injection in query string must be blocked with 403
subtest 'params() - SQL injection blocked with 403' => sub {
plan tests => 2;
reset_env();
$ENV{GATEWAY_INTERFACE} = 'CGI/1.1';
$ENV{REQUEST_METHOD} = 'GET';
$ENV{QUERY_STRING} = "id=1'%20OR%201=1";
my $info = CGI::Info->new();
my $p = $info->params();
ok(!defined $p, 'SQL injection blocked');
is($info->status(), $config{status_forbidden}, 'status 403 set on SQL injection');
};
# XSS in query string must be blocked with 403
subtest 'params() - XSS injection blocked with 403' => sub {
plan tests => 2;
reset_env();
$ENV{GATEWAY_INTERFACE} = 'CGI/1.1';
$ENV{REQUEST_METHOD} = 'GET';
$ENV{QUERY_STRING} = 'q=%3Cscript%3Ealert(1)%3C%2Fscript%3E';
my $info = CGI::Info->new();
my $p = $info->params();
ok(!defined $p, 'XSS injection blocked');
is($info->status(), $config{status_forbidden}, 'status 403 set on XSS');
};
# Directory traversal must be blocked with 403
subtest 'params() - directory traversal blocked with 403' => sub {
plan tests => 2;
reset_env();
$ENV{GATEWAY_INTERFACE} = 'CGI/1.1';
$ENV{REQUEST_METHOD} = 'GET';
$ENV{QUERY_STRING} = 'file=../../etc/passwd';
my $info = CGI::Info->new();
my $p = $info->params();
ok(!defined $p, 'directory traversal blocked');
is($info->status(), $config{status_forbidden}, 'status 403 set on traversal');
};
# mustleak probe must be blocked with 403
subtest 'params() - mustleak probe blocked with 403' => sub {
plan tests => 2;
reset_env();
$ENV{GATEWAY_INTERFACE} = 'CGI/1.1';
$ENV{REQUEST_METHOD} = 'GET';
$ENV{QUERY_STRING} = 'x=mustleak.com/probe';
my $info = CGI::Info->new();
my $p = $info->params();
ok(!defined $p, 'mustleak probe blocked');
is($info->status(), $config{status_forbidden}, 'status 403 set on mustleak');
};
# Duplicate keys should be comma-joined
subtest 'params() - duplicate keys comma-joined' => sub {
plan tests => 1;
reset_env();
$ENV{GATEWAY_INTERFACE} = 'CGI/1.1';
$ENV{REQUEST_METHOD} = 'GET';
$ENV{QUERY_STRING} = 'color=red&color=blue';
my $info = CGI::Info->new();
my $p = $info->params();
like($p->{color}, qr/red.*blue|blue.*red/, 'duplicate values are comma-joined');
};
# POST without CONTENT_LENGTH returns undef and sets 411
subtest 'params() - POST missing CONTENT_LENGTH sets 411' => sub {
plan tests => 2;
reset_env();
$ENV{GATEWAY_INTERFACE} = 'CGI/1.1';
$ENV{REQUEST_METHOD} = 'POST';
my $info = CGI::Info->new();
my $p = $info->params();
ok(!defined $p, 'POST without CONTENT_LENGTH returns undef');
is($info->status(), $config{status_length_req}, 'status 411 set on missing CONTENT_LENGTH');
};
# POST with oversized body returns undef and sets 413
subtest 'params() - POST oversized body sets 413' => sub {
plan tests => 2;
reset_env();
$ENV{GATEWAY_INTERFACE} = 'CGI/1.1';
$ENV{REQUEST_METHOD} = 'POST';
$ENV{CONTENT_LENGTH} = $config{upload_oversized};
my $info = CGI::Info->new(max_upload_size => $config{upload_small});
my $p = $info->params();
ok(!defined $p, 'oversized POST returns undef');
is($info->status(), $config{status_too_large}, 'status 413 set on oversized upload');
};
# Non-CGI: ARGV key=value pairs
subtest 'params() - command-line ARGV key=value pairs' => sub {
plan tests => 2;
reset_env();
local @ARGV = ('name=Alice', 'age=30');
my $info = CGI::Info->new();
my $p = $info->params();
is($p->{name}, 'Alice', 'name parsed from ARGV');
is($p->{age}, '30', 'age parsed from ARGV');
};
# --mobile ARGV flag sets is_mobile
subtest 'params() - --mobile ARGV flag sets is_mobile' => sub {
plan tests => 1;
reset_env();
local @ARGV = ('--mobile', 'x=1');
my $info = CGI::Info->new();
$info->params();
ok($info->is_mobile(), '--mobile flag sets is_mobile');
};
( run in 2.567 seconds using v1.01-cache-2.11-cpan-c221a9de4ec )