more unicode fixes
John Napiorkowski [Mon, 24 Nov 2014 22:28:33 +0000 (16:28 -0600)]
lib/Catalyst.pm
lib/Catalyst/Engine.pm
lib/Catalyst/Request.pm
t/utf_incoming.t

index 1b73f23..7c20e93 100644 (file)
@@ -2279,7 +2279,24 @@ Prepares body parameters.
 
 sub prepare_body_parameters {
     my $c = shift;
-    $c->engine->prepare_body_parameters( $c, @_ );
+    $c->request->prepare_body_parameters( $c, @_ );
+
+    # If we have an encoding configured (like UTF-8) in general we expect a client
+    # to POST with the encoding we fufilled the request in. Otherwise don't do any
+    # encoding (good change wide chars could be in HTML entity style llike the old
+    # days -JNAP
+
+    # so, now that HTTP::Body prepared the body params, we gotta 'walk' the structure
+    # and do any needed decoding.
+
+    # This only does something if the encoding is set via the encoding param.  Remember
+    # this is assuming the client is not bad and responds with what you provided.  In
+    # general you can just use utf8 and get away with it.
+
+    if($c->encoding) {
+        my $current_parameters = $c->request->body_parameters;
+        $c->request->body_parameters($c->_handle_unicode_decoding($current_parameters));
+    }
 }
 
 =head2 $c->prepare_connection
@@ -2566,18 +2583,7 @@ sub prepare_uploads {
     my $enc = $c->encoding;
     return unless $enc;
 
-    # Uggg we hook prepare uploads to do the encoding crap on post and query
-    # parameters!  Cargo culted from old encoding plugin.  Sorry -jnap
-    for my $key (qw/ parameters query_parameters body_parameters /) {
-        for my $value ( values %{ $c->request->{$key} } ) {
-            # N.B. Check if already a character string and if so do not try to double decode.
-            #      http://www.mail-archive.com/catalyst@lists.scsys.co.uk/msg02350.html
-            #      this avoids exception if we have already decoded content, and is _not_ the
-            #      same as not encoding on output which is bad news (as it does the wrong thing
-            #      for latin1 chars for example)..
-            $value = $c->_handle_unicode_decoding($value);
-        }
-    }
+    ## Only trying to decode the filenames.
     for my $value ( values %{ $c->request->uploads } ) {
         # skip if it fails for uploads, as we don't usually want uploads touched
         # in any way
@@ -3115,8 +3121,10 @@ sub _handle_unicode_decoding {
         return $value;
     }
     elsif ( ref $value eq 'HASH' ) {
-        foreach ( values %$value ) {
-            $_ = $self->_handle_unicode_decoding($_);
+        foreach (keys %$value) {
+            my $encoded_key = $self->_handle_param_unicode_decoding($_);
+            $value->{$encoded_key} = $self->_handle_unicode_decoding($value->{$_});
+            delete $value->{$_};
         }
         return $value;
     }
index 927d363..71a743d 100644 (file)
@@ -7,16 +7,12 @@ use CGI::Simple::Cookie;
 use Data::Dump qw/dump/;
 use Errno 'EWOULDBLOCK';
 use HTML::Entities;
-use HTTP::Body;
 use HTTP::Headers;
-use URI::QueryParam;
 use Plack::Loader;
 use Catalyst::EngineLoader;
-use Encode ();
+use Encode 2.21 'decode_utf8';
 use Plack::Request::Upload;
 use Hash::MultiValue;
-use utf8;
-
 use namespace::clean -except => 'meta';
 
 # Amount of data to read from input on each pass
@@ -593,7 +589,9 @@ sub prepare_query_parameters {
     # Check for keywords (no = signs)
     # (yes, index() is faster than a regex :))
     if ( index( $query_string, '=' ) < 0 ) {
-        $c->request->query_keywords($self->unescape_uri($query_string));
+        my $keywords = $self->unescape_uri($query_string);
+        $keywords = decode_utf8 $keywords;
+        $c->request->query_keywords();
         return;
     }
 
@@ -607,10 +605,13 @@ sub prepare_query_parameters {
     for my $item ( @params ) {
 
         my ($param, $value)
-            = map { $self->unescape_uri($_) }
+            = map { decode_utf8($self->unescape_uri($_)) }
               split( /=/, $item, 2 );
 
-        $param = $self->unescape_uri($item) unless defined $param;
+        unless(defined $param) {
+            $param = $self->unescape_uri($item);
+            $param = decode_utf8 $param;
+        }
 
         if ( exists $query{$param} ) {
             if ( ref $query{$param} ) {
index df5f68a..7b41cfe 100644 (file)
@@ -10,7 +10,7 @@ use HTTP::Headers;
 use Stream::Buffered;
 use Hash::MultiValue;
 use Scalar::Util;
-
+use HTTP::Body;
 use Moose;
 
 use namespace::clean -except => 'meta';
index 9a3d2d8..7e2888d 100644 (file)
@@ -2,6 +2,7 @@ use utf8;
 use warnings;
 use strict;
 use Test::More;
+use HTTP::Request::Common;
 
 # Test cases for incoming utf8 
 
@@ -42,7 +43,7 @@ use Test::More;
 ok my $psgi = MyApp->psgi_app, 'build psgi app';
 
 use Catalyst::Test 'MyApp';
-use Encode 2.21 'decode_utf8';
+use Encode 2.21 'decode_utf8', 'encode_utf8';
 
 {
   my $res = request "/root/♥";
@@ -69,12 +70,20 @@ use Encode 2.21 'decode_utf8';
 }
 
 {
-  my $res = request "/base/♥?♥=♥♥";
+  my ($res, $c) = ctx_request POST "/base/♥?♥=♥&♥=♥♥", [a=>1, b=>'', '♥'=>'♥', '♥'=>'♥♥'];
 
   is $res->code, 200, 'OK';
   is decode_utf8($res->content), '<p>This is base-link action ♥</p>', 'correct body';
   is $res->content_length, 35, 'correct length';
+  is $c->req->parameters->{'♥'}[0], '♥';
+  is $c->req->query_parameters->{'♥'}[0], '♥';
+  is $c->req->body_parameters->{'♥'}[0], '♥';
+  is $c->req->parameters->{'♥'}[0], '♥';
 }
 
+## tests for args and captureargs (chained and otherise)
+## warn $c->req->uri; (seemsto be pre encodinged and all
+## test what uri_for looks like in responses 
+
 
 done_testing;