Support changing the sort direction of elements

When choosing different sorting criteria for the elements (with the "?C=x"
URL argument), allow also specifying a second "O=x" argument for the
direction: "?C=x&O=A" selects ascending direction, while "?C=x&O=D" chooses
descending direction.
pull/8/head
Adrian Perez de Castro 2013-10-24 21:45:18 +03:00
parent d78536c9a4
commit 1226d363be
1 changed files with 99 additions and 22 deletions

View File

@ -96,11 +96,17 @@ typedef struct {
static int ngx_libc_cdecl static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_name(const void *one, const void *two); ngx_http_fancyindex_cmp_entries_name_desc(const void *one, const void *two);
static int ngx_libc_cdecl static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_size(const void *one, const void *two); ngx_http_fancyindex_cmp_entries_size_desc(const void *one, const void *two);
static int ngx_libc_cdecl static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_mtime(const void *one, const void *two); ngx_http_fancyindex_cmp_entries_mtime_desc(const void *one, const void *two);
static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_name_asc(const void *one, const void *two);
static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_size_asc(const void *one, const void *two);
static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_mtime_asc(const void *one, const void *two);
static ngx_int_t ngx_http_fancyindex_error(ngx_http_request_t *r, static ngx_int_t ngx_http_fancyindex_error(ngx_http_request_t *r,
ngx_dir_t *dir, ngx_str_t *name); ngx_dir_t *dir, ngx_str_t *name);
@ -369,6 +375,7 @@ make_content_buf(
ngx_http_fancyindex_entry_t *entry; ngx_http_fancyindex_entry_t *entry;
int (*sort_cmp_func) (const void*, const void*); int (*sort_cmp_func) (const void*, const void*);
ngx_int_t sort_descending = 0;
off_t length; off_t length;
size_t len, root, copy, allocated; size_t len, root, copy, allocated;
@ -585,24 +592,46 @@ make_content_buf(
/* Sort entries, if needed */ /* Sort entries, if needed */
if (entries.nelts > 1) { if (entries.nelts > 1) {
sort_cmp_func = ngx_http_fancyindex_cmp_entries_name; /*
* Determine the sorting criteria. URL arguments look like:
*
* C=x[&O=y]
*
* Where x={M,S,N} and y={A,D}
*/
if ((r->args.len == 3 || (r->args.len == 7 && r->args.data[3] == '&')) &&
r->args.data[0] == 'C' && r->args.data[1] == '=')
{
/* Determine whether the direction of the sorting */
sort_descending = r->args.len == 7
&& r->args.data[4] == 'O'
&& r->args.data[5] == '='
&& r->args.data[6] == 'D';
/* Determine the sorting criteria */ /* Pick the sorting criteria */
if (r->args.len == 3 && r->args.data[0] == 'C' && r->args.data[1] == '=') {
switch (r->args.data[2]) { switch (r->args.data[2]) {
case 'M': /* Sort by mtime */ case 'M': /* Sort by mtime */
sort_cmp_func = ngx_http_fancyindex_cmp_entries_mtime; sort_cmp_func = sort_descending
? ngx_http_fancyindex_cmp_entries_mtime_desc
: ngx_http_fancyindex_cmp_entries_mtime_asc;
break; break;
case 'S': /* Sort by size */ case 'S': /* Sort by size */
sort_cmp_func = ngx_http_fancyindex_cmp_entries_size; sort_cmp_func = sort_descending
? ngx_http_fancyindex_cmp_entries_size_desc
: ngx_http_fancyindex_cmp_entries_size_asc;
break; break;
case 'N': /* Sort by name */ case 'N': /* Sort by name */
default: default:
sort_cmp_func = sort_descending
? ngx_http_fancyindex_cmp_entries_name_desc
: ngx_http_fancyindex_cmp_entries_name_asc;
break; break;
} }
} }
else {
sort_cmp_func = ngx_http_fancyindex_cmp_entries_name_asc;
}
/* Any other argument (or no argument): sort by file name */
ngx_qsort(entry, (size_t) entries.nelts, ngx_qsort(entry, (size_t) entries.nelts,
sizeof(ngx_http_fancyindex_entry_t), sizeof(ngx_http_fancyindex_entry_t),
sort_cmp_func); sort_cmp_func);
@ -922,38 +951,34 @@ add_builtin_header:
static int ngx_libc_cdecl static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_name(const void *one, const void *two) ngx_http_fancyindex_cmp_entries_name_desc(const void *one, const void *two)
{ {
ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one; ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two; ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two;
/* move the directories to the start */
if (first->dir && !second->dir) { if (first->dir && !second->dir) {
/* move the directories to the start */
return -1; return -1;
} }
if (!first->dir && second->dir) { if (!first->dir && second->dir) {
/* move the directories to the start */
return 1; return 1;
} }
return (int) ngx_strcmp(first->name.data, second->name.data); return (int) ngx_strcmp(second->name.data, first->name.data);
} }
static int ngx_libc_cdecl static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_size(const void *one, const void *two) ngx_http_fancyindex_cmp_entries_size_desc(const void *one, const void *two)
{ {
ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one; ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two; ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two;
/* move the directories to the start */
if (first->dir && !second->dir) { if (first->dir && !second->dir) {
/* move the directories to the start */
return -1; return -1;
} }
if (!first->dir && second->dir) { if (!first->dir && second->dir) {
/* move the directories to the start */
return 1; return 1;
} }
@ -962,18 +987,16 @@ ngx_http_fancyindex_cmp_entries_size(const void *one, const void *two)
static int ngx_libc_cdecl static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_mtime(const void *one, const void *two) ngx_http_fancyindex_cmp_entries_mtime_desc(const void *one, const void *two)
{ {
ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one; ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two; ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two;
/* move the directories to the start */
if (first->dir && !second->dir) { if (first->dir && !second->dir) {
/* move the directories to the start */
return -1; return -1;
} }
if (!first->dir && second->dir) { if (!first->dir && second->dir) {
/* move the directories to the start */
return 1; return 1;
} }
@ -981,6 +1004,60 @@ ngx_http_fancyindex_cmp_entries_mtime(const void *one, const void *two)
} }
static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_name_asc(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;
/* move the directories to the start */
if (first->dir && !second->dir) {
return -1;
}
if (!first->dir && second->dir) {
return 1;
}
return (int) ngx_strcmp(first->name.data, second->name.data);
}
static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_size_asc(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;
/* move the directories to the start */
if (first->dir && !second->dir) {
return -1;
}
if (!first->dir && second->dir) {
return 1;
}
return first->size - second->size;
}
static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_mtime_asc(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;
/* move the directories to the start */
if (first->dir && !second->dir) {
return -1;
}
if (!first->dir && second->dir) {
return 1;
}
return first->mtime - second->mtime;
}
static ngx_int_t static ngx_int_t
ngx_http_fancyindex_error(ngx_http_request_t *r, ngx_dir_t *dir, ngx_str_t *name) ngx_http_fancyindex_error(ngx_http_request_t *r, ngx_dir_t *dir, ngx_str_t *name)
{ {