[Catalyst-commits] r14096 - in Catalyst-Plugin-Unicode-Encoding/trunk: . lib/Catalyst/Plugin/Unicode t t/lib

t0m at dev.catalyst.perl.org t0m at dev.catalyst.perl.org
Wed Sep 7 20:19:23 GMT 2011


Author: t0m
Date: 2011-09-07 20:19:23 +0000 (Wed, 07 Sep 2011)
New Revision: 14096

Modified:
   Catalyst-Plugin-Unicode-Encoding/trunk/Changes
   Catalyst-Plugin-Unicode-Encoding/trunk/Makefile.PL
   Catalyst-Plugin-Unicode-Encoding/trunk/README
   Catalyst-Plugin-Unicode-Encoding/trunk/lib/Catalyst/Plugin/Unicode/Encoding.pm
   Catalyst-Plugin-Unicode-Encoding/trunk/t/06request_decode.t
   Catalyst-Plugin-Unicode-Encoding/trunk/t/lib/TestApp.pm
Log:
svn merge -r14090:14095 http://dev.catalyst.perl.org/repos/Catalyst/Catalyst-Plugin-Unicode-Encoding/branches/decoding_callback/

Modified: Catalyst-Plugin-Unicode-Encoding/trunk/Changes
===================================================================
--- Catalyst-Plugin-Unicode-Encoding/trunk/Changes	2011-09-07 20:08:24 UTC (rev 14095)
+++ Catalyst-Plugin-Unicode-Encoding/trunk/Changes	2011-09-07 20:19:23 UTC (rev 14096)
@@ -1,5 +1,9 @@
 Revision history for Perl extension Catalyst::Plugin::Unicode::Encoding
 
+1.2
+    - Use a callback in failed decoding process so that the app has a chance
+      to handle it nicely
+
 1.1 2010-07-05 17:52:00
     - Skip Mech tests unless TWMC is a high enough version. (RT#55302)
     - Move Pod tests to only run for module authors

Modified: Catalyst-Plugin-Unicode-Encoding/trunk/Makefile.PL
===================================================================
--- Catalyst-Plugin-Unicode-Encoding/trunk/Makefile.PL	2011-09-07 20:08:24 UTC (rev 14095)
+++ Catalyst-Plugin-Unicode-Encoding/trunk/Makefile.PL	2011-09-07 20:19:23 UTC (rev 14096)
@@ -8,10 +8,12 @@
 requires 'Catalyst' => '5.80';
 requires 'LWP' => '5.828'; # LWP had unicode fail in 5.8.26
 requires 'URI' => '1.36';
+requires 'Try::Tiny';
 
 author_requires 'Test::WWW::Mechanize::Catalyst' => 0.51;
 test_requires 'Test::More' => '0.88';
 test_requires 'IO::Scalar';
+test_requires 'HTTP::Status';
 
 author_tests 't/author';
 

Modified: Catalyst-Plugin-Unicode-Encoding/trunk/README
===================================================================
--- Catalyst-Plugin-Unicode-Encoding/trunk/README	2011-09-07 20:08:24 UTC (rev 14095)
+++ Catalyst-Plugin-Unicode-Encoding/trunk/README	2011-09-07 20:19:23 UTC (rev 14096)
@@ -32,6 +32,30 @@
         Setups "$c->encoding" with encoding specified in
         "$c->config->{encoding}".
 
+    handle_unicode_encoding_exception ($exception_context)
+        Method called when decoding process for a request fails.
+
+        An $exception_context hashref is provided to allow you to override
+        the behaviour of your application when given data with incorrect
+        encodings.
+
+        The default method throws exceptions in the case of invalid request
+        parameters (resulting in a 500 error), but ignores errors in upload
+        filenames.
+
+        The keys passed in the $exception_context hash are:
+
+        param_value
+            The value which was not able to be decoded.
+
+        error_msg
+            The exception recieved from Encode.
+
+        encoding_step
+            What type of data was being decoded. Valid values are
+            (currently) "params" - for request parameters / arguments /
+            captures and "uploads" - for request upload filenames.
+
 SEE ALSO
     Encode, Encode::Encoding, Catalyst::Plugin::Unicode, Catalyst.
 

Modified: Catalyst-Plugin-Unicode-Encoding/trunk/lib/Catalyst/Plugin/Unicode/Encoding.pm
===================================================================
--- Catalyst-Plugin-Unicode-Encoding/trunk/lib/Catalyst/Plugin/Unicode/Encoding.pm	2011-09-07 20:08:24 UTC (rev 14095)
+++ Catalyst-Plugin-Unicode-Encoding/trunk/lib/Catalyst/Plugin/Unicode/Encoding.pm	2011-09-07 20:19:23 UTC (rev 14096)
@@ -4,11 +4,13 @@
 use base 'Class::Data::Inheritable';
 
 use Carp ();
+use MRO::Compat;
+use Try::Tiny;
+
 use Encode 2.21 ();
+our $CHECK = Encode::FB_CROAK | Encode::LEAVE_SRC;
 
-use MRO::Compat;
-our $VERSION = '1.1';
-our $CHECK   = Encode::FB_CROAK | Encode::LEAVE_SRC;
+our $VERSION = '1.2';
 
 __PACKAGE__->mk_classdata('_encoding');
 
@@ -93,13 +95,22 @@
                 #      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)..
-                $_ = Encode::is_utf8( $_ ) ? $_ : $enc->decode( $_, $CHECK );
+                $_ = $c->_handle_param_unicode_decoding($_);
             }
         }
     }
     for my $value ( values %{ $c->request->uploads } ) {
-        $_->{filename} = $enc->decode( $_->{filename}, $CHECK )
-            for ( ref($value) eq 'ARRAY' ? @{$value} : $value );
+        # skip if it fails for uploads, as we don't usually want uploads touched
+        # in any way
+        $_->{filename} = try {
+        $enc->decode( $_->{filename}, $CHECK )
+    } catch {
+        $c->handle_unicode_encoding_exception({
+            param_value => $_->{filename},
+            error_msg => $_,
+            encoding_step => 'uploads',
+        });
+    } for ( ref($value) eq 'ARRAY' ? @{$value} : $value );
     }
 }
 
