mod_autoindex StUdLyInDeXiNg
At some point Netgod forked mod_autoindex from upstream and added the
StudlyIndex option. That was fine until upstream added some features
and fixed some bugs. The plan is to turn the mod_autoindex in contrib
into a patch to the mod_autoindex distributed with apache.
Here is that patch. Comments welcomed (it's 17k, I must have missed
*something*).
--- build-tree-apache/apache_1.3.29/src/modules/standard/mod_autoindex.c 2003-12-09 14:47:37.000000000 -0500
+++ build-tree-apache/apache-contrib-1.0.8a/mod_autoindex/mod_autoindex.c 2004-02-19 13:16:31.000000000 -0500
@@ -63,6 +63,7 @@
* 3/23/93
*
* Adapted to Apache by rst.
+ * StudlyIndexing by Johnie Ingram <johnie@netgod.net>
*/
#include "httpd.h"
@@ -99,6 +100,7 @@ module MODULE_VAR_EXPORT autoindex_modul
#define FOLDERS_FIRST 512
#define TRACK_MODIFIED 1024
#define SORT_NOCASE 2048
+#define STUDLY_INDEXING 4096
#define K_PAD 1
#define K_NOPAD 0
@@ -163,6 +165,17 @@ typedef struct autoindex_config_struct {
array_header *ign_list;
array_header *hdr_list;
array_header *rdme_list;
+ array_header *side_list;
+ array_header *main_list;
+ array_header *ftr_list;
+
+ char *body_col;
+ char *text_col;
+ char *hdr_col;
+ char *rdme_col;
+ char *side_col;
+ char *main_col;
+ char *ftr_col;
} autoindex_config_rec;
@@ -196,11 +209,19 @@ static ap_inline int is_parent(const cha
* We include the DOCTYPE because we may be using features therefrom (i.e.,
* HEIGHT and WIDTH attributes on the icons if we're FancyIndexing).
*/
-static void emit_preamble(request_rec *r, char *title)
+static void emit_preamble(request_rec *r, char *title,
+ autoindex_config_rec *autoindex_conf)
{
- ap_rvputs(r, DOCTYPE_HTML_3_2,
+ ap_rvputs(r, DOCTYPE_HTML_4_0T,
"<HTML>\n <HEAD>\n <TITLE>Index of ", title,
- "</TITLE>\n </HEAD>\n <BODY>\n", NULL);
+ "</TITLE>\n </HEAD>\n <BODY bgcolor=\"",
+ autoindex_conf->body_col ?: "#ffffff", "\" text=\"",
+ autoindex_conf->text_col ?: "#000000", "\"", NULL);
+ if (autoindex_conf->opts & STUDLY_INDEXING) {
+ ap_rvputs(r, " leftmargin=\"0\" topmargin=\"0\" \n "
+ "marginwidth=\"0\" marginheight=\"0\"", NULL);
+ }
+ ap_rputs(">\n\n", r);
}
static void push_item(array_header *arr, char *type, char *to, char *path,
@@ -340,6 +361,27 @@ static const char *add_readme(cmd_parms
return NULL;
}
+static const char *add_sidebar(cmd_parms *cmd, void *d, char *name)
+{
+ push_item(((autoindex_config_rec *) d)->side_list, 0, NULL, cmd->path,
+ name);
+ return NULL;
+}
+
+static const char *add_body(cmd_parms *cmd, void *d, char *name)
+{
+ push_item(((autoindex_config_rec *) d)->main_list, 0, NULL, cmd->path,
+ name);
+ return NULL;
+}
+
+static const char *add_footer(cmd_parms *cmd, void *d, char *name)
+{
+ push_item(((autoindex_config_rec *) d)->ftr_list, 0, NULL, cmd->path,
+ name);
+ return NULL;
+}
+
/* A legacy directive, FancyIndexing is superseded by the IndexOptions
* keyword. But for compatibility..
*/
@@ -385,6 +427,12 @@ static const char *add_opts(cmd_parms *c
if (!strcasecmp(w, "FancyIndexing")) {
option = FANCY_INDEXING;
}
+ else if (!strcasecmp(w, "StudlyIndexing")) {
+ /* automatic FancyIndexing on, NameWidth=*, etc. */
+ option = STUDLY_INDEXING + FANCY_INDEXING
+ + ICONS_ARE_LINKS + SUPPRESS_DESC;
+ d_cfg->name_adjust = K_ADJUST;
+ }
else if (!strcasecmp(w, "IconsAreLinks")) {
option = ICONS_ARE_LINKS;
}
@@ -406,16 +454,16 @@ static const char *add_opts(cmd_parms *c
else if (!strcasecmp(w, "SuppressColumnSorting")) {
option = SUPPRESS_COLSORT;
}
- else if (!strcasecmp(w, "FoldersFirst")) {
- option = FOLDERS_FIRST;
+ else if (!strcasecmp(w, "FoldersFirst")) {
+ option = FOLDERS_FIRST;
}
else if (!strcasecmp(w, "TrackModified")) {
- option = TRACK_MODIFIED;
+ option = TRACK_MODIFIED;
}
else if (!strcasecmp(w, "IgnoreCase")) {
- option = SORT_NOCASE;
+ option = SORT_NOCASE;
}
- else if (!strcasecmp(w, "None")) {
+ else if (!strcasecmp(w, "None")) {
if (action != '\0') {
return "Cannot combine '+' or '-' with 'None' keyword";
}
@@ -501,7 +549,49 @@ static const char *add_opts(cmd_parms *c
d_cfg->desc_adjust = K_NOADJUST;
}
}
- else {
+ else if (!strncasecmp(w, "BodyColor=", 10)) {
+ if (action == '-') {
+ return "Cannot combine '-' with BodyColor=#xxxxxx";
+ }
+ d_cfg->body_col = ap_pstrdup(d_cfg->desc_list->pool, &w[10]);
+ }
+ else if (!strncasecmp(w, "TextColor=", 10)) {
+ if (action == '-') {
+ return "Cannot combine '-' with TextColor=#xxxxxx";
+ }
+ d_cfg->text_col = ap_pstrdup(d_cfg->desc_list->pool, &w[10]);
+ }
+ else if (!strncasecmp(w, "HeaderColor=", 12)) {
+ if (action == '-') {
+ return "Cannot combine '-' with HeaderColor=#xxxxxx";
+ }
+ d_cfg->hdr_col = ap_pstrdup(d_cfg->desc_list->pool, &w[12]);
+ }
+ else if (!strncasecmp(w, "ReadmeColor=", 12)) {
+ if (action == '-') {
+ return "Cannot combine '-' with ReadmeColor=#xxxxxx";
+ }
+ d_cfg->rdme_col = ap_pstrdup(d_cfg->desc_list->pool, &w[12]);
+ }
+ else if (!strncasecmp(w, "SidebarColor=", 13)) {
+ if (action == '-') {
+ return "Cannot combine '-' with SidebarColor=#xxxxxx";
+ }
+ d_cfg->side_col = ap_pstrdup(d_cfg->desc_list->pool, &w[13]);
+ }
+ else if (!strncasecmp(w, "MainColor=", 10)) {
+ if (action == '-') {
+ return "Cannot combine '-' with MainColor=#xxxxxx";
+ }
+ d_cfg->main_col = ap_pstrdup(d_cfg->desc_list->pool, &w[10]);
+ }
+ else if (!strncasecmp(w, "FooterColor=", 12)) {
+ if (action == '-') {
+ return "Cannot combine '-' with FooterColor=#xxxxxx";
+ }
+ d_cfg->ftr_col = ap_pstrdup(d_cfg->desc_list->pool, &w[12]);
+ }
+ else {
return "Invalid directory indexing option";
}
if (action == '\0') {
@@ -595,6 +685,9 @@ static const command_rec autoindex_cmds[
"Descriptive text followed by one or more filenames"},
{"HeaderName", add_header, NULL, DIR_CMD_PERMS, TAKE1, "a filename"},
{"ReadmeName", add_readme, NULL, DIR_CMD_PERMS, TAKE1, "a filename"},
+ {"SidebarName", add_sidebar, NULL, DIR_CMD_PERMS, TAKE1, "a filename"},
+ {"BodyName", add_body, NULL, DIR_CMD_PERMS, TAKE1, "a filename"},
+ {"FooterName", add_footer, NULL, DIR_CMD_PERMS, TAKE1, "a filename"},
{"FancyIndexing", fancy_indexing, NULL, DIR_CMD_PERMS, FLAG,
"Limited to 'on' or 'off' (superseded by IndexOptions FancyIndexing)"},
{"DefaultIcon", ap_set_string_slot,
@@ -620,6 +713,9 @@ static void *create_autoindex_config(poo
new->ign_list = ap_make_array(p, 4, sizeof(struct item));
new->hdr_list = ap_make_array(p, 4, sizeof(struct item));
new->rdme_list = ap_make_array(p, 4, sizeof(struct item));
+ new->side_list = ap_make_array(p, 4, sizeof(struct item));
+ new->main_list = ap_make_array(p, 4, sizeof(struct item));
+ new->ftr_list = ap_make_array(p, 4, sizeof(struct item));
new->opts = 0;
new->incremented_opts = 0;
new->decremented_opts = 0;
@@ -646,6 +742,9 @@ static void *merge_autoindex_configs(poo
new->desc_list = ap_append_arrays(p, add->desc_list, base->desc_list);
new->icon_list = ap_append_arrays(p, add->icon_list, base->icon_list);
new->rdme_list = ap_append_arrays(p, add->rdme_list, base->rdme_list);
+ new->side_list = ap_append_arrays(p, add->side_list, base->side_list);
+ new->main_list = ap_append_arrays(p, add->main_list, base->main_list);
+ new->ftr_list = ap_append_arrays(p, add->ftr_list, base->ftr_list);
if (add->opts & NO_OPTIONS) {
/*
* If the current directory says 'no options' then we also
@@ -715,6 +814,22 @@ static void *merge_autoindex_configs(poo
new->default_order = (add->default_order != NULL)
? add->default_order : base->default_order;
+
+ new->body_col = (add->body_col != NULL)
+ ? add->body_col : base->body_col;
+ new->text_col = (add->text_col != NULL)
+ ? add->text_col : base->text_col;
+ new->hdr_col = (add->hdr_col != NULL)
+ ? add->hdr_col : base->hdr_col;
+ new->rdme_col = (add->rdme_col != NULL)
+ ? add->rdme_col : base->rdme_col;
+ new->side_col = (add->side_col != NULL)
+ ? add->side_col : base->side_col;
+ new->main_col = (add->main_col != NULL)
+ ? add->main_col : base->main_col;
+ new->ftr_col = (add->ftr_col != NULL)
+ ? add->ftr_col : base->ftr_col;
+
return new;
}
@@ -789,7 +904,10 @@ static char *find_item(request_rec *r, a
#define find_icon(d,p,t) find_item(p,d->icon_list,t)
#define find_alt(d,p,t) find_item(p,d->alt_list,t)
#define find_header(d,p) find_item(p,d->hdr_list,0)
+#define find_sidebar(d,p) find_item(p,d->side_list,0)
#define find_readme(d,p) find_item(p,d->rdme_list,0)
+#define find_main(d,p) find_item(p,d->main_list,0)
+#define find_footer(d,p) find_item(p,d->ftr_list,0)
static char *find_default_icon(autoindex_config_rec *d, char *bogus_name)
{
@@ -940,12 +1058,13 @@ static int ignore_entry(autoindex_config
/*
* emit a plain text file
*/
-static void do_emit_plain(request_rec *r, FILE *f)
+static void do_emit_plain(request_rec *r, FILE *f, int autoindex_opts)
{
char buf[IOBUFSIZE + 1];
int i, n, c, ch;
- ap_rputs("<PRE>\n", r);
+ if (! (autoindex_opts & STUDLY_INDEXING))
+ ap_rputs("<PRE>\n", r);
while (!feof(f)) {
do {
n = fread(buf, sizeof(char), IOBUFSIZE, f);
@@ -977,7 +1096,50 @@ static void do_emit_plain(request_rec *r
c = i + 1;
}
}
- ap_rputs("</PRE>\n", r);
+ if (! (autoindex_opts & STUDLY_INDEXING))
+ ap_rputs("</PRE>\n", r);
+}
+
+/*
+ * If there's a file, send a subrequest to look for it. If it's
+ * found and a text file, handle it and return 0, otherwise return -1.
+ */
+static int do_emit_fancy(request_rec *r, const char *fname, int autoindex_opts)
+{
+ FILE *f;
+ request_rec *rr = NULL;
+
+ if ((fname != NULL)
+ && (rr = ap_sub_req_lookup_uri(fname, r))
+ && (rr->status == HTTP_OK)
+ && (rr->filename != NULL)
+ && S_ISREG(rr->finfo.st_mode)) {
+ /*
+ * Check for the two specific cases we allow: text/html and
+ * text/anything-else. The former is allowed to be processed for
+ * SSIs.
+ */
+ if (rr->content_type != NULL) {
+ if (!strcasecmp(ap_field_noparam(r->pool, rr->content_type),
+ "text/html")) {
+ if (ap_run_sub_req(rr) == OK) {
+ /* worked... */
+ return 0;
+ }
+ }
+ else if (!strncasecmp("text/", rr->content_type, 5)) {
+ if ((f = ap_pfopen(r->pool, rr->filename, "r")) != 0) {
+ do_emit_plain(r, f, autoindex_opts);
+ ap_pfclose(r->pool, f);
+ return 0;
+ }
+ }
+ }
+ }
+ if (rr != NULL) {
+ ap_destroy_sub_req(rr);
+ }
+ return -1;
}
/* See mod_include */
@@ -993,8 +1155,9 @@ static void do_emit_plain(request_rec *r
* instead of a text document, meaning nothing will be displayed, but
* oh well.
*/
-static void emit_head(request_rec *r, char *header_fname, int suppress_amble,
- char *title)
+static void emit_head(request_rec *r, char *header_fname,
+ autoindex_config_rec *autoindex_conf,
+ int autoindex_opts, char *title)
{
FILE *f;
request_rec *rr = NULL;
@@ -1035,8 +1198,8 @@ static void emit_head(request_rec *r, ch
emit_amble = 0;
emit_H1 = 0;
- if (! suppress_amble) {
- emit_preamble(r, title);
+ if (! (autoindex_opts & SUPPRESS_PREAMBLE)) {
+ emit_preamble(r, title, autoindex_conf);
}
/* See mod_include */
@@ -1050,7 +1213,7 @@ static void emit_head(request_rec *r, ch
*/
if (ap_run_sub_req(rr) != OK) {
/* It didn't work */
- emit_amble = suppress_amble;
+ emit_amble = autoindex_opts & SUPPRESS_PREAMBLE;
emit_H1 = 1;
}
ap_table_unset(r->notes, PARENT_STRING); /* cleanup */
@@ -1063,9 +1226,9 @@ static void emit_head(request_rec *r, ch
* where it belongs.
*/
if ((f = ap_pfopen(r->pool, rr->filename, "r")) != 0) {
- emit_preamble(r, title);
+ emit_preamble(r, title, autoindex_conf);
emit_amble = 0;
- do_emit_plain(r, f);
+ do_emit_plain(r, f, autoindex_opts);
ap_pfclose(r->pool, f);
emit_H1 = 0;
}
@@ -1085,10 +1248,28 @@ static void emit_head(request_rec *r, ch
}
if (emit_amble) {
- emit_preamble(r, title);
+ emit_preamble(r, title, autoindex_conf);
}
+
+ if (autoindex_opts & STUDLY_INDEXING) {
+ ap_rvputs(r, "<TABLE cellpadding=\"5\" cellspacing=\"5\" "
+ "width=\"100%\">\n<tbody>\n", NULL);
+ }
+
if (emit_H1) {
- ap_rvputs(r, "<H1>Index of ", title, "</H1>\n", NULL);
+ if (autoindex_opts & STUDLY_INDEXING)
+ ap_rvputs(r, "\n<TR valign=\"top\">\n"
+ "<TD class=\"header\" bgcolor=\"",
+ autoindex_conf->hdr_col ?: "#ffffff",
+ "\" colspan=\"2\">\n", NULL);
+ ap_rputs("<TABLE><TR><TD bgcolor=\"#ffffff\" "
+ "class=\"title\">\n", r);
+ ap_rvputs(r, "<FONT size=\"+3\" "
+ "face=\"Helvetica,Arial,sans-serif\">\n<B>Index of ",
+ title, "</B></FONT>\n", NULL);
+ ap_rputs("\n</TD></TR></TABLE>", r);
+ if (autoindex_opts & STUDLY_INDEXING)
+ ap_rvputs(r, "</TD>\N</TR>\n", NULL);
}
if (rr != NULL) {
ap_destroy_sub_req(rr);
@@ -1105,7 +1286,8 @@ static void emit_head(request_rec *r, ch
* instead of a text document, meaning nothing will be displayed, but
* oh well.
*/
-static void emit_tail(request_rec *r, char *readme_fname, int suppress_amble)
+static void emit_tail(request_rec *r, char *readme_fname,
+ autoindex_config_rec *autoindex_conf, int autoindex_opts)
{
FILE *f;
request_rec *rr = NULL;
@@ -1150,7 +1332,7 @@ static void emit_tail(request_rec *r, ch
if (ap_run_sub_req(rr) == OK) {
/* worked... */
suppress_sig = 1;
- suppress_post = suppress_amble;
+ suppress_post = autoindex_opts & SUPPRESS_PREAMBLE;
}
ap_table_unset(r->notes, PARENT_STRING); /* cleanup */
}
@@ -1159,7 +1341,7 @@ static void emit_tail(request_rec *r, ch
* If we can open the file, suppress the signature.
*/
if ((f = ap_pfopen(r->pool, rr->filename, "r")) != 0) {
- do_emit_plain(r, f);
+ do_emit_plain(r, f, autoindex_opts & STUDLY_INDEXING);
ap_pfclose(r->pool, f);
suppress_sig = 1;
}
@@ -1178,7 +1360,21 @@ static void emit_tail(request_rec *r, ch
ap_table_setn(hdrs, "Accept-Encoding", r_accept_enc);
}
+ if (autoindex_opts & STUDLY_INDEXING && !suppress_post) {
+ ap_rvputs(r, "\n<TR valign=\"top\">\n<TD class=\"footer\" "
+ "colspan=\"2\" bgcolor=\"",
+ autoindex_conf->ftr_col ?: "#ffffff", "\">\n", NULL);
+ if (do_emit_fancy (r, find_footer(autoindex_conf, r),
+ autoindex_opts) == 0) {
+ suppress_sig = 1;
+ }
+ ap_rputs("</TD>\n</TR>\n\n</TBODY></TABLE>\n<P>\n", r);
+ }
if (!suppress_sig) {
+ if (autoindex_opts & STUDLY_INDEXING)
+ ap_rputs ("<BR><IMG src=\"/icons/linux-pengo-small.gif\"\n"
+ "width=\"110\" height=\"44\" align=\"right\""
+ "alt=\"\">", r);
ap_rputs(ap_psignature("", r), r);
}
if (!suppress_post) {
@@ -1411,6 +1607,11 @@ static void output_directories(struct en
char *name_scratch;
char *pad_scratch;
+ if (autoindex_opts & STUDLY_INDEXING) {
+ if (do_emit_fancy (r, find_main(d, r), autoindex_opts) == 0)
+ return;
+ }
+
if (name[0] == '\0') {
name = "/";
}
@@ -1443,7 +1644,8 @@ static void output_directories(struct en
if (autoindex_opts & FANCY_INDEXING) {
ap_rputs("<PRE>", r);
if ((tp = find_default_icon(d, "^^BLANKICON^^"))) {
- ap_rvputs(r, "<IMG SRC=\"", ap_escape_html(scratch, tp),
+ ap_rvputs(r, "<IMG border=\"0\" src=\"",
+ ap_escape_html(scratch, tp),
"\" ALT=\" \"", NULL);
if (d->icon_width && d->icon_height) {
ap_rprintf
@@ -1475,7 +1677,7 @@ static void output_directories(struct en
emit_link(r, "Description", K_DESC, keyid, direction,
static_columns);
}
- ap_rputs("\n<HR>\n", r);
+ ap_rputs("\n<HR noshade align=\"left\" width=\"80%\">\n", r);
}
else {
ap_rputs("<UL>", r);
@@ -1507,7 +1709,7 @@ static void output_directories(struct en
ap_rvputs(r, "<A HREF=\"", anchor, "\">", NULL);
}
if ((ar[x]->icon) || d->default_icon) {
- ap_rvputs(r, "<IMG SRC=\"",
+ ap_rvputs(r, "<IMG border=\"0\" src=\"",
ap_escape_html(scratch,
ar[x]->icon ? ar[x]->icon
: d->default_icon),
@@ -1717,7 +1919,7 @@ static int index_directory(request_rec *
*title_endp-- = '\0';
}
- emit_head(r, find_header(autoindex_conf, r),
+ emit_head(r, find_header(autoindex_conf, r), autoindex_conf,
autoindex_opts & SUPPRESS_PREAMBLE, title_name);
/*
@@ -1779,15 +1981,27 @@ static int index_directory(request_rec *
qsort((void *) ar, num_ent, sizeof(struct ent *),
(int (*)(const void *, const void *)) dsortf);
}
+ if (autoindex_opts & STUDLY_INDEXING) {
+ ap_rputs("\n<TR valign=\"top\">\n", r);
+ ap_rvputs(r, "\n<TD class=\"sidebar\" bgcolor=\"",
+ autoindex_conf->side_col ?: "#ffffff",
+ "\" width=\"5%\">\n", NULL);
+ do_emit_fancy (r, find_sidebar(autoindex_conf, r), autoindex_opts);
+ ap_rputs("</TD>\n", r);
+ ap_rvputs(r, "\n<TD class=\"body\" bgcolor=\"",
+ autoindex_conf->main_col ?: "#ffffff", "\">\n", NULL);
+ }
output_directories(ar, num_ent, autoindex_conf, r, autoindex_opts, keyid,
direction);
ap_pclosedir(r->pool, d);
- if (autoindex_opts & FANCY_INDEXING) {
- ap_rputs("<HR>\n", r);
+ if (autoindex_opts & STUDLY_INDEXING) {
+ ap_rputs("</TD class=\"body\">\n\n</TR>\n", r);
+ }
+ else if (autoindex_opts & FANCY_INDEXING) {
+ ap_rputs("<HR noshade align=\"left\" width=\"80%\">\n", r);
}
- emit_tail(r, find_readme(autoindex_conf, r),
- autoindex_opts & SUPPRESS_PREAMBLE);
+ emit_tail(r, find_readme(autoindex_conf, r), autoindex_conf, autoindex_opts);
ap_kill_timeout(r);
return 0;
--
"Next the statesmen will invent cheap lies, putting the blame upon
the nation that is attacked, and every man will be glad of those
conscience-soothing falsities, and will diligently study them, and refuse
to examine any refutations of them; and thus he will by and by convince
himself that the war is just, and will thank God for the better sleep
he enjoys after this process of grotesque self-deception." -- Mark Twain
Reply to: