From: John Napiorkowski Date: Tue, 25 Nov 2014 16:00:27 +0000 (-0600) Subject: fixed how upload info is added to parameters X-Git-Tag: 5.90079_001~19 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Runtime.git;a=commitdiff_plain;h=4a62800defdaa16ec1a5bef88f3e639c983b6f1d fixed how upload info is added to parameters --- diff --git a/lib/Catalyst.pm b/lib/Catalyst.pm index 7c20e93..eaf5079 100644 --- a/lib/Catalyst.pm +++ b/lib/Catalyst.pm @@ -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; } diff --git a/lib/Catalyst/Engine.pm b/lib/Catalyst/Engine.pm index 71a743d..b377a63 100644 --- a/lib/Catalyst/Engine.pm +++ b/lib/Catalyst/Engine.pm @@ -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; } diff --git a/t/unicode_plugin_request_decode.t b/t/unicode_plugin_request_decode.t index c3b7171..42a9a72 100644 --- a/t/unicode_plugin_request_decode.t +++ b/t/unicode_plugin_request_decode.t @@ -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 => '

It works

'; 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 => '

It works

'; 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 => '

It works

'; 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; diff --git a/t/utf_incoming.t b/t/utf_incoming.t index 7e2888d..4a697cc 100644 --- a/t/utf_incoming.t +++ b/t/utf_incoming.t @@ -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)