From 4dfa10146f03c375140b04804bc59c3606daeccd Mon Sep 17 00:00:00 2001 From: Andy Wardley Date: Wed, 8 Jan 2014 07:41:15 +0000 Subject: [PATCH] Changed uri/url plugins to use RFC3986 --- lib/Template.pm | 8 ++-- lib/Template/Filters.pm | 68 +++++++++++++++++++++++++-------- lib/Template/Manual/Config.pod | 2 +- lib/Template/Manual/Credits.pod | 23 +++++------ lib/Template/Manual/Filters.pod | 22 ++++++++--- lib/Template/Manual/Intro.pod | 2 +- t/filter.t | 45 ++++++++++++++++++++-- 7 files changed, 127 insertions(+), 43 deletions(-) diff --git a/lib/Template.pm b/lib/Template.pm index 7816e9459..cddfb344c 100644 --- a/lib/Template.pm +++ b/lib/Template.pm @@ -10,7 +10,7 @@ # Andy Wardley # # COPYRIGHT -# Copyright (C) 1996-2013 Andy Wardley. All Rights Reserved. +# Copyright (C) 1996-2014 Andy Wardley. All Rights Reserved. # # This module is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. @@ -32,7 +32,7 @@ use File::Basename; use File::Path; use Scalar::Util qw(blessed); -our $VERSION = '2.25'; +our $VERSION = '2.26'; our $ERROR = ''; our $DEBUG = 0; our $BINMODE = 0 unless defined $BINMODE; @@ -915,11 +915,11 @@ Andy Wardley Eabw@wardley.orgE L =head1 VERSION -Template Toolkit version 2.25, released July 2013. +Template Toolkit version 2.26, released January 2014. =head1 COPYRIGHT -Copyright (C) 1996-2013 Andy Wardley. All Rights Reserved. +Copyright (C) 1996-2014 Andy Wardley. All Rights Reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. diff --git a/lib/Template/Filters.pm b/lib/Template/Filters.pm index 4a1c757b4..6e2298444 100644 --- a/lib/Template/Filters.pm +++ b/lib/Template/Filters.pm @@ -10,7 +10,7 @@ # by Leslie Michael Orchard # # COPYRIGHT -# Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved. +# Copyright (C) 1996-2014 Andy Wardley. All Rights Reserved. # # This module is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. @@ -258,31 +258,60 @@ sub _dump { # -- STATIC FILTER SUBS -- #======================================================================== +#------------------------------------------------------------------------ +# uri_filter() and url_filter() below can match using either RFC3986 or +# RFC2732. See https://github.com/abw/Template2/issues/13 +#----------------------------------------------------------------------- + +our $UNSAFE_SPEC = { + RFC2732 => q{A-Za-z0-9\-_.!~*'()}, + RFC3986 => q{A-Za-z0-9\-\._~"}, +}; +our $UNSAFE_CHARS = $UNSAFE_SPEC->{ RFC2732 }; +our $URI_REGEX; +our $URL_REGEX; +our $URI_ESCAPES; + +sub use_rfc2732 { + $UNSAFE_CHARS = $UNSAFE_SPEC->{ RFC2732 }; + $URI_REGEX = $URL_REGEX = undef; +} + +sub use_rfc3986 { + $UNSAFE_CHARS = $UNSAFE_SPEC->{ RFC3986 }; + $URI_REGEX = $URL_REGEX = undef; +} + +sub uri_escapes { + return { + map { ( chr($_), sprintf("%%%02X", $_) ) } (0..255), + }; +} + #------------------------------------------------------------------------ # uri_filter() [% FILTER uri %] # # URI escape a string. This code is borrowed from Gisle Aas' URI::Escape -# module, copyright 1995-2004. See RFC2396 for details. +# module, copyright 1995-2004. See RFC2396, RFC2732 and RFC3986 for +# details. #----------------------------------------------------------------------- -# cache of escaped characters -our $URI_ESCAPES; - sub uri_filter { my $text = shift; - $URI_ESCAPES ||= { - map { ( chr($_), sprintf("%%%02X", $_) ) } (0..255), - }; + $URI_REGEX ||= qr/([^$UNSAFE_CHARS])/; + $URI_ESCAPES ||= uri_escapes(); if ($] >= 5.008 && utf8::is_utf8($text)) { utf8::encode($text); } - - $text =~ s/([^A-Za-z0-9\-_.!~*'()])/$URI_ESCAPES->{$1}/eg; + + $text =~ s/$URI_REGEX/$URI_ESCAPES->{$1}/eg; $text; } + + #------------------------------------------------------------------------ # url_filter() [% FILTER uri %] # @@ -296,15 +325,14 @@ sub uri_filter { sub url_filter { my $text = shift; - $URI_ESCAPES ||= { - map { ( chr($_), sprintf("%%%02X", $_) ) } (0..255), - }; + $URL_REGEX ||= qr/([^;\/?:@&=+\$,$UNSAFE_CHARS])/; + $URI_ESCAPES ||= uri_escapes(); if ($] >= 5.008 && utf8::is_utf8($text)) { utf8::encode($text); } - $text =~ s/([^;\/?:@&=+\$,A-Za-z0-9\-_.!~*'()])/$URI_ESCAPES->{$1}/eg; + $text =~ s/$URL_REGEX/$URI_ESCAPES->{$1}/eg; $text; } @@ -742,6 +770,16 @@ your system. use Template::Filters; Template::Filters->use_apache_util(); +=head2 use_rfc2732() + +This class method can be called to configure the C and C filters to +use the older RFC2732 standard for matching unsafe characters. + +=head2 use_rfc3986() + +This class method can be called to configure the C and C filters to +use the newer RFC3986 standard for matching unsafe characters. + =head1 CONFIGURATION OPTIONS The following list summarises the configuration options that can be provided @@ -791,7 +829,7 @@ Andy Wardley Eabw@wardley.orgE L =head1 COPYRIGHT -Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved. +Copyright (C) 1996-2014 Andy Wardley. All Rights Reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. diff --git a/lib/Template/Manual/Config.pod b/lib/Template/Manual/Config.pod index 10d142b80..285755eab 100644 --- a/lib/Template/Manual/Config.pod +++ b/lib/Template/Manual/Config.pod @@ -6,7 +6,7 @@ # Andy Wardley # # COPYRIGHT -# Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved. +# Copyright (C) 1996-2014 Andy Wardley. All Rights Reserved. # # This module is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. diff --git a/lib/Template/Manual/Credits.pod b/lib/Template/Manual/Credits.pod index 9cc5dccb9..8d283c408 100644 --- a/lib/Template/Manual/Credits.pod +++ b/lib/Template/Manual/Credits.pod @@ -6,7 +6,7 @@ # Andy Wardley # # COPYRIGHT -# Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved. +# Copyright (C) 1996-2014 Andy Wardley. All Rights Reserved. # # This module is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. @@ -64,7 +64,7 @@ Andy Wardley Eabw@wardley.orgE L =head1 COPYRIGHT -Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved. +Copyright (C) 1996-2014 Andy Wardley. All Rights Reserved. The Template Toolkit is free software; you can redistribute it and/or modify it under the same terms as Perl itself. @@ -78,17 +78,14 @@ Please let me know if you think anyone is missing from this list. Chuck Adams, Stephen Adkins, Ivan Adzhubey, Mark Anderson, Bradley Baetz, Thierry-Michel Barral, Craig Barratt, Stas Bekman, Robin Berjon, Tony Bowden, Neil Bowers, Leon Brocard, Lyle Brooks, Norbert Buchmüller, Dave Cash, Piers -Cawley, Darren Chamberlain, Timmy Chan, Eric Cholet, Nik Clayton, Tosh Cooey, -Dave Cross, Chris Dean, Francois Desarmenien, Horst Dumcke, Mark Fowler, -Michael Fowler, Kenny Gatdula, Axel Gerstmair, Jay Hannah, Dylan William -Hardison, Perrin Harkins, Bryce Harrington, Dave Hodgkinson, Lubomir Host, -Dave Howorth, Jon Jensen, Harald Joerg, Colin Johnson, Colin Keith, Adam -Kennedy, Vivek Khera, Alexey A. Kiritchun, Rafael Kitover, Andreas Koenig, -Ivan Kurmanov, Denis F. Latypoff, Hans von Lengerke, Jonas Liljegren, Simon -Luff, Andy Maas, Paul Makepeace, Gervase Markham, Sergey Martynoff, Simon -Matthews, Robert McArthur, Craig McLane, Myk Melez, Eugene Miretskiy, -Tatsuhiko Miyagawa, Bill Moseley, Keith G. Murphy, Chris Nandor, John -Napiorkowski, Breno G. de Oliveira, Leslie Michael Orchard, Paul Orrock, +Cawley, Darren Chamberlain, Timmy Chan, Eric Cholet, Chromatic, Nik Clayton, +Tosh Cooey, Dave Cross, Chris Dean, Francois Desarmenien, Horst Dumcke, Mark +Fowler, Michael Fowler, Kenny Gatdula, Axel Gerstmair, Jay Hannah, Dylan +William Hardison, Perrin Harkins, Bryce Harrington, Dave Hodgkinson, Lubomir +Host, Dave Howorth, Jon Jensen, Harald Joerg, Colin Johnson, Colin Keith, +Adam Kennedy, Vivek Khera, Alexey A. Kiritchun, Rafael Kitover, Andreas +Koenig, Ivan Kurmanov, Denis F. Latypoff, Hans von Lengerke, Jonas Liljegren, +Simon Napiorkowski, Breno G. de Oliveira, Leslie Michael Orchard, Paul Orrock, Jonathon Padfield, Steve Peters, Briac PilprE, Yuri Pimenov, Martin Portman, Marc Remy, Slaven Rezic, Jess Robinson, Josh Rosenbaum, Christian Schaffner, Mike Schilli, Randal L. Schwartz, Paul Seamons, Paul Sharpe, diff --git a/lib/Template/Manual/Filters.pod b/lib/Template/Manual/Filters.pod index 1033d44a5..f9863be6b 100644 --- a/lib/Template/Manual/Filters.pod +++ b/lib/Template/Manual/Filters.pod @@ -127,7 +127,7 @@ equally as comprehensive) to perform the encoding. If one or other of these modules are installed on your system then the text will be encoded (via the C or C subroutines respectively) to convert all extended characters into their appropriate HTML -entities (e.g. converting 'C<é>' to 'C<é>'). If neither module is +entities (e.g. converting 'C' to 'C<é>'). If neither module is available on your system then an 'C' exception will be thrown reporting an appropriate message. @@ -206,7 +206,7 @@ Output: =head1 uri This filter URI escapes the input text, converting any characters -outside of the permitted URI character set (as defined by RFC 2396) +outside of the permitted URI character set (as defined by RFC 3986) into a C<%nn> hex escape. [% 'my file.html' | uri %] @@ -258,9 +258,21 @@ you should use the B (note spelling) filter for this purpose. Please note that this behaviour was changed in version 2.16 of the Template Toolkit. Prior to that, the uri filter did not encode the reserved characters, making it technically incorrect according to the -RFC 2396 specification. So we fixed it in 2.16 and provided the url -filter to implement the old behaviour of not encoding reserved -characters. +RFC 2396 specification (since superceded by RFC2732 and RFC3986). So we +fixed it in 2.16 and provided the url filter to implement the old behaviour +of not encoding reserved characters. + +As of version 2.26 of the Template Toolkit, the C and L filters +use the unsafe character set defined by RFC3986. This means that certain +characters ("(", ")", "~", "*", "!" and the single quote "'") are now deemed +unsafe and will be escaped as hex character sequences. The double quote +character ('"') is now deemed safe and will not be escaped. + +If you want to enable the old behaviour then call the C +method in L + + use Template::Filters + Template::Filters->use_rfc2732; =head1 url diff --git a/lib/Template/Manual/Intro.pod b/lib/Template/Manual/Intro.pod index d74ba0b98..18351e8b0 100644 --- a/lib/Template/Manual/Intro.pod +++ b/lib/Template/Manual/Intro.pod @@ -6,7 +6,7 @@ # Andy Wardley # # COPYRIGHT -# Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved. +# Copyright (C) 1996-2014 Andy Wardley. All Rights Reserved. # # This module is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. diff --git a/t/filter.t b/t/filter.t index a84c75ec6..17931b58a 100644 --- a/t/filter.t +++ b/t/filter.t @@ -4,16 +4,14 @@ # # Template script testing FILTER directive. # -# Written by Andy Wardley +# Written by Andy Wardley # -# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved. +# Copyright (C) 1996-2014 Andy Wardley. All Rights Reserved. # Copyright (C) 1998-2000 Canon Research Centre Europe Ltd. # # This is free software; you can redistribute it and/or modify it # under the same terms as Perl itself. # -# $Id$ -# #======================================================================== use strict; @@ -77,6 +75,12 @@ my $params = { stderr => sub { $stderr }, despace => bless(\&despace, 'anything'), widetext => "wide:\x{65e5}\x{672c}\x{8a9e}", + use_rfc2732 => sub { + Template::Filters->use_rfc2732; + }, + use_rfc3986 => sub { + Template::Filters->use_rfc3986; + } }; my $filters = { @@ -938,4 +942,37 @@ Foobar -- expect -- fOOBAR +-- test -- +[% "foo(bar)" | uri %] +-- expect -- +foo(bar) + +-- test -- +[% "foo(bar)" | url %] +-- expect -- +foo(bar) + +-- test -- +[% use_rfc3986; + "foo(bar)" | url; +%] +-- expect -- +foo%28bar%29 + +-- test -- +[% "foo(bar)" | uri %] +-- expect -- +foo%28bar%29 + +-- test -- +[% use_rfc2732; + "foo(bar)" | url; +%] +-- expect -- +foo(bar) + +-- test -- +[% "foo(bar)" | uri %] +-- expect -- +foo(bar)