mod_info.c.cve3499 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. /* Licensed to the Apache Software Foundation (ASF) under one or more
  2. * contributor license agreements. See the NOTICE file distributed with
  3. * this work for additional information regarding copyright ownership.
  4. * The ASF licenses this file to You under the Apache License, Version 2.0
  5. * (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * Info Module. Display configuration information for the server and
  18. * all included modules.
  19. *
  20. * <Location /server-info>
  21. * SetHandler server-info
  22. * </Location>
  23. *
  24. * GET /server-info - Returns full configuration page for server and all modules
  25. * GET /server-info?server - Returns server configuration only
  26. * GET /server-info?module_name - Returns configuration for a single module
  27. * GET /server-info?list - Returns quick list of included modules
  28. * GET /server-info?config - Returns full configuration
  29. * GET /server-info?hooks - Returns a listing of the modules active for each hook
  30. *
  31. * Original Author:
  32. * Rasmus Lerdorf <rasmus vex.net>, May 1996
  33. *
  34. * Modified By:
  35. * Lou Langholtz <ldl usi.utah.edu>, July 1997
  36. *
  37. * Apache 2.0 Port:
  38. * Ryan Morgan <rmorgan covalent.net>, August 2000
  39. *
  40. */
  41. #include "apr.h"
  42. #include "apr_strings.h"
  43. #include "apr_lib.h"
  44. #include "apr_version.h"
  45. #include "apu_version.h"
  46. #define APR_WANT_STRFUNC
  47. #include "apr_want.h"
  48. #define CORE_PRIVATE
  49. #include "httpd.h"
  50. #include "http_config.h"
  51. #include "http_core.h"
  52. #include "http_log.h"
  53. #include "http_main.h"
  54. #include "http_protocol.h"
  55. #include "http_connection.h"
  56. #include "http_request.h"
  57. #include "util_script.h"
  58. #include "ap_mpm.h"
  59. typedef struct
  60. {
  61. const char *name; /* matching module name */
  62. const char *info; /* additional info */
  63. } info_entry;
  64. typedef struct
  65. {
  66. apr_array_header_t *more_info;
  67. } info_svr_conf;
  68. module AP_MODULE_DECLARE_DATA info_module;
  69. static void *create_info_config(apr_pool_t * p, server_rec * s)
  70. {
  71. info_svr_conf *conf =
  72. (info_svr_conf *) apr_pcalloc(p, sizeof(info_svr_conf));
  73. conf->more_info = apr_array_make(p, 20, sizeof(info_entry));
  74. return conf;
  75. }
  76. static void *merge_info_config(apr_pool_t * p, void *basev, void *overridesv)
  77. {
  78. info_svr_conf *new =
  79. (info_svr_conf *) apr_pcalloc(p, sizeof(info_svr_conf));
  80. info_svr_conf *base = (info_svr_conf *) basev;
  81. info_svr_conf *overrides = (info_svr_conf *) overridesv;
  82. new->more_info =
  83. apr_array_append(p, overrides->more_info, base->more_info);
  84. return new;
  85. }
  86. static void put_int_flush_right(request_rec * r, int i, int field)
  87. {
  88. if (field > 1 || i > 9)
  89. put_int_flush_right(r, i / 10, field - 1);
  90. if (i)
  91. ap_rputc('0' + i % 10, r);
  92. else
  93. ap_rputs("&nbsp;", r);
  94. }
  95. static void mod_info_indent(request_rec * r, int nest,
  96. const char *thisfn, int linenum)
  97. {
  98. int i;
  99. const char *prevfn =
  100. ap_get_module_config(r->request_config, &info_module);
  101. if (thisfn == NULL)
  102. thisfn = "*UNKNOWN*";
  103. if (prevfn == NULL || 0 != strcmp(prevfn, thisfn)) {
  104. thisfn = ap_escape_html(r->pool, thisfn);
  105. ap_rprintf(r, "<dd><tt><strong>In file: %s</strong></tt></dd>\n",
  106. thisfn);
  107. ap_set_module_config(r->request_config, &info_module,
  108. (void *) thisfn);
  109. }
  110. ap_rputs("<dd><tt>", r);
  111. put_int_flush_right(r, linenum > 0 ? linenum : 0, 4);
  112. ap_rputs(":&nbsp;", r);
  113. for (i = 1; i <= nest; ++i) {
  114. ap_rputs("&nbsp;&nbsp;", r);
  115. }
  116. }
  117. static void mod_info_show_cmd(request_rec * r, const ap_directive_t * dir,
  118. int nest)
  119. {
  120. mod_info_indent(r, nest, dir->filename, dir->line_num);
  121. ap_rprintf(r, "%s <i>%s</i></tt></dd>\n",
  122. ap_escape_html(r->pool, dir->directive),
  123. ap_escape_html(r->pool, dir->args));
  124. }
  125. static void mod_info_show_open(request_rec * r, const ap_directive_t * dir,
  126. int nest)
  127. {
  128. mod_info_indent(r, nest, dir->filename, dir->line_num);
  129. ap_rprintf(r, "%s %s</tt></dd>\n",
  130. ap_escape_html(r->pool, dir->directive),
  131. ap_escape_html(r->pool, dir->args));
  132. }
  133. static void mod_info_show_close(request_rec * r, const ap_directive_t * dir,
  134. int nest)
  135. {
  136. const char *dirname = dir->directive;
  137. mod_info_indent(r, nest, dir->filename, 0);
  138. if (*dirname == '<') {
  139. ap_rprintf(r, "&lt;/%s&gt;</tt></dd>",
  140. ap_escape_html(r->pool, dirname + 1));
  141. }
  142. else {
  143. ap_rprintf(r, "/%s</tt></dd>", ap_escape_html(r->pool, dirname));
  144. }
  145. }
  146. static int mod_info_has_cmd(const command_rec * cmds, ap_directive_t * dir)
  147. {
  148. const command_rec *cmd;
  149. if (cmds == NULL)
  150. return 1;
  151. for (cmd = cmds; cmd->name; ++cmd) {
  152. if (strcasecmp(cmd->name, dir->directive) == 0)
  153. return 1;
  154. }
  155. return 0;
  156. }
  157. static void mod_info_show_parents(request_rec * r, ap_directive_t * node,
  158. int from, int to)
  159. {
  160. if (from < to)
  161. mod_info_show_parents(r, node->parent, from, to - 1);
  162. mod_info_show_open(r, node, to);
  163. }
  164. static int mod_info_module_cmds(request_rec * r, const command_rec * cmds,
  165. ap_directive_t * node, int from, int level)
  166. {
  167. int shown = from;
  168. ap_directive_t *dir;
  169. if (level == 0)
  170. ap_set_module_config(r->request_config, &info_module, NULL);
  171. for (dir = node; dir; dir = dir->next) {
  172. if (dir->first_child != NULL) {
  173. if (level < mod_info_module_cmds(r, cmds, dir->first_child,
  174. shown, level + 1)) {
  175. shown = level;
  176. mod_info_show_close(r, dir, level);
  177. }
  178. }
  179. else if (mod_info_has_cmd(cmds, dir)) {
  180. if (shown < level) {
  181. mod_info_show_parents(r, dir->parent, shown, level - 1);
  182. shown = level;
  183. }
  184. mod_info_show_cmd(r, dir, level);
  185. }
  186. }
  187. return shown;
  188. }
  189. typedef struct
  190. { /*XXX: should get something from apr_hooks.h instead */
  191. void (*pFunc) (void); /* just to get the right size */
  192. const char *szName;
  193. const char *const *aszPredecessors;
  194. const char *const *aszSuccessors;
  195. int nOrder;
  196. } hook_struct_t;
  197. /*
  198. * hook_get_t is a pointer to a function that takes void as an argument and
  199. * returns a pointer to an apr_array_header_t. The nasty WIN32 ifdef
  200. * is required to account for the fact that the ap_hook* calls all use
  201. * STDCALL calling convention.
  202. */
  203. typedef apr_array_header_t *(
  204. #ifdef WIN32
  205. __stdcall
  206. #endif
  207. * hook_get_t) (void);
  208. typedef struct
  209. {
  210. const char *name;
  211. hook_get_t get;
  212. } hook_lookup_t;
  213. static hook_lookup_t startup_hooks[] = {
  214. {"Pre-Config", ap_hook_get_pre_config},
  215. {"Test Configuration", ap_hook_get_test_config},
  216. {"Post Configuration", ap_hook_get_post_config},
  217. {"Open Logs", ap_hook_get_open_logs},
  218. {"Child Init", ap_hook_get_child_init},
  219. {NULL},
  220. };
  221. static hook_lookup_t request_hooks[] = {
  222. {"Pre-Connection", ap_hook_get_pre_connection},
  223. {"Create Connection", ap_hook_get_create_connection},
  224. {"Process Connection", ap_hook_get_process_connection},
  225. {"Create Request", ap_hook_get_create_request},
  226. {"Post-Read Request", ap_hook_get_post_read_request},
  227. {"Header Parse", ap_hook_get_header_parser},
  228. {"HTTP Scheme", ap_hook_get_http_scheme},
  229. {"Default Port", ap_hook_get_default_port},
  230. {"Quick Handler", ap_hook_get_quick_handler},
  231. {"Translate Name", ap_hook_get_translate_name},
  232. {"Map to Storage", ap_hook_get_map_to_storage},
  233. {"Check Access", ap_hook_get_access_checker},
  234. {"Verify User ID", ap_hook_get_check_user_id},
  235. {"Verify User Access", ap_hook_get_auth_checker},
  236. {"Check Type", ap_hook_get_type_checker},
  237. {"Fixups", ap_hook_get_fixups},
  238. {"Insert Filters", ap_hook_get_insert_filter},
  239. {"Content Handlers", ap_hook_get_handler},
  240. {"Logging", ap_hook_get_log_transaction},
  241. {"Insert Errors", ap_hook_get_insert_error_filter},
  242. {NULL},
  243. };
  244. static int module_find_hook(module * modp, hook_get_t hook_get)
  245. {
  246. int i;
  247. apr_array_header_t *hooks = hook_get();
  248. hook_struct_t *elts;
  249. if (!hooks) {
  250. return 0;
  251. }
  252. elts = (hook_struct_t *) hooks->elts;
  253. for (i = 0; i < hooks->nelts; i++) {
  254. if (strcmp(elts[i].szName, modp->name) == 0) {
  255. return 1;
  256. }
  257. }
  258. return 0;
  259. }
  260. static void module_participate(request_rec * r,
  261. module * modp,
  262. hook_lookup_t * lookup, int *comma)
  263. {
  264. if (module_find_hook(modp, lookup->get)) {
  265. if (*comma) {
  266. ap_rputs(", ", r);
  267. }
  268. ap_rvputs(r, "<tt>", lookup->name, "</tt>", NULL);
  269. *comma = 1;
  270. }
  271. }
  272. static void module_request_hook_participate(request_rec * r, module * modp)
  273. {
  274. int i, comma = 0;
  275. ap_rputs("<dt><strong>Request Phase Participation:</strong>\n", r);
  276. for (i = 0; request_hooks[i].name; i++) {
  277. module_participate(r, modp, &request_hooks[i], &comma);
  278. }
  279. if (!comma) {
  280. ap_rputs("<tt> <em>none</em></tt>", r);
  281. }
  282. ap_rputs("</dt>\n", r);
  283. }
  284. static const char *find_more_info(server_rec * s, const char *module_name)
  285. {
  286. int i;
  287. info_svr_conf *conf =
  288. (info_svr_conf *) ap_get_module_config(s->module_config,
  289. &info_module);
  290. info_entry *entry = (info_entry *) conf->more_info->elts;
  291. if (!module_name) {
  292. return 0;
  293. }
  294. for (i = 0; i < conf->more_info->nelts; i++) {
  295. if (!strcmp(module_name, entry->name)) {
  296. return entry->info;
  297. }
  298. entry++;
  299. }
  300. return 0;
  301. }
  302. static int show_server_settings(request_rec * r)
  303. {
  304. server_rec *serv = r->server;
  305. int max_daemons, forked, threaded;
  306. ap_rputs("<h2><a name=\"server\">Server Settings</a></h2>", r);
  307. ap_rprintf(r,
  308. "<dl><dt><strong>Server Version:</strong> "
  309. "<font size=\"+1\"><tt>%s</tt></font></dt>\n",
  310. ap_get_server_description());
  311. ap_rprintf(r,
  312. "<dt><strong>Server Built:</strong> "
  313. "<font size=\"+1\"><tt>%s</tt></font></dt>\n",
  314. ap_get_server_built());
  315. ap_rprintf(r,
  316. "<dt><strong>Server loaded APR Version:</strong> "
  317. "<tt>%s</tt></dt>\n", apr_version_string());
  318. ap_rprintf(r,
  319. "<dt><strong>Compiled with APR Version:</strong> "
  320. "<tt>%s</tt></dt>\n", APR_VERSION_STRING);
  321. ap_rprintf(r,
  322. "<dt><strong>Server loaded APU Version:</strong> "
  323. "<tt>%s</tt></dt>\n", apu_version_string());
  324. ap_rprintf(r,
  325. "<dt><strong>Compiled with APU Version:</strong> "
  326. "<tt>%s</tt></dt>\n", APU_VERSION_STRING);
  327. ap_rprintf(r,
  328. "<dt><strong>Module Magic Number:</strong> "
  329. "<tt>%d:%d</tt></dt>\n", MODULE_MAGIC_NUMBER_MAJOR,
  330. MODULE_MAGIC_NUMBER_MINOR);
  331. ap_rprintf(r,
  332. "<dt><strong>Hostname/port:</strong> "
  333. "<tt>%s:%u</tt></dt>\n", ap_get_server_name(r),
  334. ap_get_server_port(r));
  335. ap_rprintf(r,
  336. "<dt><strong>Timeouts:</strong> "
  337. "<tt>connection: %d &nbsp;&nbsp; "
  338. "keep-alive: %d</tt></dt>",
  339. (int) (apr_time_sec(serv->timeout)),
  340. (int) (apr_time_sec(serv->keep_alive_timeout)));
  341. ap_mpm_query(AP_MPMQ_MAX_DAEMON_USED, &max_daemons);
  342. ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded);
  343. ap_mpm_query(AP_MPMQ_IS_FORKED, &forked);
  344. ap_rprintf(r, "<dt><strong>MPM Name:</strong> <tt>%s</tt></dt>\n",
  345. ap_show_mpm());
  346. ap_rprintf(r,
  347. "<dt><strong>MPM Information:</strong> "
  348. "<tt>Max Daemons: %d Threaded: %s Forked: %s</tt></dt>\n",
  349. max_daemons, threaded ? "yes" : "no", forked ? "yes" : "no");
  350. ap_rprintf(r,
  351. "<dt><strong>Server Architecture:</strong> "
  352. "<tt>%ld-bit</tt></dt>\n", 8 * (long) sizeof(void *));
  353. ap_rprintf(r,
  354. "<dt><strong>Server Root:</strong> "
  355. "<tt>%s</tt></dt>\n", ap_server_root);
  356. ap_rprintf(r,
  357. "<dt><strong>Config File:</strong> "
  358. "<tt>%s</tt></dt>\n", ap_conftree->filename);
  359. ap_rputs("<dt><strong>Server Built With:</strong>\n"
  360. "<tt style=\"white-space: pre;\">\n", r);
  361. /* TODO: Not all of these defines are getting set like they do in main.c.
  362. * Missing some headers?
  363. */
  364. #ifdef BIG_SECURITY_HOLE
  365. ap_rputs(" -D BIG_SECURITY_HOLE\n", r);
  366. #endif
  367. #ifdef SECURITY_HOLE_PASS_AUTHORIZATION
  368. ap_rputs(" -D SECURITY_HOLE_PASS_AUTHORIZATION\n", r);
  369. #endif
  370. #ifdef OS
  371. ap_rputs(" -D OS=\"" OS "\"\n", r);
  372. #endif
  373. #ifdef APACHE_MPM_DIR
  374. ap_rputs(" -D APACHE_MPM_DIR=\"" APACHE_MPM_DIR "\"\n", r);
  375. #endif
  376. #ifdef HAVE_SHMGET
  377. ap_rputs(" -D HAVE_SHMGET\n", r);
  378. #endif
  379. #if APR_FILE_BASED_SHM
  380. ap_rputs(" -D APR_FILE_BASED_SHM\n", r);
  381. #endif
  382. #if APR_HAS_SENDFILE
  383. ap_rputs(" -D APR_HAS_SENDFILE\n", r);
  384. #endif
  385. #if APR_HAS_MMAP
  386. ap_rputs(" -D APR_HAS_MMAP\n", r);
  387. #endif
  388. #ifdef NO_WRITEV
  389. ap_rputs(" -D NO_WRITEV\n", r);
  390. #endif
  391. #ifdef NO_LINGCLOSE
  392. ap_rputs(" -D NO_LINGCLOSE\n", r);
  393. #endif
  394. #if APR_HAVE_IPV6
  395. ap_rputs(" -D APR_HAVE_IPV6 (IPv4-mapped addresses ", r);
  396. #ifdef AP_ENABLE_V4_MAPPED
  397. ap_rputs("enabled)\n", r);
  398. #else
  399. ap_rputs("disabled)\n", r);
  400. #endif
  401. #endif
  402. #if APR_USE_FLOCK_SERIALIZE
  403. ap_rputs(" -D APR_USE_FLOCK_SERIALIZE\n", r);
  404. #endif
  405. #if APR_USE_SYSVSEM_SERIALIZE
  406. ap_rputs(" -D APR_USE_SYSVSEM_SERIALIZE\n", r);
  407. #endif
  408. #if APR_USE_POSIXSEM_SERIALIZE
  409. ap_rputs(" -D APR_USE_POSIXSEM_SERIALIZE\n", r);
  410. #endif
  411. #if APR_USE_FCNTL_SERIALIZE
  412. ap_rputs(" -D APR_USE_FCNTL_SERIALIZE\n", r);
  413. #endif
  414. #if APR_USE_PROC_PTHREAD_SERIALIZE
  415. ap_rputs(" -D APR_USE_PROC_PTHREAD_SERIALIZE\n", r);
  416. #endif
  417. #if APR_PROCESS_LOCK_IS_GLOBAL
  418. ap_rputs(" -D APR_PROCESS_LOCK_IS_GLOBAL\n", r);
  419. #endif
  420. #ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
  421. ap_rputs(" -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT\n", r);
  422. #endif
  423. #if APR_HAS_OTHER_CHILD
  424. ap_rputs(" -D APR_HAS_OTHER_CHILD\n", r);
  425. #endif
  426. #ifdef AP_HAVE_RELIABLE_PIPED_LOGS
  427. ap_rputs(" -D AP_HAVE_RELIABLE_PIPED_LOGS\n", r);
  428. #endif
  429. #ifdef BUFFERED_LOGS
  430. ap_rputs(" -D BUFFERED_LOGS\n", r);
  431. #ifdef PIPE_BUF
  432. ap_rputs(" -D PIPE_BUF=%ld\n", (long) PIPE_BUF, r);
  433. #endif
  434. #endif
  435. #if APR_CHARSET_EBCDIC
  436. ap_rputs(" -D APR_CHARSET_EBCDIC\n", r);
  437. #endif
  438. #ifdef NEED_HASHBANG_EMUL
  439. ap_rputs(" -D NEED_HASHBANG_EMUL\n", r);
  440. #endif
  441. #ifdef SHARED_CORE
  442. ap_rputs(" -D SHARED_CORE\n", r);
  443. #endif
  444. /* This list displays the compiled in default paths: */
  445. #ifdef HTTPD_ROOT
  446. ap_rputs(" -D HTTPD_ROOT=\"" HTTPD_ROOT "\"\n", r);
  447. #endif
  448. #ifdef SUEXEC_BIN
  449. ap_rputs(" -D SUEXEC_BIN=\"" SUEXEC_BIN "\"\n", r);
  450. #endif
  451. #if defined(SHARED_CORE) && defined(SHARED_CORE_DIR)
  452. ap_rputs(" -D SHARED_CORE_DIR=\"" SHARED_CORE_DIR "\"\n", r);
  453. #endif
  454. #ifdef DEFAULT_PIDLOG
  455. ap_rputs(" -D DEFAULT_PIDLOG=\"" DEFAULT_PIDLOG "\"\n", r);
  456. #endif
  457. #ifdef DEFAULT_SCOREBOARD
  458. ap_rputs(" -D DEFAULT_SCOREBOARD=\"" DEFAULT_SCOREBOARD "\"\n", r);
  459. #endif
  460. #ifdef DEFAULT_LOCKFILE
  461. ap_rputs(" -D DEFAULT_LOCKFILE=\"" DEFAULT_LOCKFILE "\"\n", r);
  462. #endif
  463. #ifdef DEFAULT_ERRORLOG
  464. ap_rputs(" -D DEFAULT_ERRORLOG=\"" DEFAULT_ERRORLOG "\"\n", r);
  465. #endif
  466. #ifdef AP_TYPES_CONFIG_FILE
  467. ap_rputs(" -D AP_TYPES_CONFIG_FILE=\"" AP_TYPES_CONFIG_FILE "\"\n", r);
  468. #endif
  469. #ifdef SERVER_CONFIG_FILE
  470. ap_rputs(" -D SERVER_CONFIG_FILE=\"" SERVER_CONFIG_FILE "\"\n", r);
  471. #endif
  472. ap_rputs("</tt></dt>\n", r);
  473. ap_rputs("</dl><hr />", r);
  474. return 0;
  475. }
  476. static int dump_a_hook(request_rec * r, hook_get_t hook_get)
  477. {
  478. int i;
  479. char qs;
  480. hook_struct_t *elts;
  481. apr_array_header_t *hooks = hook_get();
  482. if (!hooks) {
  483. return 0;
  484. }
  485. if (r->args && strcasecmp(r->args, "hooks") == 0) {
  486. qs = '?';
  487. }
  488. else {
  489. qs = '#';
  490. }
  491. elts = (hook_struct_t *) hooks->elts;
  492. for (i = 0; i < hooks->nelts; i++) {
  493. ap_rprintf(r,
  494. "&nbsp;&nbsp; %02d <a href=\"%c%s\">%s</a> <br/>",
  495. elts[i].nOrder, qs, elts[i].szName, elts[i].szName);
  496. }
  497. return 0;
  498. }
  499. static int show_active_hooks(request_rec * r)
  500. {
  501. int i;
  502. ap_rputs("<h2><a name=\"startup_hooks\">Startup Hooks</a></h2>\n<dl>", r);
  503. for (i = 0; startup_hooks[i].name; i++) {
  504. ap_rprintf(r, "<dt><strong>%s:</strong>\n <br /><tt>\n",
  505. startup_hooks[i].name);
  506. dump_a_hook(r, startup_hooks[i].get);
  507. ap_rputs("\n </tt>\n</dt>\n", r);
  508. }
  509. ap_rputs
  510. ("</dl>\n<hr />\n<h2><a name=\"request_hooks\">Request Hooks</a></h2>\n<dl>",
  511. r);
  512. for (i = 0; request_hooks[i].name; i++) {
  513. ap_rprintf(r, "<dt><strong>%s:</strong>\n <br /><tt>\n",
  514. request_hooks[i].name);
  515. dump_a_hook(r, request_hooks[i].get);
  516. ap_rputs("\n </tt>\n</dt>\n", r);
  517. }
  518. ap_rputs("</dl>\n<hr />\n", r);
  519. return 0;
  520. }
  521. static int display_info(request_rec * r)
  522. {
  523. module *modp = NULL;
  524. server_rec *serv = r->server;
  525. const char *more_info;
  526. const command_rec *cmd = NULL;
  527. int comma = 0;
  528. if (strcmp(r->handler, "server-info"))
  529. return DECLINED;
  530. r->allowed |= (AP_METHOD_BIT << M_GET);
  531. if (r->method_number != M_GET)
  532. return DECLINED;
  533. ap_set_content_type(r, "text/html; charset=ISO-8859-1");
  534. ap_rputs(DOCTYPE_XHTML_1_0T
  535. "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
  536. "<head>\n"
  537. " <title>Server Information</title>\n" "</head>\n", r);
  538. ap_rputs("<body><h1 style=\"text-align: center\">"
  539. "Apache Server Information</h1>\n", r);
  540. if (!r->args || strcasecmp(r->args, "list")) {
  541. if (!r->args) {
  542. ap_rputs("<dl><dt><tt>Subpages:<br />", r);
  543. ap_rputs("<a href=\"?config\">Configuration Files</a>, "
  544. "<a href=\"?server\">Server Settings</a>, "
  545. "<a href=\"?list\">Module List</a>, "
  546. "<a href=\"?hooks\">Active Hooks</a>", r);
  547. ap_rputs("</tt></dt></dl><hr />", r);
  548. ap_rputs("<dl><dt><tt>Sections:<br />", r);
  549. ap_rputs("<a href=\"#server\">Server Settings</a>, "
  550. "<a href=\"#startup_hooks\">Startup Hooks</a>, "
  551. "<a href=\"#request_hooks\">Request Hooks</a>", r);
  552. ap_rputs("</tt></dt></dl><hr />", r);
  553. ap_rputs("<dl><dt><tt>Loaded Modules: <br />", r);
  554. /* TODO: Sort by Alpha */
  555. for (modp = ap_top_module; modp; modp = modp->next) {
  556. ap_rprintf(r, "<a href=\"#%s\">%s</a>", modp->name,
  557. modp->name);
  558. if (modp->next) {
  559. ap_rputs(", ", r);
  560. }
  561. }
  562. ap_rputs("</tt></dt></dl><hr />", r);
  563. }
  564. if (!r->args || !strcasecmp(r->args, "server")) {
  565. show_server_settings(r);
  566. }
  567. if (!r->args || !strcasecmp(r->args, "hooks")) {
  568. show_active_hooks(r);
  569. }
  570. if (r->args && 0 == strcasecmp(r->args, "config")) {
  571. ap_rputs("<dl><dt><strong>Configuration:</strong>\n", r);
  572. mod_info_module_cmds(r, NULL, ap_conftree, 0, 0);
  573. ap_rputs("</dl><hr />", r);
  574. }
  575. else {
  576. for (modp = ap_top_module; modp; modp = modp->next) {
  577. if (!r->args || !strcasecmp(modp->name, r->args)) {
  578. ap_rprintf(r,
  579. "<dl><dt><a name=\"%s\"><strong>Module Name:</strong></a> "
  580. "<font size=\"+1\"><tt><a href=\"?%s\">%s</a></tt></font></dt>\n",
  581. modp->name, modp->name, modp->name);
  582. ap_rputs("<dt><strong>Content handlers:</strong> ", r);
  583. if (module_find_hook(modp, ap_hook_get_handler)) {
  584. ap_rputs("<tt> <em>yes</em></tt>", r);
  585. }
  586. else {
  587. ap_rputs("<tt> <em>none</em></tt>", r);
  588. }
  589. ap_rputs("</dt>", r);
  590. ap_rputs
  591. ("<dt><strong>Configuration Phase Participation:</strong>\n",
  592. r);
  593. if (modp->create_dir_config) {
  594. if (comma) {
  595. ap_rputs(", ", r);
  596. }
  597. ap_rputs("<tt>Create Directory Config</tt>", r);
  598. comma = 1;
  599. }
  600. if (modp->merge_dir_config) {
  601. if (comma) {
  602. ap_rputs(", ", r);
  603. }
  604. ap_rputs("<tt>Merge Directory Configs</tt>", r);
  605. comma = 1;
  606. }
  607. if (modp->create_server_config) {
  608. if (comma) {
  609. ap_rputs(", ", r);
  610. }
  611. ap_rputs("<tt>Create Server Config</tt>", r);
  612. comma = 1;
  613. }
  614. if (modp->merge_server_config) {
  615. if (comma) {
  616. ap_rputs(", ", r);
  617. }
  618. ap_rputs("<tt>Merge Server Configs</tt>", r);
  619. comma = 1;
  620. }
  621. if (!comma)
  622. ap_rputs("<tt> <em>none</em></tt>", r);
  623. comma = 0;
  624. ap_rputs("</dt>", r);
  625. module_request_hook_participate(r, modp);
  626. cmd = modp->cmds;
  627. if (cmd) {
  628. ap_rputs
  629. ("<dt><strong>Module Directives:</strong></dt>",
  630. r);
  631. while (cmd) {
  632. if (cmd->name) {
  633. ap_rprintf(r, "<dd><tt>%s%s - <i>",
  634. ap_escape_html(r->pool, cmd->name),
  635. cmd->name[0] == '<' ? "&gt;" : "");
  636. if (cmd->errmsg) {
  637. ap_rputs(ap_escape_html(r->pool, cmd->errmsg), r);
  638. }
  639. ap_rputs("</i></tt></dd>\n", r);
  640. }
  641. else {
  642. break;
  643. }
  644. cmd++;
  645. }
  646. ap_rputs
  647. ("<dt><strong>Current Configuration:</strong></dt>\n",
  648. r);
  649. mod_info_module_cmds(r, modp->cmds, ap_conftree, 0,
  650. 0);
  651. }
  652. else {
  653. ap_rputs
  654. ("<dt><strong>Module Directives:</strong> <tt>none</tt></dt>",
  655. r);
  656. }
  657. more_info = find_more_info(serv, modp->name);
  658. if (more_info) {
  659. ap_rputs
  660. ("<dt><strong>Additional Information:</strong>\n</dt><dd>",
  661. r);
  662. ap_rputs(more_info, r);
  663. ap_rputs("</dd>", r);
  664. }
  665. ap_rputs("</dl><hr />\n", r);
  666. if (r->args) {
  667. break;
  668. }
  669. }
  670. }
  671. if (!modp && r->args && strcasecmp(r->args, "server")) {
  672. ap_rputs("<p><b>No such module</b></p>\n", r);
  673. }
  674. }
  675. }
  676. else {
  677. ap_rputs("<dl><dt>Server Module List</dt>", r);
  678. for (modp = ap_top_module; modp; modp = modp->next) {
  679. ap_rputs("<dd>", r);
  680. ap_rputs(modp->name, r);
  681. ap_rputs("</dd>", r);
  682. }
  683. ap_rputs("</dl><hr />", r);
  684. }
  685. ap_rputs(ap_psignature("", r), r);
  686. ap_rputs("</body></html>\n", r);
  687. /* Done, turn off timeout, close file and return */
  688. return 0;
  689. }
  690. static const char *add_module_info(cmd_parms * cmd, void *dummy,
  691. const char *name, const char *info)
  692. {
  693. server_rec *s = cmd->server;
  694. info_svr_conf *conf =
  695. (info_svr_conf *) ap_get_module_config(s->module_config,
  696. &info_module);
  697. info_entry *new = apr_array_push(conf->more_info);
  698. new->name = name;
  699. new->info = info;
  700. return NULL;
  701. }
  702. static const command_rec info_cmds[] = {
  703. AP_INIT_TAKE2("AddModuleInfo", add_module_info, NULL, RSRC_CONF,
  704. "a module name and additional information on that module"),
  705. {NULL}
  706. };
  707. static void register_hooks(apr_pool_t * p)
  708. {
  709. ap_hook_handler(display_info, NULL, NULL, APR_HOOK_MIDDLE);
  710. }
  711. module AP_MODULE_DECLARE_DATA info_module = {
  712. STANDARD20_MODULE_STUFF,
  713. NULL, /* dir config creater */
  714. NULL, /* dir merger --- default is to override */
  715. create_info_config, /* server config */
  716. merge_info_config, /* merge server config */
  717. info_cmds, /* command apr_table_t */
  718. register_hooks
  719. };