From d78536c9a4ae370eb11ac4a445f35651f62c8def Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Thu, 24 Oct 2013 17:38:48 +0300 Subject: [PATCH] Support sorting files using mtime or size This introduces Apache-style URL arguments to specify how to sort the entries in the generated listings: - Appending "?C=M" sorts by modification time (mtime). - Appending "?C=S" sorts by file size. - Any other (or no arguments) use the default sorting, by name. --- ngx_http_fancyindex_module.c | 70 +++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/ngx_http_fancyindex_module.c b/ngx_http_fancyindex_module.c index 01e82ff..0507ed3 100644 --- a/ngx_http_fancyindex_module.c +++ b/ngx_http_fancyindex_module.c @@ -96,7 +96,11 @@ typedef struct { static int ngx_libc_cdecl - ngx_http_fancyindex_cmp_entries(const void *one, const void *two); + ngx_http_fancyindex_cmp_entries_name(const void *one, const void *two); +static int ngx_libc_cdecl + ngx_http_fancyindex_cmp_entries_size(const void *one, const void *two); +static int ngx_libc_cdecl + ngx_http_fancyindex_cmp_entries_mtime(const void *one, const void *two); static ngx_int_t ngx_http_fancyindex_error(ngx_http_request_t *r, ngx_dir_t *dir, ngx_str_t *name); @@ -364,6 +368,8 @@ make_content_buf( { ngx_http_fancyindex_entry_t *entry; + int (*sort_cmp_func) (const void*, const void*); + off_t length; size_t len, root, copy, allocated; u_char *filename, *last, scale; @@ -579,9 +585,27 @@ make_content_buf( /* Sort entries, if needed */ if (entries.nelts > 1) { + sort_cmp_func = ngx_http_fancyindex_cmp_entries_name; + + /* Determine the sorting criteria */ + if (r->args.len == 3 && r->args.data[0] == 'C' && r->args.data[1] == '=') { + switch (r->args.data[2]) { + case 'M': /* Sort by mtime */ + sort_cmp_func = ngx_http_fancyindex_cmp_entries_mtime; + break; + case 'S': /* Sort by size */ + sort_cmp_func = ngx_http_fancyindex_cmp_entries_size; + break; + case 'N': /* Sort by name */ + default: + break; + } + } + + /* Any other argument (or no argument): sort by file name */ ngx_qsort(entry, (size_t) entries.nelts, - sizeof(ngx_http_fancyindex_entry_t), - ngx_http_fancyindex_cmp_entries); + sizeof(ngx_http_fancyindex_entry_t), + sort_cmp_func); } b->last = ngx_cpymem_str(b->last, r->uri); @@ -898,7 +922,7 @@ add_builtin_header: static int ngx_libc_cdecl -ngx_http_fancyindex_cmp_entries(const void *one, const void *two) +ngx_http_fancyindex_cmp_entries_name(const void *one, const void *two) { ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one; ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two; @@ -917,6 +941,44 @@ ngx_http_fancyindex_cmp_entries(const void *one, const void *two) } +static int ngx_libc_cdecl +ngx_http_fancyindex_cmp_entries_size(const void *one, const void *two) +{ + ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one; + ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two; + + if (first->dir && !second->dir) { + /* move the directories to the start */ + return -1; + } + + if (!first->dir && second->dir) { + /* move the directories to the start */ + return 1; + } + + return second->size - first->size; +} + + +static int ngx_libc_cdecl +ngx_http_fancyindex_cmp_entries_mtime(const void *one, const void *two) +{ + ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one; + ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two; + + if (first->dir && !second->dir) { + /* move the directories to the start */ + return -1; + } + + if (!first->dir && second->dir) { + /* move the directories to the start */ + return 1; + } + + return second->mtime - first->mtime; +} static ngx_int_t