dougm 01/03/25 17:08:30 Modified: lib/ModPerl Code.pm src/modules/perl modperl_config.c modperl_handler.c modperl_handler.h modperl_mgv.c modperl_mgv.h Log: add support for proper merge of handlers example: PerlFixupHandler One::fixup <Location /foo> PerlFixupHandler Another::fixup </Location> default request for /foo only runs Another::fixup (1.x behavior) PerlOptions +MergeHandlers (inside Location /foo) will run both One::fixup and Another::fixup Revision Changes Path 1.53 +3 -2 modperl-2.0/lib/ModPerl/Code.pm Index: Code.pm =================================================================== RCS file: /home/cvs/modperl-2.0/lib/ModPerl/Code.pm,v retrieving revision 1.52 retrieving revision 1.53 diff -u -r1.52 -r1.53 --- Code.pm 2001/03/25 17:42:26 1.52 +++ Code.pm 2001/03/26 01:08:28 1.53 @@ -89,8 +89,9 @@ #XXX: allow disabling of PerDir hooks on a PerDir basis my @hook_flags = (map { canon_uc($_) } keys %hooks); my %flags = ( - Srv => [qw(NONE CLONE PARENT ENABLED AUTOLOAD), @hook_flags, 'UNSET'], - Dir => [qw(NONE SEND_HEADER SETUP_ENV UNSET)], + Srv => [qw(NONE CLONE PARENT ENABLED AUTOLOAD MERGE_HANDLERS), + @hook_flags, 'UNSET'], + Dir => [qw(NONE SEND_HEADER SETUP_ENV MERGE_HANDLERS UNSET)], Interp => [qw(NONE IN_USE PUTBACK CLONED BASE)], Handler => [qw(NONE PARSED METHOD OBJECT ANON AUTOLOAD DYNAMIC)], ); 1.29 +31 -25 modperl-2.0/src/modules/perl/modperl_config.c Index: modperl_config.c =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_config.c,v retrieving revision 1.28 retrieving revision 1.29 diff -u -r1.28 -r1.29 --- modperl_config.c 2001/03/25 17:42:26 1.28 +++ modperl_config.c 2001/03/26 01:08:29 1.29 @@ -15,8 +15,19 @@ #define merge_item(item) \ mrg->item = add->item ? add->item : base->item +#define merge_handlers(merge_flag, array) \ + if (merge_flag(mrg)) { \ + mrg->array = modperl_handler_array_merge(p, \ + base->array, \ + add->array); \ + } \ + else { \ + merge_item(array); \ + } + void *modperl_config_dir_merge(apr_pool_t *p, void *basev, void *addv) { + int i; modperl_config_dir_t *base = (modperl_config_dir_t *)basev, *add = (modperl_config_dir_t *)addv, @@ -29,16 +40,13 @@ merge_item(interp_lifetime); #endif - { /* XXX: should do a proper merge of the arrays */ - /* XXX: and check if Perl*Handler is disabled */ - int i; - for (i=0; i < MP_HANDLER_NUM_PER_DIR; i++) { - merge_item(handlers_per_dir[i]); - } - } - mrg->flags = modperl_options_merge(p, base->flags, add->flags); + /* 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]); + } + return mrg; } @@ -132,6 +140,7 @@ /* XXX: this is not complete */ void *modperl_config_srv_merge(apr_pool_t *p, void *basev, void *addv) { + int i; modperl_config_srv_t *base = (modperl_config_srv_t *)basev, *add = (modperl_config_srv_t *)addv, @@ -151,24 +160,21 @@ merge_item(argv); - { /* XXX: should do a proper merge of the arrays */ - /* XXX: and check if Perl*Handler is disabled */ - int i; - for (i=0; i < MP_HANDLER_NUM_PER_SRV; i++) { - merge_item(handlers_per_srv[i]); - } - for (i=0; i < MP_HANDLER_NUM_FILES; i++) { - merge_item(handlers_files[i]); - } - for (i=0; i < MP_HANDLER_NUM_PROCESS; i++) { - merge_item(handlers_process[i]); - } - for (i=0; i < MP_HANDLER_NUM_CONNECTION; i++) { - merge_item(handlers_connection[i]); - } - } - mrg->flags = modperl_options_merge(p, base->flags, add->flags); + + /* XXX: check if Perl*Handler is disabled */ + for (i=0; i < MP_HANDLER_NUM_PER_SRV; i++) { + merge_handlers(MpSrvMERGE_HANDLERS, handlers_per_srv[i]); + } + for (i=0; i < MP_HANDLER_NUM_FILES; i++) { + merge_handlers(MpSrvMERGE_HANDLERS, handlers_files[i]); + } + for (i=0; i < MP_HANDLER_NUM_PROCESS; i++) { + merge_handlers(MpSrvMERGE_HANDLERS, handlers_process[i]); + } + for (i=0; i < MP_HANDLER_NUM_CONNECTION; i++) { + merge_handlers(MpSrvMERGE_HANDLERS, handlers_connection[i]); + } return mrg; } 1.7 +45 -0 modperl-2.0/src/modules/perl/modperl_handler.c Index: modperl_handler.c =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_handler.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- modperl_handler.c 2001/03/17 06:03:37 1.6 +++ modperl_handler.c 2001/03/26 01:08:29 1.7 @@ -18,6 +18,51 @@ return modperl_handler_new(p, h->name); } +int modperl_handler_equal(modperl_handler_t *h1, modperl_handler_t *h2) +{ + if (h1->mgv_cv && h2->mgv_cv) { + return modperl_mgv_equal(h1->mgv_cv, h2->mgv_cv); + } + return strEQ(h1->name, h2->name); +} + +MpAV *modperl_handler_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; + + if (!add_a) { + return base_a; + } + + if (!base_a) { + return add_a; + } + + mrg_a = apr_array_copy(p, base_a); + + mrg_h = (modperl_handler_t **)mrg_a->elts; + base_h = (modperl_handler_t **)base_a->elts; + add_h = (modperl_handler_t **)add_a->elts; + + for (i=0; i<base_a->nelts; i++) { + for (j=0; j<add_a->nelts; j++) { + if (modperl_handler_equal(base_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; +} + void modperl_handler_make_args(pTHX_ AV **avp, ...) { va_list args; 1.6 +4 -0 modperl-2.0/src/modules/perl/modperl_handler.h Index: modperl_handler.h =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_handler.h,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- modperl_handler.h 2001/03/17 06:03:37 1.5 +++ modperl_handler.h 2001/03/26 01:08:29 1.6 @@ -24,6 +24,10 @@ modperl_handler_t *modperl_handler_dup(apr_pool_t *p, modperl_handler_t *h); +int modperl_handler_equal(modperl_handler_t *h1, modperl_handler_t *h2); + +MpAV *modperl_handler_array_merge(apr_pool_t *p, MpAV *base_a, MpAV *add_a); + void modperl_handler_make_args(pTHX_ AV **avp, ...); MpAV **modperl_handler_lookup_handlers(modperl_config_dir_t *dcfg, 1.11 +18 -0 modperl-2.0/src/modules/perl/modperl_mgv.c Index: modperl_mgv.c =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_mgv.c,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- modperl_mgv.c 2001/03/25 21:26:47 1.10 +++ modperl_mgv.c 2001/03/26 01:08:29 1.11 @@ -50,6 +50,24 @@ #define hv_fetch_he(hv,k,l,h) S_hv_fetch_he(aTHX_ hv,k,l,h) +int modperl_mgv_equal(modperl_mgv_t *mgv1, + modperl_mgv_t *mgv2) +{ + for (; mgv1 && mgv2; mgv1=mgv1->next, mgv2=mgv2->next) { + if (mgv1->hash != mgv2->hash) { + return FALSE; + } + if (mgv1->len != mgv2->len) { + return FALSE; + } + if (memNE(mgv1->name, mgv2->name, mgv1->len)) { + return FALSE; + } + } + + return TRUE; +} + modperl_mgv_t *modperl_mgv_new(apr_pool_t *p) { return (modperl_mgv_t *)apr_pcalloc(p, sizeof(modperl_mgv_t)); 1.4 +3 -0 modperl-2.0/src/modules/perl/modperl_mgv.h Index: modperl_mgv.h =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_mgv.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- modperl_mgv.h 2001/03/17 06:03:37 1.3 +++ modperl_mgv.h 2001/03/26 01:08:29 1.4 @@ -3,6 +3,9 @@ modperl_mgv_t *modperl_mgv_new(apr_pool_t *p); +int modperl_mgv_equal(modperl_mgv_t *mgv1, + modperl_mgv_t *mgv2); + modperl_mgv_t *modperl_mgv_compile(pTHX_ apr_pool_t *p, const char *name); char *modperl_mgv_name_from_sv(pTHX_ apr_pool_t *p, SV *sv);