--- lighttpd-1.4.18-orig/src/mod_dirlisting.c 2007-08-18 08:25:52.000000000 -0400 +++ lighttpd-1.4.18/src/mod_dirlisting.c 2007-12-30 09:28:21.000000000 -0500 @@ -22,6 +22,19 @@ * this is a dirlisting for a lighttpd plugin */ +// you can't change these values without changing +// the constant strings in http_list_directory_header() +#define SORT_MIN 1 +#define SORT_ALPHA 1 +#define SORT_MODIFIED 2 +#define SORT_SIZE 3 +#define SORT_MAX 3 + +#define SORT_DIR_MIN 1 +#define SORT_DIR_ASC 1 +#define SORT_DIR_DESC 2 +#define SORT_DIR_MAX 2 + #ifdef HAVE_SYS_SYSLIMITS_H #include @@ -384,10 +397,11 @@ #define DIRLIST_BLOB_SIZE 16 /* simple combsort algorithm */ -static void http_dirls_sort(dirls_entry_t **ent, int num) { +static void http_dirls_sort(dirls_entry_t **ent, int num, int type, int dir) { int gap = num; int i, j; int swapped; + int res; dirls_entry_t *tmp; do { @@ -400,11 +414,31 @@ for (i = 0; i < num - gap; i++) { j = i + gap; - if (strcmp(DIRLIST_ENT_NAME(ent[i]), DIRLIST_ENT_NAME(ent[j])) > 0) { - tmp = ent[i]; - ent[i] = ent[j]; - ent[j] = tmp; - swapped = 1; + if (type == SORT_ALPHA) { + res = strcmp(DIRLIST_ENT_NAME(ent[i]), DIRLIST_ENT_NAME(ent[j])); + if ((dir == SORT_DIR_ASC && res > 0) || + (dir == SORT_DIR_DESC && res < 0)) { + tmp = ent[i]; + ent[i] = ent[j]; + ent[j] = tmp; + swapped = 1; + } + } else if (type == SORT_MODIFIED) { + if ((dir == SORT_DIR_ASC && ent[i]->mtime > ent[j]->mtime) || + (dir == SORT_DIR_DESC && ent[i]->mtime < ent[j]->mtime)) { + tmp = ent[i]; + ent[i] = ent[j]; + ent[j] = tmp; + swapped = 1; + } + } else if (type == SORT_SIZE) { + if ((dir == SORT_DIR_ASC && ent[i]->size > ent[j]->size) || + (dir == SORT_DIR_DESC && ent[i]->size < ent[j]->size)) { + tmp = ent[i]; + ent[i] = ent[j]; + ent[j] = tmp; + swapped = 1; + } } } @@ -451,9 +485,13 @@ return (out + 3 - buf); } -static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out) { +static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out, int sort, int sort_dir) { UNUSED(srv); + int sort_dir_rev; + sort_dir_rev = SORT_DIR_ASC; + if (sort_dir == SORT_DIR_ASC) sort_dir_rev = SORT_DIR_DESC; + BUFFER_APPEND_STRING_CONST(out, "\n" "\n" @@ -532,10 +570,36 @@ "\n" "" "" - "" - "" - "" - "" + "" + "" + "" + "" + ); + BUFFER_APPEND_STRING_CONST(out, "" "\n" "\n" @@ -607,6 +671,8 @@ size_t k; const char *content_type; long name_max; + int sort_dir; + int sort; #ifdef HAVE_XATTR char attrval[128]; int attrlen; @@ -646,6 +712,25 @@ return -1; } + sort_dir = 0; + sort = 0; + if (!buffer_is_empty(con->uri.query)) { + char *q; + if ((q = strstr(con->uri.query->ptr, "s="))) { + if (*(q+2) != 0) sort = atoi(q+2); + } + if ((q = strstr(con->uri.query->ptr, "d="))) { + if (*(q+2) != 0) sort_dir = atoi(q+2); + } + } + + if ((sort_dir < SORT_DIR_MIN) || (sort_dir > SORT_DIR_MAX)) { + sort_dir = SORT_DIR_ASC; + } + if ((sort < SORT_MIN) || (sort > SORT_MAX)) { + sort = SORT_ALPHA; + } + dirs.ent = (dirls_entry_t**) malloc(sizeof(dirls_entry_t*) * DIRLIST_BLOB_SIZE); assert(dirs.ent); dirs.size = DIRLIST_BLOB_SIZE; @@ -737,9 +822,15 @@ } closedir(dp); - if (dirs.used) http_dirls_sort(dirs.ent, dirs.used); + if (dirs.used) { + if (sort != SORT_SIZE) { + http_dirls_sort(dirs.ent, dirs.used, sort, sort_dir ); + } else { + http_dirls_sort(dirs.ent, dirs.used, SORT_ALPHA, SORT_DIR_DESC ); + } + } - if (files.used) http_dirls_sort(files.ent, files.used); + if (files.used) http_dirls_sort(files.ent, files.used, sort, sort_dir ); out = chunkqueue_get_append_buffer(con->write_queue); BUFFER_COPY_STRING_CONST(out, "conf.encoding); } BUFFER_APPEND_STRING_CONST(out, "\"?>\n"); - http_list_directory_header(srv, con, p, out); + http_list_directory_header(srv, con, p, out, sort, sort_dir); /* directories */ for (i = 0; i < dirs.used; i++) {
NameLast ModifiedSizeTypeNameLast ModifiedSizeType