You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@perl.apache.org by Stas Bekman <st...@stason.org> on 2004/05/13 03:51:50 UTC

[mp2] code chunks from attempts to make it possible to complain about misplaced connection filters (for archivals)

I have tried to change the filter handler merging rules so that we can 
complain about connection filters places inside resource container, but while 
it worked OK for resources running under modperl (by tweaking the dir_config 
merging), it doesn't work for non-modperl resources, since we don't control 
how rcfg is merged or may be I have missed something. In any case, I wrote a 
lot of code, so in order not to lose it I'm posting it here for the archival 
in case we need to revisit the topic later.

Index: src/modules/perl/modperl_config.c
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_config.c,v
retrieving revision 1.78
diff -u -r1.78 modperl_config.c
--- src/modules/perl/modperl_config.c	4 Mar 2004 06:01:07 -0000	1.78
+++ src/modules/perl/modperl_config.c	13 May 2004 01:28:57 -0000
@@ -32,6 +32,39 @@
  #define merge_item(item) \
      mrg->item = add->item ? add->item : base->item

+/* XXX: need to write tests */
+/* XXX: merge with modperl_handler_filter_array_merge */
+MP_INLINE static MpAV *get_non_connection_filters(apr_pool_t *p, MpAV *base_a)
+{
+    MpAV *mrg_a = NULL;
+
+    if (base_a) {
+        modperl_handler_t **base_h = (modperl_handler_t **)base_a->elts;
+        int i;
+        for (i=0; i<base_a->nelts; i++) {
+            if (!(base_h[i]->attrs & MP_FILTER_CONNECTION_HANDLER)) {
+                if (!mrg_a) {
+                    mrg_a = modperl_handler_array_new(p);
+                }
+                modperl_handler_array_push(mrg_a, base_h[i]);
+                MP_TRACE_d(MP_FUNC, "merging base filter %s\n",
+                           base_h[i]->name);
+            }
+            else {
+                MP_TRACE_d(MP_FUNC, "not merging base connection filter %s\n",
+                           base_h[i]->name);
+            }
+        }
+    }
+
+    return mrg_a;
+}
+
+#define merge_filter_item(item) \
+    mrg->item = add->item       \
+        ? add->item             \
+        : (base->item ? get_non_connection_filters(p, base->item) : NULL)
+
  static apr_table_t *modperl_table_overlap(apr_pool_t *p,
                                            apr_table_t *base,
                                            apr_table_t *add)
@@ -109,6 +142,72 @@
      return merged_config_vars;
  }

