copyparty 1.18.2__py3-none-any.whl → 1.18.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- copyparty/__main__.py +40 -1
- copyparty/__version__.py +2 -2
- copyparty/authsrv.py +70 -12
- copyparty/bos/bos.py +18 -6
- copyparty/cfg.py +4 -0
- copyparty/ftpd.py +9 -4
- copyparty/httpcli.py +31 -16
- copyparty/smbd.py +2 -2
- copyparty/svchub.py +5 -1
- copyparty/tcpsrv.py +1 -1
- copyparty/tftpd.py +6 -2
- copyparty/th_srv.py +3 -2
- copyparty/up2k.py +36 -11
- copyparty/util.py +9 -2
- copyparty/web/baguettebox.js.gz +0 -0
- copyparty/web/browser.css.gz +0 -0
- copyparty/web/browser.js.gz +0 -0
- {copyparty-1.18.2.dist-info → copyparty-1.18.3.dist-info}/METADATA +3 -1
- {copyparty-1.18.2.dist-info → copyparty-1.18.3.dist-info}/RECORD +23 -23
- {copyparty-1.18.2.dist-info → copyparty-1.18.3.dist-info}/WHEEL +0 -0
- {copyparty-1.18.2.dist-info → copyparty-1.18.3.dist-info}/entry_points.txt +0 -0
- {copyparty-1.18.2.dist-info → copyparty-1.18.3.dist-info}/licenses/LICENSE +0 -0
- {copyparty-1.18.2.dist-info → copyparty-1.18.3.dist-info}/top_level.txt +0 -0
copyparty/__main__.py
CHANGED
@@ -855,6 +855,43 @@ def get_sects():
|
|
855
855
|
"""
|
856
856
|
),
|
857
857
|
],
|
858
|
+
[
|
859
|
+
"chmod",
|
860
|
+
"file/folder permissions",
|
861
|
+
dedent(
|
862
|
+
"""
|
863
|
+
global-option \033[33m--chmod-f\033[0m and volflag \033[33mchmod_f\033[0m specifies the unix-permission to use when creating a new file
|
864
|
+
|
865
|
+
similarly, \033[33m--chmod-d\033[0m and \033[33mchmod_d\033[0m sets the directory/folder perm
|
866
|
+
|
867
|
+
the value is a three-digit octal number such as 755, 750, 644, etc.
|
868
|
+
|
869
|
+
first digit = "User"; permission for the unix-user
|
870
|
+
second digit = "Group"; permission for the unix-group
|
871
|
+
third digit = "Other"; permission for all other users/groups
|
872
|
+
|
873
|
+
for files:
|
874
|
+
0 = --- = no access
|
875
|
+
1 = --x = can execute the file as a program
|
876
|
+
2 = -w- = can write
|
877
|
+
3 = -wx = can write and execute
|
878
|
+
4 = r-- = can read
|
879
|
+
5 = r-x = can read and execute
|
880
|
+
6 = rw- = can read and write
|
881
|
+
7 = rwx = can read, write, execute
|
882
|
+
|
883
|
+
for directories/folders:
|
884
|
+
0 = --- = no access
|
885
|
+
1 = --x = can read files in folder but not list contents
|
886
|
+
2 = -w- = n/a
|
887
|
+
3 = -wx = can create files but not list
|
888
|
+
4 = r-- = can list, but not read/write
|
889
|
+
5 = r-x = can list and read files
|
890
|
+
6 = rw- = n/a
|
891
|
+
7 = rwx = can read, write, list
|
892
|
+
"""
|
893
|
+
),
|
894
|
+
],
|
858
895
|
[
|
859
896
|
"pwhash",
|
860
897
|
"password hashing",
|
@@ -1005,6 +1042,8 @@ def add_upload(ap):
|
|
1005
1042
|
ap2.add_argument("--reg-cap", metavar="N", type=int, default=38400, help="max number of uploads to keep in memory when running without \033[33m-e2d\033[0m; roughly 1 MiB RAM per 600")
|
1006
1043
|
ap2.add_argument("--no-fpool", action="store_true", help="disable file-handle pooling -- instead, repeatedly close and reopen files during upload (bad idea to enable this on windows and/or cow filesystems)")
|
1007
1044
|
ap2.add_argument("--use-fpool", action="store_true", help="force file-handle pooling, even when it might be dangerous (multiprocessing, filesystems lacking sparse-files support, ...)")
|
1045
|
+
ap2.add_argument("--chmod-f", metavar="UGO", type=u, default="", help="unix file permissions to use when creating files; default is probably 644 (OS-decided), see --help-chmod. Examples: [\033[32m644\033[0m] = owner-RW + all-R, [\033[32m755\033[0m] = owner-RWX + all-RX, [\033[32m777\033[0m] = full-yolo (volflag=chmod_f)")
|
1046
|
+
ap2.add_argument("--chmod-d", metavar="UGO", type=u, default="755", help="unix file permissions to use when creating directories; see --help-chmod. Examples: [\033[32m755\033[0m] = owner-RW + all-R, [\033[32m777\033[0m] = full-yolo (volflag=chmod_d)")
|
1008
1047
|
ap2.add_argument("--dedup", action="store_true", help="enable symlink-based upload deduplication (volflag=dedup)")
|
1009
1048
|
ap2.add_argument("--safe-dedup", metavar="N", type=int, default=50, help="how careful to be when deduplicating files; [\033[32m1\033[0m] = just verify the filesize, [\033[32m50\033[0m] = verify file contents have not been altered (volflag=safededup)")
|
1010
1049
|
ap2.add_argument("--hardlink", action="store_true", help="enable hardlink-based dedup; will fallback on symlinks when that is impossible (across filesystems) (volflag=hardlink)")
|
@@ -1041,7 +1080,7 @@ def add_network(ap):
|
|
1041
1080
|
ap2.add_argument("--rp-loc", metavar="PATH", type=u, default="", help="if reverse-proxying on a location instead of a dedicated domain/subdomain, provide the base location here; example: [\033[32m/foo/bar\033[0m]")
|
1042
1081
|
if ANYWIN:
|
1043
1082
|
ap2.add_argument("--reuseaddr", action="store_true", help="set reuseaddr on listening sockets on windows; allows rapid restart of copyparty at the expense of being able to accidentally start multiple instances")
|
1044
|
-
|
1083
|
+
elif not MACOS:
|
1045
1084
|
ap2.add_argument("--freebind", action="store_true", help="allow listening on IPs which do not yet exist, for example if the network interfaces haven't finished going up. Only makes sense for IPs other than '0.0.0.0', '127.0.0.1', '::', and '::1'. May require running as root (unless net.ipv6.ip_nonlocal_bind)")
|
1046
1085
|
ap2.add_argument("--wr-h-eps", metavar="PATH", type=u, default="", help="write list of listening-on ip:port to textfile at \033[33mPATH\033[0m when http-servers have started")
|
1047
1086
|
ap2.add_argument("--wr-h-aon", metavar="PATH", type=u, default="", help="write list of accessible-on ip:port to textfile at \033[33mPATH\033[0m when http-servers have started")
|
copyparty/__version__.py
CHANGED
copyparty/authsrv.py
CHANGED
@@ -113,6 +113,8 @@ class Lim(object):
|
|
113
113
|
|
114
114
|
self.reg = None # up2k registry
|
115
115
|
|
116
|
+
self.chmod_d = 0o755
|
117
|
+
|
116
118
|
self.nups = {} # num tracker
|
117
119
|
self.bups = {} # byte tracker list
|
118
120
|
self.bupc = {} # byte tracker cache
|
@@ -273,7 +275,7 @@ class Lim(object):
|
|
273
275
|
if not dirs:
|
274
276
|
# no branches yet; make one
|
275
277
|
sub = os.path.join(path, "0")
|
276
|
-
bos.mkdir(sub)
|
278
|
+
bos.mkdir(sub, self.chmod_d)
|
277
279
|
else:
|
278
280
|
# try newest branch only
|
279
281
|
sub = os.path.join(path, str(dirs[-1]))
|
@@ -288,7 +290,7 @@ class Lim(object):
|
|
288
290
|
|
289
291
|
# make a branch
|
290
292
|
sub = os.path.join(path, str(dirs[-1] + 1))
|
291
|
-
bos.mkdir(sub)
|
293
|
+
bos.mkdir(sub, self.chmod_d)
|
292
294
|
ret = self.dive(sub, lvs - 1)
|
293
295
|
if ret is None:
|
294
296
|
raise Pebkac(500, "rotation bug")
|
@@ -365,6 +367,7 @@ class VFS(object):
|
|
365
367
|
self.shr_src = None # source vfs+rem of a share
|
366
368
|
self.shr_files = set() # filenames to include from shr_src
|
367
369
|
self.shr_owner = "" # uname
|
370
|
+
self.shr_all_aps = []
|
368
371
|
self.aread = {}
|
369
372
|
self.awrite = {}
|
370
373
|
self.amove = {}
|
@@ -384,7 +387,7 @@ class VFS(object):
|
|
384
387
|
self.dbpath = self.histpath
|
385
388
|
self.all_vols = {vpath: self} # flattened recursive
|
386
389
|
self.all_nodes = {vpath: self} # also jumpvols/shares
|
387
|
-
self.all_aps = [(rp, self)]
|
390
|
+
self.all_aps = [(rp, [self])]
|
388
391
|
self.all_vps = [(vp, self)]
|
389
392
|
else:
|
390
393
|
self.histpath = self.dbpath = ""
|
@@ -417,7 +420,11 @@ class VFS(object):
|
|
417
420
|
rp = self.realpath
|
418
421
|
rp += "" if rp.endswith(os.sep) else os.sep
|
419
422
|
vp = self.vpath + ("/" if self.vpath else "")
|
420
|
-
|
423
|
+
hit = next((x[1] for x in aps if x[0] == rp), None)
|
424
|
+
if hit:
|
425
|
+
hit.append(self)
|
426
|
+
else:
|
427
|
+
aps.append((rp, [self]))
|
421
428
|
vps.append((vp, self))
|
422
429
|
|
423
430
|
for v in self.nodes.values():
|
@@ -841,9 +848,11 @@ class VFS(object):
|
|
841
848
|
return None
|
842
849
|
|
843
850
|
if "xvol" in self.flags:
|
844
|
-
|
851
|
+
all_aps = self.shr_all_aps or self.root.all_aps
|
852
|
+
|
853
|
+
for vap, vns in all_aps:
|
845
854
|
if aps.startswith(vap):
|
846
|
-
return
|
855
|
+
return self if self in vns else vns[0]
|
847
856
|
|
848
857
|
if self.log:
|
849
858
|
self.log("vfs", "xvol: %r" % (ap,), 3)
|
@@ -915,6 +924,9 @@ class AuthSrv(object):
|
|
915
924
|
|
916
925
|
yield prev, True
|
917
926
|
|
927
|
+
def vf0(self):
|
928
|
+
return {"d2d": True, "tcolor": self.args.tcolor}
|
929
|
+
|
918
930
|
def idp_checkin(
|
919
931
|
self, broker , uname , gname
|
920
932
|
) :
|
@@ -1620,13 +1632,12 @@ class AuthSrv(object):
|
|
1620
1632
|
t = "Read-access has been disabled due to failsafe: No volumes were defined by the config-file. This failsafe is to prevent unintended access if this is due to accidental loss of config. You can override this safeguard and allow read/write to the working-directory by adding the following arguments: -v .::rw"
|
1621
1633
|
self.log(t, 1)
|
1622
1634
|
axs = AXS()
|
1623
|
-
vfs = VFS(self.log_func, absreal("."), "", "", axs,
|
1635
|
+
vfs = VFS(self.log_func, absreal("."), "", "", axs, self.vf0())
|
1624
1636
|
if not axs.uread:
|
1625
1637
|
self.badcfg1 = True
|
1626
1638
|
elif "" not in mount:
|
1627
1639
|
# there's volumes but no root; make root inaccessible
|
1628
|
-
|
1629
|
-
vfs = VFS(self.log_func, "", "", "", AXS(), zsd)
|
1640
|
+
vfs = VFS(self.log_func, "", "", "", AXS(), self.vf0())
|
1630
1641
|
|
1631
1642
|
maxdepth = 0
|
1632
1643
|
for dst in sorted(mount.keys(), key=lambda x: (x.count("/"), len(x))):
|
@@ -1674,8 +1685,7 @@ class AuthSrv(object):
|
|
1674
1685
|
shrs = enshare[1:]
|
1675
1686
|
if enshare:
|
1676
1687
|
|
1677
|
-
|
1678
|
-
shv = VFS(self.log_func, "", shr, shr, AXS(), zsd)
|
1688
|
+
shv = VFS(self.log_func, "", shr, shr, AXS(), self.vf0())
|
1679
1689
|
|
1680
1690
|
db_path = self.args.shr_db
|
1681
1691
|
db = sqlite3.connect(db_path)
|
@@ -2057,6 +2067,7 @@ class AuthSrv(object):
|
|
2057
2067
|
|
2058
2068
|
all_mte = {}
|
2059
2069
|
errors = False
|
2070
|
+
free_umask = False
|
2060
2071
|
for vol in vfs.all_nodes.values():
|
2061
2072
|
if (self.args.e2ds and vol.axs.uwrite) or self.args.e2dsa:
|
2062
2073
|
vol.flags["e2ds"] = True
|
@@ -2113,6 +2124,27 @@ class AuthSrv(object):
|
|
2113
2124
|
t = 'volume "/%s" has invalid %stry [%s]'
|
2114
2125
|
raise Exception(t % (vol.vpath, k, vol.flags.get(k + "try")))
|
2115
2126
|
|
2127
|
+
for k in ("chmod_d", "chmod_f"):
|
2128
|
+
is_d = k == "chmod_d"
|
2129
|
+
zs = vol.flags.get(k, "")
|
2130
|
+
if not zs and is_d:
|
2131
|
+
zs = "755"
|
2132
|
+
if not zs:
|
2133
|
+
vol.flags.pop(k, None)
|
2134
|
+
continue
|
2135
|
+
if not re.match("^[0-7]{3}$", zs):
|
2136
|
+
t = "config-option '%s' must be a three-digit octal value such as [755] or [644] but the value was [%s]"
|
2137
|
+
t = t % (k, zs)
|
2138
|
+
self.log(t, 1)
|
2139
|
+
raise Exception(t)
|
2140
|
+
zi = int(zs, 8)
|
2141
|
+
vol.flags[k] = zi
|
2142
|
+
if (is_d and zi != 0o755) or not is_d:
|
2143
|
+
free_umask = True
|
2144
|
+
|
2145
|
+
if vol.lim:
|
2146
|
+
vol.lim.chmod_d = vol.flags["chmod_d"]
|
2147
|
+
|
2116
2148
|
if vol.flags.get("og"):
|
2117
2149
|
self.args.uqe = True
|
2118
2150
|
|
@@ -2342,6 +2374,10 @@ class AuthSrv(object):
|
|
2342
2374
|
if errors:
|
2343
2375
|
sys.exit(1)
|
2344
2376
|
|
2377
|
+
setattr(self.args, "free_umask", free_umask)
|
2378
|
+
if free_umask:
|
2379
|
+
os.umask(0)
|
2380
|
+
|
2345
2381
|
vfs.bubble_flags()
|
2346
2382
|
|
2347
2383
|
have_e2d = False
|
@@ -2544,6 +2580,28 @@ class AuthSrv(object):
|
|
2544
2580
|
shn.shr_src = (s_vfs, s_rem)
|
2545
2581
|
shn.realpath = s_vfs.canonical(s_rem)
|
2546
2582
|
|
2583
|
+
# root.all_aps doesn't include any shares, so make a copy where the
|
2584
|
+
# share appears in all abspaths it can provide (for example for chk_ap)
|
2585
|
+
ap = shn.realpath
|
2586
|
+
if not ap.endswith(os.sep):
|
2587
|
+
ap += os.sep
|
2588
|
+
shn.shr_all_aps = [(x, y[:]) for x, y in vfs.all_aps]
|
2589
|
+
exact = False
|
2590
|
+
for ap2, vns in shn.shr_all_aps:
|
2591
|
+
if ap == ap2:
|
2592
|
+
exact = True
|
2593
|
+
if ap2.startswith(ap):
|
2594
|
+
try:
|
2595
|
+
vp2 = vjoin(s_rem, ap2[len(ap) :])
|
2596
|
+
vn2, _ = s_vfs.get(vp2, "*", False, False)
|
2597
|
+
if vn2 == s_vfs or vn2.dbv == s_vfs:
|
2598
|
+
vns.append(shn)
|
2599
|
+
except:
|
2600
|
+
pass
|
2601
|
+
if not exact:
|
2602
|
+
shn.shr_all_aps.append((ap, [shn]))
|
2603
|
+
shn.shr_all_aps.sort(key=lambda x: len(x[0]), reverse=True)
|
2604
|
+
|
2547
2605
|
if self.args.shr_v:
|
2548
2606
|
t = "mapped %s share [%s] by [%s] => [%s] => [%s]"
|
2549
2607
|
self.log(t % (s_pr, s_k, s_un, s_vp, shn.realpath))
|
@@ -2558,7 +2616,7 @@ class AuthSrv(object):
|
|
2558
2616
|
continue # also fine
|
2559
2617
|
for zs in svn.nodes.keys():
|
2560
2618
|
# hide subvolume
|
2561
|
-
vn.nodes[zs] = VFS(self.log_func, "", "", "", AXS(),
|
2619
|
+
vn.nodes[zs] = VFS(self.log_func, "", "", "", AXS(), self.vf0())
|
2562
2620
|
|
2563
2621
|
cur2.close()
|
2564
2622
|
cur.close()
|
copyparty/bos/bos.py
CHANGED
@@ -22,14 +22,26 @@ def listdir(p = ".") :
|
|
22
22
|
|
23
23
|
|
24
24
|
def makedirs(name , mode = 0o755, exist_ok = True) :
|
25
|
+
# os.makedirs does 777 for all but leaf; this does mode on all
|
26
|
+
todo = []
|
25
27
|
bname = fsenc(name)
|
26
|
-
|
27
|
-
os.
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
while bname:
|
29
|
+
if os.path.isdir(bname):
|
30
|
+
break
|
31
|
+
todo.append(bname)
|
32
|
+
bname = os.path.dirname(bname)
|
33
|
+
if not todo:
|
34
|
+
if not exist_ok:
|
35
|
+
os.mkdir(bname) # to throw
|
32
36
|
return False
|
37
|
+
for zb in todo[::-1]:
|
38
|
+
try:
|
39
|
+
os.mkdir(zb, mode)
|
40
|
+
except:
|
41
|
+
if os.path.isdir(zb):
|
42
|
+
continue
|
43
|
+
raise
|
44
|
+
return True
|
33
45
|
|
34
46
|
|
35
47
|
def mkdir(p , mode = 0o755) :
|
copyparty/cfg.py
CHANGED
@@ -78,6 +78,8 @@ def vf_vmap() :
|
|
78
78
|
}
|
79
79
|
for k in (
|
80
80
|
"bup_ck",
|
81
|
+
"chmod_d",
|
82
|
+
"chmod_f",
|
81
83
|
"dbd",
|
82
84
|
"forget_ip",
|
83
85
|
"hsortn",
|
@@ -169,6 +171,8 @@ flagcats = {
|
|
169
171
|
"safededup": "verify on-disk data before using it for dedup",
|
170
172
|
"noclone": "take dupe data from clients, even if available on HDD",
|
171
173
|
"nodupe": "rejects existing files (instead of linking/cloning them)",
|
174
|
+
"chmod_d=755": "unix-permission for new dirs/folders",
|
175
|
+
"chmod_f=644": "unix-permission for new files",
|
172
176
|
"sparse": "force use of sparse files, mainly for s3-backed storage",
|
173
177
|
"nosparse": "deny use of sparse files, mainly for slow storage",
|
174
178
|
"daw": "enable full WebDAV write support (dangerous);\nPUT-operations will now \033[1;31mOVERWRITE\033[0;35m existing files",
|
copyparty/ftpd.py
CHANGED
@@ -225,7 +225,7 @@ class FtpFs(AbstractedFS):
|
|
225
225
|
r = "r" in mode
|
226
226
|
w = "w" in mode or "a" in mode or "+" in mode
|
227
227
|
|
228
|
-
ap = self.rv2a(filename, r, w)
|
228
|
+
ap, vfs, _ = self.rv2a(filename, r, w)
|
229
229
|
self.validpath(ap)
|
230
230
|
if w:
|
231
231
|
try:
|
@@ -257,7 +257,11 @@ class FtpFs(AbstractedFS):
|
|
257
257
|
|
258
258
|
wunlink(self.log, ap, VF_CAREFUL)
|
259
259
|
|
260
|
-
|
260
|
+
ret = open(fsenc(ap), mode, self.args.iobuf)
|
261
|
+
if w and "chmod_f" in vfs.flags:
|
262
|
+
os.fchmod(ret.fileno(), vfs.flags["chmod_f"])
|
263
|
+
|
264
|
+
return ret
|
261
265
|
|
262
266
|
def chdir(self, path ) :
|
263
267
|
nwd = join(self.cwd, path)
|
@@ -288,8 +292,9 @@ class FtpFs(AbstractedFS):
|
|
288
292
|
) = avfs.can_access("", self.h.uname)
|
289
293
|
|
290
294
|
def mkdir(self, path ) :
|
291
|
-
ap = self.rv2a(path, w=True)
|
292
|
-
|
295
|
+
ap, vfs, _ = self.rv2a(path, w=True)
|
296
|
+
chmod = vfs.flags["chmod_d"]
|
297
|
+
bos.makedirs(ap, chmod) # filezilla expects this
|
293
298
|
|
294
299
|
def listdir(self, path ) :
|
295
300
|
vpath = join(self.cwd, path)
|
copyparty/httpcli.py
CHANGED
@@ -45,6 +45,7 @@ from .util import (
|
|
45
45
|
APPLESAN_RE,
|
46
46
|
BITNESS,
|
47
47
|
DAV_ALLPROPS,
|
48
|
+
E_SCK_WR,
|
48
49
|
FN_EMB,
|
49
50
|
HAVE_SQLITE3,
|
50
51
|
HTTPCODE,
|
@@ -1369,12 +1370,13 @@ class HttpCli(object):
|
|
1369
1370
|
title = self.uparam.get("title") or self.vpath.split("/")[-1]
|
1370
1371
|
etitle = html_escape(title, True, True)
|
1371
1372
|
|
1372
|
-
baseurl = "%s://%s
|
1373
|
+
baseurl = "%s://%s/" % (
|
1373
1374
|
"https" if self.is_https else "http",
|
1374
1375
|
self.host,
|
1375
|
-
self.args.SRS,
|
1376
1376
|
)
|
1377
|
-
feed =
|
1377
|
+
feed = baseurl + self.req[1:]
|
1378
|
+
if self.is_vproxied:
|
1379
|
+
baseurl += self.args.RS
|
1378
1380
|
efeed = html_escape(feed, True, True)
|
1379
1381
|
edirlink = efeed.split("?")[0] + q_pw
|
1380
1382
|
|
@@ -1387,7 +1389,7 @@ class HttpCli(object):
|
|
1387
1389
|
\t\t<title>%s</title>
|
1388
1390
|
\t\t<description></description>
|
1389
1391
|
\t\t<link>%s</link>
|
1390
|
-
\t\t<generator>copyparty-
|
1392
|
+
\t\t<generator>copyparty-2</generator>
|
1391
1393
|
"""
|
1392
1394
|
% (efeed, etitle, edirlink)
|
1393
1395
|
]
|
@@ -2058,7 +2060,7 @@ class HttpCli(object):
|
|
2058
2060
|
fdir, fn = os.path.split(fdir)
|
2059
2061
|
rem, _ = vsplit(rem)
|
2060
2062
|
|
2061
|
-
bos.makedirs(fdir)
|
2063
|
+
bos.makedirs(fdir, vfs.flags["chmod_d"])
|
2062
2064
|
|
2063
2065
|
open_ka = {"fun": open}
|
2064
2066
|
open_a = ["wb", self.args.iobuf]
|
@@ -2116,6 +2118,8 @@ class HttpCli(object):
|
|
2116
2118
|
fn = vfs.flags["put_name2"].format(now=time.time(), cip=self.dip())
|
2117
2119
|
|
2118
2120
|
params = {"suffix": suffix, "fdir": fdir}
|
2121
|
+
if "chmod_f" in vfs.flags:
|
2122
|
+
params["chmod"] = vfs.flags["chmod_f"]
|
2119
2123
|
if self.args.nw:
|
2120
2124
|
params = {}
|
2121
2125
|
fn = os.devnull
|
@@ -2163,7 +2167,7 @@ class HttpCli(object):
|
|
2163
2167
|
if self.args.nw:
|
2164
2168
|
fn = os.devnull
|
2165
2169
|
else:
|
2166
|
-
bos.makedirs(fdir)
|
2170
|
+
bos.makedirs(fdir, vfs.flags["chmod_d"])
|
2167
2171
|
path = os.path.join(fdir, fn)
|
2168
2172
|
if not nameless:
|
2169
2173
|
self.vpath = vjoin(self.vpath, fn)
|
@@ -2295,7 +2299,7 @@ class HttpCli(object):
|
|
2295
2299
|
if self.args.hook_v:
|
2296
2300
|
log_reloc(self.log, hr["reloc"], x, path, vp, fn, vfs, rem)
|
2297
2301
|
fdir, self.vpath, fn, (vfs, rem) = x
|
2298
|
-
bos.makedirs(fdir)
|
2302
|
+
bos.makedirs(fdir, vfs.flags["chmod_d"])
|
2299
2303
|
path2 = os.path.join(fdir, fn)
|
2300
2304
|
atomic_move(self.log, path, path2, vfs.flags)
|
2301
2305
|
path = path2
|
@@ -2580,7 +2584,7 @@ class HttpCli(object):
|
|
2580
2584
|
dst = vfs.canonical(rem)
|
2581
2585
|
try:
|
2582
2586
|
if not bos.path.isdir(dst):
|
2583
|
-
bos.makedirs(dst)
|
2587
|
+
bos.makedirs(dst, vfs.flags["chmod_d"])
|
2584
2588
|
except OSError as ex:
|
2585
2589
|
self.log("makedirs failed %r" % (dst,))
|
2586
2590
|
if not bos.path.isdir(dst):
|
@@ -3011,7 +3015,7 @@ class HttpCli(object):
|
|
3011
3015
|
raise Pebkac(405, 'folder "/%s" already exists' % (vpath,))
|
3012
3016
|
|
3013
3017
|
try:
|
3014
|
-
bos.makedirs(fn)
|
3018
|
+
bos.makedirs(fn, vfs.flags["chmod_d"])
|
3015
3019
|
except OSError as ex:
|
3016
3020
|
if ex.errno == errno.EACCES:
|
3017
3021
|
raise Pebkac(500, "the server OS denied write-access")
|
@@ -3052,6 +3056,8 @@ class HttpCli(object):
|
|
3052
3056
|
|
3053
3057
|
with open(fsenc(fn), "wb") as f:
|
3054
3058
|
f.write(b"`GRUNNUR`\n")
|
3059
|
+
if "chmod_f" in vfs.flags:
|
3060
|
+
os.fchmod(f.fileno(), vfs.flags["chmod_f"])
|
3055
3061
|
|
3056
3062
|
vpath = "{}/{}".format(self.vpath, sanitized).lstrip("/")
|
3057
3063
|
self.redirect(vpath, "?edit")
|
@@ -3125,7 +3131,7 @@ class HttpCli(object):
|
|
3125
3131
|
)
|
3126
3132
|
upload_vpath = "{}/{}".format(vfs.vpath, rem).strip("/")
|
3127
3133
|
if not nullwrite:
|
3128
|
-
bos.makedirs(fdir_base)
|
3134
|
+
bos.makedirs(fdir_base, vfs.flags["chmod_d"])
|
3129
3135
|
|
3130
3136
|
rnd, lifetime, xbu, xau = self.upload_flags(vfs)
|
3131
3137
|
zs = self.uparam.get("want") or self.headers.get("accept") or ""
|
@@ -3220,8 +3226,11 @@ class HttpCli(object):
|
|
3220
3226
|
else:
|
3221
3227
|
open_args["fdir"] = fdir
|
3222
3228
|
|
3229
|
+
if "chmod_f" in vfs.flags:
|
3230
|
+
open_args["chmod"] = vfs.flags["chmod_f"]
|
3231
|
+
|
3223
3232
|
if p_file and not nullwrite:
|
3224
|
-
bos.makedirs(fdir)
|
3233
|
+
bos.makedirs(fdir, vfs.flags["chmod_d"])
|
3225
3234
|
|
3226
3235
|
# reserve destination filename
|
3227
3236
|
f, fname = ren_open(fname, "wb", fdir=fdir, suffix=suffix)
|
@@ -3325,7 +3334,7 @@ class HttpCli(object):
|
|
3325
3334
|
if nullwrite:
|
3326
3335
|
fdir = ap2 = ""
|
3327
3336
|
else:
|
3328
|
-
bos.makedirs(fdir)
|
3337
|
+
bos.makedirs(fdir, vfs.flags["chmod_d"])
|
3329
3338
|
atomic_move(self.log, abspath, ap2, vfs.flags)
|
3330
3339
|
abspath = ap2
|
3331
3340
|
sz = bos.path.getsize(abspath)
|
@@ -3446,6 +3455,8 @@ class HttpCli(object):
|
|
3446
3455
|
ft = "{}:{}".format(self.ip, self.addr[1])
|
3447
3456
|
ft = "{}\n{}\n{}\n".format(ft, msg.rstrip(), errmsg)
|
3448
3457
|
f.write(ft.encode("utf-8"))
|
3458
|
+
if "chmod_f" in vfs.flags:
|
3459
|
+
os.fchmod(f.fileno(), vfs.flags["chmod_f"])
|
3449
3460
|
except Exception as ex:
|
3450
3461
|
suf = "\nfailed to write the upload report: {}".format(ex)
|
3451
3462
|
|
@@ -3495,7 +3506,7 @@ class HttpCli(object):
|
|
3495
3506
|
lim = vfs.get_dbv(rem)[0].lim
|
3496
3507
|
if lim:
|
3497
3508
|
fp, rp = lim.all(self.ip, rp, clen, vfs.realpath, fp, self.conn.hsrv.broker)
|
3498
|
-
bos.makedirs(fp)
|
3509
|
+
bos.makedirs(fp, vfs.flags["chmod_d"])
|
3499
3510
|
|
3500
3511
|
fp = os.path.join(fp, fn)
|
3501
3512
|
rem = "{}/{}".format(rp, fn).strip("/")
|
@@ -3563,13 +3574,15 @@ class HttpCli(object):
|
|
3563
3574
|
zs = ub64enc(zb).decode("ascii")[:24].lower()
|
3564
3575
|
dp = "%s/md/%s/%s/%s" % (dbv.histpath, zs[:2], zs[2:4], zs)
|
3565
3576
|
self.log("moving old version to %s/%s" % (dp, mfile2))
|
3566
|
-
if bos.makedirs(dp):
|
3577
|
+
if bos.makedirs(dp, vfs.flags["chmod_d"]):
|
3567
3578
|
with open(os.path.join(dp, "dir.txt"), "wb") as f:
|
3568
3579
|
f.write(afsenc(vrd))
|
3580
|
+
if "chmod_f" in vfs.flags:
|
3581
|
+
os.fchmod(f.fileno(), vfs.flags["chmod_f"])
|
3569
3582
|
elif hist_cfg == "s":
|
3570
3583
|
dp = os.path.join(mdir, ".hist")
|
3571
3584
|
try:
|
3572
|
-
bos.mkdir(dp)
|
3585
|
+
bos.mkdir(dp, vfs.flags["chmod_d"])
|
3573
3586
|
hidedir(dp)
|
3574
3587
|
except:
|
3575
3588
|
pass
|
@@ -3607,6 +3620,8 @@ class HttpCli(object):
|
|
3607
3620
|
wunlink(self.log, fp, vfs.flags)
|
3608
3621
|
|
3609
3622
|
with open(fsenc(fp), "wb", self.args.iobuf) as f:
|
3623
|
+
if "chmod_f" in vfs.flags:
|
3624
|
+
os.fchmod(f.fileno(), vfs.flags["chmod_f"])
|
3610
3625
|
sz, sha512, _ = hashcopy(p_data, f, None, 0, self.args.s_wr_slp)
|
3611
3626
|
|
3612
3627
|
if lim:
|
@@ -4342,7 +4357,7 @@ class HttpCli(object):
|
|
4342
4357
|
self.log("file deleted; disconnecting")
|
4343
4358
|
break
|
4344
4359
|
except IOError as ex:
|
4345
|
-
if ex.errno not in
|
4360
|
+
if ex.errno not in E_SCK_WR:
|
4346
4361
|
raise
|
4347
4362
|
finally:
|
4348
4363
|
if f:
|
copyparty/smbd.py
CHANGED
@@ -317,7 +317,7 @@ class SMB(object):
|
|
317
317
|
|
318
318
|
self.hub.up2k.handle_mv(uname, "1.7.6.2", vp1, vp2)
|
319
319
|
try:
|
320
|
-
bos.makedirs(ap2)
|
320
|
+
bos.makedirs(ap2, vfs2.flags["chmod_d"])
|
321
321
|
except:
|
322
322
|
pass
|
323
323
|
|
@@ -331,7 +331,7 @@ class SMB(object):
|
|
331
331
|
t = "blocked mkdir (no-write-acc %s): /%s @%s"
|
332
332
|
yeet(t % (vfs.axs.uwrite, vpath, uname))
|
333
333
|
|
334
|
-
return bos.mkdir(ap)
|
334
|
+
return bos.mkdir(ap, vfs.flags["chmod_d"])
|
335
335
|
|
336
336
|
def _stat(self, vpath , *a , **ka ) :
|
337
337
|
try:
|
copyparty/svchub.py
CHANGED
@@ -21,6 +21,7 @@ from datetime import datetime
|
|
21
21
|
|
22
22
|
from .__init__ import ANYWIN, EXE, MACOS, PY2, TYPE_CHECKING, E, EnvParams, unicode
|
23
23
|
from .authsrv import BAD_CFG, AuthSrv
|
24
|
+
from .bos import bos
|
24
25
|
from .cert import ensure_cert
|
25
26
|
from .mtag import HAVE_FFMPEG, HAVE_FFPROBE, HAVE_MUTAGEN
|
26
27
|
from .pwhash import HAVE_ARGON2
|
@@ -1108,7 +1109,7 @@ class SvcHub(object):
|
|
1108
1109
|
|
1109
1110
|
fn = sel_fn
|
1110
1111
|
try:
|
1111
|
-
|
1112
|
+
bos.makedirs(os.path.dirname(fn))
|
1112
1113
|
except:
|
1113
1114
|
pass
|
1114
1115
|
|
@@ -1125,6 +1126,9 @@ class SvcHub(object):
|
|
1125
1126
|
|
1126
1127
|
lh = codecs.open(fn, "w", encoding="utf-8", errors="replace")
|
1127
1128
|
|
1129
|
+
if getattr(self.args, "free_umask", False):
|
1130
|
+
os.fchmod(lh.fileno(), 0o644)
|
1131
|
+
|
1128
1132
|
argv = [pybin] + self.argv
|
1129
1133
|
if hasattr(shlex, "quote"):
|
1130
1134
|
argv = [shlex.quote(x) for x in argv]
|
copyparty/tcpsrv.py
CHANGED
copyparty/tftpd.py
CHANGED
@@ -384,14 +384,18 @@ class Tftpd(object):
|
|
384
384
|
if not a:
|
385
385
|
a = (self.args.iobuf,)
|
386
386
|
|
387
|
-
|
387
|
+
ret = open(ap, mode, *a, **ka)
|
388
|
+
if wr and "chmod_f" in vfs.flags:
|
389
|
+
os.fchmod(ret.fileno(), vfs.flags["chmod_f"])
|
390
|
+
|
391
|
+
return ret
|
388
392
|
|
389
393
|
def _mkdir(self, vpath , *a) :
|
390
394
|
vfs, _, ap = self._v2a("mkdir", vpath, [False, True])
|
391
395
|
if "*" not in vfs.axs.uwrite:
|
392
396
|
yeet("blocked mkdir; folder not world-writable: /%s" % (vpath,))
|
393
397
|
|
394
|
-
return bos.mkdir(ap)
|
398
|
+
return bos.mkdir(ap, vfs.flags["chmod_d"])
|
395
399
|
|
396
400
|
def _unlink(self, vpath ) :
|
397
401
|
# return bos.unlink(self._v2a("stat", vpath, *a)[1])
|
copyparty/th_srv.py
CHANGED
@@ -266,7 +266,8 @@ class ThumbSrv(object):
|
|
266
266
|
self.log("joined waiting room for %r" % (tpath,))
|
267
267
|
except:
|
268
268
|
thdir = os.path.dirname(tpath)
|
269
|
-
|
269
|
+
chmod = 0o700 if self.args.free_umask else 0o755
|
270
|
+
bos.makedirs(os.path.join(thdir, "w"), chmod)
|
270
271
|
|
271
272
|
inf_path = os.path.join(thdir, "dir.txt")
|
272
273
|
if not bos.path.exists(inf_path):
|
@@ -281,7 +282,7 @@ class ThumbSrv(object):
|
|
281
282
|
vn = next((x for x in allvols if x.realpath == ptop), None)
|
282
283
|
if not vn:
|
283
284
|
self.log("ptop %r not in %s" % (ptop, allvols), 3)
|
284
|
-
vn = self.asrv.vfs.all_aps[0][1]
|
285
|
+
vn = self.asrv.vfs.all_aps[0][1][0]
|
285
286
|
|
286
287
|
self.q.put((abspath, tpath, fmt, vn))
|
287
288
|
self.log("conv %r :%s \033[0m%r" % (tpath, fmt, abspath), 6)
|
copyparty/up2k.py
CHANGED
@@ -910,7 +910,8 @@ class Up2k(object):
|
|
910
910
|
# only need to protect register_vpath but all in one go feels right
|
911
911
|
for vol in vols:
|
912
912
|
try:
|
913
|
-
|
913
|
+
# mkdir gonna happen at snap anyways;
|
914
|
+
bos.makedirs(vol.realpath, vol.flags["chmod_d"])
|
914
915
|
dir_is_empty(self.log_func, not self.args.no_scandir, vol.realpath)
|
915
916
|
except Exception as ex:
|
916
917
|
self.volstate[vol.vpath] = "OFFLINE (cannot access folder)"
|
@@ -1134,6 +1135,20 @@ class Up2k(object):
|
|
1134
1135
|
del fl[k1]
|
1135
1136
|
else:
|
1136
1137
|
fl[k1] = ",".join(x for x in fl[k1])
|
1138
|
+
|
1139
|
+
if fl["chmod_d"] == int(self.args.chmod_d, 8):
|
1140
|
+
fl.pop("chmod_d")
|
1141
|
+
try:
|
1142
|
+
if fl["chmod_f"] == int(self.args.chmod_f or "-1", 8):
|
1143
|
+
fl.pop("chmod_f")
|
1144
|
+
except:
|
1145
|
+
pass
|
1146
|
+
for k in ("chmod_f", "chmod_d"):
|
1147
|
+
try:
|
1148
|
+
fl[k] = "%o" % (fl[k])
|
1149
|
+
except:
|
1150
|
+
pass
|
1151
|
+
|
1137
1152
|
a = [
|
1138
1153
|
(ft if v is True else ff if v is False else fv).format(k, str(v))
|
1139
1154
|
for k, v in fl.items()
|
@@ -3274,7 +3289,7 @@ class Up2k(object):
|
|
3274
3289
|
reg,
|
3275
3290
|
"up2k._get_volsize",
|
3276
3291
|
)
|
3277
|
-
bos.makedirs(ap2)
|
3292
|
+
bos.makedirs(ap2, vfs.flags["chmod_d"])
|
3278
3293
|
vfs.lim.nup(cj["addr"])
|
3279
3294
|
vfs.lim.bup(cj["addr"], cj["size"])
|
3280
3295
|
|
@@ -3381,11 +3396,11 @@ class Up2k(object):
|
|
3381
3396
|
self.log(t % (mts - mtc, mts, mtc, fp))
|
3382
3397
|
ow = False
|
3383
3398
|
|
3399
|
+
ptop = job["ptop"]
|
3400
|
+
vf = self.flags.get(ptop) or {}
|
3384
3401
|
if ow:
|
3385
3402
|
self.log("replacing existing file at %r" % (fp,))
|
3386
3403
|
cur = None
|
3387
|
-
ptop = job["ptop"]
|
3388
|
-
vf = self.flags.get(ptop) or {}
|
3389
3404
|
st = bos.stat(fp)
|
3390
3405
|
try:
|
3391
3406
|
vrel = vjoin(job["prel"], fname)
|
@@ -3405,8 +3420,13 @@ class Up2k(object):
|
|
3405
3420
|
else:
|
3406
3421
|
dip = self.hub.iphash.s(ip)
|
3407
3422
|
|
3408
|
-
|
3409
|
-
|
3423
|
+
f, ret = ren_open(
|
3424
|
+
fname,
|
3425
|
+
"wb",
|
3426
|
+
fdir=fdir,
|
3427
|
+
suffix="-%.6f-%s" % (ts, dip),
|
3428
|
+
chmod=vf.get("chmod_f", -1),
|
3429
|
+
)
|
3410
3430
|
f.close()
|
3411
3431
|
return ret
|
3412
3432
|
|
@@ -4256,7 +4276,7 @@ class Up2k(object):
|
|
4256
4276
|
self.log(t, 1)
|
4257
4277
|
raise Pebkac(405, t)
|
4258
4278
|
|
4259
|
-
bos.makedirs(os.path.dirname(dabs))
|
4279
|
+
bos.makedirs(os.path.dirname(dabs), dvn.flags["chmod_d"])
|
4260
4280
|
|
4261
4281
|
c1, w, ftime_, fsize_, ip, at = self._find_from_vpath(
|
4262
4282
|
svn_dbv.realpath, srem_dbv
|
@@ -4431,7 +4451,7 @@ class Up2k(object):
|
|
4431
4451
|
vp = vjoin(dvp, rem)
|
4432
4452
|
try:
|
4433
4453
|
dvn, drem = self.vfs.get(vp, uname, False, True)
|
4434
|
-
bos.mkdir(dvn.canonical(drem))
|
4454
|
+
bos.mkdir(dvn.canonical(drem), dvn.flags["chmod_d"])
|
4435
4455
|
except:
|
4436
4456
|
pass
|
4437
4457
|
|
@@ -4501,7 +4521,7 @@ class Up2k(object):
|
|
4501
4521
|
|
4502
4522
|
is_xvol = svn.realpath != dvn.realpath
|
4503
4523
|
|
4504
|
-
bos.makedirs(os.path.dirname(dabs))
|
4524
|
+
bos.makedirs(os.path.dirname(dabs), dvn.flags["chmod_d"])
|
4505
4525
|
|
4506
4526
|
if is_dirlink:
|
4507
4527
|
dlabs = absreal(sabs)
|
@@ -5006,8 +5026,13 @@ class Up2k(object):
|
|
5006
5026
|
else:
|
5007
5027
|
dip = self.hub.iphash.s(job["addr"])
|
5008
5028
|
|
5009
|
-
|
5010
|
-
|
5029
|
+
f, job["tnam"] = ren_open(
|
5030
|
+
tnam,
|
5031
|
+
"wb",
|
5032
|
+
fdir=pdir,
|
5033
|
+
suffix="-%.6f-%s" % (job["t0"], dip),
|
5034
|
+
chmod=vf.get("chmod_f", -1),
|
5035
|
+
)
|
5011
5036
|
try:
|
5012
5037
|
abspath = djoin(pdir, job["tnam"])
|
5013
5038
|
sprs = job["sprs"]
|
copyparty/util.py
CHANGED
@@ -105,6 +105,7 @@ def _ens(want ) :
|
|
105
105
|
# WSAENOTSOCK - no longer a socket
|
106
106
|
# EUNATCH - can't assign requested address (wifi down)
|
107
107
|
E_SCK = _ens("ENOTCONN EUNATCH EBADF WSAENOTSOCK WSAECONNRESET")
|
108
|
+
E_SCK_WR = _ens("EPIPE ESHUTDOWN EBADFD")
|
108
109
|
E_ADDR_NOT_AVAIL = _ens("EADDRNOTAVAIL WSAEADDRNOTAVAIL")
|
109
110
|
E_ADDR_IN_USE = _ens("EADDRINUSE WSAEADDRINUSE")
|
110
111
|
E_ACCESS = _ens("EACCES WSAEACCES")
|
@@ -1502,6 +1503,7 @@ def ren_open(fname , *args , **kwargs ) :
|
|
1502
1503
|
fun = kwargs.pop("fun", open)
|
1503
1504
|
fdir = kwargs.pop("fdir", None)
|
1504
1505
|
suffix = kwargs.pop("suffix", None)
|
1506
|
+
chmod = kwargs.pop("chmod", -1)
|
1505
1507
|
|
1506
1508
|
if fname == os.devnull:
|
1507
1509
|
return fun(fname, *args, **kwargs), fname
|
@@ -1544,6 +1546,11 @@ def ren_open(fname , *args , **kwargs ) :
|
|
1544
1546
|
fp2 = os.path.join(fdir, fp2)
|
1545
1547
|
with open(fsenc(fp2), "wb") as f2:
|
1546
1548
|
f2.write(orig_name.encode("utf-8"))
|
1549
|
+
if chmod >= 0:
|
1550
|
+
os.fchmod(f2.fileno(), chmod)
|
1551
|
+
|
1552
|
+
if chmod >= 0:
|
1553
|
+
os.fchmod(f.fileno(), chmod)
|
1547
1554
|
|
1548
1555
|
return f, fname
|
1549
1556
|
|
@@ -2314,11 +2321,11 @@ def pathmod(
|
|
2314
2321
|
|
2315
2322
|
# try to map abspath to vpath
|
2316
2323
|
np = np.replace("/", os.sep)
|
2317
|
-
for vn_ap,
|
2324
|
+
for vn_ap, vns in vfs.all_aps:
|
2318
2325
|
if not np.startswith(vn_ap):
|
2319
2326
|
continue
|
2320
2327
|
zs = np[len(vn_ap) :].replace(os.sep, "/")
|
2321
|
-
nvp = vjoin(
|
2328
|
+
nvp = vjoin(vns[0].vpath, zs)
|
2322
2329
|
break
|
2323
2330
|
|
2324
2331
|
if nvp == "\n":
|
copyparty/web/baguettebox.js.gz
CHANGED
Binary file
|
copyparty/web/browser.css.gz
CHANGED
Binary file
|
copyparty/web/browser.js.gz
CHANGED
Binary file
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: copyparty
|
3
|
-
Version: 1.18.
|
3
|
+
Version: 1.18.3
|
4
4
|
Summary: Portable file server with accelerated resumable uploads, deduplication, WebDAV, FTP, zeroconf, media indexer, video thumbnails, audio transcoding, and write-only folders
|
5
5
|
Author-email: ed <copyparty@ocv.me>
|
6
6
|
License: MIT
|
@@ -2422,8 +2422,10 @@ TLDR: yes
|
|
2422
2422
|
| send message | yep | yep | yep | yep | yep | yep | yep | yep |
|
2423
2423
|
| set sort order | - | yep | yep | yep | yep | yep | yep | yep |
|
2424
2424
|
| zip selection | - | yep | yep | yep | yep | yep | yep | yep |
|
2425
|
+
| file search | - | yep | yep | yep | yep | yep | yep | yep |
|
2425
2426
|
| file rename | - | yep | yep | yep | yep | yep | yep | yep |
|
2426
2427
|
| file cut/paste | - | yep | yep | yep | yep | yep | yep | yep |
|
2428
|
+
| unpost uploads | - | - | yep | yep | yep | yep | yep | yep |
|
2427
2429
|
| navpane | - | yep | yep | yep | yep | yep | yep | yep |
|
2428
2430
|
| image viewer | - | yep | yep | yep | yep | yep | yep | yep |
|
2429
2431
|
| video player | - | yep | yep | yep | yep | yep | yep | yep |
|
@@ -1,17 +1,17 @@
|
|
1
1
|
copyparty/__init__.py,sha256=4aJw_Mt3eSNMV8sJ95Nh4ris-tBUYhCOV094Rnxa5Xo,2651
|
2
|
-
copyparty/__main__.py,sha256=
|
3
|
-
copyparty/__version__.py,sha256=
|
4
|
-
copyparty/authsrv.py,sha256=
|
2
|
+
copyparty/__main__.py,sha256=xfjyeCayxt3syWT1Iw6DDitRuQkrUcJvFUaEoWcIfMU,125889
|
3
|
+
copyparty/__version__.py,sha256=D7P8wrGVX6EhXwfZYGNDWFK3D95DiMYHg7ohrpDSGMM,249
|
4
|
+
copyparty/authsrv.py,sha256=TF6T254t2ZdcB_1nAq5xXQBjG5SKUtzIeN3RBhmzCtc,118943
|
5
5
|
copyparty/broker_mp.py,sha256=QdOXXvV2Xn6J0CysEqyY3GZbqxQMyWnTpnba-a5lMc0,4987
|
6
6
|
copyparty/broker_mpw.py,sha256=PpSS4SK3pItlpfD8OwVr3QmJEPKlUgaf2nuMOozixgU,3347
|
7
7
|
copyparty/broker_thr.py,sha256=fjoYtpSscUA7-nMl4r1n2R7UK3J9lrvLS3rUZ-iJzKQ,1721
|
8
8
|
copyparty/broker_util.py,sha256=76mfnFOpX1gUUvtjm8UQI7jpTIaVINX10QonM-B7ggc,1680
|
9
9
|
copyparty/cert.py,sha256=pSSeVYticrDsnsrdRtfpUQN-8WRObsqrYtSRroXmgxo,7992
|
10
|
-
copyparty/cfg.py,sha256=
|
10
|
+
copyparty/cfg.py,sha256=3rMq1XSGnzu5-_YU4DsDc9G2hMOv6VLPveF2mC3_CU8,15359
|
11
11
|
copyparty/dxml.py,sha256=vu5uZQtwvwoqnFHbULs2Zh_y2DETu0T-ENpMZ1i2CV4,2505
|
12
12
|
copyparty/fsutil.py,sha256=NC_CJC4TDag399vVDH9_uQfdfpTMwRFLNxERSWhlVvs,4594
|
13
|
-
copyparty/ftpd.py,sha256=
|
14
|
-
copyparty/httpcli.py,sha256=
|
13
|
+
copyparty/ftpd.py,sha256=xDDWixo5O2HT8wlexXQ0QRazU_fYERIJ4yF0mtu9wD0,18141
|
14
|
+
copyparty/httpcli.py,sha256=lB7CvrqyWMkXAV39oJtPof5PzDRCg7nNh7cwOoVfgO4,230547
|
15
15
|
copyparty/httpconn.py,sha256=IA9fdCjigawZ4kWhgvVN3nSiy5pb3W2qaE6rFqUYdq0,6943
|
16
16
|
copyparty/httpsrv.py,sha256=x6dl6ZjpwYREbm-eJZYnwdkhDeCA58hw_iwUMCD1Wz8,18819
|
17
17
|
copyparty/ico.py,sha256=-7QjF_jIxnPo4Vr0oUPksQ_U_Ef0HRsSPm3s71idOz8,3879
|
@@ -20,21 +20,21 @@ copyparty/metrics.py,sha256=1dim0ShnsD5cfspRbeN9Mt14wOIxPRtxCZY2IScikKw,8974
|
|
20
20
|
copyparty/mtag.py,sha256=7lINRFc1Vrc-ebP2hU3dBHH3BRFOnEmEZ0jzlpYb8Jg,19910
|
21
21
|
copyparty/multicast.py,sha256=Me4XEEJijvvK2lMRwmGU2hsaI5_E9AEpCjIC4b9UefA,12393
|
22
22
|
copyparty/pwhash.py,sha256=zHoz9FHGkFBxoRvSfG1XyjN3ibww_h5GE6_m5yS-fws,4246
|
23
|
-
copyparty/smbd.py,sha256=
|
23
|
+
copyparty/smbd.py,sha256=jeKGkVLG9-Q0zPNDZdIwb_O59388rvGzG2cQQ2qPXpk,14659
|
24
24
|
copyparty/ssdp.py,sha256=R1Z61GZOxBMF2Sk4RTxKWMOemogmcjEWG-CvLihd45k,7023
|
25
25
|
copyparty/star.py,sha256=tV5BbX6AiQ7N4UU8DYtSTckNYeoeey4DBqq4LjfymbY,3818
|
26
26
|
copyparty/sutil.py,sha256=E65jAaOzHlJYnqsOKDMPVT8kALPUVexpkSStWBdItkY,3231
|
27
|
-
copyparty/svchub.py,sha256=
|
27
|
+
copyparty/svchub.py,sha256=M7UnnqNUtVz5DQRYMHcmmyvDDtPzXKAOrW-XgJWfujc,49038
|
28
28
|
copyparty/szip.py,sha256=9srQzjsTBrBadf6QMh4YRAL70rkZLevAOHqXWK5jvr8,8846
|
29
|
-
copyparty/tcpsrv.py,sha256=
|
30
|
-
copyparty/tftpd.py,sha256=
|
29
|
+
copyparty/tcpsrv.py,sha256=BCOqlT_mRu1ibHJpPzvf9c4h83AnIMEfd8nBBednCCg,20484
|
30
|
+
copyparty/tftpd.py,sha256=sNBMqazIB37t3jwhv_F1tr0lHFsiRX-nCsICM8nbkvc,14170
|
31
31
|
copyparty/th_cli.py,sha256=IEX5tCb0gw9Z2aRIDL9bwdvJ6g5jhWZ8OEAAz16_xN4,5426
|
32
|
-
copyparty/th_srv.py,sha256=
|
32
|
+
copyparty/th_srv.py,sha256=INLaV1_NH1VKtBx9XaqyJbZNAj2ZhfcQwz0_5Y5fyiY,32744
|
33
33
|
copyparty/u2idx.py,sha256=4Y5OOPyVkc-pS0z6e3p4StXAMnjHobSOMmMsvNUTD34,13674
|
34
|
-
copyparty/up2k.py,sha256=
|
35
|
-
copyparty/util.py,sha256=
|
34
|
+
copyparty/up2k.py,sha256=KINADhvYxtCG6NEC2qytdBCsjqvOiaVR5tc6nmvlaho,178731
|
35
|
+
copyparty/util.py,sha256=9juRzN_pfH7P1eZK9Tv5ZZzBVCf8ct1La1s9lUXsRSg,104193
|
36
36
|
copyparty/bos/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
37
|
-
copyparty/bos/bos.py,sha256=
|
37
|
+
copyparty/bos/bos.py,sha256=ZwpTla_mFpoN_BbGn9h0dEn7wpZ607QJ7uYyxWJMcmw,1953
|
38
38
|
copyparty/bos/path.py,sha256=yEjCq2ki9CvxA5sCT8pS0keEXwugs0ZeUyUhdBziOCI,777
|
39
39
|
copyparty/res/COPYING.txt,sha256=1LnBxkwJuC8mRBxuoMF2UIcpCjcteIzFHotSUE1Xte0,9776
|
40
40
|
copyparty/res/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -54,10 +54,10 @@ copyparty/stolen/ifaddr/__init__.py,sha256=vpREjAyPubr5s1NJi91icXV3q1o4DrKAvHABw
|
|
54
54
|
copyparty/stolen/ifaddr/_posix.py,sha256=-67NdfGrCktfQPakT2fLbjl2U00QMvyBGkSvrUuTOrU,2626
|
55
55
|
copyparty/stolen/ifaddr/_shared.py,sha256=uNC4SdEIgdSLKvuUzsf1aM-H1Xrc_9mpLoOT43YukGs,6206
|
56
56
|
copyparty/stolen/ifaddr/_win32.py,sha256=EE-QyoBgeB7lYQ6z62VjXNaRozaYfCkaJBHGNA8QtZM,4026
|
57
|
-
copyparty/web/baguettebox.js.gz,sha256=
|
58
|
-
copyparty/web/browser.css.gz,sha256=
|
57
|
+
copyparty/web/baguettebox.js.gz,sha256=MxRofvhXjmUN7RtXtC17_9AlROVNUT-66WwJ_pHLY9c,8258
|
58
|
+
copyparty/web/browser.css.gz,sha256=29D3F4uB-VMd6uJo-SxWAwLfn08jcETYZm0SOJFJLAE,11847
|
59
59
|
copyparty/web/browser.html,sha256=auvhLVE_t0aIN0q-nk0zOWFqITgDhroMAAviBNLoFfc,4788
|
60
|
-
copyparty/web/browser.js.gz,sha256=
|
60
|
+
copyparty/web/browser.js.gz,sha256=PuTSoalzqWJigJXmDkkgaiGR-n5ieR47SU4lOvOkLZk,96513
|
61
61
|
copyparty/web/browser2.html,sha256=NRUZ08GH-e2YcGXcoz0UjYg6JIVF42u4IMX4HHwWTmg,1587
|
62
62
|
copyparty/web/cf.html,sha256=lJThtNFNAQT1ClCHHlivAkDGE0LutedwopXD62Z8Nys,589
|
63
63
|
copyparty/web/dbg-audio.js.gz,sha256=Ma-KZtK8LnmiwNvNKFKXMPYl_Nn_3U7GsJ6-DRWC2HE,688
|
@@ -110,9 +110,9 @@ copyparty/web/deps/prismd.css.gz,sha256=ObUlksQVr-OuYlTz-I4B23TeBg2QDVVGRnWBz8cV
|
|
110
110
|
copyparty/web/deps/scp.woff2,sha256=w99BDU5i8MukkMEL-iW0YO9H4vFFZSPWxbkH70ytaAg,8612
|
111
111
|
copyparty/web/deps/sha512.ac.js.gz,sha256=lFZaCLumgWxrvEuDr4bqdKHsqjX82AbVAb7_F45Yk88,7033
|
112
112
|
copyparty/web/deps/sha512.hw.js.gz,sha256=UAed2_ocklZCnIzcSYz2h4P1ycztlCLj-ewsRTud2lU,7939
|
113
|
-
copyparty-1.18.
|
114
|
-
copyparty-1.18.
|
115
|
-
copyparty-1.18.
|
116
|
-
copyparty-1.18.
|
117
|
-
copyparty-1.18.
|
118
|
-
copyparty-1.18.
|
113
|
+
copyparty-1.18.3.dist-info/licenses/LICENSE,sha256=gOr4h33pCsBEg9uIy9AYmb7qlocL4V9t2uPJS5wllr0,1072
|
114
|
+
copyparty-1.18.3.dist-info/METADATA,sha256=IwBSD6NubWRSBqPVhBc5i8L_1PLB_kwzvoz3SMVlUyo,165941
|
115
|
+
copyparty-1.18.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
116
|
+
copyparty-1.18.3.dist-info/entry_points.txt,sha256=4zw6a3rqASywQomiYLObjjlxybaI65LYYOTJwgKz7b0,128
|
117
|
+
copyparty-1.18.3.dist-info/top_level.txt,sha256=LnYUPsDyk-8kFgM6YJLG4h820DQekn81cObKSu9g-sI,10
|
118
|
+
copyparty-1.18.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|