On Tue, Mar 07, 2017 at 11:52:17AM -0800, Jacob Champion wrote:
> On 02/28/2017 04:32 PM, Jacob Champion wrote:
> > I just don't like hamstringing a nice new directive with what's
> > effectively a (rare) bug.
> 
> (The conversation kinda died shortly after I said this. That was not my
> intent -- I like this directive a lot. Whether the consensus is to keep the
> corner case, or introduce a new <IfSection> or <IfContainer>, or make the
> arg quotable, or whatever. I don't mean to be throwing up roadblocks.)

Sorry, taking my time here, and I appreciate all the feedback.  
Definitely happier to debate it and get it right than be lumbered with 
annoying edge cases forever.

I did the refactoring in r1785943, so third iteration attached has both 
<IfDirective X> and <IfSection Y>.  I'd have been fine with either 
previous iteration, but this does make sense to me.

Final call for yay/nay?

Regards, Joe
Index: server/config.c
===================================================================
--- server/config.c     (revision 1785938)
+++ server/config.c     (working copy)
@@ -2668,6 +2668,16 @@
         printf("  %s\n", ap_loaded_modules[n]->name);
 }
 
+AP_DECLARE(int) ap_exists_directive(apr_pool_t *p, const char *name)
+{
+    char *lname = apr_pstrdup(p, name);
+
+    ap_str_tolower(lname);
+    
+    return ap_config_hash &&
+        apr_hash_get(ap_config_hash, lname, APR_HASH_KEY_STRING) != NULL;
+}
+
 AP_DECLARE(void *) ap_retained_data_get(const char *key)
 {
     void *retained;
Index: server/core.c
===================================================================
--- server/core.c       (revision 1785943)
+++ server/core.c       (working copy)
@@ -2838,6 +2838,17 @@
     return (apr_stat(&sb, relative, 0, cmd->pool) == APR_SUCCESS);
 }
 
+static int test_ifdirective_section(cmd_parms *cmd, const char *arg)
+{
+    return ap_exists_directive(cmd->temp_pool, arg);
+}
+
+static int test_ifsection_section(cmd_parms *cmd, const char *arg)
+{
+    const char *name = apr_pstrcat(cmd->temp_pool, "<", arg, NULL);
+    return ap_exists_directive(cmd->temp_pool, name);
+}
+
 /* httpd.conf commands... beginning with the <VirtualHost> business */
 
 static const char *virtualhost_section(cmd_parms *cmd, void *dummy,
@@ -4456,6 +4467,12 @@
 AP_INIT_TAKE1("<IfFile", start_cond_section, (void *)test_iffile_section,
               EXEC_ON_READ | OR_ALL,
   "Container for directives based on existence of files on disk"),
+AP_INIT_TAKE1("<IfDirective", start_cond_section, (void 
*)test_ifdirective_section,
+              EXEC_ON_READ | OR_ALL,
+  "Container for directives based on existence of named directive"),
+AP_INIT_TAKE1("<IfSection", start_cond_section, (void *)test_ifsection_section,
+              EXEC_ON_READ | OR_ALL,
+  "Container for directives based on existence of named section"),
 AP_INIT_RAW_ARGS("<DirectoryMatch", dirsection, (void*)1, RSRC_CONF,
   "Container for directives affecting resources located in the "
   "specified directories"),
Index: include/http_config.h
===================================================================
--- include/http_config.h       (revision 1785938)
+++ include/http_config.h       (working copy)
@@ -992,6 +992,12 @@
 AP_DECLARE(void) ap_show_directives(void);
 
 /**
+ * Returns non-zero if a configuration directive of the given name has
+ * been registered by a module at the time of calling.
+ */
+AP_DECLARE(int) ap_exists_directive(apr_pool_t *p, const char *name);
+
+/**
  * Show the preloaded module names.  Used for httpd -l.
  */
 AP_DECLARE(void) ap_show_modules(void);

Reply via email to