From 3915fb380bd592d01afec1e785047dd432090ad4 Mon Sep 17 00:00:00 2001 From: Graham Leggett Date: Tue, 30 Mar 2010 22:14:24 +0000 Subject: [PATCH] Retract veto over inconsistent behaviour between directory and file wildcards, implement wrowe's missing directory wilcard must fail / missing file wildcard must pass requirement. Introduce 'optional' and 'strict' modifiers to the Include directive for the end user to express their desired behaviour. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@929318 13f79535-47bb-0310-9956-ffa450edef68 --- docs/manual/mod/core.xml | 89 ++++++++++++++++------------------------ server/config.c | 29 +++++++++---- server/core.c | 44 +++++++++++--------- 3 files changed, 82 insertions(+), 80 deletions(-) diff --git a/docs/manual/mod/core.xml b/docs/manual/mod/core.xml index 69fe0ccc5b..4e0beef6fb 100644 --- a/docs/manual/mod/core.xml +++ b/docs/manual/mod/core.xml @@ -1539,8 +1539,7 @@ later. Include Includes other configuration files from within the server configuration files -Include file-path|directory-path| -wildcard +Include [optional|strict] file-path|directory-path|wildcard server configvirtual host directory @@ -1562,20 +1561,27 @@ wildcard matching available in 2.3.6 and later wildcard syntax shown below, to include files that match a particular pattern, such as *.conf, for example.

-

When a wildcard is specified for a file or directory component of the - path, and no file or directory matches the wildcard, the - Include directive will be - silently ignored. When a directory or file component of the path is +

When a wildcard is specified for a file component of + the path, and no file matches the wildcard, the + Include + directive will be silently ignored. When a wildcard is + specified for a directory component of the path, and + no directory matches the wildcard, the + Include directive will + fail with an error saying the directory cannot be found. +

+ +

For further control over the behaviour of the server when no files or + directories match, prefix the path with the modifiers optional + or strict. If optional is specified, any wildcard + file or directory that does not match will be silently ignored. If + strict is specified, any wildcard file or directory that does + not match at least one file will cause server startup to fail.

+ +

When a directory or file component of the path is specified exactly, and that directory or file does not exist, Include directive will fail with an - error saying the file or directory cannot be found. This removes the need - for placeholder files to exist so that at least one file or directory is - found by the wildcard.

- -

Under certain circumstances, it may be required for the server to fail - explicitly when no files or directories match a specific wildcard. In these - cases, use the IncludeStrict - directive instead.

+ error saying the file or directory cannot be found.

The file path specified may be an absolute path, or may be relative to the ServerRoot directory.

@@ -1596,53 +1602,28 @@ wildcard matching available in 2.3.6 and later

Wildcards may be included in the directory or file portion of the - path:

+ path. In the following example, the server will fail to load if no + directories match conf/vhosts/*, but will load successfully if no + files match *.conf.

- Include conf/vhosts/*/vhost.conf + Include conf/vhosts/*/vhost.conf
Include conf/vhosts/*/*.conf
- - -apachectl - - - -IncludeStrict -Includes other configuration files from within the server -configuration files, throwing an error if no files or directories match -a wildcard - -IncludeStrict file-path|directory-path| -wildcard -server configvirtual host -directory - -Available in 2.3.6 and later - - -

This directive allows inclusion of other configuration files - from within the server configuration files.

- -

It is functionally equivalent to the - Include directive, with the additional - restriction that any wildcards are required to match at least one file or - directory.

+

In this example, the server will fail to load if either + conf/vhosts/* matches no directories, or if *.conf matches no files:

-

The file path specified may be an absolute path, or may be relative - to the ServerRoot directory.

- -

Example:

- -

The server will fail to load if the wildcard path - /usr/local/apache2/conf/vhosts/*.conf does not match at least - one file or directory.

+ + Include strict conf/vhosts/*/*.conf + + +

