mirror of
https://github.com/9001/copyparty.git
synced 2025-08-16 08:32:13 -06:00
support long filepaths on win7 + misc windows fixes
This commit is contained in:
parent
d7f1951e44
commit
a4b56c74c7
|
@ -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`
|
||||
|
|
|
@ -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=",
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue