support long filepaths on win7 + misc windows fixes

This commit is contained in:
ed 2023-02-10 18:37:37 +00:00
parent d7f1951e44
commit a4b56c74c7
13 changed files with 179 additions and 84 deletions

View file

@ -1350,7 +1350,7 @@ enable [thumbnails](#thumbnails) of...
* **AVIF pictures:** `pyvips` or `ffmpeg` or `pillow-avif-plugin`
* **JPEG XL pictures:** `pyvips` or `ffmpeg`
enable [smb](#smb-server) support:
enable [smb](#smb-server) support (**not** recommended):
* `impacket==0.10.0`
`pyvips` gives higher quality thumbnails than `Pillow` and is 320% faster, using 270% more ram: `sudo apt install libvips42 && python3 -m pip install --user -U pyvips`

View file

@ -61,7 +61,7 @@ def main():
os.chdir(cwd)
f1 = fsenc(fn)
f2 = os.path.join(b"noexif", f1)
f2 = fsenc(os.path.join(b"noexif", fn))
cmd = [
b"exiftool",
b"-exif:all=",

View file

@ -36,8 +36,10 @@ from .util import (
UNPLICATIONS,
align_tab,
ansi_re,
is_exe,
min_ex,
py_desc,
pybin,
termsize,
wrap,
)
@ -1065,6 +1067,9 @@ def main(argv: Optional[list[str]] = None) -> None:
showlic()
sys.exit(0)
if is_exe:
print("pybin: {}\n".format(pybin), end="")
ensure_locale()
if HAVE_SSL:
ensure_cert()

View file

@ -14,7 +14,7 @@ from datetime import datetime
from .__init__ import ANYWIN, TYPE_CHECKING, WINDOWS
from .bos import bos
from .cfg import vf_bmap, vf_vmap, vf_cmap, onedash, flagdescs, permdescs
from .cfg import vf_bmap, vf_vmap, vf_cmap, flagdescs, permdescs
from .util import (
IMPLICATIONS,
META_NOBOTS,
@ -22,7 +22,7 @@ from .util import (
UNPLICATIONS,
Pebkac,
absreal,
fsenc,
afsenc,
get_df,
humansize,
relchk,
@ -1083,7 +1083,7 @@ class AuthSrv(object):
promote = []
demote = []
for vol in vfs.all_vols.values():
zb = hashlib.sha512(fsenc(vol.realpath)).digest()
zb = hashlib.sha512(afsenc(vol.realpath)).digest()
hid = base64.b32encode(zb).decode("ascii").lower()
vflag = vol.flags.get("hist")
if vflag == "-":
@ -1102,7 +1102,7 @@ class AuthSrv(object):
except:
owner = None
me = fsenc(vol.realpath).rstrip()
me = afsenc(vol.realpath).rstrip()
if owner not in [None, me]:
continue

View file

@ -21,6 +21,7 @@ from .util import (
exclude_dotfiles,
fsenc,
ipnorm,
pybin,
relchk,
sanitize_fn,
vjoin,
@ -135,7 +136,8 @@ class FtpFs(AbstractedFS):
try:
vpath = vpath.replace("\\", "/").lstrip("/")
rd, fn = os.path.split(vpath)
if ANYWIN and not relchk(rd):
if ANYWIN and relchk(rd):
logging.warning("malicious vpath: %s", vpath)
raise FilesystemError("unsupported characters in filepath")
fn = sanitize_fn(fn or "", "", [".prologue.html", ".epilogue.html"])
@ -417,7 +419,7 @@ class Ftpd(object):
h1 = SftpHandler
except:
t = "\nftps requires pyopenssl;\nplease run the following:\n\n {} -m pip install --user pyopenssl\n"
print(t.format(sys.executable))
print(t.format(pybin))
sys.exit(1)
h1.certfile = os.path.join(self.args.E.cfg, "cert.pem")
@ -450,10 +452,18 @@ class Ftpd(object):
lgr = logging.getLogger("pyftpdlib")
lgr.setLevel(logging.DEBUG if self.args.ftpv else logging.INFO)
ips = self.args.i
if "::" in ips:
ips.append("0.0.0.0")
ioloop = IOLoop()
for ip in self.args.i:
for ip in ips:
for h, lp in hs:
FTPServer((ip, int(lp)), h, ioloop)
try:
FTPServer((ip, int(lp)), h, ioloop)
except:
if ip != "0.0.0.0" or "::" not in ips:
raise
Daemon(ioloop.loop, "ftp")

View file

@ -10,7 +10,17 @@ import sys
from .__init__ import PY2, WINDOWS, E, unicode
from .bos import bos
from .util import REKOBO_LKEY, fsenc, min_ex, retchk, runcmd, uncyg
from .util import (
REKOBO_LKEY,
sfsenc,
fsenc,
is_exe,
min_ex,
pybin,
retchk,
runcmd,
uncyg,
)
if True: # pylint: disable=using-constant-test
from typing import Any, Union
@ -285,9 +295,14 @@ class MTag(object):
self.log(msg, c=3)
if not self.usable:
if is_exe:
t = "need ffmpeg to read media tags; copyparty.exe cannot use mutagen"
self.log(t)
return
msg = "need Mutagen{} to read media tags so please run this:\n{}{} -m pip install --user mutagen\n"
pybin = os.path.basename(sys.executable)
self.log(msg.format(or_ffprobe, " " * 37, pybin), c=1)
pyname = os.path.basename(pybin)
self.log(msg.format(or_ffprobe, " " * 37, pyname), c=1)
return
# https://picard-docs.musicbrainz.org/downloads/MusicBrainz_Picard_Tag_Map.html
@ -519,12 +534,15 @@ class MTag(object):
env = os.environ.copy()
try:
if is_exe:
raise Exception()
pypath = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
zsl = [str(pypath)] + [str(x) for x in sys.path if x]
pypath = str(os.pathsep.join(zsl))
env["PYTHONPATH"] = pypath
except:
if not E.ox:
if not E.ox and not is_exe:
raise
ret: dict[str, Any] = {}
@ -532,7 +550,7 @@ class MTag(object):
try:
cmd = [parser.bin, abspath]
if parser.bin.endswith(".py"):
cmd = [sys.executable] + cmd
cmd = [pybin] + cmd
args = {
"env": env,
@ -551,7 +569,7 @@ class MTag(object):
else:
cmd = ["nice"] + cmd
bcmd = [fsenc(x) for x in cmd]
bcmd = [sfsenc(x) for x in cmd[:-1]] + [fsenc(cmd[-1])]
rc, v, err = runcmd(bcmd, **args) # type: ignore
retchk(rc, bcmd, err, self.log, 5, self.args.mtag_v)
v = v.strip()

View file

@ -12,7 +12,7 @@ from types import SimpleNamespace
from .__init__ import ANYWIN, TYPE_CHECKING
from .authsrv import LEELOO_DALLAS, VFS
from .bos import bos
from .util import Daemon, min_ex
from .util import Daemon, is_exe, min_ex, pybin
if True: # pylint: disable=using-constant-test
from typing import Any
@ -42,8 +42,12 @@ class SMB(object):
from impacket import smbserver
from impacket.ntlm import compute_lmhash, compute_nthash
except ImportError:
if is_exe:
print("copyparty.exe cannot do SMB")
sys.exit(1)
m = "\033[36m\n{}\033[31m\n\nERROR: need 'impacket'; please run this command:\033[33m\n {} -m pip install --user impacket\n\033[0m"
print(m.format(min_ex(), sys.executable))
print(m.format(min_ex(), pybin))
sys.exit(1)
# patch vfs into smbserver.os

View file

@ -44,6 +44,7 @@ from .util import (
ansi_re,
min_ex,
mp,
pybin,
start_log_thrs,
start_stackmon,
)
@ -206,7 +207,7 @@ class SvcHub(object):
self.thumbsrv = ThumbSrv(self)
else:
msg = "need either Pillow, pyvips, or FFmpeg to create thumbnails; for example:\n{0}{1} -m pip install --user Pillow\n{0}{1} -m pip install --user pyvips\n{0}apt install ffmpeg"
msg = msg.format(" " * 37, os.path.basename(sys.executable))
msg = msg.format(" " * 37, os.path.basename(pybin))
self.log("thumb", msg, c=3)
if not args.no_acode and args.no_thumb:
@ -413,7 +414,7 @@ class SvcHub(object):
lh = codecs.open(fn, "w", encoding="utf-8", errors="replace")
argv = [sys.executable] + self.argv
argv = [pybin] + self.argv
if hasattr(shlex, "quote"):
argv = [shlex.quote(x) for x in argv]
else:

View file

@ -20,6 +20,7 @@ from .util import (
Cooldown,
Daemon,
Pebkac,
afsenc,
fsenc,
min_ex,
runcmd,
@ -82,14 +83,14 @@ def thumb_path(histpath: str, rem: str, mtime: float, fmt: str) -> str:
# base64 = 64 = 4096
rd, fn = vsplit(rem)
if rd:
h = hashlib.sha512(fsenc(rd)).digest()
h = hashlib.sha512(afsenc(rd)).digest()
b64 = base64.urlsafe_b64encode(h).decode("ascii")[:24]
rd = "{}/{}/".format(b64[:2], b64[2:4]).lower() + b64
else:
rd = "top"
# could keep original filenames but this is safer re pathlen
h = hashlib.sha512(fsenc(fn)).digest()
h = hashlib.sha512(afsenc(fn)).digest()
fn = base64.urlsafe_b64encode(h).decode("ascii")[:24]
if fmt in ("opus", "caf"):
@ -201,7 +202,7 @@ class ThumbSrv(object):
inf_path = os.path.join(thdir, "dir.txt")
if not bos.path.exists(inf_path):
with open(inf_path, "wb") as f:
f.write(fsenc(os.path.dirname(abspath)))
f.write(afsenc(os.path.dirname(abspath)))
self.busy[tpath] = [cond]
do_conv = True

View file

@ -37,6 +37,7 @@ from .util import (
atomic_move,
db_ex_chk,
djoin,
sfsenc,
fsenc,
gen_filekey,
gen_filekey_dbg,
@ -395,7 +396,7 @@ class Up2k(object):
def _vis_job_progress(self, job: dict[str, Any]) -> str:
perc = 100 - (len(job["need"]) * 100.0 / len(job["hash"]))
path = os.path.join(job["ptop"], job["prel"], job["name"])
path = djoin(job["ptop"], job["prel"], job["name"])
return "{:5.1f}% {}".format(perc, path)
def _vis_reg_progress(self, reg: dict[str, dict[str, Any]]) -> list[str]:
@ -691,7 +692,7 @@ class Up2k(object):
pass
for k, job in reg2.items():
path = os.path.join(job["ptop"], job["prel"], job["name"])
path = djoin(job["ptop"], job["prel"], job["name"])
if bos.path.exists(path):
reg[k] = job
job["poke"] = time.time()
@ -1086,7 +1087,7 @@ class Up2k(object):
else:
rd = drd
abspath = os.path.join(top, rd)
abspath = djoin(top, rd)
self.pp.msg = "b{} {}".format(ndirs - nchecked, abspath)
try:
if os.path.isdir(abspath):
@ -1127,7 +1128,7 @@ class Up2k(object):
if crd != rd:
crd = rd
try:
cdc = set(os.listdir(os.path.join(top, rd)))
cdc = set(os.listdir(djoin(top, rd)))
except:
cdc.clear()
@ -1203,7 +1204,7 @@ class Up2k(object):
rd = drd
fn = dfn
abspath = os.path.join(ptop, rd, fn)
abspath = djoin(ptop, rd, fn)
if rei and rei.search(abspath):
continue
@ -1412,7 +1413,7 @@ class Up2k(object):
q = "insert into mt values (?,'t:mtp','a')"
cur.execute(q, (w[:16],))
abspath = os.path.join(ptop, rd, fn)
abspath = djoin(ptop, rd, fn)
self.pp.msg = "c{} {}".format(nq, abspath)
if not mpool:
n_tags = self._tagscan_file(cur, entags, w, abspath, ip, at)
@ -1576,7 +1577,7 @@ class Up2k(object):
q = "select rd, fn, ip, at from up where substr(w,1,16)=? limit 1"
rd, fn, ip, at = cur.execute(q, (w,)).fetchone()
rd, fn = s3dec(rd, fn)
abspath = os.path.join(ptop, rd, fn)
abspath = djoin(ptop, rd, fn)
q = "select k from mt where w = ?"
zq = cur.execute(q, (w,)).fetchall()
@ -2053,7 +2054,7 @@ class Up2k(object):
if dp_dir.startswith("//") or dp_fn.startswith("//"):
dp_dir, dp_fn = s3dec(dp_dir, dp_fn)
dp_abs = "/".join([ptop, dp_dir, dp_fn])
dp_abs = djoin(ptop, dp_dir, dp_fn)
try:
st = bos.stat(dp_abs)
if stat.S_ISLNK(st.st_mode):
@ -2128,7 +2129,7 @@ class Up2k(object):
# ensure the files haven't been deleted manually
names = [job[x] for x in ["name", "tnam"] if x in job]
for fn in names:
path = os.path.join(job["ptop"], job["prel"], fn)
path = djoin(job["ptop"], job["prel"], fn)
try:
if bos.path.getsize(path) > 0:
# upload completed or both present
@ -2140,9 +2141,9 @@ class Up2k(object):
break
else:
# file contents match, but not the path
src = os.path.join(job["ptop"], job["prel"], job["name"])
dst = os.path.join(cj["ptop"], cj["prel"], cj["name"])
vsrc = os.path.join(job["vtop"], job["prel"], job["name"])
src = djoin(job["ptop"], job["prel"], job["name"])
dst = djoin(cj["ptop"], cj["prel"], cj["name"])
vsrc = djoin(job["vtop"], job["prel"], job["name"])
vsrc = vsrc.replace("\\", "/") # just for prints anyways
if job["need"]:
self.log("unfinished:\n {0}\n {1}".format(src, dst))
@ -2180,7 +2181,7 @@ class Up2k(object):
else:
job["name"] = self._untaken(pdir, cj, now)
dst = os.path.join(job["ptop"], job["prel"], job["name"])
dst = djoin(job["ptop"], job["prel"], job["name"])
if not self.args.nw:
try:
dvf = self.flags[job["ptop"]]
@ -2270,7 +2271,7 @@ class Up2k(object):
and "fk" in vfs.flags
and (cj["user"] in vfs.axs.uread or cj["user"] in vfs.axs.upget)
):
ap = absreal(os.path.join(job["ptop"], job["prel"], job["name"]))
ap = absreal(djoin(job["ptop"], job["prel"], job["name"]))
ino = 0 if ANYWIN else bos.stat(ap).st_ino
fk = self.gen_fk(self.args.fk_salt, ap, job["size"], ino)
ret["fk"] = fk[: vfs.flags["fk"]]
@ -2284,7 +2285,7 @@ class Up2k(object):
if self.args.nw:
return fname
fp = os.path.join(fdir, fname)
fp = djoin(fdir, fname)
if job.get("replace") and bos.path.exists(fp):
self.log("replacing existing file at {}".format(fp))
bos.unlink(fp)
@ -2397,7 +2398,7 @@ class Up2k(object):
t = "that chunk is already being written to:\n {}\n {} {}/{}\n {}"
raise Pebkac(400, t.format(wark, chash, idx, nh, job["name"]))
path = os.path.join(job["ptop"], job["prel"], job["tnam"])
path = djoin(job["ptop"], job["prel"], job["tnam"])
chunksize = up2k_chunksize(job["size"])
ofs = [chunksize * x for x in nchunk]
@ -2428,9 +2429,9 @@ class Up2k(object):
self.db_act = time.time()
try:
job = self.registry[ptop][wark]
pdir = os.path.join(job["ptop"], job["prel"])
src = os.path.join(pdir, job["tnam"])
dst = os.path.join(pdir, job["name"])
pdir = djoin(job["ptop"], job["prel"])
src = djoin(pdir, job["tnam"])
dst = djoin(pdir, job["name"])
except Exception as ex:
return "confirm_chunk, wark, " + repr(ex) # type: ignore
@ -2463,9 +2464,9 @@ class Up2k(object):
self.db_act = time.time()
try:
job = self.registry[ptop][wark]
pdir = os.path.join(job["ptop"], job["prel"])
src = os.path.join(pdir, job["tnam"])
dst = os.path.join(pdir, job["name"])
pdir = djoin(job["ptop"], job["prel"])
src = djoin(pdir, job["tnam"])
dst = djoin(pdir, job["name"])
except Exception as ex:
raise Pebkac(500, "finish_upload, wark, " + repr(ex))
@ -2532,7 +2533,7 @@ class Up2k(object):
cur = self.cur.get(ptop)
for rd, fn, lmod in dupes:
d2 = os.path.join(ptop, rd, fn)
d2 = djoin(ptop, rd, fn)
if os.path.exists(d2):
continue
@ -2710,7 +2711,7 @@ class Up2k(object):
break
n_files += 1
abspath = os.path.join(adir, fn)
abspath = djoin(adir, fn)
volpath = "{}/{}".format(vrem, fn).strip("/")
vpath = "{}/{}".format(dbv.vpath, volpath).strip("/")
self.log("rm {}\n {}".format(vpath, abspath))
@ -2989,14 +2990,14 @@ class Up2k(object):
or to first remaining full if no dabs (delete)
"""
dupes = []
sabs = os.path.join(sptop, srem)
sabs = djoin(sptop, srem)
q = "select rd, fn from up where substr(w,1,16)=? and w=?"
for ptop, cur in self.cur.items():
for rd, fn in cur.execute(q, (wark[:16], wark)):
if rd.startswith("//") or fn.startswith("//"):
rd, fn = s3dec(rd, fn)
dvrem = "/".join([rd, fn]).strip("/")
dvrem = vjoin(rd, fn).strip("/")
if ptop != sptop or srem != dvrem:
dupes.append([ptop, dvrem])
self.log("found {} dupe: [{}] {}".format(wark, ptop, dvrem))
@ -3007,7 +3008,7 @@ class Up2k(object):
full: dict[str, tuple[str, str]] = {}
links: dict[str, tuple[str, str]] = {}
for ptop, vp in dupes:
ap = os.path.join(ptop, vp)
ap = djoin(ptop, vp)
try:
d = links if bos.path.islink(ap) else full
d[ap] = (ptop, vp)
@ -3111,7 +3112,7 @@ class Up2k(object):
def _new_upload(self, job: dict[str, Any]) -> None:
pdir = djoin(job["ptop"], job["prel"])
if not job["size"] and bos.path.isfile(os.path.join(pdir, job["name"])):
if not job["size"] and bos.path.isfile(djoin(pdir, job["name"])):
return
self.registry[job["ptop"]][job["wark"]] = job
@ -3156,7 +3157,7 @@ class Up2k(object):
suffix = "-{:.6f}-{}".format(job["t0"], dip)
with ren_open(tnam, "wb", fdir=pdir, suffix=suffix) as zfw:
f, job["tnam"] = zfw["orz"]
abspath = os.path.join(pdir, job["tnam"])
abspath = djoin(pdir, job["tnam"])
sprs = job["sprs"]
sz = job["size"]
relabel = False
@ -3255,7 +3256,7 @@ class Up2k(object):
x
for x in reg.values()
if x["need"]
and not bos.path.exists(os.path.join(x["ptop"], x["prel"], x["name"]))
and not bos.path.exists(djoin(x["ptop"], x["prel"], x["name"]))
]
if rm or lost:
@ -3268,7 +3269,7 @@ class Up2k(object):
del reg[job["wark"]]
try:
# remove the filename reservation
path = os.path.join(job["ptop"], job["prel"], job["name"])
path = djoin(job["ptop"], job["prel"], job["name"])
if bos.path.getsize(path) == 0:
bos.unlink(path)
except:
@ -3277,7 +3278,7 @@ class Up2k(object):
try:
if len(job["hash"]) == len(job["need"]):
# PARTIAL is empty, delete that too
path = os.path.join(job["ptop"], job["prel"], job["tnam"])
path = djoin(job["ptop"], job["prel"], job["tnam"])
bos.unlink(path)
except:
pass
@ -3326,7 +3327,7 @@ class Up2k(object):
continue
# self.log("\n " + repr([ptop, rd, fn]))
abspath = os.path.join(ptop, rd, fn)
abspath = djoin(ptop, rd, fn)
try:
tags = self.mtag.get(abspath)
ntags1 = len(tags)
@ -3376,7 +3377,7 @@ class Up2k(object):
if "e2d" not in self.flags[ptop]:
continue
abspath = os.path.join(ptop, rd, fn)
abspath = djoin(ptop, rd, fn)
self.log("hashing " + abspath)
inf = bos.stat(abspath)
if not inf.st_size:
@ -3455,6 +3456,6 @@ def up2k_wark_from_hashlist(salt: str, filesize: int, hashes: list[str]) -> str:
def up2k_wark_from_metadata(salt: str, sz: int, lastmod: int, rd: str, fn: str) -> str:
ret = fsenc("{}\n{}\n{}\n{}\n{}".format(salt, lastmod, sz, rd, fn))
ret = sfsenc("{}\n{}\n{}\n{}\n{}".format(salt, lastmod, sz, rd, fn))
ret = base64.urlsafe_b64encode(hashlib.sha512(ret).digest())
return "#{}".format(ret.decode("ascii"))[:44]

View file

@ -14,6 +14,7 @@ import os
import platform
import re
import select
import shutil
import signal
import socket
import stat
@ -290,6 +291,20 @@ REKOBO_KEY = {
REKOBO_LKEY = {k.lower(): v for k, v in REKOBO_KEY.items()}
pybin = sys.executable or ""
is_exe = bool(getattr(sys, "frozen", False))
if is_exe:
pybin = ""
for p in "python3 python".split():
try:
p = shutil.which(p)
if p:
pybin = p
break
except:
pass
def py_desc() -> str:
interp = platform.python_implementation()
py_ver = ".".join([str(x) for x in sys.version_info])
@ -1704,7 +1719,7 @@ def relchk(rp: str) -> str:
def absreal(fpath: str) -> str:
try:
return fsdec(os.path.abspath(os.path.realpath(fsenc(fpath))))
return fsdec(os.path.abspath(os.path.realpath(afsenc(fpath))))
except:
if not WINDOWS:
raise
@ -1824,6 +1839,24 @@ def _w8enc3(txt: str) -> bytes:
return txt.encode(FS_ENCODING, "surrogateescape")
def _msdec(txt: bytes) -> str:
ret = txt.decode(FS_ENCODING, "surrogateescape")
return ret[4:] if ret.startswith("\\\\?\\") else ret
def _msaenc(txt: str) -> bytes:
return txt.replace("/", "\\").encode(FS_ENCODING, "surrogateescape")
def _msenc(txt: str) -> bytes:
txt = txt.replace("/", "\\")
if ":" not in txt and not txt.startswith("\\\\"):
txt = absreal(txt)
ret = txt.encode(FS_ENCODING, "surrogateescape")
return ret if ret.startswith(b"\\\\?\\") else b"\\\\?\\" + ret
w8dec = _w8dec3 if not PY2 else _w8dec2
w8enc = _w8enc3 if not PY2 else _w8enc2
@ -1838,8 +1871,13 @@ def w8b64enc(txt: str) -> str:
return base64.urlsafe_b64encode(w8enc(txt)).decode("ascii")
if not PY2 or not WINDOWS:
fsenc = w8enc
if not PY2 and WINDOWS:
sfsenc = w8enc
afsenc = _msaenc
fsenc = _msenc
fsdec = _msdec
elif not PY2 or not WINDOWS:
fsenc = afsenc = sfsenc = w8enc
fsdec = w8dec
else:
# moonrunes become \x3f with bytestrings,
@ -1850,7 +1888,7 @@ else:
def _not_actually_mbcs_dec(txt: bytes) -> str:
return txt
fsenc = _not_actually_mbcs_enc
fsenc = afsenc = sfsenc = _not_actually_mbcs_enc
fsdec = _not_actually_mbcs_dec
@ -2514,12 +2552,17 @@ def _runhook(
log(t.format(arg, ocmd))
env = os.environ.copy()
# try:
pypath = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
zsl = [str(pypath)] + [str(x) for x in sys.path if x]
pypath = str(os.pathsep.join(zsl))
env["PYTHONPATH"] = pypath
# except: if not E.ox: raise
try:
if is_exe:
raise Exception()
pypath = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
zsl = [str(pypath)] + [str(x) for x in sys.path if x]
pypath = str(os.pathsep.join(zsl))
env["PYTHONPATH"] = pypath
except:
if not is_exe:
raise
ka = {
"env": env,
@ -2545,9 +2588,9 @@ def _runhook(
acmd = [cmd, arg]
if cmd.endswith(".py"):
acmd = [sys.executable] + acmd
acmd = [pybin] + acmd
bcmd = [fsenc(x) for x in acmd]
bcmd = [fsenc(x) if x == ap else sfsenc(x) for x in acmd]
t0 = time.time()
if fork:

View file

@ -44,21 +44,33 @@ read a b c d _ < <(
)
sed -r 's/1,2,3,0/'$a,$b,$c,$d'/;s/1\.2\.3/'$a.$b.$c/ <loader.rc >loader.rc2
excl=(
copyparty.broker_mp
copyparty.broker_mpw
ctypes.macholib
curses
inspect
multiprocessing
pdb
pickle
pyftpdlib.prefork
urllib.request
urllib.response
urllib.robotparser
zipfile
)
false || excl+=(
PIL
PIL.ExifTags
PIL.Image
PIL.ImageDraw
PIL.ImageOps
)
excl=( "${excl[@]/#/--exclude-module }" )
$APPDATA/python/python37/scripts/pyinstaller \
-y --clean -p mods --upx-dir=. \
--exclude-module copyparty.broker_mp \
--exclude-module copyparty.broker_mpw \
--exclude-module curses \
--exclude-module ctypes.macholib \
--exclude-module inspect \
--exclude-module multiprocessing \
--exclude-module pdb \
--exclude-module pickle \
--exclude-module pyftpdlib.prefork \
--exclude-module urllib.request \
--exclude-module urllib.response \
--exclude-module urllib.robotparser \
--exclude-module zipfile \
${excl[*]} \
--version-file loader.rc2 -i loader.ico -n copyparty -c -F loader.py \
--add-data 'mods/copyparty/res;copyparty/res' \
--add-data 'mods/copyparty/web;copyparty/web'

View file

@ -98,7 +98,7 @@ class Cfg(Namespace):
def __init__(self, a=None, v=None, c=None):
ka = {}
ex = "daw dav_inf dav_mac dotsrch e2d e2ds e2dsa e2t e2ts e2tsr e2v e2vu e2vp ed emp force_js getmod hardlink ihead magic never_symlink nid nih no_acode no_athumb no_dav no_dedup no_del no_dupe no_logues no_mv no_readme no_robots no_sb_md no_sb_lg no_scandir no_thumb no_vthumb no_zip nw xdev xlink xvol"
ex = "daw dav_inf dav_mac dotsrch e2d e2ds e2dsa e2t e2ts e2tsr e2v e2vu e2vp ed emp force_js getmod hardlink ihead magic never_symlink nid nih no_acode no_athumb no_dav no_dedup no_del no_dupe no_logues no_mv no_readme no_robots no_sb_md no_sb_lg no_scandir no_thumb no_vthumb no_zip nrand nw rand vc xdev xlink xvol"
ka.update(**{k: False for k in ex.split()})
ex = "dotpart no_rescan no_sendfile no_voldump plain_ip"