[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: