From cbc0d3fca4f06414612de441399393d4b3bbb315 Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Fri, 20 Jan 2023 15:28:42 +0200 Subject: [PATCH 01/10] CI: Update mainline and stable Nginx versions for testing --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 62c8827..374487e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,9 +11,9 @@ jobs: compiler: [gcc, clang] nginx: # Mainline - - 1.21.6 + - 1.23.3 # Stable. - - 1.20.2 + - 1.22.1 # First version with loadable module support. - 1.9.15 # Oldest supported version. From f31b92df37cf580d83b36de8abf7a83477d7b85c Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Wed, 13 Mar 2024 13:07:39 +0100 Subject: [PATCH 02/10] feat: use caddy template --- compile_flags.txt | 13 + ngx_http_fancyindex_module.c | 73 ++- t/README.txt | 1 + ...isFilenameIsMuchLongerThan20CharsMoreWords | 0 t/child-directory/c2/c3/empty-file.txt | 0 template.h | 452 ++++++++++++--- template.html | 519 +++++++++++++++--- 7 files changed, 895 insertions(+), 163 deletions(-) create mode 100644 compile_flags.txt create mode 100644 t/README.txt create mode 100644 t/ThisFilenameIsMuchLongerThan20CharsMoreWordsThisFilenameIsMuchLongerThan20CharsMoreWordsThisFilenameIsMuchLongerThan20CharsMoreWords create mode 100644 t/child-directory/c2/c3/empty-file.txt diff --git a/compile_flags.txt b/compile_flags.txt new file mode 100644 index 0000000..66cc1f9 --- /dev/null +++ b/compile_flags.txt @@ -0,0 +1,13 @@ +-I/home/thetadev/test/ngx-fancyindex/nginx-1.25.4/src/core +-I/home/thetadev/test/ngx-fancyindex/nginx-1.25.4/src/event +-I/home/thetadev/test/ngx-fancyindex/nginx-1.25.4/src/event/quic +-I/home/thetadev/test/ngx-fancyindex/nginx-1.25.4/src/event/modules +-I/home/thetadev/test/ngx-fancyindex/nginx-1.25.4/src/http +-I/home/thetadev/test/ngx-fancyindex/nginx-1.25.4/src/http/v2 +-I/home/thetadev/test/ngx-fancyindex/nginx-1.25.4/src/http/v3 +-I/home/thetadev/test/ngx-fancyindex/nginx-1.25.4/src/http/modules +-I/home/thetadev/test/ngx-fancyindex/nginx-1.25.4/src/mail +-I/home/thetadev/test/ngx-fancyindex/nginx-1.25.4/src/misc +-I/home/thetadev/test/ngx-fancyindex/nginx-1.25.4/src/os/unix +-I/home/thetadev/test/ngx-fancyindex/nginx-1.25.4/src/stream +-I/home/thetadev/test/ngx-fancyindex/nginx-1.25.4/objs diff --git a/ngx_http_fancyindex_module.c b/ngx_http_fancyindex_module.c index d523656..76fdffa 100644 --- a/ngx_http_fancyindex_module.c +++ b/ngx_http_fancyindex_module.c @@ -24,6 +24,7 @@ #include #include +#include "ngx_string.h" #include "template.h" #if defined(__GNUC__) && (__GNUC__ >= 3) @@ -330,6 +331,7 @@ typedef struct { ngx_uint_t escape; ngx_uint_t escape_html; ngx_uint_t dir; + ngx_uint_t link; time_t mtime; off_t size; } ngx_http_fancyindex_entry_t; @@ -353,6 +355,8 @@ static int ngx_libc_cdecl static int ngx_libc_cdecl ngx_http_fancyindex_cmp_entries_mtime_asc(const void *one, const void *two); +static size_t ngx_http_fancyindex_num_places (size_t n); + static ngx_int_t ngx_http_fancyindex_error(ngx_http_request_t *r, ngx_dir_t *dir, ngx_str_t *name); @@ -673,7 +677,7 @@ make_content_buf( const char *sort_url_args = ""; off_t length; - size_t len, root, allocated, escape_html; + size_t len, root, allocated, escape_html, n_files, n_dirs=0; int64_t multiplier; u_char *filename, *last; ngx_tm_t tm; @@ -845,14 +849,19 @@ make_content_buf( entry->name.len); entry->dir = ngx_de_is_dir(&dir); + entry->link = ngx_de_is_link(&dir); entry->mtime = ngx_de_mtime(&dir); entry->size = ngx_de_size(&dir); entry->utf_len = (r->headers_out.charset.len == 5 && ngx_strncasecmp(r->headers_out.charset.data, (u_char*) "utf-8", 5) == 0) ? ngx_utf8_length(entry->name.data, entry->name.len) : len; + + if (entry->dir) n_dirs += 1; } + n_files = entries.size - n_dirs; + if (ngx_close_dir(&dir) == NGX_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_close_dir_n " \"%s\" failed", &path); @@ -868,17 +877,20 @@ make_content_buf( len = r->uri.len + escape_html + ngx_sizeof_ssz(t05_body2) + ngx_sizeof_ssz(t06_list1) + + ngx_sizeof_ssz(t06_list2) + + ngx_sizeof_ssz(t06_list3) + ngx_sizeof_ssz(t_parentdir_entry) - + ngx_sizeof_ssz(t07_list2) - + ngx_fancyindex_timefmt_calc_size (&alcf->time_format) * entries.nelts - ; - else + + ngx_sizeof_ssz(t07_list2); + else len = r->uri.len + escape_html + ngx_sizeof_ssz(t06_list1) + + ngx_sizeof_ssz(t06_list2) + + ngx_sizeof_ssz(t06_list3) + ngx_sizeof_ssz(t_parentdir_entry) - + ngx_sizeof_ssz(t07_list2) - + ngx_fancyindex_timefmt_calc_size (&alcf->time_format) * entries.nelts - ; + + ngx_sizeof_ssz(t07_list2); + len += ngx_fancyindex_timefmt_calc_size (&alcf->time_format) * entries.nelts + + ngx_http_fancyindex_num_places(n_dirs) + + ngx_http_fancyindex_num_places(n_files); /* * If we are a the root of the webserver (URI = "/" --> length of 1), @@ -899,19 +911,24 @@ make_content_buf( * sizedate * */ - len += ngx_sizeof_ssz("") + + ngx_sizeof_ssz("") + entry[i].name.len + entry[i].utf_len + entry[i].escape_html - + ngx_sizeof_ssz("") + + ngx_sizeof_ssz("") + 20 /* File size */ - + ngx_sizeof_ssz("") /* Date prefix */ + + ngx_sizeof_ssz("") /* Date prefix */ + ngx_sizeof_ssz("\n") /* Date suffix */ + 2 /* CR LF */ ; + if (entry[i].dir) len += ngx_sizeof_ssz("folder"); + else len += ngx_sizeof_ssz("file"); + if (entry[i].link) len += ngx_sizeof_ssz("-shortcut"); } if ((b = ngx_create_temp_buf(r->pool, len)) == NULL) @@ -1053,6 +1070,10 @@ make_content_buf( /* Open the tag */ b->last = ngx_cpymem_ssz(b->last, t06_list1); + b->last = ngx_sprintf(b->last, "%d", n_dirs); + b->last = ngx_cpymem_ssz(b->last, t06_list2); + b->last = ngx_sprintf(b->last, "%d", n_files); + b->last = ngx_cpymem_ssz(b->last, t06_list3); tp = ngx_timeofday(); @@ -1060,23 +1081,23 @@ make_content_buf( if (r->uri.len > 1 && alcf->hide_parent == 0) { b->last = ngx_cpymem_ssz(b->last, "" - "" - "" - "" + "\">Parent directory/" + "" + "" "" CRLF); } /* Entries for directories and files */ for (i = 0; i < entries.nelts; i++) { - b->last = ngx_cpymem_ssz(b->last, ""); @@ -1447,6 +1475,15 @@ ngx_http_fancyindex_error(ngx_http_request_t *r, ngx_dir_t *dir, ngx_str_t *name return NGX_HTTP_INTERNAL_SERVER_ERROR; } +static size_t ngx_http_fancyindex_num_places (size_t n) { + int r = 1; + while (n > 9) { + n /= 10; + r++; + } + return r; +} + static void * ngx_http_fancyindex_create_loc_conf(ngx_conf_t *cf) diff --git a/t/README.txt b/t/README.txt new file mode 100644 index 0000000..6cc9c44 --- /dev/null +++ b/t/README.txt @@ -0,0 +1 @@ +Hello World, this is me ;-) diff --git a/t/ThisFilenameIsMuchLongerThan20CharsMoreWordsThisFilenameIsMuchLongerThan20CharsMoreWordsThisFilenameIsMuchLongerThan20CharsMoreWords b/t/ThisFilenameIsMuchLongerThan20CharsMoreWordsThisFilenameIsMuchLongerThan20CharsMoreWordsThisFilenameIsMuchLongerThan20CharsMoreWords new file mode 100644 index 0000000..e69de29 diff --git a/t/child-directory/c2/c3/empty-file.txt b/t/child-directory/c2/c3/empty-file.txt new file mode 100644 index 0000000..e69de29 diff --git a/template.h b/template.h index 02ba908..d771f1f 100644 --- a/template.h +++ b/template.h @@ -2,91 +2,415 @@ static const u_char t01_head1[] = "" "" "" -"" -"" -"" -"" +" " +" " +" " +" " "\n" ; static const u_char t02_head2[] = "" "\n" -"Index of " +" <title>Index of" ; static const u_char t03_head3[] = "" "" -"\n" "" ; static const u_char t04_body1[] = "" -"" -"

