diff --git a/changes-entries/66182.txt b/changes-entries/66182.txt new file mode 100644 index 00000000000..95112c102ee --- /dev/null +++ b/changes-entries/66182.txt @@ -0,0 +1,3 @@ + *) mod_autoindex: Fix a FancyIndexing listing sorted by last-modified + date (?C=M) showing 1970-01-01 for files modified before 1970, + instead of their real date. PR 66182 [Arturo Bernal] diff --git a/modules/generators/mod_autoindex.c b/modules/generators/mod_autoindex.c index 37bed118b06..a6ff4119b11 100644 --- a/modules/generators/mod_autoindex.c +++ b/modules/generators/mod_autoindex.c @@ -1416,14 +1416,9 @@ static struct ent *make_autoindex_entry(const apr_finfo_t *dirent, } ap_destroy_sub_req(rr); /* - * We don't need to take any special action for the file size key. - * If we did, it would go here. + * We don't need to take any special action for the file size or + * last-modified keys. If we did, it would go here. */ - if (keyid == K_LAST_MOD) { - if (p->lm < 0) { - p->lm = 0; - } - } return (p); } diff --git a/test/modules/generators/test_002_autoindex.py b/test/modules/generators/test_002_autoindex.py index 14d05bdc3f8..767f5f2abbb 100644 --- a/test/modules/generators/test_002_autoindex.py +++ b/test/modules/generators/test_002_autoindex.py @@ -1,9 +1,15 @@ +import calendar +import os import textwrap import pytest from pyhttpd.conf import HttpdConf +# A modification time before the 1970 epoch, to check that mod_autoindex +# does not clamp it when sorting by last-modified (BZ 66182). +OLD_MTIME = calendar.timegm((1958, 1, 1, 0, 0, 0, 0, 0, 0)) + class TestAutoindex: @@ -17,11 +23,23 @@ def _class_scope(self, env): Options +Indexes IndexOptions FancyIndexing ScanHTMLTitles + + Options +Indexes + IndexOptions FancyIndexing + """), }) conf.add_vhost(domains=[domain], port=env.http_port, doc_root="htdocs/autoindex") conf.install() + + oldmtime_dir = os.path.join(env.server_docs_dir, "autoindex", "oldmtime") + os.makedirs(oldmtime_dir, exist_ok=True) + oldfile = os.path.join(oldmtime_dir, "oldfile.txt") + with open(oldfile, "w") as f: + f.write("old file\n") + os.utime(oldfile, (OLD_MTIME, OLD_MTIME)) + assert env.apache_restart() == 0 def test_generators_002_01_scan_title_bare_amp(self, env): @@ -32,3 +50,22 @@ def test_generators_002_01_scan_title_bare_amp(self, env): r = env.curl_get(env.mkurl("http", "autoindex", "/listing/")) assert r.response["status"] == 200 assert "AT&T" in r.response["body"].decode() + + def test_generators_002_02_old_mtime_not_clamped_when_sorted(self, env): + """A file modified before 1970 keeps its real date when the listing + is explicitly sorted by last-modified (?C=M). Before the fix, + make_autoindex_entry() clamped any negative apr_time_t to 0 when + keyid == K_LAST_MOD, displaying 1970-01-01 instead of the real + 1958 date -- even though the unsorted, default-order listing (which + does not hit that code path) already showed it correctly.""" + unsorted = env.curl_get(env.mkurl("http", "autoindex", "/oldmtime/")) + assert unsorted.response["status"] == 200 + unsorted_body = unsorted.response["body"].decode() + assert "1958-01-01" in unsorted_body + + sorted_by_date = env.curl_get( + env.mkurl("http", "autoindex", "/oldmtime/?C=M;O=A")) + assert sorted_by_date.response["status"] == 200 + sorted_body = sorted_by_date.response["body"].decode() + assert "1958-01-01" in sorted_body + assert "1970-01-01" not in sorted_body