Project

General

Profile

Feature #613 » mod_dirlist_sorting.patch

patch for client-selectable directory list sorting - mcosby, 2007-12-30 14:33

View differences:

lighttpd-1.4.18/src/mod_dirlisting.c 2007-12-30 09:28:21.000000000 -0500
22 22
 * this is a dirlisting for a lighttpd plugin
23 23
 */
24 24

  
25
// you can't change these values without changing
26
// the constant strings in http_list_directory_header()
27
#define SORT_MIN 1
28
#define SORT_ALPHA 1
29
#define SORT_MODIFIED 2
30
#define SORT_SIZE 3
31
#define SORT_MAX 3
32

  
33
#define SORT_DIR_MIN 1
34
#define SORT_DIR_ASC 1
35
#define SORT_DIR_DESC 2
36
#define SORT_DIR_MAX 2
37

  
25 38

  
26 39
#ifdef HAVE_SYS_SYSLIMITS_H
27 40
#include <sys/syslimits.h>
......
384 397
#define DIRLIST_BLOB_SIZE		16
385 398

  
386 399
/* simple combsort algorithm */
387
static void http_dirls_sort(dirls_entry_t **ent, int num) {
400
static void http_dirls_sort(dirls_entry_t **ent, int num, int type, int dir) {
388 401
	int gap = num;
389 402
	int i, j;
390 403
	int swapped;
404
	int res;
391 405
	dirls_entry_t *tmp;
392 406

  
393 407
	do {
......
400 414

  
401 415
		for (i = 0; i < num - gap; i++) {
402 416
			j = i + gap;
403
			if (strcmp(DIRLIST_ENT_NAME(ent[i]), DIRLIST_ENT_NAME(ent[j])) > 0) {
404
				tmp = ent[i];
405
				ent[i] = ent[j];
406
				ent[j] = tmp;
407
				swapped = 1;
417
			if (type == SORT_ALPHA) {
418
				res = strcmp(DIRLIST_ENT_NAME(ent[i]), DIRLIST_ENT_NAME(ent[j]));
419
				if ((dir == SORT_DIR_ASC && res > 0) || 
420
					(dir == SORT_DIR_DESC && res < 0)) {
421
					tmp = ent[i];
422
					ent[i] = ent[j];
423
					ent[j] = tmp;
424
					swapped = 1;
425
				}
426
			} else if (type == SORT_MODIFIED) {
427
				if ((dir == SORT_DIR_ASC && ent[i]->mtime > ent[j]->mtime) ||
428
					(dir == SORT_DIR_DESC && ent[i]->mtime < ent[j]->mtime)) {
429
					tmp = ent[i];
430
					ent[i] = ent[j];
431
					ent[j] = tmp;
432
					swapped = 1;
433
				}
434
			} else if (type == SORT_SIZE) {
435
				if ((dir == SORT_DIR_ASC && ent[i]->size > ent[j]->size) ||
436
					(dir == SORT_DIR_DESC && ent[i]->size < ent[j]->size)) {
437
					tmp = ent[i];
438
					ent[i] = ent[j];
439
					ent[j] = tmp;
440
					swapped = 1;
441
				}
408 442
			}
409 443
		}
410 444

  
......
451 485
	return (out + 3 - buf);
452 486
}
453 487

  
454
static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out) {
488
static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out, int sort, int sort_dir) {
455 489
	UNUSED(srv);
490
	int sort_dir_rev;
456 491

  
492
	sort_dir_rev = SORT_DIR_ASC;
493
	if (sort_dir == SORT_DIR_ASC) sort_dir_rev = SORT_DIR_DESC;
494
	
457 495
	BUFFER_APPEND_STRING_CONST(out,
458 496
		"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
459 497
		"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n"
......
532 570
		"<table summary=\"Directory Listing\" cellpadding=\"0\" cellspacing=\"0\">\n"
533 571
		"<thead>"
534 572
		"<tr>"
535
			"<th class=\"n\">Name</th>"
536
			"<th class=\"m\">Last Modified</th>"
537
			"<th class=\"s\">Size</th>"
538
			"<th class=\"t\">Type</th>"
573
		"<th class=\"n\"><a href=\"?s=1&d="
574
	);
575
	if (sort == SORT_ALPHA) {
576
		buffer_append_long(out, sort_dir_rev);
577
	} else {
578
		buffer_append_long(out, sort_dir);
579
	}
580
	BUFFER_APPEND_STRING_CONST(out,
581
		"\">Name</th>"
582
		"<th class=\"m\"><a href=\"?s=2&d="
583
	);
584
	if (sort == SORT_MODIFIED) {
585
		buffer_append_long(out, sort_dir_rev);
586
	} else {
587
		buffer_append_long(out, SORT_DIR_DESC);
588
	}
589
	BUFFER_APPEND_STRING_CONST(out,
590
		"\">Last Modified</th>"
591
		"<th class=\"s\"><a href=\"?s=3&d="
592
	);
593
	if (sort == SORT_SIZE) {
594
		buffer_append_long(out, sort_dir_rev);
595
	} else {
596
		buffer_append_long(out, sort_dir);
597
	}
598
	BUFFER_APPEND_STRING_CONST(out,
599
		"\">Size</th>"
600
		"<th class=\"t\">Type</th>"
601
	);
602
	BUFFER_APPEND_STRING_CONST(out,
539 603
		"</tr>"
540 604
		"</thead>\n"
541 605
		"<tbody>\n"
......
607 671
	size_t k;
608 672
	const char *content_type;
609 673
	long name_max;
674
	int sort_dir;
675
	int sort;
610 676
#ifdef HAVE_XATTR
611 677
	char attrval[128];
612 678
	int attrlen;
......
646 712
		return -1;
647 713
	}
648 714

  
715
	sort_dir = 0;
716
	sort = 0;
717
	if (!buffer_is_empty(con->uri.query)) {
718
		char *q;
719
		if ((q = strstr(con->uri.query->ptr, "s="))) {
720
			if (*(q+2) != 0) sort = atoi(q+2); 
721
		}
722
		if ((q = strstr(con->uri.query->ptr, "d="))) {
723
			if (*(q+2) != 0) sort_dir = atoi(q+2); 
724
		}
725
	}
726

  
727
	if ((sort_dir < SORT_DIR_MIN) || (sort_dir > SORT_DIR_MAX)) {
728
		sort_dir = SORT_DIR_ASC;
729
	}
730
	if ((sort < SORT_MIN) || (sort > SORT_MAX)) {
731
		sort = SORT_ALPHA;
732
	}
733

  
649 734
	dirs.ent   = (dirls_entry_t**) malloc(sizeof(dirls_entry_t*) * DIRLIST_BLOB_SIZE);
650 735
	assert(dirs.ent);
651 736
	dirs.size  = DIRLIST_BLOB_SIZE;
......
737 822
	}
738 823
	closedir(dp);
739 824

  
740
	if (dirs.used) http_dirls_sort(dirs.ent, dirs.used);
825
	if (dirs.used) {
826
		if (sort != SORT_SIZE) {
827
			http_dirls_sort(dirs.ent, dirs.used, sort, sort_dir );
828
		} else {
829
			http_dirls_sort(dirs.ent, dirs.used, SORT_ALPHA, SORT_DIR_DESC );
830
		}
831
	}
741 832

  
742
	if (files.used) http_dirls_sort(files.ent, files.used);
833
	if (files.used) http_dirls_sort(files.ent, files.used, sort, sort_dir );
743 834

  
744 835
	out = chunkqueue_get_append_buffer(con->write_queue);
745 836
	BUFFER_COPY_STRING_CONST(out, "<?xml version=\"1.0\" encoding=\"");
......
749 840
		buffer_append_string_buffer(out, p->conf.encoding);
750 841
	}
751 842
	BUFFER_APPEND_STRING_CONST(out, "\"?>\n");
752
	http_list_directory_header(srv, con, p, out);
843
	http_list_directory_header(srv, con, p, out, sort, sort_dir);
753 844

  
754 845
	/* directories */
755 846
	for (i = 0; i < dirs.used; i++) {
(1-1/2)