In this example, the server load successfully if either conf/vhosts/* + matches no directories, or if *.conf matches no files:

- - IncludeStrict /usr/local/apache2/conf/ssl.conf
- IncludeStrict /usr/local/apache2/conf/vhosts/*.conf -
+ + Include optional conf/vhosts/*/*.conf +
diff --git a/server/config.c b/server/config.c index 5c48256236..54a58b61a2 100644 --- a/server/config.c +++ b/server/config.c @@ -1559,7 +1559,7 @@ static const char *process_resource_config_nofnmatch(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp, unsigned depth, - int strict) + enum strict_how strict) { cmd_parms parms; ap_configfile_t *cfp; @@ -1661,7 +1661,7 @@ static const char *process_resource_config_fnmatch(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp, unsigned depth, - int strict) + enum strict_how strict) { const char *rest; apr_status_t rv; @@ -1752,9 +1752,24 @@ static const char *process_resource_config_fnmatch(server_rec *s, } } } - else if (strict) { - return apr_psprintf(p, "No matches for the wildcard '%s' in %s", - fname, path); + else { + + /* Support for the three states of strictness: + * + * AP_OPTIONAL - directory and file wildcards succeed on no-match, we don't + * need to do anything here for this case. + * AP_MIXED - directory wildcards fail on no match, file wildcards succeed + * on no match. Use rest to tell between the two. + * AP_STRICT - both directory and file wildcards fail on no-match. + */ + if (AP_STRICT == strict) { + return apr_psprintf(p, "No matches for the wildcard '%s' in '%s' with " + "strict wildcard matching, failing", fname, path); + } + else if (AP_MIXED == strict && rest) { + return apr_psprintf(p, "No matches for the wildcard '%s' in '%s', failing " + "(use Include optional if required)", fname, path); + } } return NULL; @@ -1765,7 +1780,7 @@ AP_DECLARE(const char *) ap_process_resource_config_ex(server_rec *s, ap_directive_t **conftree, apr_pool_t *p, apr_pool_t *ptemp, - int strict) + enum strict_how strict) { /* XXX: lstat() won't work on the wildcard pattern... */ @@ -1814,7 +1829,7 @@ AP_DECLARE(const char *) ap_process_resource_config(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp) { - return ap_process_resource_config_ex(s, fname, conftree, p, ptemp, 0); + return ap_process_resource_config_ex(s, fname, conftree, p, ptemp, AP_MIXED); } AP_DECLARE(int) ap_process_config_tree(server_rec *s, diff --git a/server/core.c b/server/core.c index 4e333ace2b..921bf23c5e 100644 --- a/server/core.c +++ b/server/core.c @@ -2567,13 +2567,33 @@ static const char *set_use_canonical_phys_port(cmd_parms *cmd, void *d_, } static const char *include_config (cmd_parms *cmd, void *dummy, - const char *name, int strict) + const char *arg1, const char *arg2) { ap_directive_t *conftree = NULL; - const char* conffile, *error; + const char *name; + enum strict_how strict; + const char *conffile, *error; unsigned *recursion; void *data; + if (arg2) { + name = arg2; + if (!strcmp(arg1, "optional")) { + strict = AP_OPTIONAL; + } + else if (!strcmp(arg1, "strict")) { + strict = AP_STRICT; + } + else { + return apr_pstrcat(cmd->pool, "Invalid Include modifier '", + arg1, "', should be 'optional' or 'strict'", NULL); + } + } + else { + name = arg1; + strict = AP_MIXED; + } + apr_pool_userdata_get(&data, "ap_include_sentinel", cmd->pool); if (data) { recursion = data; @@ -2615,18 +2635,6 @@ static const char *include_config (cmd_parms *cmd, void *dummy, return NULL; } -static const char *include_regular_config(cmd_parms *cmd, void *dummy, - const char *name) -{ - return include_config(cmd, dummy, name, 0); -} - -static const char *include_strict_config(cmd_parms *cmd, void *dummy, - const char *name) -{ - return include_config(cmd, dummy, name, 1); -} - static const char *set_loglevel(cmd_parms *cmd, void *dummy, const char *arg) { char *str; @@ -3313,12 +3321,10 @@ AP_INIT_TAKE1("UseCanonicalPhysicalPort", set_use_canonical_phys_port, NULL, "Whether to use the physical Port when constructing URLs"), /* TODO: RlimitFoo should all be part of mod_cgi, not in the core */ /* TODO: ListenBacklog in MPM */ -AP_INIT_TAKE1("Include", include_regular_config, NULL, - (RSRC_CONF | ACCESS_CONF | EXEC_ON_READ), - "Name of the config file to be included, ignore wildcards with no match"), -AP_INIT_TAKE1("IncludeStrict", include_strict_config, NULL, +AP_INIT_TAKE12("Include", include_config, NULL, (RSRC_CONF | ACCESS_CONF | EXEC_ON_READ), - "Name of the config file to be included, fail if wildcards don't match"), + "Name of the config file to be included, ignore file wildcards with no " + "matching files, fail directory wildcards with no matching directories"), AP_INIT_TAKE1("LogLevel", set_loglevel, NULL, RSRC_CONF, "Level of verbosity in error logging"), AP_INIT_TAKE1("NameVirtualHost", ap_set_name_virtual_host, NULL, RSRC_CONF, -- 2.40.0