The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Changes 114
MANIFEST 913
Makefile.PL 11
Strip.pm 11
Strip.xs 912
strip_html.c 1255
strip_html.h 21
t/001_smoke.t 012
t/100_basic.t 070
t/200_comment.t 038
t/210_auto_reset.t 020
t/220_edge_case.t 020
t/230_filter.t 018
t/240_striptags.t 031
t/250_whitespace_single_char.t 010
t/260_offbyone.t 012
t/270_mathematical_comparisons.t 030
t/280_invalid_multiline_segfault.t 011
t/300_utf8.t 037
t/auto-reset.t 200
t/basic.t 670
t/comment.t 380
t/edge-case.t 200
t/filter.t 180
t/mathematical-comparisons.t 300
t/offbyone.t 120
t/russian.html 012
t/striptags.t 310
t/whitespace-single-char.t 100
29 files changed (This is a version diff) 281418
@@ -1,7 +1,20 @@
 Revision history for Perl extension HTML::Strip.
 
+2.02  Thu Nov 20 11:21:35 GMT 2014
+    - removed dependency on libicu-dev, which isn't as universal as expected
+      and was causing a bunch of cpan tester failures
+
+2.01  Wed Nov 19 10:48:04 GMT 2014
+    (patch contributed by Michi Steiner)
+    - clean buffer needs an extra char when emit_spaces=1 and the input has
+      nothing to be removed (RT#41035)
+
+2.00  Tue Nov 18 16:14:42 GMT 2014
+    - utf8 support via libicu (RT#42834)
+    - smoke test and utf8 test, tests ordered
+
 1.10  Tue Sep 30 14:34:47 UTC 2014
-    - Fix for RT#99207 (script mathematical symbol bug).
+    - Fix for RT#99207 (script mathematical symbol bug)
 
 1.09  Tue Sep 30 10:39:47 UTC 2014
     - offbyone.t disabled under Windows (RT#99219)
@@ -8,12 +8,16 @@ Strip.xs
 strip_html.h
 strip_html.c
 typemap
-t/basic.t
-t/auto-reset.t
-t/comment.t
-t/edge-case.t
-t/filter.t
-t/mathematical-comparisons.t
-t/offbyone.t
-t/striptags.t
-t/whitespace-single-char.t
+t/001_smoke.t
+t/100_basic.t
+t/200_comment.t
+t/210_auto_reset.t
+t/220_edge_case.t
+t/230_filter.t
+t/240_striptags.t
+t/250_whitespace_single_char.t
+t/260_offbyone.t
+t/270_mathematical_comparisons.t
+t/280_invalid_multiline_segfault.t
+t/300_utf8.t
+t/russian.html
@@ -29,7 +29,7 @@ WriteMakefile(
         },
     },
   ) : () ),
-    'LIBS'              => [''], # e.g., '-lm'
+    'LIBS'              => ['-licuuc -licuio'], # e.g., '-lm'
     'DEFINE'            => '', # e.g., '-DHAVE_SOMETHING'
     'INC'               => '', # e.g., '-I/usr/include/other'
     'OBJECT'            => '$(O_FILES)', # link all the C files too
@@ -2,7 +2,7 @@ package HTML::Strip;
 
 require DynaLoader;
 our @ISA = qw(DynaLoader);
-our $VERSION = '1.10';
+our $VERSION = '2.02';
 bootstrap HTML::Strip $VERSION;
 
 use 5.006;
@@ -14,7 +14,7 @@ create()
  PREINIT:
   Stripper * stripper;
  CODE:
-  New( 0, stripper, 1, Stripper );
+  Newx( stripper, 1, Stripper );
   reset( stripper );
   RETVAL = stripper;
  OUTPUT:
@@ -26,18 +26,21 @@ DESTROY( stripper )
  CODE:
   Safefree( stripper );
 
-char *
-strip_html( stripper, raw )
-  Stripper * stripper
-  char * raw
+SV *
+strip_html( stripper, text )
+  Stripper *    stripper
+  SV *          text
  PREINIT:
-  char * clean;
-  int size = strlen(raw) + 1;
+  char *    raw = (char *)SvPV_nolen(text);
+  char *    clean;
+  int       size = strlen(raw)+1;
  INIT:
-  New( 0, clean, size, char );
+  Newx( clean, size+1, char);
  CODE:
   strip_html( stripper, raw, clean );
-  RETVAL = clean;
+  RETVAL = newSVpv(clean, strlen(clean));
+  if( SvUTF8(text) )
+      SvUTF8_on(RETVAL);
  OUTPUT:
   RETVAL
  CLEANUP:
@@ -4,14 +4,19 @@
 #include "strip_html.h"
 
 void
