diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py index c9dab901..88e57bed 100644 --- a/copyparty/httpcli.py +++ b/copyparty/httpcli.py @@ -17,6 +17,7 @@ import threading # typechk import time import uuid from datetime import datetime +from email.utils import formatdate, parsedate from operator import itemgetter import jinja2 # typechk @@ -33,7 +34,6 @@ from .star import StreamTar from .sutil import StreamArc # typechk from .szip import StreamZip from .util import ( - HTTP_TS_FMT, HTTPCODE, META_NOBOTS, MultipartParser, @@ -54,7 +54,6 @@ from .util import ( hashcopy, html_bescape, html_escape, - http_ts, humansize, ipnorm, min_ex, @@ -515,7 +514,7 @@ class HttpCli(object): # close if unknown length, otherwise take client's preference response.append("Connection: " + ("Keep-Alive" if self.keepalive else "Close")) - response.append("Date: " + datetime.utcnow().strftime(HTTP_TS_FMT)) + response.append("Date: " + formatdate(usegmt=True)) # headers{} overrides anything set previously if headers: @@ -831,9 +830,7 @@ class HttpCli(object): pvs: dict[str, str] = { "displayname": html_escape(vp.split("/")[-1]), - "getlastmodified": datetime.utcfromtimestamp(st.st_mtime).strftime( - HTTP_TS_FMT - ), + "getlastmodified": formatdate(st.st_mtime, usegmt=True), "resourcetype": '' if isdir else "", "supportedlock": '', } @@ -2195,13 +2192,14 @@ class HttpCli(object): return True def _chk_lastmod(self, file_ts: int) -> tuple[str, bool]: - file_lastmod = http_ts(file_ts) + file_lastmod = formatdate(file_ts, usegmt=True) cli_lastmod = self.headers.get("if-modified-since") if cli_lastmod: try: # some browser append "; length=573" cli_lastmod = cli_lastmod.split(";")[0].strip() - cli_dt = time.strptime(cli_lastmod, HTTP_TS_FMT) + cli_dt = parsedate(cli_lastmod) + assert cli_dt cli_ts = calendar.timegm(cli_dt) return file_lastmod, int(file_ts) > int(cli_ts) except Exception as ex: @@ -2479,8 +2477,7 @@ class HttpCli(object): chrome = " rv:" not in self.ua mime, ico = self.ico.get(ext, not exact, chrome) - dt = datetime.utcfromtimestamp(self.E.t0) - lm = dt.strftime(HTTP_TS_FMT) + lm = formatdate(self.E.t0, usegmt=True) self.reply(ico, mime=mime, headers={"Last-Modified": lm}) return True diff --git a/copyparty/util.py b/copyparty/util.py index b7f0fa40..246e7147 100644 --- a/copyparty/util.py +++ b/copyparty/util.py @@ -24,6 +24,7 @@ import time import traceback from collections import Counter from datetime import datetime +from email.utils import formatdate from ipaddress import IPv6Address from queue import Queue @@ -137,8 +138,6 @@ else: SYMTIME = sys.version_info > (3, 6) and os.utime in os.supports_follow_symlinks -HTTP_TS_FMT = "%a, %d %b %Y %H:%M:%S GMT" - META_NOBOTS = '' HTTPCODE = { @@ -1476,8 +1475,7 @@ def gen_filekey_dbg( def gencookie(k: str, v: str, dur: Optional[int]) -> str: v = v.replace(";", "") if dur: - dt = datetime.utcfromtimestamp(time.time() + dur) - exp = dt.strftime(HTTP_TS_FMT) + exp = formatdate(time.time() + dur, usegmt=True) else: exp = "Fri, 15 Aug 1997 01:00:00 GMT" @@ -1637,11 +1635,6 @@ def ipnorm(ip: str) -> str: return ip -def http_ts(ts: int) -> str: - file_dt = datetime.utcfromtimestamp(ts) - return file_dt.strftime(HTTP_TS_FMT) - - def html_escape(s: str, quot: bool = False, crlf: bool = False) -> str: """html.escape but also newlines""" s = s.replace("&", "&").replace("<", "<").replace(">", ">")