Compare commits

...

48 commits

Author SHA1 Message Date
Adrian Perez de Castro
cbc0d3fca4 CI: Update mainline and stable Nginx versions for testing 2023-01-20 15:31:11 +02:00
Ryan Schmidt
e5f227686a Add tests for case-(in)sensitive sorting 2023-01-20 15:26:16 +02:00
Mamadou Lamine NIANG
a634077b5f 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 <git@ryandesign.com>
2023-01-20 15:26:16 +02:00
Adrian Perez de Castro
674e99547d Add missing entry in long weekday names array
The entry for Saturday was missing, as pointed out in the bug report.
While at it, add a test case.

Fixes #157
2023-01-20 15:20:40 +02:00
Adrian Perez de Castro
1494521744 build-and-run: disable HTTP rewrite module
The HTTP rewrite module needs PCRE, which is not available in the GHA
MacOS runners. It is unused by the tests, so it's safe to disable
building it.
2023-01-20 13:59:17 +02:00
Danila Vershinin
f50d7b799f Update available distros with module package
Fedora Linux has packages available, removed linking to old NGINX module package version
2022-07-19 15:54:45 +03:00
Ryan Schmidt
860a9cbd5e CI: add macOS test runners 2022-06-05 01:02:12 +03:00
Ryan Schmidt
2346fa9bde CI: Update to latest mainline and stable nginx 2022-06-05 01:02:12 +03:00
Adrian Perez de Castro
823f162085
Use the BSD license consistently
The t/preamble file incorrectly mentioned the MIT license before.
While at it, use SPDX license identification headers.

Closes #149
2022-05-26 00:40:58 +03:00
Ryan Schmidt
98f824ef91 get-pup: Use a fork of pup on recent macOS
Use a fork of pup on macOS 10.13 and higher because the binary provided
by the original project crashes immediately on those OS versions.

See https://github.com/ericchiang/pup/issues/85
2022-05-25 23:58:46 +03:00
Ryan Schmidt
8efe0b01fa Tests: Make test 02 more specific
Test for an opening table tag instead of just the word "table".
2022-05-25 23:53:42 +03:00
Ryan Schmidt
e505eb2a13 Tests: Wait for nginx to create pid file
When nginx is started, it returns control before it has created its pid
file. Since this test suite relies on the existence of the pid file,
wait until the pid file exists before returning from nginx_start. Time
out after 2 seconds so that if there is a real problem starting nginx
we don't wait forever.

Fixes #144
2022-05-25 23:52:58 +03:00
Ryan Schmidt
778561eabf README.rst: Note MacPorts can install fancyindex 2022-05-25 23:52:14 +03:00
Ryan Schmidt
83bef5c8a6 Fix 404 not found when indexing filesystem root
Backport of 4c89c09ad8

Fixes #107
2022-05-25 23:51:27 +03:00
Ryan Schmidt
b9ecd5bcb4 Tests: Fix typos in descriptions and messages 2022-05-10 22:04:11 +03:00
Ryan Schmidt
698e7ce4b9 get-pup: Verify with openssl instead of sha256sum
Use openssl to verify download because sha256sum does not exist on
macOS.
2022-05-10 21:58:05 +03:00
Ryan Schmidt
7ee6b81661 HACKING.md: Note MacPorts can install gawk too 2022-05-10 21:56:30 +03:00
Ryan Schmidt
e8a4a7eced template.awk: Fix name of HACKING file
HACKING was converted from reStructuredText to markdown back in 2014 in
0064164d4e.
2022-05-10 21:55:00 +03:00
Ryan Schmidt
3d47d0d6b1 README.rst: Fix typos and other minor edits 2022-05-10 21:54:12 +03:00
Ryan Schmidt
60e39e0929 .gitignore: Ignore nginx-*
After running t/build-and-run an nginx directory is left in the main
directory. Hide this from git status since we won't want to check it in.
2022-05-10 21:52:26 +03:00
Ryan Schmidt
a1890354e5 Tests: Build nginx in parallel on macOS 2022-05-10 19:55:34 +03:00
Ryan Schmidt
20ba8038ac Tests: Use netstat to list occupied ports on macOS
Use netstat instead of ss to list the occupied ports on macOS since
macOS doesn't have ss.

Closes #139
2022-05-10 19:46:26 +03:00
Anthony Ryan
5930c29d6a Remove fancyindex_name_length by offloading work to CSS
This is a backwards compatibility break, in that the `fancyindex_name_length` setting will now
prevent nginx from starting until removed. I do think though that most people will find the new
behavior preferable to that setting however.

There's two arguably unrelated CSS changes included in this pull request, so let me know if you
like one but not the other or vice versa I can split them up.

-----

We've introduced `table-layout: fixed;`. This is a performance optimization for browsers rendering
very large file lists.

The default mode (`table-layout: auto`) first needs to load the entire table, then calculates the
optimal column widths based on the contents of all cells in the table start to finish. This can be
a bit slow when directory listings contain tens of thousands of files or folders.

With `table-layout: fixed;` the width is determined based on the first row allowing the browser to
render to begin rendering the table immediately.

Technically, the widths of columns have changed slightly as a result of this, but we no longer need
to specify widths using style attributes, which makes it easier for custom CSS users to change the
widths.

.link was 55% wide, now 50%
.size was 20% wide, now 25%
.date was 25% wide, now 25%

-----

Rather than truncating string names server-side, we instead send the full name and tell the browser
to truncate file names with CSS. This has the advantage of always showing as much of the file name
as it can fit in a line. This has the benefit of avoiding line wraps on smaller screens (like
phones) and allowing people to resize their window larger to see more of the file name.

This reduces the code complexity server side and provides a optimal truncation on every device.
2021-10-28 22:37:48 +03:00
Adrian Perez de Castro
6cdffdb0af
Version 0.5.2 2021-10-28 22:28:07 +03:00
Adrian Perez de Castro
b0e1fa83a8 CI: Move over to GitHub Actions 2021-10-26 01:12:26 +03:00
Anthony Ryan
2e9555e759 Always use ngx_escape_html to ensure we aren't rendering file names
as HTML tags.
2021-10-25 16:19:03 +03:00
Adrian Perez de Castro
391d2d5447
CI: Update mainline version to 1.19.3 2021-02-25 19:01:53 +02:00
Tim Gates
566ad22a61 docs: fix simple typo, configration -> configuration
There is a small typo in ngx_http_fancyindex_module.c.

Should read `configuration` rather than `configration`.
2020-12-21 17:20:44 +01:00
Adrian Perez de Castro
5ca7cb32af
Version 0.5.1 2020-10-26 22:45:29 +02:00
Adrian Perez de Castro
c33b05af9e Fix check for arguments to fancyindex_{header,footer}
Closes #117
2020-10-26 22:41:38 +02:00
Adrian Perez de Castro
4fc6bb10d7
Version 0.5.0 2020-10-24 19:07:36 +03:00
Adrian Perez de Castro
618e2d154e
Add missing "use pup" command to t/07-directory-first.test 2020-10-24 18:53:53 +03:00
Adrian Perez de Castro
f52bacea8f Add unit tests for local headers and footers 2020-10-24 18:52:58 +03:00
Adrian Perez de Castro
527511fbf8 Load local header and footer files when configuring
Make the configuration process load the local files specified with
'fancyindex_{header,footer} "foo" local', instead of loading them
on every request.

