mirror of
https://github.com/9001/copyparty.git
synced 2025-09-28 12:42:26 -06:00
url-param "dl" downloads file
This commit is contained in:
parent
68503444c7
commit
48d6224ec8
|
@ -12,7 +12,6 @@ import random
|
||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
import stat
|
import stat
|
||||||
import string
|
|
||||||
import sys
|
import sys
|
||||||
import threading # typechk
|
import threading # typechk
|
||||||
import time
|
import time
|
||||||
|
@ -31,7 +30,7 @@ try:
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
from .__init__ import ANYWIN, PY2, RES, TYPE_CHECKING, EnvParams, unicode
|
from .__init__ import ANYWIN, RES, TYPE_CHECKING, EnvParams, unicode
|
||||||
from .__version__ import S_VERSION
|
from .__version__ import S_VERSION
|
||||||
from .authsrv import LEELOO_DALLAS, VFS # typechk
|
from .authsrv import LEELOO_DALLAS, VFS # typechk
|
||||||
from .bos import bos
|
from .bos import bos
|
||||||
|
@ -66,6 +65,7 @@ from .util import (
|
||||||
exclude_dotfiles,
|
exclude_dotfiles,
|
||||||
formatdate,
|
formatdate,
|
||||||
fsenc,
|
fsenc,
|
||||||
|
gen_content_disposition,
|
||||||
gen_filekey,
|
gen_filekey,
|
||||||
gen_filekey_dbg,
|
gen_filekey_dbg,
|
||||||
gencookie,
|
gencookie,
|
||||||
|
@ -4013,6 +4013,13 @@ class HttpCli(object):
|
||||||
if not editions:
|
if not editions:
|
||||||
return self.tx_404()
|
return self.tx_404()
|
||||||
|
|
||||||
|
#
|
||||||
|
# force download
|
||||||
|
|
||||||
|
if "dl" in self.ouparam:
|
||||||
|
cdis = gen_content_disposition(os.path.basename(req_path))
|
||||||
|
self.out_headers["Content-Disposition"] = cdis
|
||||||
|
|
||||||
#
|
#
|
||||||
# if-modified
|
# if-modified
|
||||||
|
|
||||||
|
@ -4181,6 +4188,13 @@ class HttpCli(object):
|
||||||
if not editions:
|
if not editions:
|
||||||
return self.tx_404()
|
return self.tx_404()
|
||||||
|
|
||||||
|
#
|
||||||
|
# force download
|
||||||
|
|
||||||
|
if "dl" in self.ouparam:
|
||||||
|
cdis = gen_content_disposition(os.path.basename(req_path))
|
||||||
|
self.out_headers["Content-Disposition"] = cdis
|
||||||
|
|
||||||
#
|
#
|
||||||
# if-modified
|
# if-modified
|
||||||
|
|
||||||
|
@ -4729,24 +4743,7 @@ class HttpCli(object):
|
||||||
if maxn < nf:
|
if maxn < nf:
|
||||||
raise Pebkac(400, t)
|
raise Pebkac(400, t)
|
||||||
|
|
||||||
safe = (string.ascii_letters + string.digits).replace("%", "")
|
cdis = gen_content_disposition("%s.%s" % (fn, ext))
|
||||||
afn = "".join([x if x in safe.replace('"', "") else "_" for x in fn])
|
|
||||||
bascii = unicode(safe).encode("utf-8")
|
|
||||||
zb = fn.encode("utf-8", "xmlcharrefreplace")
|
|
||||||
if not PY2:
|
|
||||||
zbl = [
|
|
||||||
chr(x).encode("utf-8")
|
|
||||||
if x in bascii
|
|
||||||
else "%{:02x}".format(x).encode("ascii")
|
|
||||||
for x in zb
|
|
||||||
]
|
|
||||||
else:
|
|
||||||
zbl = [unicode(x) if x in bascii else "%{:02x}".format(ord(x)) for x in zb]
|
|
||||||
|
|
||||||
ufn = b"".join(zbl).decode("ascii")
|
|
||||||
|
|
||||||
cdis = "attachment; filename=\"{}.{}\"; filename*=UTF-8''{}.{}"
|
|
||||||
cdis = cdis.format(afn, ext, ufn, ext)
|
|
||||||
self.log(repr(cdis))
|
self.log(repr(cdis))
|
||||||
self.send_headers(None, mime=mime, headers={"Content-Disposition": cdis})
|
self.send_headers(None, mime=mime, headers={"Content-Disposition": cdis})
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ from .__init__ import (
|
||||||
VT100,
|
VT100,
|
||||||
WINDOWS,
|
WINDOWS,
|
||||||
EnvParams,
|
EnvParams,
|
||||||
|
unicode,
|
||||||
)
|
)
|
||||||
from .__version__ import S_BUILD_DT, S_VERSION
|
from .__version__ import S_BUILD_DT, S_VERSION
|
||||||
from .stolen import surrogateescape
|
from .stolen import surrogateescape
|
||||||
|
@ -115,6 +116,10 @@ IP6ALL = "0:0:0:0:0:0:0:0"
|
||||||
IP6_LL = ("fe8", "fe9", "fea", "feb")
|
IP6_LL = ("fe8", "fe9", "fea", "feb")
|
||||||
IP64_LL = ("fe8", "fe9", "fea", "feb", "169.254")
|
IP64_LL = ("fe8", "fe9", "fea", "feb", "169.254")
|
||||||
|
|
||||||
|
UC_CDISP = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._"
|
||||||
|
BC_CDISP = UC_CDISP.encode("ascii")
|
||||||
|
UC_CDISP_SET = set(UC_CDISP)
|
||||||
|
BC_CDISP_SET = set(BC_CDISP)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import fcntl
|
import fcntl
|
||||||
|
@ -2073,6 +2078,29 @@ def gencookie(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def gen_content_disposition(fn: str) -> str:
|
||||||
|
safe = UC_CDISP_SET
|
||||||
|
bsafe = BC_CDISP_SET
|
||||||
|
fn = fn.replace("/", "_").replace("\\", "_")
|
||||||
|
zb = fn.encode("utf-8", "xmlcharrefreplace")
|
||||||
|
if not PY2:
|
||||||
|
zbl = [
|
||||||
|
chr(x).encode("utf-8")
|
||||||
|
if x in bsafe
|
||||||
|
else "%{:02X}".format(x).encode("ascii")
|
||||||
|
for x in zb
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
zbl = [unicode(x) if x in bsafe else "%{:02X}".format(ord(x)) for x in zb]
|
||||||
|
|
||||||
|
ufn = b"".join(zbl).decode("ascii")
|
||||||
|
afn = "".join([x if x in safe else "_" for x in fn]).lstrip(".")
|
||||||
|
while ".." in afn:
|
||||||
|
afn = afn.replace("..", ".")
|
||||||
|
|
||||||
|
return "attachment; filename=\"%s\"; filename*=UTF-8''%s" % (afn, ufn)
|
||||||
|
|
||||||
|
|
||||||
def humansize(sz: float, terse: bool = False) -> str:
|
def humansize(sz: float, terse: bool = False) -> str:
|
||||||
for unit in HUMANSIZE_UNITS:
|
for unit in HUMANSIZE_UNITS:
|
||||||
if sz < 1024:
|
if sz < 1024:
|
||||||
|
|
|
@ -160,6 +160,7 @@ authenticate using header `Cookie: cppwd=foo` or url param `&pw=foo`
|
||||||
|
|
||||||
| method | params | result |
|
| method | params | result |
|
||||||
|--|--|--|
|
|--|--|--|
|
||||||
|
| GET | `?dl` | download file (don't show in-browser) |
|
||||||
| GET | `?ls` | list files/folders at URL as JSON |
|
| GET | `?ls` | list files/folders at URL as JSON |
|
||||||
| GET | `?ls&dots` | list files/folders at URL as JSON, including dotfiles |
|
| GET | `?ls&dots` | list files/folders at URL as JSON, including dotfiles |
|
||||||
| GET | `?ls=t` | list files/folders at URL as plaintext |
|
| GET | `?ls=t` | list files/folders at URL as plaintext |
|
||||||
|
|
Loading…
Reference in a new issue