From bc603764331d643993f5e857a44f83a845b512f4 Mon Sep 17 00:00:00 2001 From: Mamadou Lamine NIANG Date: Fri, 22 Jan 2021 23:56:04 +0000 Subject: [PATCH 1/2] Add case-insensitive name sorting support Add the fancyindex_case_sensitive option which considers the case when sorting by name if it is on (which it is by default to keep current behavior) and does a case-insensitive name sort if it is off. Closes #78 Closes #124 Co-authored-by: Ryan Schmidt --- README.rst | 9 ++++++ ngx_http_fancyindex_module.c | 58 +++++++++++++++++++++++++++++++----- 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/README.rst b/README.rst index fbe76c0..d16380e 100644 --- a/README.rst +++ b/README.rst @@ -149,6 +149,15 @@ fancyindex_default_sort :Description: Defines sorting criterion by default. +fancyindex_case_sensitive +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +:Syntax: *fancyindex_case_sensitive* [*on* | *off*] +:Default: fancyindex_case_sensitive on +:Context: http, server, location +:Description: + If enabled (default setting), sorting by name will be case-sensitive. + If disabled, case will be ignored when sorting by name. + fancyindex_directories_first ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :Syntax: *fancyindex_directories_first* [*on* | *off*] diff --git a/ngx_http_fancyindex_module.c b/ngx_http_fancyindex_module.c index bfccdc8..a62ae3f 100644 --- a/ngx_http_fancyindex_module.c +++ b/ngx_http_fancyindex_module.c @@ -152,6 +152,7 @@ typedef struct { typedef struct { ngx_flag_t enable; /**< Module is enabled. */ ngx_uint_t default_sort; /**< Default sort criterion. */ + ngx_flag_t case_sensitive; /**< Case-sensitive name sorting */ ngx_flag_t dirs_first; /**< Group directories together first when sorting */ ngx_flag_t localtime; /**< File mtime dates are sent in local time. */ ngx_flag_t exact_size; /**< Sizes are sent always in bytes. */ @@ -336,13 +337,17 @@ typedef struct { static int ngx_libc_cdecl - ngx_http_fancyindex_cmp_entries_name_desc(const void *one, const void *two); + ngx_http_fancyindex_cmp_entries_name_cs_desc(const void *one, const void *two); +static int ngx_libc_cdecl + ngx_http_fancyindex_cmp_entries_name_ci_desc(const void *one, const void *two); static int ngx_libc_cdecl ngx_http_fancyindex_cmp_entries_size_desc(const void *one, const void *two); static int ngx_libc_cdecl 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); + ngx_http_fancyindex_cmp_entries_name_cs_asc(const void *one, const void *two); +static int ngx_libc_cdecl + ngx_http_fancyindex_cmp_entries_name_ci_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 @@ -391,6 +396,13 @@ static ngx_command_t ngx_http_fancyindex_commands[] = { offsetof(ngx_http_fancyindex_loc_conf_t, default_sort), &ngx_http_fancyindex_sort_criteria }, + { ngx_string("fancyindex_case_sensitive"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_fancyindex_loc_conf_t, case_sensitive), + NULL }, + { ngx_string("fancyindex_directories_first"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -950,12 +962,16 @@ make_content_buf( case 'N': /* Sort by name */ default: if (sort_descending) { - sort_cmp_func = ngx_http_fancyindex_cmp_entries_name_desc; + sort_cmp_func = alcf->case_sensitive + ? ngx_http_fancyindex_cmp_entries_name_cs_desc + : ngx_http_fancyindex_cmp_entries_name_ci_desc; if (alcf->default_sort != NGX_HTTP_FANCYINDEX_SORT_CRITERION_NAME_DESC) sort_url_args = "?C=N&O=D"; } else { - sort_cmp_func = ngx_http_fancyindex_cmp_entries_name_asc; + sort_cmp_func = alcf->case_sensitive + ? ngx_http_fancyindex_cmp_entries_name_cs_asc + : ngx_http_fancyindex_cmp_entries_name_ci_asc; if (alcf->default_sort != NGX_HTTP_FANCYINDEX_SORT_CRITERION_NAME) sort_url_args = "?C=N&O=A"; } @@ -977,11 +993,15 @@ make_content_buf( sort_cmp_func = ngx_http_fancyindex_cmp_entries_size_asc; break; case NGX_HTTP_FANCYINDEX_SORT_CRITERION_NAME_DESC: - sort_cmp_func = ngx_http_fancyindex_cmp_entries_name_desc; + sort_cmp_func = alcf->case_sensitive + ? ngx_http_fancyindex_cmp_entries_name_cs_desc + : ngx_http_fancyindex_cmp_entries_name_ci_desc; break; case NGX_HTTP_FANCYINDEX_SORT_CRITERION_NAME: default: - sort_cmp_func = ngx_http_fancyindex_cmp_entries_name_asc; + sort_cmp_func = alcf->case_sensitive + ? ngx_http_fancyindex_cmp_entries_name_cs_asc + : ngx_http_fancyindex_cmp_entries_name_ci_asc; break; } } @@ -1337,7 +1357,7 @@ ngx_http_fancyindex_handler(ngx_http_request_t *r) static int ngx_libc_cdecl -ngx_http_fancyindex_cmp_entries_name_desc(const void *one, const void *two) +ngx_http_fancyindex_cmp_entries_name_cs_desc(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; @@ -1346,6 +1366,16 @@ ngx_http_fancyindex_cmp_entries_name_desc(const void *one, const void *two) } +static int ngx_libc_cdecl +ngx_http_fancyindex_cmp_entries_name_ci_desc(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; + + return (int) ngx_strcasecmp(second->name.data, first->name.data); +} + + static int ngx_libc_cdecl ngx_http_fancyindex_cmp_entries_size_desc(const void *one, const void *two) { @@ -1367,7 +1397,7 @@ 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) +ngx_http_fancyindex_cmp_entries_name_cs_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; @@ -1376,6 +1406,16 @@ ngx_http_fancyindex_cmp_entries_name_asc(const void *one, const void *two) } +static int ngx_libc_cdecl +ngx_http_fancyindex_cmp_entries_name_ci_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; + + return (int) ngx_strcasecmp(first->name.data, second->name.data); +} + + static int ngx_libc_cdecl ngx_http_fancyindex_cmp_entries_size_asc(const void *one, const void *two) { @@ -1431,6 +1471,7 @@ ngx_http_fancyindex_create_loc_conf(ngx_conf_t *cf) */ conf->enable = NGX_CONF_UNSET; conf->default_sort = NGX_CONF_UNSET_UINT; + conf->case_sensitive = NGX_CONF_UNSET; conf->dirs_first = NGX_CONF_UNSET; conf->localtime = NGX_CONF_UNSET; conf->exact_size = NGX_CONF_UNSET; @@ -1454,6 +1495,7 @@ ngx_http_fancyindex_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->enable, prev->enable, 0); ngx_conf_merge_uint_value(conf->default_sort, prev->default_sort, NGX_HTTP_FANCYINDEX_SORT_CRITERION_NAME); + ngx_conf_merge_value(conf->case_sensitive, prev->case_sensitive, 1); ngx_conf_merge_value(conf->dirs_first, prev->dirs_first, 1); ngx_conf_merge_value(conf->localtime, prev->localtime, 0); ngx_conf_merge_value(conf->exact_size, prev->exact_size, 1); From 29b9eb437937e4d89feed117bd4f5c5d34c961cf Mon Sep 17 00:00:00 2001 From: Ryan Schmidt Date: Fri, 3 Jun 2022 16:29:38 -0500 Subject: [PATCH 2/2] Add tests for case-(in)sensitive sorting --- t/bug78-case-insensitive.test | 8 ++++++++ t/bug78-case-sensitive.test | 8 ++++++++ t/case-sensitivity/Bob | 0 t/case-sensitivity/alice | 0 4 files changed, 16 insertions(+) create mode 100644 t/bug78-case-insensitive.test create mode 100644 t/bug78-case-sensitive.test create mode 100644 t/case-sensitivity/Bob create mode 100644 t/case-sensitivity/alice diff --git a/t/bug78-case-insensitive.test b/t/bug78-case-insensitive.test new file mode 100644 index 0000000..5943075 --- /dev/null +++ b/t/bug78-case-insensitive.test @@ -0,0 +1,8 @@ +#! /bin/bash +cat <<--- +This test checks that case-insensitive sorting works. +-- + +nginx_start 'fancyindex_case_sensitive off;' +content=$(fetch /case-sensitivity/) +grep -A 999 '\' <<< "${content}" | grep '\' # Bob is after alice diff --git a/t/bug78-case-sensitive.test b/t/bug78-case-sensitive.test new file mode 100644 index 0000000..ff9037d --- /dev/null +++ b/t/bug78-case-sensitive.test @@ -0,0 +1,8 @@ +#! /bin/bash +cat <<--- +This test checks that case-sensitive sorting works. +-- + +nginx_start 'fancyindex_case_sensitive on;' +content=$(fetch /case-sensitivity/) +grep -A 999 '\' <<< "${content}" | grep '\' # alice is after Bob diff --git a/t/case-sensitivity/Bob b/t/case-sensitivity/Bob new file mode 100644 index 0000000..e69de29 diff --git a/t/case-sensitivity/alice b/t/case-sensitivity/alice new file mode 100644 index 0000000..e69de29