-----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