Welcome! Log In Create A New Profile

Advanced

[RFC] [PATCH] Autoindex: support sorting using URL parameters

January 29, 2013 12:50PM
Based on Apache HTTPD autoindex docs[1]. Supported:
- C=N sorts the directory by file name
- C=M sorts the directory by last-modified date, then file name
- C=S sorts the directory by size, then file name
- O=A sorts the listing in Ascending Order
- O=D sorts the listing in Descending Order

Not supported (does not make sense for nginx):
- C=D sorts the directory by description, then file name
- All F= (FancyIndex) related arguments
- Version sorting for file names (V=)
- Pattern filter (P=)

Argument processing stops when the query string does not exactly match the
options allowed by nginx, invalid values (like "C=m", "C=x" or "C=foo") are
ignored and cause further processing to stop.

C and O are the most useful options and can commonly be found in my old Apache
logs (also outputted in header links). This patch is made for these cases, not
for some exotic use of Apache-specific properties.

[1]: http://httpd.apache.org/docs/2.4/mod/mod_autoindex.html
---
(this patch is also available at http://lekensteyn.nl/files/nginx/)

RFC: this patch only adds support for URL parameters. Before implementing the
actual clickable headers I would like to have some feedback. Do you actually
want to add such a sorting feature to the standard autoindex module? Sorting
has also been requested on http://forum.nginx.org/read.php?10,211728

I am aware of FancyIndex[2] (which does not support sorting either), but having
two separate modules to do the exact same thing seems a bit useless.

About the implementation, I considered using the non-standard qsort_r
(different prototypes on BSD and Linux, qsort_s on Windows) for adding the sort
options. Because these prototypes and their compare functions are incompatible
I dropped that idea. Next was augmenting the directory entries struct to make
the options available, this is currently the way how it is implemented.

Parsing URL parameters is done in a separate function which is currently
non-void. Since the return value is not used at the moment, it can also be make
void. Thoughts?

[2]: http://wiki.nginx.org/NgxFancyIndex
---
src/http/modules/ngx_http_autoindex_module.c | 93 +++++++++++++++++++++++++++-
1 file changed, 92 insertions(+), 1 deletion(-)

diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c
index 450a48e..aa1be25 100644
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -24,6 +24,16 @@ typedef struct {


typedef struct {
+ u_char sort_key;
+ unsigned order_desc:1;
+} ngx_http_autoindex_opts_t;
+
+#define NGX_AUTOINDEX_SORT_NAME 'N'
+#define NGX_AUTOINDEX_SORT_MTIME 'M'
+#define NGX_AUTOINDEX_SORT_SIZE 'S'
+
+
+typedef struct {
ngx_str_t name;
size_t utf_len;
size_t escape;
@@ -33,6 +43,8 @@ typedef struct {

time_t mtime;
off_t size;
+
+ ngx_http_autoindex_opts_t *sort_opts;
} ngx_http_autoindex_entry_t;


@@ -50,6 +62,8 @@ typedef struct {

static int ngx_libc_cdecl ngx_http_autoindex_cmp_entries(const void *one,
const void *two);
+static ngx_int_t ngx_http_autoindex_get_opts(ngx_http_request_t *r,
+ ngx_http_autoindex_opts_t *opts);
static ngx_int_t ngx_http_autoindex_error(ngx_http_request_t *r,
ngx_dir_t *dir, ngx_str_t *name);
static ngx_int_t ngx_http_autoindex_init(ngx_conf_t *cf);
@@ -153,6 +167,7 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
ngx_array_t entries;
ngx_http_autoindex_entry_t *entry;
ngx_http_autoindex_loc_conf_t *alcf;
+ ngx_http_autoindex_opts_t opts;

static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
@@ -214,6 +229,8 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
return rc;
}

+ ngx_http_autoindex_get_opts(r, &opts);
+
#if (NGX_SUPPRESS_WARN)

/* MSVC thinks 'entries' may be used without having been initialized */
@@ -353,6 +370,8 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
entry->dir = ngx_de_is_dir(&dir);
entry->mtime = ngx_de_mtime(&dir);
entry->size = ngx_de_size(&dir);
+
+ entry->sort_opts = &opts;
}

if (ngx_close_dir(&dir) == NGX_ERROR) {
@@ -580,11 +599,67 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
}


+static ngx_int_t
+ngx_http_autoindex_get_opts(ngx_http_request_t *r,
+ ngx_http_autoindex_opts_t *opts)
+{
+ u_char *p, *last, key, val;
+
+ opts->sort_key = NGX_AUTOINDEX_SORT_NAME;
+ opts->order_desc = 0;
+
+ p = r->args.data;
+ last = p + r->args.len;
+
+ for ( /* void */; p < last; p++) {
+
+ key = *p++;
+
+ if (*p++ != '=') {
+ return NGX_DECLINED;
+ }
+
+ val = *p++;
+
+ /* assume one-letter value and expect separator */
+ if (p < last && *p != '&' && *p != ';') {
+ return NGX_DECLINED;
+ }
+
+ if (key == 'C') {
+ switch (val) {
+ case NGX_AUTOINDEX_SORT_NAME:
+ case NGX_AUTOINDEX_SORT_MTIME:
+ case NGX_AUTOINDEX_SORT_SIZE:
+ opts->sort_key = val;
+ break;
+ default:
+ return NGX_DECLINED;
+ }
+ } else if (key == 'O') {
+ if (val == 'D') {
+ opts->order_desc = 1;
+ } else if (val == 'A') {
+ opts->order_desc = 0;
+ } else {
+ return NGX_DECLINED;
+ }
+ } else {
+ return NGX_DECLINED;
+ }
+ }
+
+ return NGX_OK;
+}
+
+
static int ngx_libc_cdecl
ngx_http_autoindex_cmp_entries(const void *one, const void *two)
{
ngx_http_autoindex_entry_t *first = (ngx_http_autoindex_entry_t *) one;
ngx_http_autoindex_entry_t *second = (ngx_http_autoindex_entry_t *) two;
+ ngx_http_autoindex_opts_t *opts = first->sort_opts;
+ int r;

if (first->dir && !second->dir) {
/* move the directories to the start */
@@ -596,7 +671,23 @@ ngx_http_autoindex_cmp_entries(const void *one, const void *two)
return 1;
}

- return (int) ngx_strcmp(first->name.data, second->name.data);
+ switch (opts->sort_key) {
+ case NGX_AUTOINDEX_SORT_MTIME:
+ r = first->mtime - second->mtime;
+ break;
+ case NGX_AUTOINDEX_SORT_SIZE:
+ r = first->size - second->size;
+ break;
+ default: /* includes NGX_AUTOINDEX_SORT_NAME */
+ r = 0;
+ break;
+ }
+
+ if (r == 0) {
+ r = ngx_strcmp(first->name.data, second->name.data);
+ }
+
+ return opts->order_desc ? -r : r;
}


--
1.8.1.1


_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[RFC] [PATCH] Autoindex: support sorting using URL parameters

Lekensteyn 2506 January 29, 2013 12:50PM

Re: [RFC] [PATCH] Autoindex: support sorting using URL parameters

Maxim Dounin 818 January 30, 2013 12:52PM

Re: [RFC] [PATCH] Autoindex: support sorting using URL parameters

Lekensteyn 1222 January 30, 2013 01:10PM

Re: [RFC] [PATCH] Autoindex: support sorting using URL parameters

Valentin V. Bartenev 857 January 30, 2013 01:56PM

Re: [RFC] [PATCH] Autoindex: support sorting using URL parameters

Lekensteyn 1025 January 30, 2013 04:04PM

Re: [RFC] [PATCH] Autoindex: support sorting using URL parameters

Lekensteyn 1056 February 02, 2013 04:08PM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 147
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready