1 /* ====================================================================
2 * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
16 * 3. All advertising materials mentioning features or use of this
17 * software must display the following acknowledgment:
18 * "This product includes software developed by the Apache Group
19 * for use in the Apache HTTP server project (http://www.apache.org/)."
21 * 4. The names "Apache Server" and "Apache Group" must not be used to
22 * endorse or promote products derived from this software without
23 * prior written permission. For written permission, please contact
26 * 5. Products derived from this software may not be called "Apache"
27 * nor may "Apache" appear in their names without prior written
28 * permission of the Apache Group.
30 * 6. Redistributions of any form whatsoever must retain the following
32 * "This product includes software developed by the Apache Group
33 * for use in the Apache HTTP server project (http://www.apache.org/)."
35 * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
36 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46 * OF THE POSSIBILITY OF SUCH DAMAGE.
47 * ====================================================================
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Apache Group and was originally based
51 * on public domain software written at the National Center for
52 * Supercomputing Applications, University of Illinois, Urbana-Champaign.
53 * For more information on the Apache Group and the Apache HTTP server
54 * project, please see <http://www.apache.org/>.
59 * Info Module. Display configuration information for the server and
60 * all included modules.
62 * <Location /server-info>
63 * SetHandler server-info
66 * GET /server-info - Returns full configuration page for server and all modules
67 * GET /server-info?server - Returns server configuration only
68 * GET /server-info?module_name - Returns configuration for a single module
69 * GET /server-info?list - Returns quick list of included modules
71 * Rasmus Lerdorf <rasmus@vex.net>, May 1996
73 * 05.01.96 Initial Version
75 * Lou Langholtz <ldl@usi.utah.edu>, July 1997
77 * 07.11.97 Addition of the AddModuleInfo directive
82 #include "http_config.h"
83 #include "http_core.h"
85 #include "http_main.h"
86 #include "http_protocol.h"
87 #include "util_script.h"
88 #include "http_conf_globals.h"
91 char *name; /* matching module name */
92 char *info; /* additional info */
96 array_header *more_info;
99 typedef struct info_cfg_lines {
102 struct info_cfg_lines *next;
105 module MODULE_VAR_EXPORT info_module;
106 extern module *top_module;
108 static void *create_info_config(pool *p, server_rec *s)
110 info_svr_conf *conf = (info_svr_conf *) ap_pcalloc(p, sizeof(info_svr_conf));
112 conf->more_info = ap_make_array(p, 20, sizeof(info_entry));
116 static void *merge_info_config(pool *p, void *basev, void *overridesv)
118 info_svr_conf *new = (info_svr_conf *) ap_pcalloc(p, sizeof(info_svr_conf));
119 info_svr_conf *base = (info_svr_conf *) basev;
120 info_svr_conf *overrides = (info_svr_conf *) overridesv;
122 new->more_info = ap_append_arrays(p, overrides->more_info, base->more_info);
126 static char *mod_info_html_cmd_string(const char *string, char *buf, size_t buf_len)
134 /* keep space for \0 byte */
135 end_buf = buf + buf_len - 1;
136 while ((*s) && (t < end_buf)) {
138 strncpy(t, "<", end_buf - t);
141 else if (*s == '>') {
142 strncpy(t, ">", end_buf - t);
145 else if (*s == '&') {
146 strncpy(t, "&", end_buf - t);
154 /* oops, overflowed... don't overwrite */
164 static info_cfg_lines *mod_info_load_config(pool *p, const char *filename,
167 char s[MAX_STRING_LEN];
169 info_cfg_lines *new, *ret, *prev;
172 fp = ap_pcfg_openfile(p, filename);
174 ap_log_rerror(APLOG_MARK, APLOG_WARNING, r,
175 "mod_info: couldn't open config file %s",
181 while (!ap_cfg_getline(s, MAX_STRING_LEN, fp)) {
183 continue; /* skip comments */
185 new = ap_palloc(p, sizeof(struct info_cfg_lines));
194 new->cmd = ap_getword_conf(p, &t);
196 new->line = ap_pstrdup(p, t);
203 ap_cfg_closefile(fp);
207 static void mod_info_module_cmds(request_rec *r, info_cfg_lines *cfg,
208 const command_rec *cmds, char *label)
210 const command_rec *cmd = cmds;
211 info_cfg_lines *li = cfg, *li_st = NULL, *li_se = NULL;
212 info_cfg_lines *block_start = NULL;
213 int lab = 0, nest = 0;
214 char buf[MAX_STRING_LEN];
217 if (!strncasecmp(li->cmd, "<directory", 10) ||
218 !strncasecmp(li->cmd, "<location", 9) ||
219 !strncasecmp(li->cmd, "<limit", 6) ||
220 !strncasecmp(li->cmd, "<files", 6)) {
231 else if (nest && (!strncasecmp(li->cmd, "</limit", 7) ||
232 !strncasecmp(li->cmd, "</location", 10) ||
233 !strncasecmp(li->cmd, "</directory", 11) ||
234 !strncasecmp(li->cmd, "</files", 7))) {
236 if ((nest == 1 && block_start == li_st) ||
237 (nest == 2 && block_start == li_se)) {
238 ap_rputs("<dd><tt>", r);
240 ap_rputs(" ", r);
242 ap_rputs(mod_info_html_cmd_string(li->cmd, buf, sizeof(buf)), r);
245 ap_rputs(mod_info_html_cmd_string(li->line, buf, sizeof(buf)), r);
247 ap_rputs("</tt>\n", r);
279 if (!strcasecmp(cmd->name, li->cmd)) {
281 ap_rputs("<dt><strong>", r);
283 ap_rputs("</strong>\n", r);
286 if (((nest && block_start == NULL) ||
287 (nest == 2 && block_start == li_st)) &&
288 (strncasecmp(li->cmd, "<directory", 10) &&
289 strncasecmp(li->cmd, "<location", 9) &&
290 strncasecmp(li->cmd, "<limit", 6) &&
291 strncasecmp(li->cmd, "</limit", 7) &&
292 strncasecmp(li->cmd, "</location", 10) &&
293 strncasecmp(li->cmd, "</directory", 11) &&
294 strncasecmp(li->cmd, "</files", 7))) {
295 ap_rputs("<dd><tt>", r);
296 ap_rputs(mod_info_html_cmd_string(li_st->cmd, buf, sizeof(buf)), r);
299 ap_rputs(mod_info_html_cmd_string(li_st->line, buf, sizeof(buf)), r);
301 ap_rputs("</tt>\n", r);
304 ap_rputs("<dd><tt> ", r);
305 ap_rputs(mod_info_html_cmd_string(li_se->cmd, buf, sizeof(buf)), r);
308 ap_rputs(mod_info_html_cmd_string(li_se->line, buf, sizeof(buf)), r);
310 ap_rputs("</tt>\n", r);
314 ap_rputs("<dd><tt>", r);
316 ap_rputs(" ", r);
319 ap_rputs(" ", r);
321 ap_rputs(mod_info_html_cmd_string(li->cmd, buf, sizeof(buf)), r);
324 ap_rputs(mod_info_html_cmd_string(li->line, buf, sizeof(buf)), r);
327 ap_rputs("</tt>", r);
338 static char *find_more_info(server_rec *s, const char *module_name)
341 info_svr_conf *conf = (info_svr_conf *) ap_get_module_config(s->module_config,
343 info_entry *entry = (info_entry *) conf->more_info->elts;
348 for (i = 0; i < conf->more_info->nelts; i++) {
349 if (!strcmp(module_name, entry->name)) {
357 static int display_info(request_rec *r)
360 char buf[MAX_STRING_LEN], *cfname;
362 const command_rec *cmd = NULL;
363 const handler_rec *hand = NULL;
364 server_rec *serv = r->server;
366 info_cfg_lines *mod_info_cfg_httpd = NULL;
367 info_cfg_lines *mod_info_cfg_srm = NULL;
368 info_cfg_lines *mod_info_cfg_access = NULL;
370 r->allowed |= (1 << M_GET);
371 if (r->method_number != M_GET)
374 r->content_type = "text/html";
375 ap_send_http_header(r);
376 if (r->header_only) {
380 ap_rputs(DOCTYPE_HTML_3_2
381 "<html><head><title>Server Information</title></head>\n", r);
382 ap_rputs("<body><h1 align=center>Apache Server Information</h1>\n", r);
383 if (!r->args || strcasecmp(r->args, "list")) {
384 cfname = ap_server_root_relative(r->pool, ap_server_confname);
385 mod_info_cfg_httpd = mod_info_load_config(r->pool, cfname, r);
386 cfname = ap_server_root_relative(r->pool, serv->srm_confname);
387 mod_info_cfg_srm = mod_info_load_config(r->pool, cfname, r);
388 cfname = ap_server_root_relative(r->pool, serv->access_confname);
389 mod_info_cfg_access = mod_info_load_config(r->pool, cfname, r);
391 ap_rputs("<tt><a href=\"#server\">Server Settings</a>, ", r);
392 for (modp = top_module; modp; modp = modp->next) {
393 ap_rprintf(r, "<a href=\"#%s\">%s</a>", modp->name, modp->name);
398 ap_rputs("</tt><hr>", r);
401 if (!r->args || !strcasecmp(r->args, "server")) {
402 ap_rprintf(r, "<a name=\"server\"><strong>Server Version:</strong> "
403 "<font size=+1><tt>%s</tt></a></font><br>\n",
404 ap_get_server_version());
405 ap_rprintf(r, "<strong>Server Built:</strong> "
406 "<font size=+1><tt>%s</tt></a></font><br>\n",
407 ap_get_server_built());
408 ap_rprintf(r, "<strong>API Version:</strong> "
409 "<tt>%d:%d</tt><br>\n",
410 MODULE_MAGIC_NUMBER_MAJOR, MODULE_MAGIC_NUMBER_MINOR);
411 ap_rprintf(r, "<strong>User/Group:</strong> "
412 "<tt>%s(%d)/%d</tt><br>\n",
413 ap_user_name, (int) ap_user_id, (int) ap_group_id);
414 ap_rprintf(r, "<strong>Hostname/port:</strong> "
415 "<tt>%s:%u</tt><br>\n",
416 serv->server_hostname, serv->port);
417 ap_rprintf(r, "<strong>Daemons:</strong> "
418 "<tt>start: %d "
419 "min idle: %d "
420 "max idle: %d "
421 "max: %d</tt><br>\n",
422 ap_daemons_to_start, ap_daemons_min_free,
423 ap_daemons_max_free, ap_daemons_limit);
424 ap_rprintf(r, "<strong>Max Requests:</strong> "
425 "<tt>per child: %d "
426 "keep alive: %s "
427 "max per connection: %d</tt><br>\n",
428 ap_max_requests_per_child,
429 (serv->keep_alive ? "on" : "off"),
430 serv->keep_alive_max);
431 ap_rprintf(r, "<strong>Threads:</strong> "
432 "<tt>per child: %d </tt><br>\n",
433 ap_threads_per_child);
434 ap_rprintf(r, "<strong>Timeouts:</strong> "
435 "<tt>connection: %d "
436 "keep-alive: %d</tt><br>",
437 serv->timeout, serv->keep_alive_timeout);
438 ap_rprintf(r, "<strong>Server Root:</strong> "
439 "<tt>%s</tt><br>\n", ap_server_root);
440 ap_rprintf(r, "<strong>Config File:</strong> "
441 "<tt>%s</tt><br>\n", ap_server_confname);
442 ap_rprintf(r, "<strong>PID File:</strong> "
443 "<tt>%s</tt><br>\n", ap_pid_fname);
444 ap_rprintf(r, "<strong>Scoreboard File:</strong> "
445 "<tt>%s</tt><br>\n", ap_scoreboard_fname);
447 ap_rputs("<hr><dl>", r);
448 for (modp = top_module; modp; modp = modp->next) {
449 if (!r->args || !strcasecmp(modp->name, r->args)) {
450 ap_rprintf(r, "<dt><a name=\"%s\"><strong>Module Name:</strong> "
451 "<font size=+1><tt>%s</tt></a></font>\n",
452 modp->name, modp->name);
453 ap_rputs("<dt><strong>Content handlers:</strong>", r);
454 hand = modp->handlers;
457 if (hand->content_type) {
458 ap_rprintf(r, " <tt>%s</tt>\n", hand->content_type);
464 if (hand && hand->content_type) {
470 ap_rputs("<tt> <EM>none</EM></tt>", r);
472 ap_rputs("<dt><strong>Configuration Phase Participation:</strong> \n",
474 if (modp->child_init) {
475 ap_rputs("<tt>Child Init</tt>", r);
478 if (modp->create_dir_config) {
482 ap_rputs("<tt>Create Directory Config</tt>", r);
485 if (modp->merge_dir_config) {
489 ap_rputs("<tt>Merge Directory Configs</tt>", r);
492 if (modp->create_server_config) {
496 ap_rputs("<tt>Create Server Config</tt>", r);
499 if (modp->merge_server_config) {
503 ap_rputs("<tt>Merge Server Configs</tt>", r);
506 if (modp->child_exit) {
510 ap_rputs("<tt>Child Exit</tt>", r);
514 ap_rputs("<tt> <EM>none</EM></tt>", r);
516 ap_rputs("<dt><strong>Request Phase Participation:</strong> \n",
518 if (modp->post_read_request) {
519 ap_rputs("<tt>Post-Read Request</tt>", r);
522 if (modp->header_parser) {
526 ap_rputs("<tt>Header Parse</tt>", r);
529 if (modp->translate_handler) {
533 ap_rputs("<tt>Translate Path</tt>", r);
536 if (modp->access_checker) {
540 ap_rputs("<tt>Check Access</tt>", r);
543 if (modp->ap_check_user_id) {
547 ap_rputs("<tt>Verify User ID</tt>", r);
550 if (modp->auth_checker) {
554 ap_rputs("<tt>Verify User Access</tt>", r);
557 if (modp->type_checker) {
561 ap_rputs("<tt>Check Type</tt>", r);
564 if (modp->fixer_upper) {
568 ap_rputs("<tt>Fixups</tt>", r);
575 ap_rputs("<tt>Logging</tt>", r);
579 ap_rputs("<tt> <EM>none</EM></tt>", r);
581 ap_rputs("<dt><strong>Module Directives:</strong> ", r);
586 ap_rprintf(r, "<dd><tt>%s - <i>",
587 mod_info_html_cmd_string(cmd->name,
590 ap_rputs(cmd->errmsg, r);
592 ap_rputs("</i></tt>\n", r);
599 ap_rputs("<dt><strong>Current Configuration:</strong>\n", r);
600 mod_info_module_cmds(r, mod_info_cfg_httpd, modp->cmds,
602 mod_info_module_cmds(r, mod_info_cfg_srm, modp->cmds,
604 mod_info_module_cmds(r, mod_info_cfg_access, modp->cmds,
608 ap_rputs("<tt> none</tt>\n", r);
610 more_info = find_more_info(serv, modp->name);
612 ap_rputs("<dt><strong>Additional Information:</strong>\n<dd>",
614 ap_rputs(more_info, r);
616 ap_rputs("<dt><hr>\n", r);
622 if (!modp && r->args && strcasecmp(r->args, "server")) {
623 ap_rputs("<b>No such module</b>\n", r);
627 for (modp = top_module; modp; modp = modp->next) {
628 ap_rputs(modp->name, r);
634 ap_rputs("</dl>\n", r);
635 ap_rputs(ap_psignature("",r), r);
636 ap_rputs("</body></html>\n", r);
637 /* Done, turn off timeout, close file and return */
641 static const char *add_module_info(cmd_parms *cmd, void *dummy, char *name,
644 server_rec *s = cmd->server;
645 info_svr_conf *conf = (info_svr_conf *) ap_get_module_config(s->module_config,
647 info_entry *new = ap_push_array(conf->more_info);
654 static const command_rec info_cmds[] =
656 {"AddModuleInfo", add_module_info, NULL, RSRC_CONF, TAKE2,
657 "a module name and additional information on that module"},
661 static const handler_rec info_handlers[] =
663 {"server-info", display_info},
667 module MODULE_VAR_EXPORT info_module =
669 STANDARD_MODULE_STUFF,
670 NULL, /* initializer */
671 NULL, /* dir config creater */
672 NULL, /* dir merger --- default is to override */
673 create_info_config, /* server config */
674 merge_info_config, /* merge server config */
675 info_cmds, /* command table */
676 info_handlers, /* handlers */
677 NULL, /* filename translation */
678 NULL, /* check_user_id */
679 NULL, /* check auth */
680 NULL, /* check access */
681 NULL, /* type_checker */
684 NULL, /* header parser */
685 NULL, /* child_init */
686 NULL, /* child_exit */
687 NULL /* post read-request */