[Jifty-commit] r2425 - in Template-Declare: lib/Template/Declare t

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Tue Dec 26 23:16:33 EST 2006


Author: jesse
Date: Tue Dec 26 23:16:33 2006
New Revision: 2425

Added:
   Template-Declare/t/xss.t
Modified:
   Template-Declare/   (props changed)
   Template-Declare/lib/Template/Declare/Tags.pm

Log:
 r46503 at pinglin:  jesse | 2006-12-26 23:16:22 -0500
  * default to escaping user content


Modified: Template-Declare/lib/Template/Declare/Tags.pm
==============================================================================
--- Template-Declare/lib/Template/Declare/Tags.pm	(original)
+++ Template-Declare/lib/Template/Declare/Tags.pm	Tue Dec 26 23:16:33 2006
@@ -2,10 +2,12 @@
 use strict;
 
 package Template::Declare::Tags;
+use Template::Declare;
 use vars qw/@EXPORT @EXPORT_OK $PRIVATE $self/;
 use base 'Exporter';
+
 @EXPORT =
-  qw( with template private show get_current_attr attr outs in_isolation $self
+  qw( with template private show get_current_attr attr outs outs_raw in_isolation $self
       Tr td );    # these two warns the user to use row/cell instead
 
 our $DEPTH      = 0;
@@ -30,10 +32,14 @@
     $out;
 }
 
-sub outs {
+sub outs_raw {
     $BUFFER .= join( '', grep { defined } @_ );
     return '';
 }
+sub outs {
+    $BUFFER .= join( '', map { _escape_utf8($_);} grep { defined } @_ );
+    return '';
+}
 
 sub template ($$) {
     my $template_name  = shift;
@@ -125,12 +131,12 @@
 }
 
 sub _tag {
-    my $code = shift;
+    my $code      = shift;
     my $more_code = shift;
-    my (
-        $package,   $filename, $line,       $subroutine, $hasargs,
+    my ($package,   $filename, $line,       $subroutine, $hasargs,
         $wantarray, $evaltext, $is_require, $hints,      $bitmask
-    ) = caller(1);
+        )
+        = caller(1);
 
     # This is the hash of attributes filled in by attr() calls in the code;
 
@@ -138,9 +144,9 @@
     $tag =~ s/^.*\:\://;
 
     my $buf = "\n" . ( " " x $DEPTH ) . "<$tag"
-      . join( '',
+        . join( '',
         map { qq{ $_="} . ( $ATTRIBUTES{$_} || '' ) . qq{"} }
-          sort keys %ATTRIBUTES );
+            sort keys %ATTRIBUTES );
 
     my $had_content = 0;
 
@@ -157,18 +163,18 @@
             my $field = our $AUTOLOAD;
             $field =~ s/.*:://;
 
-            $field =~ s/__/:/g;     # xml__lang  is 'foo' ====> xml:lang="foo"
-            $field =~ s/_/-/g;      # http_equiv is 'bar' ====> http-equiv="bar"
+            $field =~ s/__/:/g;   # xml__lang  is 'foo' ====> xml:lang="foo"
+            $field =~ s/_/-/g;    # http_equiv is 'bar' ====> http-equiv="bar"
 
             # Squash empty values, but not '0' values
-            my $val = join(' ', grep {defined $_ && $_ ne ''} @_);
+            my $val = join( ' ', grep { defined $_ && $_ ne '' } @_ );
 
-            append_attr($field,$val);
+            append_attr( $field, $val );
         };
 
         local *append_attr = sub {
-            my $field   = shift;
-            my $val     = shift;
+            my $field = shift;
+            my $val   = shift;
 
             use bytes;
             $val =~ s/&/&#38;/g;
@@ -184,16 +190,15 @@
             wantarray ? () : '';
         };
 
+        my $last = join '',map{ ref($_) ? $_ : _escape_utf8($_) } $code->();
 
-        my $last = join '', $code->();
-
-        if (length($BUFFER)) {
+        if ( length($BUFFER) ) {
 
-            # We concatenate to force scalarization when $last or $BUFFER is solely a Jifty::Web::Link
+# We concatenate to force scalarization when $last or $BUFFER is solely a Jifty::Web::Link
             $buf .= '>' . $BUFFER;
             $had_content = 1;
-        } elsif (length $last) {
-            $buf .= '>'. $last;
+        } elsif ( length $last ) {
+            $buf .= '>' . $last;
             $had_content = 1;
         } else {
             $had_content = 0;
@@ -205,20 +210,22 @@
         $BUFFER .= $buf;
         $BUFFER .= "\n" . ( " " x $DEPTH ) if ( $buf =~ /\n/ );
         $BUFFER .= "</$tag>";
-    }
-    elsif ($tag =~ m{\A(?: base | meta | link | hr | br | param | img | area | input | col )\z}x) {
+    } elsif ( $tag
+        =~ m{\A(?: base | meta | link | hr | br | param | img | area | input | col )\z}x
+        )
+    {
+
         # EMPTY tags can close themselves.
-        $BUFFER .= $buf." />";
-    }
-    else {
+        $BUFFER .= $buf . " />";
+    } else {
+
         # Otherwise we supply a closing tag.
-        $BUFFER .= $buf."></$tag>";
+        $BUFFER .= $buf . "></$tag>";
     }
 
     if ($more_code) {
         $more_code->();
-    }
-    else {
+    } else {
         return '';
     }
 }
@@ -267,4 +274,18 @@
     return $buf;
 }
 
