File Coverage

blib/lib/POE/XUL/Request.pm
Criterion Covered Total %
statement 34 126 26.9
branch 5 52 9.6
condition 0 6 0.0
subroutine 10 17 58.8
pod 1 9 11.1
total 50 210 23.8


line stmt bran cond sub pod time code
1             package POE::XUL::Request;
2             # $Id: Request.pm 1566 2010-11-03 03:13:32Z fil $
3             # Copyright Philip Gwyn 2007-2010. All rights reserved.
4              
5 15     15   464 use strict;
  15         14  
  15         414  
6 15     15   45 use warnings;
  15         12  
  15         302  
7              
8 15     15   54 use Carp;
  15         22  
  15         679  
9 15     15   440 use HTTP::Status;
  15         3243  
  15         3068  
10 15     15   68 use POE::XUL::Logging;
  15         13  
  15         675  
11 15     15   7020 use Unicode::String qw( latin1 utf8 );
  15         41414  
  15         884  
12              
13 15     15   78 use constant DEBUG => 0;
  15         18  
  15         821  
14              
15 15     15   59 use base 'POE::Component::Server::HTTP::Request';
  15         16  
  15         13326  
16              
17             our $VERSION = '0.0601';
18              
19             ##############################################################
20             # Rebless an HTTP::Request to us, so we can add the param argument
21             sub new
22             {
23 0     0 1 0 my( $package, $req ) = @_;
24              
25 0         0 my $self = bless $req, $package;
26              
27 0         0 my $rv = $self->parse_args;
28 0 0       0 return $rv if $rv;
29 0         0 return $self;
30             }
31              
32             ##############################################################
33             # Get the arguments out of a request
34             sub parse_args
35             {
36 0     0 0 0 my( $self ) = @_;
37 0         0 my $P;
38 0 0       0 return if $self->{P};
39              
40 0         0 local $ENV{QUERY_STRING};
41 0         0 my $method = $self->method;
42 0 0       0 if( $method eq 'GET' ) {
    0          
43             # TODO: is query UTF-8?
44 0         0 DEBUG and
45             xdebug "GET: ", $self->uri->query;
46 0         0 $P = $self->decode_urlencoded( $self->uri->query );
47             }
48             elsif( $method eq 'POST' ) {
49 0         0 $P = $self->parse_post_args;
50 0 0       0 return $P unless ref $P;
51             }
52             else {
53 0         0 return RC_METHOD_NOT_ALLOWED;
54             }
55              
56             ####
57 0         0 $self->{P} = $P;
58 0         0 return;
59             }
60              
61             sub pre_log
62             {
63 0     0 0 0 my( $self ) = @_;
64 0         0 my $P = $self->{P};
65 0         0 xwarn "Request=", join( ' ', map { "$_:@{$P->{$_}}" } sort keys %$P), "\n";
  0         0  
  0         0  
66 0         0 return;
67             }
68              
69             ##############################################################
70             # Get a request parameter. Uses the P hash created in parse_args()
71             sub param
72             {
73 43     43 0 4107 my( $self, $key, $value ) = @_;
74 43 100       62 if( 3==@_ ) {
75 8 50       14 if( ref $value ) {
76 0         0 $self->{P}{$key} = $value;
77             }
78             else {
79 8         31 $self->{P}{$key} = [ $value ];
80             }
81             }
82 43         35 my $V = $self->{P}->{$key};
83 43 100       80 return $V->[0] unless wantarray();
84 16         32 return @$V;
85             }
86              
87             sub params
88             {
89 8     8 0 6 my( $self ) = @_;
90 8         7 return keys %{$self->{P}};
  8         26  
91             }
92              
93             ##############################################################
94             sub parse_post_args
95             {
96 0     0 0   my( $self ) = @_;
97              
98             # NOTE : this might/will fail if we use a different
99             # content-type. In which case, we have to move to Apache::Request
100             # Also, maybe we should look at $request->dencoded_content;
101              
102 0           my $C = $self->content;
103              
104 0           if( 1 ) {
105 0           my $bad = 0;
106             # This code was to handle over-long requests. But it
107             # turned out the bug was in fact in POE::Filter::HTTPD
108 0           my $l = $self->header('Content-Length');
109 0 0         if( $l != length( $C ) ) { # MSIE5.01 does this
110 0           xlog "WRONG LENGTH";
111 0           $C = substr( $C, 0, $l );
112 0           $bad++;
113             }
114 0 0         $bad++ if $C =~ s/%0D%0A/%0A/g; # I hate you milkman MSIE!
115 0 0         $bad++ if $C =~ s/%0D/%0A/g;
116 0 0         $bad++ if $C =~ s/\r\n/\n/g;
117 0 0         if( $bad ) {
118 0           xlog "Broken User-Agent = ", $self->header('User-Agent');
119 0           $self->content( $C );
120 0           $self->header( 'Content-Length' => length( $C ) );
121             }
122             }
123              
124 0           my $ct = $self->header( 'Content-Type' );
125 0           my $charset = '';
126 0 0         if( $ct =~ s/; charset=(.+)// ) {
127 0           $charset = $1;
128             }
129 0           DEBUG and xdebug "POST ct=$ct -- charset=$charset";
130 0 0 0       if( $ct eq 'application/x-www-form-urlencoded' ) {
    0          
131 0           return $self->decode_urlencoded( $C, $charset );
132             }
133             elsif( $ct eq 'application/json' or $ct eq 'text/json' ) {
134             # TODO : request might be an array of requests!
135 0           return $self->decode_json ( $C );
136             }
137 0           xwarn "Unable to parse $ct";
138 0           return RC_UNSUPPORTED_MEDIA_TYPE;
139             }
140              
141             ##############################################################
142             sub decode_json
143             {
144 0     0 0   my( $self, $C ) = @_;
145 0           my $args = eval {
146 0 0         if( $JSON::XS::VERSION > 2 ) {
147 0           return JSON::XS::decode_json( $C )
148             }
149             else {
150 0           return JSON::XS::from_json( $C )
151             }
152             };
153 0 0         if( $@ ) {
154 0           xwarn "JSON error: $@";
155 0           return RC_BAD_REQUEST;
156             }
157 0 0         unless( 'HASH' eq ref $args ) {
158 0           return RC_UNSUPPORTED_MEDIA_TYPE;
159             }
160 0           my $P = {};
161 0           while( my( $k, $v ) = each %$args ) {
162 0 0         if( ref $v ) {
163 0           $P->{$k} = $v;
164             }
165             else {
166 0           $P->{$k} = [ $v ];
167             }
168             }
169 0           return $P;
170             }
171              
172             ##############################################################
173             sub decode_urlencoded
174             {
175 0     0 0   my( $self, $C, $charset ) = @_;
176              
177 0 0         return $C unless defined $C;
178 0           my $form;
179              
180 0           foreach my $bit ( split /&/, $C ) {
181 0           my( $key, $value ) = split "=", $bit, 2;
182              
183 0           $key = $self->decode_urlencoded_value( $key, $charset );
184 0           $value = $self->decode_urlencoded_value( $value, $charset );
185 0 0         unless( exists $form->{$key} ) {
186 0           $form->{$key} = [ $value ];
187             } else {
188 0           push @{ $form->{$key} }, $value;
  0            
189             }
190             }
191              
192 0           return $form;
193             }
194              
195             ##############################################################
196             sub decode_urlencoded_value
197             {
198 0     0 0   my( $self, $value, $charset ) = @_;
199 0 0 0       return '' unless defined $value and $value ne '';
200 0           $value =~ tr/+/ /;
201 0           $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/egs;
  0            
202              
203 0 0         return $value unless $charset;
204              
205 0           my $U;
206 0 0         if( $charset eq 'UTF-8' ) {
207 0           $U = utf8( $value );
208             }
209            
210 0 0         if( defined $U ) {
211 0           return $U->latin1;
212             }
213 0           xwarn "Failed to decode $charset string";
214 0           return $value;
215             }
216              
217             1;