fixed how upload info is added to parameters
John Napiorkowski [Tue, 25 Nov 2014 16:00:27 +0000 (10:00 -0600)]
lib/Catalyst.pm
lib/Catalyst/Engine.pm
t/unicode_plugin_request_decode.t
t/utf_incoming.t

index 7c20e93..eaf5079 100644 (file)
@@ -2579,26 +2579,6 @@ Prepares uploads.
 sub prepare_uploads {
     my $c = shift;
     $c->engine->prepare_uploads( $c, @_ );
-
-    my $enc = $c->encoding;
-    return unless $enc;
-
-    ## 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
-        for my $inner_value ( ref($value) eq 'ARRAY' ? @{$value} : $value ) {
-            $inner_value->{filename} = try {
-                $enc->decode( $inner_value->{filename}, $c->_encode_check )
-            } catch {
-                $c->handle_unicode_encoding_exception({
-                    param_value => $inner_value->{filename},
-                    error_msg => $_,
-                    encoding_step => 'uploads',
-                });
-            };
-        }
-    }
 }
 
 =head2 $c->prepare_write
@@ -3124,7 +3104,10 @@ sub _handle_unicode_decoding {
         foreach (keys %$value) {
             my $encoded_key = $self->_handle_param_unicode_decoding($_);
             $value->{$encoded_key} = $self->_handle_unicode_decoding($value->{$_});
-            delete $value->{$_};
+
+            # If the key was encoded we now have two (the original and current so
+            # delete the original.
+            delete $value->{$_} if $_ ne $encoded_key;
         }
         return $value;
     }
index 71a743d..b377a63 100644 (file)
@@ -669,20 +669,25 @@ sub prepare_uploads {
     my $request = $c->request;
     return unless $request->_body;
 
+    my $enc = $c->encoding;
     my $uploads = $request->_body->upload;
     my $parameters = $request->parameters;
     foreach my $name (keys %$uploads) {
+        $name = $c->_handle_unicode_decoding($name) if $enc;
         my $files = $uploads->{$name};
         my @uploads;
         for my $upload (ref $files eq 'ARRAY' ? @$files : ($files)) {
             my $headers = HTTP::Headers->new( %{ $upload->{headers} } );
+            my $filename = $upload->{filename};
+            $filename = $c->_handle_unicode_decoding($filename) if $enc;
+
             my $u = Catalyst::Request::Upload->new
               (
                size => $upload->{size},
                type => scalar $headers->content_type,
                headers => $headers,
                tempname => $upload->{tempname},
-               filename => $upload->{filename},
+               filename => $filename,
               );
             push @uploads, $u;
         }
index c3b7171..42a9a72 100644 (file)
@@ -1,6 +1,6 @@
 use strict;
 use warnings;
-use Test::More tests => 5 * 5;
+use Test::More;
 use utf8;
 
 # setup library path
@@ -17,42 +17,19 @@ my $encode_str = "\x{e3}\x{81}\x{82}"; # e38182 is japanese 'あ'
 my $decode_str = Encode::decode('utf-8' => $encode_str);
 my $escape_str = uri_escape_utf8($decode_str);
 
-check_parameter(GET "/?foo=$escape_str");
-check_parameter(POST '/', ['foo' => $encode_str]);
-check_parameter(POST '/',
-    Content_Type => 'form-data',
-    Content => [
-        'foo' => [
-            "$Bin/unicode_plugin_request_decode.t",
-            $encode_str,
-        ]
-    ],
-);
-
-check_argument(GET "/$escape_str");
-check_capture(GET "/capture/$escape_str");
-
-# sending non-utf8 data
-my $non_utf8_data = "%C3%E6%CB%AA";
-check_fallback(GET "/?q=${non_utf8_data}");
-check_fallback(GET "/${non_utf8_data}");
-check_fallback(GET "/capture/${non_utf8_data}");
-check_fallback(POST '/', ['foo' => $non_utf8_data]);
-
 sub check_parameter {
     my ( undef, $c ) = ctx_request(shift);
     is $c->res->output => '<h1>It works</h1>';
 
     my $foo = $c->req->param('foo');
-    ok utf8::is_utf8($foo);
-    is $foo => $decode_str;
+    is $foo, $decode_str;
 
     my $other_foo = $c->req->method eq 'POST'
         ? $c->req->upload('foo')
             ? $c->req->upload('foo')->filename
             : $c->req->body_parameters->{foo}
         : $c->req->query_parameters->{foo};
-    ok utf8::is_utf8($other_foo);
+
     is $other_foo => $decode_str;
 }
 
@@ -61,7 +38,6 @@ sub check_argument {
     is $c->res->output => '<h1>It works</h1>';
 
     my $foo = $c->req->args->[0];
-    ok utf8::is_utf8($foo);
     is $foo => $decode_str;
 }
 
@@ -70,7 +46,6 @@ sub check_capture {
     is $c->res->output => '<h1>It works</h1>';
 
     my $foo = $c->req->captures->[0];
-    ok utf8::is_utf8($foo);
     is $foo => $decode_str;
 }
 
@@ -78,3 +53,27 @@ sub check_fallback {
   my ( $res, $c ) = ctx_request(shift);
   ok(!is_server_error($res->code)) or diag('Response code is: ' . $res->code);
 }
+
+check_parameter(GET "/?foo=$escape_str");
+check_parameter(POST '/', ['foo' => $encode_str]);
+check_parameter(POST '/',
+    Content_Type => 'form-data',
+    Content => [
+        'foo' => [
+            "$Bin/unicode_plugin_request_decode.t",
+            $encode_str,
+        ]
+    ],
+);
+
+check_argument(GET "/$escape_str");
+check_capture(GET "/capture/$escape_str");
+
+# sending non-utf8 data
+my $non_utf8_data = "%C3%E6%CB%AA";
+check_fallback(GET "/?q=${non_utf8_data}");
+check_fallback(GET "/${non_utf8_data}");
+check_fallback(GET "/capture/${non_utf8_data}");
+check_fallback(POST '/', ['foo' => $non_utf8_data]);
+
+done_testing;
index 7e2888d..4a697cc 100644 (file)
@@ -79,6 +79,11 @@ use Encode 2.21 'decode_utf8', 'encode_utf8';
   is $c->req->query_parameters->{'♥'}[0], '♥';
   is $c->req->body_parameters->{'♥'}[0], '♥';
   is $c->req->parameters->{'♥'}[0], '♥';
+
+  is $c->req->parameters->{a}, 1;
+  is $c->req->body_parameters->{a}, 1;
+
+
 }
 
 ## tests for args and captureargs (chained and otherise)