File Coverage

blib/lib/CGI/PSGI.pm
Criterion Covered Total %
statement 75 101 74.2
branch 23 50 46.0
condition 14 29 48.2
subroutine 10 12 83.3
pod 4 6 66.6
total 126 198 63.6


line stmt bran cond sub pod time code
1             package CGI::PSGI;
2              
3 7     7   298818 use strict;
  7         16  
  7         286  
4 7     7   183 use 5.008_001;
  7         24  
  7         399  
5             our $VERSION = '0.15';
6              
7 7     7   40 use base qw(CGI);
  7         93  
  7         26828  
8              
9             sub new {
10 18     18 1 28526 my($class, $env) = @_;
11 18         87 CGI::initialize_globals();
12              
13 18         401 my $self = bless {
14             psgi_env => $env,
15             use_tempfile => 1,
16             }, $class;
17              
18 18         44 local *ENV = $env;
19 18         40 local $CGI::MOD_PERL = 0;
20 18         126 $self->SUPER::init;
21              
22 18         51044 $self;
23             }
24              
25             sub env {
26 0     0 1 0 $_[0]->{psgi_env};
27             }
28              
29             sub read_from_client {
30 2     2 0 6985 my($self, $buff, $len, $offset) = @_;
31 2         30 $self->{psgi_env}{'psgi.input'}->read($$buff, $len, $offset);
32             }
33              
34             # copied from CGI.pm
35             sub read_from_stdin {
36 0     0 0 0 my($self, $buff) = @_;
37              
38 0         0 my($eoffound) = 0;
39 0         0 my($localbuf) = '';
40 0         0 my($tempbuf) = '';
41 0         0 my($bufsiz) = 1024;
42 0         0 my($res);
43              
44 0         0 while ($eoffound == 0) {
45 0         0 $res = $self->{psgi_env}{'psgi.input'}->read($tempbuf, $bufsiz, 0);
46              
47 0 0       0 if ( !defined($res) ) {
48             # TODO: how to do error reporting ?
49 0         0 $eoffound = 1;
50 0         0 last;
51             }
52 0 0       0 if ( $res == 0 ) {
53 0         0 $eoffound = 1;
54 0         0 last;
55             }
56 0         0 $localbuf .= $tempbuf;
57             }
58              
59 0         0 $$buff = $localbuf;
60              
61 0         0 return $res;
62             }
63              
64             # copied and rearanged from CGI::header
65             sub psgi_header {
66 12     12 1 3280 my($self, @p) = @_;
67              
68 12         20 my(@header);
69              
70 12         108 my($type,$status,$cookie,$target,$expires,$nph,$charset,$attachment,$p3p,@other) =
71             CGI::rearrange([['TYPE','CONTENT_TYPE','CONTENT-TYPE'],
72             'STATUS',['COOKIE','COOKIES'],'TARGET',
73             'EXPIRES','NPH','CHARSET',
74             'ATTACHMENT','P3P'],@p);
75              
76             # CR escaping for values, per RFC 822
77 12         1419 for my $header ($type,$status,$cookie,$target,$expires,$nph,$charset,$attachment,$p3p,@other) {
78 100 100       200 if (defined $header) {
79             # From RFC 822:
80             # Unfolding is accomplished by regarding CRLF immediately
81             # followed by a LWSP-char as equivalent to the LWSP-char.
82 24         127 $header =~ s/$CGI::CRLF(\s)/$1/g;
83              
84             # All other uses of newlines are invalid input.
85 24 100       241 if ($header =~ m/$CGI::CRLF|\015|\012/) {
86             # shorten very long values in the diagnostic
87 6 50       19 $header = substr($header,0,72).'...' if (length $header > 72);
88 6         73 die "Invalid header value contains a newline not followed by whitespace: $header";
89             }
90             }
91             }
92              
93 6 50 0     28 $type ||= 'text/html' unless defined($type);
94 6 50       21 if (defined $charset) {
95 0         0 $self->charset($charset);
96             } else {
97 6 100       46 $charset = $self->charset if $type =~ /^text\//;
98             }
99 6   100     82 $charset ||= '';
100              
101             # rearrange() was designed for the HTML portion, so we
102             # need to fix it up a little.
103 6         8 my @other_headers;
104 6         18 for (@other) {
105             # Don't use \s because of perl bug 21951
106 3 50       33 next unless my($header,$value) = /([^ \r\n\t=]+)=\"?(.+?)\"?$/;
107 3         14 $header =~ s/^(\w)(.*)/"\u$1\L$2"/e;
  3         15  
108 3         71 push @other_headers, $header, $self->unescapeHTML($value);
109             }
110              
111 6 50 66     214 $type .= "; charset=$charset"
      66        
      33        
112             if $type ne ''
113             and $type !~ /\bcharset\b/
114             and defined $charset
115             and $charset ne '';
116              
117             # Maybe future compatibility. Maybe not.
118 6   50     28 my $protocol = $self->{psgi_env}{SERVER_PROTOCOL} || 'HTTP/1.0';
119              
120 6 50       17 push(@header, "Window-Target", $target) if $target;
121 6 50       19 if ($p3p) {
122 0 0       0 $p3p = join ' ',@$p3p if ref($p3p) eq 'ARRAY';
123 0         0 push(@header,"P3P", qq(policyref="/w3c/p3p.xml", CP="$p3p"));
124             }
125              
126             # push all the cookies -- there may be several
127 6 50       24 if ($cookie) {
128 0 0 0     0 my(@cookie) = ref($cookie) && ref($cookie) eq 'ARRAY' ? @{$cookie} : $cookie;
  0         0  
129 0         0 for (@cookie) {
130 0 0       0 my $cs = UNIVERSAL::isa($_,'CGI::Cookie') ? $_->as_string : $_;
131 0 0       0 push(@header,"Set-Cookie", $cs) if $cs ne '';
132             }
133             }
134             # if the user indicates an expiration time, then we need
135             # both an Expires and a Date header (so that the browser is
136             # uses OUR clock)
137 6 50       37 push(@header,"Expires", CGI::expires($expires,'http'))
138             if $expires;
139 6 50 33     53 push(@header,"Date", CGI::expires(0,'http')) if $expires || $cookie || $nph;
      33        
140 6 50       118 push(@header,"Pragma", "no-cache") if $self->cache();
141 6 50       752 push(@header,"Content-Disposition", "attachment; filename=\"$attachment\"") if $attachment;
142 6         15 push(@header, @other_headers);
143              
144 6 100       26 push(@header,"Content-Type", $type) if $type ne '';
145              
146 6   100     26 $status ||= "200";
147 6         46 $status =~ s/\D*$//;
148              
149 6         45 return $status, \@header;
150             }
151              
152             # Ported from CGI.pm's redirect() method.
153             sub psgi_redirect {
154 6     6 1 8164 my ($self,@p) = @_;
155 6         47 my($url,$target,$status,$cookie,$nph,@other) =
156             CGI::rearrange([['LOCATION','URI','URL'],'TARGET','STATUS',['COOKIE','COOKIES'],'NPH'],@p);
157 6 50       398 $status = '302 Found' unless defined $status;
158 6   66     60 $url ||= $self->self_url;
159 6         114 my(@o);
160 6         13 for (@other) { tr/\"//d; push(@o,split("=",$_,2)); }
  4         12  
  4         19  
161 6         23 unshift(@o,
162             '-Status' => $status,
163             '-Location'=> $url,
164             '-nph' => $nph);
165 6 50       21 unshift(@o,'-Target'=>$target) if $target;
166 6         355 unshift(@o,'-Type'=>'');
167 6         9 my @unescaped;
168 6 50       15 unshift(@unescaped,'-Cookie'=>$cookie) if $cookie;
169 6         15 return $self->psgi_header((map {$self->unescapeHTML($_)} @o),@unescaped);
  56         3836  
170             }
171              
172             # The list is auto generated and modified with:
173             # perl -nle '/^sub (\w+)/ and $sub=$1; \
174             # /^}\s*$/ and do { print $sub if $code{$sub} =~ /([\%\$]ENV|http\()/; undef $sub };\
175             # $code{$sub} .= "$_\n" if $sub; \
176             # /^\s*package [^C]/ and exit' \
177             # `perldoc -l CGI`
178             for my $method (qw(
179             url_param
180             url
181             cookie
182             raw_cookie
183             _name_and_path_from_env
184             request_method
185             content_type
186             path_translated
187             request_uri
188             Accept
189             user_agent
190             virtual_host
191             remote_host
192             remote_addr
193             referrer
194             server_name
195             server_software
196             virtual_port
197             server_port
198             server_protocol
199             http
200             https
201             remote_ident
202             auth_type
203             remote_user
204             user_name
205             read_multipart
206             read_multipart_related
207             )) {
208 7     7   159551 no strict 'refs';
  7         19  
  7         1241  
209             *$method = sub {
210 90     90   32137 my $self = shift;
211 90         181 my $super = "SUPER::$method";
212 90         249 local *ENV = $self->{psgi_env};
213 90         1672 $self->$super(@_);
214             };
215             }
216              
217             sub DESTROY {
218 18     18   12137 my $self = shift;
219 18         67 CGI::initialize_globals();
220             }
221              
222             1;
223             __END__