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

Hi,

the attached patch makes Apache::Filter::remove work also for nativ filters.

Why do I need this?

First, from a users point of view it is not very understandable why a mod_perl 
filter can be removed but a native filter (eg. INCLUDES) cannot.

My actual problem is the following. I have got some CGI and mod_perl scripts 
that generate HTML and images. The HTML output should be filtered by INCLUDES 
and a mod_perl filter, the images should be filtered only by my mod_perl 
filter. The mod_perl filter must be called _after_ INCLUDES.

If I "AddOutputFilterByType INCLUDES text/html" the INCLUDES filter is called 
_before_ the mod_perl filter. If I use PerlSetOutputFilter the filters are 
called in the right order but INCLUDES is called for all documents.

There are multiple solutions. I could patch mod_include or add a 
PerlAddOutputFilterByType directive or just use the existing 
PerlSetOutputFilter and write a little filter that checks the requests 
content-type and removes the next filter in the chain if needed:

PerlOutputFilterHandler Apache::Opis::RemoveNextFilterIfNotTextHtml
PerlSetOutputFilter INCLUDES
PerlOutputFilterHandler Apache::Opis::MyFilter

where Apache::Opis::MyFilter is the filter that needs to be called after 
INCLUDES. The removing filter looks like:

- --------------------------------------------------------------------
package Apache::Opis::RemoveNextFilterIfNotTextHtml;

use strict;
use Apache::Filter ();
use Apache::FilterRec ();
use Apache::RequestRec ();

use Apache::Const -compile => qw(OK DECLINED);

sub handler {
  my $f   = shift;
  my $r   = $f->r;

  unless( $r->content_type =~ m!text/html!i ) {
    eval {
      $f->next->remove;
    };
    warn $@ if $@;
  }
  $f->remove;

  return Apache::DECLINED;
}

1;
- --------------------------------------------------------------------

This code fails with INCLUDES because mod_include is not a mod_perl filter. 
Hence I had to patch Apache::Filter::remove.

Torsten


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

iD8DBQFBeAxWwicyCTir8T4RAnqyAJ0UW7ky8Z4ApZND9SDpX+LMNzijuACfZwkM
fQvJW0WchvJo9MsUvJmCoos=
=mizK
-----END PGP SIGNATURE-----
--- mod_perl-1.99_16/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-21 13:52:13.243774248 +0200
@@ -277,12 +277,85 @@
 }
 
 static MP_INLINE
+void mpxs_Apache__Filter_remove_native_filter(pTHX_ ap_filter_t* f)
+{
+    ap_filter_t *list;
+
+    if( f->c ) {
+	for( list=f->c->input_filters; list; list=list->next ) {
+	    if( list==f ) {
+		ap_remove_input_filter(f);
+		return;
+	    }
+	}
+    }
+
+    if( f->r ) {
+	for( list=f->r->proto_input_filters; list; list=list->next ) {
+	    if( list==f ) {
+		ap_remove_input_filter(f);
+		return;
+	    }
+	}
+    }
+
+    if( f->r ) {
+	for( list=f->r->input_filters; list; list=list->next ) {
+	    if( list==f ) {
+		ap_remove_input_filter(f);
+		return;
+	    }
+	}
+    }
+
+    if( f->c ) {
+	for( list=f->c->output_filters; list; list=list->next ) {
+	    if( list==f ) {
+		ap_remove_output_filter(f);
+		return;
+	    }
+	}
+    }
+
+    if( f->r ) {
+	for( list=f->r->proto_output_filters; list; list=list->next ) {
+	    if( list==f ) {
+		ap_remove_output_filter(f);
+		return;
+	    }
+	}
+    }
+
+    if( f->r ) {
+	for( list=f->r->output_filters; list; list=list->next ) {
+	    if( list==f ) {
+		ap_remove_output_filter(f);
+		return;
+	    }
+	}
+    }
+
+    Perl_croak(aTHX_ "filter=%d not removed", f);
+    return;
+}
+
+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",

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