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 &quot;Size&quot;,
  +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 &quot;1K&quot;.
  +</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)
  
  
  

Reply via email to