Additionally, change the syntax of the configuration directive to accept
an optional parameter indicating whether the header (or footer) is to be
loaded as a subrequest (default, for backwards compatibility) or a local
file (must be specified explicitly). This avoids the footgun of having
a local file which accidentally happens to match the subrequest that one
had the intention to do when configuring.
2020-10-24 18:52:58 +03:00
JoungKyun Kim
5ac161ccc3 fixed #82 fancyindex can't print list with auth-ldap module
- fixed signedness problems
- fixed gabage characters
2020-10-24 18:34:41 +03:00
Adrian Perez de Castro
140dcb7a8f Properly escape square brackets with old Nginx versions 2020-10-24 15:40:07 +03:00
Adrian Perez de Castro
6637a7afab Update to Nginx 0.8 as oldest supported version 2020-10-24 15:40:07 +03:00
Adrian Perez de Castro
d3d7adc89d README: Update CI link to use travis-ci.com instead of .org 2020-10-24 14:08:56 +03:00
Adrian Perez de Castro
52a17b7a17 CI: Update Nginx mainline and stable versions 2020-10-24 14:08:56 +03:00
z4yx
63d19686df add a test of ngx_http_fancyindex_cmp_entries_dirs_first 2020-10-24 13:17:10 +03:00
z4yx
b3e06fd31b remove ngx_http_fancyindex_cmp_entries_dirs_first 2020-10-24 13:17:10 +03:00
z4yx
c0448985b6 ngx_int_t -> int 2020-10-24 13:17:10 +03:00
z4yx
a05006e3c4 replace ngx_sort with ngx_qsort 2020-10-24 13:17:10 +03:00
Joshua Shaffer
56934db14c update readme 2020-05-26 16:14:09 +03:00
Joshua Shaffer
42e21c9153 Added test for show_dotfiles 2020-05-26 16:14:09 +03:00
Joshua Shaffer
7444208a36 t/* should be eol=lf so bash can run 2020-05-26 16:14:09 +03:00
Joshua Shaffer
94bb8164b2 Fixes #54. Adds configuration option 'fancyindex_show_dotfiles' to show dotfiles. 2020-05-26 16:14:09 +03:00
Adrian Perez de Castro
11101de198
make-dist: Add script to generate release tarballs
Because the source archives from GitHub tags may not always produce the
same tarball when fetching at different times. Having proper tarballs
for releases also allows signing them i.e. with PGP.
2020-02-19 13:05:55 +02:00
35 changed files with 821 additions and 319 deletions

4
.gitattributes vendored Normal file
View file

@ -0,0 +1,4 @@
/.gitignore export-ignore
/.travis.yml export-ignore
/make-dist export-ignore
t/* text eol=lf

49
.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,49 @@
---
name: Build
on: [pull_request]
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-18.04]
compiler: [gcc, clang]
nginx:
# Mainline
- 1.23.3
# Stable.
- 1.22.1
# First version with loadable module support.
- 1.9.15
# Oldest supported version.
- 0.8.55
dynamic: [0, 1]
exclude:
- nginx: 0.8.55
dynamic: 1
- nginx: 0.8.55
os: macos-latest
- compiler: gcc
os: macos-latest
runs-on: ${{ matrix.os }}
env:
CFLAGS: "-Wno-error"
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Packages
run: |
case $RUNNER_OS in
Linux )
sudo apt update
sudo apt install -y libpcre3-dev libssl-dev
;;
* )
;;
esac
t/get-pup || echo 'Tests needing pup will be skipped'
- name: Test
env:
CC: ${{ matrix.compiler }}
run: t/build-and-run ${{ matrix.nginx }} ${{ matrix.dynamic }}

1
.gitignore vendored
View file

@ -1,4 +1,5 @@
*.sw[op]
/nginx-*
/t/*.sh
/t/*.out
/t/*.err

View file

@ -1,39 +0,0 @@
language: c
compiler:
- clang
- gcc
env:
# Mainline.
- NGINX=1.15.2
- NGINX=1.15.2 DYNAMIC=1
# Stable.
- NGINX=1.14.0
- NGINX=1.14.0 DYNAMIC=1
# Other configurations.
- NGINX=1.12.2
- NGINX=1.12.2 DYNAMIC=1
- NGINX=1.10.3
# Version 1.9.15 was the first with loadable module support.
- NGINX=1.9.15
- NGINX=1.9.15 DYNAMIC=1
- NGINX=1.8.1
# Also, the oldest supported version
# TODO: Fails building because it won't find IOV_MAX from header.
#- NGINX=0.7.69
sudo: false
addons:
apt:
packages:
- libpcre3-dev
- libssl-dev
cache: ccache
script:
- echo "NGINX=${NGINX} ${DYNAMIC:+DYNAMIC=${DYNAMIC}}"
- t/get-pup || echo 'Tests needing pup will be skipped'
- t/build-and-run ${NGINX} ${DYNAMIC}

View file

@ -3,6 +3,40 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
## [0.5.2] - 2021-10-28
### Fixed
- Properly escape file names to ensure that file names are never renreded
as HTML. (Patch by Anthony Ryan <<anthonyryan1@gmail.com>>,
[#128](https://github.com/aperezdc/ngx-fancyindex/pull/128).)
## [0.5.1] - 2020-10-26
### Fixed
- Properly handle optional second argument to `fancyindex_header` and
`fancyindex_footer`
([#117](https://github.com/aperezdc/ngx-fancyindex/issues/117)).
## [0.5.0] - 2020-10-24
### Added
- New option `fancyindex_show_dotfiles`. (Path by Joshua Shaffer
<<joshua.shaffer@icmrl.net>>.)
- The `fancyindex_header` and `fancyindex_footer` options now support local
files properly, by means of a `local` flag. (Patches by JoungKyun Kim
<<joungkyun@gmail.com>> and Adrián Pérez <<aperez@igalia.com>>.)
### Changed
- Improved performance of directory entry sorting, which should be quite
noticeable for directories with thousands of files. (Patch by
[Yuxiang Zhang](https://github.com/z4yx).)
- The minimum Nginx version supported by the module is now 0.8.x.
### Fixed
- Properly escape square brackets in directory entry names when the module
is built with older versions of Nginx. (Patch by Adrián Pérez
<<aperez@igalia.com>>.)
- Fix directory entry listing not being shown when using the
[nginx-auth-ldap](https://github.com/kvspb/nginx-auth-ldap) module. (Patch
by JoungKyun Kim <<joungkyun@gmail.com>>.)
## [0.4.4] - 2020-02-19
### Added
- New option `fancyindex_hide_parent_dir`, which disables generating
@ -148,7 +182,10 @@ All notable changes to this project will be documented in this file.
- `NEWS.rst` file, to act as change log.
[Unreleased]: https://github.com/aperezdc/ngx-fancyindex/compare/v0.4.4...HEAD
[Unreleased]: https://github.com/aperezdc/ngx-fancyindex/compare/v0.5.2...HEAD
[0.5.2]: https://github.com/aperezdc/ngx-fancyindex/compare/v0.5.1...v0.5.2
[0.5.1]: https://github.com/aperezdc/ngx-fancyindex/compare/v0.5.0...v0.5.1
[0.5.0]: https://github.com/aperezdc/ngx-fancyindex/compare/v0.4.4...v0.5.0
[0.4.4]: https://github.com/aperezdc/ngx-fancyindex/compare/v0.4.3...v0.4.4
[0.4.3]: https://github.com/aperezdc/ngx-fancyindex/compare/v0.4.2...v0.4.3
[0.4.2]: https://github.com/aperezdc/ngx-fancyindex/compare/v0.4.1...v0.4.2

View file

@ -26,4 +26,5 @@ install it and use `gawk` instead in the command line above.
This includes macOS where the current built-in `awk` (currently version
20070501 at time of testing on 10.13.6) doesn't apply correctly and causes
characters to be omitted from the output. `gawk` can be installed with a
package manager such as [Homebrew](https://brew.sh).
package manager such as [Homebrew](https://brew.sh) or
[MacPorts](https://ports.macports.org/port/gawk).

View file

@ -2,8 +2,8 @@
Nginx Fancy Index module
========================
.. image:: https://travis-ci.org/aperezdc/ngx-fancyindex.svg?branch=master
:target: https://travis-ci.org/aperezdc/ngx-fancyindex
.. image:: https://travis-ci.com/aperezdc/ngx-fancyindex.svg?branch=master
:target: https://travis-ci.com/aperezdc/ngx-fancyindex
:alt: Build Status
.. contents::
@ -13,9 +13,9 @@ the built-in `autoindex <http://wiki.nginx.org/NginxHttpAutoindexModule>`__
module does, but adding a touch of style. This is possible because the module
allows a certain degree of customization of the generated content:
* Custom headers. Either local or stored remotely.
* Custom footers. Either local or stored remotely.
* Add you own CSS style rules.
* Custom headers, either local or stored remotely.
* Custom footers, either local or stored remotely.
* Add your own CSS style rules.
* Allow choosing to sort elements by name (default), modification time, or
size; both ascending (default), or descending.
@ -26,30 +26,32 @@ server written by `Igor Sysoev <http://sysoev.ru>`__.
Requirements
============
CentOS 7
~~~~~~~~
CentOS, RHEL, Fedora Linux
~~~~~~~~~~~~~~~~~~~~~~~~~~
For users of the `official stable <https://www.nginx.com/resources/wiki/start/topics/tutorials/install/>`__ Nginx repository, `extra packages repository with dynamic modules <https://www.getpagespeed.com/redhat>`__ is available and fancyindex is included.
Install directly::
Install repository configuration, then the module package::
yum install https://extras.getpagespeed.com/redhat/7/x86_64/RPMS/nginx-module-fancyindex-1.12.0.0.4.1-1.el7.gps.x86_64.rpm
Alternatively, add extras repository first (for future updates) and install the module::
yum install nginx-module-fancyindex
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install nginx-module-fancyindex
Then load the module in `/etc/nginx/nginx.conf` using::
load_module "modules/ngx_http_fancyindex_module.so";
macOS
~~~~~
Users can `install Nginx on macOS with MacPorts <https://ports.macports.org/port/nginx>`__; fancyindex is included::
sudo port install nginx
Other platforms
~~~~~~~~~~~~~~~
In most other cases you will need the sources for Nginx_. Any version starting from the 0.7
series onwards will work. Note that the modules *might* compile with
versions in the 0.6 series by applying ``nginx-0.6-support.patch``, but this
is unsupported (YMMV).
In most other cases you will need the sources for Nginx_. Any version starting
from the 0.8 series should work.
In order to use the ``fancyindex_header_`` and ``fancyindex_footer_`` directives
you will also need the `ngx_http_addition_module <https://nginx.org/en/docs/http/ngx_http_addition_module.html>`_
@ -115,8 +117,8 @@ achieved using the module:
`@TheInsomniac <https://github.com/TheInsomniac>`__. Uses custom header and
footer.
* `Theme <https://github.com/Naereen/Nginx-Fancyindex-Theme>`__ by
`@Naereen <https://github.com/Naereen/>`__. Uses custom header and footer, the
header includes search field to filter by filename using JavaScript.
`@Naereen <https://github.com/Naereen/>`__. Uses custom header and footer. The
header includes a search field to filter by file name using JavaScript.
* `Theme <https://github.com/fraoustin/Nginx-Fancyindex-Theme>`__ by
`@fraoustin <https://github.com/fraoustin>`__. Responsive theme using
Material Design elements.
@ -144,6 +146,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*]
@ -170,32 +181,26 @@ fancyindex_exact_size
:Default: fancyindex_exact_size on
:Context: http, server, location
:Description:
Defines how to represent file sizes in the directory listing; either
Defines how to represent file sizes in the directory listing: either
accurately, or rounding off to the kilobyte, the megabyte and the
gigabyte.
fancyindex_name_length
~~~~~~~~~~~~~~~~~~~~~~
:Syntax: *fancyindex_name_length length*
:Default: fancyindex_name_length 50
:Context: http, server, location
:Description:
Defines the maximum file name length limit in bytes.
fancyindex_footer
~~~~~~~~~~~~~~~~~
:Syntax: *fancyindex_footer path*
:Syntax: *fancyindex_footer path* [*subrequest* | *local*]
:Default: fancyindex_footer ""
:Context: http, server, location
:Description:
Specifies which file should be inserted at the foot of directory listings.
If set to an empty string, the default footer supplied by the module will
be sent.
be sent. The optional parameter indicates whether the *path* is to be
treated as a URI to load using a *subrequest* (the default), or whether
it refers to a *local* file.
.. note:: Using this directive needs the ngx_http_addition_module_ built
into Nginx.
.. warning:: When inserting custom header/footer a subrequest will be
.. warning:: When inserting custom a header/footer, a subrequest will be
issued so potentially any URL can be used as source for them. Although it
will work with external URLs, only using internal ones is supported.
External URLs are totally untested and using them will make Nginx_ block
@ -205,13 +210,15 @@ fancyindex_footer
fancyindex_header
~~~~~~~~~~~~~~~~~
:Syntax: *fancyindex_header path*
:Syntax: *fancyindex_header path* [*subrequest* | *local*]
:Default: fancyindex_header ""
:Context: http, server, location
:Description:
Specifies which file should be inserted at the head of directory listings.
If set to an empty string, the default header supplied by the module will
be sent.
be sent. The optional parameter indicates whether the *path* is to be
treated as a URI to load using a *subrequest* (the default), or whether
it refers to a *local* file.
.. note:: Using this directive needs the ngx_http_addition_module_ built
into Nginx.
@ -222,21 +229,30 @@ fancyindex_show_path
:Default: fancyindex_show_path on
:Context: http, server, location
:Description:
Whether to output or not the path and the closing </h1> tag after the header.
Whether or not to output the path and the closing </h1> tag after the header.
This is useful when you want to handle the path displaying with a PHP script
for example.
.. warning:: This directive can be turned off only if a custom header is provided
using fancyindex_header.
fancyindex_show_dotfiles
~~~~~~~~~~~~~~~~~~~~
:Syntax: *fancyindex_show_dotfiles* [*on* | *off*]
:Default: fancyindex_show_dotfiles off
:Context: http, server, location
:Description:
Whether to list files that are preceded with a dot. Normal convention is to
hide these.
fancyindex_ignore
~~~~~~~~~~~~~~~~~
:Syntax: *fancyindex_ignore string1 [string2 [... stringN]]*
:Default: No default.
:Context: http, server, location
:Description:
Specifies a list of file names which will be not be shown in generated
listings. If Nginx was built with PCRE support strings are interpreted as
Specifies a list of file names which will not be shown in generated
listings. If Nginx was built with PCRE support, strings are interpreted as
regular expressions.
fancyindex_hide_symlinks
@ -253,7 +269,7 @@ fancyindex_hide_parent_dir
:Default: fancyindex_hide_parent_dir off
:Context: http, server, location
:Description:
When enabled, it will not show parent directory.
When enabled, it will not show the parent directory.
fancyindex_localtime
~~~~~~~~~~~~~~~~~~~~

10
make-dist Executable file
View file

@ -0,0 +1,10 @@
#! /bin/sh
set -e
GIT_TAG=$(git describe --tags HEAD)
VERSION=${GIT_TAG#v}
PV="ngx-fancyindex-${VERSION}"
set -x
git archive --worktree-attributes --prefix="${PV}/" -o "${PV}.tar" "${GIT_TAG}"
xz -f9 "${PV}.tar"

View file

@ -1,23 +0,0 @@
=== modified file 'ngx_http_fancyindex_module.c'
--- ngx_http_fancyindex_module.c 2008-09-11 17:55:52 +0000
+++ ngx_http_fancyindex_module.c 2008-12-10 01:33:43 +0000
@@ -383,7 +383,7 @@
entry->mtime = ngx_de_mtime(&dir);
entry->size = ngx_de_size(&dir);
entry->utf_len = (r->utf8)
- ? ngx_utf8_length(entry->name.data, entry->name.len)
+ ? ngx_utf_length(entry->name.data, entry->name.len)
: len;
}
@@ -478,8 +478,7 @@
copy = NGX_HTTP_FANCYINDEX_NAME_LEN + 1;
}
- b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data,
- copy, entry[i].name.len);
+ b->last = ngx_utf_cpystrn(b->last, entry[i].name.data, copy);
last = b->last;
} else {

View file

@ -16,7 +16,7 @@
* Base functionality heavy based upon the stock nginx autoindex module,
* which in turn was made by Igor Sysoev, like the majority of nginx.
*
* Distributed under terms of the BSD license.
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <ngx_config.h>
@ -37,7 +37,7 @@ static const char *short_weekday[] = {
"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun",
};
static const char *long_weekday[] = {
"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Sunday",
"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday",
};
static const char *short_month[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
@ -140,28 +140,34 @@ ngx_fancyindex_timefmt (u_char *buffer, const ngx_str_t *fmt, const ngx_tm_t *tm
#undef DATETIME_CASE
}
typedef struct {
ngx_str_t path;
ngx_str_t local;
} ngx_fancyindex_headerfooter_conf_t;
/**
* Configuration structure for the fancyindex module. The configuration
* commands defined in the module do fill in the members of this structure.
*/
typedef struct {
ngx_flag_t enable; /**< Module is enabled. */
ngx_uint_t default_sort; /**< Default sort criterion. */
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. */
ngx_uint_t name_length; /**< Maximum length of file names in bytes. */
ngx_flag_t hide_symlinks;/**< Hide symbolic links in listings. */
ngx_flag_t show_path; /**< Whether to display or not the path + '</h1>' after the header */
ngx_flag_t hide_parent; /**< Hide parent directory. */
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. */
ngx_flag_t hide_symlinks; /**< Hide symbolic links in listings. */
ngx_flag_t show_path; /**< Whether to display or not the path + '</h1>' after the header */
ngx_flag_t hide_parent; /**< Hide parent directory. */
ngx_flag_t show_dot_files; /**< Show files that start with a dot.*/
ngx_str_t header; /**< File name for header, or empty if none. */
ngx_str_t footer; /**< File name for footer, or empty if none. */
ngx_str_t css_href; /**< Link to a CSS stylesheet, or empty if none. */
ngx_str_t time_format; /**< Format used for file timestamps. */
ngx_str_t css_href; /**< Link to a CSS stylesheet, or empty if none. */
ngx_str_t time_format; /**< Format used for file timestamps. */
ngx_array_t *ignore; /**< List of files to ignore in listings. */
ngx_array_t *ignore; /**< List of files to ignore in listings. */
ngx_fancyindex_headerfooter_conf_t header;
ngx_fancyindex_headerfooter_conf_t footer;
} ngx_http_fancyindex_loc_conf_t;
#define NGX_HTTP_FANCYINDEX_SORT_CRITERION_NAME 0
@ -181,6 +187,106 @@ static ngx_conf_enum_t ngx_http_fancyindex_sort_criteria[] = {
{ ngx_null_string, 0 }
};
enum {
NGX_HTTP_FANCYINDEX_HEADERFOOTER_SUBREQUEST,
NGX_HTTP_FANCYINDEX_HEADERFOOTER_LOCAL,
};
static ngx_uint_t
headerfooter_kind(const ngx_str_t *value)
{
static const struct {
ngx_str_t name;
ngx_uint_t value;
} values[] = {
{ ngx_string("subrequest"), NGX_HTTP_FANCYINDEX_HEADERFOOTER_SUBREQUEST },
{ ngx_string("local"), NGX_HTTP_FANCYINDEX_HEADERFOOTER_LOCAL },
};
unsigned i;
for (i = 0; i < sizeof(values) / sizeof(values[0]); i++) {
if (value->len == values[i].name.len &&
ngx_strcasecmp(value->data, values[i].name.data) == 0)
{
return values[i].value;
}
}
return NGX_CONF_UNSET_UINT;
}
static char*
ngx_fancyindex_conf_set_headerfooter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_fancyindex_headerfooter_conf_t *item =
(void*) (((char*) conf) + cmd->offset);
ngx_str_t *values = cf->args->elts;
if (item->path.data)
return "is duplicate";
item->path = values[1];
/* Kind of path. Default is "subrequest". */
ngx_uint_t kind = NGX_HTTP_FANCYINDEX_HEADERFOOTER_SUBREQUEST;
if (cf->args->nelts == 3) {
kind = headerfooter_kind(&values[2]);
if (kind == NGX_CONF_UNSET_UINT) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unknown header/footer kind \"%V\"", &values[2]);
return NGX_CONF_ERROR;
}
}
if (kind == NGX_HTTP_FANCYINDEX_HEADERFOOTER_LOCAL) {
ngx_file_t file;
ngx_file_info_t fi;
ssize_t n;
ngx_memzero(&file, sizeof(ngx_file_t));
file.log = cf->log;
file.fd = ngx_open_file(item->path.data, NGX_FILE_RDONLY, 0, 0);
if (file.fd == NGX_INVALID_FILE) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
"cannot open file \"%V\"", &values[1]);
return NGX_CONF_ERROR;
}
if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) {
ngx_close_file(file.fd);
ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
"cannot get info for file \"%V\"", &values[1]);
return NGX_CONF_ERROR;
}
item->local.len = ngx_file_size(&fi);
item->local.data = ngx_pcalloc(cf->pool, item->local.len + 1);
if (item->local.data == NULL) {
ngx_close_file(file.fd);
return NGX_CONF_ERROR;
}
n = item->local.len;
while (n > 0) {
ssize_t r = ngx_read_file(&file,
item->local.data + file.offset,
n,
file.offset);
if (r == NGX_ERROR) {
ngx_close_file(file.fd);
ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
"cannot read file \"%V\"", &values[1]);
return NGX_CONF_ERROR;
}
n -= r;
}
item->local.data[item->local.len] = '\0';
}
return NGX_CONF_OK;
}
#define NGX_HTTP_FANCYINDEX_PREALLOCATE 50
@ -222,6 +328,7 @@ typedef struct {
ngx_str_t name;
size_t utf_len;
ngx_uint_t escape;
ngx_uint_t escape_html;
ngx_uint_t dir;
time_t mtime;
off_t size;
@ -229,19 +336,21 @@ typedef struct {
static ngx_int_t ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_dirs_first(const void *one, const void *two);
static ngx_int_t ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_name_desc(const void *one, const void *two);
static ngx_int_t ngx_libc_cdecl
static int ngx_libc_cdecl
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 ngx_int_t ngx_libc_cdecl
static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_mtime_desc(const void *one, const void *two);
static ngx_int_t ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_name_asc(const void *one, const void *two);
static ngx_int_t ngx_libc_cdecl
static int ngx_libc_cdecl
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 ngx_int_t ngx_libc_cdecl
static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_mtime_asc(const void *one, const void *two);
static ngx_int_t ngx_http_fancyindex_error(ngx_http_request_t *r,
@ -270,11 +379,6 @@ static ngx_inline ngx_buf_t*
make_header_buf(ngx_http_request_t *r, const ngx_str_t css_href)
ngx_force_inline;
static ngx_inline ngx_buf_t*
make_footer_buf(ngx_http_request_t *r)
ngx_force_inline;
static ngx_command_t ngx_http_fancyindex_commands[] = {
@ -292,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,
@ -313,23 +424,16 @@ static ngx_command_t ngx_http_fancyindex_commands[] = {
offsetof(ngx_http_fancyindex_loc_conf_t, exact_size),
NULL },
{ ngx_string("fancyindex_name_length"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_num_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_fancyindex_loc_conf_t, name_length),
NULL },
{ ngx_string("fancyindex_header"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_str_slot,
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
ngx_fancyindex_conf_set_headerfooter,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_fancyindex_loc_conf_t, header),
NULL },
{ ngx_string("fancyindex_footer"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_str_slot,
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
ngx_fancyindex_conf_set_headerfooter,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_fancyindex_loc_conf_t, footer),
NULL },
@ -362,6 +466,13 @@ static ngx_command_t ngx_http_fancyindex_commands[] = {
offsetof(ngx_http_fancyindex_loc_conf_t, show_path),
NULL },
{ ngx_string("fancyindex_show_dotfiles"),
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, show_dot_files),
NULL },
{ ngx_string("fancyindex_hide_parent_dir"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
@ -390,8 +501,8 @@ static ngx_http_module_t ngx_http_fancyindex_module_ctx = {
NULL, /* create server configuration */
NULL, /* merge server configuration */
ngx_http_fancyindex_create_loc_conf, /* create location configration */
ngx_http_fancyindex_merge_loc_conf /* merge location configration */
ngx_http_fancyindex_create_loc_conf, /* create location configuration */
ngx_http_fancyindex_merge_loc_conf /* merge location configuration */
};
@ -444,6 +555,8 @@ ngx_fancyindex_escape_filename(u_char *dst, u_char *src, size_t size)
switch (*psrc++) {
case ':':
case '?':
case '[':
case ']':
escapes++;
break;
}
@ -485,6 +598,16 @@ ngx_fancyindex_escape_filename(u_char *dst, u_char *src, size_t size)
*dst++ = '3';
*dst++ = 'F';
break;
case '[':
*dst++ = '%';
*dst++ = '5';
*dst++ = 'B';
break;
case ']':
*dst++ = '%';
*dst++ = '5';
*dst++ = 'D';
break;
default:
*dst++ = *buf;
}
@ -504,6 +627,7 @@ ngx_fancyindex_escape_filename(u_char *dst, u_char *src, size_t size)
static ngx_inline ngx_buf_t*
make_header_buf(ngx_http_request_t *r, const ngx_str_t css_href)
{
ngx_buf_t *b;
size_t blen = r->uri.len
+ ngx_sizeof_ssz(t01_head1)
+ ngx_sizeof_ssz(t02_head2)
@ -518,9 +642,8 @@ make_header_buf(ngx_http_request_t *r, const ngx_str_t css_href)
;
}
ngx_buf_t *b = ngx_create_temp_buf(r->pool, blen);
if (b == NULL) goto bailout;
if ((b = ngx_create_temp_buf(r->pool, blen)) == NULL)
return NULL;
b->last = ngx_cpymem_ssz(b->last, t01_head1);
@ -535,31 +658,10 @@ make_header_buf(ngx_http_request_t *r, const ngx_str_t css_href)
b->last = ngx_cpymem_ssz(b->last, t03_head3);
b->last = ngx_cpymem_ssz(b->last, t04_body1);
bailout:
return b;
}
static ngx_inline ngx_buf_t*
make_footer_buf(ngx_http_request_t *r)
{
/*
* TODO: Make this buffer static (i.e. readonly and reusable from
* one request to another.
*/
ngx_buf_t *b = ngx_create_temp_buf(r->pool, ngx_sizeof_ssz(t08_foot1));
if (b == NULL) goto bailout;
b->last = ngx_cpymem_ssz(b->last, t08_foot1);
bailout:
return b;
}
static ngx_inline ngx_int_t
make_content_buf(
ngx_http_request_t *r, ngx_buf_t **pb,
@ -567,11 +669,11 @@ make_content_buf(
{
ngx_http_fancyindex_entry_t *entry;
ngx_int_t (*sort_cmp_func) (const void*, const void*);
int (*sort_cmp_func)(const void *, const void *);
const char *sort_url_args = "";
off_t length;
size_t len, root, copy, allocated;
size_t len, root, allocated, escape_html;
int64_t multiplier;
u_char *filename, *last;
ngx_tm_t tm;
@ -594,7 +696,10 @@ make_content_buf(
return NGX_HTTP_INTERNAL_SERVER_ERROR;
allocated = path.len;
path.len = last - path.data - 1;
path.len = last - path.data;
if (path.len > 1) {
path.len--;
}
path.data[path.len] = '\0';
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@ -654,7 +759,7 @@ make_content_buf(
len = ngx_de_namelen(&dir);
if (ngx_de_name(&dir)[0] == '.')
if (!alcf->show_dot_files && ngx_de_name(&dir)[0] == '.')
continue;
if (alcf->hide_symlinks && ngx_de_is_link (&dir))
@ -735,6 +840,9 @@ make_content_buf(
entry->escape = 2 * ngx_fancyindex_escape_filename(NULL,
ngx_de_name(&dir),
len);
entry->escape_html = ngx_escape_html(NULL,
entry->name.data,
entry->name.len);
entry->dir = ngx_de_is_dir(&dir);
entry->mtime = ngx_de_mtime(&dir);
@ -753,8 +861,11 @@ 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
len = r->uri.len + escape_html
+ ngx_sizeof_ssz(t05_body2)
+ ngx_sizeof_ssz(t06_list1)
+ ngx_sizeof_ssz(t_parentdir_entry)
@ -762,7 +873,7 @@ make_content_buf(
+ ngx_fancyindex_timefmt_calc_size (&alcf->time_format) * entries.nelts
;
else
len = r->uri.len
len = r->uri.len + escape_html
+ ngx_sizeof_ssz(t06_list1)
+ ngx_sizeof_ssz(t_parentdir_entry)
+ ngx_sizeof_ssz(t07_list2)
@ -788,14 +899,13 @@ make_content_buf(
* <td>size</td><td>date</td>
* </tr>
*/
len += ngx_sizeof_ssz("<tr><td class=\"link\"><a href=\"")
len += ngx_sizeof_ssz("<tr><td colspan=\"2\" class=\"link\"><a href=\"")
+ entry[i].name.len + entry[i].escape /* Escaped URL */
+ ngx_sizeof_ssz("?C=x&amp;O=y") /* URL sorting arguments */
+ ngx_sizeof_ssz("\" title=\"")
+ entry[i].name.len + entry[i].utf_len
+ entry[i].name.len + entry[i].utf_len + entry[i].escape_html
+ ngx_sizeof_ssz("\">")
+ entry[i].name.len + entry[i].utf_len
+ alcf->name_length + ngx_sizeof_ssz("&gt;")
+ entry[i].name.len + entry[i].utf_len + entry[i].escape_html
+ ngx_sizeof_ssz("</a></td><td class=\"size\">")
+ 20 /* File size */
+ ngx_sizeof_ssz("</td><td class=\"date\">") /* Date prefix */
@ -852,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&amp;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&amp;O=A";
}
@ -879,35 +993,61 @@ 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;
}
}
/* Sort entries, if needed */
if (entries.nelts > 1) {
/* Use ngx_sort for stability */
ngx_sort(entry, (size_t) entries.nelts,
sizeof(ngx_http_fancyindex_entry_t),
sort_cmp_func);
if (alcf->dirs_first)
{
/* Sort directories first */
ngx_sort(entry, (size_t) entries.nelts,
sizeof(ngx_http_fancyindex_entry_t),
ngx_http_fancyindex_cmp_entries_dirs_first);
}
ngx_http_fancyindex_entry_t *l, *r;
l = entry;
r = entry + entries.nelts - 1;
while (l < r)
{
while (l < r && l->dir)
l++;
while (l < r && !r->dir)
r--;
if (l < r) {
/* Now l points a file while r points a directory */
ngx_http_fancyindex_entry_t tmp;
tmp = *l;
*l = *r;
*r = tmp;
}
}
if (r->dir)
r++;
if (r > entry)
/* Sort directories */
ngx_qsort(entry, (size_t)(r - entry),
sizeof(ngx_http_fancyindex_entry_t), sort_cmp_func);
if (r < entry + entries.nelts)
/* Sort files */
ngx_qsort(r, (size_t)(entry + entries.nelts - r),
sizeof(ngx_http_fancyindex_entry_t), sort_cmp_func);
} else {
ngx_qsort(entry, (size_t)entries.nelts,
sizeof(ngx_http_fancyindex_entry_t), sort_cmp_func);
}
}
/* Display the path, if needed */
if (alcf->show_path){
b->last = ngx_cpymem_str(b->last, r->uri);
b->last = last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len);
b->last = ngx_cpymem_ssz(b->last, t05_body2);
}
@ -920,7 +1060,7 @@ make_content_buf(
if (r->uri.len > 1 && alcf->hide_parent == 0) {
b->last = ngx_cpymem_ssz(b->last,
"<tr>"
"<td class=\"link\"><a href=\"../");
"<td colspan=\"2\" class=\"link\"><a href=\"../");
if (*sort_url_args) {
b->last = ngx_cpymem(b->last,
sort_url_args,
@ -936,7 +1076,7 @@ make_content_buf(
/* Entries for directories and files */
for (i = 0; i < entries.nelts; i++) {
b->last = ngx_cpymem_ssz(b->last, "<tr><td class=\"link\"><a href=\"");
b->last = ngx_cpymem_ssz(b->last, "<tr><td colspan=\"2\" class=\"link\"><a href=\"");
if (entry[i].escape) {
ngx_fancyindex_escape_filename(b->last,
@ -960,40 +1100,21 @@ make_content_buf(
*b->last++ = '"';
b->last = ngx_cpymem_ssz(b->last, " title=\"");
b->last = ngx_cpymem_str(b->last, entry[i].name);
b->last = (u_char *) ngx_escape_html(b->last, entry[i].name.data, entry[i].name.len);
*b->last++ = '"';
*b->last++ = '>';
len = entry[i].utf_len;
if (entry[i].name.len - len) {
if (len > alcf->name_length) {
copy = alcf->name_length - 3 + 1;
} else {
copy = alcf->name_length + 1;
}
b->last = (u_char *) ngx_escape_html(b->last, entry[i].name.data, entry[i].name.len);
last = b->last - 3;
b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data,
copy, entry[i].name.len);
last = b->last;
} else {
b->last = ngx_cpystrn(b->last, entry[i].name.data,
alcf->name_length + 1);
last = b->last - 3;
if (entry[i].dir) {
*b->last++ = '/';
len++;
}
if (len > alcf->name_length) {
b->last = ngx_cpymem_ssz(last, "..&gt;</a></td><td class=\"size\">");
} else {
if (entry[i].dir && alcf->name_length - len > 0) {
*b->last++ = '/';
len++;
}
b->last = ngx_cpymem_ssz(b->last, "</a></td><td class=\"size\">");
}
b->last = ngx_cpymem_ssz(b->last, "</a></td><td class=\"size\">");
if (alcf->exact_size) {
if (entry[i].dir) {
@ -1016,7 +1137,7 @@ make_content_buf(
if (j == DIM(sizes) - 1)
b->last = ngx_sprintf(b->last, "%O %s", length, sizes[j]);
else
b->last = ngx_sprintf(b->last, "%.1f %s",
b->last = ngx_sprintf(b->last, "%.1f %s",
(float) length / multiplier, sizes[j]);
}
}
@ -1088,19 +1209,19 @@ ngx_http_fancyindex_handler(ngx_http_request_t *r)
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only)
return rc;
if (alcf->header.len > 0) {
if (alcf->header.path.len > 0 && alcf->header.local.len == 0) {
/* URI is configured, make Nginx take care of with a subrequest. */
sr_uri = &alcf->header;
sr_uri = &alcf->header.path;
if (*sr_uri->data != '/') {
/* Relative path */
rel_uri.len = r->uri.len + alcf->header.len;
rel_uri.len = r->uri.len + alcf->header.path.len;
rel_uri.data = ngx_palloc(r->pool, rel_uri.len);
if (rel_uri.data == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
ngx_memcpy(ngx_cpymem(rel_uri.data, r->uri.data, r->uri.len),
alcf->header.data, alcf->header.len);
alcf->header.path.data, alcf->header.path.len);
sr_uri = &rel_uri;
}
@ -1128,25 +1249,42 @@ ngx_http_fancyindex_handler(ngx_http_request_t *r)
}
else {
add_builtin_header:
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http fancyindex: adding built-in header");
/* Make space before */
out[1].next = out[0].next;
out[1].buf = out[0].buf;
/* Chain header buffer */
out[0].next = &out[1];
out[0].buf = make_header_buf(r, alcf->css_href);
if (alcf->header.local.len > 0) {
/* Header buffer is local, make a buffer pointing to the data. */
out[0].buf = ngx_calloc_buf(r->pool);
if (out[0].buf == NULL)
return NGX_ERROR;
out[0].buf->memory = 1;
out[0].buf->pos = alcf->header.local.data;
out[0].buf->last = alcf->header.local.data + alcf->header.local.len;
} else {
/* Prepare a buffer with the contents of the builtin header. */
out[0].buf = make_header_buf(r, alcf->css_href);
}
}
/* If footer is disabled, chain up footer buffer. */
if (alcf->footer.len == 0) {
ngx_uint_t last = (alcf->header.len == 0) ? 2 : 1;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http fancyindex: adding built-in footer at %i", last);
if (alcf->footer.path.len == 0 || alcf->footer.local.len > 0) {
ngx_uint_t last = (alcf->header.path.len == 0) ? 2 : 1;
out[last-1].next = &out[last];
out[last].buf = make_footer_buf(r);
out[last].buf = ngx_calloc_buf(r->pool);
if (out[last].buf == NULL)
return NGX_ERROR;
out[last].buf->memory = 1;
if (alcf->footer.local.len > 0) {
out[last].buf->pos = alcf->footer.local.data;
out[last].buf->last = alcf->footer.local.data + alcf->footer.local.len;
} else {
out[last].buf->pos = (u_char*) t08_foot1;
out[last].buf->last = (u_char*) t08_foot1 + sizeof(t08_foot1) - 1;
}
out[last-1].buf->last_in_chain = 0;
out[last].buf->last_in_chain = 1;
@ -1167,17 +1305,17 @@ add_builtin_header:
return NGX_HTTP_INTERNAL_SERVER_ERROR;
/* URI is configured, make Nginx take care of with a subrequest. */
sr_uri = &alcf->footer;
sr_uri = &alcf->footer.path;
if (*sr_uri->data != '/') {
/* Relative path */
rel_uri.len = r->uri.len + alcf->footer.len;
rel_uri.len = r->uri.len + alcf->footer.path.len;
rel_uri.data = ngx_palloc(r->pool, rel_uri.len);
if (rel_uri.data == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
ngx_memcpy(ngx_cpymem(rel_uri.data, r->uri.data, r->uri.len),
alcf->footer.data, alcf->footer.len);
alcf->footer.path.data, alcf->footer.path.len);
sr_uri = &rel_uri;
}
@ -1202,7 +1340,12 @@ add_builtin_header:
* we get something different from a 404?
*/
out[0].next = NULL;
out[0].buf = make_footer_buf(r);
out[0].buf = ngx_calloc_buf(r->pool);
if (out[0].buf == NULL)
return NGX_ERROR;
out[0].buf->memory = 1;
out[0].buf->pos = (u_char*) t08_foot1;
out[0].buf->last = (u_char*) t08_foot1 + sizeof(t08_foot1) - 1;
out[0].buf->last_in_chain = 1;
out[0].buf->last_buf = 1;
/* Directly send out the builtin footer */
@ -1212,26 +1355,9 @@ add_builtin_header:
return (r != r->main) ? rc : ngx_http_send_special(r, NGX_HTTP_LAST);
}
static ngx_int_t ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_dirs_first(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;
/* move the directories to the start */
if (first->dir && !second->dir) {
return -1;
}
if (!first->dir && second->dir) {
return 1;
}
return 0;
}
static ngx_int_t ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_name_desc(const void *one, const void *two)
static int ngx_libc_cdecl
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;
@ -1240,7 +1366,17 @@ ngx_http_fancyindex_cmp_entries_name_desc(const void *one, const void *two)
}
static ngx_int_t ngx_libc_cdecl
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)
{
ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
@ -1250,7 +1386,7 @@ ngx_http_fancyindex_cmp_entries_size_desc(const void *one, const void *two)
}
static ngx_int_t ngx_libc_cdecl
static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_mtime_desc(const void *one, const void *two)
{
ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
@ -1260,8 +1396,8 @@ ngx_http_fancyindex_cmp_entries_mtime_desc(const void *one, const void *two)
}
static ngx_int_t ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_name_asc(const void *one, const void *two)
static int ngx_libc_cdecl
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;
@ -1270,7 +1406,17 @@ ngx_http_fancyindex_cmp_entries_name_asc(const void *one, const void *two)
}
static ngx_int_t ngx_libc_cdecl
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)
{
ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
@ -1280,7 +1426,7 @@ ngx_http_fancyindex_cmp_entries_size_asc(const void *one, const void *two)
}
static ngx_int_t ngx_libc_cdecl
static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_mtime_asc(const void *one, const void *two)
{
ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
@ -1314,25 +1460,26 @@ ngx_http_fancyindex_create_loc_conf(ngx_conf_t *cf)
/*
* Set by ngx_pcalloc:
* conf->header.len = 0
* conf->header.data = NULL
* conf->footer.len = 0
* conf->footer.data = NULL
* conf->header.*.len = 0
* conf->header.*.data = NULL
* conf->footer.*.len = 0
* conf->footer.*.data = NULL
* conf->css_href.len = 0
* conf->css_href.data = NULL
* conf->time_format.len = 0
* conf->time_format.data = NULL
*/
conf->enable = NGX_CONF_UNSET;
conf->default_sort = NGX_CONF_UNSET_UINT;
conf->dirs_first = NGX_CONF_UNSET;
conf->localtime = NGX_CONF_UNSET;
conf->name_length = NGX_CONF_UNSET_UINT;
conf->exact_size = NGX_CONF_UNSET;
conf->ignore = NGX_CONF_UNSET_PTR;
conf->hide_symlinks = NGX_CONF_UNSET;
conf->show_path = NGX_CONF_UNSET;
conf->hide_parent = NGX_CONF_UNSET;
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;
conf->ignore = NGX_CONF_UNSET_PTR;
conf->hide_symlinks = NGX_CONF_UNSET;
conf->show_path = NGX_CONF_UNSET;
conf->hide_parent = NGX_CONF_UNSET;
conf->show_dot_files = NGX_CONF_UNSET;
return conf;
}
@ -1348,14 +1495,18 @@ 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);
ngx_conf_merge_value(conf->show_path, prev->show_path, 1);
ngx_conf_merge_uint_value(conf->name_length, prev->name_length, 50);
ngx_conf_merge_value(conf->show_dot_files, prev->show_dot_files, 0);
ngx_conf_merge_str_value(conf->header.path, prev->header.path, "");
ngx_conf_merge_str_value(conf->header.path, prev->header.local, "");
ngx_conf_merge_str_value(conf->footer.path, prev->footer.path, "");
ngx_conf_merge_str_value(conf->footer.path, prev->footer.local, "");
ngx_conf_merge_str_value(conf->header, prev->header, "");
ngx_conf_merge_str_value(conf->footer, prev->footer, "");
ngx_conf_merge_str_value(conf->css_href, prev->css_href, "");
ngx_conf_merge_str_value(conf->time_format, prev->time_format, "%Y-%b-%d %H:%M");
@ -1364,7 +1515,7 @@ ngx_http_fancyindex_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->hide_parent, prev->hide_parent, 0);
/* Just make sure we haven't disabled the show_path directive without providing a custom header */
if (conf->show_path == 0 && conf->header.len == 0)
if (conf->show_path == 0 && conf->header.path.len == 0)
{
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "FancyIndex : cannot set show_path to off without providing a custom header !");
return NGX_CONF_ERROR;

View file

@ -7,5 +7,5 @@ the fancyindex module.
nginx_start
content=$(fetch --with-headers)
grep 'Index of /' <<< "${content}" # It is an index
grep '\<table\>' <<< "${content}" # It contains a table
grep '<table\>' <<< "${content}" # It contains a table
grep '^ Content-Type:[[:space:]]*text/html' <<< "${content}"

View file

@ -1,6 +1,7 @@
#! /bin/bash
cat <<---
We test if the output from using "fancyindex_exact_size off" looks sane
This test checks if the output from using "fancyindex_exact_size off"
looks sane.
--
nginx_start 'fancyindex_exact_size off;'
content=$(fetch)

View file

@ -1,8 +1,8 @@
#! /bin/bash
cat <<---
This test fetches the root directory served by Nginx, which has no index
file, and checks the output contains a few HTML elements know to exist in
a directory index.
file, and checks that the output contains a few HTML elements known to
exist in a directory index.
--
use pup
nginx_start

View file

@ -1,6 +1,6 @@
#! /bin/bash
cat <<---
This test check the output using "fancyindex_hide_parent_dir on"
This test checks the output using "fancyindex_hide_parent_dir on".
--
use pup
nginx_start 'fancyindex_hide_parent_dir on;'

50
t/07-directory-first.test Normal file
View file

@ -0,0 +1,50 @@
#! /bin/bash
cat <<---
This test checks the output using "fancyindex_directories_first on".
--
use pup
for d in "008d" "000d" "004d" ; do
mkdir -p "${TESTDIR}/dir_first/${d}"
done
for f in "005f" "001f" "003f"; do
touch "${TESTDIR}/dir_first/${f}"
done
for d in "006d" "002d" ; do
mkdir -p "${TESTDIR}/dir_first/${d}"
done
nginx_start 'fancyindex_directories_first on;'
previous=''
cur_type=''
while read -r name ; do
case "$name" in
*Parent*)
;;
*d*)
echo "dir $name"
[[ "$cur_type" = f ]] && fail 'Directories should come before files'
cur_type=d
if [[ -z ${previous} ]] ; then
previous=${name}
else
[[ ${previous} < ${name} ]] || fail \
'Name %s should come before %s\n' "${previous}" "${name}"
fi
;;
*f*)
echo "file $name"
[[ -z "$cur_type" ]] && fail 'Directories should come before files'
if [[ "$cur_type" = d ]] ; then
cur_type=f
previous=${name}
else
[[ ${previous} < ${name} ]] || fail \
'Name %s should come before %s\n' "${previous}" "${name}"
fi
;;
esac
done < <( fetch '/dir_first/' \
| pup -p body table tbody 'td:nth-child(1)' text{} )
nginx_is_running || fail "Nginx died"

21
t/07-show_dotfiles.test Normal file
View file

@ -0,0 +1,21 @@
#! /bin/bash
cat <<---
This test checks the option to show dotfiles.
--
# Turn it on.
nginx_start 'fancyindex_show_dotfiles on;'
on_content=$(fetch /show_dotfiles/)
nginx_stop
if [ $(grep '.okay' <<< "${on_content}") -ne 0 ] ; then
exit 1
fi
# Turn it off.
nginx_start
off_content=$(fetch /show_dotfiles/)
nginx_stop
if [ $(grep '.okay' <<< "${on_content}") -eq 0] ; then
exit 1
fi
exit 0

17
t/08-local-footer.test Normal file
View file

@ -0,0 +1,17 @@
#! /bin/bash
cat <<---
This test checks that a local footer can be included with
"fancyindex_header ... local".
--
use pup
cat > "${TESTDIR}/footer" <<EOF
<div id="customfooter">yes</div>
EOF
nginx_start "fancyindex_footer \"${TESTDIR}/footer\" local;"
T=$(fetch / | pup -p body 'div#customfooter' text{})
[[ $T == yes ]] || fail 'Custom header missing'
nginx_is_running || fail 'Nginx died'

17
t/09-local-header.test Normal file
View file

@ -0,0 +1,17 @@
#! /bin/bash
cat <<---
This test checks that a local header can be included with
"fancyindex_header ... local".
--
use pup
cat > "${TESTDIR}/header" <<EOF
<div id="customheader">yes</div>
EOF
nginx_start "fancyindex_header \"${TESTDIR}/header\" local;"
T=$(fetch / | pup -p body 'div#customheader' text{})
[[ $T == yes ]] || fail 'Custom header missing'
nginx_is_running || fail 'Nginx died'

View file

@ -0,0 +1,26 @@
#! /bin/bash
cat <<---
This test checks that both a local header and footer can be included with
"fancyindex_{header,footer} ... local".
--
use pup
cat > "${TESTDIR}/header" <<EOF
<div id="customheader">yes</div>
EOF
cat > "${TESTDIR}/footer" <<EOF
<div id="customfooter">yes</div>
EOF
nginx_start "fancyindex_header \"${TESTDIR}/header\" local;
fancyindex_footer \"${TESTDIR}/footer\" local;"
P=$(fetch /)
H=$(pup -p body 'div#customheader' text{} <<< "$P")
[[ $H == yes ]] || fail 'Custom header missing'
F=$(pup -p body 'div#customfooter' text{} <<< "$P")
[[ $F == yes ]] || fail 'Custom footer missing'
nginx_is_running || fail 'Nginx died'

View file

@ -0,0 +1,31 @@
#! /bin/bash
cat <<---
This test checks that local footers are correctly included in the presence of
directives in nested locations:
fancyindex_footer <one> local;
location /sub {
fancyindex_footer <another> local;
}
--
use pup
echo '<div id="topfooter">yes</div>' > "${TESTDIR}/top-footer"
echo '<div id="subfooter">yes</div>' > "${TESTDIR}/sub-footer"
nginx_start "fancyindex_footer \"${TESTDIR}/top-footer\" local;
location /child-directory {
fancyindex_footer \"${TESTDIR}/sub-footer\" local;
}"
T=$(fetch /)
echo "$T" > "$TESTDIR/top.html"
[[ $(pup -p body 'div#topfooter' text{} <<< "$T") = yes ]] || fail 'Custom header missing at /'
[[ -z $(pup -p body 'div#subfooter' text{} <<< "$T") ]] || fail 'Wrong header at /'
T=$(fetch /child-directory/)
[[ $(pup -p body 'div#subfooter' text{} <<< "$T") = yes ]] || fail 'Custom header missing at /sub/'
[[ -z $(pup -p body 'div#topfooter' text{} <<< "$T") ]] || fail 'Wrong header at /sub/'
nginx_is_running || fail 'Nginx died'

View file

@ -0,0 +1,11 @@
#! /bin/bash
cat <<---
This test checks that the configuration file is properly parsed if there
is only one parameter passed to the fancyindex_header and fancyindex_footer
configuration directives.
--
nginx_start 'fancyindex_header "/header";
fancyindex_footer "/footer";'
nginx_is_running || fail 'Nginx died'

View file

@ -0,0 +1,9 @@
#! /bin/bash
cat <<---
Bug #107: 404 is returned when indexing filesystem root
https://github.com/aperezdc/ngx-fancyindex/issues/107
--
nginx_start 'root /;'
content=$(fetch)
grep 'Index of /' <<< "${content}" # It is an index
grep '<table\>' <<< "${content}" # It contains a table

View file

@ -0,0 +1,27 @@
#! /bin/bash
cat <<---
Check whether the Saturday long day name is available.
https://github.com/aperezdc/ngx-fancyindex/issues/157
--
use pup
nginx_start 'fancyindex_time_format "%A"; fancyindex_default_sort date;'
mkdir -p "${TESTDIR}/weekdays"
for (( i=2 ; i <= 8 ; i++ )) ; do
TZ=UTC touch -d "2023-01-0${i}T06:00:00" "${TESTDIR}/weekdays/day$i.txt"
done
ls "${TESTDIR}/weekdays"
content=$(fetch /weekdays/)
# We need row+1 because the first one is the table header.
dayname=$(pup -p body table tbody \
'tr:nth-child(7)' 'td:nth-child(3)' 'text{}' \
<<< "$content")
[[ $dayname = Saturday ]] || fail 'Sixth day is not Saturday'
dayname=$(pup -p body table tbody \
'tr:nth-child(8)' 'td:nth-child(3)' 'text{}' \
<<< "$content")
[[ $dayname = Sunday ]] || fail 'Seventh day is not Sunday'
nginx_is_running || fail 'Nginx died'

View file

@ -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 '\<alice\>' <<< "${content}" | grep '\<Bob\>' # Bob is after alice

View file

@ -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 '\<Bob\>' <<< "${content}" | grep '\<alice\>' # alice is after Bob

View file

@ -12,6 +12,15 @@ if [[ $2 -eq 1 ]] ; then
readonly DYNAMIC=$2
fi
case $(uname -s) in
Darwin)
JOBS=$(sysctl -n hw.activecpu)
;;
*)
JOBS=1
;;
esac
cd "$(dirname "$0")/.."
wget -O - http://nginx.org/download/nginx-${NGINX}.tar.gz | tar -xzf -
rm -rf prefix/
@ -19,7 +28,9 @@ cd nginx-${NGINX}
./configure \
--add-${DYNAMIC:+dynamic-}module=.. \
--with-http_addition_module \
--without-http_rewrite_module \
--prefix="$(pwd)/../prefix"
make -j"$JOBS"
make install
cd ..
exec ./t/run prefix ${DYNAMIC}

0
t/case-sensitivity/Bob Normal file
View file

0
t/case-sensitivity/alice Normal file
View file

View file

@ -1,8 +1,8 @@
#! /bin/bash
set -e
declare -r VERSION='0.4.0'
declare -r SHASUMS='\
ec9522193516ad49c78d40a8163f1d92e98866892a11aadb7be584a975026a8a pup_69c02e189c2aaed331061ee436c39e72b830ef32_darwin_amd64.xz
75c27caa0008a9cc639beb7506077ad9f32facbffcc4e815e999eaf9588a527e pup_v0.4.0_darwin_386.zip
c539a697efee2f8e56614a54cb3b215338e00de1f6a7c2fa93144ab6e1db8ebe pup_v0.4.0_darwin_amd64.zip
259eee82c7d7d766f1b8f93a382be21dcfefebc855a9ce8124fd78717f9df439 pup_v0.4.0_dragonfly_amd64.zip
@ -33,49 +33,73 @@ e965c6f04b897240d84c60e2c18226deb231a657c5583680f58a61051ff5a100 pup_v0.4.0_ope
6755cbd43e94eaf173689e93e914c7056a2249c2977e5b90024fb397f9b45ba4 pup_v0.4.0_windows_amd64.zip
'
declare -r BASEURL="https://github.com/ericchiang/pup/releases/download/v${VERSION}"
declare -r TDIR=$(dirname "$0")
ARCH=''
OS=''
case $(uname -m) in
x86_64 | amd64 ) ARCH=amd64 ;;
i[3456]86 ) ARCH=386 ;;
* ) ARCH= ;;
esac
OS=$(uname -s | tr 'A-Z' 'a-z')
case ${OS} in
linux | freebsd | openbsd | netbsd | darwin ) ;;
* ) OS=''
* ) OS= ;;
esac
# The binary of pup 0.4.0 for macOS provided by the original project
# crashes immediately on macOS 10.13 (Darwin 17) and up so use a fork:
# https://github.com/ericchiang/pup/issues/85
if [[ ${OS} = darwin && $(uname -r | cut -d. -f1) -ge 17 ]] ; then
USE_FORK=1
else
USE_FORK=0
fi
if (( USE_FORK )) ; then
declare -r VERSION=69c02e189c2aaed331061ee436c39e72b830ef32
declare -r DISTFILE="pup_${VERSION}_${OS}_${ARCH}.xz"
declare -r URL="https://github.com/frioux/pup/releases/download/untagged-${VERSION}/pup.mac.xz"
if ! command -v xz >/dev/null ; then
echo "xz not found" 1>&2
exit 3
fi
else
declare -r VERSION=0.4.0
declare -r DISTFILE="pup_v${VERSION}_${OS}_${ARCH}.zip"
declare -r URL="https://github.com/ericchiang/pup/releases/download/v${VERSION}/${DISTFILE}"
fi
if [[ -z ${ARCH} || -z ${OS} ]] ; then
echo "pup ${VERSION} is not available for $(uname -s) on $(uname -m)" 1>&2
exit 1
fi
declare -r ZIPFILE="pup_v${VERSION}_${OS}_${ARCH}.zip"
EXPECT_SHA=''
EXPECT_SHA=
while read sum fname ; do
if [[ ${fname} = ${ZIPFILE} ]] ; then
if [[ ${fname} = ${DISTFILE} ]] ; then
EXPECT_SHA=${sum}
break
fi
done <<< "${SHASUMS}"
wget -cO "${TDIR}/${ZIPFILE}" "${BASEURL}/${ZIPFILE}"
wget -cO "${TDIR}/${DISTFILE}" "${URL}"
read -r GOT_SHA _ < <( sha256sum "${TDIR}/${ZIPFILE}" )
read -r _ GOT_SHA < <( openssl sha256 < "${TDIR}/${DISTFILE}" )
if [[ ${EXPECT_SHA} = ${GOT_SHA} ]] ; then
echo "Checksum for ${ZIPFILE} verified :-)"
echo "Checksum for ${DISTFILE} verified :-)"
else
rm -f "${TDIR}/${ZIPFILE}" "${TDIR}/pup"
echo "Checksum for ${ZIPFILE} does not match :-("
rm -f "${TDIR}/${DISTFILE}" "${TDIR}/pup"
echo "Checksum for ${DISTFILE} does not match :-("
echo " Expected: ${EXPECT_SHA}"
echo " Got: ${GOT_SHA}"
exit 2
fi 1>&2
rm -f "${TDIR}/pup"
unzip "${TDIR}/${ZIPFILE}" pup -d "${TDIR}"
if (( USE_FORK )) ; then
(cd "${TDIR}" && xz -dk "${DISTFILE}" && mv "${DISTFILE%.*}" pup && chmod a+x pup)
else
unzip "${TDIR}/${DISTFILE}" pup -d "${TDIR}"
fi

View file

@ -3,7 +3,7 @@
# preamble
# Copyright (C) 2016 Adrian Perez <aperez@igalia.com>
#
# Distributed under terms of the MIT license.
# SPDX-License-Identifier: BSD-2-Clause
#
function nginx_conf_generate () {
@ -20,7 +20,7 @@ function nginx_conf_generate () {
keepalive_timeout 65;
server {
server_name localhost;
listen 127.0.0.1:8888;
listen 127.0.0.1:${NGINX_PORT};
root ${TESTDIR};
error_page 500 502 503 504 /50x.html;
location = /50x.html { root html; }
@ -36,6 +36,19 @@ function nginx_conf_generate () {
readonly NGINX_CONF="${PREFIX}/conf/nginx.conf"
readonly NGINX_PID="${PREFIX}/logs/nginx.pid"
case $(uname -s) in
Darwin)
NGINX_PORT=$(netstat -a -n -finet -ptcp | awk '/LISTEN/ { sub(".+\\.", "", $4) ; seen[$4]=1 }
END { p=1025 ; while (seen[p]) p++; print p}')
;;
*)
NGINX_PORT=$(ss -4Htnl | awk '{ sub("[^:]+:", "", $4) ; seen[$4]=1 }
END { p=1025 ; while (seen[p]) p++; print p}')
;;
esac
readonly NGINX_PORT
rm -f "${NGINX_CONF}" "${NGINX_PID}"
mkdir -p "${PREFIX}/logs"
@ -77,6 +90,11 @@ function nginx_start () {
if [[ $# -gt 0 || ! -r ${NGINX_CONF} ]] ; then nginx_conf "$@" ; fi
nginx_stop # Ensure that it is not running.
nginx
local n=0
while [[ ! -r ${NGINX_PID} && n -lt 20 ]] ; do
sleep 0.1 # Wait until pid exists.
n=$((n+1))
done
}
function fetch () {
@ -85,7 +103,7 @@ function fetch () {
opts+=( -S )
shift
fi
wget "${opts[@]}" -O- "http://localhost:8888${1:-/}" 2>&1
wget "${opts[@]}" -O- "http://localhost:${NGINX_PORT}${1:-/}" 2>&1
}
function skip () {

2
t/run
View file

@ -1,4 +1,4 @@
#! /bin/bash
#!/bin/bash
set -e
if [[ $# -lt 1 || $# -gt 2 ]] ; then

0
t/show_dotfiles/.okay Normal file
View file

View file

@ -3,7 +3,7 @@
# Copyright © Adrian Perez <aperez@igalia.com>
#
# Converts an HTML template into a C header suitable for inclusion.
# Take a look at the HACKING.rst file to know how to use it :-)
# Take a look at the HACKING.md file to know how to use it :-)
#
# This code is placed in the public domain.

View file

@ -11,6 +11,9 @@ static const u_char t01_head1[] = ""
"font-family:\"Bitstream Vera Sans\",\"Lucida Grande\","
"\"Lucida Sans Unicode\",Lucidux,Verdana,Lucida,sans-serif;"
"}"
"table {"
"table-layout: fixed;"
"}"
"tr:nth-child(even) {"
"background:#f4f4f4;"
"}"
@ -33,6 +36,11 @@ static const u_char t01_head1[] = ""
"a:hover {"
"color:#e33;"
"}"
".link {"
"white-space: nowrap;"
"text-overflow: '>';"
"overflow: hidden;"
"}"
"</style>"
"\n"
;
@ -57,9 +65,9 @@ static const u_char t06_list1[] = ""
"<table id=\"list\">"
"<thead>"
"<tr>"
"<th style=\"width:55%\"><a href=\"?C=N&amp;O=A\">File Name</a>&nbsp;<a href=\"?C=N&amp;O=D\">&nbsp;&darr;&nbsp;</a></th>"
"<th style=\"width:20%\"><a href=\"?C=S&amp;O=A\">File Size</a>&nbsp;<a href=\"?C=S&amp;O=D\">&nbsp;&darr;&nbsp;</a></th>"
"<th style=\"width:25%\"><a href=\"?C=M&amp;O=A\">Date</a>&nbsp;<a href=\"?C=M&amp;O=D\">&nbsp;&darr;&nbsp;</a></th>"
"<th colspan=\"2\"><a href=\"?C=N&amp;O=A\">File Name</a>&nbsp;<a href=\"?C=N&amp;O=D\">&nbsp;&darr;&nbsp;</a></th>"
"<th><a href=\"?C=S&amp;O=A\">File Size</a>&nbsp;<a href=\"?C=S&amp;O=D\">&nbsp;&darr;&nbsp;</a></th>"
"<th><a href=\"?C=M&amp;O=A\">Date</a>&nbsp;<a href=\"?C=M&amp;O=D\">&nbsp;&darr;&nbsp;</a></th>"
"</tr>"
"</thead>"
"\n"
@ -67,7 +75,7 @@ static const u_char t06_list1[] = ""
;
static const u_char t_parentdir_entry[] = ""
"<tr>"
"<td class=\"link\"><a href=\"../?C=N&amp;O=A\">Parent directory/</a></td>"
"<td colspan=\"2\" class=\"link\"><a href=\"../?C=N&amp;O=A\">Parent directory/</a></td>"
"<td class=\"size\">-</td>"
"<td class=\"date\">-</td>"
"</tr>"

View file

@ -10,6 +10,9 @@
font-family:"Bitstream Vera Sans","Lucida Grande",
"Lucida Sans Unicode",Lucidux,Verdana,Lucida,sans-serif;
}
table {
table-layout: fixed;
}
tr:nth-child(even) {
background:#f4f4f4;
}
@ -32,6 +35,11 @@
a:hover {
color:#e33;
}
.link {
white-space: nowrap;
text-overflow: '>';
overflow: hidden;
}
</style>
<!-- var t02_head2 -->
@ -55,33 +63,33 @@
<table id="list">
<thead>
<tr>
<th style="width:55%"><a href="?C=N&amp;O=A">File Name</a>&nbsp;<a href="?C=N&amp;O=D">&nbsp;&darr;&nbsp;</a></th>
<th style="width:20%"><a href="?C=S&amp;O=A">File Size</a>&nbsp;<a href="?C=S&amp;O=D">&nbsp;&darr;&nbsp;</a></th>
<th style="width:25%"><a href="?C=M&amp;O=A">Date</a>&nbsp;<a href="?C=M&amp;O=D">&nbsp;&darr;&nbsp;</a></th>
<th colspan="2"><a href="?C=N&amp;O=A">File Name</a>&nbsp;<a href="?C=N&amp;O=D">&nbsp;&darr;&nbsp;</a></th>
<th><a href="?C=S&amp;O=A">File Size</a>&nbsp;<a href="?C=S&amp;O=D">&nbsp;&darr;&nbsp;</a></th>
<th><a href="?C=M&amp;O=A">Date</a>&nbsp;<a href="?C=M&amp;O=D">&nbsp;&darr;&nbsp;</a></th>
</tr>
</thead>
<tbody>
<!-- var t_parentdir_entry -->
<tr>
<td class="link"><a href="../?C=N&amp;O=A">Parent directory/</a></td>
<td colspan="2" class="link"><a href="../?C=N&amp;O=A">Parent directory/</a></td>
<td class="size">-</td>
<td class="date">-</td>
</tr>
<!-- var NONE -->
<tr>
<td>test file 1</td>
<td colspan="2">test file 1</td>
<td>123kB</td>
<td>date</td>
</tr>
<tr>
<td>test file 2</td>
<td colspan="2">test file 2</td>
<td>321MB</td>
<td>date</td>
</tr>
<tr>
<td>test file 3</td>
<td colspan="2">test file 3</td>
<td>666</td>
<td>date</td>
</tr>