diff options
Diffstat (limited to 'APACHE_1_3_42/src/modules/standard/mod_info.c')
-rw-r--r-- | APACHE_1_3_42/src/modules/standard/mod_info.c | 730 |
1 files changed, 730 insertions, 0 deletions
diff --git a/APACHE_1_3_42/src/modules/standard/mod_info.c b/APACHE_1_3_42/src/modules/standard/mod_info.c new file mode 100644 index 0000000000..e672807a0b --- /dev/null +++ b/APACHE_1_3_42/src/modules/standard/mod_info.c @@ -0,0 +1,730 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Info Module. Display configuration information for the server and + * all included modules. + * + * <Location /server-info> + * SetHandler server-info + * </Location> + * + * GET /server-info - Returns full configuration page for server and all modules + * GET /server-info?server - Returns server configuration only + * GET /server-info?module_name - Returns configuration for a single module + * GET /server-info?list - Returns quick list of included modules + * + * Rasmus Lerdorf <rasmus@php.net>, May 1996 + * + * 05.01.96 Initial Version + * + * Lou Langholtz <ldl@usi.utah.edu>, July 1997 + * + * 07.11.97 Addition of the AddModuleInfo directive + * + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_main.h" +#include "http_protocol.h" +#include "util_script.h" +#include "http_conf_globals.h" + +typedef struct { + char *name; /* matching module name */ + char *info; /* additional info */ +} info_entry; + +typedef struct { + array_header *more_info; +} info_svr_conf; + +typedef struct info_cfg_lines { + char *cmd; + char *line; + 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 API_VAR_EXPORT *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(pool *p, server_rec *s) +{ + info_svr_conf *conf = (info_svr_conf *) ap_pcalloc(p, sizeof(info_svr_conf)); + + conf->more_info = ap_make_array(p, 20, sizeof(info_entry)); + return conf; +} + +static void *merge_info_config(pool *p, void *basev, void *overridesv) +{ + info_svr_conf *new = (info_svr_conf *) ap_pcalloc(p, sizeof(info_svr_conf)); + info_svr_conf *base = (info_svr_conf *) basev; + info_svr_conf *overrides = (info_svr_conf *) overridesv; + + new->more_info = ap_append_arrays(p, overrides->more_info, base->more_info); + return new; +} + +static char *mod_info_html_cmd_string(const char *string, char *buf, size_t buf_len) +{ + const char *s; + char *t; + char *end_buf; + + s = string; + t = buf; + /* keep space for \0 byte */ + end_buf = buf + buf_len - 1; + while ((*s) && (t < end_buf)) { + if (*s == '<') { + strncpy(t, "<", end_buf - t); + t += 4; + } + else if (*s == '>') { + strncpy(t, ">", end_buf - t); + t += 4; + } + else if (*s == '&') { + strncpy(t, "&", end_buf - t); + t += 5; + } + else { + *t++ = *s; + } + s++; + } + /* oops, overflowed... don't overwrite */ + if (t > end_buf) { + *end_buf = '\0'; + } + else { + *t = '\0'; + } + return (buf); +} + +static info_cfg_lines *mod_info_load_config(pool *p, const char *filename, + request_rec *r) +{ + char s[MAX_STRING_LEN]; + configfile_t *fp; + info_cfg_lines *new, *ret, *prev; + const char *t; + + fp = ap_pcfg_openfile(p, filename); + if (!fp) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, r, + "mod_info: couldn't open config file %s", + filename); + return NULL; + } + ret = NULL; + prev = NULL; + while (!ap_cfg_getline(s, MAX_STRING_LEN, fp)) { + if (*s == '#') { + continue; /* skip comments */ + } + new = ap_palloc(p, sizeof(struct info_cfg_lines)); + new->next = NULL; + if (!ret) { + ret = new; + } + if (prev) { + prev->next = new; + } + t = s; + new->cmd = ap_getword_conf(p, &t); + if (*t) { + new->line = ap_pstrdup(p, t); + } + else { + new->line = NULL; + } + prev = new; + } + ap_cfg_closefile(fp); + return (ret); +} + +static void mod_info_module_cmds(request_rec *r, info_cfg_lines *cfg, + const command_rec *cmds, char *label) +{ + const command_rec *cmd = cmds; + info_cfg_lines *li = cfg, *li_st = NULL, *li_se = NULL; + info_cfg_lines *block_start = NULL; + int lab = 0, nest = 0; + char buf[MAX_STRING_LEN]; + + while (li) { + if (!strncasecmp(li->cmd, "<directory", 10) || + !strncasecmp(li->cmd, "<location", 9) || + !strncasecmp(li->cmd, "<limit", 6) || + !strncasecmp(li->cmd, "<files", 6)) { + if (nest) { + li_se = li; + } + else { + li_st = li; + } + li = li->next; + nest++; + continue; + } + else if (nest && (!strncasecmp(li->cmd, "</limit", 7) || + !strncasecmp(li->cmd, "</location", 10) || + !strncasecmp(li->cmd, "</directory", 11) || + !strncasecmp(li->cmd, "</files", 7))) { + if (block_start) { + if ((nest == 1 && block_start == li_st) || + (nest == 2 && block_start == li_se)) { + ap_rputs("<dd><tt>", r); + if (nest == 2) { + ap_rputs(" ", r); + } + ap_rputs(mod_info_html_cmd_string(li->cmd, buf, sizeof(buf)), r); + ap_rputs(" ", r); + if (li->line) { + ap_rputs(mod_info_html_cmd_string(li->line, buf, sizeof(buf)), r); + } + ap_rputs("</tt>\n", r); + nest--; + if (!nest) { + block_start = NULL; + li_st = NULL; + } + else { + block_start = li_st; + } + li_se = NULL; + } + else { + nest--; + if (!nest) { + li_st = NULL; + } + li_se = NULL; + } + } + else { + nest--; + if (!nest) { + li_st = NULL; + } + li_se = NULL; + } + li = li->next; + continue; + } + cmd = cmds; + while (cmd) { + if (cmd->name) { + if (!strcasecmp(cmd->name, li->cmd)) { + if (!lab) { + ap_rputs("<dt><strong>", r); + ap_rputs(label, r); + ap_rputs("</strong>\n", r); + lab = 1; + } + if (((nest && block_start == NULL) || + (nest == 2 && block_start == li_st)) && + (strncasecmp(li->cmd, "<directory", 10) && + strncasecmp(li->cmd, "<location", 9) && + strncasecmp(li->cmd, "<limit", 6) && + strncasecmp(li->cmd, "</limit", 7) && + strncasecmp(li->cmd, "</location", 10) && + strncasecmp(li->cmd, "</directory", 11) && + strncasecmp(li->cmd, "</files", 7))) { + ap_rputs("<dd><tt>", r); + ap_rputs(mod_info_html_cmd_string(li_st->cmd, buf, sizeof(buf)), r); + ap_rputs(" ", r); + if (li_st->line) { + ap_rputs(mod_info_html_cmd_string(li_st->line, buf, sizeof(buf)), r); + } + ap_rputs("</tt>\n", r); + block_start = li_st; + if (li_se) { + ap_rputs("<dd><tt> ", r); + ap_rputs(mod_info_html_cmd_string(li_se->cmd, buf, sizeof(buf)), r); + ap_rputs(" ", r); + if (li_se->line) { + ap_rputs(mod_info_html_cmd_string(li_se->line, buf, sizeof(buf)), r); + } + ap_rputs("</tt>\n", r); + block_start = li_se; + } + } + ap_rputs("<dd><tt>", r); + if (nest) { + ap_rputs(" ", r); + } + if (nest == 2) { + ap_rputs(" ", r); + } + ap_rputs(mod_info_html_cmd_string(li->cmd, buf, sizeof(buf)), r); + if (li->line) { + ap_rputs(" <i>", r); + ap_rputs(mod_info_html_cmd_string(li->line, buf, sizeof(buf)), r); + ap_rputs("</i>", r); + } + ap_rputs("</tt>", r); + } + } + else + break; + cmd++; + } + li = li->next; + } +} + +static char *find_more_info(server_rec *s, const char *module_name) +{ + int i; + info_svr_conf *conf = (info_svr_conf *) ap_get_module_config(s->module_config, + &info_module); + info_entry *entry = (info_entry *) conf->more_info->elts; + + if (!module_name) { + return 0; + } + for (i = 0; i < conf->more_info->nelts; i++) { + if (!strcmp(module_name, entry->name)) { + return entry->info; + } + entry++; + } + return 0; +} + +static void mod_info_dirwalk(pool *p, const char *fname, + request_rec *r, array_header *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 *) ap_push_array(carray); + cnew->fname = ap_pstrdup(p, fname); + cnew->clines = mod_info_cfg_tmp; + } else { + DIR *dirp; + struct DIR_TYPE *dir_entry; + int current; + array_header *candidates = NULL; + info_fnames *fnew; + + dirp = ap_popendir(p, fname); + if (dirp == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, r, + "mod_info: couldn't open config directory %s", + fname); + return; + } + candidates = ap_make_array(p, 1, sizeof(info_fnames)); + while ((dir_entry = readdir(dirp)) != NULL) { + /* strip out '.' and '..' */ + if (strcmp(dir_entry->d_name, ".") && + strcmp(dir_entry->d_name, "..")) { + fnew = (info_fnames *) ap_push_array(candidates); + fnew->fname = ap_make_full_path(p, fname, dir_entry->d_name); + } + } + ap_pclosedir(p, 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; + char buf[MAX_STRING_LEN], *cfname; + char *more_info; + const command_rec *cmd = NULL; + const handler_rec *hand = NULL; + server_rec *serv = r->server; + int comma = 0; + array_header *allconfigs = NULL; + info_clines *cnew = NULL; + int current; + char *relpath; + + r->allowed |= (1 << M_GET); + if (r->method_number != M_GET) + return DECLINED; + + r->content_type = "text/html"; + ap_send_http_header(r); + if (r->header_only) { + return 0; + } +#ifdef CHARSET_EBCDIC + /* Server-generated response, converted */ + ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1); +#endif + ap_hard_timeout("send server info", r); + + ap_rputs(DOCTYPE_HTML_3_2 + "<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 = ap_make_array(r->pool, 1, sizeof(info_clines)); + cfname = ap_server_root_relative(r->pool, ap_server_confname); + mod_info_dirwalk(r->pool, cfname, r, allconfigs); + cfname = ap_server_root_relative(r->pool, serv->srm_confname); + mod_info_dirwalk(r->pool, cfname, r, allconfigs); + cfname = ap_server_root_relative(r->pool, serv->access_confname); + 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) { + ap_rprintf(r, "<a href=\"#%s\">%s</a>", modp->name, modp->name); + if (modp->next) { + ap_rputs(", ", r); + } + } + ap_rputs("</tt><hr>", r); + + } + if (!r->args || !strcasecmp(r->args, "server")) { + ap_rprintf(r, "<a name=\"server\"><strong>Server Version:</strong> " + "<font size=+1><tt>%s</tt></a></font><br>\n", + ap_get_server_version()); + ap_rprintf(r, "<strong>Server Built:</strong> " + "<font size=+1><tt>%s</tt></a></font><br>\n", + ap_get_server_built()); + ap_rprintf(r, "<strong>API Version:</strong> " + "<tt>%d:%d</tt><br>\n", + MODULE_MAGIC_NUMBER_MAJOR, MODULE_MAGIC_NUMBER_MINOR); + ap_rprintf(r, "<strong>Run Mode:</strong> <tt>%s</tt><br>\n", + (ap_standalone ? "standalone" : "inetd")); + ap_rprintf(r, "<strong>User/Group:</strong> " + "<tt>%s(%d)/%d</tt><br>\n", + ap_user_name, (int) ap_user_id, (int) ap_group_id); + ap_rprintf(r, "<strong>Hostname/port:</strong> " + "<tt>%s:%u</tt><br>\n", + serv->server_hostname, serv->port); + ap_rprintf(r, "<strong>Daemons:</strong> " + "<tt>start: %d " + "min idle: %d " + "max idle: %d " + "max: %d</tt><br>\n", + ap_daemons_to_start, ap_daemons_min_free, + ap_daemons_max_free, ap_daemons_limit); + ap_rprintf(r, "<strong>Max Requests:</strong> " + "<tt>per child: %d " + "keep alive: %s " + "max per connection: %d</tt><br>\n", + ap_max_requests_per_child, + (serv->keep_alive ? "on" : "off"), + serv->keep_alive_max); + ap_rprintf(r, "<strong>Threads:</strong> " + "<tt>per child: %d </tt><br>\n", + ap_threads_per_child); + ap_rprintf(r, "<strong>Excess requests:</strong> " + "<tt>per child: %d </tt><br>\n", + ap_excess_requests_per_child); + ap_rprintf(r, "<strong>Timeouts:</strong> " + "<tt>connection: %d " + "keep-alive: %d</tt><br>", + serv->timeout, serv->keep_alive_timeout); + ap_rprintf(r, "<strong>Server Root:</strong> " + "<tt>%s</tt><br>\n", ap_server_root); + ap_rprintf(r, "<strong>Config File:</strong> " + "<tt>%s</tt><br>\n", ap_server_confname); + ap_rprintf(r, "<strong>PID File:</strong> " + "<tt>%s</tt><br>\n", ap_pid_fname); + ap_rprintf(r, "<strong>Scoreboard File:</strong> " + "<tt>%s</tt><br>\n", ap_scoreboard_fname); + } + ap_rputs("<hr><dl>", r); + for (modp = top_module; modp; modp = modp->next) { + if (!r->args || !strcasecmp(modp->name, r->args)) { + ap_rprintf(r, "<dt><a name=\"%s\"><strong>Module Name:</strong> " + "<font size=+1><tt>%s</tt></a></font>\n", + modp->name, modp->name); + ap_rputs("<dt><strong>Content handlers:</strong>", r); + hand = modp->handlers; + if (hand) { + while (hand) { + if (hand->content_type) { + ap_rprintf(r, " <tt>%s</tt>\n", hand->content_type); + } + else { + break; + } + hand++; + if (hand && hand->content_type) { + ap_rputs(",", r); + } + } + } + else { + ap_rputs("<tt> <EM>none</EM></tt>", r); + } + ap_rputs("<dt><strong>Configuration Phase Participation:</strong> \n", + r); + if (modp->child_init) { + ap_rputs("<tt>Child Init</tt>", r); + comma = 1; + } + if (modp->create_dir_config) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("<tt>Create Directory Config</tt>", r); + comma = 1; + } + if (modp->merge_dir_config) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("<tt>Merge Directory Configs</tt>", r); + comma = 1; + } + if (modp->create_server_config) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("<tt>Create Server Config</tt>", r); + comma = 1; + } + if (modp->merge_server_config) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("<tt>Merge Server Configs</tt>", r); + comma = 1; + } + if (modp->child_exit) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("<tt>Child Exit</tt>", r); + comma = 1; + } + if (!comma) + ap_rputs("<tt> <EM>none</EM></tt>", r); + comma = 0; + ap_rputs("<dt><strong>Request Phase Participation:</strong> \n", + r); + if (modp->post_read_request) { + ap_rputs("<tt>Post-Read Request</tt>", r); + comma = 1; + } + if (modp->header_parser) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("<tt>Header Parse</tt>", r); + comma = 1; + } + if (modp->translate_handler) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("<tt>Translate Path</tt>", r); + comma = 1; + } + if (modp->access_checker) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("<tt>Check Access</tt>", r); + comma = 1; + } + if (modp->ap_check_user_id) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("<tt>Verify User ID</tt>", r); + comma = 1; + } + if (modp->auth_checker) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("<tt>Verify User Access</tt>", r); + comma = 1; + } + if (modp->type_checker) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("<tt>Check Type</tt>", r); + comma = 1; + } + if (modp->fixer_upper) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("<tt>Fixups</tt>", r); + comma = 1; + } + if (modp->logger) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("<tt>Logging</tt>", r); + comma = 1; + } + if (!comma) + ap_rputs("<tt> <EM>none</EM></tt>", r); + comma = 0; + ap_rputs("<dt><strong>Module Directives:</strong> ", r); + cmd = modp->cmds; + if (cmd) { + while (cmd) { + if (cmd->name) { + ap_rprintf(r, "<dd><tt>%s - <i>", + mod_info_html_cmd_string(cmd->name, + buf, sizeof(buf))); + if (cmd->errmsg) { + ap_rputs(cmd->errmsg, r); + } + ap_rputs("</i></tt>\n", r); + } + else { + break; + } + cmd++; + } + ap_rputs("<dt><strong>Current Configuration:</strong>\n", r); + 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); + } + more_info = find_more_info(serv, modp->name); + if (more_info) { + ap_rputs("<dt><strong>Additional Information:</strong>\n<dd>", + r); + ap_rputs(more_info, r); + } + ap_rputs("<dt><hr>\n", r); + if (r->args) { + break; + } + } + } + if (!modp && r->args && strcasecmp(r->args, "server")) { + ap_rputs("<b>No such module</b>\n", r); + } + } + else { + for (modp = top_module; modp; modp = modp->next) { + ap_rputs(modp->name, r); + if (modp->next) { + ap_rputs("<br>", r); + } + } + } + ap_rputs("</dl>\n", r); + ap_rputs(ap_psignature("",r), r); + ap_rputs("</body></html>\n", r); + /* Done, turn off timeout, close file and return */ + ap_kill_timeout(r); + return 0; +} + +static const char *add_module_info(cmd_parms *cmd, void *dummy, char *name, + char *info) +{ + server_rec *s = cmd->server; + info_svr_conf *conf = (info_svr_conf *) ap_get_module_config(s->module_config, + &info_module); + info_entry *new = ap_push_array(conf->more_info); + + new->name = name; + new->info = info; + return NULL; +} + +static const command_rec info_cmds[] = +{ + {"AddModuleInfo", add_module_info, NULL, RSRC_CONF, TAKE2, + "a module name and additional information on that module"}, + {NULL} +}; + +static const handler_rec info_handlers[] = +{ + {"server-info", display_info}, + {NULL} +}; + +module MODULE_VAR_EXPORT info_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + NULL, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + create_info_config, /* server config */ + merge_info_config, /* merge server config */ + info_cmds, /* command table */ + info_handlers, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; + |