line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package CGI::Easy::Util; |
2
|
3
|
|
|
3
|
|
38
|
use 5.010001; |
|
3
|
|
|
|
|
8
|
|
3
|
3
|
|
|
3
|
|
12
|
use warnings; |
|
3
|
|
|
|
|
3
|
|
|
3
|
|
|
|
|
54
|
|
4
|
3
|
|
|
3
|
|
11
|
use strict; |
|
3
|
|
|
|
|
4
|
|
|
3
|
|
|
|
|
48
|
|
5
|
3
|
|
|
3
|
|
10
|
use utf8; |
|
3
|
|
|
|
|
3
|
|
|
3
|
|
|
|
|
18
|
|
6
|
3
|
|
|
3
|
|
62
|
use Carp; |
|
3
|
|
|
|
|
4
|
|
|
3
|
|
|
|
|
173
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = 'v2.0.1'; |
9
|
|
|
|
|
|
|
|
10
|
3
|
|
|
3
|
|
1157
|
use Export::Attrs; |
|
3
|
|
|
|
|
19647
|
|
|
3
|
|
|
|
|
18
|
|
11
|
3
|
|
|
3
|
|
1272
|
use URI::Escape qw( uri_unescape uri_escape_utf8 ); |
|
3
|
|
|
|
|
3751
|
|
|
3
|
|
|
|
|
244
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
sub date_http :Export { |
15
|
6
|
|
|
6
|
1
|
11
|
my ($tick) = @_; |
16
|
6
|
|
|
|
|
13
|
return _date($tick, 'http'); |
17
|
3
|
|
|
3
|
|
17
|
} |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
13
|
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub date_cookie :Export { |
20
|
9
|
|
|
9
|
1
|
14
|
my ($tick) = @_; |
21
|
9
|
|
|
|
|
14
|
return _date($tick, 'cookie'); |
22
|
3
|
|
|
3
|
|
638
|
} |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
22
|
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
sub _date { |
25
|
15
|
|
|
15
|
|
21
|
my ($tick, $format) = @_; |
26
|
15
|
100
|
|
|
|
28
|
my $sp = $format eq 'cookie' ? q{-} : q{ }; |
27
|
15
|
|
|
|
|
54
|
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime $tick; |
28
|
15
|
|
|
|
|
26
|
my $wkday = qw(Sun Mon Tue Wed Thu Fri Sat)[$wday]; |
29
|
15
|
|
|
|
|
20
|
my $month = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)[$mon]; |
30
|
15
|
|
|
|
|
74
|
return sprintf "%s, %02d$sp%s$sp%s %02d:%02d:%02d GMT", |
31
|
|
|
|
|
|
|
$wkday, $mday, $month, $year+1900, $hour, $min, $sec; ## no critic(ProhibitMagicNumbers) |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
sub make_cookie :Export { |
35
|
12
|
|
|
12
|
1
|
15
|
my ($opt) = @_; |
36
|
12
|
50
|
|
|
|
22
|
return q{} if !defined $opt->{name}; |
37
|
|
|
|
|
|
|
|
38
|
12
|
|
|
|
|
14
|
my $name = $opt->{name}; |
39
|
12
|
50
|
|
|
|
21
|
my $value = defined $opt->{value} ? $opt->{value} : q{}; |
40
|
12
|
|
|
|
|
15
|
my $domain = $opt->{domain}; |
41
|
12
|
50
|
|
|
|
17
|
my $path = defined $opt->{path} ? $opt->{path} : q{/}; # IE require it |
42
|
|
|
|
|
|
|
my $expires = defined $opt->{expires} && $opt->{expires} =~ /\A\d+\z/xms ? |
43
|
12
|
100
|
66
|
|
|
62
|
date_cookie($opt->{expires}) : $opt->{expires}; |
44
|
12
|
|
|
|
|
17
|
my $set_cookie = 'Set-Cookie: '; |
45
|
12
|
|
|
|
|
22
|
$set_cookie .= uri_escape_utf8($name) . q{=} . uri_escape_utf8($value); |
46
|
12
|
100
|
|
|
|
374
|
$set_cookie .= "; domain=$domain" if defined $domain; ## no critic(ProhibitPostfixControls) |
47
|
12
|
|
|
|
|
16
|
$set_cookie .= "; path=$path"; |
48
|
12
|
100
|
|
|
|
22
|
$set_cookie .= "; expires=$expires" if defined $expires;## no critic(ProhibitPostfixControls) |
49
|
12
|
50
|
|
|
|
19
|
$set_cookie .= '; secure' if $opt->{secure}; ## no critic(ProhibitPostfixControls) |
50
|
12
|
|
|
|
|
14
|
$set_cookie .= "\r\n"; |
51
|
12
|
|
|
|
|
40
|
return $set_cookie; |
52
|
3
|
|
|
3
|
|
1315
|
} |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
9
|
|
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub uri_unescape_plus :Export { |
55
|
112
|
|
|
112
|
1
|
149
|
my ($s) = @_; |
56
|
112
|
|
|
|
|
242
|
$s =~ s/[+]/ /xmsg; |
57
|
112
|
|
|
|
|
156
|
return uri_unescape($s); |
58
|
3
|
|
|
3
|
|
556
|
} |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
20
|
|
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
sub burst_urlencoded :Export { |
61
|
38
|
|
|
38
|
1
|
58
|
my ($buffer) = @_; |
62
|
38
|
|
|
|
|
42
|
my %param; |
63
|
38
|
50
|
|
|
|
54
|
if (defined $buffer) { |
64
|
38
|
|
|
|
|
6248
|
foreach my $pair (split /[&;]/xms, $buffer) { |
65
|
49
|
|
|
|
|
3323
|
my ($name, $data) = split /=/xms, $pair, 2; |
66
|
49
|
50
|
|
|
|
118
|
$name = !defined $name ? q{} : uri_unescape_plus($name); |
67
|
49
|
100
|
|
|
|
584
|
$data = !defined $data ? q{} : uri_unescape_plus($data); |
68
|
49
|
|
|
|
|
330
|
push @{ $param{$name} }, $data; |
|
49
|
|
|
|
|
2668
|
|
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
} |
71
|
38
|
|
|
|
|
101
|
return \%param; |
72
|
3
|
|
|
3
|
|
875
|
} |
|
3
|
|
|
|
|
11
|
|
|
3
|
|
|
|
|
13
|
|
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
# This function derived from CGI::Minimal (1.29) by |
75
|
|
|
|
|
|
|
# Benjamin Franz |
76
|
|
|
|
|
|
|
# Copyright (c) Benjamin Franz. All rights reserved. |
77
|
|
|
|
|
|
|
sub burst_multipart :Export { |
78
|
2
|
|
|
2
|
1
|
12
|
my ($buffer, $bdry) = @_; |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# Special case boundaries causing problems with 'split' |
81
|
2
|
50
|
|
|
|
9
|
if ($bdry =~ m{[^A-Za-z0-9',-./:=]}ms) { ## no critic (ProhibitEnumeratedClasses) |
82
|
0
|
|
|
|
|
0
|
my $nbdry = $bdry; |
83
|
0
|
|
|
|
|
0
|
$nbdry =~ s/([^A-Za-z0-9',-.\/:=])/ord($1)/msge;## no critic (ProhibitEnumeratedClasses) |
|
0
|
|
|
|
|
0
|
|
84
|
0
|
|
|
|
|
0
|
my $quoted_boundary = quotemeta $nbdry; |
85
|
0
|
|
|
|
|
0
|
while ($buffer =~ m/$quoted_boundary/ms) { |
86
|
0
|
|
|
|
|
0
|
$nbdry .= chr(65 + int rand 25); ## no critic (ProhibitParensWithBuiltins, ProhibitMagicNumbers) |
87
|
0
|
|
|
|
|
0
|
$quoted_boundary = quotemeta $nbdry; |
88
|
|
|
|
|
|
|
} |
89
|
0
|
|
|
|
|
0
|
my $old_boundary = quotemeta $bdry; |
90
|
0
|
|
|
|
|
0
|
$buffer =~ s/$old_boundary/$nbdry/msg; |
91
|
0
|
|
|
|
|
0
|
$bdry = $nbdry; |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
2
|
|
|
|
|
6
|
$bdry = "--$bdry(--)?\r\n"; |
95
|
2
|
|
|
|
|
52
|
my @pairs = split /$bdry/ms, $buffer; |
96
|
|
|
|
|
|
|
|
97
|
2
|
|
|
|
|
5
|
my (%param, %filename, %mimetype); |
98
|
2
|
|
|
|
|
6
|
foreach my $pair (@pairs) { |
99
|
16
|
100
|
|
|
|
27
|
next if !defined $pair; |
100
|
10
|
|
|
|
|
12
|
chop $pair; # Trailing \015 |
101
|
10
|
|
|
|
|
10
|
chop $pair; # Trailing \012 |
102
|
10
|
50
|
|
|
|
18
|
last if $pair eq q{--}; |
103
|
10
|
100
|
|
|
|
17
|
next if !$pair; |
104
|
|
|
|
|
|
|
|
105
|
6
|
|
|
|
|
21
|
my ($header, $data) = split /\r\n\r\n/ms, $pair, 2; |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# parse the header |
108
|
6
|
|
|
|
|
17
|
$header =~ s/\r\n/\n/msg; |
109
|
6
|
|
|
|
|
13
|
my @headerlines = split /\n/ms, $header; |
110
|
6
|
|
|
|
|
7
|
my ($name, $filename, $mimetype); |
111
|
|
|
|
|
|
|
|
112
|
6
|
|
|
|
|
9
|
foreach my $headfield (@headerlines) { |
113
|
8
|
|
|
|
|
17
|
my ($fname, $fdata) = split /: /ms, $headfield, 2; |
114
|
8
|
100
|
|
|
|
19
|
if (lc $fname eq 'content-type') { |
115
|
2
|
|
|
|
|
2
|
$mimetype = $fdata; |
116
|
|
|
|
|
|
|
} |
117
|
8
|
100
|
|
|
|
15
|
if (lc $fname eq 'content-disposition') { |
118
|
6
|
|
|
|
|
13
|
my @dispositionlist = split /; /ms, $fdata; |
119
|
6
|
|
|
|
|
9
|
foreach my $dispitem (@dispositionlist) { |
120
|
14
|
100
|
|
|
|
23
|
next if $dispitem eq 'form-data'; |
121
|
8
|
|
|
|
|
14
|
my ($dispfield,$dispdata) = split /=/ms, $dispitem, 2; |
122
|
8
|
|
|
|
|
21
|
$dispdata =~ s/\A\"//ms; |
123
|
8
|
|
|
|
|
19
|
$dispdata =~ s/\"\z//ms; |
124
|
8
|
100
|
|
|
|
15
|
if ($dispfield eq 'name') { |
125
|
6
|
|
|
|
|
9
|
$name = $dispdata; |
126
|
|
|
|
|
|
|
} |
127
|
8
|
100
|
|
|
|
17
|
if ($dispfield eq 'filename') { |
128
|
2
|
|
|
|
|
4
|
$filename = $dispdata; |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
} |
133
|
6
|
50
|
|
|
|
11
|
next if !defined $name; |
134
|
6
|
50
|
|
|
|
8
|
next if !defined $data; |
135
|
|
|
|
|
|
|
|
136
|
6
|
|
|
|
|
7
|
push @{ $param{$name} }, $data; |
|
6
|
|
|
|
|
14
|
|
137
|
6
|
|
|
|
|
14
|
push @{ $filename{$name} }, $filename; |
|
6
|
|
|
|
|
17
|
|
138
|
6
|
|
|
|
|
7
|
push @{ $mimetype{$name} }, $mimetype; |
|
6
|
|
|
|
|
18
|
|
139
|
|
|
|
|
|
|
} |
140
|
2
|
|
|
|
|
8
|
return (\%param, \%filename, \%mimetype); |
141
|
3
|
|
|
3
|
|
1787
|
} |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
17
|
|
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
### Unrelated to CGI, and thus internal/undocumented |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub _quote { |
147
|
10
|
|
|
10
|
|
14
|
my ($s) = @_; |
148
|
10
|
50
|
|
|
|
15
|
croak 'can\'t quote undefined value' if !defined $s; |
149
|
10
|
100
|
|
|
|
28
|
if ($s =~ / \s | ' | \A\z /xms) { |
150
|
2
|
|
|
|
|
4
|
$s =~ s/'/''/xmsg; |
151
|
2
|
|
|
|
|
3
|
$s = "'$s'"; |
152
|
|
|
|
|
|
|
} |
153
|
10
|
|
|
|
|
30
|
return $s; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub _unquote { |
157
|
12
|
|
|
12
|
|
62
|
my ($s) = @_; |
158
|
12
|
100
|
|
|
|
21
|
if ($s =~ s/\A'(.*)'\z/$1/xms) { |
159
|
1
|
|
|
|
|
3
|
$s =~ s/''/'/xmsg; |
160
|
|
|
|
|
|
|
} |
161
|
12
|
|
|
|
|
43
|
return $s; |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
sub quote_list :Export { |
165
|
4
|
|
|
4
|
0
|
8
|
return join q{ }, map {_quote($_)} @_; |
|
10
|
|
|
|
|
16
|
|
166
|
3
|
|
|
3
|
|
999
|
} |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
20
|
|
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
sub unquote_list :Export { |
169
|
22
|
|
|
22
|
0
|
45
|
my ($s) = @_; |
170
|
22
|
100
|
|
|
|
42
|
return if !defined $s; |
171
|
3
|
|
|
|
|
5
|
my @w; |
172
|
3
|
|
|
|
|
25
|
while ($s =~ /\G ( [^'\s]+ | '[^']*(?:''[^']*)*' ) (?:\s+|\z)/xmsgc) { |
173
|
12
|
|
|
|
|
19
|
my $w = $1; |
174
|
12
|
|
|
|
|
17
|
push @w, _unquote($w); |
175
|
|
|
|
|
|
|
} |
176
|
3
|
50
|
|
|
|
11
|
return if $s !~ /\G\z/xmsg; |
177
|
3
|
|
|
|
|
6
|
return \@w; |
178
|
3
|
|
|
3
|
|
806
|
} |
|
3
|
|
|
|
|
20
|
|
|
3
|
|
|
|
|
12
|
|
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
sub unquote_hash :Export { |
181
|
22
|
|
|
22
|
0
|
36
|
my $w = unquote_list(@_); |
182
|
22
|
100
|
66
|
|
|
75
|
return $w && $#{$w} % 2 ? { @{$w} } : undef; |
|
3
|
|
|
|
|
13
|
|
183
|
3
|
|
|
3
|
|
560
|
} |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
9
|
|
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
1; # Magic true value required at end of module |
187
|
|
|
|
|
|
|
__END__ |