Skip to content

Commit

Permalink
added xss_escape function to Mojo::Util
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Nov 11, 2014
1 parent 1abeb21 commit f2891eb
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 20 deletions.
1 change: 1 addition & 0 deletions 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
Expand Down
10 changes: 3 additions & 7 deletions lib/Mojo/Template.pm
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
13 changes: 12 additions & 1 deletion lib/Mojo/Util.pm
Expand Up @@ -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]) }
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -719,6 +724,12 @@ Escape unsafe characters C<&>, C<E<lt>>, C<E<gt>>, C<"> and C<'> in string.
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>.
Expand Down
16 changes: 7 additions & 9 deletions lib/Mojolicious/Plugin/TagHelpers.pm
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand All @@ -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);
$content = $c->param($name) // $content // $cb // '';

return _validation($c, $name, 'textarea', @_, name => $name, $cb);
return _validation($c, $name, 'textarea', @_, name => $name, $content);
}

sub _validation {
Expand Down
7 changes: 6 additions & 1 deletion t/mojo/util.t
Expand Up @@ -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
Expand All @@ -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';
Expand Down Expand Up @@ -193,6 +194,10 @@ is xml_escape('привет'), 'привет', 'right XML escaped result';
is xml_escape('привет<foo>'), 'привет&lt;foo&gt;',
'right XML escaped result';

# xss_escape
is xss_escape('<p>'), '&lt;p&gt;', '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';

Expand Down
6 changes: 4 additions & 2 deletions t/mojolicious/tag_helper_lite_app.t
Expand Up @@ -68,7 +68,8 @@ EOF

# Shortcut
$t->get_ok('/small_tags')->status_is(200)->content_is(<<EOF);
<div>test &amp; 123</div>
<div id="&amp;lt;">test &amp; 123</div>
<div id="&lt;">test&nbsp;321</div>
<div>
<p id="0">just</p>
<p>0</p>
Expand Down Expand Up @@ -494,7 +495,8 @@ __DATA__
%= tag 'bar', class => 'test', ''
@@ small_tags.html.ep
%=t div => 'test & 123'
%=t div => (id => '&lt;') => 'test & 123'
%=t div => (id => b('&lt;')) => b('test&nbsp;321')
%=t div => begin
%=t p => (id => 0) => 'just'
%=t p => 0
Expand Down

0 comments on commit f2891eb

Please sign in to comment.