diff options
author | Graham Leggett <minfrin@apache.org> | 2018-11-25 21:15:21 +0000 |
---|---|---|
committer | Graham Leggett <minfrin@apache.org> | 2018-11-25 21:15:21 +0000 |
commit | b1e34549c190b63293cbef10cb80383fa8607b29 (patch) | |
tree | a72bcfb095603a6ed21ff9616baaf585927404a6 /server/config.c | |
parent | 3552227669381241e81b2126f94cf61665672d5d (diff) | |
download | httpd-b1e34549c190b63293cbef10cb80383fa8607b29.tar.gz |
core: Split out the ability to parse wildcard files and directories
from the Include/IncludeOptional directives into a generic set of
functions ap_dir_nofnmatch() and ap_dir_fnmatch().
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1847430 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'server/config.c')
-rw-r--r-- | server/config.c | 230 |
1 files changed, 21 insertions, 209 deletions
diff --git a/server/config.c b/server/config.c index b06b6e55ce..dcadba0c66 100644 --- a/server/config.c +++ b/server/config.c @@ -1795,18 +1795,6 @@ static const char *process_command_config(server_rec *s, return NULL; } -typedef struct { - const char *fname; -} fnames; - -static int fname_alphasort(const void *fn1, const void *fn2) -{ - const fnames *f1 = fn1; - const fnames *f2 = fn2; - - return strcmp(f1->fname,f2->fname); -} - /** * Used by -D DUMP_INCLUDES to output the config file "tree". */ @@ -1902,200 +1890,15 @@ AP_DECLARE(const char *) ap_process_resource_config(server_rec *s, return NULL; } -static const char *process_resource_config_nofnmatch(server_rec *s, - const char *fname, - ap_directive_t **conftree, - apr_pool_t *p, - apr_pool_t *ptemp, - unsigned depth, - int optional) -{ - const char *error; - apr_status_t rv; - - if (ap_is_directory(ptemp, fname)) { - apr_dir_t *dirp; - apr_finfo_t dirent; - int current; - apr_array_header_t *candidates = NULL; - fnames *fnew; - char *path = apr_pstrdup(ptemp, fname); - - if (++depth > AP_MAX_INCLUDE_DIR_DEPTH) { - return apr_psprintf(p, "Directory %s exceeds the maximum include " - "directory nesting level of %u. You have " - "probably a recursion somewhere.", path, - AP_MAX_INCLUDE_DIR_DEPTH); - } - - /* - * first course of business is to grok all the directory - * entries here and store 'em away. Recall we need full pathnames - * for this. - */ - rv = apr_dir_open(&dirp, path, ptemp); - if (rv != APR_SUCCESS) { - return apr_psprintf(p, "Could not open config directory %s: %pm", - path, &rv); - } - - candidates = apr_array_make(ptemp, 1, sizeof(fnames)); - while (apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp) == APR_SUCCESS) { - /* strip out '.' and '..' */ - if (strcmp(dirent.name, ".") - && strcmp(dirent.name, "..")) { - fnew = (fnames *) apr_array_push(candidates); - fnew->fname = ap_make_full_path(ptemp, path, dirent.name); - } - } - - apr_dir_close(dirp); - if (candidates->nelts != 0) { - qsort((void *) candidates->elts, candidates->nelts, - sizeof(fnames), fname_alphasort); - - /* - * Now recurse these... we handle errors and subdirectories - * via the recursion, which is nice - */ - for (current = 0; current < candidates->nelts; ++current) { - fnew = &((fnames *) candidates->elts)[current]; - error = process_resource_config_nofnmatch(s, fnew->fname, - conftree, p, ptemp, - depth, optional); - if (error) { - return error; - } - } - } - - return NULL; - } - else if (optional) { - /* If the optinal flag is set (like for IncludeOptional) we can - * tolerate that no file or directory is present and bail out. - */ - apr_finfo_t finfo; - if (apr_stat(&finfo, fname, APR_FINFO_TYPE, ptemp) != APR_SUCCESS - || finfo.filetype == APR_NOFILE) - return NULL; - } - - return ap_process_resource_config(s, fname, conftree, p, ptemp); -} +typedef struct { + server_rec *s; + ap_directive_t **conftree; +} configs; -static const char *process_resource_config_fnmatch(server_rec *s, - const char *path, - const char *fname, - ap_directive_t **conftree, - apr_pool_t *p, - apr_pool_t *ptemp, - unsigned depth, - int optional) +static const char *process_resource_config_cb(ap_dir_match_t *w, const char *fname) { - const char *rest; - apr_status_t rv; - apr_dir_t *dirp; - apr_finfo_t dirent; - apr_array_header_t *candidates = NULL; - fnames *fnew; - int current; - - /* find the first part of the filename */ - rest = ap_strchr_c(fname, '/'); - if (rest) { - fname = apr_pstrmemdup(ptemp, fname, rest - fname); - rest++; - } - - /* optimisation - if the filename isn't a wildcard, process it directly */ - if (!apr_fnmatch_test(fname)) { - path = ap_make_full_path(ptemp, path, fname); - if (!rest) { - return process_resource_config_nofnmatch(s, path, - conftree, p, - ptemp, 0, optional); - } - else { - return process_resource_config_fnmatch(s, path, rest, - conftree, p, - ptemp, 0, optional); - } - } - - /* - * first course of business is to grok all the directory - * entries here and store 'em away. Recall we need full pathnames - * for this. - */ - rv = apr_dir_open(&dirp, path, ptemp); - if (rv != APR_SUCCESS) { - /* If the directory doesn't exist and the optional flag is set - * there is no need to return an error. - */ - if (rv == APR_ENOENT && optional) { - return NULL; - } - return apr_psprintf(p, "Could not open config directory %s: %pm", - path, &rv); - } - - candidates = apr_array_make(ptemp, 1, sizeof(fnames)); - while (apr_dir_read(&dirent, APR_FINFO_DIRENT | APR_FINFO_TYPE, dirp) == APR_SUCCESS) { - /* strip out '.' and '..' */ - if (strcmp(dirent.name, ".") - && strcmp(dirent.name, "..") - && (apr_fnmatch(fname, dirent.name, - APR_FNM_PERIOD) == APR_SUCCESS)) { - const char *full_path = ap_make_full_path(ptemp, path, dirent.name); - /* If matching internal to path, and we happen to match something - * other than a directory, skip it - */ - if (rest && (dirent.filetype != APR_DIR)) { - continue; - } - fnew = (fnames *) apr_array_push(candidates); - fnew->fname = full_path; - } - } - - apr_dir_close(dirp); - if (candidates->nelts != 0) { - const char *error; - - qsort((void *) candidates->elts, candidates->nelts, - sizeof(fnames), fname_alphasort); - - /* - * Now recurse these... we handle errors and subdirectories - * via the recursion, which is nice - */ - for (current = 0; current < candidates->nelts; ++current) { - fnew = &((fnames *) candidates->elts)[current]; - if (!rest) { - error = process_resource_config_nofnmatch(s, fnew->fname, - conftree, p, - ptemp, 0, optional); - } - else { - error = process_resource_config_fnmatch(s, fnew->fname, rest, - conftree, p, - ptemp, 0, optional); - } - if (error) { - return error; - } - } - } - else { - - if (!optional) { - return apr_psprintf(p, "No matches for the wildcard '%s' in '%s', failing " - "(use IncludeOptional if required)", fname, path); - } - } - - return NULL; + configs *cfgs = w->ctx; + return ap_process_resource_config(cfgs->s, fname, cfgs->conftree, w->p, w->ptemp); } AP_DECLARE(const char *) ap_process_fnmatch_configs(server_rec *s, @@ -2105,8 +1908,18 @@ AP_DECLARE(const char *) ap_process_fnmatch_configs(server_rec *s, apr_pool_t *ptemp, int optional) { - /* XXX: lstat() won't work on the wildcard pattern... - */ + configs cfgs; + ap_dir_match_t w; + + cfgs.s = s; + cfgs.conftree = conftree; + + w.prefix = "Include/IncludeOptional: "; + w.p = p; + w.ptemp = ptemp; + w.flags = (optional ? AP_DIR_FLAG_OPTIONAL : AP_DIR_FLAG_NONE) | AP_DIR_FLAG_RECURSIVE; + w.cb = process_resource_config_cb; + w.ctx = &cfgs; /* don't require conf/httpd.conf if we have a -C or -c switch */ if ((ap_server_pre_read_config->nelts @@ -2119,7 +1932,7 @@ AP_DECLARE(const char *) ap_process_fnmatch_configs(server_rec *s, } if (!apr_fnmatch_test(fname)) { - return process_resource_config_nofnmatch(s, fname, conftree, p, ptemp, 0, optional); + return ap_dir_nofnmatch(&w, fname); } else { apr_status_t status; @@ -2137,8 +1950,7 @@ AP_DECLARE(const char *) ap_process_fnmatch_configs(server_rec *s, } /* walk the filepath */ - return process_resource_config_fnmatch(s, rootpath, filepath, conftree, p, ptemp, - 0, optional); + return ap_dir_fnmatch(&w, rootpath, filepath); } } |