From 6ebf77b96c1912fa0406e84ab18fbb02ba6a8590 Mon Sep 17 00:00:00 2001 From: Jim Jagielski Date: Thu, 5 Oct 2000 22:35:08 +0000 Subject: [PATCH] Port over the config directory stuff... git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86409 13f79535-47bb-0310-9956-ffa450edef68 --- include/httpd.h | 16 ++++++ modules/generators/mod_info.c | 93 ++++++++++++++++++++++++++++++----- server/config.c | 65 +++++++++++++++++++++++- server/util.c | 36 ++++++++++++++ 4 files changed, 198 insertions(+), 12 deletions(-) diff --git a/include/httpd.h b/include/httpd.h index ad5cbe9117..77f7c7ca63 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -1371,6 +1371,15 @@ API_EXPORT(int) ap_strcasecmp_match(const char *str, const char *exp); */ API_EXPORT(char *) ap_strcasestr(const char *s1, const char *s2); +/** + * Return a pointer to the location inside of bigstring immediately after prefix + * @param bigstring The input string + * @param prefix The prefix to strip away + * @return A pointer relative to bigstring after prefix + * deffunc char *ap_stripprefix(const char *bigstring, const char *prefix); + */ +API_EXPORT(char *) ap_stripprefix(const char *bigstring, const char *prefix); + /** * Decode a base64 encoded string into memory allocated out of a pool * @param p The pool to allocate out of @@ -1525,6 +1534,13 @@ API_EXPORT(gid_t) ap_gname2id(const char *name); * Given the name of an object in the file system determine if it is a directory * @param name The name of the object to check * @return 1 if it is a directory, 0 otherwise + * @deffunc int ap_is_rdirectory(const char *name) + */ +API_EXPORT(int) ap_is_rdirectory(const char *name); +/** + * Given the name of an object in the file system determine if it is a directory - this version is symlink aware + * @param name The name of the object to check + * @return 1 if it is a directory, 0 otherwise * @deffunc int ap_is_directory(const char *name) */ API_EXPORT(int) ap_is_directory(const char *name); diff --git a/modules/generators/mod_info.c b/modules/generators/mod_info.c index 4499258943..6a8758cbf8 100644 --- a/modules/generators/mod_info.c +++ b/modules/generators/mod_info.c @@ -103,9 +103,27 @@ typedef struct info_cfg_lines { struct info_cfg_lines *next; } info_cfg_lines; +typedef struct { /* shamelessly lifted from http_config.c */ + char *fname; +} info_fnames; + +typedef struct { + info_cfg_lines *clines; + char *fname; +} info_clines; + module MODULE_VAR_EXPORT info_module; extern module *top_module; +/* shamelessly lifted from http_config.c */ +static int fname_alphasort(const void *fn1, const void *fn2) +{ + const info_fnames *f1 = fn1; + const info_fnames *f2 = fn2; + + return strcmp(f1->fname,f2->fname); +} + static void *create_info_config(apr_pool_t *p, server_rec *s) { info_svr_conf *conf = (info_svr_conf *) apr_pcalloc(p, sizeof(info_svr_conf)); @@ -356,6 +374,53 @@ static char *find_more_info(server_rec *s, const char *module_name) return 0; } +static void mod_info_dirwalk(pool *p, const char *fname, + request_rec *r, apr_array_header_t *carray) +{ + info_clines *cnew = NULL; + info_cfg_lines *mod_info_cfg_tmp = NULL; + + if (!ap_is_rdirectory(fname)) { + mod_info_cfg_tmp = mod_info_load_config(p, fname, r); + cnew = (info_clines *) apr_push_array(carray); + cnew->fname = ap_pstrdup(p, fname); + cnew->clines = mod_info_cfg_tmp; + } else { + apr_dir_t *dirp; + int current; + apr_array_header_t *candidates = NULL; + info_fnames *fnew; + + if (apr_opendir(&dirp, fname, p) != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, r, + "mod_info: couldn't open config directory %s", + fname); + return; + } + candidates = apr_make_array(p, 1, sizeof(info_fnames)); + while (apr_readdir(dirp) == APR_SUCCESS) { + char *d_name; + apr_get_dir_filename(&d_name, dirp); + /* strip out '.' and '..' */ + if (strcmp(d_name, ".") && + strcmp(d_name, "..")) { + fnew = (info_fnames *) apr_push_array(candidates); + fnew->fname = ap_make_full_path(p, fname, d_name); + } + } + apr_closedir(dirp); + if (candidates->nelts != 0) { + qsort((void *) candidates->elts, candidates->nelts, + sizeof(info_fnames), fname_alphasort); + for (current = 0; current < candidates->nelts; ++current) { + fnew = &((info_fnames *) candidates->elts)[current]; + mod_info_dirwalk(p, fnew->fname, r, carray); + } + } + } + return; +} + static int display_info(request_rec *r) { module *modp = NULL; @@ -365,13 +430,14 @@ static int display_info(request_rec *r) const handler_rec *hand = NULL; server_rec *serv = r->server; int comma = 0; - info_cfg_lines *mod_info_cfg_httpd = NULL; - info_cfg_lines *mod_info_cfg_srm = NULL; - info_cfg_lines *mod_info_cfg_access = NULL; + apr_array_header_t *allconfigs = NULL; + info_clines *cnew = NULL; + int current; + char *relpath; r->allowed |= (1 << M_GET); if (r->method_number != M_GET) - return DECLINED; + return DECLINED; r->content_type = "text/html"; ap_send_http_header(r); @@ -383,8 +449,9 @@ static int display_info(request_rec *r) "Server Information\n", r); ap_rputs("

Apache Server Information

\n", r); if (!r->args || strcasecmp(r->args, "list")) { + allconfigs = apr_make_array(r->pool, 1, sizeof(info_clines)); cfname = ap_server_root_relative(r->pool, ap_server_confname); - mod_info_cfg_httpd = mod_info_load_config(r->pool, cfname, r); + mod_info_dirwalk(r->pool, cfname, r, allconfigs); if (!r->args) { ap_rputs("Server Settings, ", r); for (modp = top_module; modp; modp = modp->next) { @@ -595,12 +662,16 @@ static int display_info(request_rec *r) cmd++; } ap_rputs("
Current Configuration:\n", r); - mod_info_module_cmds(r, mod_info_cfg_httpd, modp->cmds, - "httpd.conf"); - mod_info_module_cmds(r, mod_info_cfg_srm, modp->cmds, - "srm.conf"); - mod_info_module_cmds(r, mod_info_cfg_access, modp->cmds, - "access.conf"); + for (current = 0; current < allconfigs->nelts; ++current) { + cnew = &((info_clines *) allconfigs->elts)[current]; + /* get relative pathname with some safeguards */ + relpath = ap_stripprefix(cnew->fname,ap_server_root); + if (*relpath != '\0' && relpath != cnew->fname && + *relpath == '/') + relpath++; + mod_info_module_cmds(r, cnew->clines, modp->cmds, + relpath); + } } else { ap_rputs(" none\n", r); diff --git a/server/config.c b/server/config.c index f965592cc0..51fe37a14d 100644 --- a/server/config.c +++ b/server/config.c @@ -1318,6 +1318,18 @@ static void process_command_config(server_rec *s, apr_array_header_t *arr, ap_cfg_closefile(parms.config_file); } +typedef struct { + 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); +} + void ap_process_resource_config(server_rec *s, const char *fname, ap_directive_t **conftree, apr_pool_t *p, apr_pool_t *ptemp) @@ -1337,6 +1349,58 @@ void ap_process_resource_config(server_rec *s, const char *fname, return; } + /* + * here we want to check if the candidate file is really a + * directory, and most definitely NOT a symlink (to prevent + * horrible loops). If so, let's recurse and toss it back into + * the function. + */ + if (ap_is_rdirectory(fname)) { + apr_dir_t *dirp; + int current; + apr_array_header_t *candidates = NULL; + fnames *fnew; + + /* + * first course of business is to grok all the directory + * entries here and store 'em away. Recall we need full pathnames + * for this. + */ + fprintf(stderr, "Processing config directory: %s\n", fname); + if (apr_opendir(&dirp, fname, p) != APR_SUCCESS) { + perror("fopen"); + fprintf(stderr, "%s: could not open config directory %s\n", + ap_server_argv0, fname); + exit(1); + } + candidates = apr_make_array(p, 1, sizeof(fnames)); + while (apr_readdir(dirp) == APR_SUCCESS) { + char *d_name; + apr_get_dir_filename(&d_name, dirp); + /* strip out '.' and '..' */ + if (strcmp(d_name, ".") && + strcmp(d_name, "..")) { + fnew = (fnames *) apr_push_array(candidates); + fnew->fname = ap_make_full_path(p, fname, d_name); + } + } + apr_closedir(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]; + fprintf(stderr, " Processing config file: %s\n", fnew->fname); + ap_process_resource_config(s, fnew->fname, conftree, p, ptemp); + } + } + return; + } + /* GCC's initialization extensions are soooo nice here... */ parms = default_parms; @@ -1472,7 +1536,6 @@ int ap_parse_htaccess(void **result, request_rec *r, int override, return OK; } - CORE_EXPORT(const char *) ap_init_virtual_host(apr_pool_t *p, const char *hostname, server_rec *main_server, server_rec **ps) { diff --git a/server/util.c b/server/util.c index 2273058283..9191ad0df9 100644 --- a/server/util.c +++ b/server/util.c @@ -333,6 +333,32 @@ API_EXPORT(char *) ap_strcasestr(const char *s1, const char *s2) } return((char *)s1); } + +/* + * Returns an offsetted pointer in bigstring immediately after + * prefix. Returns bigstring if bigstring doesn't start with + * prefix or if prefix is longer than bigstring while still matching. + * NOTE: pointer returned is relative to bigstring, so we + * can use standard pointer comparisons in the calling function + * (eg: test if ap_stripprefix(a,b) == a) + */ +API_EXPORT(char *) ap_stripprefix(const char *bigstring, const char *prefix) +{ + char *p1; + if (*prefix == '\0') { + return( (char *)bigstring); + } + p1 = (char *)bigstring; + while(*p1 && *prefix) { + if (*p1++ != *prefix++) + return( (char *)bigstring); + } + if (*prefix == '\0') + return(p1); + else /* hit the end of bigstring! */ + return( (char *)bigstring); +} + /* * Apache stub function for the regex libraries regexec() to make sure the * whole regex(3) API is available through the Apache (exported) namespace. @@ -1652,6 +1678,16 @@ API_EXPORT(int) ap_is_directory(const char *path) return (finfo.filetype == APR_DIR); } +API_EXPORT(int) ap_is_rdirectory(const char *path) +{ + apr_finfo_t finfo; + + if (apr_lstat(&finfo, path, NULL) == -1) + return 0; /* in error condition, just return no */ + + return (finfo.filetype == APR_DIR); +} + API_EXPORT(char *) ap_make_full_path(apr_pool_t *a, const char *src1, const char *src2) { -- 2.50.1