-strip_html( Stripper * stripper, const char * raw, char * output ) {
-  const char * p_raw = raw;
-  const char * raw_end = raw + strlen(raw);
+strip_html( Stripper * stripper, char * raw, char * output ) {
+  char * p_raw = raw;
+  char * raw_end = raw + strlen(raw);
   char * p_output = output;
+  int width;
+
+  if( stripper->o_debug ) {
+      printf( "[DEBUG] input string: %s\n", p_raw );
+  }
 
   while( p_raw < raw_end ) {
     if( stripper->o_debug ) {
-      printf( "[DEBUG] char %c state %c %c %c tag:%5s, %c %c %c %c, %c %c %c %c:%c, ",
+      printf( "[DEBUG] char %C state %c %c %c tag:%5s, %c %c %c %c, %c %c %c %c:%c, ",
         *p_raw,
         (stripper->f_closing ? 'C' : ' '),
         (stripper->f_in_tag ? 'T' : ' '),
@@ -28,6 +33,9 @@ strip_html( Stripper * stripper, const char * raw, char * output ) {
         (stripper->quote ? stripper->quote : ' ')
       );
     }
+
+    width = utf8_char_width(p_raw);
+    // either a single char or a set of unicode code points;
     if( stripper->f_in_tag ) {
       /* inside a tag */
       /* check if we know either the tagname, or that we're in a declaration */
@@ -47,7 +55,7 @@ strip_html( Stripper * stripper, const char * raw, char * output ) {
           stripper->f_closing = 0;
         /* we only care about closing tags within a stripped tags block (e.g. scripts) */
         } else if( !stripper->f_in_striptag || stripper->f_closing ) {
-          /* if we don't have the full tag name yet, add current character unless it's whitespace, a '/', or a '>';
+          /* if we don't have the full tag name yet, add p_raw character unless it's whitespace, a '/', or a '>';
              otherwise null pad the string and set the full tagname flag, and check the tagname against stripped ones.
              also sanity check we haven't reached the array bounds, and truncate the tagname here if we have */
           if( (!isspace( *p_raw ) && *p_raw != '/' && *p_raw != '>') &&
@@ -77,7 +85,7 @@ strip_html( Stripper * stripper, const char * raw, char * output ) {
       } else {
         if( stripper->f_in_quote ) {
           /* inside a quote */
-          /* end of quote if current character matches the opening quote character */
+          /* end of quote if p_raw character matches the opening quote character */
           if( *p_raw == stripper->quote ) {
             stripper->quote = 0;
             stripper->f_in_quote = 0;
@@ -96,13 +104,13 @@ strip_html( Stripper * stripper, const char * raw, char * output ) {
             if( stripper->f_in_decl ) {
               /* inside a declaration */
               if( stripper->f_lastchar_minus ) {
-                /* last character was a minus, so if current one is, then we're either entering or leaving a comment */
+                /* last character was a minus, so if p_raw one is, then we're either entering or leaving a comment */
                 if( *p_raw == '-' ) {
                   stripper->f_in_comment = !stripper->f_in_comment;
                 }
                 stripper->f_lastchar_minus = 0;
               } else {
-                /* if current character is a minus, we might be starting a comment marker */
+                /* if p_raw character is a minus, we might be starting a comment marker */
                 if( *p_raw == '-' ) {
                   stripper->f_lastchar_minus = 1;
                 }
@@ -150,7 +158,9 @@ strip_html( Stripper * stripper, const char * raw, char * output ) {
           if( stripper->o_debug ) {
             printf("CHAR %c", *p_raw);
           }
-          *p_output++ = *p_raw;
+          strncpy(p_output, p_raw, width);
+          p_output += width;
+
           /* reset 'just seen tag' flag */
           stripper->f_just_seen_tag = 0;
           /* reset 'outputted space' flag if character is not one */
@@ -162,7 +172,7 @@ strip_html( Stripper * stripper, const char * raw, char * output ) {
         }
       }
     } /* in tag check */
-    p_raw++;
+    p_raw += width;
     if( stripper->o_debug ) {
       printf("\n");
     }
@@ -175,6 +185,38 @@ strip_html( Stripper * stripper, const char * raw, char * output ) {
   }
 }
 
+int
+utf8_char_width(unsigned char * string) {
+    if (~*string & 128) {                   // 0xxxxxxx
+        return 1;
+    } else if ((*string & 192) == 128) {      // 10xxxxxx
+        /* latter bytes of a multibyte utf8 char
+       XXX this should never happen in practice XXX
+           but we account for it anyway */
+        int width = 1;
+        char * p = string;
+        while ((*p++ & 192) == 128) {
+            width++;
+        }
+        return width;
+    } else if ((*string & 224) == 192) {      // 110xxxxx
+        return 2;
+    } else if ((*string & 240) == 224) {      // 1110xxxx
+        return 3;
+    } else if ((*string & 248) == 240) {      // 11110xxx
+        return 4;
+    /* part of ioriginal utf8 spec, but not used
+    } else if ((*string & 252) == 248) {      // 111110xx
+        return 1;
+    } else if ((*string & 254) == 252) {      // 1111110x
+        return 1;
+    */
+    } else {
+        printf( "[WARN] invalid utf8 char ord=%i\n", *string );
+        return 1;
+    }
+}
+
 void
 reset( Stripper * stripper ) {
   stripper->f_in_tag = 0;
@@ -193,6 +235,7 @@ reset( Stripper * stripper ) {
 
   stripper->f_in_striptag = 0;
 
+  memset(stripper->tagname, 0, sizeof(stripper->tagname));
 }
 
 void
@@ -216,11 +259,11 @@ add_striptag( Stripper * stripper, char * striptag ) {
 
 void
 check_end( Stripper * stripper, char end ) {
-  /* if current character is a slash, may be a closed tag */
+  /* if p_raw character is a slash, may be a closed tag */
   if( end == '/' ) {
     stripper->f_lastchar_slash = 1;
   } else {
-    /* if the current character is a '>', then the tag has ended */
+    /* if the p_raw character is a '>', then the tag has ended */
     /* slight hack to deal with mathematical characters in script tags:
      * if we're in a stripped block, and this is a closing tag, spaces
      * will also end the tag, since we only want it for comparison with
@@ -1,4 +1,3 @@
-
 #define MAX_TAGNAMELENGTH 20
 #define MAX_STRIPTAGS 20
 
@@ -33,7 +32,7 @@ typedef struct Stripper {
   int o_debug;
 } Stripper;
 
-void strip_html( Stripper * stripper, const char * raw, char * clean );
+void strip_html( Stripper * stripper, char * raw, char * clean );
 void reset( Stripper * stripper );
 void clear_striptags( Stripper * stripper );
 void add_striptag( Stripper * stripper, char * tag );
@@ -0,0 +1,12 @@
+use Test::More tests => 3;
+use Test::Exception;
+
+use_ok 'HTML::Strip';
+
+my $hs;
+lives_ok( sub { $hs = HTML::Strip->new() }, "constructor doesn't blow up" );
+
+SKIP: {
+    skip "Constructor failed", 1 unless $hs;
+    lives_ok( sub { $hs->parse('') }, "->parse() doesn't blow up" );
+}
@@ -0,0 +1,70 @@
+use Test::More tests => 19;
+
+use feature 'unicode_strings';
+use utf8;
+
+BEGIN { use_ok 'HTML::Strip' }
+
+{
+  my $hs = HTML::Strip->new();
+
+  is( $hs->parse( 'test' ), 'test', 'works with plain text' );
+  $hs->eof;
+
+  is( $hs->parse( '<em>test</em>' ), 'test', 'works with <em>|</em> tags' );
+  $hs->eof;
+
+  is( $hs->parse( 'foo<br>bar' ), 'foo bar', 'works with <br> tag' );
+  $hs->eof;
+
+  is( $hs->parse( '<p align="center">test</p>' ), 'test', 'works with tags with attributes' );
+  $hs->eof;
+
+  is( $hs->parse( '<p align="center>test</p>' ), '', '"works" with non-terminated quotes' );
+  $hs->eof;
+
+  is( $hs->parse( '<foo>bar' ), 'bar', 'strips <foo> tags' );
+  is( $hs->parse( '</foo>baz' ), ' baz', 'strips </foo> tags' );
+  $hs->eof;
+
+  is( $hs->parse( '<!-- <p>foo</p> bar -->baz' ), 'baz', 'strip comments' );
+  $hs->eof;
+
+  is( $hs->parse( '<img src="foo.gif" alt="a > b">bar' ), 'bar', 'works with quote attributes which contain >' );
+  $hs->eof;
+
+  is( $hs->parse( '<script> if (a>b && a<c) { ... } </script>bar' ), 'bar', '<script> tag and content are stripped' );
+  $hs->eof;
+
+  is( $hs->parse( '<# just data #>bar' ), 'bar', 'weird tags get stripped' );
+  $hs->eof;
+
+  TODO: {
+    local $TODO = "fix CDATA handling";
+    is( $hs->parse( '<![INCLUDE CDATA [ >>>>>>>>>>>> ]]>bar' ), 'bar', 'character data gets stripped' );
+    $hs->eof;
+  }
+
+  is( $hs->parse( '<script>foo</script>bar' ), 'bar', '<script> nodes are stripped' );
+  $hs->eof;
+
+  my $has_html_entities = eval { require HTML::Entities; 1 };
+  SKIP: {
+    skip 'HTML::Entities not available', 2 unless $has_html_entities;
+
+    is( $hs->parse( '&#060;foo&#062;' ), '<foo>', 'numeric HTML entities are decoded' );
+    $hs->eof;
+    is( $hs->parse( '&lt;foo&gt;' ), '<foo>', 'HTML entities are decoded' );
+    $hs->eof;
+  }
+
+  $hs->set_decode_entities(0);
+  is( $hs->parse( '&#060;foo&#062;' ), '&#060;foo&#062;', 'entities decoding off works' );
+  $hs->eof;
+
+  is( $hs->parse( '&lt;foo&gt;' ), '&lt;foo&gt;', 'entities decoding off works' );
+  $hs->eof;
+
+  is( $hs->parse( '<script>foo</script>bar' ), 'bar', '"script" is a default strip_tag' );
+  $hs->eof;
+}
@@ -0,0 +1,38 @@
+
+# http://rt.cpan.org/Public/Bug/Display.html?id=32355
+
+use Test::More tests => 7;
+
+BEGIN { use_ok 'HTML::Strip' }
+
+# stripping declarations
+{
+  my $hs = HTML::Strip->new();
+  is( $hs->parse( q{<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>Text</html>} ),
+      "Text", 'decls are stripped' );
+  $hs->eof;
+}
+
+# stripping comments
+{
+  my $hs = HTML::Strip->new();
+  is( $hs->parse( q{<html><!-- a comment to be stripped -->Hello World!</html>} ),
+      "Hello World!", "comments are stripped" );
+  $hs->eof;
+
+  is( $hs->parse( q{<html><!-- comment with a ' apos -->Hello World!</html>} ), 
+     "Hello World!", q{comments may contain '} );
+  $hs->eof;
+
+  is( $hs->parse( q{<html><!-- comment with a " quote -->Hello World!</html>} ), 
+     "Hello World!", q{comments may contain "} );
+  $hs->eof;
+
+  is( $hs->parse( q{<html><!-- comment -- "quote" >Hello World!</html>} ), 
+     "Hello World!", "weird decls are stripped" );
+  $hs->eof;
+
+  is( $hs->parse( "a<>b" ),
+      "a b", 'edge case with <> ok' );
+
+}
@@ -0,0 +1,20 @@
+
+use Test::More tests => 5;
+
+BEGIN { use_ok 'HTML::Strip' }
+
+{
+  my $hs = HTML::Strip->new; # auto_reset off by default
+  my $o = $hs->parse( "<html>\nTitle\n<script>a+b\n" );
+  is( $o, "\nTitle\n" );
+  my $o2 = $hs->parse( "c+d\n</script>\nEnd\n</html>" );
+  is( $o2, "\nEnd\n" );
+}
+
+{
+  my $hs = HTML::Strip->new( auto_reset => 1 ); # auto_reset on
+  my $o = $hs->parse( "<html>\nTitle\n<script>a+b\n" );
+  is( $o, "\nTitle\n" );
+  my $o2 = $hs->parse( "c+d\n</script>\nEnd\n</html>" );
+  is( $o2, "c+d\n\nEnd\n" );
+}
@@ -0,0 +1,20 @@
+use Test::More;
+
+BEGIN { use_ok 'HTML::Strip' }
+
+# test for RT#21008
+
+# stripping comments 
+{
+    my $hs = HTML::Strip->new();
+    is( $hs->parse( "a<>b" ), "a b", 'edge case with <> ok' );
+    $hs->eof;
+    is( $hs->parse( "a<>b c<>d" ), "a b c d", 'edge case with <>s ok' );
+    $hs->eof;
+    is( $hs->parse( "From: <>\n\na. Title: some text\n\nb. etc\n" ), "From: \n\na. Title: some text\n\nb. etc\n", 'test case' ); 
+    is( $hs->parse( "From: <>\n\na. Title: some text\n\nb. etc\n" ), "From: \n\na. Title: some text\n\nb. etc\n", 'test case' ); 
+    $hs->eof; 
+    is( $hs->parse( q{this is an "example" with 'quoted' parts that should not be stripped} ), q{this is an "example" with 'quoted' parts that should not be stripped} ); 
+}
+
+done_testing;
@@ -0,0 +1,18 @@
+use Test::More tests => 3;
+
+BEGIN { use_ok 'HTML::Strip' }
+
+{
+  my $hs = HTML::Strip->new( filter => undef );
+  ok( $hs->parse( '<html>&nbsp;</html>' ), '&nbsp;' );
+  $hs->eof;
+
+}
+
+{
+  my $filter = sub { my $s = shift; $s =~ s/\s/ /g;; $s };
+  my $hs = HTML::Strip->new( filter => $filter );
+  ok( $hs->parse( "<html>title\ntext\ntext</html>" ), 'title text text' );
+  $hs->eof;
+
+}
@@ -0,0 +1,31 @@
+use Test::More tests => 6;
+
+BEGIN { use_ok 'HTML::Strip' }
+
+{
+  # set_striptags( \@ARRAY )
+  my $hs = HTML::Strip->new;
+  $hs->set_striptags( [ 'foo' ] );
+
+  is( $hs->parse( '<script>foo</script>bar' ), 'foo bar', 'set_striptags redefinition works' );
+  $hs->eof;
+
+  is( $hs->parse( '<foo>foo</foo>bar' ), 'bar', 'set_striptags redefinition works' );
+  $hs->eof;
+}
+
+{
+  # set_striptags( LIST )
+  my @striptags = qw(baz quux);
+  my $hs = HTML::Strip->new;
+  $hs->set_striptags( @striptags );
+
+  is( $hs->parse( '<baz>fumble</baz>bar<quux>foo</quux>' ), 'bar', 'stripping user-defined tags ok' );
+  $hs->eof;
+
+  is( $hs->parse( '<baz>fumble<quux/>foo</baz>bar' ), 'bar', 'stripping user-defined tags ok' );
+  $hs->eof;
+
+  is( $hs->parse( '<foo> </foo> <bar> baz </bar>' ), '   baz ', 'stripping user-defined tags ok' );
+  $hs->eof;
+}
@@ -0,0 +1,10 @@
+use Test::More tests => 2;
+
+BEGIN { use_ok 'HTML::Strip' }
+
+# test for RT#19036
+{
+    my $hs = HTML::Strip->new();
+    is( $hs->parse( '<tr><td>01 May 2006</td><td>0</td><td>10</td></tr>' ), '01 May 2006 0 10', "whitespace single character bug" );
+    $hs->eof;
+}
@@ -0,0 +1,12 @@
+use strict;
+
+# test for RT#94713
+use Test::More tests => 1;
+
+my $INC = join ' ', map { "-I$_" } @INC;
+
+SKIP: {
+    skip "test fails on windows", 1 if $^O eq 'MSWin32';
+    is(`MALLOC_OPTIONS=Z $^X $INC -MHTML::Strip -e 'print HTML::Strip->new->parse(q[<li>abc < 0.5 km</li><li>xyz</li>])'`, q[abc xyz]);
+}
+
@@ -0,0 +1,30 @@
+use Test::More tests => 3;
+
+BEGIN { use_ok 'HTML::Strip' }
+
+# test for RT#35345
+{
+    my $hs = HTML::Strip->new();
+    is( $hs->parse( <<EOF ), "\nHello\n", "mathematical comparisons in strip tags bug RT#35345" );
+<script>
+function shovelerMain (detectBuyBox) {
+    for (var i = 0; i < Shoveler.Instances.length; i++) {
+...
+</script>
+<h1>Hello</h1>
+EOF
+    $hs->eof;
+}
+
+# test for RT#99207
+{
+    my $hs = HTML::Strip->new();
+    is( $hs->parse( <<EOF ), "\nhallo\n", "mathematical comparisons in strip tags bug RT#99207" );
+<script type="text/javascript">
+    document.write('<scr'+'ipt src="//www3.smartadserver.com/call/pubj/' + sas_config.pageid + '/' + formatid + '/' + sas_config.master + '/' + sas_config.tmstp + '/' + encodeURIComponent(target) + '?"></scr'+'ipt>');
+</script>
+<span>hallo</span>
+EOF
+    $hs->eof;
+}
+
@@ -0,0 +1,11 @@
+use Test::More tests => 2;
+use Test::Exception;
+
+use HTML::Strip;
+
+# test for RT#41035
+my $hs = HTML::Strip->new();
+
+ok( $hs->parse('<b>1</b><li>') );
+lives_ok( sub { $hs->parse('ABC. DEFGH:') }, "no segfault" );
+
@@ -0,0 +1,37 @@
+use Test::More tests => 4;
+
+use HTML::Strip;
+use FindBin qw/$Bin/;
+
+use Encode qw/encode is_utf8/;
+
+my $filename = "$Bin/russian.html";
+ok( open my $fh, $filename );
+SKIP: {
+    skip "Cannot open $filename", 3 unless $fh;
+
+	binmode $fh, ':utf8';
+    local $/;
+	my $data = <$fh>;
+	close $fh;
+
+	my $hs = HTML::Strip->new();
+	ok( my $clean_text = $hs->parse( $data ) );
+
+    ok( is_utf8($clean_text), "Text comes back as UTF-8" );
+	is( encode( 'UTF-8', $clean_text ), <<EOF );
+ 23 января 2009 года \\r
+ 28 января 2009 года в Челябинске состоится семинар компании «Доктор Веб» — российского разработчика средств информационной безопасности под маркой Dr.Web. Мероприятие посетят партнеры компании, а также представители региональных масс-медиа. \\r
+ На сегодняшний день все большее количество пользователей в Челябинской области проявляют интерес к проблеме информационной безопасности. Несмотря на финансовый кризис, спрос на средства антивирусной и антиспам-защиты в регионе остается достаточно высоким. «Доктор Веб», высоко оценивая потребительский потенциал области, 28 января проведет в Челябинске партнерский семинар, который соберет многочисленных партнеров компании. \\r
+ В ходе семинара специалисты «Доктор Веб» подробно расскажут о ключевых функциях программных продуктов Dr.Web, их преимуществах в сравнении с конкурентами. Особое внимание будет уделено новинкам — Dr.Web Security Space и Антивирус Dr.Web для Windows 5.0. Помимо этого, будут обсуждены новые вирусные угрозы и технологии борьбы с ними. \\r
+ Также в рамках семинара состоится вручение сертификатов специалиста по продажам программного обеспечения Dr.Web. Для получения сертификата участник семинара должен дистанционно сдать экзамен до 26 января 2009 г. Для этого необходимо будет предварительно заполнить регистрационную анкету на сайте компании «Доктор Веб» , выбрав в ней соответствующий пункт («сдать on-line экзамен»). \\r
+ В подарок все участники семинара получат ключи, позволяющие в течение 2 месяцев бесплатно протестировать всю линейку продуктов Dr.Web. \\r
+ \\r
+ Адрес : \\r
+ Отель «Holiday Inn Chelyabinsk-Riverside», Университетская набережная, 18 \\r
+ Конференц-зал (2 этаж) \\r
+ Регистрация участников: 11:00 — 11:30 \\r
+ 
+EOF
+}
+
@@ -1,20 +0,0 @@
-
-use Test::More tests => 5;
-
-BEGIN { use_ok 'HTML::Strip' }
-
-{
-  my $hs = HTML::Strip->new; # auto_reset off by default
-  my $o = $hs->parse( "<html>\nTitle\n<script>a+b\n" );
-  is( $o, "\nTitle\n" );
-  my $o2 = $hs->parse( "c+d\n</script>\nEnd\n</html>" );
-  is( $o2, "\nEnd\n" );
-}
-
-{
-  my $hs = HTML::Strip->new( auto_reset => 1 ); # auto_reset on
-  my $o = $hs->parse( "<html>\nTitle\n<script>a+b\n" );
-  is( $o, "\nTitle\n" );
-  my $o2 = $hs->parse( "c+d\n</script>\nEnd\n</html>" );
-  is( $o2, "c+d\n\nEnd\n" );
-}
@@ -1,67 +0,0 @@
-use Test::More tests => 19;
-
-BEGIN { use_ok 'HTML::Strip' }
-
-{
-  my $hs = new HTML::Strip;
-
-  is( $hs->parse( 'test' ), 'test', 'works with plain text' );
-  $hs->eof;
-
-  is( $hs->parse( '<em>test</em>' ), 'test', 'works with <em>|</em> tags' );
-  $hs->eof;
-
-  is( $hs->parse( 'foo<br>bar' ), 'foo bar', 'works with <br> tag' );
-  $hs->eof;
-
-  is( $hs->parse( '<p align="center">test</p>' ), 'test', 'works with tags with attributes' );
-  $hs->eof;
-
-  is( $hs->parse( '<p align="center>test</p>' ), '', '"works" with non-terminated quotes' );
-  $hs->eof;
-
-  is( $hs->parse( '<foo>bar' ), 'bar', 'strips <foo> tags' );
-  is( $hs->parse( '</foo>baz' ), ' baz', 'strips </foo> tags' );
-  $hs->eof;
-
-  is( $hs->parse( '<!-- <p>foo</p> bar -->baz' ), 'baz', 'strip comments' );
-  $hs->eof;
-
-  is( $hs->parse( '<img src="foo.gif" alt="a > b">bar' ), 'bar', 'works with quote attributes which contain >' );
-  $hs->eof;
-
-  is( $hs->parse( '<script> if (a>b && a<c) { ... } </script>bar' ), 'bar', '<script> tag and content are stripped' );
-  $hs->eof;
-
-  is( $hs->parse( '<# just data #>bar' ), 'bar', 'weird tags get stripped' );
-  $hs->eof;
-
-  TODO: {
-    local $TODO = "fix CDATA handling";
-    is( $hs->parse( '<![INCLUDE CDATA [ >>>>>>>>>>>> ]]>bar' ), 'bar', 'character data gets stripped' );
-    $hs->eof;
-  }
-
-  is( $hs->parse( '<script>foo</script>bar' ), 'bar', '<script> nodes are stripped' );
-  $hs->eof;
-
-  my $has_html_entities = eval { require HTML::Entities; 1 };
-  SKIP: {
-    skip 'HTML::Entities not available', 2 unless $has_html_entities;
-
-    is( $hs->parse( '&#060;foo&#062;' ), '<foo>', 'numeric HTML entities are decoded' );
-    $hs->eof;
-    is( $hs->parse( '&lt;foo&gt;' ), '<foo>', 'HTML entities are decoded' );
-    $hs->eof;
-  }
-
-  $hs->set_decode_entities(0);
-  is( $hs->parse( '&#060;foo&#062;' ), '&#060;foo&#062;', 'entities decoding off works' );
-  $hs->eof;
-
-  is( $hs->parse( '&lt;foo&gt;' ), '&lt;foo&gt;', 'entities decoding off works' );
-  $hs->eof;
-
-  is( $hs->parse( '<script>foo</script>bar' ), 'bar', '"script" is a default strip_tag' );
-  $hs->eof;
-}
@@ -1,38 +0,0 @@
-
-# http://rt.cpan.org/Public/Bug/Display.html?id=32355
-
-use Test::More tests => 7;
-
-BEGIN { use_ok 'HTML::Strip' }
-
-# stripping declarations
-{
-  my $hs = HTML::Strip->new();
-  is( $hs->parse( q{<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>Text</html>} ),
-      "Text", 'decls are stripped' );
-  $hs->eof;
-}
-
-# stripping comments
-{
-  my $hs = HTML::Strip->new();
-  is( $hs->parse( q{<html><!-- a comment to be stripped -->Hello World!</html>} ),
-      "Hello World!", "comments are stripped" );
-  $hs->eof;
-
-  is( $hs->parse( q{<html><!-- comment with a ' apos -->Hello World!</html>} ), 
-     "Hello World!", q{comments may contain '} );
-  $hs->eof;
-
-  is( $hs->parse( q{<html><!-- comment with a " quote -->Hello World!</html>} ), 
-     "Hello World!", q{comments may contain "} );
-  $hs->eof;
-
-  is( $hs->parse( q{<html><!-- comment -- "quote" >Hello World!</html>} ), 
-     "Hello World!", "weird decls are stripped" );
-  $hs->eof;
-
-  is( $hs->parse( "a<>b" ),
-      "a b", 'edge case with <> ok' );
-
-}
@@ -1,20 +0,0 @@
-use Test::More;
-
-BEGIN { use_ok 'HTML::Strip' }
-
-# test for RT#21008
-
-# stripping comments 
-{
-    my $hs = HTML::Strip->new();
-    is( $hs->parse( "a<>b" ), "a b", 'edge case with <> ok' );
-    $hs->eof;
-    is( $hs->parse( "a<>b c<>d" ), "a b c d", 'edge case with <>s ok' );
-    $hs->eof;
-    is( $hs->parse( "From: <>\n\na. Title: some text\n\nb. etc\n" ), "From: \n\na. Title: some text\n\nb. etc\n", 'test case' ); 
-    is( $hs->parse( "From: <>\n\na. Title: some text\n\nb. etc\n" ), "From: \n\na. Title: some text\n\nb. etc\n", 'test case' ); 
-    $hs->eof; 
-    is( $hs->parse( q{this is an "example" with 'quoted' parts that should not be stripped} ), q{this is an "example" with 'quoted' parts that should not be stripped} ); 
-}
-
-done_testing;
@@ -1,18 +0,0 @@
-use Test::More tests => 3;
-
-BEGIN { use_ok 'HTML::Strip' }
-
-{
-  my $hs = HTML::Strip->new( filter => undef );
-  ok( $hs->parse( '<html>&nbsp;</html>' ), '&nbsp;' );
-  $hs->eof;
-
-}
-
-{
-  my $filter = sub { my $s = shift; $s =~ s/\s/ /g;; $s };
-  my $hs = HTML::Strip->new( filter => $filter );
-  ok( $hs->parse( "<html>title\ntext\ntext</html>" ), 'title text text' );
-  $hs->eof;
-
-}
@@ -1,30 +0,0 @@
-use Test::More tests => 3;
-
-BEGIN { use_ok 'HTML::Strip' }
-
-# test for RT#35345
-{
-    my $hs = HTML::Strip->new();
-    is( $hs->parse( <<EOF ), "\nHello\n", "mathematical comparisons in strip tags bug RT#35345" );
-<script>
-function shovelerMain (detectBuyBox) {
-    for (var i = 0; i < Shoveler.Instances.length; i++) {
-...
-</script>
-<h1>Hello</h1>
-EOF
-    $hs->eof;
-}
-
-# test for RT#99207
-{
-    my $hs = HTML::Strip->new();
-    is( $hs->parse( <<EOF ), "\nhallo\n", "mathematical comparisons in strip tags bug RT#99207" );
-<script type="text/javascript">
-    document.write('<scr'+'ipt src="//www3.smartadserver.com/call/pubj/' + sas_config.pageid + '/' + formatid + '/' + sas_config.master + '/' + sas_config.tmstp + '/' + encodeURIComponent(target) + '?"></scr'+'ipt>');
-</script>
-<span>hallo</span>
-EOF
-    $hs->eof;
-}
-
@@ -1,12 +0,0 @@
-use strict;
-
-# test for RT#94713
-use Test::More tests => 1;
-
-my $INC = join ' ', map { "-I$_" } @INC;
-
-SKIP: {
-    skip "test fails on windows", 1 if $^O eq 'MSWin32';
-    is(`MALLOC_OPTIONS=Z $^X $INC -MHTML::Strip -e 'print HTML::Strip->new->parse(q[<li>abc < 0.5 km</li><li>xyz</li>])'`, q[abc xyz]);
-}
-
@@ -0,0 +1,12 @@
+ <p><b>23 января 2009 года </b></p>\r
+ <p><b>28 января 2009 года в Челябинске состоится семинар компании «Доктор Веб» &mdash; российского разработчика средств информационной безопасности под маркой Dr.Web. Мероприятие посетят партнеры компании, а также представители региональных масс-медиа.</b></p>\r
+ <p>На сегодняшний день все большее количество пользователей в Челябинской области проявляют интерес к проблеме информационной безопасности. Несмотря на финансовый кризис, спрос на средства антивирусной и антиспам-защиты в регионе остается достаточно высоким. «Доктор Веб», высоко оценивая потребительский потенциал области, 28 января проведет в Челябинске партнерский семинар, который соберет многочисленных партнеров компании.</p>\r
+ <p>В ходе семинара специалисты «Доктор Веб» подробно расскажут о ключевых функциях программных продуктов Dr.Web, их преимуществах в сравнении с конкурентами. Особое внимание будет уделено новинкам &mdash; Dr.Web Security Space и Антивирус Dr.Web для Windows 5.0. Помимо этого, будут обсуждены новые вирусные угрозы и технологии борьбы с ними.</p> \r
+ <p>Также в рамках семинара состоится вручение сертификатов специалиста по продажам программного обеспечения Dr.Web. Для получения сертификата участник семинара должен дистанционно сдать экзамен до 26 января 2009 г. Для этого необходимо будет предварительно заполнить <a href="http://partners.drweb.com/survey/?id=5528912">регистрационную анкету на сайте компании «Доктор Веб»</a>, выбрав в ней соответствующий пункт («сдать on-line экзамен»).</p>\r
+ <p>В подарок все участники семинара получат ключи, позволяющие в течение 2 месяцев бесплатно протестировать всю линейку продуктов Dr.Web.</p>\r
+ \r
+ <p><b>Адрес</b>:<br>\r
+ Отель «Holiday Inn Chelyabinsk-Riverside», Университетская набережная, 18<br>\r
+ Конференц-зал (2 этаж)<br>\r
+ Регистрация участников: 11:00 &mdash; 11:30</p>\r
+ 
@@ -1,31 +0,0 @@
-use Test::More tests => 6;
-
-BEGIN { use_ok 'HTML::Strip' }
-
-{
-  # set_striptags( \@ARRAY )
-  my $hs = HTML::Strip->new;
-  $hs->set_striptags( [ 'foo' ] );
-
-  is( $hs->parse( '<script>foo</script>bar' ), 'foo bar', 'set_striptags redefinition works' );
-  $hs->eof;
-
-  is( $hs->parse( '<foo>foo</foo>bar' ), 'bar', 'set_striptags redefinition works' );
-  $hs->eof;
-}
-
-{
-  # set_striptags( LIST )
-  my @striptags = qw(baz quux);
-  my $hs = HTML::Strip->new;
-  $hs->set_striptags( @striptags );
-
-  is( $hs->parse( '<baz>fumble</baz>bar<quux>foo</quux>' ), 'bar', 'stripping user-defined tags ok' );
-  $hs->eof;
-
-  is( $hs->parse( '<baz>fumble<quux/>foo</baz>bar' ), 'bar', 'stripping user-defined tags ok' );
-  $hs->eof;
-
-  is( $hs->parse( '<foo> </foo> <bar> baz </bar>' ), '   baz ', 'stripping user-defined tags ok' );
-  $hs->eof;
-}
@@ -1,10 +0,0 @@
-use Test::More tests => 2;
-
-BEGIN { use_ok 'HTML::Strip' }
-
-# test for RT#19036
-{
-    my $hs = HTML::Strip->new();
-    is( $hs->parse( '<tr><td>01 May 2006</td><td>0</td><td>10</td></tr>' ), '01 May 2006 0 10', "whitespace single character bug" );
-    $hs->eof;
-}