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