2
2
* ngx_http_fancyindex_module.c
3
* Copyright © 2007-2011 Adrian Perez <aperez@igalia.com>
3
* Copyright © 2007-2013 Adrian Perez <aperez@igalia.com>
5
5
* Module used for fancy indexing of directories. Features and differences
6
6
* with the stock nginx autoindex module:
98
98
static int ngx_libc_cdecl
99
ngx_http_fancyindex_cmp_entries(const void *one, const void *two);
99
ngx_http_fancyindex_cmp_entries_name_desc(const void *one, const void *two);
100
static int ngx_libc_cdecl
101
ngx_http_fancyindex_cmp_entries_size_desc(const void *one, const void *two);
102
static int ngx_libc_cdecl
103
ngx_http_fancyindex_cmp_entries_mtime_desc(const void *one, const void *two);
104
static int ngx_libc_cdecl
105
ngx_http_fancyindex_cmp_entries_name_asc(const void *one, const void *two);
106
static int ngx_libc_cdecl
107
ngx_http_fancyindex_cmp_entries_size_asc(const void *one, const void *two);
108
static int ngx_libc_cdecl
109
ngx_http_fancyindex_cmp_entries_mtime_asc(const void *one, const void *two);
101
111
static ngx_int_t ngx_http_fancyindex_error(ngx_http_request_t *r,
102
112
ngx_dir_t *dir, ngx_str_t *name);
365
375
ngx_http_fancyindex_entry_t *entry;
377
int (*sort_cmp_func) (const void*, const void*);
378
const char *sort_url_args = "";
368
381
size_t len, root, copy, allocated;
369
382
u_char *filename, *last, scale;
556
570
* is stripped out:
559
* <td><a href="U">fname</a></td>
573
* <td><a href="U[?sort]">fname</a></td>
560
574
* <td>size</td><td>date</td>
563
577
len += ngx_sizeof_ssz("<tr class=\"X\"><td><a href=\"")
564
578
+ entry[i].name.len + entry[i].escape /* Escaped URL */
579
+ ngx_sizeof_ssz("?C=x&O=y") /* URL sorting arguments */
565
580
+ ngx_sizeof_ssz("\">")
566
581
+ entry[i].name.len + entry[i].utf_len
567
582
+ NGX_HTTP_FANCYINDEX_NAME_LEN + ngx_sizeof_ssz(">")
577
592
if ((b = ngx_create_temp_buf(r->pool, len)) == NULL)
578
593
return NGX_HTTP_INTERNAL_SERVER_ERROR;
596
* Determine the sorting criteria. URL arguments look like:
600
* Where x={M,S,N} and y={A,D}
602
if ((r->args.len == 3 || (r->args.len == 7 && r->args.data[3] == '&')) &&
603
r->args.data[0] == 'C' && r->args.data[1] == '=')
605
/* Determine whether the direction of the sorting */
606
ngx_int_t sort_descending = r->args.len == 7
607
&& r->args.data[4] == 'O'
608
&& r->args.data[5] == '='
609
&& r->args.data[6] == 'D';
611
/* Pick the sorting criteria */
612
switch (r->args.data[2]) {
613
case 'M': /* Sort by mtime */
614
if (sort_descending) {
615
sort_cmp_func = ngx_http_fancyindex_cmp_entries_mtime_desc;
616
sort_url_args = "?C=M&O=D";
619
sort_cmp_func = ngx_http_fancyindex_cmp_entries_mtime_asc;
620
sort_url_args = "?C=M&O=A";
623
case 'S': /* Sort by size */
624
if (sort_descending) {
625
sort_cmp_func = ngx_http_fancyindex_cmp_entries_size_desc;
626
sort_url_args = "?C=S&O=D";
629
sort_cmp_func = ngx_http_fancyindex_cmp_entries_size_asc;
630
sort_url_args = "?C=S&O=A";
633
case 'N': /* Sort by name */
635
if (sort_descending) {
636
sort_cmp_func = ngx_http_fancyindex_cmp_entries_name_desc;
637
sort_url_args = "?C=N&O=D";
640
sort_cmp_func = ngx_http_fancyindex_cmp_entries_name_asc;
646
sort_cmp_func = ngx_http_fancyindex_cmp_entries_name_asc;
580
649
/* Sort entries, if needed */
581
650
if (entries.nelts > 1) {
582
651
ngx_qsort(entry, (size_t) entries.nelts,
583
sizeof(ngx_http_fancyindex_entry_t),
584
ngx_http_fancyindex_cmp_entries);
652
sizeof(ngx_http_fancyindex_entry_t),
587
656
b->last = ngx_cpymem_str(b->last, r->uri);
591
660
tp = ngx_timeofday();
662
/* "Parent dir" entry, always first */
663
b->last = ngx_cpymem_ssz(b->last,
665
"<td><a href=\"../");
666
if (*sort_url_args) {
667
b->last = ngx_cpymem(b->last,
669
ngx_sizeof_ssz("?C=N&O=A"));
671
b->last = ngx_cpymem_ssz(b->last,
672
"\">Parent directory/</a></td>"
677
/* Entries for directories and files */
593
678
for (i = 0; i < entries.nelts; i++) {
594
679
static const char _evenodd[] = { 'e', 'o' };
595
680
b->last = ngx_cpymem_ssz(b->last, "<tr class=\"");
900
990
static int ngx_libc_cdecl
901
ngx_http_fancyindex_cmp_entries(const void *one, const void *two)
903
ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
904
ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two;
906
if (first->dir && !second->dir) {
907
/* move the directories to the start */
911
if (!first->dir && second->dir) {
912
/* move the directories to the start */
991
ngx_http_fancyindex_cmp_entries_name_desc(const void *one, const void *two)
993
ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
994
ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two;
996
/* move the directories to the start */
997
if (first->dir && !second->dir) {
1000
if (!first->dir && second->dir) {
1004
return (int) ngx_strcmp(second->name.data, first->name.data);
1008
static int ngx_libc_cdecl
1009
ngx_http_fancyindex_cmp_entries_size_desc(const void *one, const void *two)
1011
ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
1012
ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two;
1014
/* move the directories to the start */
1015
if (first->dir && !second->dir) {
1018
if (!first->dir && second->dir) {
1022
return second->size - first->size;
1026
static int ngx_libc_cdecl
1027
ngx_http_fancyindex_cmp_entries_mtime_desc(const void *one, const void *two)
1029
ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
1030
ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two;
1032
/* move the directories to the start */
1033
if (first->dir && !second->dir) {
1036
if (!first->dir && second->dir) {
1040
return second->mtime - first->mtime;
1044
static int ngx_libc_cdecl
1045
ngx_http_fancyindex_cmp_entries_name_asc(const void *one, const void *two)
1047
ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
1048
ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two;
1050
/* move the directories to the start */
1051
if (first->dir && !second->dir) {
1054
if (!first->dir && second->dir) {
1062
static int ngx_libc_cdecl
1063
ngx_http_fancyindex_cmp_entries_size_asc(const void *one, const void *two)
1065
ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
1066
ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two;
1068
/* move the directories to the start */
1069
if (first->dir && !second->dir) {
1072
if (!first->dir && second->dir) {
1076
return first->size - second->size;
1080
static int ngx_libc_cdecl
1081
ngx_http_fancyindex_cmp_entries_mtime_asc(const void *one, const void *two)
1083
ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
1084
ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two;
1086
/* move the directories to the start */
1087
if (first->dir && !second->dir) {
1090
if (!first->dir && second->dir) {
1094
return first->mtime - second->mtime;
922
1098
static ngx_int_t