+sub _escape_utf8 {
+    my $val =shift;
+    use bytes;
+    no warnings 'uninitialized';
+    $val =~ s/&/&#38;/g;
+    $val =~ s/</&lt;/g;
+    $val =~ s/>/&gt;/g;
+    $val =~ s/\(/&#40;/g;
+    $val =~ s/\)/&#41;/g;
+    $val =~ s/"/&#34;/g;
+    $val =~ s/'/&#39;/g;
+    return $val;
+}
+
 1;

Added: Template-Declare/t/xss.t
==============================================================================
--- (empty file)
+++ Template-Declare/t/xss.t	Tue Dec 26 23:16:33 2006
@@ -0,0 +1,58 @@
+use warnings;
+use strict;
+
+
+package Wifty::UI;
+use base qw/Template::Declare/;
+use Template::Declare::Tags;
+use Test::More tests => 8;
+
+
+template content => sub { div { outs('This is my <b>content</b>') } };
+template content_2 => sub { div { 'This is my <b>content</b>' } };
+template content_3 => sub { div { p{ 'This is my <b>content</b>'}}; };
+template content_4 => sub { div { p{ outs('This is my '); b{ 'content'}}}; };
+
+package Template::Declare::Tags;
+
+use Test::More;
+use HTML::Lint;
+
+our $self;
+local $self = {};
+bless $self, 'Wifty::UI';
+
+Template::Declare->init( roots => ['Wifty::UI']);
+
+
+for (qw(content content_2 content_3 ) ){
+{
+local $Template::Declare::Tags::BUFFER;
+my $simple =(show($_));
+ok($simple =~ 'This is my &lt;b&gt;content');
+ok_lint($simple);
+}
+}
+for (qw(content_4) ){
+{
+local $Template::Declare::Tags::BUFFER;
+my $simple =(show($_));
+ok($simple =~ m/This is my\s*<b>\s*content/);
+ok_lint($simple);
+}
+}
+sub ok_lint {
+    my $html = shift;
+
+    my $lint = HTML::Lint->new;
+
+    $lint->parse($html);
+    is( $lint->errors, 0, "Lint checked clean" );
+    foreach my $error ( $lint->errors ) {
+        diag( $error->as_string );
+    }
+
+}
+
+
+1;


More information about the Jifty-commit mailing list