properly encode stuff in fragments
John Napiorkowski [Mon, 27 Jul 2015 15:20:54 +0000 (10:20 -0500)]
lib/Catalyst.pm
t/utf_incoming.t

index 82c7534..8bdad88 100644 (file)
@@ -1634,8 +1634,10 @@ sub uri_for {
 
     # remove and save fragment if there is one
     my $fragment;
-    if ($args =~ s/(#.+)$//) {
-      $fragment = $1;
+    if ($args =~ s/#(.+)$//) {
+      $fragment = encode_utf8($1);
+      $fragment =~ s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go;
+      $fragment =~ s/ /+/g;
     }
 
     if (my @keys = keys %$params) {
@@ -1668,7 +1670,7 @@ sub uri_for {
     $args =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
 
     # re-attach fragment on the end of everything after adding params
-    $query .= $fragment if $fragment;
+    $args .= "#$fragment" if $fragment;
 
     my $res = bless(\"${base}${args}${query}", $class);
     $res;
index baa3f2a..2adccb4 100644 (file)
@@ -33,7 +33,7 @@ use Scalar::Util ();
   sub uri_for :Path('uri_for') {
     my ($self, $c) = @_;
     $c->response->content_type('text/html');
-    $c->response->body("${\$c->uri_for($c->controller('Root')->action_for('argend'), ['♥'], '♥', {'♥'=>'♥♥'})}");
+    $c->response->body("${\$c->uri_for($c->controller('Root')->action_for('argend'), ['♥'], '♥#X♥X', {'♥'=>'♥♥'})}");
   }
 
   sub heart_with_arg :Path('a♥') Args(1)  {
@@ -318,12 +318,12 @@ use Catalyst::Test 'MyApp';
 
 {
   my ($res, $c) = ctx_request "/root/uri_for";
-  my $url = $c->uri_for($c->controller('Root')->action_for('argend'), ['♥'], '♥', {'♥'=>'♥♥'});
+  my $url = $c->uri_for($c->controller('Root')->action_for('argend'), ['♥'], '♥#X♥X', {'♥'=>'♥♥'});
 
   is $res->code, 200, 'OK';
   is decode_utf8($res->content), "$url", 'correct body'; #should do nothing
   is $res->content, "$url", 'correct body';
-  is $res->content_length, 90, 'correct length';
+  is $res->content_length, 102, 'correct length';
   is $res->content_charset, 'UTF-8';
 
   {