*/
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
* 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);
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));
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;
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);
"<html><head><title>Server Information</title></head>\n", r);
ap_rputs("<body><h1 align=center>Apache Server Information</h1>\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("<tt><a href=\"#server\">Server Settings</a>, ", r);
for (modp = top_module; modp; modp = modp->next) {
cmd++;
}
ap_rputs("<dt><strong>Current Configuration:</strong>\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("<tt> none</tt>\n", r);
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)
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;
return OK;
}
-
CORE_EXPORT(const char *) ap_init_virtual_host(apr_pool_t *p, const char *hostname,
server_rec *main_server, server_rec **ps)
{
}
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.
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)
{