-
-
Save anonymous/4b50c57e75785fb2d91f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Changes b/Changes | |
index 5a57ba3..42394eb 100644 | |
--- a/Changes | |
+++ b/Changes | |
@@ -1,6 +1,7 @@ | |
5.60 2014-11-11 | |
- Added to_array method to Mojo::Collection. | |
+ - Added xss_escape function to Mojo::Util. | |
- Updated Net::DNS::Native requirement to 0.12 for some important bug fixes. | |
5.59 2014-11-07 | |
diff --git a/lib/Mojo/Template.pm b/lib/Mojo/Template.pm | |
index e025c25..78d4407 100644 | |
--- a/lib/Mojo/Template.pm | |
+++ b/lib/Mojo/Template.pm | |
@@ -14,7 +14,7 @@ has capture_end => 'end'; | |
has capture_start => 'begin'; | |
has comment_mark => '#'; | |
has encoding => 'UTF-8'; | |
-has escape => sub { \&Mojo::Util::xml_escape }; | |
+has escape => sub { \&Mojo::Util::xss_escape }; | |
has [qw(escape_mark expression_mark trim_mark)] => '='; | |
has [qw(line_start replace_mark)] => '%'; | |
has name => 'template'; | |
@@ -264,11 +264,7 @@ sub _wrap { | |
my ($self, $code) = @_; | |
# Escape function | |
- my $escape = $self->escape; | |
- monkey_patch $self->namespace, _escape => sub { | |
- no warnings 'uninitialized'; | |
- ref $_[0] eq 'Mojo::ByteStream' ? $_[0] : $escape->("$_[0]"); | |
- }; | |
+ monkey_patch $self->namespace, '_escape', $self->escape; | |
# Wrap lines | |
my $num = () = $code =~ /\n/g; | |
@@ -493,7 +489,7 @@ Encoding used for template files. | |
$mt = $mt->escape(sub {...}); | |
A callback used to escape the results of escaped expressions, defaults to | |
-L<Mojo::Util/"xml_escape">. | |
+L<Mojo::Util/"xss_escape">. | |
$mt->escape(sub { | |
my $str = shift; | |
diff --git a/lib/Mojo/Util.pm b/lib/Mojo/Util.pm | |
index c168f38..d6d860c 100644 | |
--- a/lib/Mojo/Util.pm | |
+++ b/lib/Mojo/Util.pm | |
@@ -58,7 +58,7 @@ our @EXPORT_OK = ( | |
qw(md5_sum monkey_patch punycode_decode punycode_encode quote), | |
qw(secure_compare sha1_bytes sha1_sum slurp split_header spurt squish), | |
qw(steady_time tablify trim unindent unquote url_escape url_unescape), | |
- qw(xml_escape xor_encode) | |
+ qw(xml_escape xor_encode xss_escape) | |
); | |
sub b64_decode { decode_base64($_[0]) } | |
@@ -352,6 +352,11 @@ sub xor_encode { | |
return $output .= $buffer ^ substr($key, 0, length $buffer, ''); | |
} | |
+sub xss_escape { | |
+ no warnings 'uninitialized'; | |
+ ref $_[0] eq 'Mojo::ByteStream' ? $_[0] : xml_escape("$_[0]"); | |
+} | |
+ | |
sub _adapt { | |
my ($delta, $numpoints, $firsttime) = @_; | |
use integer; | |
@@ -719,6 +724,12 @@ Escape unsafe characters C<&>, C<E<lt>>, C<E<gt>>, C<"> and | |
XOR encode string with variable length key. | |
+=head2 xss_escape | |
+ | |
+ my $escaped = xss_escape $str; | |
+ | |
+Same as L</"xml_escape">, but does not escape L<Mojo::ByteStream> objects. | |
+ | |
=head1 SEE ALSO | |
L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>. | |
diff --git a/lib/Mojolicious/Plugin/TagHelpers.pm b/lib/Mojolicious/Plugin/TagHe | |
index 6ef43ac..221ac57 100644 | |
--- a/lib/Mojolicious/Plugin/TagHelpers.pm | |
+++ b/lib/Mojolicious/Plugin/TagHelpers.pm | |
@@ -2,7 +2,7 @@ package Mojolicious::Plugin::TagHelpers; | |
use Mojo::Base 'Mojolicious::Plugin'; | |
use Mojo::ByteStream; | |
-use Mojo::Util 'xml_escape'; | |
+use Mojo::Util 'xss_escape'; | |
use Scalar::Util 'blessed'; | |
sub register { | |
@@ -140,7 +140,7 @@ sub _option { | |
$attrs{selected} = 'selected' if exists $values->{$pair->[1]}; | |
%attrs = (%attrs, @$pair[2 .. $#$pair]); | |
- return _tag('option', %attrs, sub { xml_escape $pair->[0] }); | |
+ return _tag('option', %attrs, $pair->[0]); | |
} | |
sub _password_field { | |
@@ -212,13 +212,13 @@ sub _tag { | |
} | |
delete $attrs{data}; | |
} | |
- $tag .= qq{ $_="} . xml_escape($attrs{$_} // '') . '"' for sort keys %attrs; | |
+ $tag .= qq{ $_="} . xss_escape($attrs{$_} // '') . '"' for sort keys %attrs; | |
# Empty element | |
unless ($cb || defined $content) { $tag .= ' />' } | |
# End tag | |
- else { $tag .= '>' . ($cb ? $cb->() : xml_escape($content)) . "</$name>" } | |
+ else { $tag .= '>' . ($cb ? $cb->() : xss_escape $content) . "</$name>" } | |
# Prevent escaping | |
return Mojo::ByteStream->new($tag); | |
@@ -234,13 +234,11 @@ sub _tag_with_error { | |
sub _text_area { | |
my ($c, $name) = (shift, shift); | |
- # Make sure content is wrapped | |
- my $cb = ref $_[-1] eq 'CODE' ? pop : sub {''}; | |
+ my $cb = ref $_[-1] eq 'CODE' ? pop : undef; | |
my $content = @_ % 2 ? shift : undef; | |
- $cb = sub { xml_escape $content } | |
- if defined($content = $c->param($name) // $content); | |
- return _validation($c, $name, 'textarea', @_, name => $name, $cb); | |
+ $content = $c->param($name) // $content // $cb // ''; | |
+ return _validation($c, $name, 'textarea', @_, name => $name, $content); | |
} | |
sub _validation { | |
diff --git a/t/mojo/util.t b/t/mojo/util.t | |
index 9f949f1..07e7800 100644 | |
--- a/t/mojo/util.t | |
+++ b/t/mojo/util.t | |
@@ -6,6 +6,7 @@ use lib "$FindBin::Bin/lib"; | |
use Test::More; | |
use File::Spec::Functions qw(catfile splitdir); | |
use File::Temp 'tempdir'; | |
+use Mojo::ByteStream 'b'; | |
use Mojo::DeprecationTest; | |
use Mojo::Util | |
@@ -14,7 +15,7 @@ use Mojo::Util | |
qw(monkey_patch punycode_decode punycode_encode quote secure_compare), | |
qw(secure_compare sha1_bytes sha1_sum slurp split_header spurt squish), | |
qw(steady_time tablify trim unindent unquote url_escape url_unescape), | |
- qw(xml_escape xor_encode); | |
+ qw(xml_escape xor_encode xss_escape); | |
# camelize | |
is camelize('foo_bar_baz'), 'FooBarBaz', 'right camelized result'; | |
@@ -193,6 +194,10 @@ is xml_escape('привет'), 'привет', 'right XML escaped resul | |
is xml_escape('привет<foo>'), 'привет<foo>', | |
'right XML escaped result'; | |
+# xss_escape | |
+is xss_escape('<p>'), '<p>', 'right XSS escaped result'; | |
+is xss_escape(b('<p>')), '<p>', 'right XSS escaped result'; | |
+ | |
# punycode_encode | |
is punycode_encode('bücher'), 'bcher-kva', 'right punycode encoded result'; | |
diff --git a/t/mojolicious/tag_helper_lite_app.t b/t/mojolicious/tag_helper_lite | |
index b2fd857..039e9a6 100644 | |
--- a/t/mojolicious/tag_helper_lite_app.t | |
+++ b/t/mojolicious/tag_helper_lite_app.t | |
@@ -68,7 +68,8 @@ EOF | |
# Shortcut | |
$t->get_ok('/small_tags')->status_is(200)->content_is(<<EOF); | |
-<div>test & 123</div> | |
+<div id="&lt;">test & 123</div> | |
+<div id="<">test 321</div> | |
<div> | |
<p id="0">just</p> | |
<p>0</p> | |
@@ -494,7 +495,8 @@ __DATA__ | |
%= tag 'bar', class => 'test', '' | |
@@ small_tags.html.ep | |
-%=t div => 'test & 123' | |
+%=t div => (id => '<') => 'test & 123' | |
+%=t div => (id => b('<')) => b('test 321') | |
%=t div => begin | |
%=t p => (id => 0) => 'just' | |
%=t p => 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment