File Coverage

blib/lib/WebDAO/CV.pm
Criterion Covered Total %
statement 108 148 72.9
branch 28 56 50.0
condition 14 27 51.8
subroutine 17 19 89.4
pod 8 11 72.7
total 175 261 67.0


line stmt bran cond sub pod time code
1             #===============================================================================
2             #
3             # DESCRIPTION: controller
4             #
5             # AUTHOR: Aliaksandr P. Zahatski,
6             #===============================================================================
7             #$Id$
8             package WebDAO::CV;
9             our $VERSION = '0.01';
10 5     5   4646 use URI;
  5         21462  
  5         133  
11 5     5   919 use Data::Dumper;
  5         6106  
  5         254  
12 5     5   31 use strict;
  5         7  
  5         107  
13 5     5   25 use warnings;
  5         11  
  5         125  
14 5     5   3638 use HTTP::Body;
  5         227748  
  5         149  
15 5     5   628 use WebDAO::Base;
  5         10  
  5         459  
16 5     5   23 use base qw( WebDAO::Base );
  5         11  
  5         7763  
17              
18             __PACKAGE__->mk_attr(status=>200, _parsed_cookies=>undef);
19              
20             sub new {
21 13     13 1 14587 my $class = shift;
22 13 50 33     157 my $self = bless( ( $#_ == 0 ) ? shift : {@_}, ref($class) || $class );
23 13         86 $self->{headers} = {};
24 13         185 $self
25             }
26              
27             =head2 url (-options1=>1)
28              
29             from url: http://testwd.zag:82/Envs/partsh.sd?23=23
30             where options:
31            
32             -path_info -> /Envs/partsh.sd
33             -base -> http://example.com:82
34              
35             defaul http://testwd.zag:82/Envs/partsh.sd?23=23
36            
37             =cut
38              
39             sub url {
40 20     20 1 1197 my $self = shift;
41 20         59 my %args = @_;
42 20         40 my $env = $self->{env};
43              
44 20 100       68 if ( exists $env->{FCGI_ROLE} ) {
45             ( $env->{PATH_INFO}, $env->{QUERY_STRING} ) =
46 4         36 $env->{REQUEST_URI} =~ /([^?]*)(?:\?(.*)$)?/s;
47             }
48 20   100     89 my $path = $env->{PATH_INFO} || ''; # 'PATH_INFO' => '/Env'
49 20   100     76 my $host = $env->{HTTP_HOST} || 'example.org'; # 'HTTP_HOST' => '127.0.0.1:5000'
50 20   100     85 my $query = $env->{QUERY_STRING}|| ''; # 'QUERY_STRING' => '434=34&erer=2'
51 20   50     90 my $proto = $env->{'psgi.url_scheme'} || 'http';
52 20         54 my $full_path = "$proto://${host}${path}?$query";
53             #clear / at end
54 20 100       67 $full_path =~ s!/$!! if $path =~ m!^/!;
55 20         101 my $uri = URI->new($full_path);
56              
57 20 100       41632 if ( exists $args{-path_info} ) {
    100          
58 5         35 return $uri->path();
59             }
60             elsif ( exists $args{-base} ) {
61 9         113 return "$proto://$host";
62             }
63 6         20 return URI->new($full_path)->canonical;
64             }
65              
66             =head2 method
67              
68             retrun HTTP method
69              
70             =cut
71              
72             sub method {
73 1     1 1 651 my $self = shift;
74 1 50       8 $self->{env}->{REQUEST_METHOD} || "GET";
75             }
76              
77             =head2
78              
79             return hashref
80              
81             {
82             'application/xhtml+xml' => undef,
83             'application/xml' => undef,
84             'text/html' => undef
85             };
86              
87             =cut
88             sub accept {
89 5     5 0 12 my $self = shift;
90 5   100     178 my $accept = $self->{env}->{HTTP_ACCEPT} || return {};
91 1         3 my ($types) = split( ';', $accept );
92 1         3 my %res;
93 1         10 @res{ split( ',', $types ) } = ();
94 1         10 \%res;
95             }
96              
97             =head2 param
98              
99             return params
100              
101             =cut
102              
103             sub param {
104 9     9 1 18 my $self = shift;
105 9         22 my $params = $self->{parsed_params};
106 9 100       28 unless ($params) {
107             #init by POST params
108 5         25 $params = $self->_parse_body;
109 5         16 my @get_params = $self->url()->query_form;
110 5         1046 while (my ($k, $v) = splice(@get_params,0,2 )) {
111 1 50       4 unless ( exists $params->{ $k } ) {
112 1         6 $params->{ $k } = $v
113             } else {
114 0         0 my $val = $params->{ $k };
115             #if array ?
116 0 0       0 if ( ref $val ) {
117 0         0 push @$val, $v
118             } else {
119 0 0       0 $params->{ $k } = [$val, ref($v) ? @$v : $v]
120             }
121             }
122             }
123 5         17 $self->{parsed_params} = $params;
124             }
125 9 100       56 return keys %$params unless @_;
126 1 50       5 return undef unless exists $params->{$_[0]};
127 1         3 my $res = $params->{$_[0]};
128 1 50       12 if ( ref($res) ) {
129 0 0       0 return wantarray ? @$res : $res->[0]
130             }
131 1         8 return $res;
132             }
133              
134             #parse body
135             sub _parse_body {
136 5     5   9 my $self = shift;
137              
138 5         14 my $content_type = $self->{env}->{CONTENT_TYPE};
139 5         20 my $content_length = $self->{env}->{CONTENT_LENGTH};
140 5 50 33     78 if (!$content_type && !$content_length) {
141 5         14 return {};
142             }
143              
144 0         0 my $body = HTTP::Body->new($content_type, $content_length);
145 0         0 $body->cleanup(1);
146              
147 0         0 my $input = $self->{env}->{'psgi.input'};
148 0 0       0 if ( $input ) {
149             #reset IO
150 0         0 $input->seek(0,0);
151             }
152             else {
153             # for FCGI, Shell
154 0         0 $input = \*STDIN
155             }
156 0         0 my $spin = 0;
157              
158 0         0 while ($content_length) {
159 0 0       0 $input->read(my $chunk, $content_length < 8192 ? $content_length : 8192);
160 0         0 my $read = length $chunk;
161 0         0 $content_length -= $read;
162 0         0 $body->add($chunk);
163 0 0 0     0 if ($read == 0 && $spin++ > 2000) {
164 0         0 Carp::croak "Bad Content-Length: maybe client disconnect? ($content_length bytes remaining)";
165             }
166             }
167 0         0 $self->{'http.body'} = $body;
168 0         0 return $body->param
169             }
170              
171             =head2 body
172              
173             Return HTTP body file descriptor
174              
175             my $body;
176             {
177             local $/;
178             my $fd = $r->get_request->body;
179             $body = <$fd>;
180             }
181              
182             =cut
183              
184             sub body {
185 0     0 1 0 my $self = shift;
186 0 0       0 unless ( exists $self->{'http.body'} ) {
187 0         0 $self->_parse_body();
188             }
189              
190 0   0     0 my $http_body = $self->{'http.body'} || return undef;
191 0         0 return $http_body->body;
192             }
193              
194             =head2 get-body
195              
196             Return HTTP body text
197              
198             my $body= $r->get_request->get_body;
199              
200             =cut
201              
202             sub get_body {
203 0     0 0 0 my $self = shift;
204 0         0 my $body;
205             {
206 0         0 local $/;
  0         0  
207 0 0       0 if ( my $fd = $self->body ) {
208 0         0 $body = <$fd>
209             }
210             }
211 0         0 return $body
212             }
213              
214             =head2 set_header
215              
216             $cv->set_header("Content-Type" => 'text/html; charset=utf-8')
217              
218             =cut
219              
220             sub set_header {
221 5     5 1 17 my ( $self, $name, $par ) = @_;
222              
223             #collect -cookies
224 5 50       18 if ( $name eq 'Set-Cookie' ) {
225 0         0 push @{ $self->{headers}->{$name} }, $par;
  0         0  
226             }
227             else {
228 5         24 $self->{headers}->{$name} = $par;
229             }
230             }
231              
232             =head3 print_headers [ header1=>value, ...]
233              
234             Method for output headers
235              
236             =cut
237              
238             sub print_headers {
239 4     4 1 7 my $self = shift;
240             #save cookie
241 4         10 my $cookie = delete $self->{headers}->{"Set-Cookie"};
242             #merge in and exists headers
243 4         5 my %headers = ( %{ $self->{headers} } , @_ );
  4         16  
244             #merge cookies
245 4 50       13 if ( $cookie ) {
246 0         0 push @{ $headers{"Set-Cookie"} }, @$cookie;
  0         0  
247             }
248 4         8 my @cookies_headers = ();
249             #format cookies
250 4 100       11 if ( my $cookies = delete $headers{"Set-Cookie"} ) {
251 1         3 foreach my $c ( @$cookies ) {
252 2         2 my $hvalue;
253 2 50       6 if (ref($c) eq 'HASH') {
254 2   50     9 my $path = $c->{path} || '/';
255             # Set-Cookie: srote=ewe&1&1&2; path=$path
256 2         7 $hvalue = "$c->{name}=$c->{value}; path=$path";
257 2 100       7 if (my $expires = $c->{expires}) {
258 1         5 my @MON = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
259 1         3 my @WDAY = qw( Sun Mon Tue Wed Thu Fri Sat );
260 1         8 my($sec, $min, $hour, $mday, $mon, $year, $wday) = gmtime($expires);
261 1         2 $year += 1900;
262 1         8 $expires = sprintf("%s, %02d-%s-%04d %02d:%02d:%02d GMT",
263             $WDAY[$wday], $mday, $MON[$mon], $year, $hour, $min, $sec);
264 1         4 $hvalue .=" ;expires=$expires";
265             }
266 0         0 } else { $hvalue = $c }
267 2         5 push @cookies_headers, "Set-Cookie", $hvalue;
268             }
269             }
270 4         98 my $status = $self->status;
271 4   50     36 my $fd = $self->{writer}->([$status||"200", [%headers, @cookies_headers], undef]);
272 4         70 $self->{fd} = $fd;
273             }
274              
275             sub print {
276 1     1 0 3 my $self = shift;
277 1 50       4 if (exists $self->{fd}) {
278 1         3 foreach my $line (@_) {
279 1 50       4 utf8::encode( $line) if utf8::is_utf8($line);
280 1         6 $self->{fd}->write($line);
281             }
282             } else {
283 0         0 print @_;
284             }
285             }
286              
287             =head2 get_cookie
288              
289             return hashref to {key=>value}
290              
291             =cut
292              
293             sub get_cookie {
294 1     1 1 638 my $self = shift;
295 1   50     6 my $str = $self->{env}->{HTTP_COOKIE} || return {};
296 1 50       26 if ($self->_parsed_cookies) { return $self->_parsed_cookies };
  0         0  
297 1         2 my %res;
298             %res =
299 1         6 map { URI::Escape::uri_unescape($_) } map { split '=',$_,2 } split(/\s*[;]\s*/,
  4         22  
  2         6  
300             $str);
301 1         29 $self->_parsed_cookies(\%res);
302 1         14 \%res;
303             }
304              
305              
306             1;
307              
308