-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Friday 22 October 2004 00:38, Stas Bekman wrote:
> Torsten Förtsch wrote:
> > +    if( f->c ) {
> > +     for( list=f->c->input_filters; list; list=list->next ) {
> > +         if( list==f ) {
> > +             ap_remove_input_filter(f);
> > +             return;
> > +         }
> > +     }
> > +    }
>
> [ snipped other filter chains traversals ]
>
> but why do you need to traverse all these lists? is it because we don't
> know whether the given filter is an input filter or output one? May be
> it's easier to attach some flag to the filter object to say which kind of
> filter is that?

I thought about it this night and realized that I need not to traverse these 
lists at all. At first ist was a try to guess what to call 
ap_input_filter_remove or ap_output_filter_remove. But if the filter is not 
in an appropriate chain these functions do simply nothing. Hence I can call 
them both if I don't know what kind of filter it is.

> > +static MP_INLINE
> >  void mpxs_Apache__Filter_remove(pTHX_ I32 items, SV **MARK, SV **SP)
> >  {
> >      modperl_filter_t *modperl_filter;
> >      ap_filter_t *f;
> >  
> > -    mpxs_usage_va_1(modperl_filter, "$filter->remove()");
> > +    if (items < 1) {
> > +        Perl_croak(aTHX_ "usage: $filter->remove()");
> > +    }
> > +
> > +    modperl_filter = mp_xs_sv2_modperl_filter(*MARK);
> > +
> > +    if( !modperl_filter ) {  /* native filter */
> > +        mpxs_Apache__Filter_remove_native_filter(aTHX_
> > (ap_filter_t*)SvIV(SvRV(*MARK))); +     return;
> > +    }
> > +
> >      f = modperl_filter->f;
> >  
> >      MP_TRACE_f(MP_FUNC, "   %s\n\n\tfilter removes itself\n",
>
> Also if you could add a test, that will save some time to us. e.g. take
> the t/filter/TestFilter/both_str_req_mix.pm as the base (could probably
> simplify it a bit to just test that it can be removed both on input and
> output). to make your work easier you could just start messing with this
> test and then post it or if you know A-T better you could start a new test

The attached patch contains the updated Apache__Filter.h and a test that 
removes INCLUDES from the output chain and DEFLATE from input.

Torsten
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)

iD8DBQFBeQbrwicyCTir8T4RAtq3AJ9Gpdal0wooCpAST5MYY92dJmueLwCfffB8
KnDaSw1Xs7JDLBQNICt0b5Y=
=YYFu
-----END PGP SIGNATURE-----
diff -Naur mod_perl-1.99_16.orig/t/filter/TestFilter/both_str_native_remove.pm mod_perl-1.99_16/t/filter/TestFilter/both_str_native_remove.pm
--- mod_perl-1.99_16.orig/t/filter/TestFilter/both_str_native_remove.pm	1970-01-01 01:00:00.000000000 +0100
+++ mod_perl-1.99_16/t/filter/TestFilter/both_str_native_remove.pm	2004-10-22 15:03:31.740525400 +0200
@@ -0,0 +1,128 @@
+package TestFilter::both_str_native_remove;
+
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+
+use Apache::RequestRec ();
+use Apache::RequestIO ();
+
+use Apache::Filter ();
+use Apache::FilterRec ();
+
+use Apache::Const -compile => qw(OK DECLINED);
+
+# this filter removes the next filter in chain and itself
+sub remove_next_filter {
+      my $f = shift;
+
+      if( $f->r->args=~/remove/ ) {
+	$f->next->remove;
+      }
+      $f->remove;
+      return Apache::DECLINED;
+}
+
+# this filter removes the next filter in chain and itself
+sub remove_deflate {
+      my $f = shift;
+
+      if( $f->r->args=~/remove/ ) {
+	for( my $ff=$f->r->input_filters; $ff; $ff=$ff->next ) {
+	  if( $ff->frec->name eq 'deflate' ) {
+	    $ff->remove;
+	    last;
+	  }
+	}
+      }
+      $f->remove;
+      return Apache::DECLINED;
+}
+
+# this filter inserts the current filter list at eos
+sub insert_filter_list {
+      my $f = shift;
+
+      unless( $f->ctx ) {
+	  $f->ctx(1);
+	  $f->r->headers_out->unset('Content-Length');
+      }
+
+      while ($f->read(my $buffer, 1024)) {
+          $f->print($buffer);
+      }
+
+      if ($f->seen_eos) {
+	  my @flist;
+	  for( my $f=$f->r->output_filters; $f; $f=$f->next ) {
+	      push @flist, $f->frec->name;
+	  }
+	  {local $"=','; $f->print("flist2: @flist\n");}
+      }
+
+      return Apache::OK;
+}
+
+sub input_filter_list {
+      my $f = shift;
+
+      unless ($f->ctx) {
+	  my @flist;
+	  for( my $f=$f->r->input_filters; $f; $f=$f->next ) {
+	      push @flist, $f->frec->name;
+	  }
+	  my $x=$f->r->pnotes('INPUT_FILTERS')||[];
+	  {local $"=','; push @{$x}, "@flist";}
+	  $f->r->pnotes('INPUT_FILTERS'=>$x);
+      }
+
+      return Apache::DECLINED;
+}
+
+
+sub response {
+    my $r = shift;
+
+    # just to make sure that print() won't flush, or we would get the
+    # count wrong
+    local $| = 0;
+
+    $r->content_type('text/plain');
+    if ($r->method_number == Apache::M_POST) {
+        $r->print( "content: ".ModPerl::Test::read_post($r)."\n" );
+    }
+
+    my $i=1;
+    foreach my $x (@{$r->pnotes('INPUT_FILTERS')||[]}) {
+      $r->print("fin$i: $x\n");
+      $i++;
+    }
+
+    $r->subprocess_env( SSI_TEST=>'SSI OK' );
+    my @flist;
+    for( my $f=$r->output_filters; $f; $f=$f->next ) {
+        push @flist, $f->frec->name;
+    }
+    {local $"=','; $r->print("flist1: @flist\n");}
+    $r->rflush;     # this sends the data in the buffer + flush bucket
+    $r->print('x<!--#echo var=');
+    $r->rflush;     # this sends the data in the buffer + flush bucket
+    $r->print('"SSI_TEST" -->x'."\n");
+
+    Apache::OK;
+}
+1;
+__DATA__
+Options +Includes
+SetHandler modperl
+PerlModule              TestFilter::both_str_native_remove
+PerlResponseHandler     TestFilter::both_str_native_remove::response
+PerlOutputFilterHandler TestFilter::both_str_native_remove::remove_next_filter
+PerlSetOutputFilter     INCLUDES
+PerlOutputFilterHandler TestFilter::both_str_native_remove::insert_filter_list
+PerlInputFilterHandler  TestFilter::both_str_native_remove::input_filter_list
+PerlInputFilterHandler  TestFilter::both_str_native_remove::remove_deflate
+PerlSetInputFilter      DEFLATE
+PerlInputFilterHandler  TestFilter::both_str_native_remove::input_filter_list
diff -Naur mod_perl-1.99_16.orig/t/filter/both_str_native_remove.t mod_perl-1.99_16/t/filter/both_str_native_remove.t
--- mod_perl-1.99_16.orig/t/filter/both_str_native_remove.t	1970-01-01 01:00:00.000000000 +0100
+++ mod_perl-1.99_16/t/filter/both_str_native_remove.t	2004-10-22 15:02:58.332604176 +0200
@@ -0,0 +1,63 @@
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestRequest;
+use Apache::TestUtil;
+
+plan tests =>8, need 'deflate', 'include',
+    need_min_module_version("Compress::Zlib", "1.09");
+
+require Compress::Zlib;
+
+my ($location, $response, $expected, $t);
+
+
+# 1. check if DEFLATE input and INCLUDES output filter work
+
+$location = '/TestFilter__both_str_native_remove';
+$response = POST_BODY $location,
+	    	      content=>Compress::Zlib::memGzip('gzipped text'),
+		     'Content-Encoding' => "gzip";
+
+$expected = 'xSSI OKx';
+($t)=$response=~/^(xSSI OKx)$/m;
+ok t_cmp($t, $expected, "check if INCLUDES work");
+
+$expected = 'gzipped text';
+($t)=$response=~/^content: (gzipped text)$/m;
+ok t_cmp($t, $expected, "check if DEFLATE input work");
+
+
+
+# 2. check if DEFLATE input and INCLUDES output filter can be removed
+
+$location = '/TestFilter__both_str_native_remove?remove';
+$response = POST_BODY $location, content=>'plain text';
+
+$expected = 'modperl_request_output,includes,modperl_request_output,';
+($t)=$response=~/^flist1: (modperl_request_output,includes,modperl_request_output,)/m;
+ok t_cmp($t, $expected, "check if INCLUDES is present");
+
+$expected = 'modperl_request_output,';
+($t)=$response=~/^flist2: (modperl_request_output,)(?!includes)/m;
+ok t_cmp($t, $expected, "check if INCLUDES is removed");
+
+$expected = 'x<!--#echo var="SSI_TEST" -->x';
+($t)=$response=~/^(x<!--#echo var="SSI_TEST" -->x)$/m;
+ok t_cmp($t, $expected, "check if INCLUDES does not work");
+
+$expected = 'deflate';
+($t)=$response=~/^fin1: \S+,(deflate),\S+/m;
+ok t_cmp($t, $expected, "check if DEFLATE is present");
+
+$expected = undef;
+($t)=$response=~/^fin2: \S+,(deflate),\S+/m;
+ok t_cmp($t, $expected, "check if DEFLATE is removed");
+
+$expected = 'plain text';
+($t)=$response=~/^content: (plain text)$/m;
+ok t_cmp($t, $expected, "check if DEFLATE input does not work");
+
+
+
diff -Naur mod_perl-1.99_16.orig/xs/Apache/Filter/Apache__Filter.h mod_perl-1.99_16/xs/Apache/Filter/Apache__Filter.h
--- mod_perl-1.99_16.orig/xs/Apache/Filter/Apache__Filter.h	2004-07-12 09:32:07.000000000 +0200
+++ mod_perl-1.99_16/xs/Apache/Filter/Apache__Filter.h	2004-10-22 15:04:09.586771896 +0200
@@ -282,7 +282,24 @@
     modperl_filter_t *modperl_filter;
     ap_filter_t *f;
 
-    mpxs_usage_va_1(modperl_filter, "$filter->remove()");
+    if (items < 1) {
+        Perl_croak(aTHX_ "usage: $filter->remove()");
+    }
+
+    modperl_filter = mp_xs_sv2_modperl_filter(*MARK);
+
+    if( !modperl_filter ) {	/* native filter */
+        f=(ap_filter_t*)SvIV(SvRV(*MARK));
+
+	/* the filter can reside in only one chain. hence we try to remove */
+	/* it first from the input chains then from the output chains. */
+	/* too bad, ap_*_remove_filter are void functions. so, there is no */
+	/* way to check if the filter is successfully removed. */
+        ap_remove_input_filter(f);
+        ap_remove_output_filter(f);
+	return;
+    }
+
     f = modperl_filter->f;
 
     MP_TRACE_f(MP_FUNC, "   %s\n\n\tfilter removes itself\n",

-- 
Report problems: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html
List etiquette: http://perl.apache.org/maillist/email-etiquette.html

Reply via email to