coar 97/07/25 04:04:05
Modified: htdocs/manual new_features_1_3.html
htdocs/manual/mod mod_autoindex.html
src CHANGES mod_autoindex.c
Log:
Add ability to sort FancyIndexed directories by the different
column values, ascending or descending. Also update the new
features page with some stuff that got missed.
Reviewed by: Marc Slemko, Dean Gaudet, Alexei Kosut
Revision Changes Path
1.11 +41 -1 apache/htdocs/manual/new_features_1_3.html
Index: new_features_1_3.html
===================================================================
RCS file: /export/home/cvs/apache/htdocs/manual/new_features_1_3.html,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- new_features_1_3.html 1997/07/21 21:26:53 1.10
+++ new_features_1_3.html 1997/07/25 11:03:58 1.11
@@ -29,7 +29,47 @@
1.3</a> has the following specific new user features:</p>
<ul>
-
+<LI><A
+ HREF="mod/mod_autoindex.html"
+ ><STRONG>Sortable Directory Listings</STRONG></A>
+ <BR>
+ If a directory listing is displayed using
+ <A
+ HREF="mod/mod_autoindex.html#indexoptions"
+ >FancyIndexing</A>,
+ clicking on a column title will now sort the listing in
+ order by the values in that column. Selecting the column
+ repeatedly will toggle between ascending and descending order.
+</LI>
+<LI><A
+ HREF="mod/mod_autoindex.html#indexoptions"
+ ><STRONG><SAMP>SuppressHTMLPreamble</SAMP> Option for
+ FancyIndexed Directories</STRONG></A>
+ <BR>
+ If a directory is marked for display with FancyIndexing, the listing
+ page usually follows a predefined format using server-generated HTML.
+ <STRONG>If</STRONG> the IndexOptions directive for the directory
+ includes the <SAMP>SuppressHTMLPreamble</SAMP> option,
+ <STRONG>and</STRONG> a file specified by the
+ <A
+ HREF="mod/mod_autoindex.html#headername"
+ >HeaderName</A>
+ directive is found in the directory, <STRONG>and</STRONG> the header
+ file is recognized as containing HTML (determined by the file
+ extension), <STRONG>then</STRONG> the module will assume that the
+ header file contains the necessary introductory HTML tags and will not
+ generate them itself.
+</LI>
+<LI><STRONG>Less Buffering of CGI Script Output</STRONG>
+ <BR>
+ In previous versions of Apache, the output from CGI scripts would be
+ internally buffered by the server, and wouldn't be forwarded to the
+ client until either the buffers were full or the CGI script completed.
+ As of Apache 1.3, the buffer to the client is flushed any time it
+ contains something and the server is waiting for more information from
+ the script. This allows CGI script to provide partial status reports
+ during long processing operations.
+</LI>
<li><b><a href="windows.html">Support for Windows NT/95</a></b><br>
Apache now supports the Windows NT and Windows 95 operating systems,
as well as the Unix systems supported in previos releases. Although the
1.12 +18 -0 apache/htdocs/manual/mod/mod_autoindex.html
Index: mod_autoindex.html
===================================================================
RCS file: /export/home/cvs/apache/htdocs/manual/mod/mod_autoindex.html,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- mod_autoindex.html 1997/07/15 15:57:28 1.11
+++ mod_autoindex.html 1997/07/25 11:04:00 1.12
@@ -35,6 +35,24 @@
</ul>
The two functions are separated so that you can completely remove
(or replace) automatic index generation should you want to.
+<P>
+If
+<A
+ HREF="#fancyindexing"
+>FancyIndexing</A>
+is enabled, the column headers are links that control the
+order of the display. If you select a header link, the
+listing will be regenerated, sorted by the values in that
+column. Selecting the same header repeatedly toggles
+between ascending and descending order.
+</P>
+<P>
+Note that when the display is sorted by "Size",
+it's the <EM>actual</EM> size of the files that's used,
+not the displayed value - so a 1010-byte file will
+always be displayed before a 1011-byte file (if in ascending
+order) even though they both are shown as "1K".
+</P>
<h2>Directives</h2>
1.365 +7 -3 apache/src/CHANGES
Index: CHANGES
===================================================================
RCS file: /export/home/cvs/apache/src/CHANGES,v
retrieving revision 1.364
retrieving revision 1.365
diff -u -r1.364 -r1.365
--- CHANGES 1997/07/24 04:38:07 1.364
+++ CHANGES 1997/07/25 11:04:02 1.365
@@ -1,13 +1,17 @@
Changes with Apache 1.3a2
-
+
+ *) mod_autoindex now allows sorting of FancyIndexed directory listings
+ by the various fields (name, size, et cetera), either in ascending
+ or descending order. Just click on the column header. [Ken Coar]
+
*) PORT: Various tweaks to eliminate pointer-int casting warnings on 64-bit
- cpus like the alpha. Apache still stores ints in pointers, but that's
+ CPUs like the Alpha. Apache still stores ints in pointers, but that's
the relatively safe direction. [Dean Gaudet] PR#344
*) PORT: QNX mmap() support for faster/more reliable scoreboard handling.
[Igor N Kovalenko <[EMAIL PROTECTED]>] PR#683
- *) child_main avoids an uneeded call to select() when there is only one
+ *) child_main avoids an unneeded call to select() when there is only one
listening socket. [Dean Gaudet]
*) In the event that the server is starved for idle servers it will
1.42 +174 -13 apache/src/mod_autoindex.c
Index: mod_autoindex.c
===================================================================
RCS file: /export/home/cvs/apache/src/mod_autoindex.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -r1.41 -r1.42
--- mod_autoindex.c 1997/07/24 04:38:10 1.41
+++ mod_autoindex.c 1997/07/25 11:04:03 1.42
@@ -89,6 +89,17 @@
#define SUPPRESS_PREAMBLE 64
/*
+ * Define keys for sorting.
+ */
+#define K_NAME 'N' /* Sort by file name (default) */
+#define K_LAST_MOD 'M' /* Last modification date */
+#define K_SIZE 'S' /* Size (absolute, not as displayed) */
+#define K_DESC 'D' /* Description */
+
+#define D_ASCENDING 'A'
+#define D_DESCENDING 'D'
+
+/*
* These are the dimensions of the default icons supplied with Apache.
*/
#define DEFAULT_ICON_WIDTH 20
@@ -370,8 +381,12 @@
char *alt;
char *desc;
size_t size;
+ char *size_cmp;
time_t lm;
+ char *lm_cmp;
struct ent *next;
+ int ascending;
+ char key;
};
static char *find_item(request_rec *r, array_header *list, int path_only) {
@@ -593,7 +608,9 @@
}
static struct ent *make_autoindex_entry(char *name, int autoindex_opts,
- autoindex_config_rec *d, request_rec *r)
+ autoindex_config_rec *d,
+ request_rec *r, char keyid,
+ char direction)
{
struct ent *p;
@@ -610,6 +627,8 @@
p->alt = NULL;
p->desc = NULL;
p->lm = -1;
+ p->key = toupper(keyid);
+ p->ascending = (toupper(direction) == D_ASCENDING);
if (autoindex_opts & FANCY_INDEXING) {
request_rec *rr = sub_req_lookup_file (name, r);
@@ -638,6 +657,16 @@
destroy_sub_req (rr);
}
+ if (keyid == K_SIZE) {
+ p->size_cmp = palloc (r->pool, 14);
+ ap_snprintf (p->size_cmp, 14, "%013d", p->size);
+ }
+ if (keyid == K_LAST_MOD) {
+ struct tm *ts = localtime(&p->lm);
+
+ p->lm_cmp = palloc (r->pool, 15);
+ strftime (p->lm_cmp, 15, "%Y%m%d%H%M%S", ts);
+ }
return(p);
}
@@ -669,8 +698,29 @@
return desc;
}
+/*
+ * Emit the anchor for the specified field. If a field is the key for the
+ * current request, the link changes its meaning to reverse the order when
+ * selected again. Non-active fields always start in ascending order.
+ */
+static void emit_link(request_rec *r, char *anchor, char fname, char curkey,
+ char curdirection)
+{
+ char qvalue[5];
+ int reverse;
+
+ qvalue[0] = '?';
+ qvalue[1] = fname;
+ qvalue[2] = '=';
+ qvalue[4] = '\0';
+ reverse = ((curkey == fname) && (curdirection == D_ASCENDING));
+ qvalue[3] = reverse ? D_DESCENDING : D_ASCENDING;
+ rvputs (r, "<A HREF=\"", qvalue, "\">", anchor, "</A>", NULL);
+}
+
static void output_directories(struct ent **ar, int n,
- autoindex_config_rec *d, request_rec *r, int autoindex_opts)
+ autoindex_config_rec *d, request_rec *r,
+ int autoindex_opts, char keyid, char direction)
{
int x, len;
char *name = r->uri;
@@ -695,13 +745,19 @@
}
rputs ("> ", r);
}
- rputs("Name ", r);
- if (!(autoindex_opts & SUPPRESS_LAST_MOD))
- rputs("Last modified ", r);
- if (!(autoindex_opts & SUPPRESS_SIZE))
- rputs("Size ", r);
- if (!(autoindex_opts & SUPPRESS_DESC))
- rputs("Description", r);
+ emit_link(r, "Name", K_NAME, keyid, direction);
+ rputs (" ", r);
+ if (!(autoindex_opts & SUPPRESS_LAST_MOD)) {
+ emit_link(r, "Last modified", K_LAST_MOD, keyid, direction);
+ rputs(" ", r);
+ }
+ if (!(autoindex_opts & SUPPRESS_SIZE)) {
+ emit_link(r, "Size", K_SIZE, keyid, direction);
+ rputs(" ", r);
+ }
+ if (!(autoindex_opts & SUPPRESS_DESC)) {
+ emit_link(r, "Description", K_DESC, keyid, direction);
+ }
rputs("\n<HR>\n", r);
}
else {
@@ -802,9 +858,81 @@
}
-static int dsortf(struct ent **s1, struct ent **s2)
+static int dsortf(struct ent **e1, struct ent **e2)
{
- return(strcmp((*s1)->name, (*s2)->name));
+ char *s1;
+ char *s2;
+ char *s3;
+ int result;
+
+ /*
+ * Choose the right values for the sort keys.
+ */
+ switch ((*e1)->key) {
+ case K_LAST_MOD:
+ s1 = (*e1)->lm_cmp;
+ s2 = (*e2)->lm_cmp;
+ break;
+ case K_SIZE:
+ s1 = (*e1)->size_cmp;
+ s2 = (*e2)->size_cmp;
+ break;
+ case K_DESC:
+ s1 = (*e1)->desc;
+ s2 = (*e2)->desc;
+ break;
+ case K_NAME:
+ default:
+ s1 = (*e1)->name;
+ s2 = (*e2)->name;
+ break;
+ }
+ /*
+ * If we're supposed to sort in DEscending order, reverse the arguments.
+ */
+ if (!(*e1)->ascending) {
+ s3 = s1;
+ s1 = s2;
+ s2 = s3;
+ }
+
+ /*
+ * Take some care, here, in case one string or the other (or both) is
+ * NULL.
+ */
+
+ /*
+ * Two valid strings, compare normally.
+ */
+ if ((s1 != NULL) && (s2 != NULL)) {
+ result = strcmp(s1, s2);
+ }
+ /*
+ * Two NULL strings - primary keys are equal (fake it).
+ */
+ else if ((s1 == NULL) && (s2 == NULL)) {
+ result = 0;
+ }
+ /*
+ * s1 is NULL, but s2 is a string - so s2 wins.
+ */
+ else if (s1 == NULL) {
+ result = -1;
+ }
+ /*
+ * Last case: s1 is a string and s2 is NULL, so s1 wins.
+ */
+ else {
+ result = 1;
+ }
+ /*
+ * If the keys were equal, the file name is *always* the secondary key -
+ * in ascending order.
+ */
+ if (!result) {
+ result = strcmp((*e1)->name, (*e2)->name);
+ }
+ return result;
}
@@ -820,7 +948,13 @@
struct ent *head, *p;
struct ent **ar = NULL;
char *tmp;
+ const char *qstring;
int autoindex_opts = find_opts(autoindex_conf, r);
+ char key;
+ int sort_ascending = 1;
+ char *query_string;
+ char keyid;
+ char direction;
if (!(d = popendir(r->pool, name))) {
log_reason ("Can't open directory for index", r->filename, r);
@@ -852,13 +986,39 @@
rvputs(r, "<H1>Index of ", title_name, "</H1>\n", NULL);
}
+ /*
+ * Figure out what sort of indexing (if any) we're supposed to use.
+ */
+ qstring = r->args;
+
+ /*
+ * If no QUERY_STRING was specified, we use the default: ascending by
+ * name.
+ */
+ if ((qstring == NULL) || (*qstring == '\0')) {
+ keyid = K_NAME;
+ direction = D_ASCENDING;
+ }
+ else {
+ keyid = *qstring;
+ getword (r->pool, &qstring, '=');
+ if (qstring != '\0') {
+ direction = *qstring;
+ }
+ else {
+ direction = D_ASCENDING;
+ }
+ }
+
/*
* Since we don't know how many dir. entries there are, put them into a
* linked list and then arrayificate them so qsort can use them.
*/
head = NULL;
while ((dstruct = readdir(d))) {
- if ((p = make_autoindex_entry(dstruct->d_name, autoindex_opts,
autoindex_conf, r))) {
+ p = make_autoindex_entry(dstruct->d_name, autoindex_opts,
+ autoindex_conf, r, keyid, direction);
+ if (p != NULL) {
p->next = head;
head = p;
num_ent++;
@@ -880,7 +1040,8 @@
(int (*)(const void *, const void *))dsortf);
#endif
}
- output_directories(ar, num_ent, autoindex_conf, r, autoindex_opts);
+ output_directories(ar, num_ent, autoindex_conf, r, autoindex_opts, keyid,
+ direction);
pclosedir(r->pool, d);
if (autoindex_opts & FANCY_INDEXING)