Index of " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +"
" +"

" ; static const u_char t05_body2[] = "" -"

" -"\n" +"

" ; static const u_char t06_list1[] = "" -"
last = ngx_cpymem(b->last, sort_url_args, ngx_sizeof_ssz("?C=N&O=A")); } b->last = ngx_cpymem_ssz(b->last, - "\">Parent directory/--
last = ngx_cpymem_ssz(b->last, "
last, @@ -1103,6 +1124,13 @@ make_content_buf( b->last = (u_char *) ngx_escape_html(b->last, entry[i].name.data, entry[i].name.len); *b->last++ = '"'; *b->last++ = '>'; + b->last = ngx_cpymem_ssz(b->last, "last = ngx_cpymem_ssz(b->last, "folder"); + else b->last = ngx_cpymem_ssz(b->last, "file"); + if (entry[i].link) b->last = ngx_cpymem_ssz(b->last, "-shortcut"); + + b->last = ngx_cpymem_ssz(b->last, "\">"); len = entry[i].utf_len; @@ -1114,7 +1142,7 @@ make_content_buf( len++; } - b->last = ngx_cpymem_ssz(b->last, ""); + b->last = ngx_cpymem_ssz(b->last, ""); if (alcf->exact_size) { if (entry[i].dir) { @@ -1143,7 +1171,7 @@ make_content_buf( } ngx_gmtime(entry[i].mtime + tp->gmtoff * 60 * alcf->localtime, &tm); - b->last = ngx_cpymem_ssz(b->last, ""); + b->last = ngx_cpymem_ssz(b->last, ""); b->last = ngx_fancyindex_timefmt(b->last, &alcf->time_format, &tm); b->last = ngx_cpymem_ssz(b->last, "
" -"" -"" -"" -"" -"" -"" -"" +" " +"
" +"
" +"
" +" " +; +static const u_char t06_list2[] = "" +" directories" +"" +; +static const u_char t06_list3[] = "" +" files" +" " +"
" +"
" +"
" +"
File Name  ↓ File Size  ↓ Date  ↓ 
" +" " +" " +" " +" " +" " +" " +" " "\n" -"" +" " ; static const u_char t_parentdir_entry[] = "" -"" -"" -"" -"" -"" +" " +" " +" " +" " +" " "\n" ; static const u_char t07_list2[] = "" -"" -"
" +" Size  ↓ " +" " +" Size  ↓ " +" " +" Modified  ↓ " +"
Parent directory/--
" +" " +" Parent directory" +" " +"
" +" " +" " +" " +" " +"\n" ; static const u_char t08_foot1[] = "" -"" +"
" +"

Powered by Nginx

" +"
" +" " +" " "" ; #define NFI_TEMPLATE_SIZE (0 \ @@ -96,6 +420,8 @@ static const u_char t08_foot1[] = "" + nfi_sizeof_ssz(t04_body1) \ + nfi_sizeof_ssz(t05_body2) \ + nfi_sizeof_ssz(t06_list1) \ + + nfi_sizeof_ssz(t06_list2) \ + + nfi_sizeof_ssz(t06_list3) \ + nfi_sizeof_ssz(t_parentdir_entry) \ + nfi_sizeof_ssz(t07_list2) \ + nfi_sizeof_ssz(t08_foot1) \ diff --git a/template.html b/template.html index b2f521b..cb359c2 100644 --- a/template.html +++ b/template.html @@ -1,101 +1,456 @@ - - - - + + + + - Index of + <title>Index of <!-- var NONE --> - /path/to/somewhere +/path/to/somewhere <!-- var t03_head3 --> - - - + + - -

Index of + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

- /path/to/somewhere +/path/to/somewhere -

- +

- - - - - - - - + +
+
+
+ + +13 + + directories + + +5 + + files + +
+
+
+
File Name  ↓ File Size  ↓ Date  ↓ 
+ + + + + + + - + - - - - - + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - -
+ Size  ↓  + + Size  ↓  + + Modified  ↓  +
--
+ + Parent directory + +
test file 1123kBdate
test file 2321MBdate
test file 3666date
+ + + test folder/ + + date
+ + + test file 1 + + date
+ + + + + test file 2 + + date
+ + + + + test file 3 + + date
+ + + + + - + + + From 8ec3c8bdfdcb833b0bae1b5e785f237ee2da51a2 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Wed, 13 Mar 2024 16:17:45 +0100 Subject: [PATCH 03/10] feat: clickable path display --- ngx_http_fancyindex_module.c | 63 +++++++++++++++++++++++++----------- template.h | 18 ++++++----- template.html | 27 +++++++++------- 3 files changed, 69 insertions(+), 39 deletions(-) diff --git a/ngx_http_fancyindex_module.c b/ngx_http_fancyindex_module.c index 76fdffa..deaba70 100644 --- a/ngx_http_fancyindex_module.c +++ b/ngx_http_fancyindex_module.c @@ -677,7 +677,7 @@ make_content_buf( const char *sort_url_args = ""; off_t length; - size_t len, root, allocated, escape_html, n_files, n_dirs=0; + size_t len, root, allocated, n_files, n_dirs=0; int64_t multiplier; u_char *filename, *last; ngx_tm_t tm; @@ -849,7 +849,7 @@ make_content_buf( entry->name.len); entry->dir = ngx_de_is_dir(&dir); - entry->link = ngx_de_is_link(&dir); + entry->link = ngx_de_is_link(&dir); entry->mtime = ngx_de_mtime(&dir); entry->size = ngx_de_size(&dir); entry->utf_len = (r->headers_out.charset.len == 5 && @@ -871,27 +871,35 @@ make_content_buf( * Calculate needed buffer length. */ - escape_html = ngx_escape_html(NULL, r->uri.data, r->uri.len); - - if (alcf->show_path) - len = r->uri.len + escape_html - + ngx_sizeof_ssz(t05_body2) - + ngx_sizeof_ssz(t06_list1) + len = ngx_sizeof_ssz(t06_list1) + ngx_sizeof_ssz(t06_list2) + ngx_sizeof_ssz(t06_list3) + ngx_sizeof_ssz(t_parentdir_entry) - + ngx_sizeof_ssz(t07_list2); - else - len = r->uri.len + escape_html - + ngx_sizeof_ssz(t06_list1) - + ngx_sizeof_ssz(t06_list2) - + ngx_sizeof_ssz(t06_list3) - + ngx_sizeof_ssz(t_parentdir_entry) - + ngx_sizeof_ssz(t07_list2); - len += ngx_fancyindex_timefmt_calc_size (&alcf->time_format) * entries.nelts + + ngx_sizeof_ssz(t07_list2) + + ngx_fancyindex_timefmt_calc_size (&alcf->time_format) * entries.nelts + ngx_http_fancyindex_num_places(n_dirs) + ngx_http_fancyindex_num_places(n_files); + if (alcf->show_path) { + len += ngx_sizeof_ssz(t05_body2) + + ngx_sizeof_ssz("

/") + + ngx_sizeof_ssz("

") + + ngx_sizeof_ssz(t05_body3); + + ngx_uint_t last_slash = 0; + for (i = 1; i < r->uri.len; i++) { + u_char c = r->uri.data[i]; + if (c == '/') { + len += ngx_sizeof_ssz("") + + ngx_sizeof_ssz("/") + + ngx_escape_uri(NULL, r->uri.data, i, NGX_ESCAPE_URI) + + ngx_escape_html(NULL, r->uri.data + last_slash + 1, i - last_slash - 1); + last_slash = i; + } + } + } + /* * If we are a the root of the webserver (URI = "/" --> length of 1), * do not display the "Parent Directory" link. @@ -1063,9 +1071,26 @@ make_content_buf( } /* Display the path, if needed */ - if (alcf->show_path){ - b->last = last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len); + if (alcf->show_path) { b->last = ngx_cpymem_ssz(b->last, t05_body2); + b->last = ngx_cpymem_ssz(b->last, "

/"); + + ngx_uint_t last_slash = 0; + for (i = 1; i < r->uri.len; i++) { + u_char c = r->uri.data[i]; + if (c == '/') { + b->last = ngx_cpymem_ssz(b->last, "last = (u_char *) ngx_escape_uri(b->last, r->uri.data, i, NGX_ESCAPE_URI); + b->last = ngx_cpymem_ssz(b->last, "\">"); + b->last = (u_char *) ngx_escape_html(b->last, r->uri.data + last_slash + 1, i - last_slash - 1); + b->last = ngx_cpymem_ssz(b->last, "/"); + + last_slash = i; + } + } + + b->last = ngx_cpymem_ssz(b->last, "

"); + b->last = ngx_cpymem_ssz(b->last, t05_body3); } /* Open the tag */ diff --git a/template.h b/template.h index d771f1f..1a73f0b 100644 --- a/template.h +++ b/template.h @@ -28,6 +28,9 @@ static const u_char t01_head1[] = "" " padding: 0 20px;" " }" " header {" +" display: flex;" +" flex-direction: row;" +" gap: 1em;" " padding-top: 25px;" " padding-bottom: 15px;" " background-color: #f2f2f2;" @@ -178,11 +181,9 @@ static const u_char t01_head1[] = "" " }" " }" " " -"\n" ; static const u_char t02_head2[] = "" -"\n" -" Index of" +"<title> " ; static const u_char t03_head3[] = "" "" @@ -287,14 +288,14 @@ static const u_char t04_body1[] = "" " " " " " " -"
" -"

" ; static const u_char t05_body2[] = "" -"

" +"
" +; +static const u_char t05_body3[] = "" +"
" ; static const u_char t06_list1[] = "" -"
" "
" "
" "
" @@ -356,7 +357,7 @@ static const u_char t07_list2[] = "" ; static const u_char t08_foot1[] = "" " " "