+/* this is identical to modperl_handler_array_merge, but it makes sure
+ * so that connection filters won't be merged into the resource
+ * config. So if a user specifies a connection filter inside a resouce
+ * we can complain about it, without worrying about connection filters
+ * coming from the merge, which are skipped anyway */
+static MpAV *modperl_handler_filter_array_merge(apr_pool_t *p,
+                                                MpAV *base_a, MpAV *add_a)
+{
+    int i, j;
+    modperl_handler_t **base_h, **add_h, **mrg_h;
+    MpAV *mrg_a = NULL;
+
+    /* first merge any non-connection filters from base */
+    if (base_a) {
+        base_h = (modperl_handler_t **)base_a->elts;
+        for (i=0; i<base_a->nelts; i++) {
+            if (!(base_h[i]->attrs & MP_FILTER_CONNECTION_HANDLER)) {
+                if (!mrg_a) {
+                    mrg_a = modperl_handler_array_new(p);
+                }
+                modperl_handler_array_push(mrg_a, base_h[i]);
+                MP_TRACE_d(MP_FUNC, "merging base filter %s\n",
+                           base_h[i]->name);
+            }
+            else {
+                MP_TRACE_d(MP_FUNC, "not merging base connection filter %s\n",
+                           base_h[i]->name);
+            }
+        }
+    }
+
+    if (!mrg_a) {
+        return add_a;
+    }
+
+    /* XXX: you should complain here about connection filters! since
+     * the request phase may never come. ??? */
+
+    /* second add all filters from resource which weren't already
+     * added from base */
+    if (add_a) {
+        int mrg_nelts = mrg_a->nelts;
+        mrg_h  = (modperl_handler_t **)mrg_a->elts;
+        add_h  = (modperl_handler_t **)add_a->elts;
+        MP_TRACE_d(MP_FUNC, "mrg_a %d elements\n",
+                   mrg_a->nelts);
+
+        for (i=0; i<mrg_nelts; i++) {
+            for (j=0; j<add_a->nelts; j++) {
+                if (modperl_handler_equal(mrg_h[i], add_h[j])) {
+                    MP_TRACE_d(MP_FUNC, "both base and new config contain %s\n",
+                               add_h[j]->name);
+                }
+                else {
+                    modperl_handler_array_push(mrg_a, add_h[j]);
+                    MP_TRACE_d(MP_FUNC, "base does not contain %s\n",
+                               add_h[j]->name);
+                }
+            }
+        }
+    }
+
+    return mrg_a;
+}
+
+
  #define merge_handlers(merge_flag, array) \
      if (merge_flag(mrg)) { \
          mrg->array = modperl_handler_array_merge(p, \
@@ -119,6 +218,19 @@
          merge_item(array); \
      }

+#define merge_filter_handlers(merge_flag, array) \
+    if (merge_flag(mrg)) { \
+        mrg->array = modperl_handler_filter_array_merge(p, \
+                                                 base->array, \
+                                                 add->array); \
+    } \
+    else { \
+        merge_filter_item(array); \
+    }
+
+
+
+
  void *modperl_config_dir_merge(apr_pool_t *p, void *basev, void *addv)
  {
      int i;
@@ -156,7 +268,13 @@

      /* XXX: check if Perl*Handler is disabled */
      for (i=0; i < MP_HANDLER_NUM_PER_DIR; i++) {
-        merge_handlers(MpDirMERGE_HANDLERS, handlers_per_dir[i]);
+        /* XXX: output filters */
+        if (i == MP_INPUT_FILTER_HANDLER) {
+            merge_filter_handlers(MpDirMERGE_HANDLERS, handlers_per_dir[i]);
+        }
+        else {
+            merge_handlers(MpDirMERGE_HANDLERS, handlers_per_dir[i]);
+        }
      }

      return mrg;
Index: src/modules/perl/modperl_filter.c

[...]

+            /* process non-mod_perl filter handlers */
              if ((handlers[i]->attrs & MP_FILTER_HTTPD_HANDLER)) {
                  addfunc(handlers[i]->name, NULL, r, r->connection);
                  MP_TRACE_f(MP_FUNC,
@@ -963,10 +973,26 @@
                  continue;
              }

-            if ((handlers[i]->attrs & MP_FILTER_CONNECTION_HANDLER)) {
+            /* XXX: would be nice to complain about connection
+             * filters, placed inside the resource container,
+             * unfortunately for now we can only silently skip them,
+             * because they are valid inside this
+             * dcfg->handlers_per_dir[] entry. It'd be possible to
+             * check if some configuration was misplaced if
+             * connection, request and httpd filter handlers each had
+             * a separate dcfg->handlers_per_dir[] entry, instead of
+             * sharing a single slot for them all..
+             */
+
+            if ((handlers[i]->attrs &&
+                 handlers[i]->attrs & MP_FILTER_CONNECTION_HANDLER)) {
+                dTHX;
                  MP_TRACE_f(MP_FUNC,
-                           "%s is not a FilterRequest handler\n",
+                           "%s is not a FilterRequest handler, skipping\n",
                             handlers[i]->name);
+                Perl_warn(aTHX_ "warn: WHOAH, can't run connection filter %s 
from here", handlers[i]->name);
+                //Perl_croak(aTHX_ "WHOAH, can't run connection filter from 
here");
+
                  continue;
              }

-- 
__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org