@@ -108,10 +119,8 @@
 
     my $ret = $c->next::method(@_);
 
-    my $enc = $c->encoding;
-
     foreach (@{$c->req->arguments}, @{$c->req->captures}) {
-        $_ = Encode::is_utf8( $_ ) ? $_ : $enc->decode( $_, $CHECK );
+      $_ = $c->_handle_param_unicode_decoding($_);
     }
 
     return $ret;
@@ -129,6 +138,28 @@
     return $self->next::method(@_);
 }
 
+sub _handle_param_unicode_decoding {
+    my ( $self, $value ) = @_;
+    my $enc = $self->encoding;
+    return try {
+        Encode::is_utf8( $value ) ?
+            $value
+        : $enc->decode( $value, $CHECK );
+    }
+    catch {
+        $self->handle_unicode_encoding_exception({
+            param_value => $value,
+            error_msg => $_,
+            encoding_step => 'params',
+        });
+    };
+}
+
+sub handle_unicode_encoding_exception {
+    my ( $self, $exception_ctx ) = @_;
+    die $exception_ctx->{error_msg};
+}
+
 1;
 
 __END__
@@ -183,8 +214,38 @@
 
 Setups C<< $c->encoding >> with encoding specified in C<< $c->config->{encoding} >>.
 
+=item handle_unicode_encoding_exception ($exception_context)
+
+Method called when decoding process for a request fails.
+
+An C<$exception_context> hashref is provided to allow you to override the
+behaviour of your application when given data with incorrect encodings.
+
+The default method throws exceptions in the case of invalid request parameters
+(resulting in a 500 error), but ignores errors in upload filenames.
+
+The keys passed in the C<$exception_context> hash are:
+
+=over
+
+=item param_value
+
+The value which was not able to be decoded.
+
+=item error_msg
+
+The exception recieved from L<Encode>.
+
+=item encoding_step
+
+What type of data was being decoded. Valid values are (currently)
+C<params> - for request parameters / arguments / captures
+and C<uploads> - for request upload filenames.
+
 =back
 
+=back
+
 =head1 SEE ALSO
 
 L<Encode>, L<Encode::Encoding>, L<Catalyst::Plugin::Unicode>, L<Catalyst>.

Modified: Catalyst-Plugin-Unicode-Encoding/trunk/t/06request_decode.t
===================================================================
--- Catalyst-Plugin-Unicode-Encoding/trunk/t/06request_decode.t	2011-09-07 20:08:24 UTC (rev 14095)
+++ Catalyst-Plugin-Unicode-Encoding/trunk/t/06request_decode.t	2011-09-07 20:19:23 UTC (rev 14096)
@@ -2,7 +2,7 @@
 
 use strict;
 use warnings;
-use Test::More tests => 7 * 3;
+use Test::More tests => 5 * 5;
 use utf8;
 
 # setup library path
@@ -13,6 +13,7 @@
 use Encode;
 use HTTP::Request::Common;
 use URI::Escape qw/uri_escape_utf8/;
+use HTTP::Status 'is_server_error';
 
 my $encode_str = "\x{e3}\x{81}\x{82}"; # e38182 is japanese 'あ'
 my $decode_str = Encode::decode('utf-8' => $encode_str);
@@ -33,6 +34,13 @@
 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>';
@@ -67,3 +75,8 @@
     ok utf8::is_utf8($foo);
     is $foo => $decode_str;
 }
+
+sub check_fallback {
+  my ( $res, $c ) = ctx_request(shift);
+  ok(!is_server_error($res->code)) or diag('Response code is: ' . $res->code);
+}

Modified: Catalyst-Plugin-Unicode-Encoding/trunk/t/lib/TestApp.pm
===================================================================
--- Catalyst-Plugin-Unicode-Encoding/trunk/t/lib/TestApp.pm	2011-09-07 20:08:24 UTC (rev 14095)
+++ Catalyst-Plugin-Unicode-Encoding/trunk/t/lib/TestApp.pm	2011-09-07 20:19:23 UTC (rev 14096)
@@ -12,4 +12,9 @@
 
 __PACKAGE__->setup;
 
+sub handle_unicode_encoding_exception {
+  my ( $self, $param_value, $error_msg ) = @_;
+  return $param_value;
+}
+
 1;




More information about the Catalyst-commits mailing list